Record GL trial-balance integrity check (audit #2)
Empirical per-company trial-balance net on stored CurrentBalance. Both tenants imbalanced, but from pre-existing data, not this session: - Demo: $89.5k opening-balance-without-equity (demo artifact) + $3,153.63 postings. - SCP: $3,079.52, all postings. Forensics: AR reconciles (invoices−payments), but Revenue has $0 GL movement (24 header-only invoices, 0 line items → no per-item revenue credit) and payment-side bank debit never posted. One-sided postings from imported/header-only docs + null offset accounts skipped by AccountBalanceService — same class as O2/O6/O7/O8. Conclusion: this session's changes did not introduce the imbalance and in fact prevent the bug class going forward. Remediation options documented (not auto-applied — SCP is live data). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -246,8 +246,40 @@ deposit account. **No ledger-drift bugs found.** Notes:
|
||||
always consistent with the displayed type. A read-only sweep of the dev DB (109 accounts) found **0** existing
|
||||
mismatches, so no repair tool was needed.
|
||||
|
||||
### 2026-06-20 — GL trial-balance integrity check (audit "#2")
|
||||
Ran an empirical per-company trial-balance net on stored `Account.CurrentBalance`
|
||||
(`SUM(debit-normal) − SUM(credit-normal)`, which must net to 0 for balanced books). **Both tenants are
|
||||
imbalanced**, but the cause is pre-existing data, **not** this session's changes.
|
||||
|
||||
- **Demo Company:** net Dr **$92,653.63** = **$89,500 opening-balance** entry without an offsetting equity
|
||||
line (normal demo-data artifact) + **$3,153.63** from postings.
|
||||
- **SCP Powder Coating** (opening balance $0, clean start): net Dr **$3,079.52**, entirely from postings.
|
||||
|
||||
**Root cause (forensics on SCP):** AR reconciles correctly (~invoices $21,496 − payments $18,314 ≈ stored
|
||||
$3,079), so AR posted on both sides. But **Revenue has $0 GL movement** (the 24 invoices are header-only —
|
||||
**0 line items** — so the per-`InvoiceItem` revenue credit never fires) and the **payment-side bank debit
|
||||
never posted** ($0 bank delta from 22 payments). This is the classic one-sided posting from
|
||||
(a) imported/header-only invoices and (b) postings to unconfigured (null) offset accounts, which
|
||||
`AccountBalanceService` silently skips. Same architectural class as O2/O6/O7/O8.
|
||||
|
||||
**Conclusion:** this session's work (default GL accounts, deposit guard, money-account guards, tenant sweep)
|
||||
**did not introduce the imbalance** — those changes are read-path + validation + defaults and actually
|
||||
*prevent* this bug class going forward (new invoices now fall back to a default revenue account; deposits/
|
||||
payments are guarded against null money accounts). The existing imbalance is legacy/imported data.
|
||||
|
||||
**Remediation options (owner's call — not auto-applied; SCP is live company data):**
|
||||
- `Recalculate Balances` re-derives from source docs but will **not** conjure revenue for header-only
|
||||
invoices (no line items to credit), so it won't fully fix SCP on its own.
|
||||
- Durable fix: the **JournalEntry single-source** refactor (`docs/ACCOUNTING_LEDGER_REFACTOR.md`) forces every
|
||||
event to post balanced lines.
|
||||
- Historical cleanup: correcting journal entries (or backfilling revenue/bank accounts on the imported docs
|
||||
then recomputing) — a deliberate data-remediation task.
|
||||
- Worth considering: surfacing this trial-balance net as a built-in "GL Health" indicator so drift is visible.
|
||||
|
||||
## Status
|
||||
**All findings O1–O9 + the read-path sweep are resolved** on `dev` (O9 by policy decision — expense at
|
||||
purchase — needing no code change). The optional structural follow-up is the JournalEntry single-source
|
||||
refactor (`docs/ACCOUNTING_LEDGER_REFACTOR.md`), which would prevent the O2/O6/O7/O8 bug class from recurring.
|
||||
The 2026-06-20 trial-balance check confirmed a pre-existing GL imbalance from legacy/imported one-sided
|
||||
postings (not from recent changes) — see above for remediation options.
|
||||
Original audit numbering #1–3/#5/#6/#8 remains unrecoverable (see top). Nothing merged to `master` yet.
|
||||
|
||||
Reference in New Issue
Block a user