Commit e06900e1 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix(accounting): balance sheet did not balance — accumulated profit was omitted

Assets came to 124,051,895.29 against liabilities + equity of 84,950,136.58.
Out by 39,101,758.71 — a balance sheet that does not balance.

Cause: the sheet added only the CURRENT fiscal year's net income to equity. No
year-end closing entry has ever been posted here (period_closings is empty), so
the revenue and expense accounts still carry all-time balances and retained
earnings has never absorbed prior years. The earlier years' profit therefore sat
in the income accounts and appeared nowhere on the sheet.

Verified against the live ledger:
  liabilities                     79,821,436.63
  revenue - expenses (all time)   44,230,458.66   (80,820,684.83 - 36,590,226.17)
                                 ---------------
                                 124,051,895.29 = total assets, exactly

Accumulated profit now runs from the first posted entry rather than the fiscal
year start. This stays correct after closing entries begin: a closing entry moves
the profit into retained earnings and zeroes the income accounts, so the figure
then covers only post-closing activity while the closed profit sits in the equity
accounts. The current fiscal year's slice is still returned separately, as
current_period_net_income, because that is what the board asks about.

Note for the chart: there are no accounts typed 'equity' at all — capital (2101)
and retained earnings (210201) are typed 'liability'. That is why total_equity
consists solely of the accumulated-profit line. The sheet balances either way,
but the classification is worth revisiting with the accountants.
Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
parent 8af96aea
......@@ -179,16 +179,38 @@ final class FinancialReportService
}
}
// Calculate current-period net income and add to equity
$fiscalYearStart = self::getFiscalYearStart($asOfDate);
$incomeStatement = self::getIncomeStatement($fiscalYearStart, $asOfDate, $costCenterId, $branchId);
$netIncome = $incomeStatement['net_income'];
// Accumulated profit must be carried into equity for the sheet to balance.
//
// It has to run from INCEPTION, not from the fiscal-year start. No year-end
// closing entry has ever been posted in this ledger (period_closings is
// empty), so the revenue and expense accounts still carry their all-time
// balances and retained earnings has never absorbed prior years. Adding only
// the current year left the sheet out by exactly the earlier years' profit —
// 39,101,758.71 against assets of 124,051,895.29.
//
// Accumulating from inception is also correct once closing entries do start:
// a closing entry moves the P&L into retained earnings and zeroes the income
// accounts, so this figure then covers only the post-closing activity while
// the closed profit sits in the equity accounts above. Either way it balances.
$inception = $db->selectOne(
"SELECT MIN(entry_date) AS d FROM journal_entries WHERE status = 'posted' AND is_archived = 0"
);
$fromDate = $inception['d'] ?? '1900-01-01';
$accumulated = self::getIncomeStatement($fromDate, $asOfDate, $costCenterId, $branchId);
$netIncome = $accumulated['net_income'];
// The current fiscal year's slice is reported alongside it, because that is
// the figure the board actually asks about.
$currentPeriod = self::getIncomeStatement(
self::getFiscalYearStart($asOfDate), $asOfDate, $costCenterId, $branchId
);
if (bccomp($netIncome, '0.00', 2) !== 0) {
$equity[] = [
'account_code' => '---',
'name_ar' => 'صافي ربح/خسارة الفترة',
'name_en' => 'Current Period Net Income',
'name_ar' => 'أرباح متراكمة غير مقفلة',
'name_en' => 'Accumulated Undistributed Profit',
'balance' => $netIncome,
];
$totalEquity = bcadd($totalEquity, $netIncome, 2);
......@@ -204,6 +226,8 @@ final class FinancialReportService
'total_liabilities' => $totalLiabilities,
'total_equity' => $totalEquity,
'total_liabilities_and_equity' => $totalLiabilitiesAndEquity,
'net_income' => $netIncome,
'current_period_net_income' => $currentPeriod['net_income'],
'is_balanced' => bccomp($totalAssets, $totalLiabilitiesAndEquity, 2) === 0,
'as_of_date' => $asOfDate,
];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment