Currency lock: why we treat it as a structural invariant
Most billing systems let you change a tenant's currency in settings. Tenelix doesn't — and that's the whole point.
Imagine a clinic that's been operating in NGN for two years. They issue thousands of invoices, collect millions in payments, and one day someone changes the currency setting from NGN to USD. What happens?
In most systems: the previous invoices are silently re-displayed in USD. The numbers look small. Nobody notices for a week. By the time finance catches it, reports across an entire fiscal quarter are corrupted.
This is the kind of bug that a settings page shouldn't be able to cause.
How Tenelix handles it
Tenelix locks the tenant's currency the moment any revenue artifact exists. Specifically:
- The first time a
Serviceis created in the tenant, currency is locked - Or the first time an
Invoiceis created - Or the first time a
Paymentis recorded
Once locked, the currency setting becomes read-only. The settings page shows a banner explaining why. The only way to "change" currency is via a support-assisted migration, which involves explicit reconciliation — not a dropdown.
The check is enforced at three layers
This is a recurring pattern in Tenelix: any sensitive invariant gets enforced at three layers:
- Route ability — the route is gated by an ability check
- FormRequest::authorize() — the request validates the operation is allowed
- AuthorizationService::authorize() — the controller / action re-checks at the data layer
For currency lock specifically, layer 3 is the structural one. Even if someone bypassed the route and the form request, the data layer refuses. The lock isn't a UI concern; it's a database concern.
Why this matters
Healthcare clinics get audited. Currency drift in financial records is the kind of thing that turns a quarterly review into a forensic investigation. The right design for systems handling money is to make drift structurally impossible, not just unlikely.
Settings pages should never silently corrupt history. We've seen too many billing systems where they do — and we built Tenelix to be the opposite end of that spectrum.
If you've ever spent a weekend manually re-denominating an entire ledger, you know exactly why this matters.