Skip to content

Commit d6cc8bb

Browse files
committed
Merge branch 'issues/923'
2 parents 978844d + a4cb76a commit d6cc8bb

12 files changed

Lines changed: 791 additions & 15 deletions

File tree

library/src/main/java/org/mustangproject/Invoice.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public class Invoice implements IExportableTransaction {
5454
protected BigDecimal totalPrepaidAmount = null;
5555
protected Date detailedDeliveryDateStart = null;
5656
protected Date detailedDeliveryPeriodEnd = null;
57+
protected IReferencedDocument tenderReference = null;
5758

5859
protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<>(),
5960
Charges = new ArrayList<>(), LogisticsServiceCharges = new ArrayList<>();
@@ -144,6 +145,34 @@ public String getNumber() {
144145
return number;
145146
}
146147

148+
149+
150+
@Override
151+
/***
152+
* BT-17
153+
*/
154+
public IReferencedDocument getTenderReferencedDocument() {
155+
return tenderReference;
156+
}
157+
158+
159+
/***
160+
* BT-17
161+
* @param dr
162+
* @return
163+
*/
164+
public Invoice setTenderReferencedDocument(ReferencedDocument dr) {
165+
tenderReference=dr;
166+
return this;
167+
}
168+
169+
public Invoice setTenderReferencedDocument(String ID) {
170+
ReferencedDocument dr=new ReferencedDocument(ID);
171+
setTenderReferencedDocument(dr);
172+
return this;
173+
}
174+
175+
147176
public Invoice setNumber(String number) {
148177
this.number = number;
149178
return this;

library/src/main/java/org/mustangproject/Item.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
import com.fasterxml.jackson.annotation.JsonIgnore;
44
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
55
import com.fasterxml.jackson.annotation.JsonInclude;
6-
import org.mustangproject.ZUGFeRD.IReferencedDocument;
7-
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
8-
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem;
9-
import org.mustangproject.ZUGFeRD.LineCalculator;
6+
import org.mustangproject.ZUGFeRD.*;
107
import org.mustangproject.util.NodeMap;
118
import org.w3c.dom.Node;
129
import org.w3c.dom.NodeList;
@@ -90,6 +87,9 @@ public Item(NodeList itemChilds, boolean recalcPrice) {
9087
icnm.getAsNodeMap("ClassifiedTaxCategory")
9188
.flatMap(m -> m.getAsBigDecimal("Percent"))
9289
.ifPresent(product::setVATPercent);
90+
91+
92+
9393
});
9494
itemMap.getAsNodeMap("AssociatedDocumentLineDocument")
9595
.flatMap(icnm -> icnm.getAsString("LineID"))
@@ -132,6 +132,7 @@ public Item(NodeList itemChilds, boolean recalcPrice) {
132132
}
133133
}
134134

