DEV Community

Son Do
Son Do

Posted on

Stop Re-Keying Invoices: Posting Billing and LawPay Events to the GL

Series -- When the Aggregate Looks Right: 0: Overview · 1: Chart of Accounts · 2: Three-Way Reconciliation · 3: The Aggregate Can Lie · 4: Bank Sync · 5: GL Integration

The invoice already exists in MyCase. The LawPay settlement already hit the
payment ledger. Somewhere else -- a spreadsheet, a separate accounting tool,
a second set of books -- someone types the same numbers again.

That re-keying is not a one-off fat-finger story. It is the default
integration pattern when practice management and firm accounting are two
systems of truth. The concrete miss inside the pattern is familiar: a
payment shows as collected in billing, and the books disagree, or the books
never got the line at all. Someone forgot, or delayed, or rounded, or
posted to the wrong place on the second pass.

This post is about refusing that pattern. We integrated existing MyCase
billing, invoicing, and LawPay payment ledger events into MyCase Accounting
GL posting rules on Rails so time, invoices, and trust/operating payments
posted without re-keying.

The rejected alternative: export/import

The easy-sounding integration is a file. Export invoices and payments from
billing. Import them into Accounting on a schedule. Call it done.

Export/import keeps two systems of truth and reintroduces lag. Anything that
can lag can miss. Anything that can miss puts you back in the phone-call
failure mode from Part 0: the
aggregate looks fine until a human notices the gap.

What we shipped instead: auto-post at the billing and payment event. When
the billing layer records the fact, Accounting posting rules write the GL
entries into the
locked chart of accounts
under trust and operating rules. One event, one post, same Rails
transaction boundary where we could keep it honest.

The boundary: ledger-to-GL inside the monolith

There is no romantic microservice story here. Billing and Accounting lived
in the same Rails monolith. The seam was a ledger-to-GL bridge:

  • Billing owns the payment and invoice facts.
  • Accounting owns the posting rules onto the chart of accounts.
  • The contract is prosaic: when billing records X, Accounting posts Y, routed trust versus operating correctly.

Ledger-to-GL bridge: billing events post into the general ledger at event time inside the monolith

That boring boundary matters. It means the invoice identity
Part 3 matches against is the
same invoice billing just wrote -- not a copied row from last night's CSV
that drifted. It means
Part 4 Match has real in-system
twins to link bank feed lines to, instead of an empty ledger waiting on
manual entry.

Firms activate Accounting onto the pre-populated locked chart; posting
rules hang on those system accounts from the first event.

Closing the series

The failure mode at the start of this series was simple and ugly: an
aggregate that reconciled to the cent while a client's money was in the
wrong place.

The path through it was cumulative:

  1. Lock the chart so auto-post and matching have stable identity.
  2. Auto-generate client trust ledgers so three-way is real, not optional.
  3. Flag trust-to-operating movement with invoice-exact matching so reviewers trust every alert.
  4. Match bank feeds without categorizing trust into a second source of truth.
  5. Post billing and LawPay events into the GL at event time so the books and the practice stay one system of truth.

Closing the loop: how Parts 1-5 compose into books that cannot hide behind a clean aggregate

Watch closely without destroying the signal. Stop making a human retype the
signal into a second ledger. That is the work.

Series -- When the Aggregate Looks Right: 0: Overview · 1: Chart of Accounts · 2: Three-Way Reconciliation · 3: The Aggregate Can Lie · 4: Bank Sync · 5: GL Integration

Top comments (0)