Merge branch 'master' of https://github.com/ZUGFeRD/mustangproject into master

This commit is contained in:
Ulrich Zielhofer
2020-11-03 15:42:50 +01:00
9 changed files with 497 additions and 218 deletions

View File

@@ -3,16 +3,17 @@
- support for ZF 2.1.1, i.e. "Reference profile" Xrechnung - 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) - ZF 2.1.1 now default (up to 1.7.8 ZF2 could be set but ZF1 was default)
- integrates validator
- removed jaxb #87 - removed jaxb #87
- fluent setter api/pushprovider #40 - fluent setter api/pushprovider #40
- new xrechnung profile - new xrechnung reference profile
- visualization? zugferdvisualizer? - visualization zugferdvisualizer
- migration feature (XSLT upgrade of ZF1 to ZF2) has been improved and moved from the commandline into the library - 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) - german bank account numbers can no longer be specified (dropped in favor of IBAN and BIC)
- factory for xrechnung #86 - factory for xrechnung #86
- moved to Maven central - moved to Maven central
- complete or discard read into push provider - 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 - validator now additionally supports xrechnung
- modular project setup - modular project setup
- getSellerTradePartyAddress (PR #157 ) thanks to aberndt-hub - getSellerTradePartyAddress (PR #157 ) thanks to aberndt-hub

View File

@@ -84,7 +84,10 @@ changes to
``` ```
IZUGFeRDExporter ze = new ZUGFeRDExporterFromA1().setZUGFeRDVersion(1).setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.EN16931).load(SOURCE_PDF)) { 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 The importer can still be used like
@@ -92,7 +95,41 @@ The importer can still be used like
ZUGFeRDImporter zi = new ZUGFeRDImporter(inputStream); ZUGFeRDImporter zi = new ZUGFeRDImporter(inputStream);
String amount = zi.getAmount(); 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 ### Using the library to create e-invoices
From maven central fetch From maven central fetch
@@ -143,7 +180,33 @@ zf2p.generateXML(i);
String theXML = new String(zf2p.getXML()); String theXML = new String(zf2p.getXML());
``` ```
or can also be used with setTransaction to generate invoice PDFs straight away. 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 ### Embedding the validator
The validator library also contains the functionality to
read/write ZUGFeRD-invoices like the (smaller) library module.
``` ```
<dependencies> <dependencies>
<dependency> <dependency>

View File

@@ -2,7 +2,11 @@ package org.mustangproject.ZUGFeRD;
import java.math.BigDecimal; 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 totalGross;
private BigDecimal price; private BigDecimal price;
private BigDecimal priceGross; private BigDecimal priceGross;
@@ -11,7 +15,7 @@ public class LineCalc {
private BigDecimal allowance = new BigDecimal(0); private BigDecimal allowance = new BigDecimal(0);
private BigDecimal charge = 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) { if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) {
for (IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) { for (IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) {

View File

@@ -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<BigDecimal, VATAmount> 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<BigDecimal, VATAmount> getVATPercentAmountMap() {
HashMap<BigDecimal, VATAmount> 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();
}
}

View File

@@ -104,6 +104,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
@Override @Override
public void generateXML(IExportableTransaction trans) { public void generateXML(IExportableTransaction trans) {
this.trans = trans; this.trans = trans;
this.calc=new TransactionCalculator(trans);
boolean hasDueDate=false; boolean hasDueDate=false;
String taxCategoryCode=""; String taxCategoryCode="";
@@ -288,7 +289,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
} }
} }
HashMap<BigDecimal, VATAmount> VATPercentAmountMap = getVATPercentAmountMap(); HashMap<BigDecimal, VATAmount> VATPercentAmountMap = calc.getVATPercentAmountMap();
for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) {
VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); VATAmount amount = VATPercentAmountMap.get(currentTaxPercent);
if (amount != null) { if (amount != null) {
@@ -329,23 +330,23 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
} }
xml = xml + " <ram:SpecifiedTradeSettlementMonetarySummation>\n" xml = xml + " <ram:SpecifiedTradeSettlementMonetarySummation>\n"
+ " <ram:LineTotalAmount currencyID=\""+trans.getCurrency()+"\">" + currencyFormat(getTotal()) + "</ram:LineTotalAmount>\n" //$NON-NLS-2$ + " <ram:LineTotalAmount currencyID=\""+trans.getCurrency()+"\">" + currencyFormat(calc.getTotal()) + "</ram:LineTotalAmount>\n" //$NON-NLS-2$
// currencyID=\"EUR\" // currencyID=\"EUR\"
+ " <ram:ChargeTotalAmount currencyID=\"" + trans.getCurrency() + "\">0.00</ram:ChargeTotalAmount>\n" // currencyID=\"EUR\" + " <ram:ChargeTotalAmount currencyID=\"" + trans.getCurrency() + "\">0.00</ram:ChargeTotalAmount>\n" // currencyID=\"EUR\"
+ " <ram:AllowanceTotalAmount currencyID=\"" + trans.getCurrency() + "\">0.00</ram:AllowanceTotalAmount>\n" // + " <ram:AllowanceTotalAmount currencyID=\"" + trans.getCurrency() + "\">0.00</ram:AllowanceTotalAmount>\n" //
// currencyID=\"EUR\" // currencyID=\"EUR\"
// + " <ChargeTotalAmount currencyID=\"EUR\">5.80</ChargeTotalAmount>\n" // + " <ChargeTotalAmount currencyID=\"EUR\">5.80</ChargeTotalAmount>\n"
// + " <AllowanceTotalAmount currencyID=\"EUR\">14.73</AllowanceTotalAmount>\n" // + " <AllowanceTotalAmount currencyID=\"EUR\">14.73</AllowanceTotalAmount>\n"
+ " <ram:TaxBasisTotalAmount currencyID=\"" + trans.getCurrency() + "\">" + currencyFormat(getTotal()) + "</ram:TaxBasisTotalAmount>\n" //$NON-NLS-2$ + " <ram:TaxBasisTotalAmount currencyID=\"" + trans.getCurrency() + "\">" + currencyFormat(calc.getTotal()) + "</ram:TaxBasisTotalAmount>\n" //$NON-NLS-2$
// // // //
// currencyID=\"EUR\" // currencyID=\"EUR\"
+ " <ram:TaxTotalAmount currencyID=\"" + trans.getCurrency() + "\">" + " <ram:TaxTotalAmount currencyID=\"" + trans.getCurrency() + "\">"
+ currencyFormat(getTotalGross().subtract(getTotal())) + "</ram:TaxTotalAmount>\n" + currencyFormat(calc.getTotalGross().subtract(calc.getTotal())) + "</ram:TaxTotalAmount>\n"
+ " <ram:GrandTotalAmount currencyID=\"" + trans.getCurrency() + "\">" + currencyFormat(getTotalGross()) + "</ram:GrandTotalAmount>\n" //$NON-NLS-2$ + " <ram:GrandTotalAmount currencyID=\"" + trans.getCurrency() + "\">" + currencyFormat(calc.getTotalGross()) + "</ram:GrandTotalAmount>\n" //$NON-NLS-2$
// // // //
// currencyID=\"EUR\" // currencyID=\"EUR\"
+ " <ram:TotalPrepaidAmount currencyID=\"" + trans.getCurrency() + "\">" + currencyFormat(getTotalPrepaid()) + "</ram:TotalPrepaidAmount>\n" + " <ram:TotalPrepaidAmount currencyID=\"" + trans.getCurrency() + "\">" + currencyFormat(calc.getTotalPrepaid()) + "</ram:TotalPrepaidAmount>\n"
+ " <ram:DuePayableAmount currencyID=\"" + trans.getCurrency() + "\">" + currencyFormat(getTotalGross().subtract(getTotalPrepaid())) + "</ram:DuePayableAmount>\n" //$NON-NLS-2$ + " <ram:DuePayableAmount currencyID=\"" + trans.getCurrency() + "\">" + currencyFormat(calc.getTotalGross().subtract(calc.getTotalPrepaid())) + "</ram:DuePayableAmount>\n" //$NON-NLS-2$
// // // //
// currencyID=\"EUR\" // currencyID=\"EUR\"
+ " </ram:SpecifiedTradeSettlementMonetarySummation>\n" + " </ram:SpecifiedTradeSettlementMonetarySummation>\n"
@@ -361,7 +362,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
} }
LineCalc lc = new LineCalc(currentItem); LineCalculator lc = new LineCalculator(currentItem);
xml = xml + " <ram:IncludedSupplyChainTradeLineItem>\n" + xml = xml + " <ram:IncludedSupplyChainTradeLineItem>\n" +
" <ram:AssociatedDocumentLineDocument>\n" " <ram:AssociatedDocumentLineDocument>\n"
+ " <ram:LineID>" + lineID + "</ram:LineID>\n" //$NON-NLS-2$ + " <ram:LineID>" + lineID + "</ram:LineID>\n" //$NON-NLS-2$
@@ -482,7 +483,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
if (discountTerms != null) { if (discountTerms != null) {
paymentTermsXml += "<ram:ApplicableTradePaymentDiscountTerms>"; paymentTermsXml += "<ram:ApplicableTradePaymentDiscountTerms>";
String currency = trans.getCurrency(); String currency = trans.getCurrency();
String basisAmount = currencyFormat(getTotalGross()); String basisAmount = currencyFormat(calc.getTotalGross());
paymentTermsXml += "<ram:BasisAmount currencyID=\"" + currency + "\">" + basisAmount + "</ram:BasisAmount>"; paymentTermsXml += "<ram:BasisAmount currencyID=\"" + currency + "\">" + basisAmount + "</ram:BasisAmount>";
paymentTermsXml += "<ram:CalculationPercent>" + discountTerms.getCalculationPercentage().toString() paymentTermsXml += "<ram:CalculationPercent>" + discountTerms.getCalculationPercentage().toString()
+ "</ram:CalculationPercent>"; + "</ram:CalculationPercent>";

View File

@@ -29,23 +29,23 @@ import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.Base64;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.dom4j.Document; import org.dom4j.Document;
import org.dom4j.DocumentException; import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper; import org.dom4j.DocumentHelper;
import org.dom4j.io.OutputFormat; import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter; import org.dom4j.io.XMLWriter;
import org.mustangproject.FileAttachment; import org.mustangproject.FileAttachment;
import org.mustangproject.Invoice;
import org.mustangproject.XMLTools; import org.mustangproject.XMLTools;
public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvider { public class ZUGFeRD2PullProvider implements IXMLProvider {
//// MAIN CLASS //// MAIN CLASS
protected SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); protected SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd");
protected byte[] zugferdData; protected byte[] zugferdData;
protected IExportableTransaction trans; protected IExportableTransaction trans;
protected TransactionCalculator calc;
private String paymentTermsDescription; private String paymentTermsDescription;
protected Profile profile = Profiles.getByName("EN16931"); protected Profile profile = Profiles.getByName("EN16931");
@@ -99,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<BigDecimal, VATAmount> 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<BigDecimal, VATAmount> getVATPercentAmountMap() {
HashMap<BigDecimal, VATAmount> 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 @Override
public Profile getProfile() { public Profile getProfile() {
@@ -304,6 +193,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide
@Override @Override
public void generateXML(IExportableTransaction trans) { public void generateXML(IExportableTransaction trans) {
this.trans = trans; this.trans = trans;
this.calc=new TransactionCalculator(trans);
boolean hasDueDate = false; boolean hasDueDate = false;
String taxCategoryCode = ""; String taxCategoryCode = "";
@@ -386,7 +276,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide
exemptionReason = "<ram:ExemptionReason>" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + "</ram:ExemptionReason>"; exemptionReason = "<ram:ExemptionReason>" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + "</ram:ExemptionReason>";
} }
LineCalc lc = new LineCalc(currentItem); LineCalculator lc = new LineCalculator(currentItem);
xml = xml + " <ram:IncludedSupplyChainTradeLineItem>\n" + xml = xml + " <ram:IncludedSupplyChainTradeLineItem>\n" +
" <ram:AssociatedDocumentLineDocument>\n" " <ram:AssociatedDocumentLineDocument>\n"
+ " <ram:LineID>" + lineID + "</ram:LineID>\n" //$NON-NLS-2$ + " <ram:LineID>" + lineID + "</ram:LineID>\n" //$NON-NLS-2$
@@ -498,13 +388,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide
// Additional Documents of XRechnung (Rechnungsbegruendende Unterlagen - BG-24 XRechnung) // Additional Documents of XRechnung (Rechnungsbegruendende Unterlagen - BG-24 XRechnung)
if (trans.getAdditionalReferencedDocuments() != null) { if (trans.getAdditionalReferencedDocuments() != null) {
for (FileAttachment f : trans.getAdditionalReferencedDocuments()) { for (FileAttachment f : trans.getAdditionalReferencedDocuments()) {
// final String documentContent = Base64.encodeBase64String(f.getData()); final String documentContent = new String(Base64.getEncoder().encodeToString(f.getData()));
xml = xml + " <ram:AdditionalReferencedDocument>\n" xml = xml + " <ram:AdditionalReferencedDocument>\n"
+ " <ram:IssuerAssignedID>" + f.getFilename() + "</ram:IssuerAssignedID>\n" + " <ram:IssuerAssignedID>" + f.getFilename() + "</ram:IssuerAssignedID>\n"
+ " <ram:TypeCode>916</ram:TypeCode>\n" + " <ram:TypeCode>916</ram:TypeCode>\n"
+ " <ram:Name>" + f.getDescription() + "</ram:Name>\n" + " <ram:Name>" + f.getDescription() + "</ram:Name>\n"
+ " <ram:AttachmentBinaryObject mimeCode=\"" + f.getMimetype() + "\"\n" + " <ram:AttachmentBinaryObject mimeCode=\"" + f.getMimetype() + "\"\n"
// + " filename=\"" + f.getFilename() + ">" + documentContent + "\n" + " filename=\"" + f.getFilename() + ">" + documentContent + "\n"
+ " </ram:AdditionalReferencedDocument>\n"; + " </ram:AdditionalReferencedDocument>\n";
} }
} }
@@ -557,7 +447,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide
} }
} }
HashMap<BigDecimal, VATAmount> VATPercentAmountMap = getVATPercentAmountMap(); HashMap<BigDecimal, VATAmount> VATPercentAmountMap = calc.getVATPercentAmountMap();
for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) {
VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); VATAmount amount = VATPercentAmountMap.get(currentTaxPercent);
if (amount != null) { if (amount != null) {
@@ -591,7 +481,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide
" <ram:ChargeIndicator>\n" + " <ram:ChargeIndicator>\n" +
" <udt:Indicator>true</udt:Indicator>\n" + " <udt:Indicator>true</udt:Indicator>\n" +
" </ram:ChargeIndicator>\n" + " </ram:ChargeIndicator>\n" +
" <ram:ActualAmount>" + currencyFormat(getCharges()) + "</ram:ActualAmount>\n" + " <ram:ActualAmount>" + currencyFormat(calc.getCharges()) + "</ram:ActualAmount>\n" +
" <ram:Reason>Charge</ram:Reason>\n" + " <ram:Reason>Charge</ram:Reason>\n" +
" <ram:CategoryTradeTax>\n" + " <ram:CategoryTradeTax>\n" +
" <ram:TypeCode>VAT</ram:TypeCode>\n" + " <ram:TypeCode>VAT</ram:TypeCode>\n" +
@@ -608,7 +498,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide
" <ram:ChargeIndicator>\n" + " <ram:ChargeIndicator>\n" +
" <udt:Indicator>false</udt:Indicator>\n" + " <udt:Indicator>false</udt:Indicator>\n" +
" </ram:ChargeIndicator>\n" + " </ram:ChargeIndicator>\n" +
" <ram:ActualAmount>" + currencyFormat(getAllowances()) + "</ram:ActualAmount>\n" + " <ram:ActualAmount>" + currencyFormat(calc.getAllowances()) + "</ram:ActualAmount>\n" +
" <ram:Reason>Allowance</ram:Reason>\n" + " <ram:Reason>Allowance</ram:Reason>\n" +
" <ram:CategoryTradeTax>\n" + " <ram:CategoryTradeTax>\n" +
" <ram:TypeCode>VAT</ram:TypeCode>\n" + " <ram:TypeCode>VAT</ram:TypeCode>\n" +
@@ -644,24 +534,24 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide
} }
String allowanceTotalLine = "<ram:AllowanceTotalAmount>" + currencyFormat(getAllowances()) + "</ram:AllowanceTotalAmount>"; String allowanceTotalLine = "<ram:AllowanceTotalAmount>" + currencyFormat(calc.getAllowances()) + "</ram:AllowanceTotalAmount>";
String chargesTotalLine = "<ram:ChargeTotalAmount>" + currencyFormat(getCharges()) + "</ram:ChargeTotalAmount>"; String chargesTotalLine = "<ram:ChargeTotalAmount>" + currencyFormat(calc.getCharges()) + "</ram:ChargeTotalAmount>";
xml = xml + " <ram:SpecifiedTradeSettlementHeaderMonetarySummation>\n" xml = xml + " <ram:SpecifiedTradeSettlementHeaderMonetarySummation>\n"
+ " <ram:LineTotalAmount>" + currencyFormat(getTotal()) + "</ram:LineTotalAmount>\n" //$NON-NLS-2$ + " <ram:LineTotalAmount>" + currencyFormat(calc.getTotal()) + "</ram:LineTotalAmount>\n" //$NON-NLS-2$
+ chargesTotalLine + chargesTotalLine
+ allowanceTotalLine + allowanceTotalLine
+ " <ram:TaxBasisTotalAmount>" + currencyFormat(getTaxBasis()) + "</ram:TaxBasisTotalAmount>\n" //$NON-NLS-2$ + " <ram:TaxBasisTotalAmount>" + currencyFormat(calc.getTaxBasis()) + "</ram:TaxBasisTotalAmount>\n" //$NON-NLS-2$
// // // //
// currencyID=\"EUR\" // currencyID=\"EUR\"
+ " <ram:TaxTotalAmount currencyID=\"" + trans.getCurrency() + "\">" + " <ram:TaxTotalAmount currencyID=\"" + trans.getCurrency() + "\">"
+ currencyFormat(getTotalGross().subtract(getTaxBasis())) + "</ram:TaxTotalAmount>\n" + currencyFormat(calc.getTotalGross().subtract(calc.getTaxBasis())) + "</ram:TaxTotalAmount>\n"
+ " <ram:GrandTotalAmount>" + currencyFormat(getTotalGross()) + "</ram:GrandTotalAmount>\n" //$NON-NLS-2$ + " <ram:GrandTotalAmount>" + currencyFormat(calc.getTotalGross()) + "</ram:GrandTotalAmount>\n" //$NON-NLS-2$
// // // //
// currencyID=\"EUR\" // currencyID=\"EUR\"
+ " <ram:TotalPrepaidAmount>" + currencyFormat(getTotalPrepaid()) + "</ram:TotalPrepaidAmount>\n" + " <ram:TotalPrepaidAmount>" + currencyFormat(calc.getTotalPrepaid()) + "</ram:TotalPrepaidAmount>\n"
+ " <ram:DuePayableAmount>" + currencyFormat(getTotalGross().subtract(getTotalPrepaid())) + "</ram:DuePayableAmount>\n" //$NON-NLS-2$ + " <ram:DuePayableAmount>" + currencyFormat(calc.getTotalGross().subtract(calc.getTotalPrepaid())) + "</ram:DuePayableAmount>\n" //$NON-NLS-2$
// // // //
// currencyID=\"EUR\" // currencyID=\"EUR\"
+ " </ram:SpecifiedTradeSettlementHeaderMonetarySummation>\n" + " </ram:SpecifiedTradeSettlementHeaderMonetarySummation>\n"
@@ -720,7 +610,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide
if (discountTerms != null) { if (discountTerms != null) {
paymentTermsXml += "<ram:ApplicableTradePaymentDiscountTerms>"; paymentTermsXml += "<ram:ApplicableTradePaymentDiscountTerms>";
String currency = trans.getCurrency(); String currency = trans.getCurrency();
String basisAmount = currencyFormat(getTotalGross()); String basisAmount = currencyFormat(calc.getTotalGross());
paymentTermsXml += "<ram:BasisAmount currencyID=\"" + currency + "\">" + basisAmount + "</ram:BasisAmount>"; paymentTermsXml += "<ram:BasisAmount currencyID=\"" + currency + "\">" + basisAmount + "</ram:BasisAmount>";
paymentTermsXml += "<ram:CalculationPercent>" + discountTerms.getCalculationPercentage().toString() paymentTermsXml += "<ram:CalculationPercent>" + discountTerms.getCalculationPercentage().toString()
+ "</ram:CalculationPercent>"; + "</ram:CalculationPercent>";
@@ -742,8 +632,4 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide
return paymentTermsXml; return paymentTermsXml;
} }
@Override
public BigDecimal getValue() {
return getTotal();
}
} }

