working on cash discount abstraction (XR and reading is still missing)

This commit is contained in:
jstaerk
2024-05-09 08:59:20 +02:00
parent e8bbc6c008
commit 757910fff8
9 changed files with 309 additions and 213 deletions

View File

@@ -7,6 +7,8 @@
- UBL importer to also parse contacts - UBL importer to also parse contacts
- https://github.com/ZUGFeRD/mustangproject/pull/369 - https://github.com/ZUGFeRD/mustangproject/pull/369
- upgrade ph-schematron from 6.3.3 to 8 - upgrade ph-schematron from 6.3.3 to 8
- support inputstreams https://github.com/ZUGFeRD/mustangproject/pull/379
- #314 ZUGFeRDInvoiceImporter additional constructur
2.10.0 2.10.0
======= =======

View File

@@ -1,5 +1,5 @@
## General approach ## Typical process
1. build 1. build
@@ -29,6 +29,18 @@ If you do a pull request, please do a feature branch, e.g. if you are working on
Most of mustang is a library, adding (autmated junit) test cases is often not only the most sustainable but also the fastest way to see if new/changed functionality works. If something is changed so that old test cases break on purpose please do not just remove them but take the time to fix the test cases Most of mustang is a library, adding (autmated junit) test cases is often not only the most sustainable but also the fastest way to see if new/changed functionality works. If something is changed so that old test cases break on purpose please do not just remove them but take the time to fix the test cases
## Typical workflow
If e.g. new elements or attributes are added, they are often added
* in the object so that a developer can use them
* in the interface so that a old fashioned developer could use them as well
* in the pullprovider so that it actually finds it's way into the XML
* in at least one test, after the test has been run this should at least once be
* validated. If that works one can start implementing the
* reading part (along with tests), then it needs to be
* documented e.g. on the homepage and
* communicated, at the very least by mentioning it in the history.md
## Architecture ## Architecture
Mustang contains a library to read/write e-invoices, Mustang contains a library to read/write e-invoices,

View File

@@ -0,0 +1,50 @@
package org.mustangproject;
import org.mustangproject.ZUGFeRD.IZUGFeRDCashDiscount;
import java.math.BigDecimal;
public class CashDiscount implements IZUGFeRDCashDiscount {
protected BigDecimal percent;
protected Integer days=null;
/***
* Create a cash discount (skonto) with the specified height in the specified period.
* Should someone add more period types than just "days" there
* is be space for a (optional) third parameter
*
* @param percent max 3 decimals "behind the dot", more precision is currently ignored
* @param days
*/
public CashDiscount(BigDecimal percent, int days) {
this.percent = percent;
this.days = days;
}
/***
* @return this particular cash discount as cross industry invoice XML
*/
public String getAsCII() {
return "<ram:SpecifiedTradePaymentTerms>"+
"<ram:Description>Cash Discount</ram:Description>"+
" <ram:ApplicableTradePaymentDiscountTerms>"+
" <ram:BasisPeriodMeasure unitCode=\"DAY\">"+days+"</ram:BasisPeriodMeasure>"+
" <ram:CalculationPercent>"+XMLTools.nDigitFormat(percent,3)+"</ram:CalculationPercent>"+
" </ram:ApplicableTradePaymentDiscountTerms>"+
"</ram:SpecifiedTradePaymentTerms>";
}
/***
* since EN16931 voted not to have (or even allow) cash discounts in their core invoice the german
* XRechnung CIUS defined it's own proprietary format for a freetext field
* @return this particular cash discount in proprietary xrechnung format
*/
public String getAsXRechnung() {
return "#SKONTO#TAGE="+days+"#PROZENT="+XMLTools.nDigitFormat(percent,3)+"#\n";
}
}

View File

