Part 15 of 40 · 7 min read
Record to report: make the operating picture explainable
Experimental · Work in progress · Internal R&D
Connect operational events to balanced postings and period review, with explicit reversal and duplicate-obligation handling.
Arunank Sharan · Kuzushi Labs ·
In this article
A company can have a full pipeline, active projects and an empty bank account. To understand the business, I need to distinguish commitments, earned amounts, invoices, receipts and costs. The Record-to-Report loop translates operational events into financial records that can be inspected and reconciled.
The prototype has journal entries, balanced postings, account balances, reversals and period-close gates. It also has local examples connecting delivery and purchasing events to the same ledger. These are useful executable patterns, while production accounting rules and integrations remain work in progress.
Follow one illustrative transaction
Use a simplified example: accepted work creates an S$18,000 receivable under the example's posting policy; a supplier cost of S$12,000 is approved and paid; the customer has not paid yet.
| Event | Debit | Credit |
|---|---|---|
| Eligible customer billing event | Receivable 18,000 | Revenue 18,000 |
| Approved operating expense | Expense 12,000 | Payable 12,000 |
| Confirmed supplier payment | Payable 12,000 | Cash 12,000 |
The example has a positive revenue-minus-expense difference and a cash outflow. That is the point: “profitable work” and “cash collected” are not the same state. The exact recognition and classification policy must be attached to the real agreement and transaction; a generic sales event cannot decide it for every business.
The posting engine uses deterministic rules
The existing engine represents a journal as postings, checks its balance and applies it through a governed action. An unbalanced journal is rejected. A reversal is represented explicitly rather than silently rewriting the original entry.
A compact illustration of the intended numeric boundary is:
from decimal import Decimal
postings = [
{"account": "receivable", "debit": Decimal("18000.00"), "credit": Decimal("0")},
{"account": "revenue", "debit": Decimal("0"), "credit": Decimal("18000.00")},
]
assert sum(p["debit"] - p["credit"] for p in postings) == 0
This example uses decimal arithmetic. The prototype currently contains float-based money values and a balance tolerance. Migrating the production boundary to exact money types, currency-aware rounding and explicit exchange-rate records is part of the hardening plan.
The model can help explain an invoice, identify a likely classification or investigate a discrepancy. Posting amounts and balance checks should remain deterministic.
One obligation must not create revenue twice
The current event map includes sales-close and delivery-related inputs that can each produce a simple receivable/revenue example. In isolated tests that demonstrates several integration routes. If all were enabled together without a recognition key, one customer commitment could be counted more than once.
The integrated design needs a unique claim such as:
(tenant, obligation_id, recognition_policy_version, recognition_event_id)
A consumer records the claim atomically with the journal. Delivery acceptance and invoice generation can both refer to it without each creating another recognition. A transport retry is another source of duplication, but not the only one: two different events can describe the same underlying economic result.
Close a period without erasing uncertainty
The local close process uses a checklist and includes a trial-balance gate. A balanced ledger is necessary, but it can still contain the wrong account, duplicate entries or an omitted transaction. The close review should therefore include reconciliations, unresolved exceptions and evidence that the period's source systems were covered.
An operator-facing exception might say:
Period: September
Issue: bank import completed after the reporting cutoff
Affected records: 3 unallocated receipts
Decision: review allocations before locking the period
Evidence: import batch and statement references attached
A hard close is a consequential action. The AI can prepare the checklist and explanations; the authorised person decides the close. Corrections after closure need a defined adjustment process with their own records.
Connect the business record to the explanation
The founder should be able to move from a dashboard amount to its journals, then to the invoice or delivery evidence that caused them. A generated narrative should cite those records. It should not invent a story about “strong customer demand” because revenue rose.
For the first real deployment, I would keep an existing accounting system authoritative while comparing the platform's projected records in shadow mode. The connector would retain external journal IDs and reconciliation differences. Replacing established financial records before this comparison would create unnecessary operational risk.
The useful measure
I would track reconciliation coverage, duplicate postings, unmatched-source age, correction volume and time to resolve an exception. The platform's local tests already demonstrate balanced income and cost examples on one runtime. The next proof is a complete, reproducible source-to-report path for a small real period, with every difference explained.
Prove that the posting is internally consistent
The operational platform needs an explainable projection of money movements and obligations. A balanced journal is one mechanical condition, not proof that the chosen accounting treatment is correct. I would encode the approved posting policy separately from the event handler and retain its version with every entry.
The public lab checks exact minor-unit balance and rejects mixed-currency lines:
from company_lab.business import balanced
entry = [
{"currency": "SGD", "debit": 600000, "credit": 0},
{"currency": "SGD", "debit": 0, "credit": 600000},
]
assert balanced(entry)
assert not balanced([entry[0], {**entry[1], "currency": "USD"}])
Account codes, recognition policy, taxes and currency translation are outside this minimal calculation. In a real setup, the company's accounting policy and accountant determine those mappings. The engineering task is to execute them consistently and make every derived number traceable.
Deduplicate by the obligation, not only the event
A delivery event and a proof-of-delivery event can both describe the same accepted milestone. Deduplicating each event ID does not stop two consumers from posting the same obligation twice. Introduce a business key such as (tenant, commitment, milestone, posting_purpose, policy_version) and decide deliberately how policy changes produce adjustments rather than duplicates.
A proposed posting request carries the source event, underlying obligation, evidence version, posting template and expected period. The financial consumer claims that obligation in the same transaction as creating the journal entry. A unique constraint becomes an accounting control with a concrete failure signal.
CREATE TABLE posting_claim (
tenant_id TEXT NOT NULL,
obligation_id TEXT NOT NULL,
purpose TEXT NOT NULL,
journal_id TEXT NOT NULL,
PRIMARY KEY (tenant_id, obligation_id, purpose)
);
This schema is a design fragment. Version corrections should normally produce linked adjustments under the approved policy, rather than changing the purpose key to evade the uniqueness rule.
Make reversals explicit
If an invoice is cancelled after posting, preserve the original entry and add a linked reversal or adjustment. Editing the historical amount destroys the ability to explain earlier reports. The operation record should identify who requested the correction, which source changed and why the accounting projection needed to change.
A report then becomes a query over committed entries with clear period and status rules. Drafts should not quietly enter an operational cash forecast or formal financial report under the same label. If the founder wants a forecast that includes draft invoices, show the forecast assumption separately from confirmed receivables.
Reconcile three views of the same business
The platform's operating records, the accounting system and provider or bank evidence will not always update at the same instant. A reconciliation job compares their identities and balances, then categorises differences: timing, missing event, duplicate mapping, amount mismatch or policy exception.
For example, a provider confirms a payment while the accounting API is unavailable. Cash evidence exists, but the posting projection is pending. The founder should see that specific state. Marking the entire customer journey failed would hide useful progress; marking every system synchronised would be false.
The connector can prepare a batch of reviewed entries and retain external journal IDs. Its retries use the original posting operation identity. If the accounting provider lacks an idempotency contract, perform a lookup or hold an uncertain result instead of blindly recreating the entry.
Close a period with inspectable gates
Before a period is locked, check unresolved receipt outcomes, unbalanced drafts, unmatched invoices, missing required approvals and reconciliation exceptions. A failed gate should identify the records that need action. A single “close failed” message is not enough for one founder to operate the system.
The implementation exercise is to send two distinct delivery events for one milestone, then reverse the obligation. The expected ledger contains one original posting and one linked correction, not two originals and an unexplained overwrite. That is a much stronger test of financial workflow integrity than checking that a generated report sounds coherent.