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, ]; } }