From aa5944326f308876d8c99229e5f2c6fa3496ad6b Mon Sep 17 00:00:00 2001 From: jstaerk Date: Mon, 9 May 2022 21:38:26 +0200 Subject: [PATCH] simplest possible UBL despatch advice --- .../java/org/mustangproject/EStandard.java | 2 +- .../ZUGFeRD/DAPullProvider.java | 2 +- .../ZUGFeRD/EinLieferscheinExporter.java | 76 ++++++++++ .../org/mustangproject/ZUGFeRD/Profiles.java | 2 +- .../ZUGFeRD/UBLDAPullProvider.java | 137 ++++++++++++++++++ .../org/mustangproject/ZUGFeRD/DXTest.java | 2 +- .../org/mustangproject/ZUGFeRD/UBLTest.java | 38 ++++- 7 files changed, 254 insertions(+), 5 deletions(-) create mode 100644 library/src/main/java/org/mustangproject/ZUGFeRD/EinLieferscheinExporter.java create mode 100644 library/src/main/java/org/mustangproject/ZUGFeRD/UBLDAPullProvider.java diff --git a/library/src/main/java/org/mustangproject/EStandard.java b/library/src/main/java/org/mustangproject/EStandard.java index 6cf07237..96f1b7b4 100644 --- a/library/src/main/java/org/mustangproject/EStandard.java +++ b/library/src/main/java/org/mustangproject/EStandard.java @@ -1,6 +1,6 @@ package org.mustangproject; public enum EStandard { - facturx, orderx, deliveradvice, zugferd, cii, ubl + facturx, orderx, despatchadvice, ubldespatchadvice, zugferd, cii, ubl } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/DAPullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/DAPullProvider.java index 5ef1d409..8fbaf975 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/DAPullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/DAPullProvider.java @@ -39,7 +39,7 @@ public class DAPullProvider extends ZUGFeRD2PullProvider implements IXMLProvider protected IExportableTransaction trans; private String paymentTermsDescription; - protected Profile profile = Profiles.getByName(EStandard.deliveradvice,"pilot", 1); + protected Profile profile = Profiles.getByName(EStandard.despatchadvice,"pilot", 1); @Override diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/EinLieferscheinExporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/EinLieferscheinExporter.java new file mode 100644 index 00000000..609755e1 --- /dev/null +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/EinLieferscheinExporter.java @@ -0,0 +1,76 @@ +/** + * ********************************************************************* + *

+ * Copyright 2018 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.apache.pdfbox.cos.*; +import org.apache.pdfbox.io.IOUtils; +import org.apache.pdfbox.pdmodel.*; +import org.apache.pdfbox.pdmodel.common.PDMetadata; +import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification; +import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile; +import org.apache.pdfbox.preflight.PreflightDocument; +import org.apache.pdfbox.preflight.exception.ValidationException; +import org.apache.pdfbox.preflight.parser.PreflightParser; +import org.apache.pdfbox.preflight.utils.ByteArrayDataSource; +import org.apache.xmpbox.XMPMetadata; +import org.apache.xmpbox.schema.AdobePDFSchema; +import org.apache.xmpbox.schema.DublinCoreSchema; +import org.apache.xmpbox.schema.PDFAIdentificationSchema; +import org.apache.xmpbox.schema.XMPBasicSchema; +import org.apache.xmpbox.type.BadFieldValueException; +import org.apache.xmpbox.xml.XmpSerializer; + +import javax.activation.DataSource; +import javax.activation.FileDataSource; +import javax.xml.transform.TransformerException; +import java.io.*; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Map; + +public class EinLieferscheinExporter implements IExporter { + IXMLProvider xmlProvider; + IExportableTransaction trans; + + public EinLieferscheinExporter() { + xmlProvider=new UBLDAPullProvider(); + } + + + @Override + public IExporter setTransaction(IExportableTransaction trans) throws IOException { + this.trans=trans; + return this; + } + + @Override + public void export(String ZUGFeRDfilename) throws IOException { + export(new FileOutputStream(new File(ZUGFeRDfilename))); + + } + + @Override + public void export(OutputStream output) throws IOException { + xmlProvider.generateXML(trans); + byte[] bytes=xmlProvider.getXML(); + output.write(bytes, 0, bytes.length); + } +} diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java b/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java index 8f22805e..b5b9ae88 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java @@ -63,7 +63,7 @@ public class Profiles { throw new RuntimeException("Profile not found"); } return result; - } else if (standard == EStandard.deliveradvice) { + } else if (standard == EStandard.despatchadvice) { Profile result = null; result = dx1Map.get(name.toUpperCase()); if (result == null) { diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/UBLDAPullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/UBLDAPullProvider.java new file mode 100644 index 00000000..2890e4b5 --- /dev/null +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/UBLDAPullProvider.java @@ -0,0 +1,137 @@ +/** + * ********************************************************************* + *

+ * Copyright 2018 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.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; +import org.mustangproject.EStandard; +import org.mustangproject.FileAttachment; +import org.mustangproject.XMLTools; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.Base64; +import java.util.Date; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static org.mustangproject.ZUGFeRD.ZUGFeRDDateFormat.DATE; +import static org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants.CORRECTEDINVOICE; +import static org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants.CATEGORY_CODES_WITH_EXEMPTION_REASON; + +public class UBLDAPullProvider implements IXMLProvider { + + protected IExportableTransaction trans; + protected TransactionCalculator calc; + byte[] ublData; + protected Profile profile = Profiles.getByName(EStandard.ubldespatchadvice, "basic", 1); + + + @Override + public void generateXML(IExportableTransaction trans) { + this.trans = trans; + this.calc = new TransactionCalculator(trans); + + final SimpleDateFormat ublDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + + + String xml = "\n" + + "\n" + + " " + XMLTools.encodeXML(trans.getNumber()) + "\n" + + " "+ublDateFormat.format(trans.getIssueDate())+"\n" + + " \n" + + " \n"; + + int i = 1; + for (IZUGFeRDExportableItem item : trans.getZFItems()) { + xml += + " \n" + + " " + XMLTools.encodeXML(Integer.toString(i++)) + "\n" + + " \n" + + " " + XMLTools.encodeXML(item.getBuyerOrderReferencedDocumentLineID()) + "\n" + + " \n" + + " \n" + + " \n"; + + } + xml += "\n"; + final byte[] ublRaw; + try { + ublRaw = xml.getBytes("UTF-8"); + + ublData = XMLTools.removeBOM(ublRaw); + } catch (final UnsupportedEncodingException e) { + Logger.getLogger(UBLDAPullProvider.class.getName()).log(Level.SEVERE, null, e); + } + } + + + @Override + public byte[] getXML() { + + byte[] res = ublData; + + final StringWriter sw = new StringWriter(); + Document document = null; + try { + document = DocumentHelper.parseText(new String(ublData)); + } catch (final DocumentException e1) { + Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e1); + } + try { + final OutputFormat format = OutputFormat.createPrettyPrint(); + format.setTrimText(false); + final XMLWriter writer = new XMLWriter(sw, format); + writer.write(document); + res = sw.toString().getBytes(StandardCharsets.UTF_8); + + } catch (final IOException e) { + Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e); + } + + return res; + + } + + @Override + public void setTest() { + + } + + @Override + public void setProfile(Profile p) { + profile = p; + } + + @Override + public Profile getProfile() { + return profile; + } + +} diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/DXTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/DXTest.java index ec4409b5..b62937f3 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/DXTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/DXTest.java @@ -324,7 +324,7 @@ public class DXTest extends MustangReaderTestCase implements IExportableTransact Invoice i = createDA(recipient); DAPullProvider zf2p = new DAPullProvider(); - zf2p.setProfile(Profiles.getByName(EStandard.deliveradvice,"Pilot",1)); + zf2p.setProfile(Profiles.getByName(EStandard.despatchadvice,"Pilot",1)); zf2p.generateXML(i); String theXML = new String(zf2p.getXML(), StandardCharsets.UTF_8); try { diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/UBLTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/UBLTest.java index 9e8f22e8..59d1e653 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/UBLTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/UBLTest.java @@ -21,16 +21,24 @@ */ package org.mustangproject.ZUGFeRD; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Date; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +import org.mustangproject.*; import org.mustangproject.CII.CIIToUBL; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class UBLTest extends ResourceCase { + final String TARGET_XML = "./target/testout-1Lieferschein.xml"; public void testUBLBasic() { @@ -47,11 +55,39 @@ public class UBLTest extends ResourceCase { expected = ResourceUtilities.readFile(StandardCharsets.UTF_8, expectedFile.getAbsolutePath()).replaceAll("\r\n", "\n"); result = ResourceUtilities.readFile(StandardCharsets.UTF_8, tempFile.getAbsolutePath()).replaceAll("\r\n", "\n"); } catch (final IOException e) { - fail("Exception should not happen: "+e.getMessage()); + fail("Exception should not happen: " + e.getMessage()); } assertNotNull(result); assertEquals(expected, result); } + + public void test1Lieferschein() { + + EinLieferscheinExporter oe = new EinLieferscheinExporter(); + Invoice i = new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()) + .setSender(new TradeParty("Test company", "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 + .setNumber("123").addItem(new Item(new Product("Testprodukt", "", "C62", BigDecimal.ZERO), /*price*/ new BigDecimal("1.0"), /*qty*/ new BigDecimal("1.0")).addReferencedLineID("A12")); + + UBLDAPullProvider zf2p = new UBLDAPullProvider(); + zf2p.setProfile(Profiles.getByName(EStandard.despatchadvice, "Pilot", 1)); + zf2p.generateXML(i); + + try { + oe.setTransaction(i); + ByteArrayOutputStream baos=new ByteArrayOutputStream(); + oe.export(baos); + + String theXML = baos.toString("UTF-8"); + assertTrue(theXML.contains("