From b624052facda4a3256881a9491ddd783963cf6cf Mon Sep 17 00:00:00 2001 From: jstaerk Date: Sat, 31 Oct 2020 12:40:45 +0100 Subject: [PATCH 1/6] use java8 base64 encode --- .../org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 1e6f09c5..75fda7af 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -29,8 +29,9 @@ import java.util.Date; import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.Base64; -import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; +import net.sf.saxon.value.Base64BinaryValue; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; @@ -498,13 +499,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide // Additional Documents of XRechnung (Rechnungsbegruendende Unterlagen - BG-24 XRechnung) if (trans.getAdditionalReferencedDocuments() != null) { for (FileAttachment f : trans.getAdditionalReferencedDocuments()) { - // final String documentContent = Base64.encodeBase64String(f.getData()); + final String documentContent = new String(Base64.getEncoder().encodeToString(f.getData())); xml = xml + " \n" + " " + f.getFilename() + "\n" + " 916\n" + " " + f.getDescription() + "\n" + " " + documentContent + "\n" + + " filename=\"" + f.getFilename() + ">" + documentContent + "\n" + " \n"; } } From 0ac9ac6cac8466e4f9372e66bd58725804ff8670 Mon Sep 17 00:00:00 2001 From: jstaerk Date: Sat, 31 Oct 2020 13:57:33 +0100 Subject: [PATCH 2/6] parse item attributes --- .../ZUGFeRD/ZUGFeRDInvoiceImporter.java | 40 ++++++++++++++++--- .../ZUGFeRD/ZF2ZInvoiceImporterTest.java | 7 ++-- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java index 4ef4f238..cdbd6fbe 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java @@ -31,7 +31,7 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { "//BuyerTradeParty"); NodeList BuyerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); - zpp= new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number); + zpp = new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number); //.addItem(new Item(new Product("Testprodukt","","C62",new BigDecimal(0)),amount,new BigDecimal(1.0))) zpp.setOwnOrganisationName(extractString("//SellerTradeParty/Name")); @@ -42,11 +42,17 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { if (nodes.getLength() == 0) { } else { for (int i = 0; i < nodes.getLength(); i++) { + + String price = "0"; + String name = ""; + String description = ""; + String quantity = "0"; + String vatPercent = "0"; + String unitCode = "0"; + //nodes.item(i).getTextContent())) { Node currentItemNode = nodes.item(i); NodeList itemChilds = currentItemNode.getChildNodes(); - String price = "0"; - String quantity = "0"; for (int itemChildIndex = 0; itemChildIndex < itemChilds.getLength(); itemChildIndex++) { if (itemChilds.item(itemChildIndex).getNodeName().equals("ram:SpecifiedLineTradeAgreement")) { NodeList tradeLineChilds = itemChilds.item(itemChildIndex).getChildNodes(); @@ -67,13 +73,35 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { for (int tradeLineChildIndex = 0; tradeLineChildIndex < tradeLineChilds.getLength(); tradeLineChildIndex++) { if (tradeLineChilds.item(tradeLineChildIndex).getNodeName().equals("ram:BilledQuantity")) { quantity = tradeLineChilds.item(tradeLineChildIndex).getTextContent(); + unitCode = tradeLineChilds.item(tradeLineChildIndex).getAttributes().getNamedItem("unitCode").getNodeValue(); } } } + if (itemChilds.item(itemChildIndex).getNodeName().equals("ram:SpecifiedTradeProduct")) { + NodeList tradeProductChilds = itemChilds.item(itemChildIndex).getChildNodes(); + for (int tradeProductChildIndex = 0; tradeProductChildIndex < tradeProductChilds.getLength(); tradeProductChildIndex++) { + if (tradeProductChilds.item(tradeProductChildIndex).getNodeName().equals("ram:Name")) { + name = tradeProductChilds.item(tradeProductChildIndex).getTextContent(); + } + } + } + if (itemChilds.item(itemChildIndex).getNodeName().equals("ram:SpecifiedLineTradeSettlement")) { + NodeList tradeSettlementChilds = itemChilds.item(itemChildIndex).getChildNodes(); + for (int tradeSettlementChildIndex = 0; tradeSettlementChildIndex < tradeSettlementChilds.getLength(); tradeSettlementChildIndex++) { + if (tradeSettlementChilds.item(tradeSettlementChildIndex).getNodeName().equals("ram:ApplicableTradeTax")) { + NodeList taxChilds = tradeSettlementChilds.item(tradeSettlementChildIndex).getChildNodes(); + for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) { + if (taxChilds.item(taxChildIndex).getNodeName().equals("ram:RateApplicablePercent")) { + vatPercent = taxChilds.item(taxChildIndex).getTextContent(); + } + } + } + } + } + + } -// Logger.getLogger(ZUGFeRDInvoiceImporter.class.getName()).log(Level.INFO, "deb "+price); -// dummywerte sind derzeit noch produkname, beschreibung, unit, VAT percent, menge - zpp.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(0)), new BigDecimal(price), new BigDecimal(quantity))); + zpp.addItem(new Item(new Product(name, description, unitCode, new BigDecimal(vatPercent)), new BigDecimal(price), new BigDecimal(quantity))); } } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java index e9f9afb9..6f0568d2 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java @@ -45,11 +45,12 @@ public class ZF2ZInvoiceImporterTest extends TestCase { assertEquals(3, invoice.getZFItems().length); assertEquals("400.0000", invoice.getZFItems()[1].getQuantity().toString()); - /* assertEquals("160.0000", invoice.getZFItems()[0].getPrice().toString()); + assertEquals("160.0000", invoice.getZFItems()[0].getPrice().toString()); assertEquals("Heiße Luft pro Liter", invoice.getZFItems()[2].getProduct().getName()); - assertEquals("7", invoice.getZFItems()[0].getProduct().getVATPercent().toString()); + assertEquals("LTR", invoice.getZFItems()[2].getProduct().getUnit()); + assertEquals("7.00", invoice.getZFItems()[0].getProduct().getVATPercent().toString()); + -*/ } From 45cccee02fafc4a5c4a18e446674476c9f722a02 Mon Sep 17 00:00:00 2001 From: jstaerk Date: Sat, 31 Oct 2020 16:19:34 +0100 Subject: [PATCH 3/6] parsing invoice dates --- .../ZUGFeRD/ZUGFeRDInvoiceImporter.java | 102 +++++++++++++++++- .../mustangproject/ZUGFeRD/ZF2PushTest.java | 2 +- .../ZUGFeRD/ZF2ZInvoiceImporterTest.java | 14 +++ 3 files changed, 113 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java index cdbd6fbe..5dfe8b9c 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java @@ -6,6 +6,8 @@ import org.w3c.dom.NodeList; import javax.xml.xpath.*; import java.math.BigDecimal; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.Date; public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { @@ -15,7 +17,7 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { public Invoice extractInvoice() { - String number = "AB123"; + String number = ""; /** * dummywerte sind derzeit noch setDueDate setIssueDate setDeliveryDate setSender setRecipient setnumber * bspw. due date //ExchangedDocument//IssueDateTime//DateTimeString : due date optional @@ -30,8 +32,100 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { xpr = xpath.compile( "//BuyerTradeParty"); NodeList BuyerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + xpr = xpath.compile( + "//*[local-name()=\"ExchangedDocument\"]"); + NodeList ExchangedDocumentNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); - zpp = new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number); + Date issueDate = null; + Date dueDate = null; + Date deliveryDate = null; + for (int i = 0; i < ExchangedDocumentNodes.getLength(); i++) { + + //nodes.item(i).getTextContent())) { + Node exchangedDocumentNode = ExchangedDocumentNodes.item(i); + NodeList exchangedDocumentChilds = exchangedDocumentNode.getChildNodes(); + for (int documentChildIndex = 0; documentChildIndex < exchangedDocumentChilds.getLength(); documentChildIndex++) { + if (exchangedDocumentChilds.item(documentChildIndex).getNodeName().equals("ram:ID")) { + /* NodeList tradeLineChilds = itemChilds.item(documentChildIndex).getChildNodes(); + for (int tradeLineChildIndex = 0; tradeLineChildIndex < tradeLineChilds.getLength(); tradeLineChildIndex++) { + if (tradeLineChilds.item(tradeLineChildIndex).getNodeName().equals("ram:NetPriceProductTradePrice")) { + NodeList netChilds = tradeLineChilds.item(tradeLineChildIndex).getChildNodes(); + for (int netIndex = 0; netIndex < netChilds.getLength(); netIndex++) { + if (netChilds.item(netIndex).getNodeName().equals("ram:ChargeAmount")) { + price = netChilds.item(netIndex).getTextContent();//ram:ChargeAmount + + } + } + } + }*/ + number = exchangedDocumentChilds.item(documentChildIndex).getTextContent(); + } + if (exchangedDocumentChilds.item(documentChildIndex).getNodeName().equals("ram:IssueDateTime")) { + NodeList issueDateTimeChilds = exchangedDocumentChilds.item(documentChildIndex).getChildNodes(); + for (int issueDateChildIndex = 0; issueDateChildIndex < issueDateTimeChilds.getLength(); issueDateChildIndex++) { + if (issueDateTimeChilds.item(issueDateChildIndex).getNodeName().equals("udt:DateTimeString")) { + issueDate = new SimpleDateFormat("yyyyMMdd").parse(issueDateTimeChilds.item(issueDateChildIndex).getTextContent()); + } + } + } + } + } + + + xpr = xpath.compile( + "//*[local-name()=\"ApplicableHeaderTradeDelivery\"]"); + NodeList headerTradeDeliveryNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + + for (int i = 0; i < headerTradeDeliveryNodes.getLength(); i++) { + //nodes.item(i).getTextContent())) { + Node headerTradeDeliveryNode = headerTradeDeliveryNodes.item(i); + NodeList headerTradeDeliveryChilds = headerTradeDeliveryNode.getChildNodes(); + for (int deliveryChildIndex = 0; deliveryChildIndex < headerTradeDeliveryChilds.getLength(); deliveryChildIndex++) { + if (headerTradeDeliveryChilds.item(deliveryChildIndex).getNodeName().equals("ram:ActualDeliverySupplyChainEvent")) { + NodeList actualDeliveryChilds = headerTradeDeliveryChilds.item(deliveryChildIndex).getChildNodes(); + for (int actualDeliveryChildIndex = 0; actualDeliveryChildIndex < actualDeliveryChilds.getLength(); actualDeliveryChildIndex++) { + if (actualDeliveryChilds.item(actualDeliveryChildIndex).getNodeName().equals("ram:OccurrenceDateTime")) { + NodeList occurenceChilds = actualDeliveryChilds.item(actualDeliveryChildIndex).getChildNodes(); + for (int occurenceChildIndex = 0; occurenceChildIndex < occurenceChilds.getLength(); occurenceChildIndex++) { + if (occurenceChilds.item(occurenceChildIndex).getNodeName().equals("udt:DateTimeString")) { + deliveryDate = new SimpleDateFormat("yyyyMMdd").parse(occurenceChilds.item(occurenceChildIndex).getTextContent()); + + } + } + } + } + } + } + } + + + xpr = xpath.compile( + "//*[local-name()=\"ApplicableHeaderTradeSettlement\"]"); + NodeList headerTradeSettlementNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + + for (int i = 0; i < headerTradeSettlementNodes.getLength(); i++) { + //nodes.item(i).getTextContent())) { + Node headerTradeSettlementNode = headerTradeSettlementNodes.item(i); + NodeList headerTradeSettlementChilds = headerTradeSettlementNode.getChildNodes(); + for (int settlementChildIndex = 0; settlementChildIndex < headerTradeSettlementChilds.getLength(); settlementChildIndex++) { + if (headerTradeSettlementChilds.item(settlementChildIndex).getNodeName().equals("ram:SpecifiedTradePaymentTerms")) { + NodeList paymentTermChilds = headerTradeSettlementChilds.item(settlementChildIndex).getChildNodes(); + for (int paymentTermChildIndex = 0; paymentTermChildIndex < paymentTermChilds.getLength(); paymentTermChildIndex++) { + if (paymentTermChilds.item(paymentTermChildIndex).getNodeName().equals("ram:DueDateDateTime")) { + NodeList dueDateChilds = paymentTermChilds.item(paymentTermChildIndex).getChildNodes(); + for (int dueDateChildIndex = 0; dueDateChildIndex < dueDateChilds.getLength(); dueDateChildIndex++) { + if (dueDateChilds.item(dueDateChildIndex).getNodeName().equals("udt:DateTimeString")) { + dueDate = new SimpleDateFormat("yyyyMMdd").parse(dueDateChilds.item(dueDateChildIndex).getTextContent()); + + } + } + } + } + } + } + } + + zpp = new Invoice().setDueDate(dueDate).setDeliveryDate(deliveryDate).setIssueDate(issueDate).setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number); //.addItem(new Item(new Product("Testprodukt","","C62",new BigDecimal(0)),amount,new BigDecimal(1.0))) zpp.setOwnOrganisationName(extractString("//SellerTradeParty/Name")); @@ -109,10 +203,10 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { } catch (XPathExpressionException e) { e.printStackTrace(); + } catch (ParseException ex) { + ex.printStackTrace(); } return zpp; } - - } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java index 9d599875..6c70f5cb 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java @@ -49,7 +49,7 @@ public class ZF2PushTest extends TestCase { // the writing part String orgname = "Test company"; - String number = "123"; + String number = "RE-20170509/505"; String amountStr = "1.00"; BigDecimal amount = new BigDecimal(amountStr); String occurenceFrom = "20201001"; diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java index 6f0568d2..37a8e823 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java @@ -27,6 +27,11 @@ import junit.framework.TestCase; import junit.framework.Test; import junit.framework.TestSuite; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + /*** * Classname ZF2ZInvoiceImporterTest is alphabetical behind the tests which will create the file @@ -49,6 +54,15 @@ public class ZF2ZInvoiceImporterTest extends TestCase { assertEquals("Heiße Luft pro Liter", invoice.getZFItems()[2].getProduct().getName()); assertEquals("LTR", invoice.getZFItems()[2].getProduct().getUnit()); assertEquals("7.00", invoice.getZFItems()[0].getProduct().getVATPercent().toString()); + assertEquals("RE-20170509/505", invoice.getNumber()); + + SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); + assertEquals("2017-05-09",sdf.format(invoice.getIssueDate())); + assertEquals("2017-05-07",sdf.format(invoice.getDeliveryDate())); + assertEquals("2017-05-30",sdf.format(invoice.getDueDate())); + + + // name street location zip country, contact name phone email, total amount From aaa106f09a5d09ec5cea6e8edb0b5b70679b3858 Mon Sep 17 00:00:00 2001 From: jstaerk Date: Sat, 31 Oct 2020 16:43:04 +0100 Subject: [PATCH 4/6] import seller and buyer correctly --- .../ZUGFeRD/ZUGFeRDInvoiceImporter.java | 26 +++++++------------ .../ZUGFeRD/ZF2ZInvoiceImporterTest.java | 9 +++++++ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java index 5dfe8b9c..c219caec 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java @@ -15,10 +15,14 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { super(filename); } + /*** + * This will parse a XML into a invoice object + * @return the parsed invoice object + */ public Invoice extractInvoice() { String number = ""; - /** + /* * dummywerte sind derzeit noch setDueDate setIssueDate setDeliveryDate setSender setRecipient setnumber * bspw. due date //ExchangedDocument//IssueDateTime//DateTimeString : due date optional */ @@ -27,15 +31,17 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { Invoice zpp = null; try { XPathExpression xpr = xpath.compile( - "//SellerTradeParty"); + "//*[local-name()=\"SellerTradeParty\"]"); NodeList SellerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + xpr = xpath.compile( - "//BuyerTradeParty"); + "//*[local-name()=\"BuyerTradeParty\"]"); NodeList BuyerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); xpr = xpath.compile( "//*[local-name()=\"ExchangedDocument\"]"); NodeList ExchangedDocumentNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + Date issueDate = null; Date dueDate = null; Date deliveryDate = null; @@ -46,18 +52,6 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { NodeList exchangedDocumentChilds = exchangedDocumentNode.getChildNodes(); for (int documentChildIndex = 0; documentChildIndex < exchangedDocumentChilds.getLength(); documentChildIndex++) { if (exchangedDocumentChilds.item(documentChildIndex).getNodeName().equals("ram:ID")) { - /* NodeList tradeLineChilds = itemChilds.item(documentChildIndex).getChildNodes(); - for (int tradeLineChildIndex = 0; tradeLineChildIndex < tradeLineChilds.getLength(); tradeLineChildIndex++) { - if (tradeLineChilds.item(tradeLineChildIndex).getNodeName().equals("ram:NetPriceProductTradePrice")) { - NodeList netChilds = tradeLineChilds.item(tradeLineChildIndex).getChildNodes(); - for (int netIndex = 0; netIndex < netChilds.getLength(); netIndex++) { - if (netChilds.item(netIndex).getNodeName().equals("ram:ChargeAmount")) { - price = netChilds.item(netIndex).getTextContent();//ram:ChargeAmount - - } - } - } - }*/ number = exchangedDocumentChilds.item(documentChildIndex).getTextContent(); } if (exchangedDocumentChilds.item(documentChildIndex).getNodeName().equals("ram:IssueDateTime")) { @@ -128,7 +122,6 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { zpp = new Invoice().setDueDate(dueDate).setDeliveryDate(deliveryDate).setIssueDate(issueDate).setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number); //.addItem(new Item(new Product("Testprodukt","","C62",new BigDecimal(0)),amount,new BigDecimal(1.0))) zpp.setOwnOrganisationName(extractString("//SellerTradeParty/Name")); - xpr = xpath.compile( "//*[local-name()=\"IncludedSupplyChainTradeLineItem\"]"); NodeList nodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); @@ -209,4 +202,5 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { return zpp; } + } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java index 37a8e823..3ebad073 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java @@ -61,6 +61,15 @@ public class ZF2ZInvoiceImporterTest extends TestCase { assertEquals("2017-05-07",sdf.format(invoice.getDeliveryDate())); assertEquals("2017-05-30",sdf.format(invoice.getDueDate())); + assertEquals("Bahnstr. 42", invoice.getRecipient().getStreet()); + assertEquals("88802", invoice.getRecipient().getZIP()); + assertEquals("DE", invoice.getRecipient().getCountry()); + assertEquals("Spielkreis", invoice.getRecipient().getLocation()); + + assertEquals("Ecke 12", invoice.getSender().getStreet()); + assertEquals("12345", invoice.getSender().getZIP()); + assertEquals("DE", invoice.getSender().getCountry()); + assertEquals("Stadthausen", invoice.getSender().getLocation()); // name street location zip country, contact name phone email, total amount From ede19a6b74b7e34c1fae50bce0cf641954556986 Mon Sep 17 00:00:00 2001 From: jstaerk Date: Sat, 31 Oct 2020 18:16:10 +0100 Subject: [PATCH 5/6] refactoring Transactioncalculator --- History.md | 7 +- .../{LineCalc.java => LineCalculator.java} | 8 +- .../ZUGFeRD/TransactionCalculator.java | 134 ++++++++ .../ZUGFeRD/ZUGFeRD1PullProvider.java | 19 +- .../ZUGFeRD/ZUGFeRD2PullProvider.java | 147 +------- .../ZUGFeRD/ZUGFeRDInvoiceImporter.java | 317 +++++++++--------- .../ZUGFeRD/ZF2ZInvoiceImporterTest.java | 16 +- 7 files changed, 340 insertions(+), 308 deletions(-) rename library/src/main/java/org/mustangproject/ZUGFeRD/{LineCalc.java => LineCalculator.java} (89%) create mode 100644 library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java diff --git a/History.md b/History.md index 05ce9552..8571a94b 100644 --- a/History.md +++ b/History.md @@ -3,16 +3,17 @@ - support for ZF 2.1.1, i.e. "Reference profile" Xrechnung - ZF 2.1.1 now default (up to 1.7.8 ZF2 could be set but ZF1 was default) +- integrates validator - removed jaxb #87 - fluent setter api/pushprovider #40 -- new xrechnung profile -- visualization? zugferdvisualizer? +- new xrechnung reference profile +- visualization zugferdvisualizer - migration feature (XSLT upgrade of ZF1 to ZF2) has been improved and moved from the commandline into the library - german bank account numbers can no longer be specified (dropped in favor of IBAN and BIC) - factory for xrechnung #86 - moved to Maven central - complete or discard read into push provider -- integrates validator +- now TransactionCalculator is a dedicated class and no longer mixed up with pullprovider - validator now additionally supports xrechnung - modular project setup - getSellerTradePartyAddress (PR #157 ) thanks to aberndt-hub diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalc.java b/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java similarity index 89% rename from library/src/main/java/org/mustangproject/ZUGFeRD/LineCalc.java rename to library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java index 39511cb0..5912ff3f 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalc.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java @@ -2,7 +2,11 @@ package org.mustangproject.ZUGFeRD; import java.math.BigDecimal; -public class LineCalc { +/*** + * the linecalculator does the math within an item line, and e.g. calculates quantity*price. + * @see TransactionCalculator + */ +public class LineCalculator { private BigDecimal totalGross; private BigDecimal price; private BigDecimal priceGross; @@ -11,7 +15,7 @@ public class LineCalc { private BigDecimal allowance = new BigDecimal(0); private BigDecimal charge = new BigDecimal(0); - public LineCalc(IZUGFeRDExportableItem currentItem) { + public LineCalculator(IZUGFeRDExportableItem currentItem) { if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) { for (IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) { diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java new file mode 100644 index 00000000..909a619a --- /dev/null +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java @@ -0,0 +1,134 @@ +package org.mustangproject.ZUGFeRD; + +import java.math.BigDecimal; +import java.util.HashMap; + +/*** + * The Transactioncalculator e.g. adds the line totals and applies VAT on whole invoices + * @see LineCalculator + */ +public class TransactionCalculator implements IAbsoluteValueProvider { + protected IExportableTransaction trans; + + public TransactionCalculator(IExportableTransaction trans) { + this.trans=trans; + } + + protected BigDecimal getTotalPrepaid() { + if (trans.getTotalPrepaidAmount() == null) { + return new BigDecimal(0); + } else { + return trans.getTotalPrepaidAmount(); + } + } + + protected BigDecimal getTotalGross() { + + BigDecimal res = getTaxBasis(); + HashMap VATPercentAmountMap = getVATPercentAmountMap(); + for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { + VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); + res = res.add(amount.getCalculated()); + } + return res; + } + + protected BigDecimal getCharges() { + BigDecimal res = new BigDecimal(0); + IZUGFeRDAllowanceCharge[] charges = trans.getZFCharges(); + if ((charges != null) && (charges.length > 0)) { + for (IZUGFeRDAllowanceCharge currentCharge : charges) { + res = res.add(currentCharge.getTotalAmount(this)); + } + } + return res; + } + + protected BigDecimal getAllowances() { + BigDecimal res = new BigDecimal(0); + IZUGFeRDAllowanceCharge[] allowances = trans.getZFAllowances(); + if ((allowances != null) && (allowances.length > 0)) { + for (IZUGFeRDAllowanceCharge currentAllowance : allowances) { + res = res.add(currentAllowance.getTotalAmount(this)); + } + } + return res; + } + + protected BigDecimal getTotal() { + BigDecimal res = new BigDecimal(0); + for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { + LineCalculator lc = new LineCalculator(currentItem); + res = res.add(lc.getItemTotalGrossAmount()); + } + return res; + } + + protected BigDecimal getTaxBasis() { + BigDecimal res = getTotal().add(getCharges()).subtract(getAllowances()); + return res; + } + + /** + * which taxes have been used with which amounts in this transaction, empty for + * no taxes, or e.g. 19:190 and 7:14 if 1000 Eur were applicable to 19% VAT + * (=190 EUR VAT) and 200 EUR were applicable to 7% (=14 EUR VAT) 190 Eur + * + * @return which taxes have been used with which amounts in this invoice + */ + protected HashMap getVATPercentAmountMap() { + HashMap hm = new HashMap<>(); + + for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { + BigDecimal percent = currentItem.getProduct().getVATPercent(); + LineCalculator lc = new LineCalculator(currentItem); + VATAmount itemVATAmount = new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount(), + trans.getDocumentCode()); + VATAmount current = hm.get(percent); + if (current == null) { + hm.put(percent, itemVATAmount); + } else { + hm.put(percent, current.add(itemVATAmount)); + } + } + + + IZUGFeRDAllowanceCharge[] charges = trans.getZFCharges(); + if ((charges != null) && (charges.length > 0)) { + for (IZUGFeRDAllowanceCharge currentCharge : charges) { + VATAmount theAmount = hm.get(currentCharge.getTaxPercent()); + if (theAmount == null) { + theAmount = new VATAmount(new BigDecimal(0), new BigDecimal(0), "S"); + } + theAmount.setBasis(theAmount.getBasis().add(currentCharge.getTotalAmount(this))); + BigDecimal factor = currentCharge.getTaxPercent().divide(new BigDecimal(100)); + theAmount.setCalculated(theAmount.getBasis().multiply(factor)); + hm.put(currentCharge.getTaxPercent(), theAmount); + } + } + IZUGFeRDAllowanceCharge[] allowances = trans.getZFAllowances(); + if ((allowances != null) && (allowances.length > 0)) { + for (IZUGFeRDAllowanceCharge currentAllowance : allowances) { + VATAmount theAmount = hm.get(currentAllowance.getTaxPercent()); + if (theAmount == null) { + theAmount = new VATAmount(new BigDecimal(0), new BigDecimal(0), "S"); + } + theAmount.setBasis(theAmount.getBasis().subtract(currentAllowance.getTotalAmount(this))); + BigDecimal factor = currentAllowance.getTaxPercent().divide(new BigDecimal(100)); + theAmount.setCalculated(theAmount.getBasis().multiply(factor)); + + hm.put(currentAllowance.getTaxPercent(), theAmount); + } + } + + + return hm; + } + + + @Override + public BigDecimal getValue() { + return getTotal(); + } + +} diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java index deca7fcf..032b6bfc 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java @@ -104,6 +104,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr @Override public void generateXML(IExportableTransaction trans) { this.trans = trans; + this.calc=new TransactionCalculator(trans); boolean hasDueDate=false; String taxCategoryCode=""; @@ -288,7 +289,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr } } - HashMap VATPercentAmountMap = getVATPercentAmountMap(); + HashMap VATPercentAmountMap = calc.getVATPercentAmountMap(); for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); if (amount != null) { @@ -329,23 +330,23 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr } xml = xml + " \n" - + " " + currencyFormat(getTotal()) + "\n" //$NON-NLS-2$ + + " " + currencyFormat(calc.getTotal()) + "\n" //$NON-NLS-2$ // currencyID=\"EUR\" + " 0.00\n" // currencyID=\"EUR\" + " 0.00\n" // // currencyID=\"EUR\" // + " 5.80\n" // + " 14.73\n" - + " " + currencyFormat(getTotal()) + "\n" //$NON-NLS-2$ + + " " + currencyFormat(calc.getTotal()) + "\n" //$NON-NLS-2$ // // // currencyID=\"EUR\" + " " - + currencyFormat(getTotalGross().subtract(getTotal())) + "\n" - + " " + currencyFormat(getTotalGross()) + "\n" //$NON-NLS-2$ + + currencyFormat(calc.getTotalGross().subtract(calc.getTotal())) + "\n" + + " " + currencyFormat(calc.getTotalGross()) + "\n" //$NON-NLS-2$ // // // currencyID=\"EUR\" - + " " + currencyFormat(getTotalPrepaid()) + "\n" - + " " + currencyFormat(getTotalGross().subtract(getTotalPrepaid())) + "\n" //$NON-NLS-2$ + + " " + currencyFormat(calc.getTotalPrepaid()) + "\n" + + " " + currencyFormat(calc.getTotalGross().subtract(calc.getTotalPrepaid())) + "\n" //$NON-NLS-2$ // // // currencyID=\"EUR\" + " \n" @@ -361,7 +362,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr } - LineCalc lc = new LineCalc(currentItem); + LineCalculator lc = new LineCalculator(currentItem); xml = xml + " \n" + " \n" + " " + lineID + "\n" //$NON-NLS-2$ @@ -482,7 +483,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr if (discountTerms != null) { paymentTermsXml += ""; String currency = trans.getCurrency(); - String basisAmount = currencyFormat(getTotalGross()); + String basisAmount = currencyFormat(calc.getTotalGross()); paymentTermsXml += "" + basisAmount + ""; paymentTermsXml += "" + discountTerms.getCalculationPercentage().toString() + ""; diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 75fda7af..9dc9b68d 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -31,22 +31,21 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.Base64; -import net.sf.saxon.value.Base64BinaryValue; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.mustangproject.FileAttachment; -import org.mustangproject.Invoice; import org.mustangproject.XMLTools; -public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvider { +public class ZUGFeRD2PullProvider implements IXMLProvider { //// MAIN CLASS protected SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); protected byte[] zugferdData; protected IExportableTransaction trans; + protected TransactionCalculator calc; private String paymentTermsDescription; protected Profile profile = Profiles.getByName("EN16931"); @@ -100,117 +99,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide } - //move - protected BigDecimal getTotalPrepaid() { - if (trans.getTotalPrepaidAmount() == null) { - return new BigDecimal(0); - } else { - return trans.getTotalPrepaidAmount(); - } - } - - protected BigDecimal getTotalGross() { - - BigDecimal res = getTaxBasis(); - HashMap VATPercentAmountMap = getVATPercentAmountMap(); - for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { - VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); - res = res.add(amount.getCalculated()); - } - return res; - } - - protected BigDecimal getCharges() { - BigDecimal res = new BigDecimal(0); - IZUGFeRDAllowanceCharge[] charges = trans.getZFCharges(); - if ((charges != null) && (charges.length > 0)) { - for (IZUGFeRDAllowanceCharge currentCharge : charges) { - res = res.add(currentCharge.getTotalAmount(this)); - } - } - return res; - } - - protected BigDecimal getAllowances() { - BigDecimal res = new BigDecimal(0); - IZUGFeRDAllowanceCharge[] allowances = trans.getZFAllowances(); - if ((allowances != null) && (allowances.length > 0)) { - for (IZUGFeRDAllowanceCharge currentAllowance : allowances) { - res = res.add(currentAllowance.getTotalAmount(this)); - } - } - return res; - } - - protected BigDecimal getTotal() { - BigDecimal res = new BigDecimal(0); - for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { - LineCalc lc = new LineCalc(currentItem); - res = res.add(lc.getItemTotalGrossAmount()); - } - return res; - } - - protected BigDecimal getTaxBasis() { - BigDecimal res = getTotal().add(getCharges()).subtract(getAllowances()); - return res; - } - - /** - * which taxes have been used with which amounts in this transaction, empty for - * no taxes, or e.g. 19:190 and 7:14 if 1000 Eur were applicable to 19% VAT - * (=190 EUR VAT) and 200 EUR were applicable to 7% (=14 EUR VAT) 190 Eur - * - * @return which taxes have been used with which amounts in this invoice - */ - protected HashMap getVATPercentAmountMap() { - HashMap hm = new HashMap<>(); - - for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { - BigDecimal percent = currentItem.getProduct().getVATPercent(); - LineCalc lc = new LineCalc(currentItem); - VATAmount itemVATAmount = new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount(), - trans.getDocumentCode()); - VATAmount current = hm.get(percent); - if (current == null) { - hm.put(percent, itemVATAmount); - } else { - hm.put(percent, current.add(itemVATAmount)); - } - } - - - IZUGFeRDAllowanceCharge[] charges = trans.getZFCharges(); - if ((charges != null) && (charges.length > 0)) { - for (IZUGFeRDAllowanceCharge currentCharge : charges) { - VATAmount theAmount = hm.get(currentCharge.getTaxPercent()); - if (theAmount == null) { - theAmount = new VATAmount(new BigDecimal(0), new BigDecimal(0), "S"); - } - theAmount.setBasis(theAmount.getBasis().add(currentCharge.getTotalAmount(this))); - BigDecimal factor = currentCharge.getTaxPercent().divide(new BigDecimal(100)); - theAmount.setCalculated(theAmount.getBasis().multiply(factor)); - hm.put(currentCharge.getTaxPercent(), theAmount); - } - } - IZUGFeRDAllowanceCharge[] allowances = trans.getZFAllowances(); - if ((allowances != null) && (allowances.length > 0)) { - for (IZUGFeRDAllowanceCharge currentAllowance : allowances) { - VATAmount theAmount = hm.get(currentAllowance.getTaxPercent()); - if (theAmount == null) { - theAmount = new VATAmount(new BigDecimal(0), new BigDecimal(0), "S"); - } - theAmount.setBasis(theAmount.getBasis().subtract(currentAllowance.getTotalAmount(this))); - BigDecimal factor = currentAllowance.getTaxPercent().divide(new BigDecimal(100)); - theAmount.setCalculated(theAmount.getBasis().multiply(factor)); - - hm.put(currentAllowance.getTaxPercent(), theAmount); - } - } - - - return hm; - } @Override public Profile getProfile() { @@ -305,6 +193,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide @Override public void generateXML(IExportableTransaction trans) { this.trans = trans; + this.calc=new TransactionCalculator(trans); boolean hasDueDate = false; String taxCategoryCode = ""; @@ -387,7 +276,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide exemptionReason = "" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + ""; } - LineCalc lc = new LineCalc(currentItem); + LineCalculator lc = new LineCalculator(currentItem); xml = xml + " \n" + " \n" + " " + lineID + "\n" //$NON-NLS-2$ @@ -558,7 +447,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide } } - HashMap VATPercentAmountMap = getVATPercentAmountMap(); + HashMap VATPercentAmountMap = calc.getVATPercentAmountMap(); for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); if (amount != null) { @@ -592,7 +481,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide " \n" + " true\n" + " \n" + - " " + currencyFormat(getCharges()) + "\n" + + " " + currencyFormat(calc.getCharges()) + "\n" + " Charge\n" + " \n" + " VAT\n" + @@ -609,7 +498,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide " \n" + " false\n" + " \n" + - " " + currencyFormat(getAllowances()) + "\n" + + " " + currencyFormat(calc.getAllowances()) + "\n" + " Allowance\n" + " \n" + " VAT\n" + @@ -645,24 +534,24 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide } - String allowanceTotalLine = "" + currencyFormat(getAllowances()) + ""; + String allowanceTotalLine = "" + currencyFormat(calc.getAllowances()) + ""; - String chargesTotalLine = "" + currencyFormat(getCharges()) + ""; + String chargesTotalLine = "" + currencyFormat(calc.getCharges()) + ""; xml = xml + " \n" - + " " + currencyFormat(getTotal()) + "\n" //$NON-NLS-2$ + + " " + currencyFormat(calc.getTotal()) + "\n" //$NON-NLS-2$ + chargesTotalLine + allowanceTotalLine - + " " + currencyFormat(getTaxBasis()) + "\n" //$NON-NLS-2$ + + " " + currencyFormat(calc.getTaxBasis()) + "\n" //$NON-NLS-2$ // // // currencyID=\"EUR\" + " " - + currencyFormat(getTotalGross().subtract(getTaxBasis())) + "\n" - + " " + currencyFormat(getTotalGross()) + "\n" //$NON-NLS-2$ + + currencyFormat(calc.getTotalGross().subtract(calc.getTaxBasis())) + "\n" + + " " + currencyFormat(calc.getTotalGross()) + "\n" //$NON-NLS-2$ // // // currencyID=\"EUR\" - + " " + currencyFormat(getTotalPrepaid()) + "\n" - + " " + currencyFormat(getTotalGross().subtract(getTotalPrepaid())) + "\n" //$NON-NLS-2$ + + " " + currencyFormat(calc.getTotalPrepaid()) + "\n" + + " " + currencyFormat(calc.getTotalGross().subtract(calc.getTotalPrepaid())) + "\n" //$NON-NLS-2$ // // // currencyID=\"EUR\" + " \n" @@ -721,7 +610,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide if (discountTerms != null) { paymentTermsXml += ""; String currency = trans.getCurrency(); - String basisAmount = currencyFormat(getTotalGross()); + String basisAmount = currencyFormat(calc.getTotalGross()); paymentTermsXml += "" + basisAmount + ""; paymentTermsXml += "" + discountTerms.getCalculationPercentage().toString() + ""; @@ -743,8 +632,4 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide return paymentTermsXml; } - @Override - public BigDecimal getValue() { - return getTotal(); - } } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java index c219caec..042398f9 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java @@ -19,7 +19,7 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { * This will parse a XML into a invoice object * @return the parsed invoice object */ - public Invoice extractInvoice() { + public Invoice extractInvoice() throws XPathExpressionException, ParseException { String number = ""; /* @@ -29,177 +29,170 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { XPathFactory xpathFact = XPathFactory.newInstance(); XPath xpath = xpathFact.newXPath(); Invoice zpp = null; - try { - XPathExpression xpr = xpath.compile( - "//*[local-name()=\"SellerTradeParty\"]"); - NodeList SellerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + XPathExpression xpr = xpath.compile( + "//*[local-name()=\"SellerTradeParty\"]"); + NodeList SellerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); - xpr = xpath.compile( - "//*[local-name()=\"BuyerTradeParty\"]"); - NodeList BuyerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); - xpr = xpath.compile( - "//*[local-name()=\"ExchangedDocument\"]"); - NodeList ExchangedDocumentNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + xpr = xpath.compile( + "//*[local-name()=\"BuyerTradeParty\"]"); + NodeList BuyerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + xpr = xpath.compile( + "//*[local-name()=\"ExchangedDocument\"]"); + NodeList ExchangedDocumentNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); - Date issueDate = null; - Date dueDate = null; - Date deliveryDate = null; - for (int i = 0; i < ExchangedDocumentNodes.getLength(); i++) { + Date issueDate = null; + Date dueDate = null; + Date deliveryDate = null; + for (int i = 0; i < ExchangedDocumentNodes.getLength(); i++) { - //nodes.item(i).getTextContent())) { - Node exchangedDocumentNode = ExchangedDocumentNodes.item(i); - NodeList exchangedDocumentChilds = exchangedDocumentNode.getChildNodes(); - for (int documentChildIndex = 0; documentChildIndex < exchangedDocumentChilds.getLength(); documentChildIndex++) { - if (exchangedDocumentChilds.item(documentChildIndex).getNodeName().equals("ram:ID")) { - number = exchangedDocumentChilds.item(documentChildIndex).getTextContent(); - } - if (exchangedDocumentChilds.item(documentChildIndex).getNodeName().equals("ram:IssueDateTime")) { - NodeList issueDateTimeChilds = exchangedDocumentChilds.item(documentChildIndex).getChildNodes(); - for (int issueDateChildIndex = 0; issueDateChildIndex < issueDateTimeChilds.getLength(); issueDateChildIndex++) { - if (issueDateTimeChilds.item(issueDateChildIndex).getNodeName().equals("udt:DateTimeString")) { - issueDate = new SimpleDateFormat("yyyyMMdd").parse(issueDateTimeChilds.item(issueDateChildIndex).getTextContent()); - } + //nodes.item(i).getTextContent())) { + Node exchangedDocumentNode = ExchangedDocumentNodes.item(i); + NodeList exchangedDocumentChilds = exchangedDocumentNode.getChildNodes(); + for (int documentChildIndex = 0; documentChildIndex < exchangedDocumentChilds.getLength(); documentChildIndex++) { + if (exchangedDocumentChilds.item(documentChildIndex).getNodeName().equals("ram:ID")) { + number = exchangedDocumentChilds.item(documentChildIndex).getTextContent(); + } + if (exchangedDocumentChilds.item(documentChildIndex).getNodeName().equals("ram:IssueDateTime")) { + NodeList issueDateTimeChilds = exchangedDocumentChilds.item(documentChildIndex).getChildNodes(); + for (int issueDateChildIndex = 0; issueDateChildIndex < issueDateTimeChilds.getLength(); issueDateChildIndex++) { + if (issueDateTimeChilds.item(issueDateChildIndex).getNodeName().equals("udt:DateTimeString")) { + issueDate = new SimpleDateFormat("yyyyMMdd").parse(issueDateTimeChilds.item(issueDateChildIndex).getTextContent()); } } } } - - - xpr = xpath.compile( - "//*[local-name()=\"ApplicableHeaderTradeDelivery\"]"); - NodeList headerTradeDeliveryNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); - - for (int i = 0; i < headerTradeDeliveryNodes.getLength(); i++) { - //nodes.item(i).getTextContent())) { - Node headerTradeDeliveryNode = headerTradeDeliveryNodes.item(i); - NodeList headerTradeDeliveryChilds = headerTradeDeliveryNode.getChildNodes(); - for (int deliveryChildIndex = 0; deliveryChildIndex < headerTradeDeliveryChilds.getLength(); deliveryChildIndex++) { - if (headerTradeDeliveryChilds.item(deliveryChildIndex).getNodeName().equals("ram:ActualDeliverySupplyChainEvent")) { - NodeList actualDeliveryChilds = headerTradeDeliveryChilds.item(deliveryChildIndex).getChildNodes(); - for (int actualDeliveryChildIndex = 0; actualDeliveryChildIndex < actualDeliveryChilds.getLength(); actualDeliveryChildIndex++) { - if (actualDeliveryChilds.item(actualDeliveryChildIndex).getNodeName().equals("ram:OccurrenceDateTime")) { - NodeList occurenceChilds = actualDeliveryChilds.item(actualDeliveryChildIndex).getChildNodes(); - for (int occurenceChildIndex = 0; occurenceChildIndex < occurenceChilds.getLength(); occurenceChildIndex++) { - if (occurenceChilds.item(occurenceChildIndex).getNodeName().equals("udt:DateTimeString")) { - deliveryDate = new SimpleDateFormat("yyyyMMdd").parse(occurenceChilds.item(occurenceChildIndex).getTextContent()); - - } - } - } - } - } - } - } - - - xpr = xpath.compile( - "//*[local-name()=\"ApplicableHeaderTradeSettlement\"]"); - NodeList headerTradeSettlementNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); - - for (int i = 0; i < headerTradeSettlementNodes.getLength(); i++) { - //nodes.item(i).getTextContent())) { - Node headerTradeSettlementNode = headerTradeSettlementNodes.item(i); - NodeList headerTradeSettlementChilds = headerTradeSettlementNode.getChildNodes(); - for (int settlementChildIndex = 0; settlementChildIndex < headerTradeSettlementChilds.getLength(); settlementChildIndex++) { - if (headerTradeSettlementChilds.item(settlementChildIndex).getNodeName().equals("ram:SpecifiedTradePaymentTerms")) { - NodeList paymentTermChilds = headerTradeSettlementChilds.item(settlementChildIndex).getChildNodes(); - for (int paymentTermChildIndex = 0; paymentTermChildIndex < paymentTermChilds.getLength(); paymentTermChildIndex++) { - if (paymentTermChilds.item(paymentTermChildIndex).getNodeName().equals("ram:DueDateDateTime")) { - NodeList dueDateChilds = paymentTermChilds.item(paymentTermChildIndex).getChildNodes(); - for (int dueDateChildIndex = 0; dueDateChildIndex < dueDateChilds.getLength(); dueDateChildIndex++) { - if (dueDateChilds.item(dueDateChildIndex).getNodeName().equals("udt:DateTimeString")) { - dueDate = new SimpleDateFormat("yyyyMMdd").parse(dueDateChilds.item(dueDateChildIndex).getTextContent()); - - } - } - } - } - } - } - } - - zpp = new Invoice().setDueDate(dueDate).setDeliveryDate(deliveryDate).setIssueDate(issueDate).setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number); -//.addItem(new Item(new Product("Testprodukt","","C62",new BigDecimal(0)),amount,new BigDecimal(1.0))) - zpp.setOwnOrganisationName(extractString("//SellerTradeParty/Name")); - xpr = xpath.compile( - "//*[local-name()=\"IncludedSupplyChainTradeLineItem\"]"); - NodeList nodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); - - if (nodes.getLength() == 0) { - } else { - for (int i = 0; i < nodes.getLength(); i++) { - - String price = "0"; - String name = ""; - String description = ""; - String quantity = "0"; - String vatPercent = "0"; - String unitCode = "0"; - - //nodes.item(i).getTextContent())) { - Node currentItemNode = nodes.item(i); - NodeList itemChilds = currentItemNode.getChildNodes(); - for (int itemChildIndex = 0; itemChildIndex < itemChilds.getLength(); itemChildIndex++) { - if (itemChilds.item(itemChildIndex).getNodeName().equals("ram:SpecifiedLineTradeAgreement")) { - NodeList tradeLineChilds = itemChilds.item(itemChildIndex).getChildNodes(); - for (int tradeLineChildIndex = 0; tradeLineChildIndex < tradeLineChilds.getLength(); tradeLineChildIndex++) { - if (tradeLineChilds.item(tradeLineChildIndex).getNodeName().equals("ram:NetPriceProductTradePrice")) { - NodeList netChilds = tradeLineChilds.item(tradeLineChildIndex).getChildNodes(); - for (int netIndex = 0; netIndex < netChilds.getLength(); netIndex++) { - if (netChilds.item(netIndex).getNodeName().equals("ram:ChargeAmount")) { - price = netChilds.item(netIndex).getTextContent();//ram:ChargeAmount - - } - } - } - } - } - if (itemChilds.item(itemChildIndex).getNodeName().equals("ram:SpecifiedLineTradeDelivery")) { - NodeList tradeLineChilds = itemChilds.item(itemChildIndex).getChildNodes(); - for (int tradeLineChildIndex = 0; tradeLineChildIndex < tradeLineChilds.getLength(); tradeLineChildIndex++) { - if (tradeLineChilds.item(tradeLineChildIndex).getNodeName().equals("ram:BilledQuantity")) { - quantity = tradeLineChilds.item(tradeLineChildIndex).getTextContent(); - unitCode = tradeLineChilds.item(tradeLineChildIndex).getAttributes().getNamedItem("unitCode").getNodeValue(); - } - } - } - if (itemChilds.item(itemChildIndex).getNodeName().equals("ram:SpecifiedTradeProduct")) { - NodeList tradeProductChilds = itemChilds.item(itemChildIndex).getChildNodes(); - for (int tradeProductChildIndex = 0; tradeProductChildIndex < tradeProductChilds.getLength(); tradeProductChildIndex++) { - if (tradeProductChilds.item(tradeProductChildIndex).getNodeName().equals("ram:Name")) { - name = tradeProductChilds.item(tradeProductChildIndex).getTextContent(); - } - } - } - if (itemChilds.item(itemChildIndex).getNodeName().equals("ram:SpecifiedLineTradeSettlement")) { - NodeList tradeSettlementChilds = itemChilds.item(itemChildIndex).getChildNodes(); - for (int tradeSettlementChildIndex = 0; tradeSettlementChildIndex < tradeSettlementChilds.getLength(); tradeSettlementChildIndex++) { - if (tradeSettlementChilds.item(tradeSettlementChildIndex).getNodeName().equals("ram:ApplicableTradeTax")) { - NodeList taxChilds = tradeSettlementChilds.item(tradeSettlementChildIndex).getChildNodes(); - for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) { - if (taxChilds.item(taxChildIndex).getNodeName().equals("ram:RateApplicablePercent")) { - vatPercent = taxChilds.item(taxChildIndex).getTextContent(); - } - } - } - } - } - - - } - zpp.addItem(new Item(new Product(name, description, unitCode, new BigDecimal(vatPercent)), new BigDecimal(price), new BigDecimal(quantity))); - } - - } - - - } catch (XPathExpressionException e) { - e.printStackTrace(); - } catch (ParseException ex) { - ex.printStackTrace(); } + + xpr = xpath.compile( + "//*[local-name()=\"ApplicableHeaderTradeDelivery\"]"); + NodeList headerTradeDeliveryNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + + for (int i = 0; i < headerTradeDeliveryNodes.getLength(); i++) { + //nodes.item(i).getTextContent())) { + Node headerTradeDeliveryNode = headerTradeDeliveryNodes.item(i); + NodeList headerTradeDeliveryChilds = headerTradeDeliveryNode.getChildNodes(); + for (int deliveryChildIndex = 0; deliveryChildIndex < headerTradeDeliveryChilds.getLength(); deliveryChildIndex++) { + if (headerTradeDeliveryChilds.item(deliveryChildIndex).getNodeName().equals("ram:ActualDeliverySupplyChainEvent")) { + NodeList actualDeliveryChilds = headerTradeDeliveryChilds.item(deliveryChildIndex).getChildNodes(); + for (int actualDeliveryChildIndex = 0; actualDeliveryChildIndex < actualDeliveryChilds.getLength(); actualDeliveryChildIndex++) { + if (actualDeliveryChilds.item(actualDeliveryChildIndex).getNodeName().equals("ram:OccurrenceDateTime")) { + NodeList occurenceChilds = actualDeliveryChilds.item(actualDeliveryChildIndex).getChildNodes(); + for (int occurenceChildIndex = 0; occurenceChildIndex < occurenceChilds.getLength(); occurenceChildIndex++) { + if (occurenceChilds.item(occurenceChildIndex).getNodeName().equals("udt:DateTimeString")) { + deliveryDate = new SimpleDateFormat("yyyyMMdd").parse(occurenceChilds.item(occurenceChildIndex).getTextContent()); + + } + } + } + } + } + } + } + + + xpr = xpath.compile( + "//*[local-name()=\"ApplicableHeaderTradeSettlement\"]"); + NodeList headerTradeSettlementNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + + for (int i = 0; i < headerTradeSettlementNodes.getLength(); i++) { + //nodes.item(i).getTextContent())) { + Node headerTradeSettlementNode = headerTradeSettlementNodes.item(i); + NodeList headerTradeSettlementChilds = headerTradeSettlementNode.getChildNodes(); + for (int settlementChildIndex = 0; settlementChildIndex < headerTradeSettlementChilds.getLength(); settlementChildIndex++) { + if (headerTradeSettlementChilds.item(settlementChildIndex).getNodeName().equals("ram:SpecifiedTradePaymentTerms")) { + NodeList paymentTermChilds = headerTradeSettlementChilds.item(settlementChildIndex).getChildNodes(); + for (int paymentTermChildIndex = 0; paymentTermChildIndex < paymentTermChilds.getLength(); paymentTermChildIndex++) { + if (paymentTermChilds.item(paymentTermChildIndex).getNodeName().equals("ram:DueDateDateTime")) { + NodeList dueDateChilds = paymentTermChilds.item(paymentTermChildIndex).getChildNodes(); + for (int dueDateChildIndex = 0; dueDateChildIndex < dueDateChilds.getLength(); dueDateChildIndex++) { + if (dueDateChilds.item(dueDateChildIndex).getNodeName().equals("udt:DateTimeString")) { + dueDate = new SimpleDateFormat("yyyyMMdd").parse(dueDateChilds.item(dueDateChildIndex).getTextContent()); + + } + } + } + } + } + } + } + + zpp = new Invoice().setDueDate(dueDate).setDeliveryDate(deliveryDate).setIssueDate(issueDate).setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number); +//.addItem(new Item(new Product("Testprodukt","","C62",new BigDecimal(0)),amount,new BigDecimal(1.0))) + zpp.setOwnOrganisationName(extractString("//SellerTradeParty/Name")); + xpr = xpath.compile( + "//*[local-name()=\"IncludedSupplyChainTradeLineItem\"]"); + NodeList nodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + + if (nodes.getLength() == 0) { + } else { + for (int i = 0; i < nodes.getLength(); i++) { + + String price = "0"; + String name = ""; + String description = ""; + String quantity = "0"; + String vatPercent = "0"; + String unitCode = "0"; + + //nodes.item(i).getTextContent())) { + Node currentItemNode = nodes.item(i); + NodeList itemChilds = currentItemNode.getChildNodes(); + for (int itemChildIndex = 0; itemChildIndex < itemChilds.getLength(); itemChildIndex++) { + if (itemChilds.item(itemChildIndex).getNodeName().equals("ram:SpecifiedLineTradeAgreement")) { + NodeList tradeLineChilds = itemChilds.item(itemChildIndex).getChildNodes(); + for (int tradeLineChildIndex = 0; tradeLineChildIndex < tradeLineChilds.getLength(); tradeLineChildIndex++) { + if (tradeLineChilds.item(tradeLineChildIndex).getNodeName().equals("ram:NetPriceProductTradePrice")) { + NodeList netChilds = tradeLineChilds.item(tradeLineChildIndex).getChildNodes(); + for (int netIndex = 0; netIndex < netChilds.getLength(); netIndex++) { + if (netChilds.item(netIndex).getNodeName().equals("ram:ChargeAmount")) { + price = netChilds.item(netIndex).getTextContent();//ram:ChargeAmount + + } + } + } + } + } + if (itemChilds.item(itemChildIndex).getNodeName().equals("ram:SpecifiedLineTradeDelivery")) { + NodeList tradeLineChilds = itemChilds.item(itemChildIndex).getChildNodes(); + for (int tradeLineChildIndex = 0; tradeLineChildIndex < tradeLineChilds.getLength(); tradeLineChildIndex++) { + if (tradeLineChilds.item(tradeLineChildIndex).getNodeName().equals("ram:BilledQuantity")) { + quantity = tradeLineChilds.item(tradeLineChildIndex).getTextContent(); + unitCode = tradeLineChilds.item(tradeLineChildIndex).getAttributes().getNamedItem("unitCode").getNodeValue(); + } + } + } + if (itemChilds.item(itemChildIndex).getNodeName().equals("ram:SpecifiedTradeProduct")) { + NodeList tradeProductChilds = itemChilds.item(itemChildIndex).getChildNodes(); + for (int tradeProductChildIndex = 0; tradeProductChildIndex < tradeProductChilds.getLength(); tradeProductChildIndex++) { + if (tradeProductChilds.item(tradeProductChildIndex).getNodeName().equals("ram:Name")) { + name = tradeProductChilds.item(tradeProductChildIndex).getTextContent(); + } + } + } + if (itemChilds.item(itemChildIndex).getNodeName().equals("ram:SpecifiedLineTradeSettlement")) { + NodeList tradeSettlementChilds = itemChilds.item(itemChildIndex).getChildNodes(); + for (int tradeSettlementChildIndex = 0; tradeSettlementChildIndex < tradeSettlementChilds.getLength(); tradeSettlementChildIndex++) { + if (tradeSettlementChilds.item(tradeSettlementChildIndex).getNodeName().equals("ram:ApplicableTradeTax")) { + NodeList taxChilds = tradeSettlementChilds.item(tradeSettlementChildIndex).getChildNodes(); + for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) { + if (taxChilds.item(taxChildIndex).getNodeName().equals("ram:RateApplicablePercent")) { + vatPercent = taxChilds.item(taxChildIndex).getTextContent(); + } + } + } + } + } + + + } + zpp.addItem(new Item(new Product(name, description, unitCode, new BigDecimal(vatPercent)), new BigDecimal(price), new BigDecimal(quantity))); + } + + } + + return zpp; } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java index 3ebad073..01adc049 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java @@ -27,6 +27,9 @@ import junit.framework.TestCase; import junit.framework.Test; import junit.framework.TestSuite; +import javax.xml.xpath.XPathExpressionException; +import java.math.BigDecimal; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; @@ -44,7 +47,14 @@ public class ZF2ZInvoiceImporterTest extends TestCase { ZUGFeRDInvoiceImporter zii=new ZUGFeRDInvoiceImporter(TARGET_PDF); - Invoice invoice=zii.extractInvoice(); + boolean hasExceptions=false; + Invoice invoice=null; + try { + invoice=zii.extractInvoice(); + } catch (XPathExpressionException | ParseException e) { + hasExceptions=true; + } + assertFalse(hasExceptions); // Reading ZUGFeRD assertEquals("Bei Spiel GmbH", invoice.getOwnOrganisationName()); assertEquals(3, invoice.getZFItems().length); @@ -71,6 +81,10 @@ public class ZF2ZInvoiceImporterTest extends TestCase { assertEquals("DE", invoice.getSender().getCountry()); assertEquals("Stadthausen", invoice.getSender().getLocation()); + TransactionCalculator tc=new TransactionCalculator(invoice); + assertEquals(new BigDecimal("571.040000"),tc.getTotalGross()); + + // name street location zip country, contact name phone email, total amount From 9efb2204d549fea8709b46f73dd4081117240e58 Mon Sep 17 00:00:00 2001 From: jstaerk Date: Tue, 3 Nov 2020 08:36:41 +0100 Subject: [PATCH 6/6] minor corrections --- Release_Notes.md | 67 ++++++++++++++++- .../mustangproject/ZUGFeRD/ZF2PushTest.java | 73 +++++++++++++++---- 2 files changed, 123 insertions(+), 17 deletions(-) diff --git a/Release_Notes.md b/Release_Notes.md index b7e8ed83..d617726b 100644 --- a/Release_Notes.md +++ b/Release_Notes.md @@ -84,7 +84,10 @@ changes to ``` IZUGFeRDExporter ze = new ZUGFeRDExporterFromA1().setZUGFeRDVersion(1).setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.EN16931).load(SOURCE_PDF)) { -``` +``` + +The old Contact class has been corrected to TradeParty. The TradeParty class +can now refer to a (human) Contact from the new Contact() class. The importer can still be used like @@ -92,7 +95,41 @@ The importer can still be used like ZUGFeRDImporter zi = new ZUGFeRDImporter(inputStream); String amount = zi.getAmount(); ``` -but we are also working on an importer to import into the new invoice class. +but there is also the new invoiceImporter +``` + + ZUGFeRDInvoiceImporter zii=new ZUGFeRDInvoiceImporter(TARGET_PDF); + + Invoice invoice=null; + try { + invoice=zii.extractInvoice(); + } catch (XPathExpressionException | ParseException e) { +// handle Exceptions + } + assertFalse(hasExceptions); + // Reading ZUGFeRD + assertEquals("Bei Spiel GmbH", invoice.getOwnOrganisationName()); + assertEquals(3, invoice.getZFItems().length); + assertEquals("400.0000", invoice.getZFItems()[1].getQuantity().toString()); + + assertEquals("160.0000", invoice.getZFItems()[0].getPrice().toString()); + assertEquals("Heiße Luft pro Liter", invoice.getZFItems()[2].getProduct().getName()); + assertEquals("LTR", invoice.getZFItems()[2].getProduct().getUnit()); + assertEquals("7.00", invoice.getZFItems()[0].getProduct().getVATPercent().toString()); + assertEquals("RE-20170509/505", invoice.getNumber()); + + SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); + assertEquals("2017-05-09",sdf.format(invoice.getIssueDate())); + + assertEquals("Bahnstr. 42", invoice.getRecipient().getStreet()); + assertEquals("88802", invoice.getRecipient().getZIP()); + assertEquals("DE", invoice.getRecipient().getCountry()); + assertEquals("Spielkreis", invoice.getRecipient().getLocation()); + + TransactionCalculator tc=new TransactionCalculator(invoice); + assertEquals(new BigDecimal("571.040000"),tc.getTotalGross()); + +``` ### Using the library to create e-invoices From maven central fetch @@ -143,7 +180,33 @@ zf2p.generateXML(i); String theXML = new String(zf2p.getXML()); ``` or can also be used with setTransaction to generate invoice PDFs straight away. +### Embedding ZF1 to ZF2 migration +The functionality is based on the XSLT file in library/src/main/resources/stylesheets/ZF1ToZF2.xsl, +it can be accessed via +``` + XMLUpgrader zmi = new XMLUpgrader(); + String xml = zmi.migrateFromV1ToV2(xmlName); + Files.write(Paths.get(outName), xml.getBytes()); + +``` +### Embedding ZF2 visualization + +In case you don't want to access this functionality over the +commandline you can use +``` + ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer(); + xml = zvi.visualize(sourceName); + Files.write(Paths.get("factur-x.xml"), xml.getBytes()); +``` +for the visualizer. The output requires a CSS and a javascript file which are in the + jar's resources as + (/src/main/resources/)xrechnung-viewer.css + (/src/main/respurces/)xrechnung-viewer.js + + ### Embedding the validator +The validator library also contains the functionality to +read/write ZUGFeRD-invoices like the (smaller) library module. ``` diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java index 6c70f5cb..7b9e0f22 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java @@ -38,6 +38,7 @@ import junit.framework.TestCase; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ZF2PushTest extends TestCase { final String TARGET_PDF = "./target/testout-ZF2Push.pdf"; + final String TARGET_ALLOWANCESPDF = "./target/testout-ZF2PushAllowances.pdf"; final String TARGET_CORRECTIONPDF = "./target/testout-ZF2PushCorrection.pdf"; final String TARGET_ITEMCHARGESALLOWANCESPDF = "./target/testout-ZF2PushItemChargesAllowances.pdf"; final String TARGET_CHARGESALLOWANCESPDF = "./target/testout-ZF2PushChargesAllowances.pdf"; @@ -50,8 +51,8 @@ public class ZF2PushTest extends TestCase { String orgname = "Test company"; String number = "RE-20170509/505"; - String amountStr = "1.00"; - BigDecimal amount = new BigDecimal(amountStr); + String priceStr = "1.00"; + BigDecimal price = new BigDecimal(priceStr); String occurenceFrom = "20201001"; String occurenceTo = "20201005"; String contractID = "376zreurzu0983"; @@ -63,7 +64,7 @@ public class ZF2PushTest extends TestCase { .load(SOURCE_PDF)) { try { - ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setContractReferencedDocument(contractID).setOccurrencePeriod(new SimpleDateFormat("yyyyMMdd").parse(occurenceFrom), new SimpleDateFormat("yyyyMMdd").parse(occurenceTo)).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addBankDetails(new BankDetails("777666555", "DE4321"))).setOwnTaxID("4711").setOwnVATID("DE19990815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").setAdditionalAddress("Hinterhaus 3").setContact(new Contact("nameRep", "phoneRep", "emailRep@test.com"))).setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)))); + ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setContractReferencedDocument(contractID).setOccurrencePeriod(new SimpleDateFormat("yyyyMMdd").parse(occurenceFrom), new SimpleDateFormat("yyyyMMdd").parse(occurenceTo)).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addBankDetails(new BankDetails("777666555", "DE4321"))).setOwnTaxID("4711").setOwnVATID("DE19990815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").setAdditionalAddress("Hinterhaus 3").setContact(new Contact("nameRep", "phoneRep", "emailRep@test.com"))).setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))); } catch (ParseException ex) { throw new RuntimeException("Parse exception"); } @@ -102,9 +103,9 @@ public class ZF2PushTest extends TestCase { String orgname = "Test company"; String number = "123"; - String amountStr = "1.00"; + String priceStr = "1.00"; String taxID = "9990815"; - BigDecimal amount = new BigDecimal(amountStr); + BigDecimal price = new BigDecimal(priceStr); try (InputStream SOURCE_PDF = this.getClass() .getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); @@ -115,7 +116,7 @@ public class ZF2PushTest extends TestCase { byte[] b = {12, 13}; ze.attachFile("one.pdf", b, "Application/PDF", "Alternative"); ze.attachFile("two.pdf", b, "Application/PDF", "Alternative"); - ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID(taxID)).setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE4711").setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE"))).setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0))) + ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID(taxID)).setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE4711").setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE"))).setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0))) ); String theXML = new String(ze.getProvider().getXML()); @@ -238,14 +239,56 @@ public class ZF2PushTest extends TestCase { } + } + + public void testAllowancesExport() { + + String orgname = "Test company"; + String number = "123"; + BigDecimal qty = new BigDecimal("20"); + try (InputStream SOURCE_PDF = this.getClass() + .getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); + + ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application") + .setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("en16931")).ignorePDFAErrors() + .load(SOURCE_PDF)) { + + ze.setTransaction(new Invoice().setDueDate(new Date()).setOccurrenceDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE")).setOwnTaxID("4711").setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number) + .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(500.0), qty).addAllowance(new Allowance(new BigDecimal(300)).setTaxPercent(new BigDecimal(19)))) + .addAllowance(new Allowance(new BigDecimal(600)).setTaxPercent(new BigDecimal(19))) + + ); + String theXML = new String(ze.getProvider().getXML()); + assertTrue(theXML.contains("