feat: period-scoped P&L and as-of balance sheet; closes don't zero periods
The engine only had life-of-ledger P&L and balance sheet totals, so every export labeled with a date range or as-of date (PDF, XLSX, CPA package) printed all-time numbers under that label. Core now has: - profit_and_loss_for_period(start, end, class?) and balance_sheet_as_of(as_of), each with a line per account (StatementLine: code, name, normal-side amount) and exact totals. - Ledger::closing_entry_ids(). Period statements exclude closing entries. A close (Dr revenue / Cr expense / net to Retained Earnings, dated at period end) moves earnings; it doesn't earn or spend. Counting it made a closed period's P&L read as break-even, and made the cash flow show zero net income plus a fake "owner contribution" to Retained Earnings. The as-of balance sheet keeps closing entries: after a close the earnings belong in Retained Earnings, not current earnings. Tests: tests/statements.rs, a two-month fixture with every expected number computed by hand (Jan NI 1,700; Feb 880; balance sheets on four dates; a closed January still reporting 1,700 and a cash flow with one financing line). Mutation-checked: dropping the closing exclusion fails it (0 vs 1,700). Properties: period P&Ls partition a year at any split, and a range's net income equals the change in current earnings across it, with A = L + E on both dates. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MtYEaR6M6Ybdhm6X98BWNu
This commit is contained in:
1 parent
5548902f27
commit
c6faeeb827
7 files changed
+505
-13
No files matched your search
+13
-4
@@ -34,10 +34,19 @@ requirement conflict, the requirement wins.
|
||||
total credits (the `balanced()` check).
|
||||
- **R-8 — Balance sheet.** Assets, liabilities, equity grouped by account
|
||||
type. The accounting equation holds exactly: assets = liabilities + equity.
|
||||
Because period close (R-FUTURE-2) doesn't exist yet, current earnings (net
|
||||
income to date) are folded into equity so the equation holds on a live book.
|
||||
- **R-9 — Profit and loss.** Revenue and expenses for the life of the ledger,
|
||||
with net income. Period filtering arrives with R-FUTURE-2.
|
||||
Current earnings (revenue minus expenses not yet closed to retained
|
||||
earnings) are folded into equity so the equation holds on a live book.
|
||||
`balance_sheet_as_of` gives the statement as of any date, a line per
|
||||
account, counting every entry dated on or before it (closing entries
|
||||
included: after a close the earnings sit in retained earnings).
|
||||
- **R-9 — Profit and loss.** Revenue and expenses with net income.
|
||||
`profit_and_loss_for_period` scopes it to a date range (optionally one
|
||||
class), a line per account, and **excludes closing entries**: a close moves
|
||||
earnings into retained earnings and must not make a closed period read as
|
||||
break-even. The cash flow statement excludes closing entries for the same
|
||||
reason. Period P&Ls partition: split a range anywhere and the halves sum
|
||||
to the whole, and a range's net income equals the change in current
|
||||
earnings across it (property-tested).
|
||||
- **R-10 — Canonical snapshots.** `reports::snapshot()` renders the three
|
||||
core reports as deterministic JSON (decimal strings, sorted lines, fixed
|
||||
keys). Two engines fed the same books must produce identical output. This
|
||||
|
||||
Reference in new issue
Block a user