Rounding rules
How Alya Books rounds amounts, VAT and totals, in the editor, the API, the XML and the VAT return.
All amounts are in the document currency with two decimals (fils for AED). One rounding function is used everywhere (round2 in _shared/ubl.ts): half away from zero, after snapping the value to six decimals so floating-point noise cannot flip a half. Examples: 1.005 → 1.01, -1.005 → -1.01, 2.675 → 2.68, 0.1 + 0.2 → 0.30.
Order of operations
- Line net amount (BT-131) = quantity × unit price, rounded. Quantities keep three decimals, prices two.
- Line VAT shown on the line = line net × rate ÷ 100, rounded. It is informational; the XML carries no per-line VAT amount.
- Document allowances and charges (BG-20, BG-21) are rounded amounts that join the tax group of their category and rate.
- Tax groups: lines, allowances and charges are grouped by VAT category and rate. Per group, the taxable amount is summed and rounded, then VAT = taxable × rate ÷ 100, rounded (BT-116, BT-117). This is the amount in
cac:TaxSubtotal. - Totals: line extension (BT-106), tax exclusive (BT-109) = lines − allowances + charges, VAT total (BT-110) = sum of group VAT, tax inclusive (BT-112) = tax exclusive + VAT, each rounded.
Because VAT is rounded per group rather than per line, the sum of the line VAT amounts may differ from the group VAT by a fils. The group figure is the reported one; validation (BT-110, BT-112) accepts the recomputed values only.
Where the same rules apply
- The editor (
computeLines,computeDocumentTotals),POST /invoices(computeApiLines), the PDF and the XML share the code, so the three documents always agree. - The VAT 201 worksheet re-derives each invoice's per-category VAT with the same rule in SQL (
round(taxable, 2)thenround(taxable × rate / 100, 2)), so box totals equal the sum of the reported tax subtotals. - Received documents are validated with a tolerance of one fils per total.
- Gross entry (Prices include VAT) stores net = gross ÷ (1 + rate), rounded, and continues with the net rules.
Tests
src/test/vat.test.ts covers the half-up cases, the editor/API parity, the per-group VAT and the worksheet arithmetic; src/test/api-core.test.ts covers the document totals.