# BR-CO-12: Fix a document charge total that does not match its charges

The charge total in the monetary totals must equal the sum of the document-level charge amounts, rounded to two decimals.

- Layer: EN 16931
- Severity: fatal (the document is invalid)
- Topics: Totals, Allowances and charges
- Official definition: https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-tc434/BR-CO-12/
- Explanation last updated: 2026-09-20

## The short answer

`BR-CO-12` fails when `cac:LegalMonetaryTotal/cbc:ChargeTotalAmount` disagrees with the document-level charges. Sum `cbc:Amount` over the `cac:AllowanceCharge` elements that sit directly under the document root with `cbc:ChargeIndicator` of `true`, round to two decimals, and send that as the charge total.

Charges attached to a line stay out of this figure; they are part of the line net amount.

## What the rule checks

Only `cac:AllowanceCharge` children of the `Invoice` or `CreditNote` root with `cbc:ChargeIndicator` of `true` are summed. Document-level allowances, and any `cac:AllowanceCharge` inside a line or a price, are left out.

The summed charges are rounded to two decimals and must equal the total exactly. A total of 3.51 against a single charge of 3.50 fails.

Leaving `cbc:ChargeTotalAmount` out is accepted only when the document has no document-level charges. A charge without a total fails. Without any charges, a total of 0.00 passes and any other value fails.

| Term | Meaning | UBL element |
|---|---|---|
| BT-108 | Sum of charges on document level | `cac:LegalMonetaryTotal/cbc:ChargeTotalAmount` |
| BT-99 | Document level charge amount | `cac:AllowanceCharge[cbc:ChargeIndicator = true]/cbc:Amount` |

## How an integration ends up here

Possible causes, from the shape of the rule rather than from measured usage:

- Freight, handling or similar fees are stored as a header figure in the source system, and the `cac:AllowanceCharge` elements are generated from a different place that does not agree with it.
- A line-level charge is counted in the document charge total as well as in its line net amount.
- The `cbc:ChargeIndicator` is wrong on one element, so a charge is summed with the allowances or an allowance with the charges.
- The charge elements are written but the total is skipped because the mapping treats it as optional.
- A percentage charge is recalculated for the total instead of reusing the rounded `cbc:Amount` that was written.

## How to fix it

1. Collect the `cac:AllowanceCharge` elements directly under the document root whose `cbc:ChargeIndicator` is `true`.
2. Add their `cbc:Amount` values, as written in the XML, with decimal arithmetic and round to two decimals.
3. Write the result to `cac:LegalMonetaryTotal/cbc:ChargeTotalAmount`. With no document-level charges, omit the element or send 0.00.
4. Rebuild the total without VAT from the corrected charge total, since `BR-CO-13` reads it.

The recorded example has one document-level charge, 10 percent of a 35.00 base.

```text
Document-level charges: 3.50
Charge total sent (BT-108): 4.50, so BR-CO-12 fails
Total without VAT sent: 68.50, which is 66.00 - 1.00 + 3.50
Against the 4.50 that was sent, BR-CO-13 expects 66.00 - 1.00 + 4.50 = 69.50, so it fails too
```

## Before and after

These are fragments, not complete documents. The complete synthetic documents they come from are linked below.

Fragment of the failing invoice: the total says 4.50, the only document-level charge is 3.50

```xml
<cac:AllowanceCharge>
  <cbc:ChargeIndicator>true</cbc:ChargeIndicator>
  <cbc:AllowanceChargeReasonCode>CG</cbc:AllowanceChargeReasonCode>
  <cbc:AllowanceChargeReason>Example document charge</cbc:AllowanceChargeReason>
  <cbc:MultiplierFactorNumeric>10</cbc:MultiplierFactorNumeric>
  <cbc:Amount currencyID="GBP">3.50</cbc:Amount>
  <cbc:BaseAmount currencyID="GBP">35.00</cbc:BaseAmount>
  <!-- tax category omitted from this fragment -->
</cac:AllowanceCharge>

<cac:LegalMonetaryTotal>
  <cbc:LineExtensionAmount currencyID="GBP">66.00</cbc:LineExtensionAmount>
  <cbc:TaxExclusiveAmount currencyID="GBP">68.50</cbc:TaxExclusiveAmount>
  <!-- total with VAT omitted from this fragment -->
  <cbc:AllowanceTotalAmount currencyID="GBP">1.00</cbc:AllowanceTotalAmount>
  <cbc:ChargeTotalAmount currencyID="GBP">4.50</cbc:ChargeTotalAmount>
  <!-- prepaid, rounding and payable amounts omitted from this fragment -->
</cac:LegalMonetaryTotal>
```

