VAT breakdown for O

Error BR-FXEXT-O-01 Factur-X

An Invoice that contains an Invoice line (BG-25) where the "Subtype of invoice line item" (BT-X-8) has the value "DETAIL" or is not specified, a Document level allowance (BG-20) or a Document level charge or tax (BG-21) or a Logistics Service Charge ( BG-X-42) where the VAT category code (BT-151, BT-95, BT-102, or BT-X-273) is “O” ("Not subject to VAT") shall contain in the VAT breakdown (BG-23) at least one VAT category code (BT-118) equal with “O” ("Not subject to VAT").

Mandatory rule: As long as it is violated, the invoice is invalid and will be rejected by validators.
What is wrong

The tax category O appears in the checked tax information, but the VAT breakdown does not include it together with at least one matching tax entry. The check considers ram:ApplicableTradeTax at document level and on invoice lines, as well as ram:CategoryTradeTax and ram:AppliedTradeTax.

What the rule means

O denotes a transaction not subject to VAT. The VAT breakdown must report this tax category so that the invoice presents its VAT treatment consistently.

Please include `O` in the VAT breakdown

The invoice contains information for tax category O, but the corresponding VAT breakdown is not fully matched. You can update the invoice information so the entries correspond.

What to do
  1. For the affected invoice lines, check AssociatedDocument.LineStatusReasonCode; a missing value or DETAIL is considered.
  2. Check the recorded tax categories in TaxCategoryCodes.
  3. Add the corresponding VAT breakdown using AddApplicableTradeTax(...).
  4. Generate the invoice again and validate it again.
What it looks like
✗ Triggers the message
<rsm:CrossIndustryInvoice>
  <ram:ApplicableHeaderTradeSettlement>
    <ram:ApplicableTradeTax>
      <ram:CategoryCode>O</ram:CategoryCode>
    </ram:ApplicableTradeTax>
  </ram:ApplicableHeaderTradeSettlement>
</rsm:CrossIndustryInvoice>
✓ Correct
<rsm:CrossIndustryInvoice>
  <ram:ApplicableHeaderTradeSettlement>
    <ram:ApplicableTradeTax>
      <ram:CategoryCode>O</ram:CategoryCode>
    </ram:ApplicableTradeTax>
  </ram:ApplicableHeaderTradeSettlement>
  <ram:SpecifiedLineTradeSettlement>
    <ram:ApplicableTradeTax>
      <ram:CategoryCode>O</ram:CategoryCode>
    </ram:ApplicableTradeTax>
  </ram:SpecifiedLineTradeSettlement>
</rsm:CrossIndustryInvoice>
Check in FactoorSharp
  • TaxCategoryCodes (BT-151; BT-95; BT-102; BT-118)
  • AssociatedDocument.LineStatusReasonCode (BT-X-8)
  • FacturXInvoice.AddApplicableTradeTax(basisAmount, percent, taxAmount, typeCode, categoryCode, allowanceChargeBasisAmount, exemptionReasonCode, exemptionReason, lineTotalBasisAmount) (BG-23)
  • FacturXInvoice.AnyApplicableTradeTaxes() (BG-23)
  • FacturXInvoice.GetApplicableTradeTaxes() (BG-23)
Technical details

The XPath expression passes if O occurs nowhere in the checked tax information. Otherwise, both a ram:ApplicableTradeTax with O under ram:ApplicableHeaderTradeSettlement and at least one matching entry in the checked line or tax-group elements must be present.

Where the rule applies

The rule applies to the invoice in rsm:CrossIndustryInvoice. It concerns the VAT breakdown in ram:ApplicableHeaderTradeSettlement and matching tax information for invoice lines and other tax groups.

Context (rule/@context)
/rsm:CrossIndustryInvoice
Test expression (assert/@test)
( count(//ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax[ram:CategoryCode='O'])=0 and count(//ram:SpecifiedLineTradeSettlement[ not(ram:AssociatedDocumentLineDocument/ram:LineStatusReasonCode) or ram:AssociatedDocumentLineDocument/ram:LineStatusReasonCode = 'DETAIL' ]/ram:ApplicableTradeTax[ram:CategoryCode='O'])=0 and count(//ram:CategoryTradeTax[ram:CategoryCode='O'])=0 and count(//ram:AppliedTradeTax[ram:CategoryCode='O'])=0 ) or ( count(//ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax[ram:CategoryCode='O'])>=1 and ( exists(//ram:SpecifiedLineTradeSettlement[ not(ram:AssociatedDocumentLineDocument/ram:LineStatusReasonCode) or ram:AssociatedDocumentLineDocument/ram:LineStatusReasonCode = 'DETAIL' ]/ram:ApplicableTradeTax[ram:CategoryCode='O']) or exists(//ram:CategoryTradeTax[ram:CategoryCode='O']) or exists(//ram:AppliedTradeTax[ram:CategoryCode='O']) ) )