header('HX-Request')) { return response('', 200)->header('HX-Redirect', route('finance.account-ledger')); } return view('finance.account-ledger'); } /** * 계정별원장 데이터 조회 */ public function list(Request $request): JsonResponse { $tenantId = session('selected_tenant_id', 1); $startDate = $request->input('start_date', now()->startOfMonth()->format('Y-m-d')); $endDate = $request->input('end_date', now()->endOfMonth()->format('Y-m-d')); $accountCode = $request->input('account_code'); if (! $accountCode) { return response()->json([ 'account' => null, 'period' => compact('startDate', 'endDate'), 'monthly_data' => [], 'grand_total' => ['debit' => 0, 'credit' => 0, 'balance' => 0], ]); } // 계정과목 정보 $account = AccountCode::where('tenant_id', $tenantId) ->where('code', $accountCode) ->first(); if (! $account) { return response()->json(['error' => '계정과목을 찾을 수 없습니다.'], 404); } // 일반전표 분개 라인 $journalLines = DB::table('journal_entry_lines as jel') ->join('journal_entries as je', 'je.id', '=', 'jel.journal_entry_id') ->leftJoin('trading_partners as tp', function ($join) use ($tenantId) { $join->on('tp.id', '=', 'jel.trading_partner_id') ->where('tp.tenant_id', '=', $tenantId); }) ->where('jel.tenant_id', $tenantId) ->where('jel.account_code', $accountCode) ->whereBetween('je.entry_date', [$startDate, $endDate]) ->whereNull('je.deleted_at') ->select([ 'je.entry_date as date', 'jel.description', 'jel.trading_partner_id', 'jel.trading_partner_name', 'tp.biz_no', 'jel.debit_amount', 'jel.credit_amount', DB::raw("'journal' as source_type"), 'jel.journal_entry_id as source_id', ]); // 홈택스 세금계산서 분개 $hometaxLines = DB::table('hometax_invoice_journals as hij') ->join('hometax_invoices as hi', 'hi.id', '=', 'hij.hometax_invoice_id') ->where('hij.tenant_id', $tenantId) ->where('hij.account_code', $accountCode) ->whereBetween('hij.write_date', [$startDate, $endDate]) ->whereNull('hi.deleted_at') ->select([ 'hij.write_date as date', 'hij.description', DB::raw('NULL as trading_partner_id'), 'hij.trading_partner_name', DB::raw("CASE WHEN hi.invoice_type = 'sales' THEN hi.invoicee_corp_num ELSE hi.invoicer_corp_num END as biz_no"), 'hij.debit_amount', 'hij.credit_amount', DB::raw("'hometax' as source_type"), 'hij.hometax_invoice_id as source_id', ]); // UNION ALL → 날짜순 정렬 $allLines = $journalLines->unionAll($hometaxLines) ->orderBy('date') ->get(); // 이월잔액 계산 (조회 시작일 이전) $carryForward = $this->calculateCarryForward($tenantId, $accountCode, $startDate, $account->category); // 월별 그룹핑 + 잔액 계산 $isDebitNormal = in_array($account->category, ['asset', 'expense']); $runningBalance = $carryForward['balance']; $monthlyData = []; $grandDebit = 0; $grandCredit = 0; foreach ($allLines as $line) { $month = substr($line->date, 0, 7); // YYYY-MM if (! isset($monthlyData[$month])) { $monthlyData[$month] = [ 'month' => $month, 'items' => [], 'subtotal' => ['debit' => 0, 'credit' => 0], ]; } $debit = (int) $line->debit_amount; $credit = (int) $line->credit_amount; if ($isDebitNormal) { $runningBalance += ($debit - $credit); } else { $runningBalance += ($credit - $debit); } $monthlyData[$month]['items'][] = [ 'date' => $line->date, 'description' => $line->description, 'trading_partner_name' => $line->trading_partner_name, 'biz_no' => $line->biz_no, 'debit_amount' => $debit, 'credit_amount' => $credit, 'balance' => $runningBalance, 'source_type' => $line->source_type, 'source_id' => $line->source_id, ]; $monthlyData[$month]['subtotal']['debit'] += $debit; $monthlyData[$month]['subtotal']['credit'] += $credit; $grandDebit += $debit; $grandCredit += $credit; } // 누계 계산 $cumulativeDebit = 0; $cumulativeCredit = 0; foreach ($monthlyData as &$md) { $cumulativeDebit += $md['subtotal']['debit']; $cumulativeCredit += $md['subtotal']['credit']; $md['cumulative'] = [ 'debit' => $cumulativeDebit, 'credit' => $cumulativeCredit, ]; } unset($md); return response()->json([ 'account' => [ 'code' => $account->code, 'name' => $account->name, 'category' => $account->category, ], 'period' => [ 'start_date' => $startDate, 'end_date' => $endDate, ], 'carry_forward' => $carryForward, 'monthly_data' => array_values($monthlyData), 'grand_total' => [ 'debit' => $grandDebit, 'credit' => $grandCredit, 'balance' => $runningBalance, ], ]); } /** * 이월잔액 계산 (조회 시작일 이전 합계) */ private function calculateCarryForward(int $tenantId, string $accountCode, string $startDate, string $category): array { // 일반전표 $journalSums = DB::table('journal_entry_lines as jel') ->join('journal_entries as je', 'je.id', '=', 'jel.journal_entry_id') ->where('jel.tenant_id', $tenantId) ->where('jel.account_code', $accountCode) ->where('je.entry_date', '<', $startDate) ->whereNull('je.deleted_at') ->selectRaw('COALESCE(SUM(jel.debit_amount), 0) as total_debit, COALESCE(SUM(jel.credit_amount), 0) as total_credit') ->first(); // 홈택스 $hometaxSums = DB::table('hometax_invoice_journals as hij') ->join('hometax_invoices as hi', 'hi.id', '=', 'hij.hometax_invoice_id') ->where('hij.tenant_id', $tenantId) ->where('hij.account_code', $accountCode) ->where('hij.write_date', '<', $startDate) ->whereNull('hi.deleted_at') ->selectRaw('COALESCE(SUM(hij.debit_amount), 0) as total_debit, COALESCE(SUM(hij.credit_amount), 0) as total_credit') ->first(); $debit = (int) $journalSums->total_debit + (int) $hometaxSums->total_debit; $credit = (int) $journalSums->total_credit + (int) $hometaxSums->total_credit; $isDebitNormal = in_array($category, ['asset', 'expense']); $balance = $isDebitNormal ? ($debit - $credit) : ($credit - $debit); return compact('debit', 'credit', 'balance'); } }