refactoring Transactioncalculator
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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()) {
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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>";
|
||||||
|
|||||||
@@ -31,22 +31,21 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
import net.sf.saxon.value.Base64BinaryValue;
|
|
||||||
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");
|
||||||
|
|
||||||
@@ -100,117 +99,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//move
|
|
||||||
protected BigDecimal getTotalPrepaid() {
|
|
||||||
if (trans.getTotalPrepaidAmount() == null) {
|
|
||||||
return new BigDecimal(0);
|
|
||||||
} else {
|
|
||||||
return trans.getTotalPrepaidAmount();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BigDecimal getTotalGross() {
|
|
||||||
|
|
||||||
BigDecimal res = getTaxBasis();
|
|
||||||
HashMap<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() {
|
||||||
@@ -305,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 = "";
|
||||||
@@ -387,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$
|
||||||
@@ -558,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) {
|
||||||
@@ -592,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" +
|
||||||
@@ -609,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" +
|
||||||
@@ -645,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"
|
||||||
@@ -721,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>";
|
||||||
@@ -743,8 +632,4 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvide
|
|||||||
return paymentTermsXml;
|
return paymentTermsXml;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigDecimal getValue() {
|
|
||||||
return getTotal();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter {
|
|||||||
* This will parse a XML into a invoice object
|
* This will parse a XML into a invoice object
|
||||||
* @return the parsed invoice object
|
* @return the parsed invoice object
|
||||||
*/
|
*/
|
||||||
public Invoice extractInvoice() {
|
public Invoice extractInvoice() throws XPathExpressionException, ParseException {
|
||||||
|
|
||||||
String number = "";
|
String number = "";
|
||||||
/*
|
/*
|
||||||
@@ -29,7 +29,6 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter {
|
|||||||
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\"]");
|
"//*[local-name()=\"SellerTradeParty\"]");
|
||||||
NodeList SellerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
NodeList SellerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||||
@@ -194,12 +193,6 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (XPathExpressionException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ParseException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return zpp;
|
return zpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ 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.text.SimpleDateFormat;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -44,7 +47,14 @@ 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);
|
||||||
@@ -71,6 +81,10 @@ public class ZF2ZInvoiceImporterTest extends TestCase {
|
|||||||
assertEquals("DE", invoice.getSender().getCountry());
|
assertEquals("DE", invoice.getSender().getCountry());
|
||||||
assertEquals("Stadthausen", invoice.getSender().getLocation());
|
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
|
// name street location zip country, contact name phone email, total amount
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user