Files
sam-api/app/Services/AccountLedgerService.php

175 lines
6.9 KiB
PHP
Raw Normal View History

<?php
namespace App\Services;
use Illuminate\Support\Facades\DB;
class AccountLedgerService extends Service
{
/**
* 계정별원장 조회
*/
public function index(array $params): array
{
$tenantId = $this->tenantId();
$startDate = $params['start_date'];
$endDate = $params['end_date'];
$accountCode = $params['account_code'];
// 계정과목 정보
$account = DB::table('account_codes')
->where('tenant_id', $tenantId)
->where('code', $accountCode)
->where('is_active', true)
->first(['code', 'name', 'category', 'sub_category']);
if (! $account) {
return [
'account' => null,
'period' => compact('startDate', 'endDate'),
'carry_forward' => ['debit' => 0, 'credit' => 0, 'balance' => 0],
'monthly_data' => [],
'grand_total' => ['debit' => 0, 'credit' => 0, 'balance' => 0],
];
}
// 일반전표 분개 라인
$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_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',
'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',
]);
$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);
if (! isset($monthlyData[$month])) {
$monthlyData[$month] = [
'month' => $month,
'items' => [],
'subtotal' => ['debit' => 0, 'credit' => 0],
];
}
$debit = (int) $line->debit_amount;
$credit = (int) $line->credit_amount;
$runningBalance += $isDebitNormal ? ($debit - $credit) : ($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' => (int) $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 [
'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');
}
}