- prevent nullpointerexception https://github.com/ZUGFeRD/mustangproject/pull/302 thanks to weclapp-dev

- lines no longer included in basic-wl and minimum
- due date and delivery date no longer mandatory for credit notes
- Allow foreign limited addresses, e.g. allow Parties withpout postal addresses/postcodes
- Allow invoices in minimum profile e.g. dont use applicabletradetax, linetotalamount, paymentreference etc in Minimum profile
This commit is contained in:
jstaerk
2022-12-22 20:49:08 +01:00
parent 9396ff280b
commit 794edc272b
4 changed files with 312 additions and 161 deletions

View File

@@ -6,6 +6,11 @@
- Corrected forgotten --d CLI shortcut
- No uber jar #297
- automated server tests
- prevent nullpointerexception https://github.com/ZUGFeRD/mustangproject/pull/302 thanks to weclapp-dev
- lines no longer included in basic-wl and minimum
- due date and delivery date no longer mandatory for credit notes
- Allow foreign limited addresses, e.g. allow Parties withpout postal addresses/postcodes
- Allow invoices in minimum profile e.g. dont use applicabletradetax, linetotalamount, paymentreference etc in Minimum profile
2.5.7
=======

View File

@@ -21,7 +21,6 @@
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.IOException;
@@ -43,6 +42,7 @@ import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.mustangproject.FileAttachment;
import org.mustangproject.XMLTools;
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
public class ZUGFeRD2PullProvider implements IXMLProvider {
@@ -166,9 +166,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
xml += "</ram:DefinedTradeContact>";
}
xml += "<ram:PostalTradeAddress>"
+ "<ram:PostcodeCode>" + XMLTools.encodeXML(party.getZIP())
+ "</ram:PostcodeCode>";
xml += "<ram:PostalTradeAddress>";
if (party.getZIP() != null) {
xml += "<ram:PostcodeCode>" + XMLTools.encodeXML(party.getZIP())
+ "</ram:PostcodeCode>";
}
if (party.getStreet() != null) {
xml += "<ram:LineOne>" + XMLTools.encodeXML(party.getStreet())
+ "</ram:LineOne>";
@@ -181,11 +184,16 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
xml += "<ram:LineThree>" + XMLTools.encodeXML(party.getAdditionalAddressExtension())
+ "</ram:LineThree>";
}
xml += "<ram:CityName>" + XMLTools.encodeXML(party.getLocation())
+ "</ram:CityName>"
+ "<ram:CountryID>" + XMLTools.encodeXML(party.getCountry())
if (party.getLocation() != null) {
xml += "<ram:CityName>" + XMLTools.encodeXML(party.getLocation())
+ "</ram:CityName>";
}
;
//country IS mandatory
xml += "<ram:CountryID>" + XMLTools.encodeXML(party.getCountry())
+ "</ram:CountryID>"
+ "</ram:PostalTradeAddress>";
if ((party.getVATID() != null) && (!isShipToTradeParty)) {
xml += "<ram:SpecifiedTaxRegistration>"
+ "<ram:ID schemeID=\"VA\">" + XMLTools.encodeXML(party.getVATID())
@@ -270,10 +278,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
String exemptionReason = "";
if (trans.getPaymentTermDescription() != null) {
paymentTermsDescription = XMLTools.encodeXML(trans.getPaymentTermDescription());
paymentTermsDescription = XMLTools.encodeXML(trans.getPaymentTermDescription());
}
if ((paymentTermsDescription == null) && (trans.getDocumentCode() != CORRECTEDINVOICE)/* && (trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE)*/) {
if ((paymentTermsDescription == null) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CORRECTEDINVOICE) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE)) {
paymentTermsDescription = "Zahlbar ohne Abzug bis " + germanDateFormat.format(trans.getDueDate());
}
@@ -357,124 +365,127 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
}
}
final LineCalculator lc = new LineCalculator(currentItem);
xml += "<ram:IncludedSupplyChainTradeLineItem>" +
"<ram:AssociatedDocumentLineDocument>"
+ "<ram:LineID>" + lineID + "</ram:LineID>"
+ notes
+ "</ram:AssociatedDocumentLineDocument>"
+ "<ram:SpecifiedTradeProduct>";
if ((currentItem.getProduct().getGlobalIDScheme() != null) && (currentItem.getProduct().getGlobalID() != null)) {
xml += "<ram:GlobalID schemeID=\""+XMLTools.encodeXML(currentItem.getProduct().getGlobalIDScheme())+"\">"+XMLTools.encodeXML(currentItem.getProduct().getGlobalID())+"</ram: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);
}
}
String itemTotalAllowanceChargeStr = "";
if (currentItem.getItemTotalAllowances() != null && currentItem.getItemTotalAllowances().length > 0) {
for (final IZUGFeRDAllowanceCharge itemTotalAllowance : currentItem.getItemTotalAllowances()) {
itemTotalAllowanceChargeStr += getItemTotalAllowanceChargeStr(itemTotalAllowance, currentItem);
}
}
xml += "<ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>"
+ "<ram:Description>" + XMLTools.encodeXML(currentItem.getProduct().getDescription())
+ "</ram:Description>"
+ "</ram:SpecifiedTradeProduct>"
+ "<ram:SpecifiedLineTradeAgreement>";
if (currentItem.getReferencedDocuments() != null) {
for (final IReferencedDocument currentReferencedDocument : currentItem.getReferencedDocuments()) {
xml += "<ram:AdditionalReferencedDocument>" +
"<ram:IssuerAssignedID>" + XMLTools.encodeXML(currentReferencedDocument.getIssuerAssignedID()) + "</ram:IssuerAssignedID>" +
"<ram:TypeCode>" + XMLTools.encodeXML(currentReferencedDocument.getTypeCode()) + "</ram:TypeCode>" +
"<ram:ReferenceTypeCode>" + XMLTools.encodeXML(currentReferencedDocument.getReferenceTypeCode()) + "</ram:ReferenceTypeCode>" +
"</ram:AdditionalReferencedDocument>";
if ((getProfile() != Profiles.getByName("Minimum")) && (getProfile() != Profiles.getByName("BasicWL"))) {
xml += "<ram:IncludedSupplyChainTradeLineItem>" +
"<ram:AssociatedDocumentLineDocument>"
+ "<ram:LineID>" + lineID + "</ram:LineID>"
+ notes
+ "</ram:AssociatedDocumentLineDocument>"
+ "<ram:SpecifiedTradeProduct>";
if ((currentItem.getProduct().getGlobalIDScheme() != null) && (currentItem.getProduct().getGlobalID() != null)) {
xml += "<ram:GlobalID schemeID=\"" + XMLTools.encodeXML(currentItem.getProduct().getGlobalIDScheme()) + "\">" + XMLTools.encodeXML(currentItem.getProduct().getGlobalID()) + "</ram:GlobalID>";
}
}
if (currentItem.getBuyerOrderReferencedDocumentLineID() != null) {
xml += "<ram:BuyerOrderReferencedDocument> "
+ "<ram:LineID>" + XMLTools.encodeXML(currentItem.getBuyerOrderReferencedDocumentLineID()) + "</ram:LineID>"
+ "</ram:BuyerOrderReferencedDocument>";
}
xml += "<ram:GrossPriceProductTradePrice>"
+ "<ram:ChargeAmount>" + priceFormat(lc.getPriceGross())
+ "</ram:ChargeAmount>" //currencyID=\"EUR\"
+ "<ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit())
+ "\">" + quantityFormat(currentItem.getBasisQuantity()) + "</ram:BasisQuantity>"
+ allowanceChargeStr
// + " <AppliedTradeAllowanceCharge>"
// + " <ChargeIndicator>false</ChargeIndicator>"
// + " <ActualAmount currencyID=\"EUR\">0.6667</ActualAmount>"
// + " <Reason>Rabatt</Reason>"
// + " </AppliedTradeAllowanceCharge>"
+ "</ram:GrossPriceProductTradePrice>"
+ "<ram:NetPriceProductTradePrice>"
+ "<ram:ChargeAmount>" + priceFormat(lc.getPrice())
+ "</ram:ChargeAmount>" // currencyID=\"EUR\"
+ "<ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit())
+ "\">" + quantityFormat(currentItem.getBasisQuantity()) + "</ram:BasisQuantity>"
+ "</ram:NetPriceProductTradePrice>"
+ "</ram:SpecifiedLineTradeAgreement>"
+ "<ram:SpecifiedLineTradeDelivery>"
+ "<ram:BilledQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit()) + "\">"
+ quantityFormat(currentItem.getQuantity()) + "</ram:BilledQuantity>"
+ "</ram:SpecifiedLineTradeDelivery>"
+ "<ram:SpecifiedLineTradeSettlement>"
+ "<ram:ApplicableTradeTax>"
+ "<ram:TypeCode>VAT</ram:TypeCode>"
+ exemptionReason
+ "<ram:CategoryCode>" + currentItem.getProduct().getTaxCategoryCode() + "</ram:CategoryCode>"
+ "<ram:RateApplicablePercent>"
+ vatFormat(currentItem.getProduct().getVATPercent()) + "</ram:RateApplicablePercent>"
+ "</ram:ApplicableTradeTax>";
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.getProduct().getSellerAssignedID() != null) {
xml += "<ram:SellerAssignedID>"
+ XMLTools.encodeXML(currentItem.getProduct().getSellerAssignedID()) + "</ram:SellerAssignedID>";
}
if (currentItem.getDetailedDeliveryPeriodTo() != null) {
xml += "<ram:EndDateTime>" + DATE.udtFormat(currentItem.getDetailedDeliveryPeriodTo()) + "</ram:EndDateTime>";
if (currentItem.getProduct().getBuyerAssignedID() != null) {
xml += "<ram:BuyerAssignedID>"
+ XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "</ram:BuyerAssignedID>";
}
xml += "</ram:BillingSpecifiedPeriod>";
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);
}
}
String itemTotalAllowanceChargeStr = "";
if (currentItem.getItemTotalAllowances() != null && currentItem.getItemTotalAllowances().length > 0) {
for (final IZUGFeRDAllowanceCharge itemTotalAllowance : currentItem.getItemTotalAllowances()) {
itemTotalAllowanceChargeStr += getItemTotalAllowanceChargeStr(itemTotalAllowance, currentItem);
}
}
xml += "<ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>"
+ "<ram:Description>" + XMLTools.encodeXML(currentItem.getProduct().getDescription())
+ "</ram:Description>"
+ "</ram:SpecifiedTradeProduct>"
+ "<ram:SpecifiedLineTradeAgreement>";
if (currentItem.getReferencedDocuments() != null) {
for (final IReferencedDocument currentReferencedDocument : currentItem.getReferencedDocuments()) {
xml += "<ram:AdditionalReferencedDocument>" +
"<ram:IssuerAssignedID>" + XMLTools.encodeXML(currentReferencedDocument.getIssuerAssignedID()) + "</ram:IssuerAssignedID>" +
"<ram:TypeCode>" + XMLTools.encodeXML(currentReferencedDocument.getTypeCode()) + "</ram:TypeCode>" +
"<ram:ReferenceTypeCode>" + XMLTools.encodeXML(currentReferencedDocument.getReferenceTypeCode()) + "</ram:ReferenceTypeCode>" +
"</ram:AdditionalReferencedDocument>";
}
}
if (currentItem.getBuyerOrderReferencedDocumentLineID() != null) {
xml += "<ram:BuyerOrderReferencedDocument> "
+ "<ram:LineID>" + XMLTools.encodeXML(currentItem.getBuyerOrderReferencedDocumentLineID()) + "</ram:LineID>"
+ "</ram:BuyerOrderReferencedDocument>";
}
xml += "<ram:GrossPriceProductTradePrice>"
+ "<ram:ChargeAmount>" + priceFormat(lc.getPriceGross())
+ "</ram:ChargeAmount>" //currencyID=\"EUR\"
+ "<ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit())
+ "\">" + quantityFormat(currentItem.getBasisQuantity()) + "</ram:BasisQuantity>"
+ allowanceChargeStr
// + " <AppliedTradeAllowanceCharge>"
// + " <ChargeIndicator>false</ChargeIndicator>"
// + " <ActualAmount currencyID=\"EUR\">0.6667</ActualAmount>"
// + " <Reason>Rabatt</Reason>"
// + " </AppliedTradeAllowanceCharge>"
+ "</ram:GrossPriceProductTradePrice>"
+ "<ram:NetPriceProductTradePrice>"
+ "<ram:ChargeAmount>" + priceFormat(lc.getPrice())
+ "</ram:ChargeAmount>" // currencyID=\"EUR\"
+ "<ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit())
+ "\">" + quantityFormat(currentItem.getBasisQuantity()) + "</ram:BasisQuantity>"
+ "</ram:NetPriceProductTradePrice>"
+ "</ram:SpecifiedLineTradeAgreement>"
+ "<ram:SpecifiedLineTradeDelivery>"
+ "<ram:BilledQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit()) + "\">"
+ quantityFormat(currentItem.getQuantity()) + "</ram:BilledQuantity>"
+ "</ram:SpecifiedLineTradeDelivery>"
+ "<ram:SpecifiedLineTradeSettlement>"
+ "<ram:ApplicableTradeTax>"
+ "<ram:TypeCode>VAT</ram:TypeCode>"
+ exemptionReason
+ "<ram:CategoryCode>" + currentItem.getProduct().getTaxCategoryCode() + "</ram:CategoryCode>"
+ "<ram:RateApplicablePercent>"
+ vatFormat(currentItem.getProduct().getVATPercent()) + "</ram:RateApplicablePercent>"
+ "</ram:ApplicableTradeTax>";
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 += itemTotalAllowanceChargeStr;
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 += itemTotalAllowanceChargeStr;
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>";
@@ -528,51 +539,61 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if (trans.getSpecifiedProcuringProjectID() != null) {
xml += " <ram:SpecifiedProcuringProject>"
+ " <ram:ID>"
+ XMLTools.encodeXML(trans.getSpecifiedProcuringProjectID()) + "</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>";
xml += "</ram:ApplicableHeaderTradeAgreement>";
xml += "<ram:ApplicableHeaderTradeDelivery>";
if (this.trans.getDeliveryAddress() != null) {
xml += "<ram:ShipToTradeParty>" +
getTradePartyAsXML(this.trans.getDeliveryAddress(), false, true) +
"</ram:ShipToTradeParty>";
}
xml += "<ram:ActualDeliverySupplyChainEvent>"
+ "<ram:OccurrenceDateTime>";
if (trans.getDeliveryDate() != null) {
xml += "<ram:ActualDeliverySupplyChainEvent>"
+ "<ram:OccurrenceDateTime>";
xml += DATE.udtFormat(trans.getDeliveryDate());
xml += "</ram:OccurrenceDateTime>";
xml += " </ram:ActualDeliverySupplyChainEvent>";
} else {
throw new IllegalStateException("No delivery date provided");
if (trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE) {
throw new IllegalStateException("No delivery date provided");
}
}
xml += "</ram:OccurrenceDateTime>";
xml += " </ram:ActualDeliverySupplyChainEvent>";
/*
* + "<DeliveryNoteReferencedDocument>" +
* "<IssueDateTime format=\"102\">20130603</IssueDateTime>" +
* "<ID>2013-51112</ID>" +
* "</DeliveryNoteReferencedDocument>"
*/
/*
* + "<DeliveryNoteReferencedDocument>" +
* "<IssueDateTime format=\"102\">20130603</IssueDateTime>" +
* "<ID>2013-51112</ID>" +
* "</DeliveryNoteReferencedDocument>"
*/
if (trans.getDespatchAdviceReferencedDocumentID() != null) {
xml += "<ram:DespatchAdviceReferencedDocument>";
xml += "<ram:IssuerAssignedID>"+XMLTools.encodeXML(trans.getDespatchAdviceReferencedDocumentID())+"</ram:IssuerAssignedID>";
xml += "<ram:IssuerAssignedID>" + XMLTools.encodeXML(trans.getDespatchAdviceReferencedDocumentID()) + "</ram:IssuerAssignedID>";
xml += "</ram:DespatchAdviceReferencedDocument>";
}
xml += " </ram:ApplicableHeaderTradeDelivery> <ram:ApplicableHeaderTradeSettlement>"
+ " <ram:PaymentReference>" + XMLTools.encodeXML(trans.getNumber()) + "</ram:PaymentReference>"
+ " <ram:InvoiceCurrencyCode>" + trans.getCurrency() + "</ram:InvoiceCurrencyCode>";
xml += "</ram:ApplicableHeaderTradeDelivery>";
xml += "<ram:ApplicableHeaderTradeSettlement>";
if ((trans.getNumber() != null) && (getProfile() != Profiles.getByName("Minimum"))) {
xml += " <ram:PaymentReference>" + XMLTools.encodeXML(trans.getNumber()) + "</ram:PaymentReference>";
}
xml += " <ram:InvoiceCurrencyCode>" + trans.getCurrency() + "</ram:InvoiceCurrencyCode>";
if (trans.getTradeSettlementPayment() != null) {
for (final IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) {
if (payment != null) {
hasDueDate = true;
xml += payment.getSettlementXML();
if (getProfile() != Profiles.getByName("Minimum")) {
xml += payment.getSettlementXML();
}
}
}
}
@@ -582,11 +603,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if (payment instanceof IZUGFeRDTradeSettlementPayment) {
hasDueDate = true;
}
xml += payment.getSettlementXML();
if (getProfile() != Profiles.getByName("Minimum")) {
xml += payment.getSettlementXML();
}
}
}
}
if ((trans.getDocumentCode() == CORRECTEDINVOICE)/*||(trans.getDocumentCode() == DocumentCodeTypeConstants.CREDITNOTE)*/) {
if ((trans.getDocumentCode() == DocumentCodeTypeConstants.CORRECTEDINVOICE) || (trans.getDocumentCode() == DocumentCodeTypeConstants.CREDITNOTE)) {
hasDueDate = false;
}
@@ -596,15 +619,18 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if (amount != null) {
final String amountCategoryCode = amount.getCategoryCode();
final boolean displayExemptionReason = CATEGORY_CODES_WITH_EXEMPTION_REASON.contains(amountCategoryCode);
xml += "<ram:ApplicableTradeTax>"
+ "<ram:CalculatedAmount>" + currencyFormat(amount.getCalculated())
+ "</ram:CalculatedAmount>" //currencyID=\"EUR\"
+ "<ram:TypeCode>VAT</ram:TypeCode>"
+ (displayExemptionReason ? exemptionReason : "")
+ "<ram:BasisAmount>" + currencyFormat(amount.getBasis()) + "</ram:BasisAmount>" // currencyID=\"EUR\"
+ "<ram:CategoryCode>" + amountCategoryCode + "</ram:CategoryCode>"
+ "<ram:RateApplicablePercent>"
+ vatFormat(currentTaxPercent) + "</ram:RateApplicablePercent></ram:ApplicableTradeTax>";
if (getProfile() != Profiles.getByName("Minimum")) {
xml += "<ram:ApplicableTradeTax>"
+ "<ram:CalculatedAmount>" + currencyFormat(amount.getCalculated())
+ "</ram:CalculatedAmount>" //currencyID=\"EUR\"
+ "<ram:TypeCode>VAT</ram:TypeCode>"
+ (displayExemptionReason ? exemptionReason : "")
+ "<ram:BasisAmount>" + currencyFormat(amount.getBasis()) + "</ram:BasisAmount>" // currencyID=\"EUR\"
+ "<ram:CategoryCode>" + amountCategoryCode + "</ram:CategoryCode>"
+ "<ram:RateApplicablePercent>"
+ vatFormat(currentTaxPercent) + "</ram:RateApplicablePercent></ram:ApplicableTradeTax>";
}
}
}
if ((trans.getDetailedDeliveryPeriodFrom() != null) || (trans.getDetailedDeliveryPeriodTo() != null)) {
@@ -660,7 +686,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
}
if ((trans.getPaymentTerms() == null) && ((paymentTermsDescription != null) || (trans.getTradeSettlement() != null) || (hasDueDate))) {
if ((trans.getPaymentTerms() == null) && (getProfile() != Profiles.getByName("Minimum")) && ((paymentTermsDescription != null) || (trans.getTradeSettlement() != null) || (hasDueDate))) {
xml += "<ram:SpecifiedTradePaymentTerms>";
if (paymentTermsDescription != null) {
@@ -691,20 +717,24 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
final String chargesTotalLine = "<ram:ChargeTotalAmount>" + currencyFormat(calc.getChargesForPercent(null)) + "</ram:ChargeTotalAmount>";
xml += "<ram:SpecifiedTradeSettlementHeaderMonetarySummation>"
+ "<ram:LineTotalAmount>" + currencyFormat(calc.getTotal()) + "</ram:LineTotalAmount>"
+ chargesTotalLine
+ allowanceTotalLine
+ "<ram:TaxBasisTotalAmount>" + currencyFormat(calc.getTaxBasis()) + "</ram:TaxBasisTotalAmount>"
xml += "<ram:SpecifiedTradeSettlementHeaderMonetarySummation>";
if (getProfile() != Profiles.getByName("Minimum")) {
xml += "<ram:LineTotalAmount>" + currencyFormat(calc.getTotal()) + "</ram:LineTotalAmount>";
xml += chargesTotalLine
+ allowanceTotalLine;
}
xml += "<ram:TaxBasisTotalAmount>" + currencyFormat(calc.getTaxBasis()) + "</ram:TaxBasisTotalAmount>"
// //
// currencyID=\"EUR\"
+ "<ram:TaxTotalAmount currencyID=\"" + trans.getCurrency() + "\">"
+ currencyFormat(calc.getGrandTotal().subtract(calc.getTaxBasis())) + "</ram:TaxTotalAmount>"
+ "<ram:GrandTotalAmount>" + currencyFormat(calc.getGrandTotal()) + "</ram:GrandTotalAmount>"
+ "<ram:GrandTotalAmount>" + currencyFormat(calc.getGrandTotal()) + "</ram:GrandTotalAmount>";
// //
// currencyID=\"EUR\"
+ " <ram:TotalPrepaidAmount>" + currencyFormat(calc.getTotalPrepaid()) + "</ram:TotalPrepaidAmount>"
+ "<ram:DuePayableAmount>" + currencyFormat(calc.getGrandTotal().subtract(calc.getTotalPrepaid())) + "</ram:DuePayableAmount>"
if (getProfile() != Profiles.getByName("Minimum")) {
xml+=" <ram:TotalPrepaidAmount>" + currencyFormat(calc.getTotalPrepaid()) + "</ram:TotalPrepaidAmount>";
}
xml+= "<ram:DuePayableAmount>" + currencyFormat(calc.getGrandTotal().subtract(calc.getTotalPrepaid())) + "</ram:DuePayableAmount>"
+ "</ram:SpecifiedTradeSettlementHeaderMonetarySummation>";
if (trans.getInvoiceReferencedDocumentID() != null) {
xml += " <ram:InvoiceReferencedDocument>"
@@ -713,7 +743,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if (trans.getInvoiceReferencedIssueDate() != null) {
xml += "<ram:FormattedIssueDateTime>"
+ DATE.qdtFormat(trans.getInvoiceReferencedIssueDate())
+ "</ram:FormattedIssueDateTime>";
+ "</ram:FormattedIssueDateTime>";
}
xml += " </ram:InvoiceReferencedDocument>";
}

View File

@@ -0,0 +1,96 @@
/**
* *********************************************************************
* <p>
* Copyright 2019 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 junit.framework.TestCase;
import org.mustangproject.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
/***
* This is a test to confirm the minimum steps to implement a interface are still sufficient
*
* @author jstaerk
*
*/
public class ProfilesMinimumBasicWLTest extends TestCase {
final String TARGET_PDF_FX_MINIMUM = "./target/testout-Minimum.pdf";
public void testMinimumExport() {
String ownNumber = "NUMFACTURE";
String ownBIC = "COBADEFFXXX";
String ownIBAN = "DE88200800000970375700";
String ownOrgName = "ME";
// the writing part
try (InputStream SOURCE_PDF = this.getClass()
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf");
IZUGFeRDExporter ze = new ZUGFeRDExporterFromA1().setZUGFeRDVersion(2).setProfile("Minimum").load(SOURCE_PDF)) {
//https://stackoverflow.com/questions/72450066/creating-a-min-basic-and-basic-wl-factur-x-using-mustang
Invoice i = new Invoice()
.setIssueDate(new Date())
/* .setDueDate(new Date())
.setDetailedDeliveryPeriod(new Date(), new Date())
.setDeliveryDate(new Date())*/
.setSender(
new TradeParty().setName(ownOrgName).setCountry("FR")
.addBankDetails(new BankDetails(ownIBAN, ownBIC)))
.setRecipient(
new TradeParty().setName("Client").setCountry("FR"))
.setNumber(ownNumber)
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(123), new BigDecimal(1)))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(123), new BigDecimal(1)))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(123), new BigDecimal(1)))
.setCreditNote();
ze.setTransaction(i);
ze.export(TARGET_PDF_FX_MINIMUM);
// check for pdf-a schema extension
// assertFalse(pdfContent.indexOf("<zf:ConformanceLevel>EN 16931</zf:ConformanceLevel>") == -1);
// assertFalse(pdfContent.indexOf("<pdfaSchema:prefix>zf</pdfaSchema:prefix>") == -1);
// assertFalse(pdfContent.indexOf("urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#") == -1);
} catch (IOException e) {
fail("IOException should not happen in testZExport");
}
// now check the contents (like MustangReaderTest)
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF_FX_MINIMUM);
// Reading ZUGFeRD
assertEquals(zi.getAmount(), "439.11");
// assertEquals(zi.getBIC(), ownBIC);
// assertEquals(zi.getIBAN(), ownIBAN);
assertEquals(zi.getHolder(), ownOrgName);
// assertEquals(zi.getForeignReference(), ownNumber);
}
}

View File

@@ -248,9 +248,29 @@ public class LibraryTest extends ResourceCase {
assertThat(res).valueByXPath("count(//notice)")
.asInt()
.isEqualTo(0);
}
public void testMinimumProfileValidity() {
File tempFile = new File("../library/target/testout-Minimum.pdf");
ZUGFeRDValidator zfv = new ZUGFeRDValidator();
String res = zfv.validate(tempFile.getAbsolutePath());
assertThat(res).valueByXPath("count(//error)")
.asInt()
.isEqualTo(0);
assertThat(res).valueByXPath("/validation/summary/@status")
.asString()
.isEqualTo("valid");// expect to be valid because XR notices are, well, only notices
assertThat(res).valueByXPath("/validation/xml/summary/@status")
.asString()
.isEqualTo("valid");
/** end of errors due to version mismatch*/
assertThat(res).valueByXPath("count(//notice)")
.asInt()
.isEqualTo(0);
}
}