Fragment of the corrected invoice: the total equals the one charge

```xml
<cac:LegalMonetaryTotal>
  <cbc:LineExtensionAmount currencyID="GBP">66.00</cbc:LineExtensionAmount>
  <cbc:TaxExclusiveAmount currencyID="GBP">68.50</cbc:TaxExclusiveAmount>
  <!-- total with VAT omitted from this fragment -->
  <cbc:AllowanceTotalAmount currencyID="GBP">1.00</cbc:AllowanceTotalAmount>
  <cbc:ChargeTotalAmount currencyID="GBP">3.50</cbc:ChargeTotalAmount>
  <!-- prepaid, rounding and payable amounts omitted from this fragment -->
</cac:LegalMonetaryTotal>
```

Only `cbc:ChargeTotalAmount` differs: 4.50 in the failing document, 3.50 in the corrected one. The failing document also reports `BR-CO-13`, because its total without VAT of 68.50 was worked out with a charge total of 3.50 and does not fit the 4.50 that was sent. Putting the charge total right clears both findings.

### What the validator reported

- The failing invoice reports **BR-CO-12** and [BR-CO-13](https://ironfang.uk/docs/finance/rules/BR-CO-13.md). The corrected document passes every layer with no findings.
  - [Download the failing XML](https://ironfang.uk/finance/rule-examples/BR-CO-12-invalid.xml)
  - [Download the corrected XML](https://ironfang.uk/finance/rule-examples/invoice-rich.xml)

Recorded on phive 12.1.0 / phive-rules-peppol 4.5.6 / Saxon-HE 12.10, the engine behind the free validator, using synthetic data. A recorded result is regression evidence for these documents; it is not a certification.

## Where it applies

- Applies to UBL `Invoice` and `CreditNote` in the same way; a credit note with the same mistake reports the same two findings.
- Leaving the total out while a charge is present also reports `BR-CO-13`, which then treats the missing charge total as nothing added.
- This rule only sums. The reason, VAT category, base amount and percentage of each charge are checked elsewhere.

## Related rules

- [BR-CO-11 is the matching check for document-level allowances](https://ironfang.uk/docs/finance/rules/BR-CO-11.md)
- [BR-CO-13 adds the charge total when it checks the total without VAT](https://ironfang.uk/docs/finance/rules/BR-CO-13.md)
- [PEPPOL-EN16931-R040 checks a charge amount against its base amount and percentage](https://ironfang.uk/docs/finance/rules/PEPPOL-EN16931-R040.md)
- [PEPPOL-EN16931-R041 requires a base amount whenever a charge carries a percentage](https://ironfang.uk/docs/finance/rules/PEPPOL-EN16931-R041.md)

## Scope and source

Written for Peppol BIS Billing 3.0.21 (May 2026), EN 16931 1.3.16, as applied to UBL 2.1 Invoice and CreditNote documents. Other profiles, syntaxes and releases can define this identifier differently. Guidance version 2026-09-24.1: source checked 2026-09-24, explanation last updated 2026-09-20.

[The official definition of BR-CO-12](https://docs.peppol.eu/poacc/billing/3.0/rules/ubl-tc434/BR-CO-12/) carries the normative wording and test. This page is our explanation of it, not a copy.

Guidance does not change the engine verdict. Fixing this finding does not mean the document passes every layer, and validation does not certify legal or tax compliance or transmit a document over Peppol.

## Links

- [This rule as a web page](https://ironfang.uk/docs/finance/rules/BR-CO-12)
- [Free Peppol invoice validator](https://ironfang.uk/tools/peppol-validator)
- [Rule index](https://ironfang.uk/docs/finance/rules.md)
- [Ironfang Finance API docs](https://ironfang.uk/docs/finance)
- The same rule is available to MCP clients as the tool `finance.rule.get` on https://mcp.ironfang.uk/mcp
