Commit Graph
44 Commits
Author SHA1 Message Date
swaitsandClaude Opus 5.5 353bef1d5d feat: general ledger by account, trial balance as of, members' equity
Three reports a CPA expects that the engine could not produce:

- general_ledger(start, end): the canonical general ledger, organized by
  account in code order. Each account has its beginning balance, every
  posting in the period (date, entry, description, debit, credit, running
  balance on the normal side) and its ending balance, which ties to the
  trial balance. Each posting names its split: the one account on the
  opposite side of its entry, or "-Split-" when that side has several,
  so a compound entry (one debit, several credits) reads correctly from
  every account it touches. The entry-ordered listing the exports called a
  "general ledger" is really the general journal.
- trial_balance_as_of(as_of): a trial balance is always as of a date.
- members_equity(start, end, members): the statement of changes in
  members' equity for a multi-member LLC taxed as a partnership. Each
  member's capital roll-forward: beginning (capital plus their share of
  undistributed earnings), contributions, allocated net income (loss),
  distributions, ending. Allocation is by ownership share to the cent,
  the last member absorbing rounding, so totals are exact and the ending
  total equals balance-sheet equity; any equity change the roll-forward
  can't explain shows as "other" instead of disappearing. Shares must be
  positive and sum to exactly 1; capital accounts must be distinct
  equity accounts (LedgerError::InvalidMembers).
- CashFlowLine.account: the account a line is about, so renderers can
  name members instead of account codes.

Tests (every expectation computed by hand): trial balance as of Jan 31;
February general ledger with beginning balances, running balances, a
card that nets to zero, an inactive account still listed, and every
ending balance tied to the trial balance; a compound entry's splits from
all three sides; a two-member partnership where 666.67 and 100.01 split
unevenly (333.34/333.33, 50.01/50.00), with and without closing January,
tying to the balance sheet each month; bad member configuration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtYEaR6M6Ybdhm6X98BWNu
2026-10-11 20:16:25 -07:00
swaitsandClaude Opus 5.5 45e167c233 chore: clippy clean across the workspace, all targets
Zero warnings from `cargo clippy --workspace --all-targets`, which is now
a hard rule rather than "clean except pre-existing":

- ChartOfAccounts::add takes the Account it registers instead of eight
  loose parameters (too_many_arguments); Ledger::add_account builds it.
  Same validation, same errors.
- close_period tool: collapse the nested if-let into a let chain.
- iif.rs docs: the IIF layout example shows tabs as `\t` instead of
  literal tab characters (tabs_in_doc_comments).
- Tests: drop an unused binding; assert! instead of assert_eq! against a
  literal bool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtYEaR6M6Ybdhm6X98BWNu
