XRechnung · CII · rule diff

XRechnung 2.1.0: CII validation rule changes

40 rules changed between 2.0.2 and 2.1.0 — added, removed, or rewritten. This is computed from the two rule sets directly, not from a changelog.

About this comparison

Revalidate compares the archived 2.0.2 and 2.1.0 rule sets at the assertion and variable level. The diff identifies changed rules; replaying your invoices shows which changes affect your documents.

Browse archived rule sets and checksums. Report published by Revalidate on .

What changed

BR-42Test expression rewritten

Test path changed from child to parent-relative

The test expression changed from "(ram:Reason) or (ram:ReasonCode)" to "(../ram:Reason) or (../ram:ReasonCode)". The inserted parent step "../" means the two referenced elements are now looked for one level up from the current context. The rule message remains the same. No other change is shown.

fatalbusiness

Original rule text: [BR-42]-Each Invoice line allowance (BG-27) shall have an Invoice line allowance reason (BT-139) or an Invoice line allowance reason code (BT-140).

Explanation and fix

What this rule requires

The rule requires that every invoice line allowance (BG-27), represented in UBL as cac:AllowanceCharge with cbc:ChargeIndicator false, and in CII as ram:SpecifiedTradeAllowanceCharge with ram:ChargeIndicator false, carries at least one of cbc:AllowanceChargeReason (BT-139) or cbc:AllowanceChargeReasonCode (BT-140) in UBL, or ram:Reason or ram:ReasonCode in CII. A document fails validation if the allowance charge has neither a reason text nor a reason code.

How to fix

Add either the allowance reason text or the allowance reason code to the line allowance. In UBL, inside the cac:AllowanceCharge with cbc:ChargeIndicator false, add cbc:AllowanceChargeReason with the reason text, or cbc:AllowanceChargeReasonCode with a code. In CII, inside ram:SpecifiedTradeAllowanceCharge with ram:ChargeIndicator false, add ram:Reason or ram:ReasonCode. If using a reason code, ensure it is one the rule accepts; the rule does not list the allowed codes here.

Guidance on this rule. The original text above is authoritative.

BR-42 rule details

Before · 2.0.2

(ram:Reason) or (ram:ReasonCode)

After · 2.1.0

(../ram:Reason) or (../ram:ReasonCode)
BR-37Test expression rewritten

The rule now reads the "VAT" category code from the parent element

The test expression changed where it looks for the document-level charge VAT category code. Previously it selected the category trade tax element directly under the current element; now it moves to the parent element and selects the category trade tax element there. The condition that the type code, uppercased, equals "VAT" and the requirement that a category code be present remain unchanged. The rule message is unchanged.

fatalbusiness

Original rule text: [BR-37]-Each Document level charge (BG-21) shall have a Document level charge VAT category code (BT-102).

Explanation and fix

What this rule requires

Rule BR-37 requires each document level charge (BG-21) to have a Document level charge VAT category code (BT-102). In UBL, an AllowanceCharge with ChargeIndicator equal to true must contain a cac:TaxCategory whose cac:TaxScheme/cbc:ID is VAT (case-insensitive, surrounding whitespace ignored) and that TaxCategory has a cbc:ID element. In CII, a SpecifiedTradeAllowanceCharge with ChargeIndicator true must have a sibling ram:CategoryTradeTax with ram:TypeCode equal to VAT (case-insensitive) and that contains a ram:CategoryCode element. The test checks presence of these elements; it does not check their values. Because the severity is fatal, a document missing them fails validation.

How to fix

For UBL, ensure the AllowanceCharge (where ChargeIndicator is true) contains a cac:TaxCategory with cac:TaxScheme/cbc:ID equal to VAT and a cbc:ID element. For CII, ensure the SpecifiedTradeAllowanceCharge has a ram:CategoryTradeTax with ram:TypeCode equal to VAT and a ram:CategoryCode element. The rule does not specify allowed category code values; use a value accepted by the applicable tax category code list.

Guidance on this rule. The original text above is authoritative.

BR-37 rule details

Before · 2.0.2

(ram:CategoryTradeTax[upper-case(ram:TypeCode) = 'VAT']/ram:CategoryCode)

After · 2.1.0

(../ram:CategoryTradeTax[upper-case(ram:TypeCode) = 'VAT']/ram:CategoryCode)
BR-CL-16Test expression rewritten

Payment means code "98" joins the allowed UNTDID 4461 codes

The rule's condition defines allowed payment means codes by checking that the text value appears inside a space-padded list. The previous list ended with "97 ZZZ"; the new list adds "98" after "97", before "ZZZ". As a result, the code "98" is now accepted where it was previously not in the allowed set. The condition otherwise remains the same.

fatalbusiness

Original rule text: [BR-CL-16]-Payment means in an invoice MUST be coded using UNTDID 4461 code list

Explanation and fix

What this rule requires

The element ram:SpecifiedTradeSettlementPaymentMeans/ram:TypeCode must contain a payment means code from the UNTDID 4461 code list. The rule accepts only the specific codes listed in its test: 1 through 70, 74 through 78, 91 through 98, and ZZZ. The value must not contain any spaces after trimming surrounding whitespace. For example, '30' or 'ZZZ' are valid, while '4 2', 'ABC', or '71' would fail.

How to fix

Set ram:SpecifiedTradeSettlementPaymentMeans/ram:TypeCode to exactly one of the allowed UNTDID 4461 codes, such as 1, 2, 30, 58, or ZZZ, with no internal spaces. If the current value is not in the allowed list, replace it with the correct payment means code for the invoice. If you are unsure which code to use, check the payment method and map it to the UNTDID 4461 list used by this rule.

Guidance on this rule. The original text above is authoritative.

BR-CL-16 rule details

Before · 2.0.2

((not(contains(normalize-space(.), ' ')) and contains(' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 74 75 76 77 78 91 92 93 94 95 96 97 ZZZ ', concat(' ', normalize-space(.), ' '))))

After · 2.1.0

((not(contains(normalize-space(.), ' ')) and contains(' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 74 75 76 77 78 91 92 93 94 95 96 97 98 ZZZ ', concat(' ', normalize-space(.), ' '))))
PEPPOL-EN16931-R046Test expression rewritten

Allowance amount conversion now uses "u:decimalOrZero" instead of "xs:decimal"

The rule's test expression changed only in the function applied to the allowance amount. Previously the allowance amount was converted with "xs:decimal"; now it is converted with "u:decimalOrZero". The element being read is unchanged, and the equality condition comparing net price to gross price minus allowance remains in place. Nothing else in the expression was altered.

warningformat

Original rule text: Item net price MUST equal (Gross price - Allowance amount) when gross price is provided.

PEPPOL-EN16931-R046 rule details

Before · 2.0.2

not(ram:ChargeAmount) or xs:decimal(../ram:NetPriceProductTradePrice/ram:ChargeAmount) = xs:decimal(ram:ChargeAmount) - xs:decimal(ram:AppliedTradeAllowanceCharge/ram:ActualAmount)

After · 2.1.0

not(ram:ChargeAmount) or xs:decimal(../ram:NetPriceProductTradePrice/ram:ChargeAmount) = xs:decimal(ram:ChargeAmount) - u:decimalOrZero(ram:AppliedTradeAllowanceCharge/ram:ActualAmount)
BR-DEC-25Test expression rewritten

The rule now checks ../ram:BasisAmount instead of ram:BasisAmount.

Why this matters

The test expression changed from string-length(substring-after(ram:BasisAmount,'.'))<=2 to string-length(substring-after(../ram:BasisAmount,'.'))<=2. The only difference is the node selected, which is now ../ram:BasisAmount rather than ram:BasisAmount. The comparison to 2 and the substring-after function are unchanged.

fatalcountry

Original rule text: [BR-DEC-25]-The allowed maximum number of decimals for the Invoice line allowance base amount (BT-137) is 2.

Explanation and fix

What this rule requires

BR-DEC-25 requires the invoice line allowance base amount (BT-137) to be expressed with no more than two decimal places. For UBL it checks cbc:BaseAmount on the line-level allowance charge; for CII it checks ram:BasisAmount under the corresponding specified trade allowance charge. A document fails if the value contains more than two digits after the decimal point, such as 10.345, because the portion after the . has length 3.

How to fix

Ensure the cbc:BaseAmount or ram:BasisAmount value for the line-level allowance charge has at most two digits after the decimal point. For example, change 10.345 to 10.34 or 10.35. The value may also be a whole number or have one decimal place. If the document is generated by software, format the allowance base amount field to output no more than two decimal places.

Guidance on this rule. The original text above is authoritative.

BR-DEC-25 rule details

Before · 2.0.2

string-length(substring-after(ram:BasisAmount,'.'))<=2

After · 2.1.0

string-length(substring-after(../ram:BasisAmount,'.'))<=2
BR-33Test expression rewritten

The rule now tests the parent element for the reason or reason code.

The test expression changed from checking the current element's child elements to checking the parent element for the reason or reason code. The previous form was "(ram:Reason) or (ram:ReasonCode)", and it is now "(../ram:Reason) or (../ram:ReasonCode)". This is a change in the relative location of the required reason or reason code; the logical structure and the rule message remain the same.

fatalbusiness

Original rule text: [BR-33]-Each Document level allowance (BG-20) shall have a Document level allowance reason (BT-97) or a Document level allowance reason code (BT-98).

Explanation and fix

What this rule requires

