Merge branch 'master' into InvoiceeInvoicer

This commit is contained in:
Frank Langelage
2025-11-01 15:29:54 +01:00
committed by GitHub
23 changed files with 869 additions and 28 deletions

View File

@@ -54,6 +54,7 @@ public class Invoice implements IExportableTransaction {
protected BigDecimal totalPrepaidAmount = null;
protected Date detailedDeliveryDateStart = null;
protected Date detailedDeliveryPeriodEnd = null;
protected IReferencedDocument tenderReference = null;
protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<>(),
Charges = new ArrayList<>(), LogisticsServiceCharges = new ArrayList<>();
@@ -135,8 +136,8 @@ public class Invoice implements IExportableTransaction {
}
@Override
public IZUGFeRDCashDiscount[] getCashDiscounts() {
return cashDiscounts.toArray(new IZUGFeRDCashDiscount[0]);
public CashDiscount[] getCashDiscounts() {
return cashDiscounts.toArray(new CashDiscount[0]);
}
@Override
@@ -144,6 +145,35 @@ public class Invoice implements IExportableTransaction {
return number;
}
@Override
/***
* BT-17
*/
public IReferencedDocument getTenderReferencedDocument() {
return tenderReference;
}
/***
* BT-17
* @param dr
* @return
*/
public Invoice setTenderReferencedDocument(ReferencedDocument dr) {
dr.setTypeCode("50");//50 is fixed for tender documents
tenderReference=dr;
return this;
}
public Invoice setTenderReferencedDocument(String ID) {
ReferencedDocument dr=new ReferencedDocument(ID);
setTenderReferencedDocument(dr);
return this;
}
public Invoice setNumber(String number) {
this.number = number;
return this;

View File

@@ -3,10 +3,7 @@ package org.mustangproject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.mustangproject.ZUGFeRD.IReferencedDocument;
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem;
import org.mustangproject.ZUGFeRD.LineCalculator;
import org.mustangproject.ZUGFeRD.*;
import org.mustangproject.util.NodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -90,6 +87,9 @@ public class Item implements IZUGFeRDExportableItem {
icnm.getAsNodeMap("ClassifiedTaxCategory")
.flatMap(m -> m.getAsBigDecimal("Percent"))
.ifPresent(product::setVATPercent);
});
itemMap.getAsNodeMap("AssociatedDocumentLineDocument")
.flatMap(icnm -> icnm.getAsString("LineID"))
@@ -132,6 +132,7 @@ public class Item implements IZUGFeRDExportableItem {
}
}
itemMap.getAsNodeMap("SpecifiedLineTradeAgreement", "SpecifiedSupplyChainTradeAgreement").ifPresent(icnm -> {
icnm.getAsNodeMap("BuyerOrderReferencedDocument")
.flatMap(bordNodes -> bordNodes.getAsString("LineID"))
@@ -622,6 +623,7 @@ public class Item implements IZUGFeRDExportableItem {
return detailedDeliveryPeriodTo;
}
public IZUGFeRDExportableItem addNotes(Collection<IncludedNote> notes) {
if (notes == null) {
return this;

View File

@@ -2,6 +2,7 @@ package org.mustangproject;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.util.Date;
import org.mustangproject.ZUGFeRD.IReferencedDocument;
@@ -17,6 +18,10 @@ public class ReferencedDocument implements IReferencedDocument {
String referenceTypeCode;
Date formattedIssueDateTime;
public ReferencedDocument() {
//bean
}
public ReferencedDocument(String issuerAssignedID, String typeCode, String referenceTypeCode) {
this(issuerAssignedID);
this.typeCode = typeCode;
@@ -36,7 +41,7 @@ public class ReferencedDocument implements IReferencedDocument {
this(issuerAssingedID);
this.formattedIssueDateTime = formattedIssueDateTime;
}
public ReferencedDocument(String issuerAssignedID) {
this.issuerAssignedID = issuerAssignedID;
}
@@ -51,6 +56,7 @@ public class ReferencedDocument implements IReferencedDocument {
/**
* which type is the document? e.g. "916" for additional invoice related
*
* @param typeCode as String, e.g. 916
*/
public void setTypeCode(String typeCode) {
@@ -59,6 +65,7 @@ public class ReferencedDocument implements IReferencedDocument {
/**
* type of the reference of this line, a UNTDID 1153 code
*
* @param referenceTypeCode three uppercase character reference type code as string
*/
public void setReferenceTypeCode(String referenceTypeCode) {
@@ -90,8 +97,7 @@ public class ReferencedDocument implements IReferencedDocument {
}
@Override
public Date getFormattedIssueDateTime()
{
public Date getFormattedIssueDateTime() {
return formattedIssueDateTime;
}
@@ -100,9 +106,20 @@ public class ReferencedDocument implements IReferencedDocument {
return null;
}
NodeMap nodes = new NodeMap(node);
return new ReferencedDocument(nodes.getAsStringOrNull("IssuerAssignedID", "ID"),
ReferencedDocument rd = new ReferencedDocument(nodes.getAsStringOrNull("IssuerAssignedID", "ID"),
nodes.getAsStringOrNull("TypeCode", "DocumentTypeCode"),
nodes.getAsStringOrNull("ReferenceTypeCode"),
XMLTools.tryDate(nodes.getAsStringOrNull("FormattedIssueDateTime")));
if (nodes.getAsStringOrNull("ID") != null) {
//sure sign for UBL: here ReferenceTypeCode is no element but a "schemeID" attribute to ID
Node idNode = nodes.getNode("ID").get();
if (idNode != null) {
Node schemeIDAttr = idNode.getAttributes().getNamedItem("schemeID");
if (schemeIDAttr != null) {
rd.setReferenceTypeCode(schemeIDAttr.getNodeValue());
}
}
}
return rd;
}
}

View File

@@ -215,6 +215,15 @@ public interface IExportableTransaction {
return null;
}
/**
* BT-17 tender or lot reference
*
* @return mandatory ID, optional Date
*/
default IReferencedDocument getTenderReferencedDocument() {
return null;
}
/**
* own name
*

View File

@@ -157,11 +157,11 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
/***
* specifies the item level delivery period (there is also one on document level),
* this will be included in a BillingSpecifiedPeriod element
* @return the beginning of the delivery period
*/
/***
* specifies the item level delivery period (there is also one on document level),
* this will be included in a BillingSpecifiedPeriod element
* @return the beginning of the delivery period
*/
default Date getDetailedDeliveryPeriodFrom() {
return null;
}

View File

@@ -73,7 +73,7 @@ public class LineCalculator {
}
if (currentItem.getProduct().getCharges()!=null) {
for (IZUGFeRDAllowanceCharge ccaf : currentItem.getProduct().getCharges()) {
delta = delta.subtract(ccaf.getTotalAmount(currentItem));
delta = delta.add(ccaf.getTotalAmount(currentItem));
}
}
}

View File

@@ -631,6 +631,18 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
}
}
if(trans.getTenderReferencedDocument() != null){
xml += "<ram:AdditionalReferencedDocument>"
+ "<ram:IssuerAssignedID>" + XMLTools.encodeXML(trans.getTenderReferencedDocument().getIssuerAssignedID()) + "</ram:IssuerAssignedID>"
+ "<ram:TypeCode>" + 50 + "</ram:TypeCode>";
if (trans.getTenderReferencedDocument().getFormattedIssueDateTime()!=null) {
final SimpleDateFormat dateFormat102 = new SimpleDateFormat("yyyyMMdd");
xml += "<ram:FormattedIssueDateTime><qdt:DateTimeString format=\"102\">"+XMLTools.encodeXML(dateFormat102.format(trans.getTenderReferencedDocument().getFormattedIssueDateTime()))+"</qdt:DateTimeString></ram:FormattedIssueDateTime>";
}
xml += "</ram:AdditionalReferencedDocument>";
}
if (trans.getSpecifiedProcuringProjectID() != null) {
xml += "<ram:SpecifiedProcuringProject>"
+ "<ram:ID>" + XMLTools.encodeXML(trans.getSpecifiedProcuringProjectID()) + "</ram:ID>";

View File

@@ -696,6 +696,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
if ((meta != null) && (meta.getLength() > 0)) {
try {
DomXmpParser xmpParser = new DomXmpParser();
xmpParser.setStrictParsing(false);
return xmpParser.parse(meta.toByteArray());
} catch (XmpParsingException e) {
throw new IOException(e);

View File

@@ -111,6 +111,7 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter {
if (metadata != null) {
try {
DomXmpParser xmpParser = new DomXmpParser();
xmpParser.setStrictParsing(false);
XMPMetadata xmp = xmpParser.parse(metadata.createInputStream());
PDFAIdentificationSchema pdfaSchema = xmp.getPDFAIdentificationSchema();

View File

@@ -612,6 +612,18 @@ public class ZUGFeRDInvoiceImporter {
if (!issueDateStr.isEmpty()) {
issueDate = parseDate(issueDateStr, "yyyy-MM-dd");
}
String tenderReference = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"OriginatorDocumentReference\"]/*[local-name()=\"ID\"]").trim();
String tenderReferenceDate = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"OriginatorDocumentReference\"]/*[local-name()=\"ID\"]").trim();
if((tenderReference != null)&&(!tenderReference.isEmpty())){
if((tenderReferenceDate != null)&&(!tenderReferenceDate.isEmpty())){
zpp.setTenderReferencedDocument(new ReferencedDocument(tenderReference, parseDate(tenderReferenceDate, "yyyy-MM-dd")));
} else {
zpp.setTenderReferencedDocument(tenderReference);
}
}
String dueDt = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"DueDate\"]").trim();
if (!dueDt.isEmpty()) {
dueDate = parseDate(dueDt, "yyyy-MM-dd");
@@ -677,6 +689,9 @@ public class ZUGFeRDInvoiceImporter {
NodeList headerTradeAgreementNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
String buyerOrderIssuerAssignedID = null;
String sellerOrderIssuerAssignedID = null;
String additionalReferencedDocument = null;
Date additionalReferencedDocumentDate = null;
for (int i = 0; i < headerTradeAgreementNodes.getLength(); i++) {
// XMLTools.trimOrNull(nodes.item(i)))) {
Node headerTradeAgreementNode = headerTradeAgreementNodes.item(i);
@@ -702,12 +717,55 @@ public class ZUGFeRDInvoiceImporter {
}
}
}
int typeC = 0;
additionalReferencedDocument=null;
additionalReferencedDocumentDate=null;
//Reading BT-17
if (headerTradeAgreementChilds.item(agreementChildIndex).getLocalName().equals("AdditionalReferencedDocument")) {
NodeList additionalChilds = headerTradeAgreementChilds.item(agreementChildIndex).getChildNodes();
for (int additionalChildIndex = 0; additionalChildIndex < additionalChilds.getLength(); additionalChildIndex++) {
if ((additionalChilds.item(additionalChildIndex).getLocalName() != null)
&& additionalChilds.item(additionalChildIndex).getLocalName().equals("TypeCode")) {
typeC = Integer.parseInt(XMLTools.trimOrNull(additionalChilds.item(additionalChildIndex)));
}
if ((additionalChilds.item(additionalChildIndex).getLocalName() != null)
&& (additionalChilds.item(additionalChildIndex).getLocalName().equals("IssuerAssignedID"))) {
additionalReferencedDocument = XMLTools.trimOrNull(additionalChilds.item(additionalChildIndex));
}
if ((additionalChilds.item(additionalChildIndex).getLocalName() != null)
&& (additionalChilds.item(additionalChildIndex).getLocalName().equals("FormattedIssueDateTime"))) {
NodeList FormattedIssueDateTimeChilds = additionalChilds.item(additionalChildIndex).getChildNodes();
for (int dateChildIndex = 0; dateChildIndex < FormattedIssueDateTimeChilds.getLength(); dateChildIndex++) {
if ((FormattedIssueDateTimeChilds.item(dateChildIndex).getLocalName() != null)
&& (FormattedIssueDateTimeChilds.item(dateChildIndex).getLocalName().equals("DateTimeString"))) {
additionalReferencedDocumentDate = XMLTools.tryDate(FormattedIssueDateTimeChilds.item(dateChildIndex));
}
}
}
}
if (typeC == 50) {
if (additionalReferencedDocument != null){
if (additionalReferencedDocumentDate!=null) {
zpp.setTenderReferencedDocument(new ReferencedDocument(additionalReferencedDocument, additionalReferencedDocumentDate));
} else {
zpp.setTenderReferencedDocument(additionalReferencedDocument);
}
}
}
}
}
}
}
String currency = extractString("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]/*[local-name()=\"InvoiceCurrencyCode\"]|//*[local-name()=\"DocumentCurrencyCode\"]");
zpp.setCurrency(currency);
@@ -950,6 +1008,7 @@ public class ZUGFeRDInvoiceImporter {
zpp.setDespatchAdviceReferencedDocumentID(s);
}
}
String invoiceReferencedDocumentID = extractString("//*[local-name()=\"InvoiceReferencedDocument\"]/*[local-name()=\"IssuerAssignedID\"]|//*[local-name()=\"BillingReference\"]/*[local-name()=\"InvoiceDocumentReference\"]/*[local-name()=\"ID\"]");
if (!invoiceReferencedDocumentID.isEmpty()) {
zpp.setInvoiceReferencedDocumentID(invoiceReferencedDocumentID);