diff --git a/History.md b/History.md index 62eeec43..13b1c573 100644 --- a/History.md +++ b/History.md @@ -1,8 +1,14 @@ + +2.15.2 +======= +2024-12-19 - correcly write charge reason codes also for non-Xrechnung #617 - correctly import additional referenced documents into invoice/corrected setting of attachments from jackson - corrected parseException structure - allow 1p0 as potential xmp version number - #618 import BT-20 +- #599 add tax category code for free export +- #600 Fixes a problem where a stream was not safely closed 2.15.1 ======= diff --git a/Mustang-CLI/pom.xml b/Mustang-CLI/pom.xml index 89e9f5fc..915cbc08 100644 --- a/Mustang-CLI/pom.xml +++ b/Mustang-CLI/pom.xml @@ -3,7 +3,7 @@ org.mustangproject core - 2.15.2-SNAPSHOT + 2.15.3-SNAPSHOT 4.0.0 org.mustangproject @@ -12,7 +12,7 @@ should also work for XRechnung/CII. jar - 2.15.2-SNAPSHOT + 2.15.3-SNAPSHOT UTF-8 11 @@ -23,7 +23,7 @@ org.mustangproject validator - 2.15.2-SNAPSHOT + 2.15.3-SNAPSHOT diff --git a/library/pom.xml b/library/pom.xml index 2c6a1284..073661c1 100644 --- a/library/pom.xml +++ b/library/pom.xml @@ -3,13 +3,13 @@ org.mustangproject core - 2.15.2-SNAPSHOT + 2.15.3-SNAPSHOT 4.0.0 org.mustangproject library - 2.15.2-SNAPSHOT + 2.15.3-SNAPSHOT jar Library to write, read and validate e-invoices (Factur-X, ZUGFeRD, Order-X, XRechnung/CII) FOSS Java library to read, write and validate european electronic invoices and orders in the UN/CEFACT @@ -200,21 +200,51 @@ - FreeSans.ttf + SourceSansPro-Regular.ttf font/ttf - FreeSerif.ttf + SourceSansPro-It.ttf - application/x-font + font/ttf - Times-Bold.ttf + SourceSansPro-Bold.ttf - application/x-font + font/ttf + + + + SourceSansPro-BoldIt.ttf + + font/ttf + + + + SourceSerifPro-Regular.ttf + + font/ttf + + + + SourceSerifPro-It.ttf + + font/ttf + + + + SourceSerifPro-Bold.ttf + + font/ttf + + + + SourceSerifPro-BoldIt.ttf + + font/ttf diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromPDFA.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromPDFA.java index 498ae7dc..c3b9299b 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromPDFA.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromPDFA.java @@ -83,8 +83,9 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter { } protected byte[] filenameToByteArray(String pdfFilename) throws IOException { - FileInputStream fileInputStream = new FileInputStream(pdfFilename); - return inputstreamToByteArray(fileInputStream); + try (FileInputStream fileInputStream = new FileInputStream(pdfFilename)) { + return inputstreamToByteArray(fileInputStream); + } } protected byte[] inputstreamToByteArray(InputStream fileInputStream) throws IOException { diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index 5189bee6..6ff0a4b8 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -659,6 +659,7 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter { * * @return a List of LineItem instances */ + @Deprecated public List getLineItemList() { final List nodeList = getLineItemNodes(); final List lineItemList = new ArrayList<>(); diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java index da10d8dd..ceda9530 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java @@ -1036,6 +1036,7 @@ public class ZUGFeRDInvoiceImporter { * for PDF embedded files in FX use getFileAttachmentsPDF() * @deprecated use invoice.getAdditionalReferencedDocuments */ + @Deprecated public List getFileAttachmentsXML() { return new ArrayList<>(Arrays.asList(importedInvoice.getAdditionalReferencedDocuments())); } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/model/TaxCategoryCodeTypeConstants.java b/library/src/main/java/org/mustangproject/ZUGFeRD/model/TaxCategoryCodeTypeConstants.java index c400cbbc..c9ecc2a0 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/model/TaxCategoryCodeTypeConstants.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/model/TaxCategoryCodeTypeConstants.java @@ -29,6 +29,7 @@ public class TaxCategoryCodeTypeConstants { public static final String ZEROTAXPRODUCTS = "Z"; public static final String UNTAXEDSERVICE = "O"; public static final String INTRACOMMUNITY = "K"; - - public static Set CATEGORY_CODES_WITH_EXEMPTION_REASON = Stream.of(INTRACOMMUNITY, REVERSECHARGE, TAXEXEMPT).collect(Collectors.toSet()); + public static final String FREEEXPORT = "G"; + + public static Set CATEGORY_CODES_WITH_EXEMPTION_REASON = Stream.of(INTRACOMMUNITY, REVERSECHARGE, TAXEXEMPT, FREEEXPORT).collect(Collectors.toSet()); } diff --git a/library/src/main/resources/fonts/SourceSansPro-Bold.ttf b/library/src/main/resources/fonts/SourceSansPro-Bold.ttf new file mode 100644 index 00000000..a253fdc2 Binary files /dev/null and b/library/src/main/resources/fonts/SourceSansPro-Bold.ttf differ diff --git a/library/src/main/resources/fonts/SourceSansPro-BoldIt.ttf b/library/src/main/resources/fonts/SourceSansPro-BoldIt.ttf new file mode 100644 index 00000000..61505f23 Binary files /dev/null and b/library/src/main/resources/fonts/SourceSansPro-BoldIt.ttf differ diff --git a/library/src/main/resources/fonts/SourceSansPro-It.ttf b/library/src/main/resources/fonts/SourceSansPro-It.ttf new file mode 100644 index 00000000..51e63421 Binary files /dev/null and b/library/src/main/resources/fonts/SourceSansPro-It.ttf differ diff --git a/library/src/main/resources/fonts/SourceSansPro-Regular.ttf b/library/src/main/resources/fonts/SourceSansPro-Regular.ttf new file mode 100644 index 00000000..d9344ce8 Binary files /dev/null and b/library/src/main/resources/fonts/SourceSansPro-Regular.ttf differ diff --git a/library/src/main/resources/fonts/SourceSerifPro-Bold.ttf b/library/src/main/resources/fonts/SourceSerifPro-Bold.ttf new file mode 100644 index 00000000..5814a6a0 Binary files /dev/null and b/library/src/main/resources/fonts/SourceSerifPro-Bold.ttf differ diff --git a/library/src/main/resources/fonts/SourceSerifPro-BoldIt.ttf b/library/src/main/resources/fonts/SourceSerifPro-BoldIt.ttf new file mode 100644 index 00000000..8a23518c Binary files /dev/null and b/library/src/main/resources/fonts/SourceSerifPro-BoldIt.ttf differ diff --git a/library/src/main/resources/fonts/SourceSerifPro-It.ttf b/library/src/main/resources/fonts/SourceSerifPro-It.ttf new file mode 100644 index 00000000..be263bee Binary files /dev/null and b/library/src/main/resources/fonts/SourceSerifPro-It.ttf differ diff --git a/library/src/main/resources/fonts/SourceSerifPro-Regular.ttf b/library/src/main/resources/fonts/SourceSerifPro-Regular.ttf new file mode 100644 index 00000000..0a05b4dc Binary files /dev/null and b/library/src/main/resources/fonts/SourceSerifPro-Regular.ttf differ diff --git a/library/src/main/resources/fop-config.xconf b/library/src/main/resources/fop-config.xconf index cf01edd3..4d93f97e 100644 --- a/library/src/main/resources/fop-config.xconf +++ b/library/src/main/resources/fop-config.xconf @@ -1,37 +1,57 @@ - - - - true - - - true - - - - - - - 96 - - 96 - - - - - - - - - - - - - - - - classpath:AdobeCompat-v2.icc - - - - + + + + true + + + true + + + + + + + 96 + + 96 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + classpath:AdobeCompat-v2.icc + + + diff --git a/library/src/main/resources/stylesheets/xr-pdf/lib/konstanten.xsl b/library/src/main/resources/stylesheets/xr-pdf/lib/konstanten.xsl index de3b5459..bcd846da 100644 --- a/library/src/main/resources/stylesheets/xr-pdf/lib/konstanten.xsl +++ b/library/src/main/resources/stylesheets/xr-pdf/lib/konstanten.xsl @@ -1,235 +1,235 @@ - - - - - - SourceSerifPro - SourceSerifPro - - - - - - - - - - - 9pt - 12pt - 3 - true - de - - - - - 18pt - - false - all - - - - - 18pt - - bold - 4mm - false - all - always - - - - - 0.5pt solid - 2.5pt - all - 4mm - always - - - - - 9pt - - bold - 0.5pt solid - 4pt 6pt - always - 0 - - - - - 10pt - - bold - 1mm - 2mm - 2mm - all - always - - - - - 2mm - 3mm - 0.5pt dotted - #999999 - always - - - - #eeeeee - 28 - - - 7pt - 10pt - 1mm - 1mm - 2mm - 1mm - - - - 9pt - 10pt - - 1mm - 1mm - 2mm - 2mm - always - - - - - 9pt - left - 0.2mm - 0.2mm - 0mm - 1mm - 0mm - always - - - - 9pt - left - 0.2mm - 0.2mm - 0mm - 1mm - 0mm - always - - - - 9pt - right - 0.2mm - 0.2mm - 0mm - 0mm - 0mm - always - - - - 9pt - left - 0.4mm - 0.2mm - 0mm - 1mm - 0.1pt solid #999999 - always - - - - 9pt - left - 0.4mm - 0.2mm - 0mm - 1mm - 0.1pt solid #999999 - always - - - - 9pt - bold - right - 0.4mm - 0.2mm - 0mm - 0mm - 0.1pt solid #999999 - always - - - - - 10mm - - - - 2mm - always - all - - - - 2mm - - - - - 2pt - 2pt - 100% - fixed - 2mm - - - - bold - - - - - - - - - 80% - italic - - - - 2pt - 2pt - 100% - fixed - 80% - italic - - - \ No newline at end of file + + + + + + SourceSansPro + SourceSerifPro + + + + + + + + + + + 9pt + 12pt + 3 + true + de + + + + + 18pt + + false + all + + + + + 18pt + + bold + 4mm + false + all + always + + + + + 0.5pt solid + 2.5pt + all + 4mm + always + + + + + 9pt + + bold + 0.5pt solid + 4pt 6pt + always + 0 + + + + + 10pt + + bold + 1mm + 2mm + 2mm + all + always + + + + + 2mm + 3mm + 0.5pt dotted + #999999 + always + + + + #eeeeee + 28 + + + 7pt + 10pt + 1mm + 1mm + 2mm + 1mm + + + + 9pt + 10pt + + 1mm + 1mm + 2mm + 2mm + always + + + + + 9pt + left + 0.2mm + 0.2mm + 0mm + 1mm + 0mm + always + + + + 9pt + left + 0.2mm + 0.2mm + 0mm + 1mm + 0mm + always + + + + 9pt + right + 0.2mm + 0.2mm + 0mm + 0mm + 0mm + always + + + + 9pt + left + 0.4mm + 0.2mm + 0mm + 1mm + 0.1pt solid #999999 + always + + + + 9pt + left + 0.4mm + 0.2mm + 0mm + 1mm + 0.1pt solid #999999 + always + + + + 9pt + bold + right + 0.4mm + 0.2mm + 0mm + 0mm + 0.1pt solid #999999 + always + + + + + 10mm + + + + 2mm + always + all + + + + 2mm + + + + + 2pt + 2pt + 100% + fixed + 2mm + + + + bold + + + + + + + + + 80% + italic + + + + 2pt + 2pt + 100% + fixed + 80% + italic + + + diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/DeSerializationTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/DeSerializationTest.java index f2d16980..746e7cbb 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/DeSerializationTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/DeSerializationTest.java @@ -166,11 +166,123 @@ public class DeSerializationTest extends ResourceCase { } + public void testDeserializedFiles() { + File inputUBL = getResourceAsFile("XRECHNUNG_Elektron.ubl.xml"); + ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(); + zii.doIgnoreCalculationErrors(); + Invoice i = new Invoice(); + String exText = null; + + try { + zii.fromXML(new String(Files.readAllBytes(inputUBL.toPath()), StandardCharsets.UTF_8)); + ObjectMapper mapper = new ObjectMapper(); + zii.extractInto(i); + String json = mapper.writeValueAsString(i); + Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class); + + assertEquals("181301674", i.getNumber()); + assertEquals(newInvoiceFromJSON.getNumber(), i.getNumber()); + assertEquals(newInvoiceFromJSON.getAdditionalReferencedDocuments()[0].getFilename(), i.getAdditionalReferencedDocuments()[0].getFilename()); + assertEquals(newInvoiceFromJSON.getAdditionalReferencedDocuments().length, 2); + + + } catch (IOException e) { + exText = e.getMessage(); + } catch (XPathExpressionException e) { + exText = e.getMessage(); + } catch (ParseException e) { + exText = e.getMessage(); + } + assertNull(exText); + + } + + public void testFileSerialization() { + + String base64 = "b25ldHdvdGhyZWU="; + String json = "{\n" + + " \"additionalReferencedDocuments\": [\n" + + " {\n" + + " \"data\": \"" + base64 + "\",\n" + + " \"description\": \"Additional file attachment\",\n" + + " \"filename\": \"text.txt\",\n" + + " \"mimetype\": \"text/plain\",\n" + + " \"relation\": \"Data\"\n" + + " }\n" + + "],\n" + + "\n" + + " \"number\": \"471102\",\n" + + " \"currency\": \"EUR\",\n" + + " \"issueDate\": \"2018-03-04T00:00:00.000+01:00\",\n" + + " \"dueDate\": \"2018-03-04T00:00:00.000+01:00\",\n" + + " \"deliveryDate\": \"2018-03-04T00:00:00.000+01:00\",\n" + + " \"sender\": {\n" + + " \"name\": \"Lieferant GmbH\",\n" + + " \"zip\": \"80333\",\n" + + " \"street\": \"Lieferantenstraße 20\",\n" + + " \"location\": \"München\",\n" + + " \"country\": \"DE\",\n" + + " \"taxID\": \"201/113/40209\",\n" + + " \"vatID\": \"DE123456789\",\n" + + " \"globalID\": \"4000001123452\",\n" + + " \"globalIDScheme\": \"0088\"\n" + + " },\n" + + " \"recipient\": {\n" + + " \"name\": \"Kunden AG Mitte\",\n" + + " \"zip\": \"69876\",\n" + + " \"street\": \"Kundenstraße 15\",\n" + + " \"location\": \"Frankfurt\",\n" + + " \"country\": \"DE\"\n" + + " },\n" + + " \"zfitems\": [\n" + + " {\n" + + " \"price\": 9.9,\n" + + " \"quantity\": 20,\n" + + " \"product\": {\n" + + " \"unit\": \"H87\",\n" + + " \"name\": \"Trennblätter A4\",\n" + + " \"description\": \"\",\n" + + " \"vatpercent\": 19,\n" + + " \"taxCategoryCode\": \"S\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"price\": 5.5,\n" + + " \"quantity\": 50,\n" + + " \"product\": {\n" + + " \"unit\": \"H87\",\n" + + " \"name\": \"Joghurt Banane\",\n" + + " \"description\": \"\",\n" + + " \"vatpercent\": 7,\n" + + " \"taxCategoryCode\": \"S\"\n" + + " }\n" + + " }\n" + + " ]\n" + + "}\n"; + + ObjectMapper mapper = new ObjectMapper(); + + try { + Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class); + ZUGFeRD2PullProvider zf2p = new ZUGFeRD2PullProvider(); + zf2p.setProfile(Profiles.getByName("XRechnung")); + zf2p.generateXML(newInvoiceFromJSON); + String theXML = new String(zf2p.getXML()); + assertTrue(theXML.contains("20180304")); + assertTrue(theXML.contains(base64)); + + } catch (Exception e) { + fail("No exception expected"); + } + + } + + public void testFull300Roundtrip() { File inputCII = getResourceAsFile("not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.cii.xml"); - Invoice i=new Invoice(); - String exText=null; + Invoice i = new Invoice(); + String exText = null; ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(); zii.doIgnoreCalculationErrors(); try { @@ -180,15 +292,15 @@ public class DeSerializationTest extends ResourceCase { String json = mapper.writeValueAsString(i); Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class); - assertEquals("Test_EeISI_100",i.getNumber()); - assertEquals(newInvoiceFromJSON.getNumber(),i.getNumber()); + assertEquals("Test_EeISI_100", i.getNumber()); + assertEquals(newInvoiceFromJSON.getNumber(), i.getNumber()); } catch (IOException e) { - exText=e.getMessage(); + exText = e.getMessage(); } catch (XPathExpressionException e) { - exText=e.getMessage(); + exText = e.getMessage(); } catch (ParseException e) { - exText=e.getMessage(); + exText = e.getMessage(); } assertNull(exText); diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/VisualizationTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/VisualizationTest.java index caef3ee9..88c4fccf 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/VisualizationTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/VisualizationTest.java @@ -1,169 +1,171 @@ -/** - * ********************************************************************* - *

