From 9af73473b7a116de6a1ec451333a840141cd703f Mon Sep 17 00:00:00 2001 From: Sebastian Sieber Date: Tue, 24 Nov 2020 09:46:12 +0100 Subject: [PATCH 01/11] Import UnitCode of basisQuantity to product. I don't know which node is the better one to read the unitCode: grossPriceProductTradePrice or netPriceProductTradePrice. I have chosen the last one. --- .../ZUGFeRD/ZUGFeRDImporter.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index 783f9000..ba496bfe 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -788,8 +788,7 @@ public class ZUGFeRDImporter { List nodeList = getLineItemNodes(); List lineItemList = new ArrayList<>(); - for (Node n: nodeList - ) { + for (Node n: nodeList) { Item lineItem = new Item(null, null, null); lineItem.setProduct(new Product(null,null,null,null)); @@ -803,13 +802,21 @@ public class ZUGFeRDImporter { node = getNodeByName(nn.getChildNodes(), "ram:NetPriceProductTradePrice"); if (node != null) { - node = getNodeByName(node.getChildNodes(), "ram:ChargeAmount"); - lineItem.setPrice(tryBigDecimal(getNodeValue(node))); + NodeList tradeAgreementChildren = node.getChildNodes(); + node = getNodeByName(tradeAgreementChildren, "ram:ChargeAmount"); + lineItem.setPrice(tryBigDecimal(getNodeValue(node))); + node = getNodeByName(tradeAgreementChildren, "ram:BasisQuantity"); + if(node.getAttributes()!=null) { + Node unitCodeAttribute = node.getAttributes().getNamedItem("unitCode"); + if(unitCodeAttribute != null) { + lineItem.getProduct().setUnit(unitCodeAttribute.getNodeValue()); + } + } } - + node = getNodeByName(nn.getChildNodes(), "ram:GrossPriceProductTradePrice"); if (node != null) { - node = getNodeByName(node.getChildNodes(), "ram:ChargeAmount"); + node = getNodeByName(node.getChildNodes(), "ram:ChargeAmount"); lineItem.setGrossPrice(tryBigDecimal(getNodeValue(node))); } break; From 95998b820aeb1e04824eebc423b3d558ecc06d91 Mon Sep 17 00:00:00 2001 From: Sebastian Sieber Date: Tue, 24 Nov 2020 14:54:21 +0100 Subject: [PATCH 02/11] Create XRechnungImporter to import data from raw xml The XRechnungImporter extends from ZUGFeRDImporter. It simply sets the given raw xml and provides otherwise the same functionality as the parent class. --- .../ZUGFeRD/XRechnungImporter.java | 21 +++++++++++++++++++ .../ZUGFeRD/ZUGFeRDImporter.java | 6 +++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 library/src/main/java/org/mustangproject/ZUGFeRD/XRechnungImporter.java diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/XRechnungImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/XRechnungImporter.java new file mode 100644 index 00000000..0855b919 --- /dev/null +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/XRechnungImporter.java @@ -0,0 +1,21 @@ +package org.mustangproject.ZUGFeRD; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class XRechnungImporter extends ZUGFeRDImporter { + + public XRechnungImporter(byte[] rawXml) { + super(); + + try { + setRawXML(rawXml); + containsMeta = true; + } catch (final IOException e) { + Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); + throw new ZUGFeRDExportException(e); + } + } + +} diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index ba496bfe..abcaace2 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -48,7 +48,7 @@ public class ZUGFeRDImporter { /** * if metadata has been found */ - private boolean containsMeta = false; + protected boolean containsMeta = false; /** * map filenames of additional XML files to their contents */ @@ -67,6 +67,10 @@ public class ZUGFeRDImporter { private Document document; + protected ZUGFeRDImporter() { + //constructor for extending classes + } + public ZUGFeRDImporter(String pdfFilename) { try (InputStream bis = Files.newInputStream(Paths.get(pdfFilename), StandardOpenOption.READ)) { extractLowLevel(bis); From 90b1d7c7aa64b23d8ad8a1ad9fc068433641dfad Mon Sep 17 00:00:00 2001 From: Sebastian Sieber Date: Wed, 25 Nov 2020 12:34:15 +0100 Subject: [PATCH 03/11] Unify the values of taxes Concerning ApplicableHeaderTradeSettlement: The amount in ApplicableTradeTax.CalculatedAmount is different from SpecifiedTradeSettlementHeaderMonetarySummation.TaxTotalAmount. To avoid this I removed the rounding from totalAmount. --- .../org/mustangproject/ZUGFeRD/TransactionCalculator.java | 2 +- .../org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java | 3 ++- .../mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java | 7 ++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java index bdb6f6e8..187adc97 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java @@ -31,7 +31,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider { VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); res = res.add(amount.getCalculated()); } - return res.setScale(2, RoundingMode.HALF_UP); + return res; } /*** diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java index 9e4b624a..9334ffe1 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java @@ -6,6 +6,7 @@ import org.w3c.dom.NodeList; import javax.xml.xpath.*; import java.math.BigDecimal; +import java.math.RoundingMode; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @@ -259,7 +260,7 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { } TransactionCalculator tc = new TransactionCalculator(zpp); - String expectedStringTotalGross = tc.getTotalGross().toPlainString(); + String expectedStringTotalGross = tc.getTotalGross().setScale(2, RoundingMode.HALF_UP).toPlainString(); if (!expectedStringTotalGross.equals(XMLTools.nDigitFormat(expectedGrandTotal, 2))) { throw new ParseException("Could not reproduce the invoice, this could mean that it could not be read properly", 0); } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java index a56f637b..add87e7e 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java @@ -20,6 +20,7 @@ package org.mustangproject.ZUGFeRD; import org.mustangproject.Invoice; +import org.mustangproject.XMLTools; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; @@ -81,7 +82,7 @@ public class ZF2ZInvoiceImporterTest extends TestCase { assertEquals("Stadthausen", invoice.getSender().getLocation()); TransactionCalculator tc=new TransactionCalculator(invoice); - assertEquals(new BigDecimal("571.04"),tc.getTotalGross()); + assertEquals("571.04", XMLTools.nDigitFormat(tc.getTotalGross(),2)); // name street location zip country, contact name phone email, total amount @@ -102,7 +103,7 @@ public class ZF2ZInvoiceImporterTest extends TestCase { } assertFalse(hasExceptions); TransactionCalculator tc=new TransactionCalculator(invoice); - assertEquals(new BigDecimal("18.33"),tc.getTotalGross()); + assertEquals("18.33", XMLTools.nDigitFormat(tc.getTotalGross(),2)); } public void testAllowancesChargesImport() { @@ -118,7 +119,7 @@ public class ZF2ZInvoiceImporterTest extends TestCase { } assertFalse(hasExceptions); TransactionCalculator tc=new TransactionCalculator(invoice); - assertEquals(new BigDecimal("11.07"),tc.getTotalGross()); + assertEquals("11.07", XMLTools.nDigitFormat(tc.getTotalGross(),2)); // name street location zip country, contact name phone email, total amount From 1e78866040c74e4c273f1ef926626340fce1e887 Mon Sep 17 00:00:00 2001 From: Sebastian Sieber Date: Tue, 24 Nov 2020 09:46:12 +0100 Subject: [PATCH 04/11] Import UnitCode of basisQuantity to product. I don't know which node is the better one to read the unitCode: grossPriceProductTradePrice or netPriceProductTradePrice. I have chosen the last one. --- .../ZUGFeRD/ZUGFeRDImporter.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index 783f9000..ba496bfe 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -788,8 +788,7 @@ public class ZUGFeRDImporter { List nodeList = getLineItemNodes(); List lineItemList = new ArrayList<>(); - for (Node n: nodeList - ) { + for (Node n: nodeList) { Item lineItem = new Item(null, null, null); lineItem.setProduct(new Product(null,null,null,null)); @@ -803,13 +802,21 @@ public class ZUGFeRDImporter { node = getNodeByName(nn.getChildNodes(), "ram:NetPriceProductTradePrice"); if (node != null) { - node = getNodeByName(node.getChildNodes(), "ram:ChargeAmount"); - lineItem.setPrice(tryBigDecimal(getNodeValue(node))); + NodeList tradeAgreementChildren = node.getChildNodes(); + node = getNodeByName(tradeAgreementChildren, "ram:ChargeAmount"); + lineItem.setPrice(tryBigDecimal(getNodeValue(node))); + node = getNodeByName(tradeAgreementChildren, "ram:BasisQuantity"); + if(node.getAttributes()!=null) { + Node unitCodeAttribute = node.getAttributes().getNamedItem("unitCode"); + if(unitCodeAttribute != null) { + lineItem.getProduct().setUnit(unitCodeAttribute.getNodeValue()); + } + } } - + node = getNodeByName(nn.getChildNodes(), "ram:GrossPriceProductTradePrice"); if (node != null) { - node = getNodeByName(node.getChildNodes(), "ram:ChargeAmount"); + node = getNodeByName(node.getChildNodes(), "ram:ChargeAmount"); lineItem.setGrossPrice(tryBigDecimal(getNodeValue(node))); } break; From a1c4f4a2d68268882bf8f01ea4d751cae54f31f2 Mon Sep 17 00:00:00 2001 From: Sebastian Sieber Date: Wed, 25 Nov 2020 12:34:15 +0100 Subject: [PATCH 05/11] Unify the values of taxes Concerning ApplicableHeaderTradeSettlement: The amount in ApplicableTradeTax.CalculatedAmount is different from SpecifiedTradeSettlementHeaderMonetarySummation.TaxTotalAmount. To avoid this I removed the rounding from totalAmount. --- .../org/mustangproject/ZUGFeRD/TransactionCalculator.java | 2 +- .../org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java | 3 ++- .../mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java | 7 ++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java index bdb6f6e8..187adc97 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java @@ -31,7 +31,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider { VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); res = res.add(amount.getCalculated()); } - return res.setScale(2, RoundingMode.HALF_UP); + return res; } /*** diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java index 9e4b624a..9334ffe1 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java @@ -6,6 +6,7 @@ import org.w3c.dom.NodeList; import javax.xml.xpath.*; import java.math.BigDecimal; +import java.math.RoundingMode; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @@ -259,7 +260,7 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { } TransactionCalculator tc = new TransactionCalculator(zpp); - String expectedStringTotalGross = tc.getTotalGross().toPlainString(); + String expectedStringTotalGross = tc.getTotalGross().setScale(2, RoundingMode.HALF_UP).toPlainString(); if (!expectedStringTotalGross.equals(XMLTools.nDigitFormat(expectedGrandTotal, 2))) { throw new ParseException("Could not reproduce the invoice, this could mean that it could not be read properly", 0); } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java index a56f637b..add87e7e 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java @@ -20,6 +20,7 @@ package org.mustangproject.ZUGFeRD; import org.mustangproject.Invoice; +import org.mustangproject.XMLTools; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; @@ -81,7 +82,7 @@ public class ZF2ZInvoiceImporterTest extends TestCase { assertEquals("Stadthausen", invoice.getSender().getLocation()); TransactionCalculator tc=new TransactionCalculator(invoice); - assertEquals(new BigDecimal("571.04"),tc.getTotalGross()); + assertEquals("571.04", XMLTools.nDigitFormat(tc.getTotalGross(),2)); // name street location zip country, contact name phone email, total amount @@ -102,7 +103,7 @@ public class ZF2ZInvoiceImporterTest extends TestCase { } assertFalse(hasExceptions); TransactionCalculator tc=new TransactionCalculator(invoice); - assertEquals(new BigDecimal("18.33"),tc.getTotalGross()); + assertEquals("18.33", XMLTools.nDigitFormat(tc.getTotalGross(),2)); } public void testAllowancesChargesImport() { @@ -118,7 +119,7 @@ public class ZF2ZInvoiceImporterTest extends TestCase { } assertFalse(hasExceptions); TransactionCalculator tc=new TransactionCalculator(invoice); - assertEquals(new BigDecimal("11.07"),tc.getTotalGross()); + assertEquals("11.07", XMLTools.nDigitFormat(tc.getTotalGross(),2)); // name street location zip country, contact name phone email, total amount From cc561a8f6680c812cb7c356547d0cc21128bcda3 Mon Sep 17 00:00:00 2001 From: Sebastian Sieber Date: Wed, 25 Nov 2020 12:57:21 +0100 Subject: [PATCH 06/11] Revert all changes This reverts commit 90b1d7c7aa64b23d8ad8a1ad9fc068433641dfad, 95998b820aeb1e04824eebc423b3d558ecc06d91 and 9af73473b7a116de6a1ec451333a840141cd703f --- .../ZUGFeRD/TransactionCalculator.java | 2 +- .../ZUGFeRD/XRechnungImporter.java | 21 ---------------- .../ZUGFeRD/ZUGFeRDImporter.java | 25 ++++++------------- .../ZUGFeRD/ZUGFeRDInvoiceImporter.java | 3 +-- .../ZUGFeRD/ZF2ZInvoiceImporterTest.java | 7 +++--- 5 files changed, 12 insertions(+), 46 deletions(-) delete mode 100644 library/src/main/java/org/mustangproject/ZUGFeRD/XRechnungImporter.java diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java index 187adc97..bdb6f6e8 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java @@ -31,7 +31,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider { VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); res = res.add(amount.getCalculated()); } - return res; + return res.setScale(2, RoundingMode.HALF_UP); } /*** diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/XRechnungImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/XRechnungImporter.java deleted file mode 100644 index 0855b919..00000000 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/XRechnungImporter.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.mustangproject.ZUGFeRD; - -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class XRechnungImporter extends ZUGFeRDImporter { - - public XRechnungImporter(byte[] rawXml) { - super(); - - try { - setRawXML(rawXml); - containsMeta = true; - } catch (final IOException e) { - Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); - throw new ZUGFeRDExportException(e); - } - } - -} diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index abcaace2..783f9000 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -48,7 +48,7 @@ public class ZUGFeRDImporter { /** * if metadata has been found */ - protected boolean containsMeta = false; + private boolean containsMeta = false; /** * map filenames of additional XML files to their contents */ @@ -67,10 +67,6 @@ public class ZUGFeRDImporter { private Document document; - protected ZUGFeRDImporter() { - //constructor for extending classes - } - public ZUGFeRDImporter(String pdfFilename) { try (InputStream bis = Files.newInputStream(Paths.get(pdfFilename), StandardOpenOption.READ)) { extractLowLevel(bis); @@ -792,7 +788,8 @@ public class ZUGFeRDImporter { List nodeList = getLineItemNodes(); List lineItemList = new ArrayList<>(); - for (Node n: nodeList) { + for (Node n: nodeList + ) { Item lineItem = new Item(null, null, null); lineItem.setProduct(new Product(null,null,null,null)); @@ -806,21 +803,13 @@ public class ZUGFeRDImporter { node = getNodeByName(nn.getChildNodes(), "ram:NetPriceProductTradePrice"); if (node != null) { - NodeList tradeAgreementChildren = node.getChildNodes(); - node = getNodeByName(tradeAgreementChildren, "ram:ChargeAmount"); - lineItem.setPrice(tryBigDecimal(getNodeValue(node))); - node = getNodeByName(tradeAgreementChildren, "ram:BasisQuantity"); - if(node.getAttributes()!=null) { - Node unitCodeAttribute = node.getAttributes().getNamedItem("unitCode"); - if(unitCodeAttribute != null) { - lineItem.getProduct().setUnit(unitCodeAttribute.getNodeValue()); - } - } + node = getNodeByName(node.getChildNodes(), "ram:ChargeAmount"); + lineItem.setPrice(tryBigDecimal(getNodeValue(node))); } - + node = getNodeByName(nn.getChildNodes(), "ram:GrossPriceProductTradePrice"); if (node != null) { - node = getNodeByName(node.getChildNodes(), "ram:ChargeAmount"); + node = getNodeByName(node.getChildNodes(), "ram:ChargeAmount"); lineItem.setGrossPrice(tryBigDecimal(getNodeValue(node))); } break; diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java index 9334ffe1..9e4b624a 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java @@ -6,7 +6,6 @@ import org.w3c.dom.NodeList; import javax.xml.xpath.*; import java.math.BigDecimal; -import java.math.RoundingMode; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @@ -260,7 +259,7 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { } TransactionCalculator tc = new TransactionCalculator(zpp); - String expectedStringTotalGross = tc.getTotalGross().setScale(2, RoundingMode.HALF_UP).toPlainString(); + String expectedStringTotalGross = tc.getTotalGross().toPlainString(); if (!expectedStringTotalGross.equals(XMLTools.nDigitFormat(expectedGrandTotal, 2))) { throw new ParseException("Could not reproduce the invoice, this could mean that it could not be read properly", 0); } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java index add87e7e..a56f637b 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java @@ -20,7 +20,6 @@ package org.mustangproject.ZUGFeRD; import org.mustangproject.Invoice; -import org.mustangproject.XMLTools; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; @@ -82,7 +81,7 @@ public class ZF2ZInvoiceImporterTest extends TestCase { assertEquals("Stadthausen", invoice.getSender().getLocation()); TransactionCalculator tc=new TransactionCalculator(invoice); - assertEquals("571.04", XMLTools.nDigitFormat(tc.getTotalGross(),2)); + assertEquals(new BigDecimal("571.04"),tc.getTotalGross()); // name street location zip country, contact name phone email, total amount @@ -103,7 +102,7 @@ public class ZF2ZInvoiceImporterTest extends TestCase { } assertFalse(hasExceptions); TransactionCalculator tc=new TransactionCalculator(invoice); - assertEquals("18.33", XMLTools.nDigitFormat(tc.getTotalGross(),2)); + assertEquals(new BigDecimal("18.33"),tc.getTotalGross()); } public void testAllowancesChargesImport() { @@ -119,7 +118,7 @@ public class ZF2ZInvoiceImporterTest extends TestCase { } assertFalse(hasExceptions); TransactionCalculator tc=new TransactionCalculator(invoice); - assertEquals("11.07", XMLTools.nDigitFormat(tc.getTotalGross(),2)); + assertEquals(new BigDecimal("11.07"),tc.getTotalGross()); // name street location zip country, contact name phone email, total amount From 751d129def174ba804f289b62a82f5f2b76c8a63 Mon Sep 17 00:00:00 2001 From: Sebastian Sieber Date: Fri, 27 Nov 2020 12:51:10 +0100 Subject: [PATCH 07/11] Add != null expression to prevent NPE --- .../org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index abcaace2..c66ae41b 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -810,12 +810,12 @@ public class ZUGFeRDImporter { node = getNodeByName(tradeAgreementChildren, "ram:ChargeAmount"); lineItem.setPrice(tryBigDecimal(getNodeValue(node))); node = getNodeByName(tradeAgreementChildren, "ram:BasisQuantity"); - if(node.getAttributes()!=null) { - Node unitCodeAttribute = node.getAttributes().getNamedItem("unitCode"); - if(unitCodeAttribute != null) { - lineItem.getProduct().setUnit(unitCodeAttribute.getNodeValue()); - } - } + if(node != null && node.getAttributes()!=null) { + Node unitCodeAttribute = node.getAttributes().getNamedItem("unitCode"); + if(unitCodeAttribute != null) { + lineItem.getProduct().setUnit(unitCodeAttribute.getNodeValue()); + } + } } node = getNodeByName(nn.getChildNodes(), "ram:GrossPriceProductTradePrice"); From 687d8f628c8d494827d6873592be0b061627a70f Mon Sep 17 00:00:00 2001 From: Sebastian Sieber Date: Tue, 1 Dec 2020 15:58:18 +0100 Subject: [PATCH 08/11] Use constants instead of magic numbers --- .../ZUGFeRD/IZUGFeRDExportableProduct.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java index efab767d..92d32e91 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java @@ -22,6 +22,8 @@ package org.mustangproject.ZUGFeRD; import java.math.BigDecimal; +import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants; + /** * Mustangproject's ZUGFeRD implementation * Necessary interface for ZUGFeRD exporter @@ -114,13 +116,15 @@ public interface IZUGFeRDExportableProduct { default String getTaxCategoryCode() { if (isIntraCommunitySupply()) { - return "K"; // within europe + return TaxCategoryCodeTypeConstants.INTRACOMMUNITY;// "K"; // within europe } else if (isReverseCharge()) { - return "AE"; // to out of europe... + return TaxCategoryCodeTypeConstants.REVERSECHARGE;// "AE"; // to out of europe... } else if (getVATPercent().equals(BigDecimal.ZERO)) { - return "Z"; // zero rated goods + return TaxCategoryCodeTypeConstants.ZEROTAXPRODUCTS; // "Z"; // zero rated goods } else { - return "S"; // one of the "standard" rates (not neccessarily a default rate, even a deducted VAT is standard calculation) + return TaxCategoryCodeTypeConstants.STANDARDRATE;// "S"; // one of the "standard" rates (not + // neccessarily a default rate, even a deducted VAT + // is standard calculation) } } From 5e71863f8b54d9749d1d7403ecb59da555674a78 Mon Sep 17 00:00:00 2001 From: Sebastian Sieber Date: Wed, 2 Dec 2020 11:28:09 +0100 Subject: [PATCH 09/11] Improve handling of categoryCode Charge returns the local field if is set. IZUGFeRDExportableProduct: Use compareTo instead of equals to check the mathematical equality. --- library/src/main/java/org/mustangproject/Charge.java | 7 +++++++ .../mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/library/src/main/java/org/mustangproject/Charge.java b/library/src/main/java/org/mustangproject/Charge.java index 2e9a2e42..5ddf3009 100644 --- a/library/src/main/java/org/mustangproject/Charge.java +++ b/library/src/main/java/org/mustangproject/Charge.java @@ -82,6 +82,13 @@ public class Charge implements IZUGFeRDAllowanceCharge { return true; } + @Override + public String getCategoryCode() { + if(categoryCode != null){ + return categoryCode; + } + return IZUGFeRDAllowanceCharge.super.getCategoryCode(); + } public Charge setCategoryCode(String categoryCode) { diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java index 92d32e91..c0d15e04 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java @@ -119,7 +119,7 @@ public interface IZUGFeRDExportableProduct { return TaxCategoryCodeTypeConstants.INTRACOMMUNITY;// "K"; // within europe } else if (isReverseCharge()) { return TaxCategoryCodeTypeConstants.REVERSECHARGE;// "AE"; // to out of europe... - } else if (getVATPercent().equals(BigDecimal.ZERO)) { + } else if (getVATPercent().compareTo(BigDecimal.ZERO) == 0) { return TaxCategoryCodeTypeConstants.ZEROTAXPRODUCTS; // "Z"; // zero rated goods } else { return TaxCategoryCodeTypeConstants.STANDARDRATE;// "S"; // one of the "standard" rates (not From 54dccc188ae57e107a29e6a8d2421f9f1a0dca0f Mon Sep 17 00:00:00 2001 From: Sebastian Sieber Date: Wed, 2 Dec 2020 14:32:18 +0100 Subject: [PATCH 10/11] Fix id of profile XRECHNUNG --- .../src/main/java/org/mustangproject/ZUGFeRD/Profiles.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java b/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java index 7221a333..2496e801 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java @@ -20,8 +20,6 @@ */ package org.mustangproject.ZUGFeRD; -import java.util.ArrayList; -import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -33,7 +31,7 @@ public class Profiles { {"BASIC", new Profile("BASIC", "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic")}, {"EN16931", new Profile("EN16931", "urn:cen.eu:en16931:2017")}, {"EXTENDED", new Profile("EXTENDED", "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended")}, - {"XRECHNUNG", new Profile("XRECHNUNG", "urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_1.2")} + {"XRECHNUNG", new Profile("XRECHNUNG", "urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0")} }).collect(Collectors.toMap(data -> (String) data[0], data -> (Profile) data[1])); static Map zf1Map = Stream.of(new Object[][]{ From 812a22e901fa06636df569578c81753dbc1f76f9 Mon Sep 17 00:00:00 2001 From: Sebastian Sieber Date: Thu, 3 Dec 2020 11:45:33 +0100 Subject: [PATCH 11/11] Add property and method TradeParty to add debit details --- .../java/org/mustangproject/TradeParty.java | 39 +++++++++++++++---- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/library/src/main/java/org/mustangproject/TradeParty.java b/library/src/main/java/org/mustangproject/TradeParty.java index df1b4a02..5729fb53 100644 --- a/library/src/main/java/org/mustangproject/TradeParty.java +++ b/library/src/main/java/org/mustangproject/TradeParty.java @@ -1,11 +1,17 @@ package org.mustangproject; -import org.mustangproject.ZUGFeRD.*; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.mustangproject.ZUGFeRD.IZUGFeRDExportableContact; +import org.mustangproject.ZUGFeRD.IZUGFeRDExportableTradeParty; +import org.mustangproject.ZUGFeRD.IZUGFeRDTradeSettlement; +import org.mustangproject.ZUGFeRD.IZUGFeRDTradeSettlementDebit; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import java.util.ArrayList; - /*** * A organisation, i.e. usually a company */ @@ -15,7 +21,8 @@ public class TradeParty implements IZUGFeRDExportableTradeParty { protected String taxID = null, vatID = null; protected String ID = null; protected String additionalAddress = null; - protected ArrayList bankDetails = new ArrayList(); + protected List bankDetails = new ArrayList<>(); + protected List debitDetails = new ArrayList<>(); protected Contact contact = null; /*** @@ -137,8 +144,17 @@ public class TradeParty implements IZUGFeRDExportableTradeParty { bankDetails.add(s); return this; } + /** + * (optional) + * @param debitDetail + * @return fluent setter + */ + public TradeParty addDebitDetails(IZUGFeRDTradeSettlementDebit debitDetail) { + debitDetails.add(debitDetail); + return this; + } - public ArrayList getBankDetails() { + public List getBankDetails() { return bankDetails; } @@ -262,10 +278,19 @@ public class TradeParty implements IZUGFeRDExportableTradeParty { } public IZUGFeRDTradeSettlement[] getAsTradeSettlement() { - if (bankDetails.size() == 0) { + if (bankDetails.isEmpty() && debitDetails.isEmpty()) { return null; } - return bankDetails.toArray(new IZUGFeRDTradeSettlement[0]); + List tradeSettlements = Stream.concat(bankDetails.stream(), debitDetails.stream()) + .map(IZUGFeRDTradeSettlement.class::cast) + .collect(Collectors.toList()); + + IZUGFeRDTradeSettlement[] result = new IZUGFeRDTradeSettlement[tradeSettlements.size()]; + for (int i = 0; i < tradeSettlements.size(); i++) { + IZUGFeRDTradeSettlement izugFeRDTradeSettlement = tradeSettlements.get(i); + result[i]=izugFeRDTradeSettlement; + } + return result; } @Override