@@ -26,12 +26,7 @@ import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import org.mustangproject.ZUGFeRD.IExportableTransaction; import org.mustangproject.ZUGFeRD.*;
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem;
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableTradeParty;
import org.mustangproject.ZUGFeRD.IZUGFeRDPaymentTerms;
import org.mustangproject.ZUGFeRD.IZUGFeRDTradeSettlement;
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants; import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@@ -47,13 +42,14 @@ public class Invoice implements IExportableTransaction {
protected String documentName = null, documentCode = null, number = null, ownOrganisationFullPlaintextInfo = null, referenceNumber = null, shipToOrganisationID = null, shipToOrganisationName = null, shipToStreet = null, shipToZIP = null, shipToLocation = null, shipToCountry = null, buyerOrderReferencedDocumentID = null, invoiceReferencedDocumentID = null, buyerOrderReferencedDocumentIssueDateTime = null, ownForeignOrganisationID = null, ownOrganisationName = null, currency = null, paymentTermDescription = null; protected String documentName = null, documentCode = null, number = null, ownOrganisationFullPlaintextInfo = null, referenceNumber = null, shipToOrganisationID = null, shipToOrganisationName = null, shipToStreet = null, shipToZIP = null, shipToLocation = null, shipToCountry = null, buyerOrderReferencedDocumentID = null, invoiceReferencedDocumentID = null, buyerOrderReferencedDocumentIssueDateTime = null, ownForeignOrganisationID = null, ownOrganisationName = null, currency = null, paymentTermDescription = null;
protected Date issueDate = null, dueDate = null, deliveryDate = null; protected Date issueDate = null, dueDate = null, deliveryDate = null;
protected TradeParty sender = null, recipient = null, deliveryAddress = null; protected TradeParty sender = null, recipient = null, deliveryAddress = null;
@JsonDeserialize(contentAs=Item.class) protected ArrayList<CashDiscount> cashDiscounts = null;
@JsonDeserialize(contentAs = Item.class)
protected ArrayList<IZUGFeRDExportableItem> ZFItems = null; protected ArrayList<IZUGFeRDExportableItem> ZFItems = null;
protected ArrayList<String> notes = null; protected ArrayList<String> notes = null;
private List<IncludedNote> includedNotes = null; private List<IncludedNote> includedNotes = null;
protected String sellerOrderReferencedDocumentID; protected String sellerOrderReferencedDocumentID;
protected String contractReferencedDocument = null; protected String contractReferencedDocument = null;
protected ArrayList<FileAttachment> xmlEmbeddedFiles=null; protected ArrayList<FileAttachment> xmlEmbeddedFiles = null;
protected BigDecimal totalPrepaidAmount = null; protected BigDecimal totalPrepaidAmount = null;
protected Date detailedDeliveryDateStart = null; protected Date detailedDeliveryDateStart = null;
@@ -70,6 +66,7 @@ public class Invoice implements IExportableTransaction {
public Invoice() { public Invoice() {
ZFItems = new ArrayList<>(); ZFItems = new ArrayList<>();
cashDiscounts = new ArrayList<>();
setCurrency("EUR"); setCurrency("EUR");
} }
@@ -100,7 +97,7 @@ public class Invoice implements IExportableTransaction {
public Invoice embedFileInXML(FileAttachment fa) { public Invoice embedFileInXML(FileAttachment fa) {
if (xmlEmbeddedFiles == null) { if (xmlEmbeddedFiles == null) {
xmlEmbeddedFiles= new ArrayList<>(); xmlEmbeddedFiles = new ArrayList<>();
} }
xmlEmbeddedFiles.add(fa); xmlEmbeddedFiles.add(fa);
return this; return this;
@@ -115,6 +112,10 @@ public class Invoice implements IExportableTransaction {
} }
@Override
public IZUGFeRDCashDiscount[] getCashDiscounts() {
return cashDiscounts.toArray(new IZUGFeRDCashDiscount[0]);
}
@Override @Override
public String getNumber() { public String getNumber() {
@@ -139,6 +140,7 @@ public class Invoice implements IExportableTransaction {
documentCode = DocumentCodeTypeConstants.CORRECTEDINVOICE; documentCode = DocumentCodeTypeConstants.CORRECTEDINVOICE;
return this; return this;
} }
public Invoice setCreditNote() { public Invoice setCreditNote() {
documentCode = DocumentCodeTypeConstants.CREDITNOTE; documentCode = DocumentCodeTypeConstants.CREDITNOTE;
return this; return this;
@@ -229,6 +231,7 @@ public class Invoice implements IExportableTransaction {
public String getBuyerOrderReferencedDocumentID() { public String getBuyerOrderReferencedDocumentID() {
return buyerOrderReferencedDocumentID; return buyerOrderReferencedDocumentID;
} }
@Override @Override
public String getSellerOrderReferencedDocumentID() { public String getSellerOrderReferencedDocumentID() {
return sellerOrderReferencedDocumentID; return sellerOrderReferencedDocumentID;
@@ -239,6 +242,7 @@ public class Invoice implements IExportableTransaction {
this.sellerOrderReferencedDocumentID = sellerOrderReferencedDocumentID; this.sellerOrderReferencedDocumentID = sellerOrderReferencedDocumentID;
return this; return this;
} }
/*** /***
* usually the order number * usually the order number
* @param buyerOrderReferencedDocumentID string with number * @param buyerOrderReferencedDocumentID string with number
@@ -258,6 +262,7 @@ public class Invoice implements IExportableTransaction {
this.invoiceReferencedDocumentID = invoiceReferencedDocumentID; this.invoiceReferencedDocumentID = invoiceReferencedDocumentID;
return this; return this;
} }
@Override @Override
public String getInvoiceReferencedDocumentID() { public String getInvoiceReferencedDocumentID() {
return invoiceReferencedDocumentID; return invoiceReferencedDocumentID;
@@ -285,7 +290,7 @@ public class Invoice implements IExportableTransaction {
* @return fluent setter * @return fluent setter
*/ */
public Invoice setTotalPrepaidAmount(BigDecimal prepaid) { public Invoice setTotalPrepaidAmount(BigDecimal prepaid) {
totalPrepaidAmount=prepaid; totalPrepaidAmount = prepaid;
return this; return this;
} }
@@ -480,6 +485,7 @@ public class Invoice implements IExportableTransaction {
/** /**
* required. * required.
* sets the invoice receiving institution = invoicee * sets the invoice receiving institution = invoicee
*
* @param recipient the invoicee organisation * @param recipient the invoicee organisation
* @return fluent setter * @return fluent setter
*/ */
@@ -491,6 +497,7 @@ public class Invoice implements IExportableTransaction {
/** /**
* required. * required.
* sets the invoicing institution = invoicer * sets the invoicing institution = invoicer
*
* @param sender the invoicer * @param sender the invoicer
* @return fluent setter * @return fluent setter
*/ */
@@ -569,6 +576,16 @@ public class Invoice implements IExportableTransaction {
this.deliveryAddress = deliveryAddress; this.deliveryAddress = deliveryAddress;
return this; return this;
} }
/***
* Adds a cash discount (skonto)
* @param CashDiscount the percent/period combination
* @return fluent setter
*/
public Invoice addCashDiscount(CashDiscount c) {
this.cashDiscounts.add(c);
return this;
}
@Override @Override
public IZUGFeRDExportableItem[] getZFItems() { public IZUGFeRDExportableItem[] getZFItems() {
@@ -576,15 +593,16 @@ public class Invoice implements IExportableTransaction {
} }
public void setZFItems(ArrayList<IZUGFeRDExportableItem> ims) { public void setZFItems(ArrayList<IZUGFeRDExportableItem> ims) {
ZFItems=ims; ZFItems = ims;
} }
/** /**
* required * required
* adds invoice "lines" :-) * adds invoice "lines" :-)
* @see Item *
* @param item the invoice line * @param item the invoice line
* @return fluent setter * @return fluent setter
* @see Item
*/ */
public Invoice addItem(IZUGFeRDExportableItem item) { public Invoice addItem(IZUGFeRDExportableItem item) {
ZFItems.add(item); ZFItems.add(item);
@@ -669,6 +687,7 @@ public class Invoice implements IExportableTransaction {
/** /**
* adds a free text paragraph, which will become an includedNote element * adds a free text paragraph, which will become an includedNote element
*
* @param text freeform UTF8 plain text * @param text freeform UTF8 plain text
* @return fluent setter * @return fluent setter
*/ */
@@ -694,6 +713,7 @@ public class Invoice implements IExportableTransaction {
/** /**
* adds a free text paragraph, which will become an includedNote element with explicit * adds a free text paragraph, which will become an includedNote element with explicit
* subjectCode {@link SubjectCode#AAI} * subjectCode {@link SubjectCode#AAI}
*
* @param content freeform UTF8 plain text * @param content freeform UTF8 plain text
* @return fluent setter * @return fluent setter
*/ */
@@ -708,6 +728,7 @@ public class Invoice implements IExportableTransaction {
/** /**
* adds a free text paragraph, which will become an includedNote element with explicit * adds a free text paragraph, which will become an includedNote element with explicit
* subjectCode {@link SubjectCode#REG} * subjectCode {@link SubjectCode#REG}
*
* @param content freeform UTF8 plain text * @param content freeform UTF8 plain text
* @return fluent setter * @return fluent setter
*/ */
@@ -722,6 +743,7 @@ public class Invoice implements IExportableTransaction {
/** /**
* adds a free text paragraph, which will become an includedNote element with explicit * adds a free text paragraph, which will become an includedNote element with explicit
* subjectCode {@link SubjectCode#ABL} * subjectCode {@link SubjectCode#ABL}
*
* @param content freeform UTF8 plain text * @param content freeform UTF8 plain text
* @return fluent setter * @return fluent setter
*/ */
@@ -736,6 +758,7 @@ public class Invoice implements IExportableTransaction {
/** /**
* adds a free text paragraph, which will become an includedNote element with explicit * adds a free text paragraph, which will become an includedNote element with explicit
* subjectCode {@link SubjectCode#CUS} * subjectCode {@link SubjectCode#CUS}
*
* @param content freeform UTF8 plain text * @param content freeform UTF8 plain text
* @return fluent setter * @return fluent setter
*/ */
@@ -750,6 +773,7 @@ public class Invoice implements IExportableTransaction {
/** /**
* adds a free text paragraph, which will become an includedNote element with explicit * adds a free text paragraph, which will become an includedNote element with explicit
* subjectCode {@link SubjectCode#SUR} * subjectCode {@link SubjectCode#SUR}
*
* @param content freeform UTF8 plain text * @param content freeform UTF8 plain text
* @return fluent setter * @return fluent setter
*/ */
@@ -764,6 +788,7 @@ public class Invoice implements IExportableTransaction {
/** /**
* adds a free text paragraph, which will become an includedNote element with explicit * adds a free text paragraph, which will become an includedNote element with explicit
* subjectCode {@link SubjectCode#TXD} * subjectCode {@link SubjectCode#TXD}
*
* @param content freeform UTF8 plain text * @param content freeform UTF8 plain text
* @return fluent setter * @return fluent setter
*/ */
@@ -778,6 +803,7 @@ public class Invoice implements IExportableTransaction {
/** /**
* adds a free text paragraph, which will become an includedNote element with explicit * adds a free text paragraph, which will become an includedNote element with explicit
* subjectCode {@link SubjectCode#ACY} * subjectCode {@link SubjectCode#ACY}
*
* @param content freeform UTF8 plain text * @param content freeform UTF8 plain text
* @return fluent setter * @return fluent setter
*/ */
@@ -788,9 +814,11 @@ public class Invoice implements IExportableTransaction {
includedNotes.add(IncludedNote.introductionNote(content)); includedNotes.add(IncludedNote.introductionNote(content));
return this; return this;
} }
/** /**
* adds a free text paragraph, which will become an includedNote element with explicit * adds a free text paragraph, which will become an includedNote element with explicit
* subjectCode {@link SubjectCode#AAK} * subjectCode {@link SubjectCode#AAK}
*
* @param content freeform UTF8 plain text * @param content freeform UTF8 plain text
* @return fluent setter * @return fluent setter
*/ */
@@ -841,6 +869,7 @@ public class Invoice implements IExportableTransaction {
/** /**
* Decide when the VAT should be collected. * Decide when the VAT should be collected.
*
* @param vatDueDateTypeCode use EventTimeCodeTypeConstants * @param vatDueDateTypeCode use EventTimeCodeTypeConstants
* @return fluent setter * @return fluent setter
*/ */

View File

@@ -120,36 +120,6 @@ public class XMLTools extends XMLWriter {
return sb.toString(); return sb.toString();
} }
/**
* Returns the Byte Order Mark size and thus allows to skips over a BOM
* at the beginning of the given ByteArrayInputStream, if one exists.
*
* @param is the ByteArrayInputStream used
* @throws IOException if can not be read from is
* @see <a href="https://www.w3.org/TR/xml/#sec-guessing">Autodetection of Character Encodings</a>
*
public static int guessBOMSize(ByteArrayInputStream is) throws IOException {
byte[] pad = new byte[4];
is.read(pad);
is.reset();
int test2 = ((pad[0] & 0xFF) << 8) | (pad[1] & 0xFF);
int test3 = ((test2 & 0xFFFF) << 8) | (pad[2] & 0xFF);
int test4 = ((test3 & 0xFFFFFF) << 8) | (pad[3] & 0xFF);
//
if (test4 == 0x0000FEFF || test4 == 0xFFFE0000 || test4 == 0x0000FFFE || test4 == 0xFEFF0000) {
// UCS-4: BOM takes 4 bytes
return 4;
} else if (test3 == 0xEFBBFF) {
// UTF-8: BOM takes 3 bytes
return 3;
} else if (test2 == 0xFEFF || test2 == 0xFFFE) {
// UTF-16: BOM takes 2 bytes
return 2;
}
return 0;
}*/
/*** /***
* removes utf8 byte order marks from byte arrays, in case one is there * removes utf8 byte order marks from byte arrays, in case one is there
* @param zugferdRaw the CII XML * @param zugferdRaw the CII XML

View File

@@ -140,6 +140,11 @@ public interface IExportableTransaction {
return null; return null;
} }
default IZUGFeRDCashDiscount[] getCashDiscounts() { return null; }
/***
* @return the invoice line items with the positions
*/
IZUGFeRDExportableItem[] getZFItems(); IZUGFeRDExportableItem[] getZFItems();
/** /**

View File

@@ -0,0 +1,20 @@
package org.mustangproject.ZUGFeRD;
import org.mustangproject.XMLTools;
public interface IZUGFeRDCashDiscount {
/***
* @return this particular cash discount as cross industry invoice XML
*/
public String getAsCII();
/***
* since EN16931 voted not to have (or even allow) cash discounts in their core invoice the german
* XRechnung CIUS defined it's own proprietary format for a freetext field
* @return this particular cash discount in proprietary xrechnung format
*/
public String getAsXRechnung();
}

View File

@@ -689,6 +689,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
} else { } else {
xml += buildPaymentTermsXml(); xml += buildPaymentTermsXml();
} }
if ((profile == Profiles.getByName("Extended"))&&(trans.getCashDiscounts()!=null)&&(trans.getCashDiscounts().length>0)) {
for (IZUGFeRDCashDiscount discount:trans.getCashDiscounts()
) {
xml += discount.getAsCII();
}
}
final String allowanceTotalLine = "<ram:AllowanceTotalAmount>" + currencyFormat(calc.getAllowancesForPercent(null)) + "</ram:AllowanceTotalAmount>"; final String allowanceTotalLine = "<ram:AllowanceTotalAmount>" + currencyFormat(calc.getAllowancesForPercent(null)) + "</ram:AllowanceTotalAmount>";

View File

@@ -93,7 +93,7 @@ public class ZF2PushTest extends TestCase {
ze.export(TARGET_PDF); ze.export(TARGET_PDF);
} catch (IOException | ParseException e) { } catch (IOException | ParseException e) {
fail("Exception should not be raised in testPushExport"); fail("Exception should not be raised");
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
@@ -142,7 +142,7 @@ public class ZF2PushTest extends TestCase {
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice")); assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
ze.export(TARGET_ATTACHMENTSPDF); ze.export(TARGET_ATTACHMENTSPDF);
} catch (IOException e) { } catch (IOException e) {
fail("IOException should not be raised in testEdgeExport"); fail("IOException should not be raised");
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
@@ -192,11 +192,11 @@ public class ZF2PushTest extends TestCase {
//assertEquals(IBAN,read.getSender().getBankDetails().get(0).getIBAN()); //assertEquals(IBAN,read.getSender().getBankDetails().get(0).getIBAN());
ze.export(TARGET_BANKPDF); ze.export(TARGET_BANKPDF);
} catch (IOException e) { } catch (IOException e) {
fail("IOException should not be raised in testEdgeExport"); fail("IOException should not be raised");
} catch (XPathExpressionException e) { } catch (XPathExpressionException e) {
fail("XPathException should not be raised in testEdgeExport"); fail("XPathException should not be raised");
} catch (ParseException e) { } catch (ParseException e) {
fail("ParseException should not be raised in testEdgeExport"); fail("ParseException should not be raised");
} }
@@ -230,7 +230,7 @@ public class ZF2PushTest extends TestCase {
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice")); assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
ze.export(TARGET_ITEMCHARGESALLOWANCESPDF); ze.export(TARGET_ITEMCHARGESALLOWANCESPDF);
} catch (IOException e) { } catch (IOException e) {
fail("IOException should not be raised in testEdgeExport"); fail("IOException should not be raised");
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
@@ -284,7 +284,7 @@ public class ZF2PushTest extends TestCase {
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice")); assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
ze.export(TARGET_INTRACOMMUNITYSUPPLYPDF); ze.export(TARGET_INTRACOMMUNITYSUPPLYPDF);
} catch (IOException e) { } catch (IOException e) {
fail("IOException should not be raised in testEdgeExport"); fail("IOException should not be raised");
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
@@ -333,7 +333,7 @@ public class ZF2PushTest extends TestCase {
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice")); assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
ze.export(TARGET_REVERSECHARGEPDF); ze.export(TARGET_REVERSECHARGEPDF);
} catch (IOException e) { } catch (IOException e) {
fail("IOException should not be raised in testEdgeExport"); fail("IOException should not be raised");
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
@@ -379,7 +379,7 @@ public class ZF2PushTest extends TestCase {
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice")); assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
ze.export(TARGET_CHARGESALLOWANCESPDF); ze.export(TARGET_CHARGESALLOWANCESPDF);
} catch (IOException e) { } catch (IOException e) {
fail("IOException should not be raised in testEdgeExport"); fail("IOException should not be raised");
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
@@ -417,7 +417,7 @@ public class ZF2PushTest extends TestCase {
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); .getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application") ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).ignorePDFAErrors() .setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("extended")).ignorePDFAErrors()
.load(SOURCE_PDF)) { .load(SOURCE_PDF)) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
@@ -435,6 +435,7 @@ public class ZF2PushTest extends TestCase {
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(16)).addGlobalID(gtin).setSellerAssignedID("4711"), price, new BigDecimal(1.0)).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"))) .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(16)).addGlobalID(gtin).setSellerAssignedID("4711"), price, new BigDecimal(1.0)).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")))
.addCharge(new Charge(new BigDecimal(0.5)).setReason("quick delivery charge").setTaxPercent(new BigDecimal(16))) .addCharge(new Charge(new BigDecimal(0.5)).setReason("quick delivery charge").setTaxPercent(new BigDecimal(16)))
.addAllowance(new Allowance(new BigDecimal(0.2)).setReason("discount").setTaxPercent(new BigDecimal(16))) .addAllowance(new Allowance(new BigDecimal(0.2)).setReason("discount").setTaxPercent(new BigDecimal(16)))
.addCashDiscount(new CashDiscount(new BigDecimal(2),14))
.setDeliveryDate(sdf.parse("2020-11-02")).setOwnVATID("DE0815").setNumber(number).setVATDueDateTypeCode(EventTimeCodeTypeConstants.PAYMENT_DATE) .setDeliveryDate(sdf.parse("2020-11-02")).setOwnVATID("DE0815").setNumber(number).setVATDueDateTypeCode(EventTimeCodeTypeConstants.PAYMENT_DATE)
); );
} catch (ParseException e) { } catch (ParseException e) {
@@ -445,7 +446,7 @@ public class ZF2PushTest extends TestCase {
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice")); assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
ze.export(TARGET_PUSHEDGE); ze.export(TARGET_PUSHEDGE);
} catch (IOException e) { } catch (IOException e) {
fail("IOException should not be raised in testEdgeExport"); fail("IOException should not be raised");
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
@@ -473,7 +474,8 @@ public class ZF2PushTest extends TestCase {
assertTrue(zi.getUTF8().contains("DE4711")); // the VAT ID should be there... assertTrue(zi.getUTF8().contains("DE4711")); // the VAT ID should be there...
assertFalse(zi.getUTF8().contains("DE47110")); // but not the VAT ID of the shiptotradeparty assertFalse(zi.getUTF8().contains("DE47110")); // but not the VAT ID of the shiptotradeparty
assertTrue(zi.getUTF8().contains("document level 2/2")); assertTrue(zi.getUTF8().contains("document level 2/2"));
assertFalse(zi.getUTF8().contains("++49555123456")); // in profile EN16931 contact fax number is not allowed assertTrue(zi.getUTF8().contains("++49555123456"));
assertTrue(zi.getUTF8().contains("Cash Discount")); // default description for cash discounts
assertThat(zi.getUTF8()).valueByXPath("//*[local-name()='ApplicableTradeTax']/*[local-name()='DueDateTypeCode']").asString() assertThat(zi.getUTF8()).valueByXPath("//*[local-name()='ApplicableTradeTax']/*[local-name()='DueDateTypeCode']").asString()
.isEqualTo(EventTimeCodeTypeConstants.PAYMENT_DATE); .isEqualTo(EventTimeCodeTypeConstants.PAYMENT_DATE);
@@ -486,9 +488,9 @@ public class ZF2PushTest extends TestCase {
} catch (XPathExpressionException e) { } catch (XPathExpressionException e) {
fail("XPathExpressionException should not be raised in testEdgeExport"); fail("XPathExpressionException should not be raised");
} catch (ParseException e) { } catch (ParseException e) {
fail("ParseException should not be raised in testEdgeExport"); fail("ParseException should not be raised");
/* a parseException would also be fired if the calculated grand total does not /* a parseException would also be fired if the calculated grand total does not
match the read grand total */ match the read grand total */
} }
@@ -518,7 +520,7 @@ public class ZF2PushTest extends TestCase {
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice")); assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
ze.export(TARGET_ALLOWANCESPDF); ze.export(TARGET_ALLOWANCESPDF);
} catch (IOException e) { } catch (IOException e) {
fail("IOException should not be raised in testEdgeExport"); fail("IOException should not be raised");
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
@@ -563,7 +565,7 @@ public class ZF2PushTest extends TestCase {
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice")); assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
ze.export(TARGET_RELATIVECHARGESALLOWANCESPDF); ze.export(TARGET_RELATIVECHARGESALLOWANCESPDF);
} catch (IOException e) { } catch (IOException e) {
fail("IOException should not be raised in testEdgeExport"); fail("IOException should not be raised");
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
@@ -613,7 +615,7 @@ public class ZF2PushTest extends TestCase {
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice")); assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
ze.export(TARGET_CORRECTIONPDF); ze.export(TARGET_CORRECTIONPDF);
} catch (IOException e) { } catch (IOException e) {
fail("IOException should not be raised in testEdgeExport"); fail("IOException should not be raised");
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
@@ -662,7 +664,7 @@ public class ZF2PushTest extends TestCase {
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice")); assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
ze.export(TARGET_CREDITNOTEPDF); ze.export(TARGET_CREDITNOTEPDF);
} catch (IOException e) { } catch (IOException e) {
fail("IOException should not be raised in testEdgeExport"); fail("IOException should not be raised");
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)