135+
135136
itemMap.getAsNodeMap("SpecifiedLineTradeAgreement", "SpecifiedSupplyChainTradeAgreement").ifPresent(icnm -> {
136137
icnm.getAsNodeMap("BuyerOrderReferencedDocument")
137138
.flatMap(bordNodes -> bordNodes.getAsString("LineID"))
@@ -622,6 +623,7 @@ public Date getDetailedDeliveryPeriodTo() {
622623
return detailedDeliveryPeriodTo;
623624
}
624625

626+
625627
public IZUGFeRDExportableItem addNotes(Collection<IncludedNote> notes) {
626628
if (notes == null) {
627629
return this;

library/src/main/java/org/mustangproject/ReferencedDocument.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
44
import com.fasterxml.jackson.annotation.JsonInclude;
5+
56
import java.util.Date;
67

78
import org.mustangproject.ZUGFeRD.IReferencedDocument;
@@ -17,6 +18,10 @@ public class ReferencedDocument implements IReferencedDocument {
1718
String referenceTypeCode;
1819
Date formattedIssueDateTime;
1920

21+
public ReferencedDocument() {
22+
//bean
23+
}
24+
2025
public ReferencedDocument(String issuerAssignedID, String typeCode, String referenceTypeCode) {
2126
this(issuerAssignedID);
2227
this.typeCode = typeCode;
@@ -36,7 +41,7 @@ public ReferencedDocument(String issuerAssingedID, Date formattedIssueDateTime)
3641
this(issuerAssingedID);
3742
this.formattedIssueDateTime = formattedIssueDateTime;
3843
}
39-
44+
4045
public ReferencedDocument(String issuerAssignedID) {
4146
this.issuerAssignedID = issuerAssignedID;
4247
}
@@ -51,6 +56,7 @@ public void setIssuerAssignedID(String issuerAssignedID) {
5156

5257
/**
5358
* which type is the document? e.g. "916" for additional invoice related
59+
*
5460
* @param typeCode as String, e.g. 916
5561
*/
5662
public void setTypeCode(String typeCode) {
@@ -59,6 +65,7 @@ public void setTypeCode(String typeCode) {
5965

6066
/**
6167
* type of the reference of this line, a UNTDID 1153 code
68+
*
6269
* @param referenceTypeCode three uppercase character reference type code as string
6370
*/
6471
public void setReferenceTypeCode(String referenceTypeCode) {
@@ -90,8 +97,7 @@ public String getReferenceTypeCode() {
9097
}
9198

9299
@Override
93-
public Date getFormattedIssueDateTime()
94-
{
100+
public Date getFormattedIssueDateTime() {
95101
return formattedIssueDateTime;
96102
}
97103

@@ -100,9 +106,20 @@ public static ReferencedDocument fromNode(Node node) {
100106
return null;
101107
}
102108
NodeMap nodes = new NodeMap(node);
103-
return new ReferencedDocument(nodes.getAsStringOrNull("IssuerAssignedID", "ID"),
109+
ReferencedDocument rd = new ReferencedDocument(nodes.getAsStringOrNull("IssuerAssignedID", "ID"),
104110
nodes.getAsStringOrNull("TypeCode", "DocumentTypeCode"),
105111
nodes.getAsStringOrNull("ReferenceTypeCode"),
106112
XMLTools.tryDate(nodes.getAsStringOrNull("FormattedIssueDateTime")));
113+
if (nodes.getAsStringOrNull("ID") != null) {
114+
//sure sign for UBL: here ReferenceTypeCode is no element but a "schemeID" attribute to ID
115+
Node idNode = nodes.getNode("ID").get();
116+
if (idNode != null) {
117+
Node schemeIDAttr = idNode.getAttributes().getNamedItem("schemeID");
118+
if (schemeIDAttr != null) {
119+
rd.setReferenceTypeCode(schemeIDAttr.getNodeValue());
120+
}
121+
}
122+
}
123+
return rd;
107124
}
108125
}

library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,15 @@ default String getOwnForeignOrganisationID() {
214214
return null;
215215
}
216216

217+
/**
218+
* BT-17 tender or lot reference
219+
*
220+
* @return mandatory ID, optional Date
221+
*/
222+
default IReferencedDocument getTenderReferencedDocument() {
223+
return null;
224+
}
225+
217226
/**
218227
* own name
219228
*

library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableItem.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,11 @@ default String[] getNotes() {
157157

158158

159159

160-
/***
161-
* specifies the item level delivery period (there is also one on document level),
162-
* this will be included in a BillingSpecifiedPeriod element
163-
* @return the beginning of the delivery period
164-
*/
160+
/***
161+
* specifies the item level delivery period (there is also one on document level),
162+
* this will be included in a BillingSpecifiedPeriod element
163+
* @return the beginning of the delivery period
164+
*/
165165
default Date getDetailedDeliveryPeriodFrom() {
166166
return null;
167167
}

library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,18 @@ public void generateXML(IExportableTransaction trans) {
631631
}
632632
}
633633

634+
if(trans.getTenderReferencedDocument() != null){
635+
xml += "<ram:AdditionalReferencedDocument>"
636+
+ "<ram:IssuerAssignedID>" + XMLTools.encodeXML(trans.getTenderReferencedDocument().getIssuerAssignedID()) + "</ram:IssuerAssignedID>"
637+
+ "<ram:TypeCode>" + 50 + "</ram:TypeCode>";
638+
if (trans.getTenderReferencedDocument().getFormattedIssueDateTime()!=null) {
639+
final SimpleDateFormat dateFormat102 = new SimpleDateFormat("yyyyMMdd");
640+
xml += "<ram:FormattedIssueDateTime><qdt:DateTimeString format=\"102\">"+XMLTools.encodeXML(dateFormat102.format(trans.getTenderReferencedDocument().getFormattedIssueDateTime()))+"</qdt:DateTimeString></ram:FormattedIssueDateTime>";
641+
}
642+
643+
644+
xml += "</ram:AdditionalReferencedDocument>";
645+
}
634646
if (trans.getSpecifiedProcuringProjectID() != null) {
635647
xml += "<ram:SpecifiedProcuringProject>"
636648
+ "<ram:ID>" + XMLTools.encodeXML(trans.getSpecifiedProcuringProjectID()) + "</ram:ID>";

library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,19 @@ public Invoice extractInto(Invoice zpp) throws XPathExpressionException, ParseEx
606606
if (!issueDateStr.isEmpty()) {
607607
issueDate = parseDate(issueDateStr, "yyyy-MM-dd");
608608
}
609+
610+
String tenderReference = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"OriginatorDocumentReference\"]/*[local-name()=\"ID\"]").trim();
611+
String tenderReferenceDate = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"OriginatorDocumentReference\"]/*[local-name()=\"ID\"]").trim();
612+
//if (tenderReference!=null) zpp... @todo bt-17 create a ubl with a date and set up an according xpath and if only tenderReference!=null only set that but if tenderReference!=null&&date!=null set both in zpp
613+
if((tenderReference != null)&&(!tenderReference.isEmpty())){
614+
if((tenderReferenceDate != null)&&(!tenderReferenceDate.isEmpty())){
615+
zpp.setTenderReferencedDocument(new ReferencedDocument(tenderReference, parseDate(tenderReferenceDate, "yyyy-MM-dd")));
616+
} else {
617+
zpp.setTenderReferencedDocument(tenderReference);
618+
}
619+
620+
}
621+
609622
String dueDt = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"DueDate\"]").trim();
610623
if (!dueDt.isEmpty()) {
611624
dueDate = parseDate(dueDt, "yyyy-MM-dd");
@@ -671,6 +684,9 @@ public Invoice extractInto(Invoice zpp) throws XPathExpressionException, ParseEx
671684
NodeList headerTradeAgreementNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
672685
String buyerOrderIssuerAssignedID = null;
673686
String sellerOrderIssuerAssignedID = null;
687+
String additionalReferencedDocument = null;
688+
Date additionalReferencedDocumentDate = null;
689+
674690
for (int i = 0; i < headerTradeAgreementNodes.getLength(); i++) {
675691
// XMLTools.trimOrNull(nodes.item(i)))) {
676692
Node headerTradeAgreementNode = headerTradeAgreementNodes.item(i);
@@ -696,12 +712,55 @@ public Invoice extractInto(Invoice zpp) throws XPathExpressionException, ParseEx
696712
}
697713
}
698714
}
715+
int typeC = 0;
716+
additionalReferencedDocument=null;
717+
additionalReferencedDocumentDate=null;
718+
//Reading BT-17
719+
if (headerTradeAgreementChilds.item(agreementChildIndex).getLocalName().equals("AdditionalReferencedDocument")) {
720+
NodeList additionalChilds = headerTradeAgreementChilds.item(agreementChildIndex).getChildNodes();
721+
for (int additionalChildIndex = 0; additionalChildIndex < additionalChilds.getLength(); additionalChildIndex++) {
722+
723+
if ((additionalChilds.item(additionalChildIndex).getLocalName() != null)
724+
&& additionalChilds.item(additionalChildIndex).getLocalName().equals("TypeCode")) {
725+
typeC = Integer.parseInt(XMLTools.trimOrNull(additionalChilds.item(additionalChildIndex)));
726+
}
727+
728+
if ((additionalChilds.item(additionalChildIndex).getLocalName() != null)
729+
&& (additionalChilds.item(additionalChildIndex).getLocalName().equals("IssuerAssignedID"))) {
730+
additionalReferencedDocument = XMLTools.trimOrNull(additionalChilds.item(additionalChildIndex));
731+
}
732+
if ((additionalChilds.item(additionalChildIndex).getLocalName() != null)
733+
&& (additionalChilds.item(additionalChildIndex).getLocalName().equals("FormattedIssueDateTime"))) {
734+
735+
NodeList FormattedIssueDateTimeChilds = additionalChilds.item(additionalChildIndex).getChildNodes();
736+
for (int dateChildIndex = 0; dateChildIndex < FormattedIssueDateTimeChilds.getLength(); dateChildIndex++) {
737+
if ((FormattedIssueDateTimeChilds.item(dateChildIndex).getLocalName() != null)
738+
&& (FormattedIssueDateTimeChilds.item(dateChildIndex).getLocalName().equals("DateTimeString"))) {
739+
additionalReferencedDocumentDate = XMLTools.tryDate(FormattedIssueDateTimeChilds.item(dateChildIndex));
740+
}
741+
742+
}
743+
}
744+
745+
}
746+
if (typeC == 50) {
747+
if (additionalReferencedDocument != null){
748+
if (additionalReferencedDocumentDate!=null) {
749+
zpp.setTenderReferencedDocument(new ReferencedDocument(additionalReferencedDocument, additionalReferencedDocumentDate));
750+
} else {
751+
zpp.setTenderReferencedDocument(additionalReferencedDocument);
752+
}
753+
}
754+
755+
}
756+
}
699757
}
700758
}
701-
702759
}
703760

704761

762+
763+
705764
String currency = extractString("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]/*[local-name()=\"InvoiceCurrencyCode\"]|//*[local-name()=\"DocumentCurrencyCode\"]");
706765
zpp.setCurrency(currency);
707766

@@ -936,6 +995,7 @@ public Invoice extractInto(Invoice zpp) throws XPathExpressionException, ParseEx
936995
zpp.setDespatchAdviceReferencedDocumentID(s);
937996
}
938997
}
998+
939999
String invoiceReferencedDocumentID = extractString("//*[local-name()=\"InvoiceReferencedDocument\"]/*[local-name()=\"IssuerAssignedID\"]|//*[local-name()=\"BillingReference\"]/*[local-name()=\"InvoiceDocumentReference\"]/*[local-name()=\"ID\"]");
9401000
if (!invoiceReferencedDocumentID.isEmpty()) {
9411001
zpp.setInvoiceReferencedDocumentID(invoiceReferencedDocumentID);

library/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,38 @@ public String getOwnCountry() {
144144
return "DE";
145145
}
146146

147+
@Override
148+
public IReferencedDocument getTenderReferencedDocument() {
149+
return new IReferencedDocument() {
150+
@Override
151+
public String getIssuerAssignedID() {
152+
return "983-jk-787";
153+
}
154+
155+
@Override
156+
public String getTypeCode() {
157+
return "50";
158+
}
159+
160+
@Override
161+
public String getReferenceTypeCode() {
162+
return "";
163+
}
164+
165+
@Override
166+
public Date getFormattedIssueDateTime() {
167+
SimpleDateFormat sdf=new SimpleDateFormat("YYYY-mm-dd");
168+
try {
169+
return sdf.parse("2025-10-12");
170+
} catch (ParseException e) {
171+
// wont happen, I promise :-)
172+
}
173+
return null; // wont happen either
174+
}
175+
176+
};
177+
}
178+
147179
@Override
148180
public String getOwnLocation() {
149181
return "Stadthausen";

library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,9 @@ public void testPushEdge() {
596596
try {
597597
SchemedID gtin = new SchemedID("0160", "2001015001325");
598598
SchemedID gln = new SchemedID("0088", "4304171000002");
599+
ReferencedDocument dr1=new ReferencedDocument("90-kl-98798-C", sdf.parse("2025-10-12"));
600+
ReferencedDocument dr2=new ReferencedDocument("90-kl-98798-C1", sdf.parse("2025-10-13"));
601+
dr2.setReferenceTypeCode("AAG");
599602
ze.setTransaction(new Invoice().setCurrency("CHF").addNote("document level 1/2").addNote("document level 2/2").setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setPaymentReference("Verwendungszweck").setDocumentName("Rechnung")
600603
.setSellerOrderReferencedDocumentID("9384").setBuyerOrderReferencedDocumentID("28934")
601604
.setDetailedDeliveryPeriod(new SimpleDateFormat("yyyyMMdd").parse(occurrenceFrom), new SimpleDateFormat("yyyyMMdd").parse(occurrenceTo))
@@ -604,10 +607,12 @@ public void testPushEdge() {
604607
.setContractReferencedDocument(contractID)
605608
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addGlobalID(gln).setEmail("recipient@test.org").addVATID("DE4711")
606609
.setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE").setFax("++49555123456")).setAdditionalAddress("Hinterhaus 3"))
607-
.addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(16)).addGlobalID(gtin).setSellerAssignedID("4711"), price, new BigDecimal(1.0)).setId("a123").addBuyerOrderReferencedDocumentID("orderId").addBuyerOrderReferencedDocumentLineID("xxx").addReferencedLineID("xxx").addNote("item level 1/1").addAllowance(new Allowance(new BigDecimal(0.02)).setReason("item discount").setTaxPercent(new BigDecimal(16))).setDetailedDeliveryPeriod(sdf.parse("2020-01-13"), sdf.parse("2020-01-15")))
610+
.addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(16)).addGlobalID(gtin).setSellerAssignedID("4711"), price, new BigDecimal(1.0)).setId("a123").
611+
addAdditionalReference(dr2).addBuyerOrderReferencedDocumentID("orderId").addBuyerOrderReferencedDocumentLineID("xxx").addReferencedLineID("xxx").addNote("item level 1/1").addAllowance(new Allowance(new BigDecimal(0.02)).setReason("item discount").setTaxPercent(new BigDecimal(16))).setDetailedDeliveryPeriod(sdf.parse("2020-01-13"), sdf.parse("2020-01-15")))
608612
.addCharge(new Charge(new BigDecimal(0.5)).setReason("quick delivery charge").setTaxPercent(new BigDecimal(16)))
609613
.addAllowance(new Allowance(new BigDecimal(0.2)).setReason("discount").setTaxPercent(new BigDecimal(16)))
610614
.addCashDiscount(new CashDiscount(new BigDecimal(2), 14))
615+
.setTenderReferencedDocument(dr1)
611616
.setDeliveryDate(sdf.parse("2020-11-02")).setNumber(number).setVATDueDateTypeCode(EventTimeCodeTypeConstants.PAYMENT_DATE)
612617
.setInvoiceReferencedDocumentID("abc123").addInvoiceReferencedDocument(new ReferencedDocument("abcd1234"))
613618
);

0 commit comments

Comments
 (0)