Attestwire › Rule reference › BR-CO-14
BR-CO-14 The total VAT is the sum of the VAT breakdown groups
noun · EN 16931 · fatal · BT-110
a VAT total that disagrees with the VAT groups it is made of.
Your invoice was refused because the total VAT it states is not the sum of the VAT shown for each rate. VAT has to be worked out per rate group and rounded there, then added; working it out once on the grand total is the usual cause of a one-cent difference. In the standard the total VAT is field 110, written BT-110, and BR-CO-14 is the rule that adds up the groups.
- Business term
BT-110— Invoice total VAT amount- Severity
fatal- Applies to
All profiles
The fix
Group your lines by category and rate first. For each group: add the net amounts, round to two decimals, multiply by the rate, round again. Then add the group VAT amounts to get the total, and state that as declaredTotals.taxAmount, or leave it out and let the library compute it.
If you are currently doing total × rate anywhere, that is the line to change, even on a single-rate invoice: the day someone adds a reduced-rate line is the day it starts producing cents that nobody can explain.
What the rule requires
The invoice total VAT amount (BT-110) equals the VAT category tax amounts (BT-117) added together, one per VAT breakdown group (BG-23).
A breakdown group is one combination of VAT category and rate. An invoice with 19% lines and 7% lines has two groups. Two lines both at 19% do not make two groups; they share one. The VAT is computed and rounded inside each group, and only then are the groups added together.
That ordering is what the rule enforces. Multiply the document total by a rate and you will be a cent out on a surprising proportion of invoices, because rounding once is not the same as rounding three times and adding.
The rule needs a stated total VAT to compare against: declaredTotals.taxAmount.
Invoice total VAT amount (BT-110) = Σ VAT category tax amount (BT-117).
Failing and passing
validateInput({
// ...
lines: [{ id: "1", description: "Consulting", quantity: 10,
unitCode: "HUR", unitPrice: 150,
vatCategory: "S", vatRate: 19 }],
declaredTotals: { taxAmount: 280.00 }, // <- BR-CO-14
});
// -> { valid: false, errors: [ { rule: "BR-CO-14", field: "BT-110", ... } ] }validateInput({
// ...
lines: [{ id: "1", description: "Consulting", quantity: 10,
unitCode: "HUR", unitPrice: 150,
vatCategory: "S", vatRate: 19 }],
declaredTotals: { taxAmount: 285.00 },
});
// -> { valid: true, errors: [] }Why it exists
A tax authority cares less what VAT you charged in total than what you charged at each rate. That is what goes on the return, and reduced rates and exemptions are where mistakes cost money. Building the total from the groups rather than the other way round means the document’s own breakdown is the source of truth, and the total is its sum.
It also means the buyer can reclaim per rate without recomputing anything.
What the library returns
The full error returned by @attestwire/en16931. It includes the rule ID,
affected field and suggested correction. Developers can use this object in their application:
{
"rule": "BR-CO-14",
"field": "BT-110",
"severity": "fatal",
"message": "BR-CO-14 requires the invoice total VAT amount (BT-110) to equal Σ VAT category tax amounts (BT-117). You declared 1.00 for BT-110, but the invoice lines compute to 285.00 — a difference of -284.00 EUR. VAT is computed per category-and-rate group and rounded there (BR-CO-17), then summed. Computing VAT on the document total instead of per group is the usual cause of a one-cent break.",
"fix": "Either correct the line data so it sums to your declared figure, or drop declaredTotals.taxAmount and let the library compute it. Note that EN 16931 sums *rounded* line amounts: round each line to 2 decimals first, then add — rounding only the final sum drifts by a cent or two on long invoices.",
"example": "\"declaredTotals\": { \"taxAmount\": 285.00 }",
"docsUrl": "https://attestwire.com/rules/BR-CO-14"
}How our check differs
Stated figures only, again. Without declaredTotals.taxAmount there is nothing to compare and the rule reports nothing.
It stands down when the document states its own group VAT amounts. If declaredTotals.subtotals carries a BT-117 per group, the comparison of stated groups against stated total owns this id, which is what a KoSIT report does, and the derived-value check does not emit a second BR-CO-14 with a different delta beside it.
See also: BR-CO-17 — the arithmetic inside a single VAT breakdown group; BR-CO-15 — BT-109 plus BT-110 gives BT-112.