Dentolize · ZATCA E-Invoice Rounding Fix Walkthrough
On this pageExecutive summaryWhy it mattersImpact and blast radiusRisk assessmentWhat this does not solve (transparency)Status & recommendation

For 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

RiskAssessment
Regression on single‑line invoicesLow — for one line, the old and new formulas are identical.
Per‑line e‑invoice values shiftNone 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 totalRemoved — the reported total now uses the invoice's own aggregation rule (EN16931 BR‑CO‑17).
Runtime doesn't pick up the fixMitigated — 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:

  1. 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.
  2. Root cause is data typing — monetary fields are stored as floating‑point Float rather than fixed‑point Decimal. Moving to Decimal would 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 clean tsc build.
  • 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→Decimal change aren't lost.