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/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/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..6610f0f2 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"); @@ -85,6 +41,7 @@ class ZUGFeRDTransactionModelConverter { private final Totals totals; private boolean isTest; private String currency = "EUR"; + private String profile; ZUGFeRDTransactionModelConverter(IZUGFeRDExportableTransaction trans) { @@ -114,7 +71,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); @@ -200,6 +157,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; } @@ -955,6 +921,11 @@ class ZUGFeRDTransactionModelConverter { return this; } + public ZUGFeRDTransactionModelConverter withProfile(String profile) { + this.profile = profile; + return this; + } + private class LineCalc { private BigDecimal totalGross; 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 :-/ } diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index 9b1f1f42..94c9fa4f 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,7 @@ 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"); } @@ -384,6 +385,37 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { 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.BASIC) >= 0); + assertFalse(pdfContent.indexOf(DocumentContextParameterTypeConstants.EXTENDED) >= 0); + assertTrue(pdfContent.indexOf(DocumentContextParameterTypeConstants.COMFORT) >= 0); + + } catch (IOException e) { + fail("IOException should not happen in testZExport"); + } + } + public void testFXExport() throws Exception {