From ce5af7b012ca2182c3d51ac6f54d136265bc5324 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Thu, 25 Jul 2019 16:55:28 +0200 Subject: [PATCH 1/5] complete profile options for v1 see "Das ZUGFeRD-Format_1p0", p. 98, lines 1982 ff. --- .../ZUGFeRD/model/DocumentContextParameterTypeConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/model/DocumentContextParameterTypeConstants.java b/src/main/java/org/mustangproject/ZUGFeRD/model/DocumentContextParameterTypeConstants.java index 57033f6d..d90eabd1 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/model/DocumentContextParameterTypeConstants.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/model/DocumentContextParameterTypeConstants.java @@ -19,7 +19,7 @@ package org.mustangproject.ZUGFeRD.model; public class DocumentContextParameterTypeConstants { + public static final String BASIC = "urn:ferd:CrossIndustryDocument:invoice:1p0:basic"; public static final String COMFORT = "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort"; public static final String EXTENDED = "urn:ferd:CrossIndustryDocument:invoice:1p0:extended"; - // this does not look complete :-/ } From 0720751d350c3de96d438fb23ed8f30e0ca28f0f Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Thu, 25 Jul 2019 17:42:03 +0200 Subject: [PATCH 2/5] failing test case to check for correct v1 profile string --- .../ZUGFeRD/MustangReaderWriterTest.java | 47 ++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index 9b1f1f42..72d0f9b0 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -30,6 +30,7 @@ import org.apache.xmpbox.xml.DomXmpParser; import org.apache.xmpbox.xml.XmpParsingException; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +import org.mustangproject.ZUGFeRD.model.DocumentContextParameterTypeConstants; import java.io.ByteArrayOutputStream; import java.io.File; @@ -349,7 +350,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { // the writing part try (InputStream SOURCE_PDF = this.getClass() - .getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf"); + .getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf"); ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setZUGFeRDVersion(2).setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.EN16931).load(SOURCE_PDF)) { @@ -366,7 +367,49 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { // assertFalse(pdfContent.indexOf("EN 16931") == -1); // assertFalse(pdfContent.indexOf("zf") == -1); // assertFalse(pdfContent.indexOf("urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#") == -1); - + + } catch (IOException e) { + fail("IOException should not happen in testZExport"); + } + + // now check the contents (like MustangReaderTest) + ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF); + + // Reading ZUGFeRD + assertEquals(zi.getAmount(), "571.04"); + assertEquals(zi.getBIC(), getTradeSettlementPayment()[0].getOwnBIC()); + assertEquals(zi.getReference(), getReferenceNumber()); + assertEquals(zi.getIBAN(), getTradeSettlementPayment()[0].getOwnIBAN()); + assertEquals(zi.getKTO(), getTradeSettlementPayment()[0].getOwnKto()); + assertEquals(zi.getHolder(), getOwnOrganisationName()); + assertEquals(zi.getForeignReference(), getNumber()); + } + + /** + * Quick and dirty copy of testZExport to check if v1 files contain + * the correct profile string when the comfort profile is selected. + */ + public void testZExportv1Profile() { + + final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20171118_506new.pdf"; + + // the writing part + try (InputStream SOURCE_PDF = this.getClass() + .getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf"); + + ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setZUGFeRDVersion(1).setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.COMFORT).load(SOURCE_PDF)) { + + ze.PDFattachZugferdFile(this); + ze.disableAutoClose(true); + ze.export(TARGET_PDF); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ze.export(baos); + ze.close(); + String pdfContent = baos.toString("UTF-8"); + assertFalse(pdfContent.indexOf(DocumentContextParameterTypeConstants.EXTENDED) >= 0); + assertTrue(pdfContent.indexOf(DocumentContextParameterTypeConstants.COMFORT) >= 0); + } catch (IOException e) { fail("IOException should not happen in testZExport"); } From b701bf25c8ca928be5e2fe77074c5c500e869463 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Thu, 25 Jul 2019 17:59:18 +0200 Subject: [PATCH 3/5] failing test case to check for correct v1 profile string --- .../ZUGFeRD/MustangReaderWriterTest.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index 72d0f9b0..94c9fa4f 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -407,24 +407,13 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { ze.export(baos); ze.close(); String pdfContent = baos.toString("UTF-8"); + assertFalse(pdfContent.indexOf(DocumentContextParameterTypeConstants.BASIC) >= 0); assertFalse(pdfContent.indexOf(DocumentContextParameterTypeConstants.EXTENDED) >= 0); assertTrue(pdfContent.indexOf(DocumentContextParameterTypeConstants.COMFORT) >= 0); } catch (IOException e) { fail("IOException should not happen in testZExport"); } - - // now check the contents (like MustangReaderTest) - ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF); - - // Reading ZUGFeRD - assertEquals(zi.getAmount(), "571.04"); - assertEquals(zi.getBIC(), getTradeSettlementPayment()[0].getOwnBIC()); - assertEquals(zi.getReference(), getReferenceNumber()); - assertEquals(zi.getIBAN(), getTradeSettlementPayment()[0].getOwnIBAN()); - assertEquals(zi.getKTO(), getTradeSettlementPayment()[0].getOwnKto()); - assertEquals(zi.getHolder(), getOwnOrganisationName()); - assertEquals(zi.getForeignReference(), getNumber()); } From 9681b4fa6d087efd88df5cd07b00fbea7dd1c6a3 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Thu, 25 Jul 2019 18:33:14 +0200 Subject: [PATCH 4/5] extend IProfileProvider to allow modification of profile --- .../ZUGFeRD/CustomXMLProvider.java | 12 +++++++++++- .../ZUGFeRD/IProfileProvider.java | 2 ++ .../ZUGFeRD/ZUGFeRD1PullProvider.java | 19 +++++++++++++++++-- .../ZUGFeRD/ZUGFeRD2PullProvider.java | 5 +++++ .../ZUGFeRD/ZUGFeRDExporter.java | 2 +- .../ZUGFeRDTransactionModelConverter.java | 8 +++++++- 6 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/CustomXMLProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/CustomXMLProvider.java index dfd8be88..6ac2c275 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/CustomXMLProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/CustomXMLProvider.java @@ -18,7 +18,7 @@ *********************************************************************** */ package org.mustangproject.ZUGFeRD; -public class CustomXMLProvider implements IXMLProvider { +public class CustomXMLProvider implements IXMLProvider, IProfileProvider { protected byte[] zugferdData; @@ -48,4 +48,14 @@ public class CustomXMLProvider implements IXMLProvider { } + @Override + public String getProfile() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setProfile(ZUGFeRDConformanceLevel level) { + // TODO Auto-generated method stub + } } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java index adc695df..d4469edb 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java @@ -21,5 +21,7 @@ package org.mustangproject.ZUGFeRD; public interface IProfileProvider { public String getProfile(); + + public void setProfile(ZUGFeRDConformanceLevel level); } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java index 3c782866..f8278a32 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java @@ -19,6 +19,7 @@ package org.mustangproject.ZUGFeRD; import org.mustangproject.ZUGFeRD.model.CrossIndustryDocumentType; +import org.mustangproject.ZUGFeRD.model.DocumentContextParameterTypeConstants; import org.mustangproject.ZUGFeRD.model.ZFNamespacePrefixMapper; import javax.xml.bind.JAXBContext; @@ -27,13 +28,27 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import java.io.ByteArrayOutputStream; -public class ZUGFeRD1PullProvider implements IXMLProvider { +public class ZUGFeRD1PullProvider implements IXMLProvider, IProfileProvider { protected byte[] zugferdData; private Marshaller marshaller; private boolean isTest; + private ZUGFeRDConformanceLevel level; + + + public void setProfile(ZUGFeRDConformanceLevel level) { + this.level = level; + } + + public String getProfile() { + switch (level) { + case BASIC: return DocumentContextParameterTypeConstants.BASIC; + case COMFORT: return DocumentContextParameterTypeConstants.COMFORT; + default: return DocumentContextParameterTypeConstants.EXTENDED; + } + } /** @@ -59,7 +74,7 @@ public class ZUGFeRD1PullProvider implements IXMLProvider { private String createZugferdXMLForTransaction(IZUGFeRDExportableTransaction trans) { JAXBElement jaxElement = - new ZUGFeRDTransactionModelConverter(trans).withTest(isTest).convertToModel(); + new ZUGFeRDTransactionModelConverter(trans).withTest(isTest).withProfile(getProfile()).convertToModel(); try { return marshalJaxToXMLString(jaxElement); diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 03db8e0c..7e12cdfe 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -71,6 +71,11 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { protected byte[] zugferdData; private IZUGFeRDExportableTransaction trans; + private ZUGFeRDConformanceLevel level; + + public void setProfile(ZUGFeRDConformanceLevel level) { + this.level = level; + } /** * enables the flag to indicate a test invoice in the XML structure diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java index af5dd4cc..f6796991 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java @@ -367,7 +367,7 @@ public class ZUGFeRDExporter implements Closeable { */ public void PDFattachZugferdFile(IZUGFeRDExportableTransaction trans) throws IOException { prepareDocument(); - + ((IProfileProvider) xmlProvider).setProfile(profile); xmlProvider.generateXML(trans); String filename = getFilenameForVersion(ZFVersion); PDFAttachGenericFile(doc, filename, "Alternative", diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java index 330619ee..6896dd2a 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java @@ -85,6 +85,7 @@ class ZUGFeRDTransactionModelConverter { private final Totals totals; private boolean isTest; private String currency = "EUR"; + private String profile; ZUGFeRDTransactionModelConverter(IZUGFeRDExportableTransaction trans) { @@ -114,7 +115,7 @@ class ZUGFeRDTransactionModelConverter { DocumentContextParameterType contextParameter = xmlFactory .createDocumentContextParameterType(); IDType idType = xmlFactory.createIDType(); - idType.setValue(DocumentContextParameterTypeConstants.EXTENDED); + idType.setValue(profile); contextParameter.setID(idType); context.getGuidelineSpecifiedDocumentContextParameter().add( contextParameter); @@ -955,6 +956,11 @@ class ZUGFeRDTransactionModelConverter { return this; } + public ZUGFeRDTransactionModelConverter withProfile(String profile) { + this.profile = profile; + return this; + } + private class LineCalc { private BigDecimal totalGross; From a7e9d72d3a3b0556a4bfc4977921ea9e2a0fee59 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Thu, 25 Jul 2019 20:35:11 +0200 Subject: [PATCH 5/5] make BuyerOrderReferencedDocument accessible --- .../IZUGFeRDExportableTransaction.java | 11 ++++ .../ZUGFeRDTransactionModelConverter.java | 55 ++++--------------- 2 files changed, 21 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java index 03a93e7d..3be30215 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java @@ -246,4 +246,15 @@ public interface IZUGFeRDExportableTransaction { return null; } + /** + * get the ID of the BuyerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement + * @return the ID of the document + */ + default String getBuyerOrderReferencedDocumentID() { return null; } + + /** + * get the issue timestamp of the BuyerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement + * @return the IssueDateTime in format CCYY-MM-DDTHH:MM:SS + */ + default String getBuyerOrderReferencedDocumentIssueDateTime() { return null; } } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java index 330619ee..fc20245c 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java @@ -31,51 +31,7 @@ import java.util.List; import javax.xml.bind.JAXBElement; -import org.mustangproject.ZUGFeRD.model.AmountType; -import org.mustangproject.ZUGFeRD.model.CodeType; -import org.mustangproject.ZUGFeRD.model.CountryIDType; -import org.mustangproject.ZUGFeRD.model.CreditorFinancialAccountType; -import org.mustangproject.ZUGFeRD.model.CreditorFinancialInstitutionType; -import org.mustangproject.ZUGFeRD.model.CrossIndustryDocumentType; -import org.mustangproject.ZUGFeRD.model.DateTimeType; -import org.mustangproject.ZUGFeRD.model.DateTimeTypeConstants; -import org.mustangproject.ZUGFeRD.model.DocumentCodeType; -import org.mustangproject.ZUGFeRD.model.DocumentContextParameterType; -import org.mustangproject.ZUGFeRD.model.DocumentContextParameterTypeConstants; -import org.mustangproject.ZUGFeRD.model.DocumentLineDocumentType; -import org.mustangproject.ZUGFeRD.model.ExchangedDocumentContextType; -import org.mustangproject.ZUGFeRD.model.ExchangedDocumentType; -import org.mustangproject.ZUGFeRD.model.IDType; -import org.mustangproject.ZUGFeRD.model.IndicatorType; -import org.mustangproject.ZUGFeRD.model.LogisticsServiceChargeType; -import org.mustangproject.ZUGFeRD.model.NoteType; -import org.mustangproject.ZUGFeRD.model.NoteTypeConstants; -import org.mustangproject.ZUGFeRD.model.ObjectFactory; -import org.mustangproject.ZUGFeRD.model.PaymentMeansCodeType; -import org.mustangproject.ZUGFeRD.model.PaymentMeansCodeTypeConstants; -import org.mustangproject.ZUGFeRD.model.PercentType; -import org.mustangproject.ZUGFeRD.model.QuantityType; -import org.mustangproject.ZUGFeRD.model.SupplyChainEventType; -import org.mustangproject.ZUGFeRD.model.SupplyChainTradeAgreementType; -import org.mustangproject.ZUGFeRD.model.SupplyChainTradeDeliveryType; -import org.mustangproject.ZUGFeRD.model.SupplyChainTradeLineItemType; -import org.mustangproject.ZUGFeRD.model.SupplyChainTradeSettlementType; -import org.mustangproject.ZUGFeRD.model.SupplyChainTradeTransactionType; -import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeType; -import org.mustangproject.ZUGFeRD.model.TaxRegistrationType; -import org.mustangproject.ZUGFeRD.model.TaxRegistrationTypeConstants; -import org.mustangproject.ZUGFeRD.model.TaxTypeCodeType; -import org.mustangproject.ZUGFeRD.model.TaxTypeCodeTypeConstants; -import org.mustangproject.ZUGFeRD.model.TextType; -import org.mustangproject.ZUGFeRD.model.TradeAddressType; -import org.mustangproject.ZUGFeRD.model.TradeAllowanceChargeType; -import org.mustangproject.ZUGFeRD.model.TradePartyType; -import org.mustangproject.ZUGFeRD.model.TradePaymentTermsType; -import org.mustangproject.ZUGFeRD.model.TradePriceType; -import org.mustangproject.ZUGFeRD.model.TradeProductType; -import org.mustangproject.ZUGFeRD.model.TradeSettlementMonetarySummationType; -import org.mustangproject.ZUGFeRD.model.TradeSettlementPaymentMeansType; -import org.mustangproject.ZUGFeRD.model.TradeTaxType; +import org.mustangproject.ZUGFeRD.model.*; class ZUGFeRDTransactionModelConverter { private static final SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); @@ -200,6 +156,15 @@ class ZUGFeRDTransactionModelConverter { tradeAgreement.setBuyerTradeParty(getBuyer()); tradeAgreement.setSellerTradeParty(getSeller()); + if (trans.getBuyerOrderReferencedDocumentID() != null) { + ReferencedDocumentType refdoc = xmlFactory.createReferencedDocumentType(); + IDType id = xmlFactory.createIDType(); + id.setValue(trans.getBuyerOrderReferencedDocumentID()); + refdoc.getID().add(id); + refdoc.setIssueDateTime(trans.getBuyerOrderReferencedDocumentIssueDateTime()); + tradeAgreement.getBuyerOrderReferencedDocument().add(refdoc); + } + return tradeAgreement; }