One ledger for a club running on six systems
Point of sale, member accounts, bookings, and statements unified behind one ledger, with double-booking made structurally impossible at the database level.
The problem
Member charges, dining, pro shop sales, events, and dues lived in separate systems that had to be reconciled by hand into a monthly statement. Reservations were coordinated across tools that had no knowledge of each other, so double-bookings were a matter of when rather than if.
What we did
- 01
Built a single ledger as the financial spine and derived every member balance from it at read time, so the statement can never drift from the transactions behind it.
- 02
Enforced no-overlap booking with a database exclusion constraint rather than application logic — two conflicting reservations cannot be committed even under a race.
- 03
Made idempotency explicit on every money-moving operation, including releasing in-progress locks on failure so a crash does not wedge the system.
- 04
Put shared, typed contracts between the API and the interface so the two could be built in parallel without drift.
- 05
Verified the complete revenue cycle through the real interface — member to charge to statement — rather than testing the pieces separately and assuming.
The transferable lesson
Some rules belong in the database, not the application. "Two people cannot book the same court at the same time" is a constraint, and a constraint enforced by Postgres holds under conditions where an application-level check quietly does not.