From e7e2141c043a9323a3aa8d019a80a03d9b400a1b Mon Sep 17 00:00:00 2001 From: jstaerk Date: Wed, 25 Nov 2020 18:34:48 +0100 Subject: [PATCH 1/6] 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(" Date: Wed, 25 Nov 2020 18:38:32 +0100 Subject: [PATCH 2/6] [maven-release-plugin] prepare release core-2.0.2 --- Mustang-CLI/pom.xml | 6 +++--- library/pom.xml | 6 +++--- pom.xml | 4 ++-- validator/pom.xml | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Mustang-CLI/pom.xml b/Mustang-CLI/pom.xml index 0df1b88d..bad8ef4b 100644 --- a/Mustang-CLI/pom.xml +++ b/Mustang-CLI/pom.xml @@ -3,14 +3,14 @@ org.mustangproject core - 2.0.2-SNAPSHOT + 2.0.2 4.0.0 org.mustangproject Mustang-CLI Mustang commandline tool jar - 2.0.2-SNAPSHOT + 2.0.2 @@ -31,7 +31,7 @@ org.mustangproject validator - 2.0.2-SNAPSHOT + 2.0.2 diff --git a/library/pom.xml b/library/pom.xml index a6e19a95..b782635a 100644 --- a/library/pom.xml +++ b/library/pom.xml @@ -3,13 +3,13 @@ org.mustangproject core - 2.0.2-SNAPSHOT + 2.0.2 4.0.0 org.mustangproject library - 2.0.2-SNAPSHOT + 2.0.2 jar Library to write and read FacturX and ZUGFeRD e-invoices. The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs. To write files, a provided PDF/A will be combined with generated or provided XML. @@ -19,7 +19,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - mustang-2.0.0-SNAPSHOT + core-2.0.2 diff --git a/pom.xml b/pom.xml index 244a3bf0..448d065e 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject core - 2.0.2-SNAPSHOT + 2.0.2 pom Mustang @@ -20,7 +20,7 @@ scm:git:git://github.com/dexecutor/dependent-tasks-executor.git scm:git:git@github.com:dexecutor/dexecutor.git https://github.com/dexecutor/dependent-tasks-executor - HEAD + core-2.0.2 diff --git a/validator/pom.xml b/validator/pom.xml index bd74cd8b..4e1ad0c4 100644 --- a/validator/pom.xml +++ b/validator/pom.xml @@ -3,7 +3,7 @@ org.mustangproject core - 2.0.2-SNAPSHOT + 2.0.2 4.0.0 org.mustangproject @@ -11,7 +11,7 @@ Library to validate e-invoices (ZUGFeRD, Factur-X and Xrechnung) jar - 2.0.2-SNAPSHOT + 2.0.2 @@ -75,7 +75,7 @@ org.mustangproject library - 2.0.2-SNAPSHOT + 2.0.2 org.xmlunit From 2555b82b6adc4d45ad22d92070518677367d6116 Mon Sep 17 00:00:00 2001 From: jstaerk Date: Wed, 25 Nov 2020 18:38:34 +0100 Subject: [PATCH 3/6] [maven-release-plugin] prepare for next development iteration --- Mustang-CLI/pom.xml | 6 +++--- library/pom.xml | 6 +++--- pom.xml | 4 ++-- validator/pom.xml | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Mustang-CLI/pom.xml b/Mustang-CLI/pom.xml index bad8ef4b..c4fd177a 100644 --- a/Mustang-CLI/pom.xml +++ b/Mustang-CLI/pom.xml @@ -3,14 +3,14 @@ org.mustangproject core - 2.0.2 + 2.0.3-SNAPSHOT 4.0.0 org.mustangproject Mustang-CLI Mustang commandline tool jar - 2.0.2 + 2.0.3-SNAPSHOT @@ -31,7 +31,7 @@ org.mustangproject validator - 2.0.2 + 2.0.3-SNAPSHOT diff --git a/library/pom.xml b/library/pom.xml index b782635a..fe73205a 100644 --- a/library/pom.xml +++ b/library/pom.xml @@ -3,13 +3,13 @@ org.mustangproject core - 2.0.2 + 2.0.3-SNAPSHOT 4.0.0 org.mustangproject library - 2.0.2 + 2.0.3-SNAPSHOT jar Library to write and read FacturX and ZUGFeRD e-invoices. The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs. To write files, a provided PDF/A will be combined with generated or provided XML. @@ -19,7 +19,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - core-2.0.2 + mustang-2.0.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index 448d065e..1769dd20 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject core - 2.0.2 + 2.0.3-SNAPSHOT pom Mustang @@ -20,7 +20,7 @@ scm:git:git://github.com/dexecutor/dependent-tasks-executor.git scm:git:git@github.com:dexecutor/dexecutor.git https://github.com/dexecutor/dependent-tasks-executor - core-2.0.2 + HEAD diff --git a/validator/pom.xml b/validator/pom.xml index 4e1ad0c4..0868f732 100644 --- a/validator/pom.xml +++ b/validator/pom.xml @@ -3,7 +3,7 @@ org.mustangproject core - 2.0.2 + 2.0.3-SNAPSHOT 4.0.0 org.mustangproject @@ -11,7 +11,7 @@ Library to validate e-invoices (ZUGFeRD, Factur-X and Xrechnung) jar - 2.0.2 + 2.0.3-SNAPSHOT @@ -75,7 +75,7 @@ org.mustangproject library - 2.0.2 + 2.0.3-SNAPSHOT org.xmlunit From 2d4408902c4bd07d2ab9c0f3a144481f740f2e35 Mon Sep 17 00:00:00 2001 From: jstaerk Date: Wed, 25 Nov 2020 18:50:39 +0100 Subject: [PATCH 4/6] v 2.0.2 --- History.md | 2 ++ doc/development_documentation.md | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/History.md b/History.md index 9625ce75..838ba158 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,7 @@ 2.0.2 ======= +2020-11-25 + - #197 file attachments - Charges/Allowances CategoryCode improvement PR #198 Thanks to weclapp-dev - support reverse charge diff --git a/doc/development_documentation.md b/doc/development_documentation.md index afe475c1..6dc8c7a9 100644 --- a/doc/development_documentation.md +++ b/doc/development_documentation.md @@ -171,7 +171,6 @@ Change to the project directory and run * clean the release with `mvn release:clean` and prepare the release with * `mvn release:prepare -DignoreSnapshots=true` and enter the version numbers. * After that is through you can create a new release via `mvn release:perform -Dmaven.java.skip=True`.This will also update the maven repo. - * Experimental: mvn deploy -Dregistry=https://maven.pkg.github.com/ZUGFeRD -Dtoken=GH_TOKEN ![screenshot](development_documentation_screenshot_release.png "Screenshot Release") From d764fb4784ff1800f89be6bfd5204ac84d98bc82 Mon Sep 17 00:00:00 2001 From: jstaerk Date: Thu, 26 Nov 2020 09:39:47 +0100 Subject: [PATCH 5/6] closes #201 --- History.md | 6 +++ .../main/java/org/mustangproject/Invoice.java | 17 +++++++ .../ZUGFeRD/ZUGFeRD2PullProvider.java | 2 +- .../org/mustangproject/ZUGFeRD/XRTest.java | 44 +++++++++++++++++++ .../mustangproject/ZUGFeRD/ZF2PushTest.java | 4 +- .../mustangproject/validator/LibraryTest.java | 2 +- 6 files changed, 71 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index 838ba158..fa2e51df 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +2.0.3 +======= + + +- #201 correct embedded files in XRechnung + 2.0.2 ======= 2020-11-25 diff --git a/library/src/main/java/org/mustangproject/Invoice.java b/library/src/main/java/org/mustangproject/Invoice.java index 68c49339..1d0c121f 100644 --- a/library/src/main/java/org/mustangproject/Invoice.java +++ b/library/src/main/java/org/mustangproject/Invoice.java @@ -40,6 +40,7 @@ public class Invoice implements IExportableTransaction { protected ArrayList ZFItems = null; protected ArrayList notes = null; protected String contractReferencedDocument = null; + protected ArrayList xmlEmbeddedFiles=null; protected Date detailedDeliveryDateStart = null; protected Date detailedDeliveryPeriodEnd = null; @@ -78,6 +79,22 @@ public class Invoice implements IExportableTransaction { return this; } + public Invoice embedFileInXML(FileAttachment fa) { + if (xmlEmbeddedFiles == null) { + xmlEmbeddedFiles=new ArrayList(); + } + xmlEmbeddedFiles.add(fa); + return this; + } + + public FileAttachment[] getAdditionalReferencedDocuments() { + if (xmlEmbeddedFiles == null) { + return null; + } + return xmlEmbeddedFiles.toArray(new FileAttachment[0]); + + } + @Override public String getNumber() { diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index f31176df..54d1c169 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -442,7 +442,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { + " 916\n" + " " + f.getDescription() + "\n" + " " + documentContent + "\n" + + " filename=\"" + f.getFilename() + "\">" + documentContent + "\n" + " \n"; } } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/XRTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/XRTest.java index 6166dd51..ac94775d 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/XRTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/XRTest.java @@ -39,6 +39,7 @@ import static org.xmlunit.assertj.XmlAssert.assertThat; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class XRTest extends TestCase { final String TARGET_XML = "./target/testout-XR.xml"; + final String TARGET_EDGE_XML = "./target/testout-XR-Edge.xml"; public void testXRExport() { // the writing part @@ -76,5 +77,48 @@ public class XRTest extends TestCase { } } + public void testXREdgeExport() { + + // the writing part + + String orgname = "Test company"; + String number = "123"; + String amountStr = "1.00"; + BigDecimal amount = new BigDecimal(amountStr); + byte[] b = {12, 13}; + FileAttachment fe1=new FileAttachment("one.pdf", "application/pdf", "Alternative", b); + FileAttachment fe2=new FileAttachment("two.pdf", "application/pdf", "Alternative", b); + Invoice i = new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()) + .setSender(new TradeParty(orgname,"teststr","55232","teststadt","DE").addTaxID("DE4711").addVATID("DE0815").setContact(new Contact("Hans Test","+49123456789","test@example.org")).addBankDetails(new BankDetails("DE12500105170648489890","COBADEFXXX"))) + .setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")) + .setReferenceNumber("991-01484-64")//leitweg-id + // not using any VAT, this is also a test of zero-rated goods: + .setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", BigDecimal.ZERO), amount, new BigDecimal(1.0))) + .embedFileInXML(fe1).embedFileInXML(fe2); + + + ZUGFeRD2PullProvider zf2p = new ZUGFeRD2PullProvider(); + + zf2p.setProfile(Profiles.getByName("XRechnung")); + zf2p.generateXML(i); + String theXML = new String(zf2p.getXML()); + assertTrue(theXML.contains(" Date: Thu, 26 Nov 2020 10:52:32 +0100 Subject: [PATCH 6/6] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c39a9eee..bcea4a64 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ If you setup a Maven project, you can grab the artifacts using org.mustangproject library - 2.0.0 + 2.0.2 ```