2026-10-11 19:24:10 -07:00
swaitsandClaude Opus 5.5 dc3dc8bd24 feat: Typst-typeset statements in US accounting format
The printpdf statements padded columns with spaces in a proportional font
(amounts didn't line up), had no company name, printed negatives as
"-207.68", and put everything on one page (a long statement was silently
cut off past ~70 lines). Now:

- PDFs are typeset by Typst from one template,
  ledger-import/templates/statement.typ. The laid-out statement goes in as
  JSON data (sys.inputs), so account names are never parsed as markup.
  Fonts are bundled (typst-assets: Libertinus Serif), so output doesn't
  depend on the machine and is byte-for-byte deterministic. Statements
  paginate, with the company/title repeated on later pages and "Page n of
  m" plus "Prepared from journal through seq N" in the footer.
- US accounting presentation, decided once in ledger-import::report and
  applied by both PDF and XLSX: tabular figures; "$" on each section's
  first amount and on every subtotal and total, pinned to the column's
  left edge; negatives in parentheses with the closing paren hanging (its
  width reserved on every row, so decimal points align); zero as a dash;
  a single rule above sums (none over an empty section) and a double rule
  under statement totals; amounts never bold, because bold figures are
  wider and would leave the decimal column. XLSX uses Excel's own
  Accounting formats for the same result.
- Cash flow: "Net change in cash" is a subtotal; only "Cash at end of
  period" takes the double rule.
- Core fix: cash_flow walked the chart in HashMap order, so the order of
  working-capital and financing lines could change between runs. Lines
  now follow account code. Test: five owners, twenty runs, always
  3000/3001/3003/3005/3009; fails without the sort.

New dependencies (ledger-import): typst, typst-layout, typst-pdf,
typst-assets (fonts), typst-as-lib (World/font plumbing), serde_json (the
template's data). Removed: printpdf. Release ledger-mcp grows by the
bundled fonts.

Tests: exact template data for a hand-built P&L (like a golden); same
statement renders to identical bytes; 200 rows of Typst markup
characters render literally and span several pages; currency-sign and
rule placement; amount splitting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtYEaR6M6Ybdhm6X98BWNu
2026-10-11 19:23:01 -07:00
swaitsandClaude Opus 5.5 78ac7099b8 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
2026-10-11 19:04:18 -07:00
swaits 266545bfb9 Payroll accounting, class tracking, CPA handoff package (48 MCP tools) 2026-10-11 15:32:02 +00:00
swaits cfebb9e8b3 Payroll accounting, class tracking, CPA handoff package (48 MCP tools) 2026-10-11 15:32:00 +00:00
swaits 6fe8814597 Payroll accounting, class tracking, CPA handoff package (48 MCP tools) 2026-10-11 15:31:58 +00:00
swaits f97be98a44 Payroll accounting, class tracking, CPA handoff package (48 MCP tools) 2026-10-11 15:31:56 +00:00
swaits c38d843633 Payroll accounting, class tracking, CPA handoff package (48 MCP tools) 2026-10-11 15:31:55 +00:00
swaits 1a3af122c5 Payroll accounting, class tracking, CPA handoff package (48 MCP tools) 2026-10-11 15:31:53 +00:00
swaits b2ae0e94f1 Payroll accounting, class tracking, CPA handoff package (48 MCP tools) 2026-10-11 15:31:51 +00:00
swaits e0be84ba95 Period close, bank rec, AR/AP, multi-currency (41 MCP tools) 2026-10-11 08:15:25 +00:00
swaits fb4dd2055d Period close, bank rec, AR/AP, multi-currency (41 MCP tools) 2026-10-11 08:15:24 +00:00
swaits 01a07aed46 Period close, bank rec, AR/AP, multi-currency (41 MCP tools) 2026-10-11 08:15:22 +00:00
swaits 6f077b4cd8 Period close, bank rec, AR/AP, multi-currency (41 MCP tools) 2026-10-11 08:15:20 +00:00
swaits 01c2689adf Period close, bank rec, AR/AP, multi-currency (41 MCP tools) 2026-10-11 08:15:18 +00:00
swaits a2b23b5fba Period close, bank rec, AR/AP, multi-currency (41 MCP tools) 2026-10-11 08:15:16 +00:00
swaits 1ce4932b9f Next steps 5-10: resources, cash flow, QB interop, backfill, HTTP, parallel-run plan 2026-10-11 03:01:24 +00:00
swaits f37457b557 Next steps 5-10: resources, cash flow, QB interop, backfill, HTTP, parallel-run plan 2026-10-11 03:01:22 +00:00
swaits 470e663f00 Next steps 5-10: resources, cash flow, QB interop, backfill, HTTP, parallel-run plan 2026-10-11 03:01:20 +00:00
swaits 3c3cab1479 Next steps 5-10: resources, cash flow, QB interop, backfill, HTTP, parallel-run plan 2026-10-11 03:01:19 +00:00
swaits e8e1c65c86 asset slice + testing initiative: fixed assets, property/mutation/fuzz testing, docs 2026-10-11 02:25:22 +00:00
swaits eaf6538d1a asset slice + testing initiative: fixed assets, property/mutation/fuzz testing, docs 2026-10-11 02:25:21 +00:00
swaits a8072e9fe1 asset slice + testing initiative: fixed assets, property/mutation/fuzz testing, docs 2026-10-11 02:25:19 +00:00
swaits 08f550d164 asset slice + testing initiative: fixed assets, property/mutation/fuzz testing, docs 2026-10-11 02:25:18 +00:00
swaits 33fe6bf5d0 asset slice + testing initiative: fixed assets, property/mutation/fuzz testing, docs 2026-10-11 02:25:16 +00:00
swaits 3e6b2b8f92 asset slice + testing initiative: fixed assets, property/mutation/fuzz testing, docs 2026-10-11 02:25:13 +00:00
swaits dd9b6694c0 asset slice + testing initiative: fixed assets, property/mutation/fuzz testing, docs 2026-10-11 02:25:12 +00:00
swaits d56b0cf97f asset slice + testing initiative: fixed assets, property/mutation/fuzz testing, docs 2026-10-11 02:25:08 +00:00
swaits 3e9f764a2c asset slice + testing initiative: fixed assets, property/mutation/fuzz testing, docs 2026-10-11 02:25:04 +00:00
swaits 3b39cd2135 asset slice + testing initiative: fixed assets, property/mutation/fuzz testing, docs 2026-10-11 02:25:03 +00:00
swaits b9527baa2e First slice: ledger-store (journal+blobs+sqlite) and ledger-mcp (18 tools, receipt policy) 2026-10-11 01:37:07 +00:00
swaits e90b09a6ea First slice: ledger-store (journal+blobs+sqlite) and ledger-mcp (18 tools, receipt policy) 2026-10-11 01:37:05 +00:00
swaits 54fc4f6300 First slice: ledger-store (journal+blobs+sqlite) and ledger-mcp (18 tools, receipt policy) 2026-10-11 01:37:03 +00:00
swaits afce942e3c Initial commit: wanderbooks accounting semantics engine 2026-10-11 00:46:24 +00:00
swaits b7b34d9fe5 Initial commit: wanderbooks accounting semantics engine 2026-10-11 00:46:23 +00:00
swaits bd6ea3e67e Initial commit: wanderbooks accounting semantics engine 2026-10-11 00:46:21 +00:00
swaits 0d05da02dc Initial commit: wanderbooks accounting semantics engine 2026-10-11 00:46:19 +00:00
swaits 7fbe8a1193 Initial commit: wanderbooks accounting semantics engine 2026-10-11 00:46:17 +00:00
swaits 3abd5ff7a1 Initial commit: wanderbooks accounting semantics engine 2026-10-11 00:46:16 +00:00
swaits 593a8bbfa4 Initial commit: wanderbooks accounting semantics engine 2026-10-11 00:46:14 +00:00
swaits a614600a87 Initial commit: wanderbooks accounting semantics engine 2026-10-11 00:46:13 +00:00
swaits d3a0b097b2 Initial commit: wanderbooks accounting semantics engine 2026-10-11 00:46:11 +00:00
swaits 3489554f57 Initial commit: wanderbooks accounting semantics engine 2026-10-11 00:46:09 +00:00