einvoice / EN 16931 / XRechnung rule reference
BR-DEX-09
What this rule means and how to fix it
Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) - Paid amount (BT-113) + Rounding amount (BT-114) + Σ Third party payment amount (BT-DEX-002).
Fälliger Zahlungsbetrag (BT-115) = Gesamtbetrag der Rechnung einschließlich Umsatzsteuer (BT-112) - Bereits gezahlter Betrag (BT-113) + Rundungsbetrag (BT-114) + Σ Betrag der Zahlung durch Dritte (BT-DEX-002).
Deutsche Fassung: Übersetzung der gleichen BT/BG-Semantik (translation — not the official assert).
- Requires
- Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) - Paid amount (BT-113) + Rounding amount (BT-114) + Σ Third party payment amount (BT-DEX-002).
- Business terms
BT-112BT-113BT-114BT-115BT-DEX-002- Syntax
- Binds the UBL-2.1 Invoice / CreditNote syntax
- Location (UBL-2.1 path)
cac:LegalMonetaryTotal- Fix
- Correct the calculated amount at `cac:LegalMonetaryTotal` so that Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) - Paid amount (BT-113) + Rounding amount (BT-114) + Σ Third party payment amount (BT-DEX-002).
- Fix (Deutsch)
- Korrigieren Sie den berechneten Betrag bei `cac:LegalMonetaryTotal`, sodass gilt: Fälliger Zahlungsbetrag (BT-115) = Gesamtbetrag der Rechnung einschließlich Umsatzsteuer (BT-112) - Bereits gezahlter Betrag (BT-113) + Rundungsbetrag (BT-114) + Σ Betrag der Zahlung durch Dritte (BT-DEX-002).
- Severity
- fatal
- Provenance source
xrechnung-ubl- Provenance assert
Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) - Paid amount (BT-113) + Rounding amount (BT-114) + Σ Third party payment amount (BT-DEX-002).
The Location above is a UBL-2.1 path, and no UN/CEFACT-CII path for this rule is published here; Fix and Fix (Deutsch), verbatim from remediation_catalog.json and not reworded here; the UBL-2.1 binding of this rule is differentially proven against the official KoSIT XRechnung 2.5.0 (XRechnung 3.0.2) Schematron.
Where to check the fix: paste the corrected invoice into the browser validator at /einvoice/validate/ — it runs this same engine locally in your browser, with no upload, and stops reporting BR-DEX-09 once the edit lands.
Korrektur prüfen: Laden Sie die geänderte Rechnung in den Browser-Validator unter /einvoice/validate/ — er führt dieselbe Engine lokal im Browser aus, ohne Upload, und meldet BR-DEX-09 nicht mehr, sobald die Korrektur greift.
The same invoice, failing and fixed
No vendored test suite ships a labelled example for this rule, so this pair was found rather than written. The engine was run over the vendored instance corpus/xrechnung-testsuite/src/test/business-cases/extension/04.01a-INVOICE_ubl.xml under --profile xrechnung, then re-run over the same file with one mechanical edit applied to one element, over and over, until the edit below changed the verdict: 1 was added to the value of TaxInclusiveAmount (14918.84 became 14919.84). The page publishes it because the engine reported BR-DEX-09 for the edited document and did not report it for the untouched one.
UBL Invoice (XRechnung extension) — fails
The vendored file around the change, verbatim:
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="EUR">12536.84</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="EUR">12536.84</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="EUR">14919.84</cbc:TaxInclusiveAmount>
<cbc:PrepaidAmount currencyID="EUR">10000.0</cbc:PrepaidAmount>
<cbc:PayableAmount currencyID="EUR">4918.84</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
UBL Invoice (XRechnung extension) — passes
The same lines as 04.01a-INVOICE_ubl.xml actually ships them — this block is the fix for the block above:
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="EUR">12536.84</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="EUR">12536.84</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="EUR">14918.84</cbc:TaxInclusiveAmount>
<cbc:PrepaidAmount currencyID="EUR">10000.0</cbc:PrepaidAmount>
<cbc:PayableAmount currencyID="EUR">4918.84</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
What the engine reports for the edited invoice
{
"element": "cac:LegalMonetaryTotal/cbc:PayableAmount",
"field": "cac:LegalMonetaryTotal/cbc:PayableAmount",
"fix_hint": "Correct the calculated amount at `cac:LegalMonetaryTotal` so that Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) - Paid amount (BT-113) + Rounding amount (BT-114) + Σ Third party payment amount (BT-DEX-002).",
"location": "cac:LegalMonetaryTotal",
"message": "'Amount due for payment' (BT-115) must equal Invoice total with VAT (BT-112) - Paid amount (BT-113) + Rounding amount (BT-114) + Σ Third party payment amount (BT-DEX-002).",
"rule": "BR-DEX-09",
"severity": "fatal",
"terms": [
"BT-112",
"BT-113",
"BT-114",
"BT-115",
"BT-DEX-002"
],
"title": "Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) - Paid amount (BT-113) + Rounding amount (BT-114) + Σ Third party payment amount (BT-DEX-002)."
}
Rule ids the engine reports for 04.01a-INVOICE_ubl.xml untouched: none. After the edit, BR-CO-15 BR-CO-16 BR-DEX-09 are reported that were not before — one mechanical edit can break more than one rule at a time, and BR-CO-15 BR-CO-16 are the neighbours this one takes with it.
Two honest limits. This is an edit that provokes the rule, not the only one, and it is not a claim about how real exporters break it. And it is the reverse of the fix a reader needs: the passing block is the vendored file's own content, which is what a conformant invoice looks like here.
Reproduce it yourself: take corpus/xrechnung-testsuite/src/test/business-cases/extension/04.01a-INVOICE_ubl.xml from this repository, apply the one edit named above, and run einvoice validate 04.01a-INVOICE_ubl.xml --profile xrechnung --format json, or paste the file into the browser validator, which runs this same engine locally with no upload.
Everything here is free and open source — pick up whatever helps, at your own pace:
- Licensing — free and open source under Apache-2.0 for everyone, including closed-source embedding: use, modify and ship it inside a commercial product with no fee and no license key.
- German remediation (
--lang de) — the German fix for this rule is in the section above; the CLI surfaces it in place of the English message with--lang de. - Quickstart / free on-ramp — the README, a copy-paste CI-gate recipe, and a 5-minute worked walkthrough.