From faf9974b41372c2d6c7f9267039696d2ce62c599 Mon Sep 17 00:00:00 2001 From: langfr Date: Sat, 1 Nov 2025 15:26:18 +0100 Subject: [PATCH] Adding a tax ExemptionReasonCode to Product. --- .../src/main/java/org/mustangproject/Item.java | 3 +++ .../main/java/org/mustangproject/Product.java | 18 +++++++++++++++++- .../ZUGFeRD/IZUGFeRDExportableProduct.java | 4 ++++ .../ZUGFeRD/ZUGFeRD2PullProvider.java | 3 +++ .../mustangproject/ZUGFeRD/ZF2PushTest.java | 3 ++- 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/library/src/main/java/org/mustangproject/Item.java b/library/src/main/java/org/mustangproject/Item.java index eff70131..5bfc9994 100644 --- a/library/src/main/java/org/mustangproject/Item.java +++ b/library/src/main/java/org/mustangproject/Item.java @@ -189,6 +189,9 @@ public class Item implements IZUGFeRDExportableItem { icnm.getAsNodeMap("ApplicableTradeTax") .flatMap(cnm -> cnm.getAsString("ExemptionReason")) .ifPresent(product::setTaxExemptionReason); + icnm.getAsNodeMap("ApplicableTradeTax") + .flatMap(cnm -> cnm.getAsString("ExemptionReasonCode")) + .ifPresent(product::setTaxExemptionReasonCode); icnm.getAllNodes("SpecifiedTradeAllowanceCharge").map(NodeMap::new).forEach(stac -> { stac.getAsNodeMap("ChargeIndicator").ifPresent(ci -> { diff --git a/library/src/main/java/org/mustangproject/Product.java b/library/src/main/java/org/mustangproject/Product.java index 6aca773a..a7609cbf 100644 --- a/library/src/main/java/org/mustangproject/Product.java +++ b/library/src/main/java/org/mustangproject/Product.java @@ -23,6 +23,7 @@ public class Product implements IZUGFeRDExportableProduct { protected String unit, name, sellerAssignedID, buyerAssignedID; protected String description = ""; protected String taxExemptionReason = null; + protected String taxExemptionReasonCode = null; protected String taxCategoryCode = null; protected BigDecimal VATPercent; protected boolean isReverseCharge = false; @@ -157,7 +158,22 @@ public class Product implements IZUGFeRDExportableProduct { * @return fluent setter */ public Product setTaxExemptionReason(String taxExemptionReasonText) { - taxExemptionReason = taxExemptionReasonText; + this.taxExemptionReason = taxExemptionReasonText; + return this; + } + + @Override + public String getTaxExemptionReasonCode() { + return taxExemptionReasonCode; + } + + /*** + * + * @param taxExemptionReasonCode, https://docs.peppol.eu/poacc/billing/3.0/codelist/vatex/ + * @return fluent setter + */ + public Product setTaxExemptionReasonCode(String taxExemptionReasonCode) { + this.taxExemptionReasonCode = taxExemptionReasonCode; return this; } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java index 6ee5f22e..7c1d53fd 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java @@ -158,6 +158,10 @@ public interface IZUGFeRDExportableProduct { return null; } + default String getTaxExemptionReasonCode() { + return null; + } + default String getCountryOfOrigin() { return null; } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 51da4a63..d3b42a41 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -537,6 +537,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { if (currentItem.getProduct().getTaxExemptionReason() != null) { xml += "" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + ""; } + if (currentItem.getProduct().getTaxExemptionReasonCode() != null) { + xml += "" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReasonCode()) + ""; + } xml += "" + currentItem.getProduct().getTaxCategoryCode() + ""; if (!currentItem.getProduct().getTaxCategoryCode().equals(TaxCategoryCodeTypeConstants.UNTAXEDSERVICE)) { xml += "" + vatFormat(currentItem.getProduct().getVATPercent()) + ""; diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java index c8a4c3bd..d8462ab7 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java @@ -160,7 +160,7 @@ public class ZF2PushTest extends TestCase { .setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE4711") .setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE"))) .setNumber(number) - .addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(0)).setTaxExemptionReason("Kleinunternehmer gemäß §19 UStG").setTaxCategoryCode("E"), price, new BigDecimal(1.0)).addNote(theNote)) + .addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(0)).setTaxExemptionReason("Kleinunternehmer gemäß §19 UStG").setTaxCategoryCode("E").setTaxExemptionReasonCode( "VATEX-EU-I" ), price, new BigDecimal(1.0)).addNote(theNote)) ); String theXML = new String(ze.getProvider().getXML(), StandardCharsets.UTF_8); assertTrue(theXML.contains("