On this page
Executive summaryWhy it mattersImpact and blast radiusRisk assessmentWhat this does not solve (transparency)Status & recommendationFor Stakeholders
Executive summary
A rounding defect could make the total Dentolize reports to Saudi Arabia's ZATCA e‑invoicing platform differ by one cent from the invoice total the patient paid, on multi‑line invoices. This PR corrects the calculation so the reported total is derived the same way as the invoice total — they now match by construction. Small change, disproportionate importance: it sits on a compliance‑critical path.
Why it matters
- Compliance integrity. ZATCA (Fatoora) is mandatory for Saudi clinics. A systematic discrepancy between the receipt and the reported total is the kind of control weakness an auditor notices.
- Financial reconciliation. Month‑end reconciliation between clinic books and reported e‑invoices should tie out to zero. A per‑invoice cent creates recurring manual clean‑up and accumulates at scale.
- Customer trust. In a market where compliance is a purchase driver, "the numbers always agree" is a credibility asset.
Impact and blast radius
- Surface area: one function of real logic —
packages/zatca/src/zatca/calc.ts— plus its committed compiled output. Diff is ~33 added / ~16 removed lines in the source. - Who's affected: Saudi clinics reporting to ZATCA, on multi‑line invoices. Single‑line invoices were already correct.
- Both invoice types covered: simplified (B2C/patient) and standard (B2B/insurance).
- No migration, no schema change, no UI change, no re‑issuing of past invoices.
Risk assessment
| Risk | Assessment |
|---|---|
| Regression on single‑line invoices | Low — for one line, the old and new formulas are identical. |
| Per‑line e‑invoice values shift | None by design — only the document‑level aggregation changed; per‑line amounts are untouched and within ZATCA's line‑vs‑category tolerance. |
| Total drifts from the invoice total | Removed — the reported total now uses the invoice's own aggregation rule (EN16931 BR‑CO‑17). |
| Runtime doesn't pick up the fix | Mitigated — the PR rebuilds and commits lib/ (the server imports the built entry point). |
What this does not solve (transparency)
Leadership should know the scope is deliberately bounded:
- A smaller residual contributor remains — a per‑unit discount rounding in the invoice calculator can still nudge a line's taxable base by a cent in specific cases. Flagged as a follow‑up.
- Root cause is data typing — monetary fields are stored as floating‑point
Floatrather than fixed‑pointDecimal. Moving toDecimalwould eliminate sub‑cent artifacts at the source, but is a larger, separate effort.
This PR fixes the dominant cause now; the follow‑ups are understood and documented, not overlooked.
Status & recommendation
- Status: unreleased, on
fix/rounding-money-in-zatca-invoice(PR #360). Verified via a standalone reproduction and a cleantscbuild. - Recommendation: low‑risk, high‑value compliance fix. Suitable to ship after the standard review, with QA focused on multi‑rate and multi‑line e‑invoice cases (see For Quality). Track the two follow‑ups so the residual cent and the
Float→Decimalchange aren't lost.