View File

@@ -6,6 +6,8 @@ import org.w3c.dom.NodeList;
import javax.xml.xpath.*; import javax.xml.xpath.*;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter {
@@ -13,78 +15,185 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter {
super(filename); super(filename);
} }
public Invoice extractInvoice() { /***
* This will parse a XML into a invoice object
* @return the parsed invoice object
*/
public Invoice extractInvoice() throws XPathExpressionException, ParseException {
String number = "AB123"; String number = "";
/** /*
* dummywerte sind derzeit noch setDueDate setIssueDate setDeliveryDate setSender setRecipient setnumber * dummywerte sind derzeit noch setDueDate setIssueDate setDeliveryDate setSender setRecipient setnumber
* bspw. due date //ExchangedDocument//IssueDateTime//DateTimeString : due date optional * bspw. due date //ExchangedDocument//IssueDateTime//DateTimeString : due date optional
*/ */
XPathFactory xpathFact = XPathFactory.newInstance(); XPathFactory xpathFact = XPathFactory.newInstance();
XPath xpath = xpathFact.newXPath(); XPath xpath = xpathFact.newXPath();
Invoice zpp = null; Invoice zpp = null;
try { XPathExpression xpr = xpath.compile(
XPathExpression xpr = xpath.compile( "//*[local-name()=\"SellerTradeParty\"]");
"//SellerTradeParty"); NodeList SellerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
NodeList SellerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
xpr = xpath.compile(
"//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); xpr = xpath.compile(
//.addItem(new Item(new Product("Testprodukt","","C62",new BigDecimal(0)),amount,new BigDecimal(1.0))) "//*[local-name()=\"BuyerTradeParty\"]");
zpp.setOwnOrganisationName(extractString("//SellerTradeParty/Name")); 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()=\"IncludedSupplyChainTradeLineItem\"]");
NodeList nodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
if (nodes.getLength() == 0) { Date issueDate = null;
} else { Date dueDate = null;
for (int i = 0; i < nodes.getLength(); i++) { Date deliveryDate = null;
//nodes.item(i).getTextContent())) { for (int i = 0; i < ExchangedDocumentNodes.getLength(); i++) {
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();
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
} //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());
} }
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();
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());
} }
} }
} }
} }
// 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)));
} }
}
}
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();
} }
return zpp; return zpp;
} }
} }

