Finance & Tax
Closing the books and staying audit-ready are the same ledger.
Finance needs to know where every invoice stands without chasing a status email. Tax needs every submission checked against the actual mandatory field set, not a best-effort mapping. Both run off one ledger with one state machine.
Closing the books
A fixed set of states, not a black hole.
Every invoice you submit lands in one of a fixed set of ledger states and stays there until it reaches a terminal one. Month-end reconciliation is a query against that state, not a spreadsheet someone rebuilds by hand.
Status is always queryable
Per-invoice status is returned on every submit and stays queryable by source_reference — no phone call to find out where an invoice is stuck.
Failures surface before month-end
A failure webhook fires the moment an invoice needs attention, so a rejected submission is a same-day fix, not a surprise during close.
Retries never duplicate
Submissions are idempotent on (tenant, source_reference), chaos-tested under concurrent load — retrying after a timeout never risks a second FTA transmission.
The audit trail is the evidence
Every transition is written to an append-only, trigger-enforced audit trail — the record an auditor asks for already exists.
Ledger state machine
Three failure-shaped states are reachable from any stage — each one is a persisted status, not a dropped request.
Staying audit-ready
Validation runs against the actual mandate, not a summary of it.
Every submission is checked against the official MoF mandatory field set and the official Peppol PINT-AE VAT codelist — including the cross-consistency and line-math checks that are easy to miss when a mapping is built by hand.
The official field set, not our interpretation of it
Validation targets the MoF mandatory field set (51 fields, V1.0 23 Feb 2026; 62 with documented extensions) and the Peppol PINT-AE VAT codelist directly.
TRN and TIN are checked, not just present
Format rules and the cross-consistency check between the Tax Registration Number and the Peppol TIN run on every submission, not just at onboarding.
Rate coherence per category
A standard-rate line can't carry a zero VAT rate, and an exempt line can't skip its exemption reason — the category and the rate are checked together.
vat_categoryenumRequiredOne of S, Z, E, O, AE, N — the official Peppol PINT-AE codes.
vat_ratedecimalRequiredMust match the category's allowed rate set (S/N: 5.00; Z/E/O: 0.00; AE: 0.00 or 5.00).
supplier_trnstring(15)Required15-digit FTA Tax Registration Number, or a standalone 10-digit TIN.
vat_exemption_reasonstringRequired whenever vat_category is E or O.