deliveradvice corrections
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
- upgraded en16931 validation to 1.3.8
|
||||||
|
- Be able to embed Cross Industry Delivery Advice
|
||||||
|
- update xr to v. 2.2
|
||||||
2.5.0
|
2.5.0
|
||||||
=======
|
=======
|
||||||
2022-04-07
|
2022-04-07
|
||||||
|
|||||||
@@ -580,7 +580,7 @@ public class Main {
|
|||||||
|
|
||||||
if (format == null) {
|
if (format == null) {
|
||||||
try {
|
try {
|
||||||
format = getStringFromUser("Format (fx=Factur-X, zf=ZUGFeRD, ox=Order-X)", "zf", "fx|zf|ox|dx");
|
format = getStringFromUser("Format (fx=Factur-X, zf=ZUGFeRD, ox=Order-X, da=Cross Industry Despatch Advice)", "zf", "fx|zf|ox|da");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.error(e.getMessage(), e);
|
LOGGER.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
@@ -603,7 +603,7 @@ public class Main {
|
|||||||
try {
|
try {
|
||||||
if ((format.equals("zf") && (zfIntVersion == 1)) || (format.equals("ox") )) {
|
if ((format.equals("zf") && (zfIntVersion == 1)) || (format.equals("ox") )) {
|
||||||
zfProfile = getStringFromUser("Profile (b)asic, (c)omfort or ex(t)ended", "t", "B|b|C|c|T|t");
|
zfProfile = getStringFromUser("Profile (b)asic, (c)omfort or ex(t)ended", "t", "B|b|C|c|T|t");
|
||||||
} else if ( (format.equals("dx"))) {
|
} else if ( (format.equals("da"))) {
|
||||||
zfProfile = getStringFromUser("Profile (p)ilot", "p", "P|p");
|
zfProfile = getStringFromUser("Profile (p)ilot", "p", "P|p");
|
||||||
} else {
|
} else {
|
||||||
zfProfile = getStringFromUser(
|
zfProfile = getStringFromUser(
|
||||||
@@ -630,8 +630,8 @@ public class Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EStandard standard=EStandard.facturx;
|
EStandard standard=EStandard.facturx;
|
||||||
if (format.equals("dx")) {
|
if (format.equals("da")) {
|
||||||
standard=EStandard.deliverx;
|
standard=EStandard.deliveradvice;
|
||||||
|
|
||||||
zfConformanceLevelProfile = Profiles.getByName(standard, "PILOT", 1);
|
zfConformanceLevelProfile = Profiles.getByName(standard, "PILOT", 1);
|
||||||
}
|
}
|
||||||
@@ -682,7 +682,7 @@ public class Main {
|
|||||||
((OXExporterFromA1)ze).ignorePDFAErrors();
|
((OXExporterFromA1)ze).ignorePDFAErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (format.equals("dx")) {
|
} else if (format.equals("da")) {
|
||||||
ze = new DXExporterFromA1().setProducer("Mustang-cli")
|
ze = new DXExporterFromA1().setProducer("Mustang-cli")
|
||||||
.setZUGFeRDVersion(zfIntVersion)
|
.setZUGFeRDVersion(zfIntVersion)
|
||||||
.setCreator(System.getProperty("user.name")).setProfile(zfConformanceLevelProfile);
|
.setCreator(System.getProperty("user.name")).setProfile(zfConformanceLevelProfile);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package org.mustangproject;
|
package org.mustangproject;
|
||||||
|
|
||||||
public enum EStandard {
|
public enum EStandard {
|
||||||
facturx, orderx, deliverx, zugferd, cii, ubl
|
facturx, orderx, deliveradvice, zugferd, cii, ubl
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,358 @@
|
|||||||
|
/**
|
||||||
|
* *********************************************************************
|
||||||
|
* <p>
|
||||||
|
* Copyright 2018 Jochen Staerk
|
||||||
|
* <p>
|
||||||
|
* Use is subject to license terms.
|
||||||
|
* <p>
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy
|
||||||
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* <p>
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* <p>
|
||||||
|
* **********************************************************************
|
||||||
|
*/
|
||||||
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
|
import static org.mustangproject.ZUGFeRD.ZUGFeRDDateFormat.DATE;
|
||||||
|
import static org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants.CORRECTEDINVOICE;
|
||||||
|
import static org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants.CATEGORY_CODES_WITH_EXEMPTION_REASON;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.mustangproject.*;
|
||||||
|
|
||||||
|
public class DAPullProvider extends ZUGFeRD2PullProvider implements IXMLProvider {
|
||||||
|
|
||||||
|
protected IExportableTransaction trans;
|
||||||
|
private String paymentTermsDescription;
|
||||||
|
protected Profile profile = Profiles.getByName(EStandard.deliveradvice,"pilot", 1);
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateXML(IExportableTransaction trans) {
|
||||||
|
this.trans = trans;
|
||||||
|
boolean hasDueDate = false;
|
||||||
|
final SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy");
|
||||||
|
|
||||||
|
final String exemptionReason = "";
|
||||||
|
|
||||||
|
String senderReg = "";
|
||||||
|
if (trans.getOwnOrganisationFullPlaintextInfo() != null) {
|
||||||
|
senderReg = "<ram:IncludedNote><ram:Content>"
|
||||||
|
+ XMLTools.encodeXML(trans.getOwnOrganisationFullPlaintextInfo()) + "</ram:Content>"
|
||||||
|
+ "<ram:SubjectCode>REG</ram:SubjectCode></ram:IncludedNote>";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
String subjectNote = "";
|
||||||
|
if (trans.getSubjectNote() != null) {
|
||||||
|
subjectNote = "<ram:IncludedNote><ram:Content>"
|
||||||
|
+ XMLTools.encodeXML(trans.getSubjectNote()) + "</ram:Content>"
|
||||||
|
+ "</ram:IncludedNote>";
|
||||||
|
}
|
||||||
|
|
||||||
|
final String typecode = "220";
|
||||||
|
/*if (trans.getDocumentCode() != null) {
|
||||||
|
typecode = trans.getDocumentCode();
|
||||||
|
}*/
|
||||||
|
String notes = "";
|
||||||
|
if (trans.getNotes() != null) {
|
||||||
|
for (final String currentNote : trans.getNotes()) {
|
||||||
|
notes += "<ram:IncludedNote><ram:Content>" + XMLTools.encodeXML(currentNote) + "</ram:Content></ram:IncludedNote>";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String testBooleanStr="true";
|
||||||
|
String xml = "<SCRDMCCBDACIDAMessageStructure\n" +
|
||||||
|
" xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:25\"\n" +
|
||||||
|
" xmlns:ram=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:101\"\n" +
|
||||||
|
" xmlns:px=\"urn:un:unece:uncefact:data:standard:SCRDMCCBDACIDAMessageStructure:1\">\n"
|
||||||
|
// + "
|
||||||
|
// xsi:schemaLocation=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100
|
||||||
|
// ../Schema/ZUGFeRD1p0.xsd\""
|
||||||
|
+ "<px:ExchangedDocumentContext>"
|
||||||
|
// + "
|
||||||
|
+" <ram:TestIndicator><udt:Indicator>"+testBooleanStr+"</udt:Indicator></ram:TestIndicator>\n"
|
||||||
|
//
|
||||||
|
+ "<ram:BusinessProcessSpecifiedDocumentContextParameter>"
|
||||||
|
+ "<ram:ID>" + getProfile().getID() + "</ram:ID>"
|
||||||
|
+ "</ram:BusinessProcessSpecifiedDocumentContextParameter>"
|
||||||
|
+ "</px:ExchangedDocumentContext>"
|
||||||
|
+ "<px:ExchangedDocument>"
|
||||||
|
+ "<ram:ID>" + XMLTools.encodeXML(trans.getNumber()) + "</ram:ID>"
|
||||||
|
// + " <ram:Name>RECHNUNG</ram:Name>"
|
||||||
|
// + "<ram:TypeCode>380</ram:TypeCode>"
|
||||||
|
+ "<ram:TypeCode>" + typecode + "</ram:TypeCode>"
|
||||||
|
+ "<ram:IssueDateTime>"
|
||||||
|
+ DATE.udtFormat(trans.getIssueDate()) + "</ram:IssueDateTime>" // date
|
||||||
|
+ notes
|
||||||
|
+ subjectNote
|
||||||
|
+ senderReg
|
||||||
|
|
||||||
|
+ "</px:ExchangedDocument>"
|
||||||
|
+ "<px:SupplyChainTradeTransaction>";
|
||||||
|
int lineID = 0;
|
||||||
|
for (final IZUGFeRDExportableItem currentItem : trans.getZFItems()) {
|
||||||
|
lineID++;
|
||||||
|
if (currentItem.getProduct().getTaxExemptionReason() != null) {
|
||||||
|
// exemptionReason = "<ram:ExemptionReason>" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + "</ram:ExemptionReason>";
|
||||||
|
}
|
||||||
|
notes = "";
|
||||||
|
if (currentItem.getNotes() != null) {
|
||||||
|
for (final String currentNote : currentItem.getNotes()) {
|
||||||
|
notes = notes + "<ram:IncludedNote><ram:Content>" + XMLTools.encodeXML(currentNote) + "</ram:Content></ram:IncludedNote>";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final LineCalculator lc = new LineCalculator(currentItem);
|
||||||
|
xml += "<ram:IncludedSupplyChainTradeLineItem>" +
|
||||||
|
"<ram:AssociatedDocumentLineDocument>"
|
||||||
|
+ "<ram:LineID>" + lineID + "</ram:LineID>"
|
||||||
|
+ notes
|
||||||
|
+ "</ram:AssociatedDocumentLineDocument>"
|
||||||
|
|
||||||
|
+ "<ram:SpecifiedTradeProduct>";
|
||||||
|
// + " <GlobalID schemeID=\"0160\">4012345001235</GlobalID>"
|
||||||
|
if (currentItem.getProduct().getSellerAssignedID() != null) {
|
||||||
|
xml += "<ram:SellerAssignedID>"
|
||||||
|
+ XMLTools.encodeXML(currentItem.getProduct().getSellerAssignedID()) + "</ram:SellerAssignedID>";
|
||||||
|
}
|
||||||
|
if (currentItem.getProduct().getBuyerAssignedID() != null) {
|
||||||
|
xml += "<ram:BuyerAssignedID>"
|
||||||
|
+ XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "</ram:BuyerAssignedID>";
|
||||||
|
}
|
||||||
|
String allowanceChargeStr = "";
|
||||||
|
if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) {
|
||||||
|
for (final IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) {
|
||||||
|
allowanceChargeStr += getAllowanceChargeStr(allowance, currentItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
|
||||||
|
for (final IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
|
||||||
|
allowanceChargeStr += getAllowanceChargeStr(charge, currentItem);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xml += "<ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>"
|
||||||
|
+ "<ram:Description>" + XMLTools.encodeXML(currentItem.getProduct().getDescription())
|
||||||
|
+ "</ram:Description>"
|
||||||
|
+ "</ram:SpecifiedTradeProduct>"
|
||||||
|
|
||||||
|
+ "<ram:SpecifiedLineTradeDelivery>"
|
||||||
|
+ "<ram:DespatchedQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit()) + "\">"
|
||||||
|
+ quantityFormat(currentItem.getQuantity()) + "</ram:DespatchedQuantity>"
|
||||||
|
+ "</ram:SpecifiedLineTradeDelivery>"
|
||||||
|
+ "<ram:SpecifiedLineTradeSettlement>";
|
||||||
|
if ((currentItem.getDetailedDeliveryPeriodFrom() != null) || (currentItem.getDetailedDeliveryPeriodTo() != null)) {
|
||||||
|
xml += "<ram:BillingSpecifiedPeriod>";
|
||||||
|
if (currentItem.getDetailedDeliveryPeriodFrom() != null) {
|
||||||
|
xml += "<ram:StartDateTime>" + DATE.udtFormat(currentItem.getDetailedDeliveryPeriodFrom()) + "</ram:StartDateTime>";
|
||||||
|
}
|
||||||
|
if (currentItem.getDetailedDeliveryPeriodTo() != null) {
|
||||||
|
xml += "<ram:EndDateTime>" + DATE.udtFormat(currentItem.getDetailedDeliveryPeriodTo()) + "</ram:EndDateTime>";
|
||||||
|
}
|
||||||
|
xml += "</ram:BillingSpecifiedPeriod>";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
xml += "<ram:SpecifiedTradeSettlementLineMonetarySummation>"
|
||||||
|
+ "<ram:LineTotalAmount>" + currencyFormat(lc.getItemTotalNetAmount())
|
||||||
|
+ "</ram:LineTotalAmount>" // currencyID=\"EUR\"
|
||||||
|
+ "</ram:SpecifiedTradeSettlementLineMonetarySummation>";
|
||||||
|
/* if (currentItem.getAdditionalReferencedDocumentID() != null) {
|
||||||
|
xml += "<ram:AdditionalReferencedDocument><ram:IssuerAssignedID>" + currentItem.getAdditionalReferencedDocumentID() + "</ram:IssuerAssignedID><ram:TypeCode>130</ram:TypeCode></ram:AdditionalReferencedDocument>";
|
||||||
|
|
||||||
|
}*/
|
||||||
|
xml += "</ram:SpecifiedLineTradeSettlement>"
|
||||||
|
+ "</ram:IncludedSupplyChainTradeLineItem>";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
xml += "<ram:ApplicableHeaderTradeAgreement>";
|
||||||
|
if (trans.getReferenceNumber() != null) {
|
||||||
|
xml += "<ram:BuyerReference>" + XMLTools.encodeXML(trans.getReferenceNumber()) + "</ram:BuyerReference>";
|
||||||
|
|
||||||
|
}
|
||||||
|
xml += "<ram:SellerTradeParty>"
|
||||||
|
+ getTradePartyAsXML(trans.getSender(), true, false)
|
||||||
|
+ "</ram:SellerTradeParty>"
|
||||||
|
+ "<ram:BuyerTradeParty>";
|
||||||
|
// + " <ID>GE2020211</ID>"
|
||||||
|
// + " <GlobalID schemeID=\"0088\">4000001987658</GlobalID>"
|
||||||
|
|
||||||
|
xml += getTradePartyAsXML(trans.getRecipient(), false, false);
|
||||||
|
xml += "</ram:BuyerTradeParty>";
|
||||||
|
|
||||||
|
if (trans.getSellerOrderReferencedDocumentID() != null) {
|
||||||
|
xml += "<ram:SellerOrderReferencedDocument>"
|
||||||
|
+ "<ram:IssuerAssignedID>"
|
||||||
|
+ XMLTools.encodeXML(trans.getSellerOrderReferencedDocumentID()) + "</ram:IssuerAssignedID>"
|
||||||
|
+ "</ram:SellerOrderReferencedDocument>";
|
||||||
|
}
|
||||||
|
if (trans.getBuyerOrderReferencedDocumentID() != null) {
|
||||||
|
xml += "<ram:BuyerOrderReferencedDocument>"
|
||||||
|
+ "<ram:IssuerAssignedID>"
|
||||||
|
+ XMLTools.encodeXML(trans.getBuyerOrderReferencedDocumentID()) + "</ram:IssuerAssignedID>"
|
||||||
|
+ "</ram:BuyerOrderReferencedDocument>";
|
||||||
|
}
|
||||||
|
if (trans.getContractReferencedDocument() != null) {
|
||||||
|
xml += "<ram:ContractReferencedDocument>"
|
||||||
|
+ "<ram:IssuerAssignedID>"
|
||||||
|
+ XMLTools.encodeXML(trans.getContractReferencedDocument()) + "</ram:IssuerAssignedID>"
|
||||||
|
+ "</ram:ContractReferencedDocument>";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional Documents of XRechnung (Rechnungsbegruendende Unterlagen - BG-24 XRechnung)
|
||||||
|
if (trans.getAdditionalReferencedDocuments() != null) {
|
||||||
|
for (final FileAttachment f : trans.getAdditionalReferencedDocuments()) {
|
||||||
|
final String documentContent = new String(Base64.getEncoder().encodeToString(f.getData()));
|
||||||
|
xml += "<ram:AdditionalReferencedDocument>"
|
||||||
|
+ "<ram:IssuerAssignedID>" + f.getFilename() + "</ram:IssuerAssignedID>"
|
||||||
|
+ "<ram:TypeCode>916</ram:TypeCode>"
|
||||||
|
+ "<ram:Name>" + f.getDescription() + "</ram:Name>"
|
||||||
|
+ "<ram:AttachmentBinaryObject mimeCode=\"" + f.getMimetype() + "\"\n"
|
||||||
|
+ "filename=\"" + f.getFilename() + "\">" + documentContent + "</ram:AttachmentBinaryObject>"
|
||||||
|
+ "</ram:AdditionalReferencedDocument>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trans.getSpecifiedProcuringProjectID() != null) {
|
||||||
|
xml += "<ram:SpecifiedProcuringProject>"
|
||||||
|
+ "<ram:ID>"
|
||||||
|
+ XMLTools.encodeXML(trans.getSpecifiedProcuringProjectID()) + "</ram:ID>";
|
||||||
|
if (trans.getSpecifiedProcuringProjectName() != null) {
|
||||||
|
xml += "<ram:Name >" + XMLTools.encodeXML(trans.getSpecifiedProcuringProjectName()) + "</ram:Name>";
|
||||||
|
}
|
||||||
|
xml += "</ram:SpecifiedProcuringProject>";
|
||||||
|
}
|
||||||
|
xml += "</ram:ApplicableHeaderTradeAgreement>"
|
||||||
|
+ "<ram:ApplicableHeaderTradeDelivery>";
|
||||||
|
if (this.trans.getDeliveryAddress() != null) {
|
||||||
|
xml += "<ram:ShipToTradeParty>" +
|
||||||
|
getTradePartyAsXML(this.trans.getDeliveryAddress(), false, true) +
|
||||||
|
"</ram:ShipToTradeParty>";
|
||||||
|
}
|
||||||
|
xml += " <ram:ActualDespatchSupplyChainEvent>\n" +
|
||||||
|
" <ram:OccurrenceDateTime>\n" +
|
||||||
|
" <udt:DateTimeString\n" +
|
||||||
|
" format=\"102\">"+ DATE.udtFormat(trans.getDeliveryDate() )+"</udt:DateTimeString>\n" +
|
||||||
|
" </ram:OccurrenceDateTime>\n" +
|
||||||
|
" </ram:ActualDespatchSupplyChainEvent>";
|
||||||
|
|
||||||
|
/*
|
||||||
|
xml += "<ram:ActualDeliverySupplyChainEvent>"
|
||||||
|
+ "<ram:OccurrenceDateTime>";
|
||||||
|
|
||||||
|
if (trans.getDeliveryDate() != null) {
|
||||||
|
xml += DATE.udtFormat(trans.getDeliveryDate());
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("No delivery date provided");
|
||||||
|
}
|
||||||
|
xml += "</ram:OccurrenceDateTime>\n";
|
||||||
|
xml += "</ram:ActualDeliverySupplyChainEvent>\n"
|
||||||
|
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* + "<DeliveryNoteReferencedDocument>\n" +
|
||||||
|
* "<IssueDateTime format=\"102\">20130603</IssueDateTime>\n" +
|
||||||
|
* "<ID>2013-51112</ID>\n" +
|
||||||
|
* "</DeliveryNoteReferencedDocument>\n"
|
||||||
|
*/
|
||||||
|
xml+= "</ram:ApplicableHeaderTradeDelivery>\n";
|
||||||
|
// + " <IncludedSupplyChainTradeLineItem>"
|
||||||
|
// + " <AssociatedDocumentLineDocument>"
|
||||||
|
// + " <IncludedNote>"
|
||||||
|
// + " <Content>Wir erlauben uns Ihnen folgende Positionen aus der Lieferung Nr.
|
||||||
|
// 2013-51112 in Rechnung zu stellen:</Content>\n"
|
||||||
|
// + " </IncludedNote>\n"
|
||||||
|
// + " </AssociatedDocumentLineDocument>\n"
|
||||||
|
// + " </IncludedSupplyChainTradeLineItem>\n";
|
||||||
|
|
||||||
|
xml += "</px:SupplyChainTradeTransaction>"
|
||||||
|
+ "</SCRDMCCBDACIDAMessageStructure>";
|
||||||
|
|
||||||
|
final byte[] zugferdRaw;
|
||||||
|
try {
|
||||||
|
zugferdRaw = xml.getBytes("UTF-8");
|
||||||
|
|
||||||
|
zugferdData = XMLTools.removeBOM(zugferdRaw);
|
||||||
|
} catch (final UnsupportedEncodingException e) {
|
||||||
|
Logger.getLogger(OXPullProvider.class.getName()).log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProfile(Profile p) {
|
||||||
|
profile = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Profile getProfile() {
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildPaymentTermsXml() {
|
||||||
|
|
||||||
|
final IZUGFeRDPaymentTerms paymentTerms = trans.getPaymentTerms();
|
||||||
|
if (paymentTerms == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String paymentTermsXml = "<ram:SpecifiedTradePaymentTerms>";
|
||||||
|
|
||||||
|
final IZUGFeRDPaymentDiscountTerms discountTerms = paymentTerms.getDiscountTerms();
|
||||||
|
final Date dueDate = paymentTerms.getDueDate();
|
||||||
|
if (dueDate != null && discountTerms != null && discountTerms.getBaseDate() != null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"if paymentTerms.dueDate is specified, paymentTerms.discountTerms.baseDate has not to be specified");
|
||||||
|
}
|
||||||
|
paymentTermsXml += "<ram:Description>" + paymentTerms.getDescription() + "</ram:Description>";
|
||||||
|
if (dueDate != null) {
|
||||||
|
paymentTermsXml += "<ram:DueDateDateTime>";
|
||||||
|
paymentTermsXml += DATE.udtFormat(dueDate);
|
||||||
|
paymentTermsXml += "</ram:DueDateDateTime>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (discountTerms != null) {
|
||||||
|
paymentTermsXml += "<ram:ApplicableTradePaymentDiscountTerms>";
|
||||||
|
final String currency = trans.getCurrency();
|
||||||
|
final String basisAmount = currencyFormat(calc.getGrandTotal());
|
||||||
|
paymentTermsXml += "<ram:BasisAmount currencyID=\"" + currency + "\">" + basisAmount + "</ram:BasisAmount>";
|
||||||
|
paymentTermsXml += "<ram:CalculationPercent>" + discountTerms.getCalculationPercentage().toString()
|
||||||
|
+ "</ram:CalculationPercent>";
|
||||||
|
|
||||||
|
if (discountTerms.getBaseDate() != null) {
|
||||||
|
final Date baseDate = discountTerms.getBaseDate();
|
||||||
|
paymentTermsXml += "<ram:BasisDateTime>";
|
||||||
|
paymentTermsXml += DATE.udtFormat(baseDate);
|
||||||
|
paymentTermsXml += "</ram:BasisDateTime>";
|
||||||
|
|
||||||
|
paymentTermsXml += "<ram:BasisPeriodMeasure unitCode=\"" + discountTerms.getBasePeriodUnitCode() + "\">"
|
||||||
|
+ discountTerms.getBasePeriodMeasure() + "</ram:BasisPeriodMeasure>";
|
||||||
|
}
|
||||||
|
|
||||||
|
paymentTermsXml += "</ram:ApplicableTradePaymentDiscountTerms>";
|
||||||
|
}
|
||||||
|
|
||||||
|
paymentTermsXml += "</ram:SpecifiedTradePaymentTerms>";
|
||||||
|
return paymentTermsXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -105,7 +105,7 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
|||||||
* OrderX document type. As of version 1.0 it may be
|
* OrderX document type. As of version 1.0 it may be
|
||||||
* ORDER, ORDER_RESPONSE, or ORDER_CHANGE
|
* ORDER, ORDER_RESPONSE, or ORDER_CHANGE
|
||||||
*/
|
*/
|
||||||
protected String deliverXDocumentType = "DESPATCHADVICE";
|
protected String despatchAdviceDocumentType = "DESPATCHADVICE";
|
||||||
|
|
||||||
|
|
||||||
private HashMap<String, byte[]> additionalXMLs = new HashMap<String, byte[]>();
|
private HashMap<String, byte[]> additionalXMLs = new HashMap<String, byte[]>();
|
||||||
@@ -404,7 +404,7 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
|||||||
*/
|
*/
|
||||||
public DXExporterFromA3 setDocumentType(String DocumentType)
|
public DXExporterFromA3 setDocumentType(String DocumentType)
|
||||||
{
|
{
|
||||||
this.deliverXDocumentType = DocumentType;
|
this.despatchAdviceDocumentType = DocumentType;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -428,7 +428,7 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
|||||||
XMPSchemaZugferd zf = new XMPSchemaZugferd(metadata, 1, true, xmlProvider.getProfile(),
|
XMPSchemaZugferd zf = new XMPSchemaZugferd(metadata, 1, true, xmlProvider.getProfile(),
|
||||||
"urn:facturx:pdfa:CrossIndustryDocument:despatchadvice:1p0#", "fx",
|
"urn:facturx:pdfa:CrossIndustryDocument:despatchadvice:1p0#", "fx",
|
||||||
"cida.xml");
|
"cida.xml");
|
||||||
zf.setType(this.deliverXDocumentType);
|
zf.setType(this.despatchAdviceDocumentType);
|
||||||
|
|
||||||
metadata.addSchema(zf);
|
metadata.addSchema(zf);
|
||||||
// also add the schema extensions...
|
// also add the schema extensions...
|
||||||
@@ -679,7 +679,7 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DXExporterFromA3 setZUGFeRDVersion(int version) {
|
public DXExporterFromA3 setZUGFeRDVersion(int version) {
|
||||||
OXPullProvider z2p = new OXPullProvider();
|
DAPullProvider z2p = new DAPullProvider();
|
||||||
setXMLProvider(z2p);
|
setXMLProvider(z2p);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class Profiles {
|
|||||||
{"BASIC", new Profile("BASIC", "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic")},
|
{"BASIC", new Profile("BASIC", "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic")},
|
||||||
{"EN16931", new Profile("EN16931", "urn:cen.eu:en16931:2017")},
|
{"EN16931", new Profile("EN16931", "urn:cen.eu:en16931:2017")},
|
||||||
{"EXTENDED", new Profile("EXTENDED", "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended")},
|
{"EXTENDED", new Profile("EXTENDED", "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended")},
|
||||||
{"XRECHNUNG", new Profile("XRECHNUNG", "urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.1")}
|
{"XRECHNUNG", new Profile("XRECHNUNG", "urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.2")}
|
||||||
|
|
||||||
}).collect(Collectors.toMap(data -> (String) data[0], data -> (Profile) data[1]));
|
}).collect(Collectors.toMap(data -> (String) data[0], data -> (Profile) data[1]));
|
||||||
static Map<String, Profile> zf1Map = Stream.of(new Object[][]{
|
static Map<String, Profile> zf1Map = Stream.of(new Object[][]{
|
||||||
@@ -51,7 +51,7 @@ public class Profiles {
|
|||||||
|
|
||||||
}).collect(Collectors.toMap(data -> (String) data[0], data -> (Profile) data[1]));
|
}).collect(Collectors.toMap(data -> (String) data[0], data -> (Profile) data[1]));
|
||||||
static Map<String, Profile> dx1Map = Stream.of(new Object[][]{
|
static Map<String, Profile> dx1Map = Stream.of(new Object[][]{
|
||||||
{"PILOT", new Profile("PILOT", "urn:facturx:pdfa:CrossIndustryDocument:despatchadvice:1p0#")}
|
{"PILOT", new Profile("PILOT", "urn:awv-net.de:CIDA:1.0:pilot")}
|
||||||
}).collect(Collectors.toMap(data -> (String) data[0], data -> (Profile) data[1]));
|
}).collect(Collectors.toMap(data -> (String) data[0], data -> (Profile) data[1]));
|
||||||
|
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ public class Profiles {
|
|||||||
throw new RuntimeException("Profile not found");
|
throw new RuntimeException("Profile not found");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else if (standard == EStandard.deliverx) {
|
} else if (standard == EStandard.deliveradvice) {
|
||||||
Profile result = null;
|
Profile result = null;
|
||||||
result = dx1Map.get(name.toUpperCase());
|
result = dx1Map.get(name.toUpperCase());
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
|
|||||||
@@ -23,9 +23,13 @@ import junit.framework.Test;
|
|||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
import org.junit.FixMethodOrder;
|
import org.junit.FixMethodOrder;
|
||||||
import org.junit.runners.MethodSorters;
|
import org.junit.runners.MethodSorters;
|
||||||
|
import org.mustangproject.EStandard;
|
||||||
import org.mustangproject.Invoice;
|
import org.mustangproject.Invoice;
|
||||||
|
import org.mustangproject.TradeParty;
|
||||||
|
|
||||||
import javax.xml.xpath.XPathExpressionException;
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -38,6 +42,8 @@ import java.util.Calendar;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
|
import static org.xmlunit.assertj.XmlAssert.assertThat;
|
||||||
|
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
public class DXTest extends MustangReaderTestCase implements IExportableTransaction {
|
public class DXTest extends MustangReaderTestCase implements IExportableTransaction {
|
||||||
final String TARGET_PDF = "./target/testout-DX.pdf";
|
final String TARGET_PDF = "./target/testout-DX.pdf";
|
||||||
@@ -198,10 +204,10 @@ public class DXTest extends MustangReaderTestCase implements IExportableTransact
|
|||||||
EdgeProduct designProduct = new EdgeProduct("", "Künstlerische Gestaltung (Stunde): Einer Beispielrechnung",
|
EdgeProduct designProduct = new EdgeProduct("", "Künstlerische Gestaltung (Stunde): Einer Beispielrechnung",
|
||||||
"HUR");
|
"HUR");
|
||||||
EdgeProduct balloonProduct = new EdgeProduct("", "Bestellerweiterung für E&F Umbau", "C62");// test for issue
|
EdgeProduct balloonProduct = new EdgeProduct("", "Bestellerweiterung für E&F Umbau", "C62");// test for issue
|
||||||
// 103
|
// 103
|
||||||
EdgeProduct airProduct = new EdgeProduct("", "Heiße Luft pro Liter", "LTR");
|
EdgeProduct airProduct = new EdgeProduct("", "Heiße Luft pro Liter", "LTR");
|
||||||
|
|
||||||
Item design=new Item(new BigDecimal("160"), new BigDecimal("1"), designProduct);
|
Item design = new Item(new BigDecimal("160"), new BigDecimal("1"), designProduct);
|
||||||
design.setAddReference("1825");
|
design.setAddReference("1825");
|
||||||
allItems[0] = design;
|
allItems[0] = design;
|
||||||
allItems[1] = new Item(new BigDecimal("0.79"), new BigDecimal("400"), balloonProduct);
|
allItems[1] = new Item(new BigDecimal("0.79"), new BigDecimal("400"), balloonProduct);
|
||||||
@@ -268,8 +274,8 @@ public class DXTest extends MustangReaderTestCase implements IExportableTransact
|
|||||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||||
|
|
||||||
DXExporterFromA1 oe = new DXExporterFromA1().setProducer("My Application")
|
DXExporterFromA1 oe = new DXExporterFromA1().setProducer("My Application")
|
||||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(1).ignorePDFAErrors()
|
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(1).ignorePDFAErrors()
|
||||||
.load(SOURCE_PDF)) {
|
.load(SOURCE_PDF)) {
|
||||||
oe.setTransaction(this);
|
oe.setTransaction(this);
|
||||||
String theXML = new String(oe.getProvider().getXML(), StandardCharsets.UTF_8);
|
String theXML = new String(oe.getProvider().getXML(), StandardCharsets.UTF_8);
|
||||||
assertTrue(theXML.contains("<rsm:SCRDMCCBDACIOMessageStructure"));
|
assertTrue(theXML.contains("<rsm:SCRDMCCBDACIOMessageStructure"));
|
||||||
@@ -292,7 +298,7 @@ public class DXTest extends MustangReaderTestCase implements IExportableTransact
|
|||||||
assertEquals(zi.getHolder(), getOwnOrganisationName());
|
assertEquals(zi.getHolder(), getOwnOrganisationName());
|
||||||
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(TARGET_PDF);
|
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(TARGET_PDF);
|
||||||
try {
|
try {
|
||||||
Invoice i=zii.extractInvoice();
|
Invoice i = zii.extractInvoice();
|
||||||
|
|
||||||
assertEquals(new BigDecimal("400.0000"), i.getZFItems()[1].getQuantity());
|
assertEquals(new BigDecimal("400.0000"), i.getZFItems()[1].getQuantity());
|
||||||
/* getting the Quantity is more difficult than usual because in OrderX it's
|
/* getting the Quantity is more difficult than usual because in OrderX it's
|
||||||
@@ -311,4 +317,55 @@ public class DXTest extends MustangReaderTestCase implements IExportableTransact
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDAGeneration() {
|
||||||
|
|
||||||
|
// the writing part
|
||||||
|
TradeParty recipient = new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE");
|
||||||
|
Invoice i = createDA(recipient);
|
||||||
|
|
||||||
|
DAPullProvider zf2p = new DAPullProvider();
|
||||||
|
zf2p.setProfile(Profiles.getByName(EStandard.deliveradvice,"Pilot",1));
|
||||||
|
zf2p.generateXML(i);
|
||||||
|
String theXML = new String(zf2p.getXML(), StandardCharsets.UTF_8);
|
||||||
|
try {
|
||||||
|
BufferedWriter writer = new BufferedWriter(new FileWriter(TARGET_XML));
|
||||||
|
writer.write(theXML);
|
||||||
|
writer.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
assertTrue(theXML.contains("<SCRDMCCBDACIDAMessageStructure"));
|
||||||
|
assertThat(theXML).valueByXPath("count(//*[local-name()='IncludedSupplyChainTradeLineItem'])")
|
||||||
|
.asInt()
|
||||||
|
.isEqualTo(2); //we have two items
|
||||||
|
|
||||||
|
|
||||||
|
assertThat(theXML).valueByXPath("//*[local-name()='ActualDespatchSupplyChainEvent']/*[local-name()='OccurrenceDateTime']/*[local-name()='DateTimeString']")
|
||||||
|
.asString()
|
||||||
|
.isEqualToIgnoringWhitespace("20210426");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
private Invoice createDA(TradeParty recipient) {
|
||||||
|
String orgname = "Test company";
|
||||||
|
String number = "123";
|
||||||
|
String amountStr = "23.00";
|
||||||
|
BigDecimal amount = new BigDecimal(amountStr);
|
||||||
|
SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy");
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date())
|
||||||
|
.setSender(new TradeParty(orgname,"teststr","55232","teststadt","DE").addTaxID("DE4711").addVATID("DE0815").setContact(new org.mustangproject.Contact("Hans Test","+49123456789","test@example.org")).addBankDetails(new org.mustangproject.BankDetails("DE12500105170648489890","COBADEFXXX")))
|
||||||
|
.setRecipient(recipient)
|
||||||
|
.setDeliveryDate(germanDateFormat.parse("26.04.2021"))
|
||||||
|
.setReferenceNumber("991-01484-64")//leitweg-id
|
||||||
|
// not using any VAT, this is also a test of zero-rated goods:
|
||||||
|
.setNumber(number)
|
||||||
|
.addItem(new org.mustangproject.Item(new org.mustangproject.Product("Testprodukt", "", "P75", BigDecimal.ZERO), amount, new BigDecimal(1.0))).addItem(new org.mustangproject.Item(new org.mustangproject.Product("Testprodukt", "", "P85", BigDecimal.ZERO), amount, new BigDecimal(1.0)));
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ public class XMLValidator extends Validator {
|
|||||||
context.setProfile(booking.getNodeValue());
|
context.setProfile(booking.getNodeValue());
|
||||||
}
|
}
|
||||||
boolean isOrderX = false;
|
boolean isOrderX = false;
|
||||||
boolean isDeliverX = false;
|
boolean isDespatchAdvice = false;
|
||||||
boolean isMiniumum = false;
|
boolean isMiniumum = false;
|
||||||
boolean isBasic = false;
|
boolean isBasic = false;
|
||||||
boolean isBasicWithoutLines = false;
|
boolean isBasicWithoutLines = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user