Replacing spreadsheets with one API
A studio group with several branches tracked appointments, stock and staff commissions in spreadsheets. Every branch kept its own file, the same client could hold two appointment records, and monthly commission numbers were reconstructed by hand at the end of each month.
What shaped the work
- Staff were not going to learn a new desktop tool — the admin had to work in a browser and be usable on a tablet at the counter.
- Customers already lived inside a chat app, so the customer-facing surface had to be a Mini Program rather than a web login.
- Money-adjacent numbers (stock movements, commissions) had to be auditable: who changed what, when.
- Existing historical records needed to survive the move, including the inconsistencies.
What it runs on
React (admin) · Django REST API · MySQL · WeChat Mini Program
What we actually built
- One API behind both surfaces: booking, stock, staff, reporting. No business rule lives in the client apps, so the admin and the Mini Program can never disagree.
- Booking carries explicit conflict rules (staff, room, service duration) instead of the soft warnings a spreadsheet gives.
- Stock movements are recorded as events tied to the service that consumed them, so a reconciliation can be reconstructed retrospectively.
- Commission is a function of stored events, not a typed number — recalculating an old month gives the same answer.
- The accountant exports one file per month from the admin rather than extracting anything from the database.
The choices that mattered
Single API, thin clients
Two front ends over one rulebook beats two implementations that drift apart in month two.
Events, not balances
A stored balance cannot answer "why is this number different from last month".
Import the mess, then clean
We imported the historical rows verbatim and flagged the duplicates, rather than silently merging records and losing the trail.
Boring stack
Django and MySQL: a future maintainer can read it without a framework tour.
What we would do next
- Branch-level performance views — the manager currently reads branch comparisons off raw exports.
- Reminder sequence for no-shows, driven from the booking records rather than a separate tool.
What is not on this page
No client name, no screenshots of their data and no metrics: those are theirs. What is here is the engineering, which is the part a buyer can evaluate. On a call we will walk through the code.