From f1f81cf0be97e23c1b82b7a4e8f5fc1e691bab30 Mon Sep 17 00:00:00 2001 From: Thomas Christlieb Date: Thu, 18 Dec 2025 08:35:48 +0100 Subject: [PATCH] add DeliveryNoteReferencedDocument - one part of Issue #589 - also see Issue #253 --- .../main/java/org/mustangproject/Invoice.java | 24 ++++++++++++++ .../ZUGFeRD/IExportableTransaction.java | 20 ++++++++++++ .../ZUGFeRD/ZUGFeRD2PullProvider.java | 18 +++++++---- .../ZUGFeRD/ZUGFeRDInvoiceImporter.java | 32 +++++++++++++++++++ .../mustangproject/ZUGFeRD/ZF2EdgeTest.java | 10 ++++++ .../mustangproject/ZUGFeRD/ZF2PushTest.java | 8 +++++ .../ZUGFeRD/ZF2ZInvoiceImporterTest.java | 2 ++ 7 files changed, 108 insertions(+), 6 deletions(-) diff --git a/library/src/main/java/org/mustangproject/Invoice.java b/library/src/main/java/org/mustangproject/Invoice.java index 0358abe9..a73889df 100644 --- a/library/src/main/java/org/mustangproject/Invoice.java +++ b/library/src/main/java/org/mustangproject/Invoice.java @@ -68,6 +68,8 @@ public class Invoice implements IExportableTransaction { protected String specifiedProcuringProjectID = null; protected String specifiedProcuringProjectName = null; protected String despatchAdviceReferencedDocumentID = null; + protected String deliveryNoteReferencedDocumentID = null; + protected Date deliveryNoteReferencedDocumentDate = null; protected String vatDueDateTypeCode = null; protected String creditorReferenceID; // required when direct debit is used. private BigDecimal roundingAmount=null; @@ -1073,6 +1075,28 @@ public class Invoice implements IExportableTransaction { return this; } + @Override + public String getDeliveryNoteReferencedDocumentID() { + return deliveryNoteReferencedDocumentID; + } + + + public Invoice setDeliveryNoteReferencedDocumentID(String deliveryNoteReferencedDocumentID) { + this.deliveryNoteReferencedDocumentID = deliveryNoteReferencedDocumentID; + return this; + } + + @Override + public Date getDeliveryNoteReferencedDocumentDate() { + return deliveryNoteReferencedDocumentDate; + } + + + public Invoice setDeliveryNoteReferencedDocumentDate(Date deliveryNoteReferencedDocumentDate) { + this.deliveryNoteReferencedDocumentDate = deliveryNoteReferencedDocumentDate; + return this; + } + @Override public String getSpecifiedProcuringProjectName() { diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java index a7cbdbd4..cb38bbeb 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java @@ -562,6 +562,26 @@ public interface IExportableTransaction { return null; } + /** + * get delivery note document ID + * ram:ApplicableHeaderTradeDelivery/ram:DeliveryNoteReferencedDocument/IssuerAssignedID + * + * @return the ID of the delivery note document + */ + default String getDeliveryNoteReferencedDocumentID() { + return null; + } + + /** + * get delivery note document date + * ram:ApplicableHeaderTradeDelivery/ram:DeliveryNoteReferencedDocument/FormattedIssueDateTime + * + * @return the date of the delivery note document + */ + default Date getDeliveryNoteReferencedDocumentDate() { + return null; + } + /*** * additional text description * diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 1688cf5c..f123411e 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -676,12 +676,18 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { + "" + DATE.udtFormat(trans.getDeliveryDate()) + "" + ""; } - /* - * + "" + - * "20130603" + - * "2013-51112" + - * "" - */ + + if (trans.getDeliveryNoteReferencedDocumentID() != null && !trans.getDeliveryNoteReferencedDocumentID().trim().isEmpty()) { + xml += ""; + xml += "" + XMLTools.encodeXML(trans.getDeliveryNoteReferencedDocumentID()) + ""; + if (trans.getDeliveryNoteReferencedDocumentDate() != null) { + final SimpleDateFormat dateFormat102 = new SimpleDateFormat("yyyyMMdd"); + xml += ""+XMLTools.encodeXML(dateFormat102.format(trans.getDeliveryNoteReferencedDocumentDate()))+""; + } + xml += ""; + + } + if (trans.getDespatchAdviceReferencedDocumentID() != null && !trans.getDespatchAdviceReferencedDocumentID().trim().isEmpty()) { xml += ""; xml += "" + XMLTools.encodeXML(trans.getDespatchAdviceReferencedDocumentID()) + ""; diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java index 5535e6f2..09803e59 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java @@ -528,6 +528,8 @@ public class ZUGFeRDInvoiceImporter { Date dueDate = null; Date deliveryDate = null; String despatchAdviceReferencedDocument = null; + String deliveryNoteReferencedDocumentID = null; + Date deliveryNoteReferencedDocumentDate = null; for (int i = 0; i < ExchangedDocumentNodes.getLength(); i++) { Node exchangedDocumentNode = ExchangedDocumentNodes.item(i); @@ -681,6 +683,28 @@ public class ZUGFeRDInvoiceImporter { } } } + + if (headerTradeDeliveryChilds.item(deliveryChildIndex).getLocalName().equals("DeliveryNoteReferencedDocument")) { + NodeList deliveryNoteReferencedDocumentChilds = headerTradeDeliveryChilds.item(deliveryChildIndex).getChildNodes(); + for (int deliveryNoteReferencedDocumentIndex = 0; deliveryNoteReferencedDocumentIndex < deliveryNoteReferencedDocumentChilds.getLength(); deliveryNoteReferencedDocumentIndex++) { + if (deliveryNoteReferencedDocumentChilds.item(deliveryNoteReferencedDocumentIndex).getLocalName() != null + && deliveryNoteReferencedDocumentChilds.item(deliveryNoteReferencedDocumentIndex).getLocalName().equals("IssuerAssignedID")) { + deliveryNoteReferencedDocumentID = XMLTools.trimOrNull(deliveryNoteReferencedDocumentChilds.item(deliveryNoteReferencedDocumentIndex)); + } + + if ((deliveryNoteReferencedDocumentChilds.item(deliveryNoteReferencedDocumentIndex).getLocalName() != null) + && (deliveryNoteReferencedDocumentChilds.item(deliveryNoteReferencedDocumentIndex).getLocalName().equals("FormattedIssueDateTime"))) { + + NodeList FormattedIssueDateTimeChilds = deliveryNoteReferencedDocumentChilds.item(deliveryNoteReferencedDocumentIndex).getChildNodes(); + for (int dateChildIndex = 0; dateChildIndex < FormattedIssueDateTimeChilds.getLength(); dateChildIndex++) { + if ((FormattedIssueDateTimeChilds.item(dateChildIndex).getLocalName() != null) + && (FormattedIssueDateTimeChilds.item(dateChildIndex).getLocalName().equals("DateTimeString"))) { + deliveryNoteReferencedDocumentDate = XMLTools.tryDate(FormattedIssueDateTimeChilds.item(dateChildIndex)); + } + } + } + } + } } } } @@ -1009,6 +1033,14 @@ public class ZUGFeRDInvoiceImporter { } } + if (deliveryNoteReferencedDocumentID != null) { + zpp.setDeliveryNoteReferencedDocumentID(deliveryNoteReferencedDocumentID); + } + + if (deliveryNoteReferencedDocumentDate != null) { + zpp.setDeliveryNoteReferencedDocumentDate(deliveryNoteReferencedDocumentDate); + } + String invoiceReferencedDocumentID = extractString("//*[local-name()=\"InvoiceReferencedDocument\"]/*[local-name()=\"IssuerAssignedID\"]|//*[local-name()=\"BillingReference\"]/*[local-name()=\"InvoiceDocumentReference\"]/*[local-name()=\"ID\"]"); if (!invoiceReferencedDocumentID.isEmpty()) { zpp.setInvoiceReferencedDocumentID(invoiceReferencedDocumentID); diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java index a82b160d..712256d5 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java @@ -304,6 +304,16 @@ public class ZF2EdgeTest extends MustangReaderTestCase { return "123"; } + @Override + public String getDeliveryNoteReferencedDocumentID() { + return "0815"; + } + + @Override + public Date getDeliveryNoteReferencedDocumentDate() { + return new GregorianCalendar(2016, Calendar.APRIL, 1).getTime(); + } + /** * Create the test case * diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java index 15c7d07a..1f81e373 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java @@ -851,6 +851,8 @@ public class ZF2PushTest extends TestCase { .setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815").addBankDetails(new BankDetails("DE88200800000970375700", "COBADEFFXXX"))) .setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0815")) .setNumber(number).setDespatchAdviceReferencedDocumentID(despatchAdviceReferencedDocumentID) + .setDeliveryNoteReferencedDocumentID("0815") + .setDeliveryNoteReferencedDocumentDate(new SimpleDateFormat("dd.MM.yyyy").parse("01.04.2016")) .addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(19)), price, qty)) .addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(19)), price, qty)) .addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(19)), price, qty)).setCreditNote(); @@ -860,6 +862,8 @@ public class ZF2PushTest extends TestCase { ze.export(TARGET_CREDITNOTEPDF); } catch (IOException e) { fail("IOException should not be raised"); + } catch (ParseException e) { + fail("ParseException should not be raised"); } // now check the contents (like MustangReaderTest) @@ -882,6 +886,8 @@ public class ZF2PushTest extends TestCase { Invoice i = zii.extractInvoice(); assertEquals(despatchAdviceReferencedDocumentID, i.getDespatchAdviceReferencedDocumentID()); + assertEquals("0815", i.getDeliveryNoteReferencedDocumentID()); + assertEquals(new SimpleDateFormat("dd.MM.yyyy").parse("01.04.2016"), i.getDeliveryNoteReferencedDocumentDate()); } catch (XPathExpressionException e) { fail("XPathExpressionException should not be raised"); @@ -912,6 +918,7 @@ public class ZF2PushTest extends TestCase { .setBuyerOrderReferencedDocumentID("") .setContractReferencedDocument("") .setDespatchAdviceReferencedDocumentID("") + .setDeliveryNoteReferencedDocumentID("") .setInvoiceReferencedDocumentID(""); zf2p.generateXML(i); @@ -928,6 +935,7 @@ public class ZF2PushTest extends TestCase { .setBuyerOrderReferencedDocumentID(" ") .setContractReferencedDocument(" ") .setDespatchAdviceReferencedDocumentID(" ") + .setDeliveryNoteReferencedDocumentID(" ") .setInvoiceReferencedDocumentID(" "); zf2p.generateXML(i); diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java index cdfbf6d0..36877696 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java @@ -894,6 +894,8 @@ public class ZF2ZInvoiceImporterTest extends ResourceCase { assertNull(invoice.getSellerOrderReferencedDocumentID()); assertNull(invoice.getDespatchAdviceReferencedDocumentID()); assertNull(invoice.getInvoiceReferencedDocumentID()); + assertNull(invoice.getDeliveryNoteReferencedDocumentID()); + assertNull(invoice.getDeliveryNoteReferencedDocumentDate()); } @Test