fix for #993
This commit is contained in:
@@ -48,6 +48,7 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -1249,6 +1250,25 @@ public class ZUGFeRDInvoiceImporter {
|
||||
//appliedAmount
|
||||
//AppliedTradeTax
|
||||
}
|
||||
|
||||
if (cd.getDays() == null) {
|
||||
NodeList siblingNodes = cashdiscountNodes.item(i).getParentNode().getChildNodes();
|
||||
for (int siblingIndex = 0; siblingIndex < siblingNodes.getLength(); siblingIndex++) {
|
||||
if (siblingNodes.item(siblingIndex).getLocalName() != null && siblingNodes.item(siblingIndex).getLocalName().equals("DueDateDateTime")) {
|
||||
NodeList dueDateChilds = siblingNodes.item(siblingIndex).getChildNodes();
|
||||
for (int dueDateChildIndex = 0; dueDateChildIndex < dueDateChilds.getLength(); dueDateChildIndex++) {
|
||||
if ((dueDateChilds.item(dueDateChildIndex).getLocalName() != null) && (dueDateChilds.item(dueDateChildIndex).getLocalName().equals("DateTimeString"))) {
|
||||
String dueDateString = XMLTools.trimOrNull(dueDateChilds.item(dueDateChildIndex));
|
||||
dueDate = parseDate(dueDateString, "yyyyMMdd");
|
||||
long diffInMillies = Math.abs(dueDate.getTime() - zpp.getIssueDate().getTime());
|
||||
long diffInDays = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
|
||||
cd.setDays((int) diffInDays);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((cd.getPercent() != null)&&(cd.getDays() != null)) {
|
||||
zpp.addCashDiscount(cd);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.mustangproject.Invoice;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.ParseException;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
/* https://github.com/ZUGFeRD/mustangproject/issues/993 */
|
||||
public class CashDiscountFacturXTest extends TestCase {
|
||||
String XMLString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
" <rsm:CrossIndustryInvoice xmlns:rsm=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:ram=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100\" xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100\" xmlns:qdt=\"urn:un:unece:uncefact:data:standard:QualifiedDataType:100\">\n" +
|
||||
" <!-- generated by: mustangproject.org v2.15.1-SNAPSHOT-->\n" +
|
||||
" <rsm:ExchangedDocumentContext>\n" +
|
||||
" <ram:GuidelineSpecifiedDocumentContextParameter>\n" +
|
||||
" <ram:ID>urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended</ram:ID>\n" +
|
||||
" </ram:GuidelineSpecifiedDocumentContextParameter>\n" +
|
||||
" </rsm:ExchangedDocumentContext>\n" +
|
||||
" <rsm:ExchangedDocument>\n" +
|
||||
" <ram:ID>471102</ram:ID>\n" +
|
||||
" <ram:TypeCode>380</ram:TypeCode>\n" +
|
||||
" <ram:IssueDateTime>\n" +
|
||||
" <udt:DateTimeString format=\"102\">20260201</udt:DateTimeString>\n" +
|
||||
" </ram:IssueDateTime>\n" +
|
||||
" </rsm:ExchangedDocument>\n" +
|
||||
" <rsm:SupplyChainTradeTransaction>\n" +
|
||||
" <ram:IncludedSupplyChainTradeLineItem>\n" +
|
||||
" <ram:AssociatedDocumentLineDocument>\n" +
|
||||
" <ram:LineID>1</ram:LineID>\n" +
|
||||
" </ram:AssociatedDocumentLineDocument>\n" +
|
||||
" <ram:SpecifiedTradeProduct>\n" +
|
||||
" <ram:Name>Trennblätter A4</ram:Name>\n" +
|
||||
" </ram:SpecifiedTradeProduct>\n" +
|
||||
" <ram:SpecifiedLineTradeAgreement>\n" +
|
||||
" <ram:NetPriceProductTradePrice>\n" +
|
||||
" <ram:ChargeAmount>9.9000</ram:ChargeAmount>\n" +
|
||||
" <ram:BasisQuantity unitCode=\"H87\">1.0000</ram:BasisQuantity>\n" +
|
||||
" </ram:NetPriceProductTradePrice>\n" +
|
||||
" </ram:SpecifiedLineTradeAgreement>\n" +
|
||||
" <ram:SpecifiedLineTradeDelivery>\n" +
|
||||
" <ram:BilledQuantity unitCode=\"H87\">20.0000</ram:BilledQuantity>\n" +
|
||||
" </ram:SpecifiedLineTradeDelivery>\n" +
|
||||
" <ram:SpecifiedLineTradeSettlement>\n" +
|
||||
" <ram:ApplicableTradeTax>\n" +
|
||||
" <ram:TypeCode>VAT</ram:TypeCode>\n" +
|
||||
" <ram:CategoryCode>S</ram:CategoryCode>\n" +
|
||||
" <ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>\n" +
|
||||
" </ram:ApplicableTradeTax>\n" +
|
||||
" <ram:SpecifiedTradeSettlementLineMonetarySummation>\n" +
|
||||
" <ram:LineTotalAmount>198.00</ram:LineTotalAmount>\n" +
|
||||
" </ram:SpecifiedTradeSettlementLineMonetarySummation>\n" +
|
||||
" </ram:SpecifiedLineTradeSettlement>\n" +
|
||||
" </ram:IncludedSupplyChainTradeLineItem>\n" +
|
||||
" <ram:IncludedSupplyChainTradeLineItem>\n" +
|
||||
" <ram:AssociatedDocumentLineDocument>\n" +
|
||||
" <ram:LineID>2</ram:LineID>\n" +
|
||||
" </ram:AssociatedDocumentLineDocument>\n" +
|
||||
" <ram:SpecifiedTradeProduct>\n" +
|
||||
" <ram:Name>Joghurt Banane</ram:Name>\n" +
|
||||
" </ram:SpecifiedTradeProduct>\n" +
|
||||
" <ram:SpecifiedLineTradeAgreement>\n" +
|
||||
" <ram:NetPriceProductTradePrice>\n" +
|
||||
" <ram:ChargeAmount>5.5000</ram:ChargeAmount>\n" +
|
||||
" <ram:BasisQuantity unitCode=\"H87\">1.0000</ram:BasisQuantity>\n" +
|
||||
" </ram:NetPriceProductTradePrice>\n" +
|
||||
" </ram:SpecifiedLineTradeAgreement>\n" +
|
||||
" <ram:SpecifiedLineTradeDelivery>\n" +
|
||||
" <ram:BilledQuantity unitCode=\"H87\">50.0000</ram:BilledQuantity>\n" +
|
||||
" </ram:SpecifiedLineTradeDelivery>\n" +
|
||||
" <ram:SpecifiedLineTradeSettlement>\n" +
|
||||
" <ram:ApplicableTradeTax>\n" +
|
||||
" <ram:TypeCode>VAT</ram:TypeCode>\n" +
|
||||
" <ram:CategoryCode>S</ram:CategoryCode>\n" +
|
||||
" <ram:RateApplicablePercent>7.00</ram:RateApplicablePercent>\n" +
|
||||
" </ram:ApplicableTradeTax>\n" +
|
||||
" <ram:SpecifiedTradeSettlementLineMonetarySummation>\n" +
|
||||
" <ram:LineTotalAmount>275.00</ram:LineTotalAmount>\n" +
|
||||
" </ram:SpecifiedTradeSettlementLineMonetarySummation>\n" +
|
||||
" </ram:SpecifiedLineTradeSettlement>\n" +
|
||||
" </ram:IncludedSupplyChainTradeLineItem>\n" +
|
||||
" <ram:ApplicableHeaderTradeAgreement>\n" +
|
||||
" <ram:SellerTradeParty>\n" +
|
||||
" <ram:Name>Lieferant GmbH</ram:Name>\n" +
|
||||
" <ram:PostalTradeAddress>\n" +
|
||||
" <ram:PostcodeCode>80333</ram:PostcodeCode>\n" +
|
||||
" <ram:LineOne>Lieferantenstraße 20</ram:LineOne>\n" +
|
||||
" <ram:CityName>München</ram:CityName>\n" +
|
||||
" <ram:CountryID>DE</ram:CountryID>\n" +
|
||||
" </ram:PostalTradeAddress>\n" +
|
||||
" <ram:SpecifiedTaxRegistration>\n" +
|
||||
" <ram:ID schemeID=\"VA\">DE123456789</ram:ID>\n" +
|
||||
" </ram:SpecifiedTaxRegistration>\n" +
|
||||
" <ram:SpecifiedTaxRegistration>\n" +
|
||||
" <ram:ID schemeID=\"FC\">201/113/40209</ram:ID>\n" +
|
||||
" </ram:SpecifiedTaxRegistration>\n" +
|
||||
" </ram:SellerTradeParty>\n" +
|
||||
" <ram:BuyerTradeParty>\n" +
|
||||
" <ram:Name>Kunden AG Mitte</ram:Name>\n" +
|
||||
" <ram:PostalTradeAddress>\n" +
|
||||
" <ram:PostcodeCode>69876</ram:PostcodeCode>\n" +
|
||||
" <ram:LineOne>Kundenstraße 15</ram:LineOne>\n" +
|
||||
" <ram:CityName>Frankfurt</ram:CityName>\n" +
|
||||
" <ram:CountryID>DE</ram:CountryID>\n" +
|
||||
" </ram:PostalTradeAddress>\n" +
|
||||
" </ram:BuyerTradeParty>\n" +
|
||||
" </ram:ApplicableHeaderTradeAgreement>\n" +
|
||||
" <ram:ApplicableHeaderTradeDelivery>\n" +
|
||||
" <ram:ActualDeliverySupplyChainEvent>\n" +
|
||||
" <ram:OccurrenceDateTime>\n" +
|
||||
" <udt:DateTimeString format=\"102\">20180304</udt:DateTimeString>\n" +
|
||||
" </ram:OccurrenceDateTime>\n" +
|
||||
" </ram:ActualDeliverySupplyChainEvent>\n" +
|
||||
" </ram:ApplicableHeaderTradeDelivery>\n" +
|
||||
" <ram:ApplicableHeaderTradeSettlement>\n" +
|
||||
" <ram:PaymentReference>471102</ram:PaymentReference>\n" +
|
||||
" <ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>\n" +
|
||||
" <ram:ApplicableTradeTax>\n" +
|
||||
" <ram:CalculatedAmount>19.25</ram:CalculatedAmount>\n" +
|
||||
" <ram:TypeCode>VAT</ram:TypeCode>\n" +
|
||||
" <ram:BasisAmount>275.00</ram:BasisAmount>\n" +
|
||||
" <ram:CategoryCode>S</ram:CategoryCode>\n" +
|
||||
" <ram:RateApplicablePercent>7.00</ram:RateApplicablePercent>\n" +
|
||||
" </ram:ApplicableTradeTax>\n" +
|
||||
" <ram:ApplicableTradeTax>\n" +
|
||||
" <ram:CalculatedAmount>37.62</ram:CalculatedAmount>\n" +
|
||||
" <ram:TypeCode>VAT</ram:TypeCode>\n" +
|
||||
" <ram:BasisAmount>198.00</ram:BasisAmount>\n" +
|
||||
" <ram:CategoryCode>S</ram:CategoryCode>\n" +
|
||||
" <ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>\n" +
|
||||
" </ram:ApplicableTradeTax>\n" +
|
||||
" <ram:SpecifiedTradePaymentTerms>\n" +
|
||||
" <ram:Description>Please remit until 04.03.2018</ram:Description>\n" +
|
||||
" <ram:DueDateDateTime>\n" +
|
||||
" <udt:DateTimeString format=\"102\">20180304</udt:DateTimeString>\n" +
|
||||
" </ram:DueDateDateTime>\n" +
|
||||
" </ram:SpecifiedTradePaymentTerms>\n" +
|
||||
" <ram:SpecifiedTradePaymentTerms>\n" +
|
||||
" <ram:Description>Bis zum 15.02.2026 erhalten Sie 4,000 % Skonto, 21.19 EUR</ram:Description>\n" +
|
||||
" <ram:DueDateDateTime>\n" +
|
||||
" <udt:DateTimeString format=\"102\">20260215</udt:DateTimeString>\n" +
|
||||
" </ram:DueDateDateTime>\n" +
|
||||
" <ram:ApplicableTradePaymentDiscountTerms>\n" +
|
||||
" <ram:BasisAmount>529.8700</ram:BasisAmount>\n" +
|
||||
" <ram:CalculationPercent>4.00</ram:CalculationPercent>\n" +
|
||||
" <ram:ActualDiscountAmount>21.19</ram:ActualDiscountAmount>\n" +
|
||||
" </ram:ApplicableTradePaymentDiscountTerms>\n" +
|
||||
" </ram:SpecifiedTradePaymentTerms>\n" +
|
||||
" <ram:SpecifiedTradePaymentTerms>\n" +
|
||||
" <ram:Description>Bis zum 16.02.2026 ohne Abzug</ram:Description>\n" +
|
||||
" <ram:DueDateDateTime>\n" +
|
||||
" <udt:DateTimeString format=\"102\">20260216</udt:DateTimeString>\n" +
|
||||
" </ram:DueDateDateTime>\n" +
|
||||
" </ram:SpecifiedTradePaymentTerms>\n" +
|
||||
" <ram:SpecifiedTradeSettlementHeaderMonetarySummation>\n" +
|
||||
" <ram:LineTotalAmount>473.00</ram:LineTotalAmount>\n" +
|
||||
" <ram:ChargeTotalAmount>0.00</ram:ChargeTotalAmount>\n" +
|
||||
" <ram:AllowanceTotalAmount>0.00</ram:AllowanceTotalAmount>\n" +
|
||||
" <ram:TaxBasisTotalAmount>473.00</ram:TaxBasisTotalAmount>\n" +
|
||||
" <ram:TaxTotalAmount currencyID=\"EUR\">56.87</ram:TaxTotalAmount>\n" +
|
||||
" <ram:GrandTotalAmount>529.87</ram:GrandTotalAmount>\n" +
|
||||
" <ram:TotalPrepaidAmount>0.00</ram:TotalPrepaidAmount>\n" +
|
||||
" <ram:DuePayableAmount>529.87</ram:DuePayableAmount>\n" +
|
||||
" </ram:SpecifiedTradeSettlementHeaderMonetarySummation>\n" +
|
||||
" </ram:ApplicableHeaderTradeSettlement>\n" +
|
||||
" </rsm:SupplyChainTradeTransaction>\n" +
|
||||
" </rsm:CrossIndustryInvoice>";
|
||||
|
||||
public void testCashDiscount() throws XPathExpressionException, ParseException {
|
||||
InputStream inputStream = new ByteArrayInputStream(XMLString.getBytes(StandardCharsets.UTF_8));
|
||||
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(inputStream);
|
||||
Invoice invoice = zii.extractInvoice();
|
||||
assertEquals(new BigDecimal("4.00"), invoice.getCashDiscounts()[0].getPercent());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user