Each Document level allowance (BG-20) must have at least one of a Document level allowance reason (BT-97) or a Document level allowance reason code (BT-98). In UBL, this means that within every cac:AllowanceCharge where cbc:ChargeIndicator is false, either cbc:AllowanceChargeReason or cbc:AllowanceChargeReasonCode must exist. In CII, within the ram:SpecifiedTradeAllowanceCharge whose ram:ChargeIndicator has udt:Indicator set to false, either ram:Reason or ram:ReasonCode must exist. This is a fatal rule, so a document that does not satisfy it fails validation.

How to fix

Ensure each document-level allowance contains at least one reason element. In UBL, add cbc:AllowanceChargeReason or cbc:AllowanceChargeReasonCode inside the relevant cac:AllowanceCharge. In CII, add ram:Reason or ram:ReasonCode inside the relevant ram:SpecifiedTradeAllowanceCharge. The rule only checks for the presence of one of these elements; it does not specify allowed code values, so if using a reason code, check the applicable code list.

Guidance on this rule. The original text above is authoritative.

BR-33 rule details

Before · 2.0.2

(ram:Reason) or (ram:ReasonCode)

After · 2.1.0

(../ram:Reason) or (../ram:ReasonCode)
BR-63Test expression rewritten

The first buyer electronic address is now the one checked for a scheme identifier

The test for the buyer electronic address requires a scheme identifier. The first part of the condition now limits the scheme identifier check to the first buyer electronic address occurrence, adding "[1]" where that occurrence is selected. Previously this part took the scheme identifier from the buyer electronic address without that restriction. The second part, which passes the rule when there is no buyer electronic address, is unchanged.

fatalbusiness

Original rule text: [BR-63]-The Buyer electronic address (BT-49) shall have a Scheme identifier.

Explanation and fix

What this rule requires

In UBL, the buyer electronic address element cac:AccountingCustomerParty/cac:Party/cbc:EndpointID must have a schemeID attribute present; the test only checks that the attribute exists, not that it is non-empty. In CII, if ram:URIUniversalCommunication is present, the first ram:URIID/@schemeID must be non-empty; if ram:URIUniversalCommunication is absent, the rule is satisfied.

How to fix

In UBL, add a schemeID attribute to cbc:EndpointID in the buyer party. In CII, if ram:URIUniversalCommunication is used, ensure the first ram:URIID has a @schemeID attribute with a non-empty value; if no ram:URIUniversalCommunication is present, no change is needed.

Guidance on this rule. The original text above is authoritative.

BR-63 rule details

Before · 2.0.2

normalize-space(rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:URIUniversalCommunication/ram:URIID/@schemeID) != '' or not (rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:URIUniversalCommunication)

After · 2.1.0

normalize-space(rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:URIUniversalCommunication[1]/ram:URIID/@schemeID) != '' or not (rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:URIUniversalCommunication)
PEPPOL-EN16931-R040Test expression rewritten

The rule replaces fixed tolerance "0.02" with variable "$slackValue".

Why this matters

The test expression changed between published 2.0.2 and published 2.1.0. The condition and the expected amount calculation are unchanged: the check still applies only when both a calculation percentage and a basis amount are present, and the expected amount is still the basis amount multiplied by the calculation percentage and divided by 100, compared with the actual amount if present and otherwise "0". The only difference is the tolerance supplied to the slack comparison, which was the literal "0.02" and is now the variable "$slackValue". No value is given for "$slackValue", so the evidence does not show whether the tolerance widened or narrowed.

warningformat

Original rule text:

PEPPOL-EN16931-R040 rule details

Before · 2.0.2

not(ram:CalculationPercent and ram:BasisAmount) or u:slack(if (ram:ActualAmount) then ram:ActualAmount else 0, (xs:decimal(ram:BasisAmount) * xs:decimal(ram:CalculationPercent)) div 100, 0.02)

After · 2.1.0

not(ram:CalculationPercent and ram:BasisAmount) or u:slack(if (ram:ActualAmount) then ram:ActualAmount else 0, (xs:decimal(ram:BasisAmount) * xs:decimal(ram:CalculationPercent)) div 100, $slackValue)
BR-32Test expression rewritten

The test now navigates from the parent context

The rule's test expression now begins with a parent navigation step, "../", before selecting the trade tax element whose type code upper-cased equals "VAT" and then its category code. Previously the selection started from the current context. The rule's own message and the condition on the type code are unchanged.

fatalbusiness

Original rule text: [BR-32]-Each Document level allowance (BG-20) shall have a Document level allowance VAT category code (BT-95).

Explanation and fix

What this rule requires

The rule is fatal and requires that each document-level allowance (BG-20) have a document-level allowance VAT category code (BT-95). In UBL, the allowance charge element cac:AllowanceCharge with cbc:ChargeIndicator = false() must contain at least one cac:TaxCategory whose cac:TaxScheme/cbc:ID is VAT and which has a cbc:ID. In CII, the allowance charge ram:SpecifiedTradeAllowanceCharge with ram:ChargeIndicator = 'false' must contain at least one ram:CategoryTradeTax with ram:TypeCode = 'VAT' and a ram:CategoryCode. For UBL, the comparison of the tax scheme ID is case-insensitive and ignores surrounding whitespace.

How to fix

In UBL, for the allowance charge with cbc:ChargeIndicator = false(), add a cac:TaxCategory that has a cac:TaxScheme with cbc:ID equal to VAT and a cbc:ID containing the VAT category code. In CII, for the allowance charge with ram:ChargeIndicator equal to 'false', add a ram:CategoryTradeTax with ram:TypeCode equal to VAT and a ram:CategoryCode containing the VAT category code. The rule does not specify which codes are allowed, so use the correct code according to the invoice context.

Guidance on this rule. The original text above is authoritative.

BR-32 rule details

Before · 2.0.2

(ram:CategoryTradeTax[upper-case(ram:TypeCode) = 'VAT']/ram:CategoryCode)

After · 2.1.0

(../ram:CategoryTradeTax[upper-case(ram:TypeCode) = 'VAT']/ram:CategoryCode)
BR-DEC-27Test expression rewritten

The decimal check now selects the charge amount from the parent element.

In version 2.0.2 the test located "ram:ActualAmount" from the current element and checked that digits after the decimal point were at most 2. In version 2.1.0 the path is "../ram:ActualAmount", so the test selects the charge amount on the parent element. Apart from that path step, the condition "string-length(substring-after(...,'.'))<=2" remains the same. The rule message still says the maximum decimals for the invoice line charge amount is 2.

fatalcountry

Original rule text: [BR-DEC-27]-The allowed maximum number of decimals for the Invoice line charge amount (BT-141) is 2.

Explanation and fix

What this rule requires

The rule requires that the Invoice line charge amount (BT-141), as given in cbc:Amount for UBL or ram:ActualAmount for CII, has at most two decimal places. The test counts the characters after the decimal point; if there are more than two, the document fails validation.

How to fix

Set the amount in cbc:Amount (UBL) or ram:ActualAmount (CII) to a value with no more than two digits after the decimal point, e.g. 10.50 or 10.5. If the original amount has more decimals, round or truncate it to two decimals before sending.

Guidance on this rule. The original text above is authoritative.

BR-DEC-27 rule details

Before · 2.0.2

string-length(substring-after(ram:ActualAmount,'.'))<=2

After · 2.1.0

string-length(substring-after(../ram:ActualAmount,'.'))<=2
BR-AE-04Test expression rewritten

Seller tax registration scheme list gains "FC" alongside "VA"

The test expression for the seller's own trade party changed from a single scheme identifier value to a list of two values. The list contains "VA" and "FC" where previously only "VA" appeared. The seller tax representative branch still contains only "VA". The buyer-side condition is unchanged.

fatalbusiness

Original rule text: [BR-AE-04]-An Invoice that contains a Document level charge (BG-21) where the Document level charge VAT category code (BT-102) is "Reverse charge" shall contain the Seller VAT Identifier (BT-31), the Seller tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63) and the Buyer VAT identifier (BT-48) and/or the Buyer legal registration identifier (BT-47).

Explanation and fix

What this rule requires

For a document containing a document-level charge with VAT category code AE (Reverse charge), this fatal rule requires both a seller identifier and a buyer identifier. In UBL, the charge is a cac:AllowanceCharge with ChargeIndicator true and TaxCategory/ID AE under VAT; seller must have cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID or cac:TaxRepresentativeParty/cac:PartyTaxScheme/cbc:CompanyID with VAT, and buyer must have cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID with VAT or cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cbc:CompanyID. In CII, the charge is ram:SpecifiedTradeAllowanceCharge with ChargeIndicator true and CategoryTradeTax with CategoryCode AE and TypeCode VAT; seller must have ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID with schemeID VA or FC, or ram:SellerTaxRepresentativeTradeParty/ram:SpecifiedTaxRegistration/ram:ID with schemeID VA, and buyer must have ram:BuyerTradeParty/ram:SpecifiedTaxRegistration/ram:ID with schemeID VA or ram:BuyerTradeParty/ram:SpecifiedLegalOrganization/ram:ID. If no such charge exists, the rule passes.

How to fix

If the document contains such a charge, ensure at least one of the required seller identifiers is present (as listed above) and at least one buyer identifier. If the charge is not actually reverse charge, change its VAT category code from AE to the correct value.

Guidance on this rule. The original text above is authoritative.

BR-AE-04 rule details

Before · 2.0.2

