# Rounding rules

> How Alya Books rounds amounts, VAT and totals, in the editor, the API, the XML and the VAT return.

Source: /docs/reference/rounding

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

1. **Line net amount** (BT-131) = quantity × unit price, rounded. Quantities keep three decimals, prices two.
2. **Line VAT** shown on the line = line net × rate ÷ 100, rounded. It is informational; the XML carries no per-line VAT amount.
3. **Document allowances and charges** (BG-20, BG-21) are rounded amounts that join the tax group of their category and rate.
4. **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`.
5. **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)` then `round(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.
