From e7e2141c043a9323a3aa8d019a80a03d9b400a1b Mon Sep 17 00:00:00 2001 From: jstaerk Date: Wed, 25 Nov 2020 18:34:48 +0100 Subject: [PATCH] support reverse charge --- History.md | 2 + .../main/java/org/mustangproject/Product.java | 33 ++++++ .../ZUGFeRD/IZUGFeRDExportableProduct.java | 15 ++- .../mustangproject/ZUGFeRD/ZF2PushTest.java | 104 ++++++++++++++++++ 4 files changed, 151 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 1a5f7fc3..9625ce75 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,8 @@ ======= - #197 file attachments - Charges/Allowances CategoryCode improvement PR #198 Thanks to weclapp-dev +- support reverse charge +- support intra community supply also in product class, not only interface 2.0.1 ===== diff --git a/library/src/main/java/org/mustangproject/Product.java b/library/src/main/java/org/mustangproject/Product.java index 241e82d8..29d15c78 100644 --- a/library/src/main/java/org/mustangproject/Product.java +++ b/library/src/main/java/org/mustangproject/Product.java @@ -10,6 +10,8 @@ import java.math.BigDecimal; public class Product implements IZUGFeRDExportableProduct { protected String unit, name, description, sellerAssignedID, buyerAssignedID; protected BigDecimal VATPercent; + protected boolean isReverseCharge=false; + protected boolean isIntraCommunitySupply=false; /*** * default constructor @@ -54,6 +56,37 @@ public class Product implements IZUGFeRDExportableProduct { return this; } + @Override + public boolean isReverseCharge() { + return isReverseCharge; + } + + @Override + public boolean isIntraCommunitySupply() { + return isIntraCommunitySupply; + } + + /*** + * sets reverse charge(=delivery to outside EU) + * @return fluent setter + */ + public Product setReverseCharge() { + isReverseCharge=true; + setVATPercent(BigDecimal.ZERO); + return this; + } + + + /*** + * sets intra community supply(=delivery outside the country inside the EU) + * @return fluent setter + */ + public Product setIntraCommunitySupply() { + isIntraCommunitySupply=true; + setVATPercent(BigDecimal.ZERO); + return this; + } + @Override public String getUnit() { return unit; diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java index 55af8ee1..efab767d 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java @@ -108,10 +108,16 @@ public interface IZUGFeRDExportableProduct { return false; } + default boolean isReverseCharge() { + return false; + } + default String getTaxCategoryCode() { if (isIntraCommunitySupply()) { - return "K"; - } else if (getVATPercent().equals(new BigDecimal(0))) { + return "K"; // within europe + } else if (isReverseCharge()) { + return "AE"; // to out of europe... + } else if (getVATPercent().equals(BigDecimal.ZERO)) { return "Z"; // zero rated goods } else { return "S"; // one of the "standard" rates (not neccessarily a default rate, even a deducted VAT is standard calculation) @@ -119,8 +125,11 @@ public interface IZUGFeRDExportableProduct { } default String getTaxExemptionReason() { - if (isIntraCommunitySupply()) + if (isIntraCommunitySupply()) { return "Intra-community supply"; + } else if (isReverseCharge()) { + return "Reverse Charge"; + } return null; } } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java index 89e96242..fb41990a 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java @@ -45,6 +45,8 @@ public class ZF2PushTest extends TestCase { final String TARGET_RELATIVECHARGESALLOWANCESPDF = "./target/testout-ZF2PushRelativeChargesAllowances.pdf"; final String TARGET_ATTACHMENTSPDF = "./target/testout-ZF2PushAttachments.pdf"; final String TARGET_PUSHEDGE = "./target/testout-ZF2PushEdge.pdf"; + final String TARGET_INTRACOMMUNITYSUPPLYPDF = "./target/testout-ZF2PushIntraCommunitySupply.pdf"; + final String TARGET_REVERSECHARGEPDF = "./target/testout-ZF2PushReverseCharge.pdf"; public void testPushExport() { @@ -198,6 +200,108 @@ public class ZF2PushTest extends TestCase { } + + public void testIntraCommunitySupplyExport() { + + String orgname = "Test company"; + String number = "123"; + String amountStr = "3.00"; + BigDecimal amount = new BigDecimal(amountStr); + try (InputStream SOURCE_PDF = this.getClass() + .getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); + + ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application") + .setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile("extended").ignorePDFAErrors() + .load(SOURCE_PDF)) { + // ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname,"teststr", "55232","teststadt","DE")).setOwnTaxID("4711").setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number) + // .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50))))); + + + ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()) + .setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addVATID("DE0815")).setOwnTaxID("4711") + .setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0816").setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562"))) + .setDeliveryAddress(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0816")) + .setNumber(number) + .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setIntraCommunitySupply(), amount, new BigDecimal(1.0))) + .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setIntraCommunitySupply(), amount, new BigDecimal(1.0))) + .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setIntraCommunitySupply(), amount, new BigDecimal(2.0))) + .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setIntraCommunitySupply(), amount, new BigDecimal(1.0))) + ); + + String theXML = new String(ze.getProvider().getXML()); + assertTrue(theXML.contains("