Front desk asks to split a bill. The company pays room and tax, the guest pays the minibar and the spa. If your booking has a total_amount column, this is now a manual exercise with a calculator and a printed folio.
A folio is a ledger
Every chargeable event is a posting, not an adjustment to a total:
folio_postings
folio_id
stay_date
code -- ROOM | TAX | FNB | SPA | MISC
description
amount_minor
posted_at
posted_by
reversed_by -- null unless corrected
The balance is the sum. It is never stored, because a stored total is a second source of truth that will disagree with the postings the first time someone corrects one.
Corrections are reversing postings, not edits. A charge posted in error stays on the folio with a matching negative beside it. That is not pedantry — a guest disputing a charge that silently vanished has no way to see it was handled, and neither does the night auditor.
Splitting is routing, not arithmetic
Add a second folio to the same reservation and give each posting an owner:
reservations 1 ─── * folios ─── * postings
“Split the bill” becomes moving postings between folios, which is one update to a foreign key and fully reversible. No recalculation, no rounding, no chance of the parts failing to sum to the whole — because the whole was always just the sum of the parts.
Routing rules make it automatic: room and tax to the company folio, everything else to the guest folio, set at check-in from the rate plan.
Why this shape survives the edge cases
Group bookings with one master account and twenty individual folios: same model. A guest extending by two nights mid-stay: two more room postings, no recalculation. Tax that changes rate on the first of the month: the postings already carry their own dates.
Every one of those breaks a total_amount column and none of them break a posting list.
The night audit falls out for free
The end-of-day run is a query over postings by date. With a total column it is a reconstruction, done nightly, that has to guess what happened.