Error codes · Peppol BIS 3.0
Only one tax total with tax subtotals must be provided
This is the rejection, word for word: „[PEPPOL-EN16931-R053] PEPPOL-EN16931-R053 fires when an invoice contains more than one cac:TaxTotal element that has cac:TaxSubtotal children. Peppol BIS Billing 3.0 allows multiple TaxTotal blocks only in narrow multi-currency scenarios (one in the document currency with subtotals, one in the tax accounting currency without subtotals). The schematron test `count(cac:TaxTotal[cac:TaxSubtotal]) = 1` enforces this: there must be exactly one TaxTotal carrying the category breakdown.“
The rule is one of the most common structural failures in cross-border Peppol pipelines. Failure modes: (1) Multi-currency invoices emit two TaxTotal elements (document currency + tax accounting currency) but both carry TaxSubtotal children. Only the document-currency one may. (2) Code that loops over VAT rates emits one cac:TaxTotal per rate instead of one TaxTotal with multiple cac:TaxSubtotal children. (3) Merging logic concatenates TaxTotal blocks from two source documents without deduplicating. (4) On CII (UN/CEFACT D16B), the equivalent rule counts `ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TaxTotalAmount[@currencyID=$documentCurrencyCode]` — duplicates of the document-currency total trigger it. (5) Custom XSLT identity transforms that copy cac:TaxTotal from input verbatim, then add a computed one — producing two.
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">190.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">1000.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">190.00</cbc:TaxAmount>
<cac:TaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>19.00</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">35.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">500.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">35.00</cbc:TaxAmount>
<cac:TaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>7.00</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
</Invoice><Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">225.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">1000.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">190.00</cbc:TaxAmount>
<cac:TaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>19.00</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:TaxCategory>
</cac:TaxSubtotal>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">500.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">35.00</cbc:TaxAmount>
<cac:TaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>7.00</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
</Invoice>Element order is part of the rule: if the element sits in the wrong place, the validator rejects with PEPPOL-EN16931-R053.