-
Notifications
You must be signed in to change notification settings - Fork 693
Description
Describe the issue
The xRechnung / ZUGFeRD / PEPPOL BIS 3.0 export has two related problems with VAT exemption handling:
Problem 1 – TaxExemptionReason (BT-120) is never exported
The element cbc:TaxExemptionReason (BT-120) is never included in the exported XML, regardless of the Tax Category or VAT setup. This is the human-readable text that explains why VAT is exempt or not charged. Multiple PEPPOL rules require that either BT-120 or BT-121 is present for exempt categories ([BR-E-10], [BR-AE-10], [BR-G-10], [BR-O-10]). While technically only one of the two is mandatory, best practice - and many validators and receiving systems - expect both the code and the textual reason to be present.
Problem 2 – TaxExemptionReasonCode (BT-121) is hard-coded to VATEX-EU-O only
The only scenario where cbc:TaxExemptionReasonCode (BT-121) is exported is for VAT % = 0% ("Not subject to VAT"), and in that case the code is always hard-coded to VATEX-EU-O.
The [PEPPOL VATEX code list] defines dozens of specific exemption reason codes (e.g., VATEX-EU-132-1I for education, VATEX-EU-AE for reverse charge, VATEX-EU-G for export outside the EU, VATEX-EU-IC for intra-community supply, VATEX-EU-D/VATEX-EU-F/VATEX-EU-I/VATEX-EU-J for margin schemes, etc.).
The fix should be straightforward: Business Central already provides both the Tax Category and the VAT Clause Code per line in the VAT Posting Setup. The VAT Clause table holds a Code and a Description. The export should use the VAT Clause Code as cbc:TaxExemptionReasonCode (BT-121) and the VAT Clause Description as cbc:TaxExemptionReason (BT-120), instead of hard-coding only the VATEX-EU-O case.
Expected behavior
When a VAT Posting Setup line has a Tax Category that requires an exemption reason (e.g., E, G, AE, K, O) and a VAT Clause Code is configured, the export should produce:
<cac:TaxCategory>
<cbc:ID>E</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cbc:TaxExemptionReasonCode>VATEX-EU-132-1I</cbc:TaxExemptionReasonCode>
<cbc:TaxExemptionReason>Exempt based on article 132, section 1 (i) of Council Directive 2006/112/EC</cbc:TaxExemptionReason>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>Currently the export produces (for VAT % = 0% only — for other exempt categories neither element is present):
<cac:TaxCategory>
<cbc:ID>O</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cbc:TaxExemptionReasonCode>VATEX-EU-O</cbc:TaxExemptionReasonCode>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>Specifically:
cbc:TaxExemptionReasonCode(BT-121) should be populated from the VAT Clause Code - not hard-coded.cbc:TaxExemptionReason(BT-120) should be populated from the VAT Clause Description.- Both fields should be exported for all Tax Categories that require them (
E,AE,G,K,O) and omitted where they must not appear (S,Zper [BR-Z-10]).
Steps to reproduce
- Use Business Central for Germany.
- Enable E-Document Service for XRechnung (or ZUGFeRD).
- Configure a Workflow and a Document Sending Profile for XRechnung or ZUGFeRD. Mark the sending profile as default and assign it to a Customer.
- Open VAT Posting Setup.
- Find a line with Tax Category = E and VAT % = 0 (e.g., INLAND / OHNE MWST.).
- Set the VAT Clause Code to a valid VATEX code (e.g., create a VAT Clause with Code =
VATEX-EU-132-1Iand Description =Exempt based on article 132, section 1 (i) of Council Directive 2006/112/EC). - Create a new Sales Invoice for the assigned Customer.
- Add a Sales Line using an Item or G/L Account that maps to the VAT Prod. Posting Group from step 5 (so Tax Category
Eapplies). - Post the Sales Invoice.
- Open the Posted Sales Invoice → Related → E-Document → Open E-Document.
- From E-Document Logs, export the XML file.
- Inspect the XML:
- Actual result:
<cbc:TaxExemptionReasonCode>=VATEX-EU-Oand<cbc:TaxExemptionReason>is missing. - Expected result:
<cbc:TaxExemptionReasonCode>=VATEX-EU-132-1I(from VAT Clause Code) and<cbc:TaxExemptionReason>= VAT Clause Description.
- Actual result:
Additional context
The infrastructure is already in place in Business Central: the VAT Posting Setup page exposes both the Tax Category and the VAT Clause Code columns. The VAT Clause table holds Code and Description. The export logic just needs to read the VAT Clause Code and Description and write them into cbc:TaxExemptionReasonCode and cbc:TaxExemptionReason respectively, instead of only handling the hard-coded VATEX-EU-O case.
Relevant PEPPOL BIS Billing 3.0 rules:
- [BR-E-10]: Tax Category E must have BT-121 or BT-120
- [BR-O-10]: Tax Category O must have BT-121 or BT-120
- [BR-AE-10]: Tax Category AE must have BT-121 or BT-120
- [BR-G-10]: Tax Category G must have BT-121 or BT-120
- [BR-CL-22]: TaxExemptionReasonCode must be from the CEF VATEX code list
- [PEPPOL-EN16931-P0104 to P0111]: Restrict allowed Tax Category per VATEX code
- [VATEX code list]
I will provide a fix for a bug
- I will provide a fix for a bug