(//ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA'] or //ram:SellerTaxRepresentativeTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA']) and (//ram:BuyerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA'] or //ram:BuyerTradeParty/ram:SpecifiedLegalOrganization/ram:ID)

After · 2.1.0

(//ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = ('VA', 'FC')] or //ram:SellerTaxRepresentativeTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA']) and (//ram:BuyerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA'] or //ram:BuyerTradeParty/ram:SpecifiedLegalOrganization/ram:ID)
BR-DEC-01Test expression rewritten

Decimal rule now checks actual amount from parent context

Why this matters

The rule's test expression changed from "string-length(substring-after(ram:ActualAmount,'.'))<=2" to "string-length(substring-after(../ram:ActualAmount,'.'))<=2". The new expression adds a parent step before the actual amount element reference, so the decimal count check is evaluated against the actual amount from the parent context rather than the current context. The rule message and the maximum of two decimals are unchanged.

fatalcountry

Original rule text: [BR-DEC-01]-The allowed maximum number of decimals for the Document level allowance amount (BT-92) is 2.

Explanation and fix

What this rule requires

The rule checks that the document level allowance amount (BT-92, German: "Dokumentenebene Nachlassbetrag") has no more than two decimal places. In UBL this is cbc:Amount inside an cac:AllowanceCharge where cbc:ChargeIndicator is false; in CII it is the ram:ActualAmount belonging to the specified trade allowance charge whose ChargeIndicator is false. The test counts the characters after the decimal point and fails if that number is greater than 2. Because the severity is fatal, the document is rejected if the amount has more than two decimal places.

How to fix

Change the document level allowance amount to a value with at most two decimal places (e.g. round to two decimal places before output). In UBL set /ubl:Invoice/cac:AllowanceCharge[cbc:ChargeIndicator=false()]/cbc:Amount (or the CreditNote equivalent) to a numeric value with no more than two digits after the decimal point. In CII set the corresponding ram:ActualAmount in the specified trade allowance charge to a value with no more than two decimal places.

Guidance on this rule. The original text above is authoritative.

BR-DEC-01 rule details

Before · 2.0.2

string-length(substring-after(ram:ActualAmount,'.'))<=2

After · 2.1.0

string-length(substring-after(../ram:ActualAmount,'.'))<=2
BR-CO-21Test expression rewritten

Allowance rule now checks parent context for reason or reason code

The test expression changed from "(ram:Reason) or (ram:ReasonCode)" to "(../ram:Reason) or (../ram:ReasonCode)". Both alternatives still require either the Document level allowance reason (BT-97) or the Document level allowance reason code (BT-98), but they are now evaluated one level up in the parent context. The structure of the condition is otherwise unchanged.

fatalbusiness

Original rule text: [BR-CO-21]-Each Document level allowance (BG-20) shall contain a Document level allowance reason (BT-97) or a Document level allowance reason code (BT-98), or both.

Explanation and fix

What this rule requires

The rule requires that every document-level allowance (BG-20), represented in UBL as cac:AllowanceCharge where cbc:ChargeIndicator is false, contains at least one of cbc:AllowanceChargeReason (BT-97) or cbc:AllowanceChargeReasonCode (BT-98). The test passes if either element exists, so a document fails when both are missing from such an allowance. This is a fatal rule, so the invoice is rejected if it does not satisfy this condition.

How to fix

For each document-level allowance (cac:AllowanceCharge with cbc:ChargeIndicator false in UBL, or ram:SpecifiedTradeAllowanceCharge with ram:ChargeIndicator false in CII), add either a cbc:AllowanceChargeReason (BT-97) or a cbc:AllowanceChargeReasonCode (BT-98), or both. Ensure the added element is not empty and contains a value accepted by the relevant format or code list.

Guidance on this rule. The original text above is authoritative.

BR-CO-21 rule details

Before · 2.0.2

(ram:Reason) or (ram:ReasonCode)

After · 2.1.0

(../ram:Reason) or (../ram:ReasonCode)
BR-CL-22Test expression rewritten

Allowed scheme list gains "VATEX-FR-FRANCHISE" and "VATEX-FR-CNWVAT"

The rule's validation test for the tax exemption reason code identifier scheme changed by widening the list of permitted scheme identifiers. Before the change, every listed value was prefixed "VATEX-EU-"; the updated expression appends "VATEX-FR-FRANCHISE" and "VATEX-FR-CNWVAT" after "VATEX-EU-J" in that space-delimited allowed list. The test still rejects values containing a space and compares the upper-cased trimmed value against the list. No other condition changed.

fatalbusiness

Original rule text: [BR-CL-22]-Tax exemption reason code identifier scheme identifier MUST belong to the CEF VATEX code list

Explanation and fix

What this rule requires

The rule requires the cbc:TaxExemptionReasonCode element (in CII: ram:ExemptionReasonCode) to contain a value that appears in the CEF VATEX code list. The test first checks that the normalized value contains no space, then checks that the uppercase form of the value is present in the list provided by the rule. A document fails if the value contains a space or is not in that list.

How to fix

Set the cbc:TaxExemptionReasonCode (or ram:ExemptionReasonCode) value to one of the codes listed in the rule's CEF VATEX code list, for example VATEX-EU-79-C or VATEX-FR-FRANCHISE. Ensure the value has no spaces; case is ignored by the test, but using the exact uppercase form is safest. If the current value is not in the list, replace it with the correct VAT exemption reason code.

Guidance on this rule. The original text above is authoritative.

BR-CL-22 rule details

Before · 2.0.2

((not(contains(normalize-space(.), ' ')) and contains(' VATEX-EU-79-C VATEX-EU-132 VATEX-EU-132-1A VATEX-EU-132-1B VATEX-EU-132-1C VATEX-EU-132-1D VATEX-EU-132-1E VATEX-EU-132-1F VATEX-EU-132-1G VATEX-EU-132-1H VATEX-EU-132-1I VATEX-EU-132-1J VATEX-EU-132-1K VATEX-EU-132-1L VATEX-EU-132-1M VATEX-EU-132-1N VATEX-EU-132-1O VATEX-EU-132-1P VATEX-EU-132-1Q VATEX-EU-143 VATEX-EU-143-1A VATEX-EU-143-1B VATEX-EU-143-1C VATEX-EU-143-1D VATEX-EU-143-1E VATEX-EU-143-1F VATEX-EU-143-1FA VATEX-EU-143-1G VATEX-EU-143-1H VATEX-EU-143-1I VATEX-EU-143-1J VATEX-EU-143-1K VATEX-EU-143-1L VATEX-EU-309 VATEX-EU-148 VATEX-EU-148-A VATEX-EU-148-B VATEX-EU-148-C VATEX-EU-148-D VATEX-EU-148-E VATEX-EU-148-F VATEX-EU-148-G VATEX-EU-151 VATEX-EU-151-1A VATEX-EU-151-1AA VATEX-EU-151-1B VATEX-EU-151-1C VATEX-EU-151-1D VATEX-EU-151-1E VATEX-EU-G VATEX-EU-O VATEX-EU-IC VATEX-EU-AE VATEX-EU-D VATEX-EU-F VATEX-EU-I VATEX-EU-J ', concat(' ', normalize-space(upper-case(.)), ' '))))

After · 2.1.0

((not(contains(normalize-space(.), ' ')) and contains(' VATEX-EU-79-C VATEX-EU-132 VATEX-EU-132-1A VATEX-EU-132-1B VATEX-EU-132-1C VATEX-EU-132-1D VATEX-EU-132-1E VATEX-EU-132-1F VATEX-EU-132-1G VATEX-EU-132-1H VATEX-EU-132-1I VATEX-EU-132-1J VATEX-EU-132-1K VATEX-EU-132-1L VATEX-EU-132-1M VATEX-EU-132-1N VATEX-EU-132-1O VATEX-EU-132-1P VATEX-EU-132-1Q VATEX-EU-143 VATEX-EU-143-1A VATEX-EU-143-1B VATEX-EU-143-1C VATEX-EU-143-1D VATEX-EU-143-1E VATEX-EU-143-1F VATEX-EU-143-1FA VATEX-EU-143-1G VATEX-EU-143-1H VATEX-EU-143-1I VATEX-EU-143-1J VATEX-EU-143-1K VATEX-EU-143-1L VATEX-EU-309 VATEX-EU-148 VATEX-EU-148-A VATEX-EU-148-B VATEX-EU-148-C VATEX-EU-148-D VATEX-EU-148-E VATEX-EU-148-F VATEX-EU-148-G VATEX-EU-151 VATEX-EU-151-1A VATEX-EU-151-1AA VATEX-EU-151-1B VATEX-EU-151-1C VATEX-EU-151-1D VATEX-EU-151-1E VATEX-EU-G VATEX-EU-O VATEX-EU-IC VATEX-EU-AE VATEX-EU-D VATEX-EU-F VATEX-EU-I VATEX-EU-J VATEX-FR-FRANCHISE VATEX-FR-CNWVAT ', concat(' ', normalize-space(upper-case(.)), ' '))))
BR-CL-05Test expression rewritten

Tax currency code list replaces "MRU" with "MRO", "STN" with "STD", and "VES" with "VEF"; drops "SLL" and "UYW"

The test's list of accepted currency codes changed. "MRU" was replaced by "MRO", "STN" by "STD", and "VES" by "VEF". "SLL" and "UYW" were dropped from the list. The rule message still requires ISO 4217 alpha-3 codes, and the no-space condition is unchanged.

fatalbusiness

Original rule text: [BR-CL-05]-Tax currency code MUST be coded using ISO code list 4217 alpha-3

Explanation and fix

What this rule requires

The rule requires cbc:TaxCurrencyCode (UBL) or ram:TaxCurrencyCode (CII) to hold an ISO 4217 alpha-3 currency code from the list accepted by BR-CL-05. It passes only when the normalized value is exactly one of the 178 listed codes, for example EUR, USD, or GBP. A document fails if the element is empty, contains only whitespace, has an internal space, or uses a code not on that list.

How to fix

Put a valid ISO 4217 alpha-3 currency code in the tax currency field, such as EUR, USD, or GBP. Ensure the value has no internal spaces (surrounding whitespace is ignored by the rule) and is not empty or only whitespace. Check that the code is present in the BR-CL-05 list; if the current code is something else, replace it with the correct three-letter ISO 4217 code.

Guidance on this rule. The original text above is authoritative.

BR-CL-05 rule details

Before · 2.0.2

((not(contains(normalize-space(.), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HRK HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRU MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SLL SOS SRD SSP STN SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UYW UZS VES VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWL ', concat(' ', normalize-space(.), ' '))))

After · 2.1.0

((not(contains(normalize-space(.), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HRK HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRO MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD SSP STD SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UZS VEF VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWL ', concat(' ', normalize-space(.), ' '))))
BR-DEC-05Test expression rewritten

Document level charge amount decimal check now reads from parent element

The check for the Document level charge amount (BT-99) previously read the value in the current element; it now reads it in the parent element. This changes which element's decimal length is compared against the allowed maximum. The stated maximum of "2" decimal places is unchanged.

fatalcountry

Original rule text: [BR-DEC-05]-The allowed maximum number of decimals for the Document level charge amount (BT-99) is 2.

Explanation and fix

What this rule requires

The rule requires that the document level charge amount (BT-99), as given in the allowance/charge element where ChargeIndicator is true, must not have more than two decimal places. The test checks the number of characters after the decimal point in the amount value; if there are more than two, the invoice fails validation as a fatal error.

How to fix

Change the document level charge amount (cbc:Amount in UBL or ram:ActualAmount in CII) to a value with at most two decimal places, for example 10.99 instead of 10.999. Ensure the system that produces this amount rounds or truncates it to two decimals for document level charges.

Guidance on this rule. The original text above is authoritative.

BR-DEC-05 rule details

Before · 2.0.2

string-length(substring-after(ram:ActualAmount,'.'))<=2

After · 2.1.0

string-length(substring-after(../ram:ActualAmount,'.'))<=2
BR-CO-22Test expression rewritten

Document-level charge reason check now uses a parent-axis step

The test expression changed from "(ram:Reason) or (ram:ReasonCode)" to "(../ram:Reason) or (../ram:ReasonCode)". The new form selects the reason or reason code elements relative to the parent of the context element, whereas the previous form selected them relative to the context element itself. No condition was added or removed, and the OR relationship is unchanged. The rule still requires a document-level charge reason or reason code, or both.

fatalbusiness

Original rule text: [BR-CO-22]-Each Document level charge (BG-21) shall contain a Document level charge reason (BT-104) or a Document level charge reason code (BT-105), or both.

Explanation and fix

What this rule requires

The rule requires that every document level charge (BG-21) contains at least one of a document level charge reason (BT-104) or a document level charge reason code (BT-105), or both. In UBL this means each cac:AllowanceCharge with cbc:ChargeIndicator = true must have a child cbc:AllowanceChargeReason or cbc:AllowanceChargeReasonCode. A document fails validation when neither element exists.

How to fix

Add cbc:AllowanceChargeReason or cbc:AllowanceChargeReasonCode (or both) to each cac:AllowanceCharge where cbc:ChargeIndicator is true. In CII, add ram:Reason or ram:ReasonCode under the applicable ram:SpecifiedTradeAllowanceCharge with ram:ChargeIndicator true. The rule only checks for the element's presence, not its content.

Guidance on this rule. The original text above is authoritative.

BR-CO-22 rule details

Before · 2.0.2

(ram:Reason) or (ram:ReasonCode)

After · 2.1.0

(../ram:Reason) or (../ram:ReasonCode)
BR-41Test expression rewritten

Invoice line allowance amount test now selects the parent element.

The test expression changed from "(ram:ActualAmount)" to "(../ram:ActualAmount)". The new expression selects the element one level above the current context; the previous expression selected it in the current context. Only the test expression changed; the rule's stated requirement is unchanged.

fatalbusiness

Original rule text: [BR-41]-Each Invoice line allowance (BG-27) shall have an Invoice line allowance amount (BT-136).

Explanation and fix

What this rule requires

BR-41 requires every invoice line allowance (BG-27) to have an invoice line allowance amount (BT-136). In UBL, for each cac:AllowanceCharge with cbc:ChargeIndicator = false(), an cbc:Amount element must exist. In CII, for each ram:SpecifiedTradeAllowanceCharge whose ram:ChargeIndicator/udt:Indicator is 'false', the parent must contain ram:ActualAmount. Because this rule is fatal, an invoice missing that amount element in any line allowance fails validation.

How to fix

Add the missing amount element to the line allowance: cbc:Amount in UBL or ram:ActualAmount in CII, with the allowance amount as its value. The test checks only that the element is present, not the value's format or sign.

Guidance on this rule. The original text above is authoritative.

BR-41 rule details

Before · 2.0.2

(ram:ActualAmount)

After · 2.1.0

(../ram:ActualAmount)
BR-AE-03Test expression rewritten

Seller tax registration scheme list gains "FC" alongside "VA"

The rule's condition for the seller trade party's tax registration identifier now specifies the scheme attribute values "VA" and "FC", where the previous version specified only "VA". The seller tax representative branch still specifies only "VA", and the buyer side is unchanged. The expanded list sits within the first alternative of the condition.

fatalbusiness

Original rule text: [BR-AE-03]-An Invoice that contains a Document level allowance (BG-20) where the Document level allowance VAT category code (BT-95) is "Reverse charge" shall contain the Seller VAT Identifier (BT-31), the Seller tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63) and the Buyer VAT identifier (BT-48) and/or the Buyer legal registration identifier (BT-47).

Explanation and fix

What this rule requires

This fatal rule applies when the invoice or credit note contains a document level allowance (BG-20) whose document level allowance VAT category code (BT-95) is "AE" (reverse charge). In that case, the document must include both a seller-side identifier and a buyer-side identifier. In UBL, the seller side is met by any cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID or by cac:TaxRepresentativeParty/cac:PartyTaxScheme/cbc:CompanyID where the tax scheme is VAT; the buyer side is met by cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID where the tax scheme is VAT or by cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cbc:CompanyID. In CII, the seller side is met by ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID with @schemeID VA or FC, or by ram:SellerTaxRepresentativeTradeParty/ram:SpecifiedTaxRegistration/ram:ID with @schemeID VA; the buyer side is met by ram:BuyerTradeParty/ram:SpecifiedTaxRegistration/ram:ID with @schemeID VA or by ram:BuyerTradeParty/ram:SpecifiedLegalOrganization/ram:ID. If no such allowance with reverse charge VAT category exists, the rule imposes no identifier requirement.

How to fix

If the invoice has a document-level allowance with VAT category AE, add or ensure at least one of the permitted seller identifiers and at least one of the permitted buyer identifiers using the element paths above. In UBL, for the seller, add cbc:CompanyID inside cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme (or add a VAT tax representative cac:TaxRepresentativeParty/cac:PartyTaxScheme/cbc:CompanyID); for the buyer, add cbc:CompanyID under cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme[cac:TaxScheme/cbc:ID='VAT'] or under cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity. In CII, ensure the seller has ram:SpecifiedTaxRegistration/ram:ID with @schemeID VA or FC (or tax representative VA), and the buyer has ram:SpecifiedTaxRegistration/ram:ID with @schemeID VA or ram:SpecifiedLegalOrganization/ram:ID. If the allowance is not actually reverse charge, correct the cbc:ID / ram:CategoryCode from AE to the appropriate value.

Guidance on this rule. The original text above is authoritative.

BR-AE-03 rule details

Before · 2.0.2

(//ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA'] or //ram:SellerTaxRepresentativeTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA']) and (//ram:BuyerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA'] or //ram:BuyerTradeParty/ram:SpecifiedLegalOrganization/ram:ID)

After · 2.1.0

(//ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = ('VA', 'FC')] or //ram:SellerTaxRepresentativeTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA']) and (//ram:BuyerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA'] or //ram:BuyerTradeParty/ram:SpecifiedLegalOrganization/ram:ID)
BR-CL-04Test expression rewritten

Allowed currency codes replace "MRU", "STN", "VES" with "MRO", "STD", "VEF" and drop "SLL", "UYW"

The test accepts a space-delimited list of currency codes. The new list replaces "MRU" with "MRO", "STN" with "STD", and "VES" with "VEF", and it no longer contains "SLL" or "UYW". The surrounding checks for no embedded space and for the code being present in that list are unchanged.

fatalbusiness

Original rule text: [BR-CL-04]-Invoice currency code MUST be coded using ISO code list 4217 alpha-3

Explanation and fix

What this rule requires

The rule requires the invoice currency code to be a valid ISO 4217 alpha-3 currency code. It checks that the code contains no spaces and appears in the rule's list of accepted currency codes. A document fails if cbc:DocumentCurrencyCode (UBL) or ram:InvoiceCurrencyCode (CII) is empty, contains whitespace, or is not one of the listed codes.

How to fix

Set the currency code element to a three-letter ISO 4217 code from the list allowed by the rule, for example EUR, USD, or GBP. In UBL use cbc:DocumentCurrencyCode; in CII use ram:InvoiceCurrencyCode. Ensure the value contains no spaces.

Guidance on this rule. The original text above is authoritative.

BR-CL-04 rule details

Before · 2.0.2

((not(contains(normalize-space(.), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HRK HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRU MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SLL SOS SRD SSP STN SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UYW UZS VES VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWL ', concat(' ', normalize-space(.), ' '))))

After · 2.1.0

((not(contains(normalize-space(.), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HRK HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRO MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD SSP STD SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UZS VEF VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWL ', concat(' ', normalize-space(.), ' '))))
BR-36Test expression rewritten

The rule now evaluates "../ram:ActualAmount" instead of "ram:ActualAmount"

The test expression changed from "ram:ActualAmount" to "../ram:ActualAmount". The rule now selects the ActualAmount element on the parent of the context node instead of on the context node itself. The rule message remains that each Document level charge (BG-21) shall have a Document level charge amount (BT-99). No other change is shown by the evidence.

fatalbusiness

Original rule text: [BR-36]-Each Document level charge (BG-21) shall have a Document level charge amount (BT-99).

Explanation and fix

What this rule requires

The rule requires that every document-level charge (BG-21) carries a document-level charge amount (BT-99). In UBL, each cac:AllowanceCharge with cbc:ChargeIndicator equal to true must contain a cbc:Amount; in CII, each SpecifiedTradeAllowanceCharge whose ChargeIndicator is true must contain an ActualAmount. A missing amount element causes this fatal validation error.

How to fix

Add the missing amount element to the document-level charge. In UBL, add cbc:Amount inside the relevant cac:AllowanceCharge; in CII, add ram:ActualAmount inside the SpecifiedTradeAllowanceCharge that has the ChargeIndicator with value true. Set its value to the charge amount.

Guidance on this rule. The original text above is authoritative.

BR-36 rule details

Before · 2.0.2

(ram:ActualAmount)

After · 2.1.0

(../ram:ActualAmount)
BR-38Test expression rewritten

Document level charge reason check now targets the parent node

The test now checks for a reason or reason code element on the parent node rather than the current node. Both alternatives and the or condition are otherwise unchanged. The rule's message still requires each "BG-21" document level charge to have a "BT-104" reason or a "BT-105" reason code.

fatalbusiness

Original rule text: [BR-38]-Each Document level charge (BG-21) shall have a Document level charge reason (BT-104) or a Document level charge reason code (BT-105).

Explanation and fix

What this rule requires

For each document-level charge (BG-21), the rule requires at least one of a charge reason (BT-104) or a charge reason code (BT-105). In UBL, a document-level charge is an cac:AllowanceCharge with cbc:ChargeIndicator = true(); it must contain either cbc:AllowanceChargeReason or cbc:AllowanceChargeReasonCode. In CII, the ram:SpecifiedTradeAllowanceCharge whose ram:ChargeIndicator has udt:Indicator='true' must contain either ram:Reason or ram:ReasonCode. Because the test uses or, having either element satisfies the rule; having neither fails validation with severity fatal.

How to fix

In the invoice, for every document-level charge that currently lacks both elements, add cbc:AllowanceChargeReason with a text description of the charge, or add cbc:AllowanceChargeReasonCode with a valid reason code, inside the corresponding cac:AllowanceCharge. In CII, add ram:Reason or ram:ReasonCode inside the ram:SpecifiedTradeAllowanceCharge for that charge. If the producing system omits these fields, configure it to populate at least one for each document-level charge. Use only reason code values accepted by the applicable code list.

Guidance on this rule. The original text above is authoritative.

BR-38 rule details

Before · 2.0.2

(ram:Reason) or (ram:ReasonCode)

After · 2.1.0

(../ram:Reason) or (../ram:ReasonCode)
BR-DEC-24Test expression rewritten

Decimal check now reads the allowance amount from the parent context

The rule checks that the invoice line allowance amount has at most "2" decimal places. The test expression changed from resolving the actual amount within the current context to resolving it from the parent context. The decimal limit and the rule message are unchanged. The evidence does not show why the path changed.

fatalcountry

Original rule text: [BR-DEC-24]-The allowed maximum number of decimals for the Invoice line allowance amount (BT-136) is 2.

Explanation and fix

What this rule requires

The rule requires the line-level allowance amount BT-136 to have no more than two decimal places. It applies to cbc:Amount inside cac:AllowanceCharge where cbc:ChargeIndicator is false (UBL), and to ram:ActualAmount inside ram:SpecifiedTradeAllowanceCharge where ram:ChargeIndicator is false (CII). The test counts the characters after the decimal point in that amount and fails if there are more than 2. A value without a decimal point passes.

How to fix

Set the allowance amount to a value with at most two decimal places, such as 10.50 or 10. In UBL change cbc:Amount; in CII change ram:ActualAmount. If the amount is produced by a system, format it to no more than two decimals before generating the invoice.

Guidance on this rule. The original text above is authoritative.

BR-DEC-24 rule details

Before · 2.0.2

string-length(substring-after(ram:ActualAmount,'.'))<=2

After · 2.1.0

string-length(substring-after(../ram:ActualAmount,'.'))<=2
BR-CL-13Test expression rewritten

The rule's allowed UNTDID 7143 codes now include "GMN"

From the 2.0.2 expression to the 2.1.0 expression, one allowed code is added: the space-separated list changes from containing "GN GS" to containing "GN GMN GS". The new value "GMN" sits between "GN" and "GS". All other entries and the surrounding whitespace padding remain the same, as does the requirement that the identifier contain no spaces.

fatalbusiness

Original rule text: [BR-CL-13]-Item classification identifier identification scheme identifier MUST be coded using one of the UNTDID 7143 list.

Explanation and fix

What this rule requires

The rule checks the item classification identifier scheme identifier in cac:CommodityClassification/cbc:ItemClassificationCode[@listID] (UBL) or ram:ClassCode[@listID] (CII). After surrounding whitespace is ignored, the value must not contain any internal space and must exactly match one of the 185 listed UNTDID 7143 codes, for example AA, AB, AC, EN, or ZZZ. A missing value, a value with internal spaces, or any value not in that list violates this fatal rule.

How to fix

Set the listID attribute to a valid UNTDID 7143 code from the rule's list, e.g. AA, AB, AC, EN, or ZZZ. The value may have leading or trailing whitespace, but after trimming it must be exactly one of those 185 codes and contain no internal spaces. If you do not know which code applies to the item classification, check the UNTDID 7143 list for the correct scheme identifier.

Guidance on this rule. The original text above is authoritative.

BR-CL-13 rule details

Before · 2.0.2

((not(contains(normalize-space(@listID), ' ')) and contains(' AA AB AC AD AE AF AG AH AI AJ AK AL AM AN AO AP AQ AR AS AT AU AV AW AX AY AZ BA BB BC BD BE BF BG BH BI BJ BK BL BM BN BO BP BQ BR BS BT BU BV BW BX BY BZ CC CG CL CR CV DR DW EC EF EMD EN FS GB GN GS HS IB IN IS IT IZ MA MF MN MP NB ON PD PL PO PV QS RC RN RU RY SA SG SK SN SRS SRT SRU SRV SRW SRX SRY SRZ SS SSA SSB SSC SSD SSE SSF SSG SSH SSI SSJ SSK SSL SSM SSN SSO SSP SSQ SSR SSS SST SSU SSV SSW SSX SSY SSZ ST STA STB STC STD STE STF STG STH STI STJ STK STL STM STN STO STP STQ STR STS STT STU STV STW STX STY STZ SUA SUB SUC SUD SUE SUF SUG SUH SUI SUJ SUK SUL SUM TG TSN TSO TSP TSQ TSR TSS TST TSU UA UP VN VP VS VX ZZZ ', concat(' ', normalize-space(@listID), ' '))))

After · 2.1.0

((not(contains(normalize-space(@listID), ' ')) and contains(' AA AB AC AD AE AF AG AH AI AJ AK AL AM AN AO AP AQ AR AS AT AU AV AW AX AY AZ BA BB BC BD BE BF BG BH BI BJ BK BL BM BN BO BP BQ BR BS BT BU BV BW BX BY BZ CC CG CL CR CV DR DW EC EF EMD EN FS GB GN GMN GS HS IB IN IS IT IZ MA MF MN MP NB ON PD PL PO PV QS RC RN RU RY SA SG SK SN SRS SRT SRU SRV SRW SRX SRY SRZ SS SSA SSB SSC SSD SSE SSF SSG SSH SSI SSJ SSK SSL SSM SSN SSO SSP SSQ SSR SSS SST SSU SSV SSW SSX SSY SSZ ST STA STB STC STD STE STF STG STH STI STJ STK STL STM STN STO STP STQ STR STS STT STU STV STW STX STY STZ SUA SUB SUC SUD SUE SUF SUG SUH SUI SUJ SUK SUL SUM TG TSN TSO TSP TSQ TSR TSS TST TSU UA UP VN VP VS VX ZZZ ', concat(' ', normalize-space(@listID), ' '))))
BR-CL-20Test expression rewritten

The allowed UNCL 7161 charge reason codes now include "PRV".

The list of allowed UNCL 7161 charge reason codes in the rule gains one value: "PRV". It is inserted between "PL" and "RAB". The surrounding condition is unchanged — a value must contain no spaces and match one of the listed codes.

fatalbusiness

Original rule text: [BR-CL-20]-Coded charge reasons MUST belong to the UNCL 7161 code list

Explanation and fix

What this rule requires

The rule requires that a coded charge reason (cbc:AllowanceChargeReasonCode in UBL or ram:ReasonCode in CII) on a charge (ChargeIndicator = true) be a single code from the UNCL 7161 list given in the rule. Ignoring surrounding whitespace, the value must not contain internal spaces and must exactly match one of the listed codes, for example AA, AAA, AAC. If the value is not one of the listed codes, or contains internal spaces, the document fails this fatal rule.

How to fix

Set the charge reason code element to a valid UNCL 7161 code from the rule's list. In UBL, this is cbc:AllowanceChargeReasonCode inside cac:AllowanceCharge where cbc:ChargeIndicator is true; in CII, it is ram:ReasonCode inside ram:SpecifiedTradeAllowanceCharge where ram:ChargeIndicator is true. Replace any free-text description or unknown code with the appropriate single code from the list, and ensure no multiple codes or internal spaces are entered. Check your code mapping or configuration for the correct charge reason code.

Guidance on this rule. The original text above is authoritative.

BR-CL-20 rule details

Before · 2.0.2

((not(contains(normalize-space(.), ' ')) and contains(' AA AAA AAC AAD AAE AAF AAH AAI AAS AAT AAV AAY AAZ ABA ABB ABC ABD ABF ABK ABL ABN ABR ABS ABT ABU ACF ACG ACH ACI ACJ ACK ACL ACM ACS ADC ADE ADJ ADK ADL ADM ADN ADO ADP ADQ ADR ADT ADW ADY ADZ AEA AEB AEC AED AEF AEH AEI AEJ AEK AEL AEM AEN AEO AEP AES AET AEU AEV AEW AEX AEY AEZ AJ AU CA CAB CAD CAE CAF CAI CAJ CAK CAL CAM CAN CAO CAP CAQ CAR CAS CAT CAU CAV CAW CAX CAY CAZ CD CG CS CT DAB DAD DAC DAF DAG DAH DAI DAJ DAK DAL DAM DAN DAO DAP DAQ DL EG EP ER FAA FAB FAC FC FH FI GAA HAA HD HH IAA IAB ID IF IR IS KO L1 LA LAA LAB LF MAE MI ML NAA OA PA PAA PC PL RAB RAC RAD RAF RE RF RH RV SA SAA SAD SAE SAI SG SH SM SU TAB TAC TT TV V1 V2 WH XAA YY ZZZ ', concat(' ', normalize-space(.), ' '))))

After · 2.1.0

((not(contains(normalize-space(.), ' ')) and contains(' AA AAA AAC AAD AAE AAF AAH AAI AAS AAT AAV AAY AAZ ABA ABB ABC ABD ABF ABK ABL ABN ABR ABS ABT ABU ACF ACG ACH ACI ACJ ACK ACL ACM ACS ADC ADE ADJ ADK ADL ADM ADN ADO ADP ADQ ADR ADT ADW ADY ADZ AEA AEB AEC AED AEF AEH AEI AEJ AEK AEL AEM AEN AEO AEP AES AET AEU AEV AEW AEX AEY AEZ AJ AU CA CAB CAD CAE CAF CAI CAJ CAK CAL CAM CAN CAO CAP CAQ CAR CAS CAT CAU CAV CAW CAX CAY CAZ CD CG CS CT DAB DAD DAC DAF DAG DAH DAI DAJ DAK DAL DAM DAN DAO DAP DAQ DL EG EP ER FAA FAB FAC FC FH FI GAA HAA HD HH IAA IAB ID IF IR IS KO L1 LA LAA LAB LF MAE MI ML NAA OA PA PAA PC PL PRV RAB RAC RAD RAF RE RF RH RV SA SAA SAD SAE SAI SG SH SM SU TAB TAC TT TV V1 V2 WH XAA YY ZZZ ', concat(' ', normalize-space(.), ' '))))
BR-44Test expression rewritten

The rule now checks the parent context for reason or reason code.

The rule's test expression changed. Previously, it checked whether the current context had an invoice line charge reason or an invoice line charge reason code. Now it checks whether the parent context has either of those elements. The form of the change is the addition of a parent step to both branches of the OR. The rule message and identifier are unchanged.

fatalbusiness

Original rule text: [BR-44]-Each Invoice line charge (BG-28) shall have an Invoice line charge reason (BT-144) or an Invoice line charge reason code (BT-145).

Explanation and fix

What this rule requires

For each invoice line charge (BG-28) in CII, represented by a ram:SpecifiedTradeAllowanceCharge containing ram:ChargeIndicator with udt:Indicator = true, the rule requires at least one of ram:Reason (BT-144) or ram:ReasonCode (BT-145) as a child of that same ram:SpecifiedTradeAllowanceCharge. A document fails if neither element is present. Because the severity is fatal, such a document does not pass validation.

How to fix

Add at least one of ram:Reason or ram:ReasonCode to the ram:SpecifiedTradeAllowanceCharge that carries the true ram:ChargeIndicator. For ram:Reason (BT-144), supply the reason text; for ram:ReasonCode (BT-145), supply a valid reason code from the applicable code list (the rule does not specify the allowed codes).

Guidance on this rule. The original text above is authoritative.

BR-44 rule details

Before · 2.0.2

(ram:Reason) or (ram:ReasonCode)

After · 2.1.0

(../ram:Reason) or (../ram:ReasonCode)
BR-DEC-28Test expression rewritten

Invoice line charge base amount decimal check now looks in the parent context

The test expression changed from selecting the basis amount in the current context to selecting the basis amount in the parent context. Previously the check applied to the basis amount directly under the context node; now it applies to the basis amount under the context node's parent. The decimal-length check still requires the Invoice line charge base amount to have no more than "2" digits after the decimal point.

fatalcountry

Original rule text: [BR-DEC-28]-The allowed maximum number of decimals for the Invoice line charge base amount (BT-142) is 2.

Explanation and fix

What this rule requires

The rule requires the invoice line charge base amount (BT-142) to have at most two decimal places. In UBL it checks cbc:BaseAmount of a line-level cac:AllowanceCharge with cbc:ChargeIndicator = true(); in CII it checks ram:BasisAmount for a corresponding ram:ChargeIndicator with value true. A value such as 1.234 fails because there are three digits after the decimal point.

How to fix

Set the affected charge base amount to a value with no more than two decimal places. In UBL, change cbc:BaseAmount in the line allowance charge; in CII, change ram:BasisAmount in the corresponding allowance charge. For example, round or format the amount to two decimals before output, e.g. 1.23 instead of 1.234.

Guidance on this rule. The original text above is authoritative.

BR-DEC-28 rule details

Before · 2.0.2

string-length(substring-after(ram:BasisAmount,'.'))<=2

After · 2.1.0

string-length(substring-after(../ram:BasisAmount,'.'))<=2
BR-CO-24Test expression rewritten

Reason and reason code checks now use parent context instead of current context

The test expression changed from "(ram:Reason) or (ram:ReasonCode)" to "(../ram:Reason) or (../ram:ReasonCode)". The added "../" prefix moves the lookup from the current context to the parent context. Both alternatives were changed in the same way, so the rule still requires one or both, just at a different relative location. The rule's stated condition is unchanged.

fatalbusiness

Original rule text: [BR-CO-24]-Each Invoice line charge (BG-28) shall contain an Invoice line charge reason (BT-144) or an Invoice line charge reason code (BT-145), or both.

Explanation and fix

What this rule requires

BR-CO-24 requires every invoice line charge (BG-28) to include at least one of cbc:AllowanceChargeReason (BT-144) or cbc:AllowanceChargeReasonCode (BT-145), or both. In UBL this applies to cac:InvoiceLine/cac:AllowanceCharge[cbc:ChargeIndicator = true()] and to cac:CreditNoteLine/cac:AllowanceCharge[cbc:ChargeIndicator = true()]; in CII it applies to the corresponding SpecifiedTradeAllowanceCharge with ChargeIndicator true. A document fails when a line charge has neither element, because the test exists(cbc:AllowanceChargeReason) or exists(cbc:AllowanceChargeReasonCode) is false.

How to fix

For each line charge in the invoice or credit note, make sure at least one of cbc:AllowanceChargeReason or cbc:AllowanceChargeReasonCode is present. In a producing system, configure the line charge to output a reason text or reason code; for UBL, add e.g. <cbc:AllowanceChargeReason>...</cbc:AllowanceChargeReason> or <cbc:AllowanceChargeReasonCode>...</cbc:AllowanceChargeReasonCode> to the charge. For CII, add ram:Reason or ram:ReasonCode to the ram:SpecifiedTradeAllowanceCharge that has ram:ChargeIndicator with indicator value 'true'.

Guidance on this rule. The original text above is authoritative.

BR-CO-24 rule details

Before · 2.0.2

(ram:Reason) or (ram:ReasonCode)

After · 2.1.0

(../ram:Reason) or (../ram:ReasonCode)
BR-DEC-02Test expression rewritten

Decimal check now reads the document level allowance base amount from the parent context

The check now selects the allowance base amount from the parent of the current context, where it previously selected it from the current context itself. The allowed maximum remains two decimal digits, and the rule message still identifies the document level allowance base amount as "BT-93". The evidence does not say why the target moved up one level.

fatalcountry

Original rule text: [BR-DEC-02]-The allowed maximum number of decimals for the Document level allowance base amount (BT-93) is 2.

Explanation and fix

What this rule requires

The rule requires that the document level allowance base amount (BT-93) in cbc:BaseAmount (UBL) or ram:BasisAmount (CII) for an allowance charge with ChargeIndicator = false has at most two digits after the decimal point. A value fails if it contains a decimal point and more than two decimal digits; values with no decimal point or with one or two decimal digits are valid.

How to fix

Set the document level allowance base amount to a value with at most two decimal places. For example, 100 or 100.50 are acceptable, while 100.505 is not. In the invoice generator, round or format cbc:BaseAmount/ram:BasisAmount for document level allowances to a maximum of two decimal digits.

Guidance on this rule. The original text above is authoritative.

BR-DEC-02 rule details

Before · 2.0.2

string-length(substring-after(ram:BasisAmount,'.'))<=2

After · 2.1.0

string-length(substring-after(../ram:BasisAmount,'.'))<=2
BR-CL-03Test expression rewritten

Currency list swaps "MRU", "STN", "VES" for "MRO", "STD", "VEF" and drops "UYW"

The rule checks a currency code against a space-separated list of ISO 4217 alpha-3 values. In the transition from 2.0.2 to 2.1.0, the allowed list changed: "MRU", "STN", and "VES" were replaced by "MRO", "STD", and "VEF", and "UYW" was removed. The other list entries and the condition that the currency code contain no spaces are unchanged. The rule's message still requires ISO code list 4217 alpha-3 coding.

fatalbusiness

Original rule text: [BR-CL-03]-currencyID MUST be coded using ISO code list 4217 alpha-3

Explanation and fix

What this rule requires

The rule requires that the @currencyID attribute on amount elements (UBL) or on ram:TaxTotalAmount (CII) contains an ISO 4217 alpha-3 currency code from the list accepted by the rule, and that the code contains no spaces. Because the severity is fatal, an invoice that does not satisfy this condition is rejected with message [BR-CL-03]-currencyID MUST be coded using ISO code list 4217 alpha-3.

How to fix

Set the currencyID attribute to a valid three-letter ISO 4217 alpha-3 code that appears in the rule's list, for example EUR or USD. Ensure the value is not empty and contains no spaces. In UBL this applies to amount elements such as cbc:TaxAmount; in CII it applies to ram:TaxTotalAmount[@currencyID]. If the current value is not a valid code, correct it in the source system.

Guidance on this rule. The original text above is authoritative.

BR-CL-03 rule details

Before · 2.0.2

((not(contains(normalize-space(@currencyID), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HRK HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRU MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SLL SOS SRD SSP STN SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UYW UZS VES VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWL ', concat(' ', normalize-space(@currencyID), ' '))))

After · 2.1.0

((not(contains(normalize-space(@currencyID), ' ')) and contains(' AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNY COP COU CRC CUC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HRK HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRO MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD SSP STD SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UZS VEF VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWL ', concat(' ', normalize-space(@currencyID), ' '))))
BR-CO-23Test expression rewritten

The condition now checks the parent element for either reason field

The test expression changed from checking the reason or reason code available at the current context to checking those same fields relative to the parent of the current context, by prefixing each with "../". The two alternatives are unchanged: the Invoice line allowance reason (BT-139) or the Invoice line allowance reason code (BT-140), or both, must still be present. No condition was added or removed; only the tree location the test inspects changed.

fatalbusiness

Original rule text: [BR-CO-23]-Each Invoice line allowance (BG-27) shall contain an Invoice line allowance reason (BT-139) or an Invoice line allowance reason code (BT-140), or both.

Explanation and fix

What this rule requires

For each invoice line allowance (BG-27), represented by a cac:AllowanceCharge with cbc:ChargeIndicator set to false (or the equivalent CII structure), the rule requires at least one of cbc:AllowanceChargeReason (BT-139) or cbc:AllowanceChargeReasonCode (BT-140) to be present. Because the test uses or, either element alone is sufficient; both is also allowed. The severity is fatal, so an invoice missing both in any line allowance does not pass validation.

How to fix

Add a cbc:AllowanceChargeReason element or a cbc:AllowanceChargeReasonCode element (or both) inside each line-level cac:AllowanceCharge where cbc:ChargeIndicator is false. In CII, add ram:Reason or ram:ReasonCode within the corresponding ram:SpecifiedTradeAllowanceCharge. The rule only checks for the presence of at least one of these elements, not its value or content.

Guidance on this rule. The original text above is authoritative.

BR-CO-23 rule details

Before · 2.0.2

(ram:Reason) or (ram:ReasonCode)

After · 2.1.0

(../ram:Reason) or (../ram:ReasonCode)
BR-AE-02Test expression rewritten

Seller tax registration ID scheme list includes "FC" as well as "VA".

The rule's test expression changed only in the seller trade party condition. Previously that condition matched a tax registration ID whose schemeID attribute was exactly "VA". Now it matches either "VA" or "FC". The seller tax representative condition still requires only "VA", and the buyer side is unchanged.

fatalbusiness

Original rule text: [BR-AE-02]-An Invoice that contains an Invoice line (BG-25) where the Invoiced item VAT category code (BT-151) is "Reverse charge" shall contain the Seller VAT Identifier (BT-31), the Seller Tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63) and the Buyer VAT identifier (BT-48) and/or the Buyer legal registration identifier (BT-47).

Explanation and fix

What this rule requires

For UBL, if any invoice or credit note contains a line with cac:ClassifiedTaxCategory[cbc:ID='AE'] and cac:TaxScheme/cbc:ID equal to VAT (case-insensitive), then the document must include at least one of: seller cac:PartyTaxScheme/cbc:CompanyID or seller tax representative cac:TaxRepresentativeParty/cac:PartyTaxScheme[cac:TaxScheme/cbc:ID='VAT']/cbc:CompanyID; and at least one of: customer cac:PartyTaxScheme[cac:TaxScheme/cbc:ID='VAT']/cbc:CompanyID or customer cac:PartyLegalEntity/cbc:CompanyID. If no such line exists, the rule passes. For CII, on each line with ram:ApplicableTradeTax[ram:CategoryCode='AE' and ram:TypeCode='VAT'], the test requires at least one of: seller ram:SpecifiedTaxRegistration/ram:ID[@schemeID='VA' or @schemeID='FC'] or seller tax representative ram:SpecifiedTaxRegistration/ram:ID[@schemeID='VA']; and at least one of: buyer ram:SpecifiedTaxRegistration/ram:ID[@schemeID='VA'] or buyer ram:SpecifiedLegalOrganization/ram:ID. Severity is fatal, so a document that does not satisfy this check fails validation.

How to fix

If the invoice has a reverse charge line (VAT category code AE), add the missing identifiers. In UBL, ensure the seller side has either cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID or cac:TaxRepresentativeParty/cac:PartyTaxScheme[cac:TaxScheme/cbc:ID='VAT']/cbc:CompanyID; and the buyer side has either cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme[cac:TaxScheme/cbc:ID='VAT']/cbc:CompanyID or cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cbc:CompanyID. In CII, ensure the seller has ram:SpecifiedTaxRegistration/ram:ID with @schemeID VA or FC, or ram:SellerTaxRepresentativeTradeParty/ram:SpecifiedTaxRegistration/ram:ID with @schemeID VA; and the buyer has ram:SpecifiedTaxRegistration/ram:ID with @schemeID VA or ram:SpecifiedLegalOrganization/ram:ID. If no reverse charge line exists, the rule passes; check that the AE code is not incorrectly applied.

Guidance on this rule. The original text above is authoritative.

BR-AE-02 rule details

Before · 2.0.2

(//ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA'] or //ram:SellerTaxRepresentativeTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA']) and (//ram:BuyerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA'] or //ram:BuyerTradeParty/ram:SpecifiedLegalOrganization/ram:ID)

After · 2.1.0

(//ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = ('VA', 'FC')] or //ram:SellerTaxRepresentativeTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA']) and (//ram:BuyerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID = 'VA'] or //ram:BuyerTradeParty/ram:SpecifiedLegalOrganization/ram:ID)
BR-31Test expression rewritten

Allowance amount check now looks in the parent element

The rule requires each Document level allowance (BG-20) to have a Document level allowance amount (BT-92). The test expression changed from "(ram:ActualAmount)" to "(../ram:ActualAmount)". The added "../" step makes the check resolve the amount in the parent of the node being tested, rather than as a child of that node.

fatalbusiness

Original rule text: [BR-31]-Each Document level allowance (BG-20) shall have a Document level allowance amount (BT-92).

Explanation and fix

What this rule requires

The rule requires that every document-level allowance (BG-20) also carries a document-level allowance amount (BT-92). It is fatal, so an invoice that does not satisfy it fails validation. In UBL, the allowance is an cac:AllowanceCharge with cbc:ChargeIndicator set to false, and the amount must be present as a child cbc:Amount. In CII, the allowance is a ram:SpecifiedTradeAllowanceCharge whose ram:ChargeIndicator has udt:Indicator = false, and the amount must be present as a sibling ram:ActualAmount. The test checks only that the respective element exists, not its value.

How to fix

For each document-level allowance, ensure the amount element is present in the XML. In UBL, add a cbc:Amount child inside the cac:AllowanceCharge where cbc:ChargeIndicator is false and populate it with the allowance amount. In CII, add a ram:ActualAmount sibling after the ram:ChargeIndicator whose udt:Indicator is false and populate it with the allowance amount. If an allowance is present but no amount is available, check the source data or mapping: the amount must be supplied as part of the allowance. The rule does not specify a minimum or format for the amount, only that the element exists.

Guidance on this rule. The original text above is authoritative.

BR-31 rule details

Before · 2.0.2

(ram:ActualAmount)

After · 2.1.0

(../ram:ActualAmount)
BR-DEC-06Test expression rewritten

The rule now checks the parent element's charge base amount instead of the current element's.

The test expression changed how it locates the document-level charge base amount. Previously the decimal-length check was applied to the amount on the current element; the new version adds a parent step, so the check now reads the amount from the parent element instead. The condition itself — that the substring after the decimal point has at most two characters — is unchanged.

fatalcountry

Original rule text: [BR-DEC-06]-The allowed maximum number of decimals for the Document level charge base amount (BT-100) is 2.

Explanation and fix

What this rule requires

For a document level charge (BT-100), the base amount in the UBL element cbc:BaseAmount or the CII element ram:BasisAmount must have no more than two decimal places. The test checks the digits after the decimal point; if there are more than two digits after the decimal point, e.g. 12.345, the rule fails. This is a fatal rule, so such a document fails validation.

How to fix

Ensure the document level charge base amount (BT-100) has at most two decimal places. In UBL, set cbc:BaseAmount to a value with no more than two digits after the decimal point, such as 12.34; in CII, set ram:BasisAmount accordingly. If the value is generated automatically, adjust the precision or rounding to two decimals.

Guidance on this rule. The original text above is authoritative.

BR-DEC-06 rule details

Before · 2.0.2

string-length(substring-after(ram:BasisAmount,'.'))<=2

After · 2.1.0

string-length(substring-after(../ram:BasisAmount,'.'))<=2
BR-43Test expression rewritten

Rule now checks parent element for the invoice line charge amount

The test expression changed from selecting the amount element directly in the current context to selecting it relative to the parent. Before, the expression was "(ram:ActualAmount)"; after, it is "(../ram:ActualAmount)". This means the check now navigates one level up the document tree before finding the invoice line charge amount. The rule's stated purpose—each invoice line charge must have an invoice line charge amount—remains unchanged.

fatalbusiness

Original rule text: [BR-43]-Each Invoice line charge (BG-28) shall have an Invoice line charge amount (BT-141).

Explanation and fix

What this rule requires

The rule requires every invoice line charge (BG-28) to include an invoice line charge amount (BT-141). In UBL, any cac:AllowanceCharge with cbc:ChargeIndicator = true() inside an cac:InvoiceLine or cac:CreditNoteLine must contain a cbc:Amount. In CII, any ram:SpecifiedTradeAllowanceCharge with ram:ChargeIndicator equal to 'true' inside a ram:SpecifiedLineTradeSettlement must contain a ram:ActualAmount. A document that does not satisfy this fatal rule fails validation.

How to fix

For UBL, add a cbc:Amount element inside the charge cac:AllowanceCharge (the one with cbc:ChargeIndicator true) for each affected line. For CII, add a ram:ActualAmount element inside the ram:SpecifiedTradeAllowanceCharge with ram:ChargeIndicator true. Populate it with the monetary amount of the line charge. The rule only checks that the element is present, not the currency or the value.

Guidance on this rule. The original text above is authoritative.

BR-43 rule details

Before · 2.0.2

(ram:ActualAmount)

After · 2.1.0

(../ram:ActualAmount)
BR-62Test expression rewritten

Only the first seller electronic address is checked for a scheme identifier.

The check that tests the scheme identifier now selects the first seller electronic address by adding an index of "[1]" to that seller electronic address. Previously the seller electronic address was selected without an explicit index. The alternative condition that the seller electronic address may be absent is unchanged.

fatalbusiness

Original rule text: [BR-62]-The Seller electronic address (BT-34) shall have a Scheme identifier.

Explanation and fix

What this rule requires

The rule requires that the Seller electronic address (BT-34) must have a Scheme identifier when provided. In UBL, the element cac:AccountingSupplierParty/cac:Party/cbc:EndpointID must have a @schemeID attribute. In CII, if any ram:URIUniversalCommunication element exists under the SellerTradeParty, its first ram:URIID must have a non-empty @schemeID attribute; if ram:URIUniversalCommunication is absent, the rule is satisfied.

How to fix

In UBL, add a schemeID attribute to cac:AccountingSupplierParty/cac:Party/cbc:EndpointID with a value accepted by the rule. In CII, if ram:URIUniversalCommunication is present, ensure its ram:URIID has a non-empty schemeID attribute. If the electronic address is not provided, no change is needed.

Guidance on this rule. The original text above is authoritative.

BR-62 rule details

Before · 2.0.2

normalize-space(rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:URIUniversalCommunication/ram:URIID/@schemeID) != '' or not (rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:URIUniversalCommunication)

After · 2.1.0

normalize-space(rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:URIUniversalCommunication[1]/ram:URIID/@schemeID) != '' or not (rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:URIUniversalCommunication)
CII-SR-459New rule

New rule requires at most one "URIUniversalCommunication" per "SellerTradeParty"

The rule is newly added in this change. Its test requires the count of "URIUniversalCommunication" elements within "SellerTradeParty" to be no more than one. The rule message is "SellerTradeParty URIUniversalCommunication should exist maximum once".

warningschema

Original rule text: [CII-SR-459] - SellerTradeParty URIUniversalCommunication should exist maximum once

Explanation and fix

What this rule requires

The rule checks that in ram:ApplicableHeaderTradeAgreement the ram:SellerTradeParty has at most one ram:URIUniversalCommunication child. The test counts these children and requires the count to be <= 1; a count of 0 is allowed. If more than one is present, the document is rejected because the rule is fatal.

How to fix

In the CII invoice, look under /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty and ensure there is no more than one ram:URIUniversalCommunication element. Remove any extra ram:URIUniversalCommunication elements, or configure the producing system to emit only one.

Guidance on this rule. The original text above is authoritative.

CII-SR-459 rule details

Added · 2.1.0

count(ram:SellerTradeParty/ram:URIUniversalCommunication) <= 1
CII-SR-461New rule

New rule allows at most one "TaxPointDate"

A new rule was added: within applicable trade tax, the number of "TaxPointDate" elements must be at most "1". Zero or one occurrence is allowed; any additional occurrence fails validation. The rule appears in the published 2.1.0 set relative to 2.0.2.

fatalschema

Original rule text: [CII-SR-461] - Only one TaxPointDate shall be present

Explanation and fix

What this rule requires

In CII, under /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement, the rule requires that the total number of ram:TaxPointDate elements directly inside any ram:ApplicableTradeTax element is at most one (count(...) <= 1). The message says "Only one TaxPointDate shall be present"; the test accepts zero or one, so the presence of two or more TaxPointDate elements under ApplicableTradeTax causes a fatal validation error.

How to fix

Check the ram:ApplicableHeaderTradeSettlement section for ram:ApplicableTradeTax elements and count their ram:TaxPointDate children. Reduce the total to at most one. In the producing system, ensure that no more than one TaxPointDate is emitted for the trade settlement; if multiple ApplicableTradeTax entries each contain a TaxPointDate, remove all but one or map the data so only a single TaxPointDate is used.

Guidance on this rule. The original text above is authoritative.

CII-SR-461 rule details

Added · 2.1.0

count(ram:ApplicableTradeTax/ram:TaxPointDate) <= 1
CII-SR-462New rule

A new rule limits applicable trade tax to at most one due date type code.

The rule set gains a new rule with the message "Only one DueDateTypeCode shall be present". The test counts occurrences of "DueDateTypeCode" within the applicable trade tax and requires the count to be at most 1. The published 2.0.2 rule set did not include this check.

fatalschema

Original rule text: [CII-SR-462] - Only one DueDateTypeCode shall be present

Explanation and fix

What this rule requires

In CII, the rule allows either no ram:DueDateTypeCode under any ram:ApplicableTradeTax, or exactly one distinct value for all such ram:DueDateTypeCode elements. A document fails when there are at least two ram:DueDateTypeCode elements with different values.

How to fix

Ensure that all ram:DueDateTypeCode elements under ram:ApplicableTradeTax contain the same value, or remove all of them if no due date type code is needed. If multiple different codes are present, change them to the intended single code according to the relevant code list.

Guidance on this rule. The original text above is authoritative.

CII-SR-462 rule details

Added · 2.1.0

count(ram:ApplicableTradeTax/ram:DueDateTypeCode) <= 1
CII-SR-460New rule

New rule limits buyer trade party's "URIUniversalCommunication" to "1".

The rule set now requires that the buyer trade party's "URIUniversalCommunication" element appear at most once. This check was not present in published "2.0.2". The new test counts those elements and requires the count to be no more than "1".

warningschema

Original rule text: [CII-SR-460] - BuyerTradeParty URIUniversalCommunication should exist maximum once

Explanation and fix

What this rule requires

The rule requires that within ram:BuyerTradeParty under ram:ApplicableHeaderTradeAgreement, the element ram:URIUniversalCommunication occurs at most once. An invoice fails if the buyer trade party has more than one ram:URIUniversalCommunication element.

How to fix

Ensure that the ram:BuyerTradeParty element contains no more than one ram:URIUniversalCommunication. Remove any additional occurrences so that only one remains, or none if not needed.

Guidance on this rule. The original text above is authoritative.

CII-SR-460 rule details

Added · 2.1.0

count(ram:BuyerTradeParty/ram:URIUniversalCommunication) <= 1

Which of these catch you depends on your invoices.

The rule diff is the same for everyone — what breaks is not. Upload a corpus once and every subsequent release gets replayed against your own invoices, so you see what breaks for you.