fix(bookkeeping): reverse-charge VAT in booking templates is 25% of the base, not 20% (#1494)

* fix(bookkeeping): reverse-charge VAT in booking templates is 25% of the base, not 20%

applyTemplate() extracted VAT out of the total (rate/(1+rate)) for every
vat line, including the fiktiv-moms pair of reverse-charge templates.
Under omvand skattskyldighet the supplier charges no VAT, so the total IS
the beskattningsunderlag: on 807.99 kr the seeded EU-purchase template
booked 161.60 kr (20%) on 2614/2645 instead of 202.00 kr (25%),
understating Ruta 30-32 and Ruta 48 on the momsdeklaration.

Fiktiv-moms lines (2614/2624/2634 output, 2615/2625/2635 import,
2645/2647 input) now compute amount x rate on top of the base.
deriveTemplateLinesFromBooking ("Spara som mall") gets the mirror fix:
RC legs no longer inflate the derived total (they net to zero), and RC
rates snap against the base, so a correct RC booking round-trips.

Counterparty/SIE learned patterns already strip RC legs and regenerate
them via generateReverseChargeLines with the gross base; those paths
were correct and are unchanged.

User-reported: "Er automatiska utrakning ar pa 20%, inte 25%".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(bookkeeping): use roundOre for template VAT rounding (guard ratchet)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(bookkeeping): clarify fiktiv-moms comment: total is the base, booked amount is the VAT

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Mattsson
2026-08-10 13:59:55 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent 38f5d9812e
commit 3ff12faa77
6 changed files with 114 additions and 22 deletions
+4 -2
View File
@@ -27,8 +27,10 @@ import { accountNumberSchema } from '@/lib/invariants/zod'
* `applyTemplate()` in `lib/bookkeeping/template-library.ts` turns a total
* amount into lines, and the three types are not decorative:
*
* - `vat`: amount is `total * vat_rate / (1 + vat_rate)`, so it carries
* `vat_rate` and never `ratio`.
* - `vat`: carries `vat_rate` and never `ratio`. Amount is
* `total * vat_rate / (1 + vat_rate)`, except on fiktiv-moms accounts
* (reverse charge/import, e.g. 2614/2645) where the total is the tax base
* and the amount is `total * vat_rate` on top.
* - `business` and `settlement`: amount is `total * ratio`, so they carry
* `ratio` and never `vat_rate`.
*