- 바로빌 카드 거래 API (16 엔드포인트): 조회, 분할, 수동입력, 숨김/복원, 금액수정, 분개 - 바로빌 은행 거래 API (13 엔드포인트): 조회, 분할, 오버라이드, 수동입력, 잔액요약, 분개 - 홈택스 세금계산서 API (13 엔드포인트): 매출/매입 조회, 수동입력, 자체분개, 통합분개 - JournalEntry 소스 타입 상수 추가 (barobill_card, barobill_bank, hometax_invoice)
223 lines
7.3 KiB
PHP
223 lines
7.3 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Barobill\HometaxInvoice;
|
|
use App\Models\Barobill\HometaxInvoiceJournal;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
/**
|
|
* 홈택스 세금계산서 서비스 (React 연동용)
|
|
*
|
|
* MNG에서 동기화된 hometax_invoices 데이터를
|
|
* React 프론트엔드에서 조회/분개 등 처리
|
|
*/
|
|
class HometaxInvoiceService extends Service
|
|
{
|
|
/**
|
|
* 매출 세금계산서 목록
|
|
*/
|
|
public function sales(array $params): array
|
|
{
|
|
return $this->listByType('sales', $params);
|
|
}
|
|
|
|
/**
|
|
* 매입 세금계산서 목록
|
|
*/
|
|
public function purchases(array $params): array
|
|
{
|
|
return $this->listByType('purchase', $params);
|
|
}
|
|
|
|
/**
|
|
* 세금계산서 상세 조회
|
|
*/
|
|
public function show(int $id): ?HometaxInvoice
|
|
{
|
|
return HometaxInvoice::where('tenant_id', $this->tenantId())
|
|
->with('journals')
|
|
->find($id);
|
|
}
|
|
|
|
/**
|
|
* 분개 저장 (홈택스 자체 분개 테이블 사용)
|
|
*/
|
|
public function saveJournals(int $invoiceId, array $items): array
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
$invoice = HometaxInvoice::where('tenant_id', $tenantId)->findOrFail($invoiceId);
|
|
|
|
return DB::transaction(function () use ($tenantId, $invoice, $items) {
|
|
// 기존 분개 삭제
|
|
HometaxInvoiceJournal::where('tenant_id', $tenantId)
|
|
->where('hometax_invoice_id', $invoice->id)
|
|
->delete();
|
|
|
|
$created = [];
|
|
foreach ($items as $index => $item) {
|
|
$created[] = HometaxInvoiceJournal::create([
|
|
'tenant_id' => $tenantId,
|
|
'hometax_invoice_id' => $invoice->id,
|
|
'nts_confirm_num' => $invoice->nts_confirm_num,
|
|
'dc_type' => $item['dc_type'],
|
|
'account_code' => $item['account_code'],
|
|
'account_name' => $item['account_name'] ?? null,
|
|
'debit_amount' => $item['debit_amount'] ?? 0,
|
|
'credit_amount' => $item['credit_amount'] ?? 0,
|
|
'description' => $item['description'] ?? null,
|
|
'sort_order' => $index + 1,
|
|
'invoice_type' => $invoice->invoice_type,
|
|
'write_date' => $invoice->write_date,
|
|
'supply_amount' => $invoice->supply_amount,
|
|
'tax_amount' => $invoice->tax_amount,
|
|
'total_amount' => $invoice->total_amount,
|
|
'trading_partner_name' => $invoice->invoice_type === 'sales'
|
|
? $invoice->invoicee_corp_name
|
|
: $invoice->invoicer_corp_name,
|
|
]);
|
|
}
|
|
|
|
return ['items' => $created, 'count' => count($created)];
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 분개 조회
|
|
*/
|
|
public function getJournals(int $invoiceId): array
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
$journals = HometaxInvoiceJournal::getByInvoiceId($tenantId, $invoiceId);
|
|
|
|
return ['items' => $journals];
|
|
}
|
|
|
|
/**
|
|
* 분개 삭제
|
|
*/
|
|
public function deleteJournals(int $invoiceId): array
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
$deleted = HometaxInvoiceJournal::where('tenant_id', $tenantId)
|
|
->where('hometax_invoice_id', $invoiceId)
|
|
->delete();
|
|
|
|
return ['deleted_count' => $deleted];
|
|
}
|
|
|
|
/**
|
|
* 수동 세금계산서 등록
|
|
*/
|
|
public function storeManual(array $data): HometaxInvoice
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
|
|
return HometaxInvoice::create(array_merge($data, [
|
|
'tenant_id' => $tenantId,
|
|
]));
|
|
}
|
|
|
|
/**
|
|
* 수동 세금계산서 수정
|
|
*/
|
|
public function updateManual(int $id, array $data): HometaxInvoice
|
|
{
|
|
$invoice = HometaxInvoice::where('tenant_id', $this->tenantId())->findOrFail($id);
|
|
$invoice->update($data);
|
|
|
|
return $invoice->fresh();
|
|
}
|
|
|
|
/**
|
|
* 수동 세금계산서 삭제 (soft delete)
|
|
*/
|
|
public function destroyManual(int $id): bool
|
|
{
|
|
$invoice = HometaxInvoice::where('tenant_id', $this->tenantId())->findOrFail($id);
|
|
|
|
return $invoice->delete();
|
|
}
|
|
|
|
/**
|
|
* 요약 통계
|
|
*/
|
|
public function summary(array $params): array
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
$startDate = $params['start_date'] ?? now()->startOfMonth()->format('Y-m-d');
|
|
$endDate = $params['end_date'] ?? now()->format('Y-m-d');
|
|
|
|
$salesQuery = HometaxInvoice::where('tenant_id', $tenantId)
|
|
->sales()
|
|
->period($startDate, $endDate);
|
|
|
|
$purchaseQuery = HometaxInvoice::where('tenant_id', $tenantId)
|
|
->purchase()
|
|
->period($startDate, $endDate);
|
|
|
|
return [
|
|
'sales' => [
|
|
'count' => (clone $salesQuery)->count(),
|
|
'supply_amount' => (int) (clone $salesQuery)->sum('supply_amount'),
|
|
'tax_amount' => (int) (clone $salesQuery)->sum('tax_amount'),
|
|
'total_amount' => (int) (clone $salesQuery)->sum('total_amount'),
|
|
],
|
|
'purchase' => [
|
|
'count' => (clone $purchaseQuery)->count(),
|
|
'supply_amount' => (int) (clone $purchaseQuery)->sum('supply_amount'),
|
|
'tax_amount' => (int) (clone $purchaseQuery)->sum('tax_amount'),
|
|
'total_amount' => (int) (clone $purchaseQuery)->sum('total_amount'),
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 타입별 목록 조회 (공통)
|
|
*/
|
|
private function listByType(string $invoiceType, array $params): array
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
$startDate = $params['start_date'] ?? now()->startOfMonth()->format('Y-m-d');
|
|
$endDate = $params['end_date'] ?? now()->format('Y-m-d');
|
|
$search = $params['search'] ?? null;
|
|
$perPage = $params['per_page'] ?? 50;
|
|
|
|
$query = HometaxInvoice::where('tenant_id', $tenantId)
|
|
->where('invoice_type', $invoiceType)
|
|
->period($startDate, $endDate);
|
|
|
|
if ($search) {
|
|
$query->where(function ($q) use ($search, $invoiceType) {
|
|
if ($invoiceType === 'sales') {
|
|
$q->where('invoicee_corp_name', 'like', "%{$search}%")
|
|
->orWhere('invoicee_corp_num', 'like', "%{$search}%");
|
|
} else {
|
|
$q->where('invoicer_corp_name', 'like', "%{$search}%")
|
|
->orWhere('invoicer_corp_num', 'like', "%{$search}%");
|
|
}
|
|
$q->orWhere('nts_confirm_num', 'like', "%{$search}%")
|
|
->orWhere('item_name', 'like', "%{$search}%");
|
|
});
|
|
}
|
|
|
|
$query->orderByDesc('write_date')->orderByDesc('issue_date');
|
|
|
|
$invoices = $query->paginate($perPage);
|
|
|
|
// 분개 존재 여부 로드
|
|
$invoiceIds = $invoices->getCollection()->pluck('id')->toArray();
|
|
$journaledIds = HometaxInvoiceJournal::getJournaledInvoiceIds($tenantId, $invoiceIds);
|
|
|
|
$invoices->getCollection()->transform(function ($invoice) use ($journaledIds) {
|
|
$invoice->has_journal = in_array($invoice->id, $journaledIds);
|
|
|
|
return $invoice;
|
|
});
|
|
|
|
return [
|
|
'data' => $invoices,
|
|
];
|
|
}
|
|
}
|