From aff57e5a511f6503c6d07ce6f1bd963db7074820 Mon Sep 17 00:00:00 2001 From: jstaerk Date: Fri, 24 Jan 2025 12:29:55 +0100 Subject: [PATCH] closes #705 --- History.md | 2 + .../ZUGFeRD/ZUGFeRDInvoiceImporter.java | 47 +- .../ZUGFeRD/ZF2ZInvoiceImporterTest.java | 18 + .../resources/cii/extended_warenrechnung.xml | 567 ++++++++++++++++++ 4 files changed, 626 insertions(+), 8 deletions(-) create mode 100644 library/src/test/resources/cii/extended_warenrechnung.xml diff --git a/History.md b/History.md index c3afba036..be39ae497 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,5 @@ +#705 + 2.16.1 ======= 2025-01-21 diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java index 9115feb44..a1cd2d8df 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java @@ -556,13 +556,13 @@ public Invoice extractInto(Invoice zpp) throws XPathExpressionException, ParseEx } zpp.addNotes(includedNotes); String rootNode = extractString("local-name(/*)"); - if (rootNode.equals("Invoice")||rootNode.equals("CreditNote")) { + if (rootNode.equals("Invoice") || rootNode.equals("CreditNote")) { // UBL... // //*[local-name()="Invoice" or local-name()="CreditNote"] number = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"ID\"]").trim(); typeCode = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"InvoiceTypeCode\"]").trim(); String issueDateStr = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"IssueDate\"]").trim(); - if (issueDateStr.length()>0) { + if (issueDateStr.length() > 0) { issueDate = new SimpleDateFormat("yyyy-MM-dd").parse(issueDateStr); } String dueDt = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"DueDate\"]").trim(); @@ -651,7 +651,7 @@ public Invoice extractInto(Invoice zpp) throws XPathExpressionException, ParseEx zpp.setCurrency(currency); String paymentTermsDescription = extractString("//*[local-name()=\"SpecifiedTradePaymentTerms\"]/*[local-name()=\"Description\"]|//*[local-name()=\"PaymentTerms\"]/*[local-name()=\"Note\"]"); - if ((paymentTermsDescription!=null)&&(!paymentTermsDescription.isEmpty())) { + if ((paymentTermsDescription != null) && (!paymentTermsDescription.isEmpty())) { zpp.setPaymentTermDescription(paymentTermsDescription); } @@ -848,15 +848,14 @@ public Invoice extractInto(Invoice zpp) throws XPathExpressionException, ParseEx Node currentItemNode = nodes.item(i); ReferencedDocument doc = ReferencedDocument.fromNode(currentItemNode); - if (doc != null - && (!Objects.equals(zpp.getInvoiceReferencedDocumentID(), doc.getIssuerAssignedID()) - || !Objects.equals(zpp.getInvoiceReferencedIssueDate(), doc.getFormattedIssueDateTime()))) - { + if (doc != null + && (!Objects.equals(zpp.getInvoiceReferencedDocumentID(), doc.getIssuerAssignedID()) + || !Objects.equals(zpp.getInvoiceReferencedIssueDate(), doc.getFormattedIssueDateTime()))) { zpp.addInvoiceReferencedDocument(doc); } } } - + zpp.setOwnOrganisationName(extractString("//*[local-name()=\"SellerTradeParty\"]/*[local-name()=\"Name\"]|//*[local-name()=\"AccountingSupplierParty\"]/*[local-name()=\"Party\"]/*[local-name()=\"PartyName\"]").trim()); String rounding = extractString("//*[local-name()=\"SpecifiedTradeSettlementHeaderMonetarySummation\"]/*[local-name()=\"RoundingAmount\"]|//*[local-name()=\"LegalMonetaryTotal\"]/*[local-name()=\"Party\"]/*[local-name()=\"PayableRoundingAmount\"]"); @@ -976,6 +975,38 @@ public Invoice extractInto(Invoice zpp) throws XPathExpressionException, ParseEx } } + xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]/*[local-name()=\"SpecifiedLogisticsServiceCharge\"]");// UBL unknown + chargeNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + for (int i = 0; i < chargeNodes.getLength(); i++) { + NodeList chargeNodeChilds = chargeNodes.item(i).getChildNodes(); + String chargeAmount = null; + String taxPercent = null; + for (int chargeChildIndex = 0; chargeChildIndex < chargeNodeChilds.getLength(); chargeChildIndex++) { + String chargeChildName = chargeNodeChilds.item(chargeChildIndex).getLocalName(); + if (chargeChildName != null) { + if (chargeChildName.equals("AppliedAmount")) { + chargeAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex)); + } else if (chargeChildName.equals("AppliedTradeTax")) { + NodeList taxChilds = chargeNodeChilds.item(chargeChildIndex).getChildNodes(); + for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) { + String taxItemName = taxChilds.item(taxChildIndex).getLocalName(); + if ((taxItemName != null) && (taxItemName.equals("RateApplicablePercent"))) { + taxPercent = XMLTools.trimOrNull(taxChilds.item(taxChildIndex)); + } + } + } + } + //appliedAmount + //AppliedTradeTax + } + if (chargeAmount != null) { + Charge c = new Charge(new BigDecimal(chargeAmount)); + if (taxPercent != null) { + c.setTaxPercent(new BigDecimal(taxPercent)); + } + zpp.addCharge(c); + } + } TransactionCalculator tc = new TransactionCalculator(zpp); diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java index 6b50de4eb..1e918395a 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java @@ -232,6 +232,24 @@ public void testZF1Import() { } + public void testSpecifiedLogisticsChargeImport() { + ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(); + File expectedResult = getResourceAsFile("cii/extended_warenrechnung.xml"); + + + boolean hasExceptions = false; + CalculatedInvoice invoice = new CalculatedInvoice(); + try { + zii.setInputStream(new FileInputStream(expectedResult)); + zii.extractInto(invoice); + } catch (XPathExpressionException | ParseException | FileNotFoundException e) { + hasExceptions = true; + } + assertFalse(hasExceptions); + TransactionCalculator tc = new TransactionCalculator(invoice); + assertEquals(new BigDecimal("518.99"), tc.getGrandTotal()); + + } public void testItemAllowancesChargesImport() { ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter("./target/testout-ZF2PushItemChargesAllowances.pdf"); diff --git a/library/src/test/resources/cii/extended_warenrechnung.xml b/library/src/test/resources/cii/extended_warenrechnung.xml new file mode 100644 index 000000000..46665e1a0 --- /dev/null +++ b/library/src/test/resources/cii/extended_warenrechnung.xml @@ -0,0 +1,567 @@ + + + + + + + + + + true + + + urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended + + + + R87654321012345 + WARENRECHNUNG + 380 + + 20180806 + + + ST3 + Es bestehen Rabatt- oder Bonusvereinbarungen. + AAK + + + EEV + Der Verkäufer bleibt Eigentümer der Waren bis zu vollständigen Erfüllung der Kaufpreisforderung. + AAJ + + + MUSTERLIEFERANT GMBH +BAHNHOFSTRASSE 99 +99199 MUSTERHAUSEN +Geschäftsführung: +Max Mustermann +USt-IdNr: DE123456789 +Telefon: +49 932 431 0 +www.musterlieferant.de +HRB Nr. 372876 +Amtsgericht Musterstadt +GLN 4304171000002 +WEEE-Reg-Nr.: DE87654321 + + REG + + + Leergutwert: 46,50 + + + Wichtige Information: Bei Bestellungen bis zum 19.12. ist die Auslieferung bis spätestens 23.12. garantiert. + + + + + + 1 + + + 4123456000014 + ZS997 + Zitronensäure 100ml + + Verpackungsart + BO + + + + + 1.0000 + + + 1.0000 + + + + 100.0000 + 4.0000 + + + + VAT + S + 19.00 + + + 100.00 + + + + + + 2 + + + 4123456000021 + GZ250 + Gelierzucker Extra 250g + + + + 1.5000 + + + false + + 0.0300 + Artikelrabatt 1 + + + + false + + 0.0200 + Artikelrabatt 2 + + + + 1.4500 + + + + 50.0000 + 1.0000 + + + + VAT + S + 7.00 + + + 72.50 + + + + + + 3 + + + 4123456000021 + GZ250 + Gelierzucker Extra 250g + Artikel wie vereinbart ohne Berechnung + + + + 0.0000 + + + 0.0000 + + + + 10.0000 + 1.0000 + + + + VAT + S + 7.00 + + + 0.00 + + + + + + 4 + + + 4100130013294 + 2031 + + Bierbrau Pils 20/0500 + EAN-VKE: 4100130913297 + + Verpackung + Kiste + + + + + 12.0000 + + + 12.0000 + + + + 15.0000 + 20.0000 + + + + VAT + S + 19.00 + + + 180.00 + + + + + + 5 + + + 2001015001325 + 1805 + + Leergutpfand 20 x 0,5l + + Verpackung + unverpackt + + + + + 3.1000 + + + 3.1000 + + + + 15.0000 + 1.0000 + + + + VAT + S + 19.00 + + + 46.50 + + + + + + 6 + + + 4123456000038 + MP107 + Mischpalette Joghurt Karton 3 x 20 + + Verpackung + Karton + + + 4123456001035 + JOG103 + Erdbeer 20 x 150g Becher + 20.0000 + + + 4123456002032 + JOG203 + Banane 20 x 150g Becher + 20.0000 + + + 4123456003039 + JOG303 + Schoko 20 x 150g Becher + 20.0000 + + + + + 30.0000 + + + false + + 0.9000 + Artikelrabatt 1 + + + + 29.1000 + + + + 2.0000 + 1.0000 + + + + VAT + S + 7.00 + + + 58.20 + + + + + + 549910 + 4333741000005 + MUSTERLIEFERANT GMBH + + + +49 932 431 500 + + + max.mustermann@musterlieferant.de + + + + 99199 + BAHNHOFSTRASSE 99 + MUSTERHAUSEN + DE + + + DE123456789 + + + + 009420 + 4304171000002 + MUSTER-KUNDE GMBH + + 40235 + KUNDENWEG 88 + DUESSELDORF + DE + + + + B123456789 + + + A456123 + 130 + + + + + 4304171088093 + MUSTER-MARKT + + 8211 + + + 31157 + HAUPTSTRASSE 44 + SARSTEDT + DE + + + + + 20180805 + + + + L87654321012345 + + + + EUR + + 009420 + 4304171000002 + MUSTER-KUNDE GMBH + + 40235 + KUNDENWEG 88 + DUESSELDORF + DE + + + + 61.07 + VAT + 321.40 + 326.50 + -5.10 + S + 19.00 + + + 8.93 + VAT + 127.59 + 130.70 + -3.11 + S + 7.00 + + + + false + + 2.00 + 280.00 + 5.60 + Rechnungsrabatt 1 + + VAT + S + 19.00 + + + + + false + + 2.00 + 130.70 + 2.61 + Rechnungsrabatt 1 + + VAT + S + 7.00 + + + + + false + + 280.00 + 2.50 + Rechnungsrabatt 2 + + VAT + S + 19.00 + + + + + false + + 130.70 + 0.50 + Rechnungsrabatt 2 + + VAT + S + 7.00 + + + + Transportkosten + 3.00 + + VAT + S + 19.00 + + + + Bei Zahlung innerhalb 14 Tagen gewähren wir 2,0% Skonto. + + 14 + 2.00 + + + + 457.20 + 3.00 + 11.21 + 448.99 + 70.00 + 518.99 + 0.00 + 518.99 + + + + \ No newline at end of file