feat: [finance] 손익계산서 월별 조회 API + 리팩토링
- GET /api/v1/income-statement/monthly?year=2026&unit=won 추가 - buildSections 공통 로직 분리 - getAccountCodes, getFiscalYear 헬퍼 분리
This commit is contained in:
@@ -28,4 +28,19 @@ public function index(Request $request)
|
||||
return $this->service->data($request->only(['start_date', 'end_date', 'unit']));
|
||||
}, __('message.fetched'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 손익계산서 월별 조회
|
||||
*/
|
||||
public function monthly(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'year' => 'required|integer|min:2020|max:2100',
|
||||
'unit' => 'nullable|in:won,thousand,million',
|
||||
]);
|
||||
|
||||
return ApiResponse::handle(function () use ($request) {
|
||||
return $this->service->monthly($request->only(['year', 'unit']));
|
||||
}, __('message.fetched'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ class IncomeStatementService extends Service
|
||||
];
|
||||
|
||||
/**
|
||||
* 손익계산서 조회
|
||||
* 손익계산서 조회 (기간)
|
||||
*/
|
||||
public function data(array $params): array
|
||||
{
|
||||
@@ -33,17 +33,86 @@ public function data(array $params): array
|
||||
$prevStartDate = date('Y-m-d', strtotime($startDate.' -1 year'));
|
||||
$prevEndDate = date('Y-m-d', strtotime($endDate.' -1 year'));
|
||||
|
||||
$accountCodes = $this->getAccountCodes($tenantId);
|
||||
$currentSums = $this->getAccountSums($tenantId, $startDate, $endDate);
|
||||
$previousSums = $this->getAccountSums($tenantId, $prevStartDate, $prevEndDate);
|
||||
$sections = $this->buildSections($accountCodes, $currentSums, $previousSums, $unit);
|
||||
|
||||
$accountCodes = DB::table('account_codes')
|
||||
$currentYear = (int) date('Y', strtotime($endDate));
|
||||
$fiscalYear = $this->getFiscalYear($currentYear);
|
||||
|
||||
return [
|
||||
'period' => [
|
||||
'current' => ['start' => $startDate, 'end' => $endDate, 'label' => "제 {$fiscalYear} (당)기"],
|
||||
'previous' => ['start' => $prevStartDate, 'end' => $prevEndDate, 'label' => '제 '.($fiscalYear - 1).' (전)기'],
|
||||
],
|
||||
'unit' => $unit,
|
||||
'sections' => $sections,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 손익계산서 월별 조회
|
||||
*/
|
||||
public function monthly(array $params): array
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$year = (int) ($params['year'] ?? now()->year);
|
||||
$unit = $params['unit'] ?? 'won';
|
||||
|
||||
$accountCodes = $this->getAccountCodes($tenantId);
|
||||
$months = [];
|
||||
|
||||
for ($m = 1; $m <= 12; $m++) {
|
||||
$startDate = sprintf('%04d-%02d-01', $year, $m);
|
||||
$endDate = date('Y-m-t', strtotime($startDate));
|
||||
|
||||
if (strtotime($startDate) > time()) {
|
||||
break;
|
||||
}
|
||||
|
||||
$sums = $this->getAccountSums($tenantId, $startDate, $endDate);
|
||||
$sections = $this->buildSections($accountCodes, $sums, $sums, $unit, true);
|
||||
|
||||
$months[] = [
|
||||
'month' => sprintf('%02d', $m),
|
||||
'label' => $m.'월',
|
||||
'sections' => $sections,
|
||||
];
|
||||
}
|
||||
|
||||
$fiscalYear = $this->getFiscalYear($year);
|
||||
|
||||
return [
|
||||
'year' => $year,
|
||||
'fiscal_year' => $fiscalYear,
|
||||
'fiscal_label' => "제 {$fiscalYear} 기",
|
||||
'unit' => $unit,
|
||||
'months' => $months,
|
||||
];
|
||||
}
|
||||
|
||||
private function getAccountCodes(int $tenantId)
|
||||
{
|
||||
return DB::table('account_codes')
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('is_active', true)
|
||||
->whereIn('category', ['revenue', 'expense'])
|
||||
->orderBy('sort_order')
|
||||
->orderBy('code')
|
||||
->get();
|
||||
}
|
||||
|
||||
private function getFiscalYear(int $currentYear): int
|
||||
{
|
||||
return $currentYear - 2024; // 코드브릿지엑스 설립 2025-09-13, 1기 = 2025년
|
||||
}
|
||||
|
||||
/**
|
||||
* 섹션 조립 공통 로직
|
||||
*/
|
||||
private function buildSections($accountCodes, array $currentSums, array $previousSums, string $unit, bool $currentOnly = false): array
|
||||
{
|
||||
$sections = [];
|
||||
$calcValues = [];
|
||||
|
||||
@@ -79,24 +148,17 @@ public function data(array $params): array
|
||||
foreach ($relatedAccounts as $ac) {
|
||||
$curDebit = $currentSums[$ac->code]['debit'] ?? 0;
|
||||
$curCredit = $currentSums[$ac->code]['credit'] ?? 0;
|
||||
$prevDebit = $previousSums[$ac->code]['debit'] ?? 0;
|
||||
$prevCredit = $previousSums[$ac->code]['credit'] ?? 0;
|
||||
$curAmount = $ac->category === 'revenue' ? ($curCredit - $curDebit) : ($curDebit - $curCredit);
|
||||
|
||||
if ($ac->category === 'revenue') {
|
||||
$curAmount = $curCredit - $curDebit;
|
||||
$prevAmount = $prevCredit - $prevDebit;
|
||||
} else {
|
||||
$curAmount = $curDebit - $curCredit;
|
||||
$prevAmount = $prevDebit - $prevCredit;
|
||||
$prevAmount = 0;
|
||||
if (! $currentOnly) {
|
||||
$prevDebit = $previousSums[$ac->code]['debit'] ?? 0;
|
||||
$prevCredit = $previousSums[$ac->code]['credit'] ?? 0;
|
||||
$prevAmount = $ac->category === 'revenue' ? ($prevCredit - $prevDebit) : ($prevDebit - $prevCredit);
|
||||
}
|
||||
|
||||
if ($curAmount != 0 || $prevAmount != 0) {
|
||||
$section['items'][] = [
|
||||
'code' => $ac->code,
|
||||
'name' => $ac->name,
|
||||
'current' => $curAmount,
|
||||
'previous' => $prevAmount,
|
||||
];
|
||||
$section['items'][] = ['code' => $ac->code, 'name' => $ac->name, 'current' => $curAmount, 'previous' => $prevAmount];
|
||||
}
|
||||
|
||||
$currentTotal += $curAmount;
|
||||
@@ -117,11 +179,8 @@ public function data(array $params): array
|
||||
}
|
||||
|
||||
$divisor = match ($unit) {
|
||||
'thousand' => 1000,
|
||||
'million' => 1000000,
|
||||
default => 1,
|
||||
'thousand' => 1000, 'million' => 1000000, default => 1
|
||||
};
|
||||
|
||||
if ($divisor > 1) {
|
||||
foreach ($sections as &$s) {
|
||||
$s['current_amount'] = (int) round($s['current_amount'] / $divisor);
|
||||
@@ -135,18 +194,7 @@ public function data(array $params): array
|
||||
unset($s);
|
||||
}
|
||||
|
||||
$currentYear = (int) date('Y', strtotime($endDate));
|
||||
$baseYear = 2024; // 코드브릿지엑스 설립 2025-09-13, 1기 = 2025년
|
||||
$fiscalYear = $currentYear - $baseYear;
|
||||
|
||||
return [
|
||||
'period' => [
|
||||
'current' => ['start' => $startDate, 'end' => $endDate, 'label' => "제 {$fiscalYear} (당)기"],
|
||||
'previous' => ['start' => $prevStartDate, 'end' => $prevEndDate, 'label' => '제 '.($fiscalYear - 1).' (전)기'],
|
||||
],
|
||||
'unit' => $unit,
|
||||
'sections' => $sections,
|
||||
];
|
||||
return $sections;
|
||||
}
|
||||
|
||||
private function getAccountSums(int $tenantId, string $startDate, string $endDate): array
|
||||
|
||||
@@ -447,3 +447,4 @@
|
||||
|
||||
// Income Statement API (손익계산서)
|
||||
Route::get('/income-statement', [IncomeStatementController::class, 'index'])->name('v1.income-statement.index');
|
||||
Route::get('/income-statement/monthly', [IncomeStatementController::class, 'monthly'])->name('v1.income-statement.monthly');
|
||||
|
||||
Reference in New Issue
Block a user