View File

@@ -38,6 +38,7 @@ import junit.framework.TestCase;
@FixMethodOrder(MethodSorters.NAME_ASCENDING) @FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ZF2PushTest extends TestCase { public class ZF2PushTest extends TestCase {
final String TARGET_PDF = "./target/testout-ZF2Push.pdf"; 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_CORRECTIONPDF = "./target/testout-ZF2PushCorrection.pdf";
final String TARGET_ITEMCHARGESALLOWANCESPDF = "./target/testout-ZF2PushItemChargesAllowances.pdf"; final String TARGET_ITEMCHARGESALLOWANCESPDF = "./target/testout-ZF2PushItemChargesAllowances.pdf";
final String TARGET_CHARGESALLOWANCESPDF = "./target/testout-ZF2PushChargesAllowances.pdf"; final String TARGET_CHARGESALLOWANCESPDF = "./target/testout-ZF2PushChargesAllowances.pdf";
@@ -49,9 +50,9 @@ public class ZF2PushTest extends TestCase {
// the writing part // the writing part
String orgname = "Test company"; String orgname = "Test company";
String number = "123"; String number = "RE-20170509/505";
String amountStr = "1.00"; String priceStr = "1.00";
BigDecimal amount = new BigDecimal(amountStr); BigDecimal price = new BigDecimal(priceStr);
String occurenceFrom = "20201001"; String occurenceFrom = "20201001";
String occurenceTo = "20201005"; String occurenceTo = "20201005";
String contractID = "376zreurzu0983"; String contractID = "376zreurzu0983";
@@ -63,7 +64,7 @@ public class ZF2PushTest extends TestCase {
.load(SOURCE_PDF)) { .load(SOURCE_PDF)) {
try { 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) { } catch (ParseException ex) {
throw new RuntimeException("Parse exception"); throw new RuntimeException("Parse exception");
} }
@@ -102,9 +103,9 @@ public class ZF2PushTest extends TestCase {
String orgname = "Test company"; String orgname = "Test company";
String number = "123"; String number = "123";
String amountStr = "1.00"; String priceStr = "1.00";
String taxID = "9990815"; String taxID = "9990815";
BigDecimal amount = new BigDecimal(amountStr); BigDecimal price = new BigDecimal(priceStr);
try (InputStream SOURCE_PDF = this.getClass() try (InputStream SOURCE_PDF = this.getClass()
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); .getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
@@ -115,7 +116,7 @@ public class ZF2PushTest extends TestCase {
byte[] b = {12, 13}; byte[] b = {12, 13};
ze.attachFile("one.pdf", b, "Application/PDF", "Alternative"); ze.attachFile("one.pdf", b, "Application/PDF", "Alternative");
ze.attachFile("two.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()); 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("<rsm:CrossIndustryInvoice"));
ze.export(TARGET_ALLOWANCESPDF);
} catch (IOException e) {
fail("IOException should not be raised in testEdgeExport");
}
// now check the contents (like MustangReaderTest)
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_ALLOWANCESPDF);
assertTrue(zi.getUTF8().contains("EUR"));
// Reading ZUGFeRD
assertEquals("4046.00", zi.getAmount());
assertEquals(zi.getHolder(), orgname);
assertEquals(zi.getForeignReference(), number);
try {
assertEquals(zi.getVersion(), 2);
} catch (Exception e) {
e.printStackTrace();
}
} }
public void testRelativeChargesAllowancesExport() { public void testRelativeChargesAllowancesExport() {
String orgname = "Test company"; String orgname = "Test company";
String number = "123"; String number = "123";
String amountStr = "3.00"; String priceStr = "3.00";
BigDecimal amount = new BigDecimal(amountStr); BigDecimal price = new BigDecimal(priceStr);
try (InputStream SOURCE_PDF = this.getClass() try (InputStream SOURCE_PDF = this.getClass()
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); .getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
@@ -254,9 +297,9 @@ public class ZF2PushTest extends TestCase {
.load(SOURCE_PDF)) { .load(SOURCE_PDF)) {
ze.setTransaction(new Invoice().setCurrency("CHF").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) ze.setTransaction(new Invoice().setCurrency("CHF").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)), amount, new BigDecimal(1.0))) .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0))) .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addCharge(new Charge().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)))) .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)).addCharge(new Charge().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19))))
.addAllowance(new Allowance().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19))) .addAllowance(new Allowance().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)))
); );
@@ -292,7 +335,7 @@ public class ZF2PushTest extends TestCase {
String number = "123"; String number = "123";
String priceStr = "1.00"; String priceStr = "1.00";
BigDecimal price = new BigDecimal(priceStr); BigDecimal price = new BigDecimal(priceStr);
BigDecimal amount = new BigDecimal(-1.0); BigDecimal qty = new BigDecimal(-1.0);
try (InputStream SOURCE_PDF = this.getClass() try (InputStream SOURCE_PDF = this.getClass()
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); .getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
@@ -301,9 +344,9 @@ public class ZF2PushTest extends TestCase {
.load(SOURCE_PDF)) { .load(SOURCE_PDF)) {
Invoice i = new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setOccurrencePeriod(new Date(), new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815")).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0815")).setNumber(number) Invoice i = new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setOccurrencePeriod(new Date(), new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815")).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0815")).setNumber(number)
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, amount)) .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, amount)) .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, amount)).setCorrection("0815"); .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty)).setCorrection("0815");
ze.setTransaction(i); ze.setTransaction(i);
String theXML = new String(ze.getProvider().getXML()); String theXML = new String(ze.getProvider().getXML());
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice")); assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));

View File

@@ -27,6 +27,14 @@ import junit.framework.TestCase;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; 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;
import java.util.GregorianCalendar;
/*** /***
* Classname ZF2ZInvoiceImporterTest is alphabetical behind the tests which will create the file * Classname ZF2ZInvoiceImporterTest is alphabetical behind the tests which will create the file
@@ -39,17 +47,47 @@ public class ZF2ZInvoiceImporterTest extends TestCase {
ZUGFeRDInvoiceImporter zii=new ZUGFeRDInvoiceImporter(TARGET_PDF); 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 // Reading ZUGFeRD
assertEquals("Bei Spiel GmbH", invoice.getOwnOrganisationName()); assertEquals("Bei Spiel GmbH", invoice.getOwnOrganisationName());
assertEquals(3, invoice.getZFItems().length); assertEquals(3, invoice.getZFItems().length);
assertEquals("400.0000", invoice.getZFItems()[1].getQuantity().toString()); 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("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());
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()));
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());
TransactionCalculator tc=new TransactionCalculator(invoice);
assertEquals(new BigDecimal("571.040000"),tc.getTotalGross());
// name street location zip country, contact name phone email, total amount
*/
} }