From 1541fc48dae4e8212c0bdec51157aa475889b1fe Mon Sep 17 00:00:00 2001 From: Jochen Staerk Date: Thu, 28 May 2015 11:43:14 +0200 Subject: [PATCH] ZUGFeRD USt 14 compliance --- .../IZUGFeRDExportableTransaction.java | 10 --- .../org/mustangproject/ZUGFeRD/VATAmount.java | 35 +++++++++ .../ZUGFeRD/ZUGFeRDExporter.java | 71 +++++++++++++++---- 3 files changed, 91 insertions(+), 25 deletions(-) create mode 100644 mustang/src/main/java/org/mustangproject/ZUGFeRD/VATAmount.java diff --git a/mustang/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java b/mustang/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java index da74ee77..fb4d5963 100644 --- a/mustang/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java +++ b/mustang/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java @@ -12,7 +12,6 @@ package org.mustangproject.ZUGFeRD; import java.math.BigDecimal; import java.util.Date; -import java.util.HashMap; public interface IZUGFeRDExportableTransaction { @@ -122,13 +121,4 @@ public interface IZUGFeRDExportableTransaction { - /** - * 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 - * - HashMap getVATPercentAmountMap(); - */ } diff --git a/mustang/src/main/java/org/mustangproject/ZUGFeRD/VATAmount.java b/mustang/src/main/java/org/mustangproject/ZUGFeRD/VATAmount.java new file mode 100644 index 00000000..f1982b40 --- /dev/null +++ b/mustang/src/main/java/org/mustangproject/ZUGFeRD/VATAmount.java @@ -0,0 +1,35 @@ +package org.mustangproject.ZUGFeRD; + +import java.math.BigDecimal; + +public class VATAmount { + + public VATAmount(BigDecimal basis, BigDecimal calculated) { + super(); + this.basis = basis; + this.calculated = calculated; + } + + BigDecimal basis, calculated; + + public BigDecimal getBasis() { + return basis; + } + + public void setBasis(BigDecimal basis) { + this.basis = basis; + } + + public BigDecimal getCalculated() { + return calculated; + } + + public void setCalculated(BigDecimal calculated) { + this.calculated = calculated; + } + + public VATAmount add(VATAmount v) { + return new VATAmount(basis.add(v.getBasis()), calculated.add(v.getCalculated())); + } + +} diff --git a/mustang/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java b/mustang/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java index 9729ce89..8d11859d 100644 --- a/mustang/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java +++ b/mustang/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java @@ -16,7 +16,6 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; import java.util.Arrays; -import java.util.Collections; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Map; @@ -43,6 +42,7 @@ import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecifica import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile; + public class ZUGFeRDExporter { /*** * You will need Apache PDFBox. To use the ZUGFeRD exporter, @@ -81,6 +81,7 @@ public class ZUGFeRDExporter { * pass a IZUGFeRDExportableTransaction for the XML to be populated. */ byte[] zugferdData = null; + private boolean isTest; private String nDigitFormat(BigDecimal value, int scale) { @@ -154,6 +155,12 @@ public class ZUGFeRDExporter { conformanceLevel=newLevel; } + /** + * enables the flag to indicate a test invoice in the XML structure + * */ + public void setTest() { + isTest=true; + } /** * Makes A PDF/A3a-compliant document from a PDF-A1 compliant document (on @@ -224,7 +231,13 @@ public class ZUGFeRDExporter { } private String getZugferdXMLForTransaction(IZUGFeRDExportableTransaction trans) { + SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy"); //$NON-NLS-1$ SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); //$NON-NLS-1$ + String testBooleanStr="false"; + if (isTest) { + testBooleanStr="true"; + + } String xml= "\n" //$NON-NLS-1$ + "\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " false\n" //$NON-NLS-1$ + + " "+testBooleanStr+"\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " urn:ferd:CrossIndustryDocument:invoice:1p0:comfort\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ @@ -322,23 +335,23 @@ public class ZUGFeRDExporter { + " \n"; //$NON-NLS-1$ - /* - HashMap VATPercentAmountMap=trans.getVATPercentAmountMap(); + + HashMap VATPercentAmountMap=getVATPercentAmountMap(trans); for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { - BigDecimal amount = VATPercentAmountMap.get(currentTaxPercent); + VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); if (amount != null) { - xml += " \n" //$NON-NLS-1$ - + " "+currencyFormat(amount, '.')+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " VAT\n" //$NON-NLS-1$ -// + " 129.37\n" - + " S\n" //$NON-NLS-1$ - + " "+currentTaxPercent+"\n" //$NON-NLS-1$ - + " \n"; //$NON-NLS-1$ + xml += " \n" //$NON-NLS-1$ + + " "+currencyFormat(amount.getCalculated())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " VAT\n" //$NON-NLS-1$ + + " "+currencyFormat(amount.getCalculated())+"\n" + + " S\n" //$NON-NLS-1$ + + " "+vatFormat(currentTaxPercent)+"\n" //$NON-NLS-1$ + + " \n"; //$NON-NLS-1$ } - }*/ + } /* xml+= " + " \n" + " false\n" @@ -373,13 +386,13 @@ public class ZUGFeRDExporter { + " \n"*/ xml=xml+ " \n" //$NON-NLS-1$ -// + " Zahlbar innerhalb 30 Tagen netto bis 04.07.2013, 3% Skonto innerhalb 10 Tagen bis 15.06.2013\n" + + " Zahlbar ohne Abzug bis "+germanDateFormat.format(trans.getDueDate())+"\n" + " "+zugferdDateFormat.format(trans.getDueDate())+"\n"//20130704 //$NON-NLS-1$ //$NON-NLS-2$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " 0.00\n" //$NON-NLS-1$ + " 0.00\n" //$NON-NLS-1$ - + " "+currencyFormat(trans.getTotal())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ +// + " "+currencyFormat(trans.getTotal())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ // + " 5.80\n" // + " 14.73\n" + " "+currencyFormat(trans.getTotal())+"\n" //$NON-NLS-1$ //$NON-NLS-2$ @@ -454,6 +467,34 @@ public class ZUGFeRDExporter { return xml; } + + /** + * 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 + * + */ + private HashMap getVATPercentAmountMap(IZUGFeRDExportableTransaction trans) { + HashMap hm=new HashMap (); + + for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { + BigDecimal percent=currentItem.getProduct().getVATPercent(); + BigDecimal currentBasis=currentItem.getPriceGross().subtract(currentItem.getPrice()); + VATAmount itemVATAmount=new VATAmount(currentBasis, currentBasis.multiply(percent)) ; + VATAmount current=hm.get(percent); + if (current==null) { + hm.put(percent, itemVATAmount); + } else { + hm.put(percent, current.add(itemVATAmount)); + + } + } + + return hm; + } + /** * Embeds the Zugferd XML structure in a file named ZUGFeRD-invoice.xml. *