A global discount doesn't just subtract from the total — it has to touch every VAT bucket
// CONTEXT
Implementing compute_document_totals: a document has per-line discounts already baked into each line's net_ht, then an optional global discount applied on top, across lines that can carry different VAT rates (20%, 10%, 5.5%, 0%)
// WHAT THE OBVIOUS VERSION WOULD DO
Sum the per-line vat_amount values that are already sitting on each line, then just subtract the global discount from the final TTC. Every line already knows its own VAT, so adding them up looks like the total — and it's wrong for a reason that isn't obvious until you look at the taxable base.
// THE CODE THAT DID IT
src/ledgercore/domain/documents/calculation.py:
if global_discount_amount.is_zero or lines_ht.is_zero:
total_vat = _sum_money((lt.vat_amount for lt in line_totals), currency)
else:
keep_ratio = Decimal("1") - (
global_discount_amount.amount / lines_ht.amount
)
total_vat = _sum_money(
(lt.net_ht * keep_ratio * lt.vat_rate.rate for lt in line_totals),
currency,
)// WHAT I FOUND
Each line's pre-computed vat_amount was calculated on that line's own net_ht, before the global discount existed. If I just summed those, the global discount would reduce the invoice's TTC total but leave the VAT total untouched — wrong taxable base. The fix: compute a single keep_ratio (fraction of lines_ht that survives the global discount), apply it to every line's net_ht before multiplying by that line's own vat_rate.rate. This keeps each line's VAT proportional to its own rate while still reflecting the global discount.
// LIMIT
No custom Decimal context anywhere (getcontext/prec don't appear in the codebase), so keep_ratio carries the full default 28-digit precision — not itself a rounding problem. But every test in test_calculation.py uses discounts that produce "clean" ratios (0.9, 1.0, 0); none exercise a discount that produces a repeating decimal (e.g. a 1/3 split across 3 lines). Since each line's VAT is rounded to 2dp independently before being summed, there's no test confirming total_vat never drifts a cent from what a single blended-rate calculation would give — the classic "sum of rounded parts vs. rounded sum" gap is unverified.
// TAKEAWAY
When a discount is applied after per-line tax has already been computed, re-deriving the tax from the discounted base (not just subtracting from the final total) is the only way to keep the tax base legally correct.