Pipeline history
Four history tables — requisition, requisition item, purchase order and bill — each recording the previous status, the new status, who changed it and when.
Access is data rather than code, duties are separated by design, and nothing is deleted. Here is how each of those actually works.
There is no hardcoded list anywhere of which role sees which page. A page is a database row, a grant is another row, and administrators edit them in the Control Unit.
Assign
The page is assigned to a department or team. This is the real boundary — it is checked on read and on write, and saving it prunes grants that fall outside it.
Grant
The role is granted the page, as four separate flags: read, write, delete and export. Write, delete and export each imply read.
Grant without assignment and nothing appears. Add a page, assign it, grant it — and it shows up in the sidebar with no release.
The superuser bypasses ordinary page checks, but four things stay off-limits even to it:
System roles and departments return an error on update, and there is no endpoint that deletes them at all.
Four different people touch a bill before it closes, and each step verifies the state the one before it left behind.
| Reserved page | Held by, and only by |
|---|---|
| Bill authorisation | Senior Account Manager |
| Billing processing | Assistant Account Manager |
| VAT & tax record | Assistant Account Manager |
These three are not merely un-granted to everyone else — they are actively revoked from every other non-superuser role each time the permission seed runs, so the separation cannot drift.
Enforced in three independent places, so no single missed check exposes a counterparty.
The data the API returns
Every email template
Every generated PDF
Records move through statuses rather than disappearing, and every stage leaves a trail behind it.
Four history tables — requisition, requisition item, purchase order and bill — each recording the previous status, the new status, who changed it and when.
Every edit to a client, vendor or user is logged and surfaced in the interface as that record's own history.
Every VAT or AIT rate change writes an audit row, retrievable per configuration.
A superuser-only feed across eight categories — user, tax, mail, authentication, vendor, client, system and other — filterable by category, status, date and free text.
Every physical transfer between vendor, warehouse, client and unit is a recorded movement, giving goods the same audit trail money has.
Requisitions, items, orders and bills each expose a full timeline, so "who touched this and when" is a page, not a database query.
Deactivated, never destroyed
Records move to inactive, suspended or archived. Users are never deleted — a deactivated account is simply refused at sign-in, leaving its history intact.
There is no hardcoded list of which role sees which page. Every page is a row, every grant is a row, and administrators edit them in the Control Unit. Add a page, grant it, and it appears in the sidebar — no release required.
Three finance pages belong to exactly one role each and are revoked from everyone else on every seed run. The person who authorises a payment is never the person who executes it.
Records move through statuses rather than disappearing. Four history tables, change logs on master data, a tax audit trail and a system-wide audit log across eight categories.
Even the superuser is denied client-only and vendor-only pages, cannot open Inventory, and cannot edit its own permission matrix. System roles and departments cannot be renamed or deleted.
Status changes run inside serializable transactions, so a partial pipeline move is impossible. Selecting a winning quote sets the winner, rejects the others and prices the item in one write.
No self-service sign-up. Every organisation and user is created by an administrator and must pass a six-digit email code — hashed, constant-time compared, valid four minutes, five attempts.