- * Copyright 2019 Jochen Staerk - *

- * Use is subject to license terms. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0. - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - *

- * See the License for the specific language governing permissions and - * limitations under the License. - *

- * ********************************************************************** - */ -package org.mustangproject.ZUGFeRD; - -import org.junit.FixMethodOrder; -import org.junit.runners.MethodSorters; -import org.mustangproject.ZUGFeRD.ZUGFeRDVisualizer.Language; -import org.mustangproject.util.ByteArraySearcher; - -import javax.xml.transform.TransformerException; -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class VisualizationTest extends ResourceCase { - - final String TARGET_PDF_CII = "./target/testout-Visualization-cii.pdf"; - final String TARGET_PDF_UBL = "./target/testout-Visualization-cii.pdf"; - - public void testCIIVisualizationBasic() { - this.runZUGFeRDVisualization("factur-x.xml", "factur-x-vis.fr.html", Language.FR); - } - - public void testCIIVisualizationExtended() { - this.runZUGFeRDVisualization("factur-x-extended.xml", "factur-x-vis-extended.de.html", Language.DE); - } - - public void testUBLCreditNoteVisualizationBasic() { - this.runZUGFeRDVisualization("ubl-creditnote.xml", "factur-x-vis-ubl-creditnote.en.html", Language.EN); - } - - public void testUBLVisualizationBasic() { - this.runZUGFeRDVisualization("ubl/01.01a-INVOICE.ubl.xml", "factur-x-vis-ubl.en.html", Language.EN); - } - - private void runZUGFeRDVisualization(String inputFilename, String resultFileName, Language lang) { - File CIIinputFile = getResourceAsFile(inputFilename); - - String expected = null; - String result = null; - try { - ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer(); - result = zvi.visualize(CIIinputFile.getAbsolutePath(), lang); - - File expectedResult = getResourceAsFile(resultFileName); - expected = new String(Files.readAllBytes(expectedResult.toPath()), StandardCharsets.UTF_8); - - } catch (UnsupportedOperationException e) { - fail("UnsupportedOperationException should not happen: " + e.getMessage()); - } catch (IllegalArgumentException e) { - fail("IllegalArgumentException should not happen: " + e.getMessage()); - } catch (TransformerException e) { - fail("TransformerException should not happen: " + e.getMessage()); - } catch (IOException e) { - fail("IOException should not happen: " + e.getMessage()); - } - - - assertNotNull(result); - /* remove file endings so that tests can also pass after checking - out from git with arbitrary options (which may include CSRF changes) - */ - assertEquals(expected.replace("\r", "") - .replace("\n", "") - .replace("\t", "") - .replace(" ", ""), result.replace("\r", "") - .replace("\n", "") - .replace("\t", "") - .replace(" ", "")); - } - - public void testPDFVisualizationCII() { - - File CIIinputFile = getResourceAsFile("cii/01.01a-INVOICE.cii.xml"); - - // the writing part - - String expected = null; - String result = null; - try { - ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer(); - zvi.toPDF(CIIinputFile.getAbsolutePath(), TARGET_PDF_CII); - } catch (UnsupportedOperationException e) { - fail("UnsupportedOperationException should not happen: " + e.getMessage()); - } catch (IllegalArgumentException e) { - fail("IllegalArgumentException should not happen: " + e.getMessage()); - } - - try { - assertTrue(ByteArraySearcher.startsWith(Files.readAllBytes(Paths.get(TARGET_PDF_CII)), new byte[]{'%', 'P', 'D', 'F'})); - } catch (IOException e) { - fail("IOException should not occur"); - } - } - - public void testPDFVisualizationUBL() { - - File UBLinputFile = getResourceAsFile("ubl/01.01a-INVOICE.ubl.xml"); - - // the writing part - String sourceFilename = "factur-x.xml"; - - String expected = null; - String result = null; - try { - ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer(); - zvi.toPDF(UBLinputFile.getAbsolutePath(), TARGET_PDF_UBL); - } catch (UnsupportedOperationException e) { - fail("UnsupportedOperationException should not happen: " + e.getMessage()); - } catch (IllegalArgumentException e) { - fail("IllegalArgumentException should not happen: " + e.getMessage()); - } - - - try { - assertTrue(ByteArraySearcher.startsWith(Files.readAllBytes(Paths.get(TARGET_PDF_CII)), new byte[]{'%', 'P', 'D', 'F'})); - } catch (IOException e) { - fail("IOException should not occur"); - } - } - - public void testPDFVisualizationUBLCreditNote() { - - File UBLinputFile = getResourceAsFile("ubl/UBL-CreditNote-2.1-Example.ubl.xml"); - - // the writing part - String sourceFilename = "factur-x.xml"; - - String expected = null; - String result = null; - try { - ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer(); - zvi.toPDF(UBLinputFile.getAbsolutePath(), TARGET_PDF_UBL); - } catch (UnsupportedOperationException e) { - fail("UnsupportedOperationException should not happen: " + e.getMessage()); - } catch (IllegalArgumentException e) { - fail("IllegalArgumentException should not happen: " + e.getMessage()); - } - - - try { - assertTrue(ByteArraySearcher.startsWith(Files.readAllBytes(Paths.get(TARGET_PDF_CII)), new byte[]{'%', 'P', 'D', 'F'})); - } catch (IOException e) { - fail("IOException should not occur"); - } - } - -} +/** + * ********************************************************************* + *

+ * Copyright 2019 Jochen Staerk + *

+ * Use is subject to license terms. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0. + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *

+ * See the License for the specific language governing permissions and + * limitations under the License. + *

+ * ********************************************************************** + */ +package org.mustangproject.ZUGFeRD; + +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import org.mustangproject.ZUGFeRD.ZUGFeRDVisualizer.Language; +import org.mustangproject.util.ByteArraySearcher; + +import javax.xml.transform.TransformerException; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class VisualizationTest extends ResourceCase { + + final String TARGET_PDF_CII = "./target/testout-Visualization-cii.pdf"; + final String TARGET_PDF_UBL = "./target/testout-Visualization-cii.pdf"; + + public void testCIIVisualizationBasic() { + this.runZUGFeRDVisualization("factur-x.xml", "factur-x-vis.fr.html", Language.FR); + } + + public void testCIIVisualizationExtended() { + this.runZUGFeRDVisualization("factur-x-extended.xml", "factur-x-vis-extended.de.html", Language.DE); + } + + public void testUBLCreditNoteVisualizationBasic() { + this.runZUGFeRDVisualization("ubl-creditnote.xml", "factur-x-vis-ubl-creditnote.en.html", Language.EN); + } + + public void testUBLVisualizationBasic() { + this.runZUGFeRDVisualization("ubl/01.01a-INVOICE.ubl.xml", "factur-x-vis-ubl.en.html", Language.EN); + } + + private void runZUGFeRDVisualization(String inputFilename, String resultFileName, Language lang) { + File CIIinputFile = getResourceAsFile(inputFilename); + + String expected = null; + String result = null; + try { + ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer(); + result = zvi.visualize(CIIinputFile.getAbsolutePath(), lang); + Files.write(Paths.get("./target/testout-" + resultFileName), result.getBytes(StandardCharsets.UTF_8)); + + File expectedResult = getResourceAsFile(resultFileName); + expected = new String(Files.readAllBytes(expectedResult.toPath()), StandardCharsets.UTF_8) + ; + + } catch (UnsupportedOperationException e) { + fail("UnsupportedOperationException should not happen: " + e.getMessage()); + } catch (IllegalArgumentException e) { + fail("IllegalArgumentException should not happen: " + e.getMessage()); + } catch (TransformerException e) { + fail("TransformerException should not happen: " + e.getMessage()); + } catch (IOException e) { + fail("IOException should not happen: " + e.getMessage()); + } + + + assertNotNull(result); + /* remove file endings so that tests can also pass after checking + out from git with arbitrary options (which may include CSRF changes) + */ + assertEquals(expected.replace("\r", "") + .replace("\n", "") + .replace("\t", "") + .replace(" ", ""), result.replace("\r", "") + .replace("\n", "") + .replace("\t", "") + .replace(" ", "")); + } + + public void testPDFVisualizationCII() { + + File CIIinputFile = getResourceAsFile("cii/01.01a-INVOICE.cii.xml"); + + // the writing part + + String expected = null; + String result = null; + try { + ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer(); + zvi.toPDF(CIIinputFile.getAbsolutePath(), TARGET_PDF_CII); + } catch (UnsupportedOperationException e) { + fail("UnsupportedOperationException should not happen: " + e.getMessage()); + } catch (IllegalArgumentException e) { + fail("IllegalArgumentException should not happen: " + e.getMessage()); + } + + try { + assertTrue(ByteArraySearcher.startsWith(Files.readAllBytes(Paths.get(TARGET_PDF_CII)), new byte[]{'%', 'P', 'D', 'F'})); + } catch (IOException e) { + fail("IOException should not occur"); + } + } + + public void testPDFVisualizationUBL() { + + File UBLinputFile = getResourceAsFile("ubl/01.01a-INVOICE.ubl.xml"); + + // the writing part + String sourceFilename = "factur-x.xml"; + + String expected = null; + String result = null; + try { + ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer(); + zvi.toPDF(UBLinputFile.getAbsolutePath(), TARGET_PDF_UBL); + } catch (UnsupportedOperationException e) { + fail("UnsupportedOperationException should not happen: " + e.getMessage()); + } catch (IllegalArgumentException e) { + fail("IllegalArgumentException should not happen: " + e.getMessage()); + } + + + try { + assertTrue(ByteArraySearcher.startsWith(Files.readAllBytes(Paths.get(TARGET_PDF_CII)), new byte[]{'%', 'P', 'D', 'F'})); + } catch (IOException e) { + fail("IOException should not occur"); + } + } + + public void testPDFVisualizationUBLCreditNote() { + + File UBLinputFile = getResourceAsFile("ubl/UBL-CreditNote-2.1-Example.ubl.xml"); + + // the writing part + String sourceFilename = "factur-x.xml"; + + String expected = null; + String result = null; + try { + ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer(); + zvi.toPDF(UBLinputFile.getAbsolutePath(), TARGET_PDF_UBL); + } catch (UnsupportedOperationException e) { + fail("UnsupportedOperationException should not happen: " + e.getMessage()); + } catch (IllegalArgumentException e) { + fail("IllegalArgumentException should not happen: " + e.getMessage()); + } + + + try { + assertTrue(ByteArraySearcher.startsWith(Files.readAllBytes(Paths.get(TARGET_PDF_CII)), new byte[]{'%', 'P', 'D', 'F'})); + } catch (IOException e) { + fail("IOException should not occur"); + } + } + +} diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java index ce0ee767..48daa626 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java @@ -1,826 +1,828 @@ - -/** - * ********************************************************************* - *

- * Copyright 2019 Jochen Staerk - *

- * Use is subject to license terms. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0. - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - *

- * See the License for the specific language governing permissions and - * limitations under the License. - *

- * ********************************************************************** - */ -package org.mustangproject.ZUGFeRD; - -import java.io.ByteArrayInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; - -import org.mustangproject.*; -import org.junit.FixMethodOrder; -import org.junit.runners.MethodSorters; - -import junit.framework.TestCase; - -import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants; -import org.mustangproject.ZUGFeRD.model.EventTimeCodeTypeConstants; - -import javax.xml.xpath.XPathExpressionException; - -import static org.xmlunit.assertj.XmlAssert.assertThat; - - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class ZF2PushTest extends TestCase { - final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20201121_508.pdf"; - final String TARGET_ALLOWANCESPDF = "./target/testout-ZF2PushAllowances.pdf"; - final String TARGET_CREDITNOTEPDF = "./target/testout-ZF2PushCreditNote.pdf"; - final String TARGET_CORRECTIONPDF = "./target/testout-ZF2PushCorrection.pdf"; - final String TARGET_ITEMCHARGESALLOWANCESPDF = "./target/testout-ZF2PushItemChargesAllowances.pdf"; - final String TARGET_CHARGESALLOWANCESPDF = "./target/testout-ZF2PushChargesAllowances.pdf"; - final String TARGET_RELATIVECHARGESALLOWANCESPDF = "./target/testout-ZF2PushRelativeChargesAllowances.pdf"; - final String TARGET_ATTACHMENTSPDF = "./target/testout-ZF2PushAttachments.pdf"; - final String TARGET_BANKPDF = "./target/testout-ZF2PushBank.pdf"; - final String TARGET_PUSHEDGE = "./target/testout-ZF2PushEdge.pdf"; - final String TARGET_INTRACOMMUNITYSUPPLYMANUALPDF = "./target/testout-ZF2PushIntraCommunitySupplyManual.pdf"; - final String TARGET_INTRACOMMUNITYSUPPLYPDF = "./target/testout-ZF2PushIntraCommunitySupply.pdf"; - final String TARGET_REVERSECHARGEPDF = "./target/testout-ZF2PushReverseCharge.pdf"; - - public void testPushExport() { - /*** - * This writes to a filename like an official sample, please consider when changing (probably better not?) - */ - // the writing part - String orgname = "Bei Spiel GmbH"; - String number = "RE-20201121/508"; - String priceStr = "160.00"; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - - BigDecimal price = new BigDecimal(priceStr); - try { - InputStream SOURCE_PDF = this.getClass() - .getResourceAsStream("/MustangGnuaccountingBeispielRE-20201121_508blanko.pdf"); - - ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1(); - ze.ignorePDFAErrors(); - ze.load(SOURCE_PDF); - ze.setProducer("My Application").setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2); - ze.setTransaction(new Invoice().setDueDate(sdf.parse("2020-12-12")).setIssueDate(sdf.parse("2020-11-21")).setDeliveryDate(sdf.parse("2020-11-10")) - .setSender(new TradeParty(orgname, "Ecke 12", "12345", "Stadthausen", "DE").addBankDetails(new BankDetails("DE88200800000970375700", "COBADEFFXXX").setAccountName("Max Mustermann")).addVATID("DE136695976")) - .setRecipient(new TradeParty("Theodor Est", "Bahnstr. 42", "88802", "Spielkreis", "DE") - .setContact(new Contact("Ingmar N. Fo", "(555) 23 78-23", "info@localhost.local")).setID("2")) - .setNumber(number) - .setReferenceNumber("AB321") - .addItem(new Item(new Product("Design (hours)", "Of a sample invoice", "HUR", new BigDecimal(7)), price, new BigDecimal(1.0))) - .addItem(new Item(new Product("Ballons", "various colors, ~2000ml", "H87", new BigDecimal(19)), new BigDecimal("0.79"), new BigDecimal(400.0))) - .addItem(new Item(new Product("Hot air „heiße Luft“ (litres)", "", "LTR", new BigDecimal(19)), new BigDecimal("0.025"), new BigDecimal(800.0))) - .setRoundingAmount(new BigDecimal("1")) - ); - - ze.export(TARGET_PDF); - } catch (IOException | ParseException e) { - fail("Exception should not be raised"); - } - - ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(TARGET_PDF); - Invoice i = new Invoice(); - try { - zii.extractInto(i); - } catch (XPathExpressionException e) { - throw new RuntimeException(e); - } catch (ParseException e) { - throw new RuntimeException(e); - } - - - // now check the contents (like MustangReaderTest) - ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF); - assertTrue(zi.getUTF8().contains("DE88200800000970375700")); //the iban - assertTrue(zi.getUTF8().contains("Max Mustermann")); //account holder - assertTrue(zi.getUTF8().contains("DueDateDateTime")); //account holder - assertTrue(zi.getUTF8().contains("20201212")); //account holder - - assertTrue(zi.getUTF8().contains("")); // maybe add a direct debit mandate to the class in the future then this would fail - assertTrue(zi.getUTF8().contains("Hinterhaus")); - assertThat(zi.getUTF8()).valueByXPath("//*[local-name()='BuyerTradeParty']/*[local-name()='GlobalID'][@schemeID=0088]").asString().isEqualTo("4304171000002"); - assertThat(zi.getUTF8()).valueByXPath("//*[local-name()='SpecifiedTradeProduct']/*[local-name()='GlobalID'][@schemeID=0160]").asString().isEqualTo("2001015001325"); - assertTrue(zi.getUTF8().contains("2001015001325")); - assertTrue(zi.getUTF8().contains("4304171000002")); - assertTrue(zi.getUTF8().contains("0088")); - assertTrue(zi.getUTF8().contains(orgID)); - assertTrue(zi.getUTF8().contains("ram:BuyerOrderReferencedDocument")); - assertTrue(zi.getUTF8().contains(occurrenceFrom)); - assertTrue(zi.getUTF8().contains(occurrenceTo)); - assertTrue(zi.getUTF8().contains(contractID)); - assertEquals(zi.importedInvoice.getZFItems()[0].getId(), "a123"); - assertTrue(zi.getUTF8().contains("20200113")); // to contain item delivery periods - assertTrue(zi.getUTF8().contains("20200115")); // to contain item delivery periods - - assertTrue(zi.getUTF8().contains("item level 1/1")); - assertTrue(zi.getUTF8().contains("DE4711")); // the VAT ID should be there... - assertFalse(zi.getUTF8().contains("DE47110")); // but not the VAT ID of the shiptotradeparty - assertTrue(zi.getUTF8().contains("document level 2/2")); - assertTrue(zi.getUTF8().contains("++49555123456")); - assertTrue(zi.getUTF8().contains("Cash Discount")); // default description for cash discounts - assertThat(zi.getUTF8()).valueByXPath("//*[local-name()='ApplicableTradeTax']/*[local-name()='DueDateTypeCode']").asString().isEqualTo(EventTimeCodeTypeConstants.PAYMENT_DATE); - - ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(TARGET_PUSHEDGE); - try { - Invoice i = zii.extractInvoice(); - - assertEquals("abc123", i.getInvoiceReferencedDocumentID()); - assertEquals("4304171000002", i.getRecipient().getGlobalID()); - assertEquals("2001015001325", i.getZFItems()[0].getProduct().getGlobalID()); - assertEquals(orgID, i.getSender().getID()); - - } catch (XPathExpressionException e) { - fail("XPathExpressionException should not be raised"); - } catch (ParseException e) { - fail("ParseException should not be raised"); - /* a parseException would also be fired if the calculated grand total does not - match the read grand total */ - } - } - - public void testAllowancesExport() { - - String orgname = "Test company"; - String number = "123"; - BigDecimal qty = new BigDecimal("20"); - try { - InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); - - ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1(); - ze.ignorePDFAErrors().load(SOURCE_PDF); - - ze.setProducer("My Application").setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("en16931")); - - ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()) - .setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815")) - .setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")) - .setNumber(number) - .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(500.0), qty).addAllowance(new Allowance(new BigDecimal(300)).setTaxPercent(new BigDecimal(19)))) - .addAllowance(new Allowance(new BigDecimal(600)).setTaxPercent(new BigDecimal(19))) - ); - String theXML = new String(ze.getProvider().getXML()); - assertTrue(theXML.contains(" + * Copyright 2019 Jochen Staerk + *

+ * Use is subject to license terms. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0. + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *

+ * See the License for the specific language governing permissions and + * limitations under the License. + *

+ * ********************************************************************** + */ +package org.mustangproject.ZUGFeRD; + +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +import org.mustangproject.*; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import junit.framework.TestCase; + +import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants; +import org.mustangproject.ZUGFeRD.model.EventTimeCodeTypeConstants; + +import javax.xml.xpath.XPathExpressionException; + +import static org.xmlunit.assertj.XmlAssert.assertThat; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ZF2PushTest extends TestCase { + final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20201121_508.pdf"; + final String TARGET_ALLOWANCESPDF = "./target/testout-ZF2PushAllowances.pdf"; + final String TARGET_CREDITNOTEPDF = "./target/testout-ZF2PushCreditNote.pdf"; + final String TARGET_CORRECTIONPDF = "./target/testout-ZF2PushCorrection.pdf"; + final String TARGET_ITEMCHARGESALLOWANCESPDF = "./target/testout-ZF2PushItemChargesAllowances.pdf"; + final String TARGET_CHARGESALLOWANCESPDF = "./target/testout-ZF2PushChargesAllowances.pdf"; + final String TARGET_RELATIVECHARGESALLOWANCESPDF = "./target/testout-ZF2PushRelativeChargesAllowances.pdf"; + final String TARGET_ATTACHMENTSPDF = "./target/testout-ZF2PushAttachments.pdf"; + final String TARGET_BANKPDF = "./target/testout-ZF2PushBank.pdf"; + final String TARGET_PUSHEDGE = "./target/testout-ZF2PushEdge.pdf"; + final String TARGET_INTRACOMMUNITYSUPPLYMANUALPDF = "./target/testout-ZF2PushIntraCommunitySupplyManual.pdf"; + final String TARGET_INTRACOMMUNITYSUPPLYPDF = "./target/testout-ZF2PushIntraCommunitySupply.pdf"; + final String TARGET_REVERSECHARGEPDF = "./target/testout-ZF2PushReverseCharge.pdf"; + + public void testPushExport() { + /*** + * This writes to a filename like an official sample, please consider when changing (probably better not?) + */ + // the writing part + String orgname = "Bei Spiel GmbH"; + String number = "RE-20201121/508"; + String priceStr = "160.00"; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + + BigDecimal price = new BigDecimal(priceStr); + try { + InputStream SOURCE_PDF = this.getClass() + .getResourceAsStream("/MustangGnuaccountingBeispielRE-20201121_508blanko.pdf"); + + ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1(); + ze.ignorePDFAErrors(); + ze.load(SOURCE_PDF); + ze.setProducer("My Application").setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2); + ze.setTransaction(new Invoice().setDueDate(sdf.parse("2020-12-12")).setIssueDate(sdf.parse("2020-11-21")).setDeliveryDate(sdf.parse("2020-11-10")) + .setSender(new TradeParty(orgname, "Ecke 12", "12345", "Stadthausen", "DE").addBankDetails(new BankDetails("DE88200800000970375700", "COBADEFFXXX").setAccountName("Max Mustermann")).addVATID("DE136695976")) + .setRecipient(new TradeParty("Theodor Est", "Bahnstr. 42", "88802", "Spielkreis", "DE") + .setContact(new Contact("Ingmar N. Fo", "(555) 23 78-23", "info@localhost.local")).setID("2")) + .setNumber(number) + .setReferenceNumber("AB321") + .addItem(new Item(new Product("Design (hours)", "Of a sample invoice", "HUR", new BigDecimal(7)), price, new BigDecimal(1.0))) + .addItem(new Item(new Product("Ballons", "various colors, ~2000ml", "H87", new BigDecimal(19)), new BigDecimal("0.79"), new BigDecimal(400.0))) + .addItem(new Item(new Product("Hot air „heiße Luft“ (litres)", "", "LTR", new BigDecimal(19)), new BigDecimal("0.025"), new BigDecimal(800.0))) + .setRoundingAmount(new BigDecimal("1")) + ); + + ze.export(TARGET_PDF); + } catch (IOException | ParseException e) { + fail("Exception should not be raised"); + } + + ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(TARGET_PDF); + Invoice i = new Invoice(); + try { + zii.extractInto(i); + } catch (XPathExpressionException e) { + throw new RuntimeException(e); + } catch (ParseException e) { + throw new RuntimeException(e); + } + + + // now check the contents (like MustangReaderTest) + ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF); + assertTrue(zi.getUTF8().contains("DE88200800000970375700")); //the iban + assertTrue(zi.getUTF8().contains("Max Mustermann")); //account holder + assertTrue(zi.getUTF8().contains("DueDateDateTime")); //account holder + assertTrue(zi.getUTF8().contains("20201212")); //account holder + + assertTrue(zi.getUTF8().contains("")); // maybe add a direct debit mandate to the class in the future then this would fail + assertTrue(zi.getUTF8().contains("Hinterhaus")); + assertThat(zi.getUTF8()).valueByXPath("//*[local-name()='BuyerTradeParty']/*[local-name()='GlobalID'][@schemeID=0088]").asString().isEqualTo("4304171000002"); + assertThat(zi.getUTF8()).valueByXPath("//*[local-name()='SpecifiedTradeProduct']/*[local-name()='GlobalID'][@schemeID=0160]").asString().isEqualTo("2001015001325"); + assertTrue(zi.getUTF8().contains("2001015001325")); + assertTrue(zi.getUTF8().contains("4304171000002")); + assertTrue(zi.getUTF8().contains("0088")); + assertTrue(zi.getUTF8().contains(orgID)); + assertTrue(zi.getUTF8().contains("ram:BuyerOrderReferencedDocument")); + assertTrue(zi.getUTF8().contains(occurrenceFrom)); + assertTrue(zi.getUTF8().contains(occurrenceTo)); + assertTrue(zi.getUTF8().contains(contractID)); + assertEquals(zi.importedInvoice.getZFItems()[0].getId(), "a123"); + assertTrue(zi.getUTF8().contains("20200113")); // to contain item delivery periods + assertTrue(zi.getUTF8().contains("20200115")); // to contain item delivery periods + + assertTrue(zi.getUTF8().contains("item level 1/1")); + assertTrue(zi.getUTF8().contains("DE4711")); // the VAT ID should be there... + assertFalse(zi.getUTF8().contains("DE47110")); // but not the VAT ID of the shiptotradeparty + assertTrue(zi.getUTF8().contains("document level 2/2")); + assertTrue(zi.getUTF8().contains("++49555123456")); + assertTrue(zi.getUTF8().contains("Cash Discount")); // default description for cash discounts + assertThat(zi.getUTF8()).valueByXPath("//*[local-name()='ApplicableTradeTax']/*[local-name()='DueDateTypeCode']").asString().isEqualTo(EventTimeCodeTypeConstants.PAYMENT_DATE); + + ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(TARGET_PUSHEDGE); + try { + Invoice i = zii.extractInvoice(); + + assertEquals("abc123", i.getInvoiceReferencedDocumentID()); + assertEquals("4304171000002", i.getRecipient().getGlobalID()); + assertEquals("2001015001325", i.getZFItems()[0].getProduct().getGlobalID()); + assertEquals(orgID, i.getSender().getID()); + + } catch (XPathExpressionException e) { + fail("XPathExpressionException should not be raised"); + } catch (ParseException e) { + fail("ParseException should not be raised"); + /* a parseException would also be fired if the calculated grand total does not + match the read grand total */ + } + } + + public void testAllowancesExport() { + + String orgname = "Test company"; + String number = "123"; + BigDecimal qty = new BigDecimal("20"); + try { + InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); + + ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1(); + ze.ignorePDFAErrors().load(SOURCE_PDF); + + ze.setProducer("My Application").setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("en16931")); + + ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()) + .setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815")) + .setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")) + .setNumber(number) + .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(500.0), qty).addAllowance(new Allowance(new BigDecimal(300)).setTaxPercent(new BigDecimal(19)))) + .addAllowance(new Allowance(new BigDecimal(600)).setTaxPercent(new BigDecimal(19))) + ); + String theXML = new String(ze.getProvider().getXML()); + assertTrue(theXML.contains("4.0.0 org.mustangproject core - 2.15.2-SNAPSHOT + 2.15.3-SNAPSHOT pom Mustang diff --git a/validator/pom.xml b/validator/pom.xml index 8fe7e62c..67d7ca94 100644 --- a/validator/pom.xml +++ b/validator/pom.xml @@ -3,7 +3,7 @@ org.mustangproject core - 2.15.2-SNAPSHOT + 2.15.3-SNAPSHOT 4.0.0 org.mustangproject @@ -11,7 +11,7 @@ Library to validate e-invoices (ZUGFeRD, Factur-X and Xrechnung) jar - 2.15.2-SNAPSHOT + 2.15.3-SNAPSHOT @@ -38,7 +38,7 @@ ${project.groupId} library - 2.15.2-SNAPSHOT + 2.15.3-SNAPSHOT org.dom4j