2026-03-19 11:08:53 +09:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers\Finance;
|
|
|
|
|
|
|
|
|
|
use App\Http\Controllers\Controller;
|
|
|
|
|
use App\Models\Barobill\AccountCode;
|
|
|
|
|
use Illuminate\Http\JsonResponse;
|
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
|
|
|
|
|
|
class AccountLedgerController extends Controller
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* 계정별원장 페이지
|
|
|
|
|
*/
|
|
|
|
|
public function index(Request $request)
|
|
|
|
|
{
|
|
|
|
|
if ($request->header('HX-Request')) {
|
|
|
|
|
return response('', 200)->header('HX-Redirect', route('finance.account-ledger'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return view('finance.account-ledger');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2026-03-19 17:36:14 +09:00
|
|
|
* 계정별원장 데이터 조회 (일반전표만)
|
2026-03-19 11:08:53 +09:00
|
|
|
*/
|
|
|
|
|
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],
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 17:36:14 +09:00
|
|
|
$account = AccountCode::withoutGlobalScopes()
|
|
|
|
|
->where('tenant_id', $tenantId)
|
2026-03-19 11:08:53 +09:00
|
|
|
->where('code', $accountCode)
|
|
|
|
|
->first();
|
|
|
|
|
|
|
|
|
|
if (! $account) {
|
|
|
|
|
return response()->json(['error' => '계정과목을 찾을 수 없습니다.'], 404);
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 17:36:14 +09:00
|
|
|
// 일반전표 분개 라인만 조회 (카드/홈택스 분개는 이미 일반전표에 포함)
|
|
|
|
|
$allLines = DB::table('journal_entry_lines as jel')
|
2026-03-19 11:08:53 +09:00
|
|
|
->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_name',
|
|
|
|
|
'tp.biz_no',
|
|
|
|
|
'jel.debit_amount',
|
|
|
|
|
'jel.credit_amount',
|
|
|
|
|
DB::raw("'journal' as source_type"),
|
|
|
|
|
'jel.journal_entry_id as source_id',
|
2026-03-19 17:36:14 +09:00
|
|
|
])
|
|
|
|
|
->orderBy('je.entry_date')
|
2026-03-19 11:08:53 +09:00
|
|
|
->get();
|
|
|
|
|
|
2026-03-19 17:36:14 +09:00
|
|
|
// 이월잔액 (일반전표만)
|
2026-03-19 11:08:53 +09:00
|
|
|
$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) {
|
2026-03-19 17:36:14 +09:00
|
|
|
$month = substr($line->date, 0, 7);
|
2026-03-19 11:08:53 +09:00
|
|
|
|
|
|
|
|
if (! isset($monthlyData[$month])) {
|
|
|
|
|
$monthlyData[$month] = [
|
|
|
|
|
'month' => $month,
|
|
|
|
|
'items' => [],
|
|
|
|
|
'subtotal' => ['debit' => 0, 'credit' => 0],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$debit = (int) $line->debit_amount;
|
|
|
|
|
$credit = (int) $line->credit_amount;
|
|
|
|
|
|
2026-03-19 17:36:14 +09:00
|
|
|
$runningBalance += $isDebitNormal ? ($debit - $credit) : ($credit - $debit);
|
2026-03-19 11:08:53 +09:00
|
|
|
|
|
|
|
|
$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,
|
2026-03-19 17:36:14 +09:00
|
|
|
'source_id' => (int) $line->source_id,
|
2026-03-19 11:08:53 +09:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$monthlyData[$month]['subtotal']['debit'] += $debit;
|
|
|
|
|
$monthlyData[$month]['subtotal']['credit'] += $credit;
|
|
|
|
|
$grandDebit += $debit;
|
|
|
|
|
$grandCredit += $credit;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 17:36:14 +09:00
|
|
|
// 누계
|
2026-03-19 11:08:53 +09:00
|
|
|
$cumulativeDebit = 0;
|
|
|
|
|
$cumulativeCredit = 0;
|
|
|
|
|
foreach ($monthlyData as &$md) {
|
|
|
|
|
$cumulativeDebit += $md['subtotal']['debit'];
|
|
|
|
|
$cumulativeCredit += $md['subtotal']['credit'];
|
2026-03-19 17:36:14 +09:00
|
|
|
$md['cumulative'] = ['debit' => $cumulativeDebit, 'credit' => $cumulativeCredit];
|
2026-03-19 11:08:53 +09:00
|
|
|
}
|
|
|
|
|
unset($md);
|
|
|
|
|
|
|
|
|
|
return response()->json([
|
|
|
|
|
'account' => [
|
|
|
|
|
'code' => $account->code,
|
|
|
|
|
'name' => $account->name,
|
|
|
|
|
'category' => $account->category,
|
|
|
|
|
],
|
2026-03-19 17:36:14 +09:00
|
|
|
'period' => ['start_date' => $startDate, 'end_date' => $endDate],
|
2026-03-19 11:08:53 +09:00
|
|
|
'carry_forward' => $carryForward,
|
|
|
|
|
'monthly_data' => array_values($monthlyData),
|
2026-03-19 17:36:14 +09:00
|
|
|
'grand_total' => ['debit' => $grandDebit, 'credit' => $grandCredit, 'balance' => $runningBalance],
|
2026-03-19 11:08:53 +09:00
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2026-03-19 17:36:14 +09:00
|
|
|
* 이월잔액 계산 (일반전표만)
|
2026-03-19 11:08:53 +09:00
|
|
|
*/
|
|
|
|
|
private function calculateCarryForward(int $tenantId, string $accountCode, string $startDate, string $category): array
|
|
|
|
|
{
|
2026-03-19 17:36:14 +09:00
|
|
|
$sums = DB::table('journal_entry_lines as jel')
|
2026-03-19 11:08:53 +09:00
|
|
|
->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();
|
|
|
|
|
|
2026-03-19 17:36:14 +09:00
|
|
|
$debit = (int) $sums->total_debit;
|
|
|
|
|
$credit = (int) $sums->total_credit;
|
2026-03-19 11:08:53 +09:00
|
|
|
$isDebitNormal = in_array($category, ['asset', 'expense']);
|
|
|
|
|
$balance = $isDebitNormal ? ($debit - $credit) : ($credit - $debit);
|
|
|
|
|
|
|
|
|
|
return compact('debit', 'credit', 'balance');
|
|
|
|
|
}
|
|
|
|
|
}
|