Merge branch 'issues/764'
# Conflicts: # library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java # library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
#786
|
#786
|
||||||
add getCalculation on calculatedInvoice
|
add getCalculation on calculatedInvoice
|
||||||
Transactioncalculator getTaxDetails to include correct percentage, calculated amounts
|
Transactioncalculator getTaxDetails to include correct percentage, calculated amounts
|
||||||
|
#764
|
||||||
|
|
||||||
2.16.5
|
2.16.5
|
||||||
=======
|
=======
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package org.mustangproject;
|
|||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import org.mustangproject.ZUGFeRD.IAbsoluteValueProvider;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* (absolute) allowances on item and document level
|
* (absolute) allowances on item and document level
|
||||||
@@ -29,6 +31,22 @@ public class Allowance extends Charge {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getTotalAmount(IAbsoluteValueProvider currentItem) {
|
||||||
|
if(totalAmount != null) {
|
||||||
|
return totalAmount;
|
||||||
|
} else if (percent!=null) {
|
||||||
|
BigDecimal singlePrice=currentItem.getValue().divide(BigDecimal.ONE.add(getPercent().divide(new BigDecimal(100))), 18, RoundingMode.HALF_UP);
|
||||||
|
// BigDecimal singlePrice=currentItem.getValue().multiply(BigDecimal.ONE.subtract(getPercent().divide(new BigDecimal(100))));
|
||||||
|
BigDecimal singlePriceDiff=currentItem.getValue().subtract(singlePrice);
|
||||||
|
return singlePriceDiff;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("percent must be set");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Always to return false for IZUGFeRDAllowanceCharge
|
* Always to return false for IZUGFeRDAllowanceCharge
|
||||||
* @return false since its not supposed to be calculated negatively
|
* @return false since its not supposed to be calculated negatively
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import org.mustangproject.ZUGFeRD.IAbsoluteValueProvider;
|
|||||||
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
|
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Absolute and relative charges for document and item level
|
* Absolute and relative charges for document and item level
|
||||||
@@ -23,6 +24,10 @@ public class Charge implements IZUGFeRDAllowanceCharge {
|
|||||||
* the absolute value if not percentage
|
* the absolute value if not percentage
|
||||||
*/
|
*/
|
||||||
protected BigDecimal totalAmount;
|
protected BigDecimal totalAmount;
|
||||||
|
/**
|
||||||
|
* the value the percentage is applied upon
|
||||||
|
*/
|
||||||
|
protected BigDecimal basisAmount;
|
||||||
/**
|
/**
|
||||||
* the tax rate the charge belongs to
|
* the tax rate the charge belongs to
|
||||||
*/
|
*/
|
||||||
@@ -103,6 +108,22 @@ public class Charge implements IZUGFeRDAllowanceCharge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getBasisAmount() {
|
||||||
|
return basisAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* sets a potential basis for the potential percentage
|
||||||
|
* @param basis the basis amount
|
||||||
|
* @return fluid setter
|
||||||
|
*/
|
||||||
|
public Charge setBasisAmount(BigDecimal basis) {
|
||||||
|
this.basisAmount = basis;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getReasonCode() {
|
public String getReasonCode() {
|
||||||
return reasonCode;
|
return reasonCode;
|
||||||
@@ -121,10 +142,13 @@ public class Charge implements IZUGFeRDAllowanceCharge {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getTotalAmount(IAbsoluteValueProvider currentItem) {
|
public BigDecimal getTotalAmount(IAbsoluteValueProvider currentItem) {
|
||||||
if (percent!=null) {
|
if(totalAmount != null) {
|
||||||
return currentItem.getValue().multiply(getPercent().divide(new BigDecimal(100)));
|
|
||||||
} else if(totalAmount != null) {
|
|
||||||
return totalAmount;
|
return totalAmount;
|
||||||
|
} else if (percent!=null) {
|
||||||
|
BigDecimal singlePrice=currentItem.getValue().divide(BigDecimal.ONE.add(getPercent().divide(new BigDecimal(100))), 18, RoundingMode.HALF_UP);
|
||||||
|
// BigDecimal singlePrice=currentItem.getValue().multiply(BigDecimal.ONE.subtract(getPercent().divide(new BigDecimal(100))));
|
||||||
|
BigDecimal singlePriceDiff=currentItem.getValue().add(singlePrice);
|
||||||
|
return singlePriceDiff;
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("percent must be set");
|
throw new RuntimeException("percent must be set");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,8 +72,6 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
//we need: name description unitcode
|
//we need: name description unitcode
|
||||||
//and we additionally have vat%
|
//and we additionally have vat%
|
||||||
|
|
||||||
// Bharti's homework 20241126:Streams https://www.youtube.com/watch?v=Lf01cBzmuXw
|
|
||||||
// and Lambdas https://www.youtube.com/watch?v=HCyx31NW8xg
|
|
||||||
setProduct(new Product(itemMap.getNode("Item").get()));
|
setProduct(new Product(itemMap.getNode("Item").get()));
|
||||||
icnm.getAsString("Name").ifPresent(product::setName);
|
icnm.getAsString("Name").ifPresent(product::setName);
|
||||||
icnm.getAsString("Description").ifPresent(product::setDescription);
|
icnm.getAsString("Description").ifPresent(product::setDescription);
|
||||||
@@ -86,17 +84,6 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
BuyersItemIdentification.getAsString("ID").ifPresent(product::setBuyerAssignedID);
|
BuyersItemIdentification.getAsString("ID").ifPresent(product::setBuyerAssignedID);
|
||||||
});
|
});
|
||||||
|
|
||||||
// String name = icnm.getAsStringOrNull("Name");
|
|
||||||
// String val = icnm.getAsStringOrNull("Value");
|
|
||||||
// if (name != null && val != null) {
|
|
||||||
// if (attributes == null) {
|
|
||||||
// attributes = new HashMap<>();
|
|
||||||
// }
|
|
||||||
// product.attributes.put(name, val);
|
|
||||||
// }
|
|
||||||
//icnm.getNode("AdditionalItemProperty").flatMap(n ->n.getAttributes()).ifPresent(product::setAttributes);
|
|
||||||
|
|
||||||
|
|
||||||
icnm.getAsNodeMap("ClassifiedTaxCategory").flatMap(m -> m.getAsBigDecimal("Percent"))
|
icnm.getAsNodeMap("ClassifiedTaxCategory").flatMap(m -> m.getAsBigDecimal("Percent"))
|
||||||
.ifPresent(product::setVATPercent);
|
.ifPresent(product::setVATPercent);
|
||||||
});
|
});
|
||||||
@@ -175,11 +162,12 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
.ifPresent(product::setTaxExemptionReason);
|
.ifPresent(product::setTaxExemptionReason);
|
||||||
|
|
||||||
icnm.getAllNodes("SpecifiedTradeAllowanceCharge").map(NodeMap::new).forEach(stac -> {
|
icnm.getAllNodes("SpecifiedTradeAllowanceCharge").map(NodeMap::new).forEach(stac -> {
|
||||||
stac.getAsNodeMap("ChargeIndicator").ifPresent(ci -> { //CII
|
stac.getAsNodeMap("ChargeIndicator").ifPresent(ci -> {
|
||||||
String isChargeString = ci.getAsString("Indicator").get();
|
String isChargeString = ci.getAsString("Indicator").get();
|
||||||
String percentString = stac.getAsStringOrNull("CalculationPercent");//MultiplierFactorNumeric
|
String percentString = stac.getAsStringOrNull("CalculationPercent");
|
||||||
String amountString = stac.getAsStringOrNull("ActualAmount");//Amount
|
String amountString = stac.getAsStringOrNull("ActualAmount");
|
||||||
String reason = stac.getAsStringOrNull("Reason");//AllowanceChargeReason
|
String basisAmountString = stac.getAsStringOrNull("BasisAmount");
|
||||||
|
String reason = stac.getAsStringOrNull("Reason");
|
||||||
Charge izac = new Charge();
|
Charge izac = new Charge();
|
||||||
if (isChargeString.equalsIgnoreCase("false")) {
|
if (isChargeString.equalsIgnoreCase("false")) {
|
||||||
izac = new Allowance();
|
izac = new Allowance();
|
||||||
@@ -188,6 +176,12 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
}
|
}
|
||||||
if (amountString != null) {
|
if (amountString != null) {
|
||||||
izac.setTotalAmount(new BigDecimal(amountString));
|
izac.setTotalAmount(new BigDecimal(amountString));
|
||||||
|
if (percentString!=null&&(percentString!="0")) {
|
||||||
|
izac.setTotalAmount(new BigDecimal(amountString).divide(getQuantity()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (basisAmountString != null) {
|
||||||
|
izac.setBasisAmount(new BigDecimal(basisAmountString));
|
||||||
}
|
}
|
||||||
if (percentString != null) {
|
if (percentString != null) {
|
||||||
izac.setPercent(new BigDecimal(percentString));
|
izac.setPercent(new BigDecimal(percentString));
|
||||||
@@ -288,6 +282,16 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public IZUGFeRDAllowanceCharge[] getAllowances() {
|
||||||
|
IZUGFeRDAllowanceCharge[] izac=new IZUGFeRDAllowanceCharge[Allowances.size()];
|
||||||
|
return Allowances.toArray(izac);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public IZUGFeRDAllowanceCharge[] getCharges() {
|
||||||
|
IZUGFeRDAllowanceCharge[] izac=new IZUGFeRDAllowanceCharge[Charges.size()];
|
||||||
|
return Charges.toArray(izac);
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* BT 132 (issue https://github.com/ZUGFeRD/mustangproject/issues/247)
|
* BT 132 (issue https://github.com/ZUGFeRD/mustangproject/issues/247)
|
||||||
* @return the line ID of the order (BT132)
|
* @return the line ID of the order (BT132)
|
||||||
@@ -461,6 +465,7 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
* @return fluent setter
|
* @return fluent setter
|
||||||
*/
|
*/
|
||||||
public Item addAllowance(IZUGFeRDAllowanceCharge izac) {
|
public Item addAllowance(IZUGFeRDAllowanceCharge izac) {
|
||||||
|
|
||||||
Allowances.add(izac);
|
Allowances.add(izac);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ public class Product implements IZUGFeRDExportableProduct {
|
|||||||
protected boolean isIntraCommunitySupply = false;
|
protected boolean isIntraCommunitySupply = false;
|
||||||
protected SchemedID globalId = null;
|
protected SchemedID globalId = null;
|
||||||
protected String countryOfOrigin = null;
|
protected String countryOfOrigin = null;
|
||||||
|
protected ArrayList<Charge> charges=new ArrayList<>();
|
||||||
|
protected ArrayList<Allowance> allowances=new ArrayList<>();
|
||||||
protected HashMap<String, String> attributes = new HashMap<>();
|
protected HashMap<String, String> attributes = new HashMap<>();
|
||||||
|
|
||||||
protected List<IDesignatedProductClassification> classifications = new ArrayList<>();
|
protected List<IDesignatedProductClassification> classifications = new ArrayList<>();
|
||||||
@@ -393,4 +395,42 @@ public class Product implements IZUGFeRDExportableProduct {
|
|||||||
this.classifications.add(classification);
|
this.classifications.add(classification);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Product addCharge(Charge e) {
|
||||||
|
charges.add(e);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Product addAllowance(Allowance a) {
|
||||||
|
allowances.add(a);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* returns the AppliedTradeAllowanceCharges of this product which are actually Charges
|
||||||
|
* @return array of or null, if none
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Charge[] getCharges() {
|
||||||
|
if (charges.size()==0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Charge[] chargeArr = new Charge[charges.size()];
|
||||||
|
return charges.toArray(chargeArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
/***
|
||||||
|
* returns the AppliedTradeAllowanceCharges of this product which are actually Allowances
|
||||||
|
* @return array of or null, if none
|
||||||
|
*/
|
||||||
|
public Allowance[] getAllowances() {
|
||||||
|
if (allowances.size()==0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Allowance[] allowanceArr = new Allowance[allowances.size()];
|
||||||
|
return allowances.toArray(allowanceArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ public interface IZUGFeRDAllowanceCharge {
|
|||||||
*/
|
*/
|
||||||
default BigDecimal getPercent() {return null;}
|
default BigDecimal getPercent() {return null;}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* returns a basis the precentage is calculated from
|
||||||
|
* @return null or the basis
|
||||||
|
*/
|
||||||
|
default BigDecimal getBasisAmount() {return null;}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* get a description for the allowance/charge
|
* get a description for the allowance/charge
|
||||||
* @return the description
|
* @return the description
|
||||||
|
|||||||
@@ -43,7 +43,11 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
|
|||||||
* item level discounts
|
* item level discounts
|
||||||
* @return array of the discounts on a single item
|
* @return array of the discounts on a single item
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
default IZUGFeRDAllowanceCharge[] getItemAllowances() {
|
default IZUGFeRDAllowanceCharge[] getItemAllowances() {
|
||||||
|
if (getProduct()!=null) {
|
||||||
|
return getProduct().getAllowances();
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,10 +55,27 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
|
|||||||
* item level price additions
|
* item level price additions
|
||||||
* @return array of the additional charges on the item
|
* @return array of the additional charges on the item
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
default IZUGFeRDAllowanceCharge[] getItemCharges() {
|
default IZUGFeRDAllowanceCharge[] getItemCharges() {
|
||||||
|
if (getProduct()!=null) {
|
||||||
|
return getProduct().getCharges();
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
default IZUGFeRDAllowanceCharge[] getAllowances() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* item level price additions
|
||||||
|
* @return array of the additional charges on the item
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default IZUGFeRDAllowanceCharge[] getCharges() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* BT 132 (issue https://github.com/ZUGFeRD/mustangproject/issues/247)
|
* BT 132 (issue https://github.com/ZUGFeRD/mustangproject/issues/247)
|
||||||
@@ -147,9 +168,9 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* specify allowances amount for the line item total
|
* get all (allowances and charges) SpecifiedTradeAllowanceCharges
|
||||||
*
|
*
|
||||||
* @return the sum of allowances for this item
|
* @return the real item lecel SpecifiedTradeAllowanceCharges
|
||||||
*/
|
*/
|
||||||
default IZUGFeRDAllowanceCharge[] getItemTotalAllowances() {
|
default IZUGFeRDAllowanceCharge[] getItemTotalAllowances() {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -166,6 +166,25 @@ public interface IZUGFeRDExportableProduct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* product level discounts (AppliedTradeAllowanceCharge, will change net price)
|
||||||
|
* @return array of the discounts on a single product
|
||||||
|
*/
|
||||||
|
default IZUGFeRDAllowanceCharge[] getAllowances() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* product level charges (AppliedTradeAllowanceCharge, will change net price)
|
||||||
|
* @return array of the additional charges on the product
|
||||||
|
*/
|
||||||
|
default IZUGFeRDAllowanceCharge[] getCharges() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detailed information about the product
|
* Detailed information about the product
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -2,30 +2,49 @@ package org.mustangproject.ZUGFeRD;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* the linecalculator does the math within an item line, and e.g. calculates quantity*price.
|
* the linecalculator does the math within an item line, and e.g. calculates quantity*price.
|
||||||
* @see TransactionCalculator
|
* @see TransactionCalculator
|
||||||
*/
|
*/
|
||||||
public class LineCalculator {
|
public class LineCalculator {
|
||||||
private final BigDecimal price;
|
protected BigDecimal price;
|
||||||
private final BigDecimal priceGross;
|
protected BigDecimal priceGross;
|
||||||
private final BigDecimal itemTotalNetAmount;
|
protected BigDecimal itemTotalNetAmount;
|
||||||
private final BigDecimal itemTotalVATAmount;
|
protected BigDecimal itemTotalVATAmount;
|
||||||
private BigDecimal allowance = BigDecimal.ZERO;
|
protected BigDecimal lineAllowance = BigDecimal.ZERO;
|
||||||
private BigDecimal charge = BigDecimal.ZERO;
|
protected BigDecimal lineCharge = BigDecimal.ZERO;
|
||||||
private BigDecimal allowanceItemTotal = BigDecimal.ZERO;
|
protected BigDecimal itemAllowance = BigDecimal.ZERO;
|
||||||
|
protected BigDecimal itemCharge = BigDecimal.ZERO;
|
||||||
|
protected BigDecimal allowanceItemTotal = BigDecimal.ZERO;
|
||||||
|
|
||||||
public LineCalculator(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()) {
|
||||||
addAllowance(allowance.getTotalAmount(currentItem));
|
BigDecimal factor=BigDecimal.ONE;
|
||||||
|
BigDecimal singleAllowance=allowance.getTotalAmount(currentItem);
|
||||||
|
addItemAllowance(singleAllowance);
|
||||||
|
|
||||||
|
if ((allowance.getPercent()!=null)&&(allowance.getPercent().compareTo(BigDecimal.ZERO)!=0)) {
|
||||||
|
factor=currentItem.getQuantity();
|
||||||
|
}
|
||||||
|
addAllowanceItemTotal(singleAllowance.multiply(factor));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
|
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
|
||||||
for (IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
|
for (IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
|
||||||
addCharge(charge.getTotalAmount(currentItem));
|
BigDecimal factor=BigDecimal.ONE;
|
||||||
|
BigDecimal singleCharge=charge.getTotalAmount(currentItem);
|
||||||
|
addItemCharge(singleCharge);
|
||||||
|
if ((charge.getPercent()!=null)&&(charge.getPercent().compareTo(BigDecimal.ZERO)!=0)) {
|
||||||
|
factor=currentItem.getQuantity();
|
||||||
|
}
|
||||||
|
subtractAllowanceItemTotal(singleCharge.multiply(factor));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentItem.getItemTotalAllowances() != null && currentItem.getItemTotalAllowances().length > 0) {
|
if (currentItem.getItemTotalAllowances() != null && currentItem.getItemTotalAllowances().length > 0) {
|
||||||
@@ -42,22 +61,39 @@ public class LineCalculator {
|
|||||||
vatPercent = BigDecimal.ZERO;
|
vatPercent = BigDecimal.ZERO;
|
||||||
}
|
}
|
||||||
BigDecimal multiplicator = vatPercent.divide(BigDecimal.valueOf(100));
|
BigDecimal multiplicator = vatPercent.divide(BigDecimal.valueOf(100));
|
||||||
priceGross = currentItem.getPrice(); // see https://github.com/ZUGFeRD/mustangproject/issues/159
|
|
||||||
price = priceGross.subtract(allowance).add(charge);
|
|
||||||
|
|
||||||
BigDecimal quantity=BigDecimal.ZERO;
|
BigDecimal quantity=BigDecimal.ZERO;
|
||||||
if ((currentItem!=null)&&(currentItem.getQuantity()!=null)) {
|
if ((currentItem!=null)&&(currentItem.getQuantity()!=null)) {
|
||||||
quantity=currentItem.getQuantity();
|
quantity=currentItem.getQuantity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
price=currentItem.getPrice();
|
||||||
|
priceGross=price;
|
||||||
|
// price=price.subtract(itemAllowance).add(itemCharge);
|
||||||
|
// BigDecimal delta=charge.subtract(allowanceItemTotal).subtract(allowance);
|
||||||
|
// delta=delta.divide(currentItem.getQuantity(), 18, RoundingMode.HALF_UP);
|
||||||
|
|
||||||
|
BigDecimal delta=BigDecimal.ZERO;
|
||||||
|
if (currentItem.getProduct().getAllowances()!=null) {
|
||||||
|
for (IZUGFeRDAllowanceCharge ccaf:currentItem.getProduct().getAllowances()) {
|
||||||
|
delta=delta.subtract(ccaf.getTotalAmount(currentItem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentItem.getProduct().getCharges()!=null) {
|
||||||
|
for (IZUGFeRDAllowanceCharge ccaf : currentItem.getProduct().getCharges()) {
|
||||||
|
delta = delta.subtract(ccaf.getTotalAmount(currentItem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
price=price.add(delta);
|
||||||
// Division/Zero occurred here.
|
// Division/Zero occurred here.
|
||||||
// Used the setScale only because that's also done in getBasisQuantity
|
// Used the setScale only because that's also done in getBasisQuantity
|
||||||
BigDecimal basisQuantity = currentItem.getBasisQuantity().compareTo(BigDecimal.ZERO) == 0
|
BigDecimal basisQuantity = currentItem.getBasisQuantity().compareTo(BigDecimal.ZERO) == 0
|
||||||
? BigDecimal.ONE.setScale(4)
|
? BigDecimal.ONE.setScale(4)
|
||||||
: currentItem.getBasisQuantity();
|
: currentItem.getBasisQuantity();
|
||||||
itemTotalNetAmount = quantity.multiply(price).divide(basisQuantity, 18, RoundingMode.HALF_UP)
|
itemTotalNetAmount = quantity.multiply(price).divide(basisQuantity, 18, RoundingMode.HALF_UP)
|
||||||
.subtract(allowanceItemTotal).setScale(2, RoundingMode.HALF_UP);
|
.add(lineCharge).subtract(lineAllowance).subtract(allowanceItemTotal).setScale(2, RoundingMode.HALF_UP);
|
||||||
itemTotalVATAmount = itemTotalNetAmount.multiply(multiplicator);
|
itemTotalVATAmount = itemTotalNetAmount.multiply(multiplicator);//.setScale(2, RoundingMode.HALF_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getPrice() {
|
public BigDecimal getPrice() {
|
||||||
@@ -80,16 +116,27 @@ public class LineCalculator {
|
|||||||
return priceGross;
|
return priceGross;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAllowance(BigDecimal b) {
|
public void addLineAllowance(BigDecimal b) {
|
||||||
allowance = allowance.add(b);
|
lineAllowance = lineAllowance.add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCharge(BigDecimal b) {
|
public void addLineCharge(BigDecimal b) {
|
||||||
charge = charge.add(b);
|
lineCharge = lineCharge.add(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItemAllowance(BigDecimal b) {
|
||||||
|
itemAllowance = itemAllowance.add(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItemCharge(BigDecimal b) {
|
||||||
|
itemCharge = itemCharge.add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAllowanceItemTotal(BigDecimal b) {
|
public void addAllowanceItemTotal(BigDecimal b) {
|
||||||
allowanceItemTotal = allowanceItemTotal.add(b);
|
allowanceItemTotal = allowanceItemTotal.add(b);
|
||||||
}
|
}
|
||||||
|
public void subtractAllowanceItemTotal(BigDecimal b) {
|
||||||
|
allowanceItemTotal = allowanceItemTotal.subtract(b);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -321,11 +321,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String reason = "";
|
String reason = "";
|
||||||
if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended") || profile == Profiles.getByName("XRechnung"))) {
|
boolean isEN16931=(profile == Profiles.getByName("XRechnung")) || (profile == Profiles.getByName("EN16931"));
|
||||||
|
if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended") || isEN16931)) {
|
||||||
reason = "<ram:Reason>" + XMLTools.encodeXML(allowance.getReason()) + "</ram:Reason>";
|
reason = "<ram:Reason>" + XMLTools.encodeXML(allowance.getReason()) + "</ram:Reason>";
|
||||||
}
|
}
|
||||||
String reasonCode = "";
|
String reasonCode = "";
|
||||||
if ((allowance.getReasonCode() != null) && (profile == Profiles.getByName("XRechnung"))) {
|
if ((allowance.getReasonCode() != null) && (profile == Profiles.getByName("Extended") || isEN16931)) {
|
||||||
// only in XRechnung profile
|
// only in XRechnung profile
|
||||||
reasonCode = "<ram:ReasonCode>" + allowance.getReasonCode() + "</ram:ReasonCode>";
|
reasonCode = "<ram:ReasonCode>" + allowance.getReasonCode() + "</ram:ReasonCode>";
|
||||||
}
|
}
|
||||||
@@ -433,24 +434,29 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
+ XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "</ram:BuyerAssignedID>";
|
+ XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "</ram:BuyerAssignedID>";
|
||||||
}
|
}
|
||||||
String allowanceChargeStr = "";
|
String allowanceChargeStr = "";
|
||||||
if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) {
|
if (currentItem.getProduct().getAllowances() != null && currentItem.getProduct().getAllowances().length > 0) {
|
||||||
for (final IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) {
|
for (final IZUGFeRDAllowanceCharge allowance : currentItem.getProduct().getAllowances()) {
|
||||||
allowanceChargeStr += getAllowanceChargeStr(allowance, currentItem);
|
allowanceChargeStr += getAllowanceChargeStr(allowance, currentItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
|
if (currentItem.getProduct().getCharges() != null && currentItem.getProduct().getCharges().length > 0) {
|
||||||
for (final IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
|
for (final IZUGFeRDAllowanceCharge charge : currentItem.getProduct().getCharges()) {
|
||||||
allowanceChargeStr += getAllowanceChargeStr(charge, currentItem);
|
allowanceChargeStr += getAllowanceChargeStr(charge, currentItem);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String itemTotalAllowanceChargeStr = "";
|
String itemTotalAllowanceChargeStr = "";
|
||||||
if (currentItem.getItemTotalAllowances() != null && currentItem.getItemTotalAllowances().length > 0) {
|
if (currentItem.getAllowances() != null && currentItem.getAllowances().length > 0) {
|
||||||
for (final IZUGFeRDAllowanceCharge itemTotalAllowance : currentItem.getItemTotalAllowances()) {
|
for (final IZUGFeRDAllowanceCharge itemTotalAllowance : currentItem.getAllowances()) {
|
||||||
itemTotalAllowanceChargeStr += getItemTotalAllowanceChargeStr(itemTotalAllowance, currentItem);
|
itemTotalAllowanceChargeStr += getItemTotalAllowanceChargeStr(itemTotalAllowance, currentItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (currentItem.getCharges() != null && currentItem.getCharges().length > 0) {
|
||||||
|
for (final IZUGFeRDAllowanceCharge itemTotalCharges : currentItem.getCharges()) {
|
||||||
|
itemTotalAllowanceChargeStr += getItemTotalAllowanceChargeStr(itemTotalCharges, currentItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xml += "<ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>";
|
xml += "<ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>";
|
||||||
if (currentItem.getProduct().getDescription() != null && currentItem.getProduct().getDescription().length() > 0) {
|
if (currentItem.getProduct().getDescription() != null && currentItem.getProduct().getDescription().length() > 0) {
|
||||||
@@ -553,7 +559,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
xml += "</ram:BillingSpecifiedPeriod>";
|
xml += "</ram:BillingSpecifiedPeriod>";
|
||||||
}
|
}
|
||||||
|
|
||||||
xml += itemTotalAllowanceChargeStr;
|
// item charges/allowances
|
||||||
|
if (!itemTotalAllowanceChargeStr.isEmpty()) {
|
||||||
|
xml += itemTotalAllowanceChargeStr ;
|
||||||
|
}
|
||||||
|
|
||||||
xml += "<ram:SpecifiedTradeSettlementLineMonetarySummation>"
|
xml += "<ram:SpecifiedTradeSettlementLineMonetarySummation>"
|
||||||
+ "<ram:LineTotalAmount>" + currencyFormat(lc.getItemTotalNetAmount())
|
+ "<ram:LineTotalAmount>" + currencyFormat(lc.getItemTotalNetAmount())
|
||||||
|
|||||||
@@ -383,29 +383,7 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
String street, name, additionalStreet, city, postal, countrySubentity, line, country = null;
|
String street, name, additionalStreet, city, postal, countrySubentity, line, country = null;
|
||||||
/*
|
|
||||||
String idx = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"ID\"]");
|
|
||||||
street = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name()=\"Address\"]/*[local-name()=\"StreetName\"]");
|
|
||||||
additionalStreet = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]/*[local-name() = \"AdditionalStreetName\"]");
|
|
||||||
city = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]/*[local-name() = \"CityName\"]");
|
|
||||||
postal = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]/*[local-name() = \"PostalZone\"]");
|
|
||||||
countrySubentity = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]/*[local-name() = \"CountrySubentity\"]");
|
|
||||||
line = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]//*[local-name() = \"AddressLine\"]/*[local-name() = \"Line\"]");
|
|
||||||
country = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]//*[local-name() = \"Country\"]/*[local-name() = \"IdentificationCode\"]");
|
|
||||||
name = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"DeliveryParty\"]//*[local-name() = \"PartyName\"]/*[local-name() = \"Name\"]");
|
|
||||||
*/
|
|
||||||
zpp.setDeliveryAddress(delivery);
|
zpp.setDeliveryAddress(delivery);
|
||||||
/*
|
|
||||||
zpp.setDeliveryAddress(new TradeParty()
|
|
||||||
.setStreet(street)
|
|
||||||
.setAdditionalAddress(additionalStreet)
|
|
||||||
.setLocation(city)
|
|
||||||
.setZIP(postal)
|
|
||||||
.setAdditionalAddressExtension(line)
|
|
||||||
.setCountry(country)
|
|
||||||
.setName(name)
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,14 +398,6 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
XPathExpression shipPayee = xpath.compile("//*[local-name()=\"PayeeParty\"]/*");
|
XPathExpression shipPayee = xpath.compile("//*[local-name()=\"PayeeParty\"]/*");
|
||||||
NodeList ublPayeeNodes = (NodeList) shipPayee.evaluate(getDocument(), XPathConstants.NODESET);
|
NodeList ublPayeeNodes = (NodeList) shipPayee.evaluate(getDocument(), XPathConstants.NODESET);
|
||||||
|
|
||||||
// if(ublPayeeNodes != null) {
|
|
||||||
// TradeParty payee = new TradeParty();
|
|
||||||
// NodeMap nodeMap = new NodeMap(ublPayeeNodes).getAsNodeMap("PayeeParty").get();
|
|
||||||
// nodeMap.getNode("ID").ifPresent(s -> {
|
|
||||||
// SchemedID sID = new SchemedID().setScheme(s.getAttributes().getNamedItem("schemeID").getTextContent()).setId(s.getTextContent());
|
|
||||||
// payee.addGlobalID(sID);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
//NodeList UBLpayeeNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
//NodeList UBLpayeeNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||||
if (ublPayeeNodes.getLength() > 0) {
|
if (ublPayeeNodes.getLength() > 0) {
|
||||||
zpp.setPayee(new TradeParty(ublPayeeNodes));
|
zpp.setPayee(new TradeParty(ublPayeeNodes));
|
||||||
@@ -836,9 +806,6 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if ((paymentMeansChilds.item(paymentTermChildIndex).getLocalName() != null) && (paymentTermChilds.item(paymentTermChildIndex).getLocalName().equals("DirectDebitMandateID"))) {
|
|
||||||
// directDebitMandateID = paymentTermChilds.item(paymentTermChildIndex).getTextContent();
|
|
||||||
// }
|
|
||||||
if ((paymentMeansChilds.item(meansChildIndex).getLocalName() != null)
|
if ((paymentMeansChilds.item(meansChildIndex).getLocalName() != null)
|
||||||
&& (paymentMeansChilds.item(meansChildIndex).getLocalName().equals("PaymentMandate"))) {
|
&& (paymentMeansChilds.item(meansChildIndex).getLocalName().equals("PaymentMandate"))) {
|
||||||
NodeList paymentMandateChilds = paymentMeansChilds.item(meansChildIndex).getChildNodes();
|
NodeList paymentMandateChilds = paymentMeansChilds.item(meansChildIndex).getChildNodes();
|
||||||
@@ -974,6 +941,7 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
NodeList chargeNodeChilds = chargeNodes.item(i).getChildNodes();
|
NodeList chargeNodeChilds = chargeNodes.item(i).getChildNodes();
|
||||||
boolean isCharge = true;
|
boolean isCharge = true;
|
||||||
String chargeAmount = null;
|
String chargeAmount = null;
|
||||||
|
String basisAmount = null;
|
||||||
String reason = null;
|
String reason = null;
|
||||||
String reasonCode = null;
|
String reasonCode = null;
|
||||||
String taxPercent = null;
|
String taxPercent = null;
|
||||||
@@ -1001,6 +969,8 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
|
|
||||||
} else if (chargeChildName.equals("ActualAmount") || chargeChildName.equals("Amount")) {
|
} else if (chargeChildName.equals("ActualAmount") || chargeChildName.equals("Amount")) {
|
||||||
chargeAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
|
chargeAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
|
||||||
|
} else if (chargeChildName.equals("BasisAmount")) {
|
||||||
|
basisAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
|
||||||
} else if (chargeChildName.equals("Reason") || chargeChildName.equals("AllowanceChargeReason")) {
|
} else if (chargeChildName.equals("Reason") || chargeChildName.equals("AllowanceChargeReason")) {
|
||||||
reason = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
|
reason = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
|
||||||
} else if (chargeChildName.equals("ReasonCode") || chargeChildName.equals("AllowanceChargeReasonCode")) {
|
} else if (chargeChildName.equals("ReasonCode") || chargeChildName.equals("AllowanceChargeReasonCode")) {
|
||||||
@@ -1028,6 +998,9 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
if (taxPercent != null) {
|
if (taxPercent != null) {
|
||||||
c.setTaxPercent(new BigDecimal(taxPercent));
|
c.setTaxPercent(new BigDecimal(taxPercent));
|
||||||
}
|
}
|
||||||
|
if (basisAmount != null) {
|
||||||
|
c.setBasisAmount(new BigDecimal(basisAmount));
|
||||||
|
}
|
||||||
zpp.addCharge(c);
|
zpp.addCharge(c);
|
||||||
} else {
|
} else {
|
||||||
Allowance a = new Allowance(new BigDecimal(chargeAmount));
|
Allowance a = new Allowance(new BigDecimal(chargeAmount));
|
||||||
@@ -1040,6 +1013,9 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
if (taxPercent != null) {
|
if (taxPercent != null) {
|
||||||
a.setTaxPercent(new BigDecimal(taxPercent));
|
a.setTaxPercent(new BigDecimal(taxPercent));
|
||||||
}
|
}
|
||||||
|
if (basisAmount != null) {
|
||||||
|
a.setBasisAmount(new BigDecimal(basisAmount));
|
||||||
|
}
|
||||||
zpp.addAllowance(a);
|
zpp.addAllowance(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,9 +54,9 @@ public class CalculationTest extends ResourceCase {
|
|||||||
|
|
||||||
final LineCalculator calculator = new LineCalculator(currentItem);
|
final LineCalculator calculator = new LineCalculator(currentItem);
|
||||||
|
|
||||||
assertEquals(valueOf(133.857).stripTrailingZeros(), calculator.getPrice().stripTrailingZeros());
|
assertEquals(valueOf(148.73).stripTrailingZeros(), calculator.getPrice().stripTrailingZeros());
|
||||||
assertEquals(valueOf(1606.28).stripTrailingZeros(), calculator.getItemTotalNetAmount().stripTrailingZeros());
|
assertEquals(valueOf(1769.89).stripTrailingZeros(), calculator.getItemTotalNetAmount().stripTrailingZeros());
|
||||||
assertEquals(valueOf(257.0048).stripTrailingZeros(), calculator.getItemTotalVATAmount().stripTrailingZeros());
|
assertEquals(valueOf(283.1824).stripTrailingZeros(), calculator.getItemTotalVATAmount().stripTrailingZeros());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -74,17 +74,20 @@ public class CalculationTest extends ResourceCase {
|
|||||||
|
|
||||||
final LineCalculator calculator = new LineCalculator(currentItem);
|
final LineCalculator calculator = new LineCalculator(currentItem);
|
||||||
|
|
||||||
assertEquals(valueOf(163.603).stripTrailingZeros(), calculator.getPrice().stripTrailingZeros());
|
assertEquals(valueOf(148.73).stripTrailingZeros(), calculator.getPrice().stripTrailingZeros());
|
||||||
assertEquals(valueOf(1963.24).stripTrailingZeros(), calculator.getItemTotalNetAmount().stripTrailingZeros());
|
assertEquals(valueOf(1799.63).stripTrailingZeros(), calculator.getItemTotalNetAmount().stripTrailingZeros());
|
||||||
assertEquals(valueOf(314.1184).stripTrailingZeros(), calculator.getItemTotalVATAmount().stripTrailingZeros());
|
assertEquals(valueOf(287.9408).stripTrailingZeros(), calculator.getItemTotalVATAmount().stripTrailingZeros());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLineCalculatorForeignCurrencyExample() {
|
public void testLineCalculatorForeignCurrencyExample() {
|
||||||
|
/*** xml of official fx sample with allowances and charges
|
||||||
/*
|
* 10x100 with 10% and 50€ item discount =850€
|
||||||
|
* +8,75 charges on document level=858,75, +19%VAT=1021,91
|
||||||
|
* prepaid 500->due payable=521,91
|
||||||
|
*/
|
||||||
File inputCII = getResourceAsFile("Extended_fremdwaehrung.xml");
|
File inputCII = getResourceAsFile("Extended_fremdwaehrung.xml");
|
||||||
inputCII=new File("C:\\Users\\jstaerk\\workspace\\XMLExamples\\zfdiverses\\20250407\\fremdwaehrung.xml");
|
|
||||||
ZUGFeRDInvoiceImporter zii=new ZUGFeRDInvoiceImporter();
|
ZUGFeRDInvoiceImporter zii=new ZUGFeRDInvoiceImporter();
|
||||||
Invoice invoice=null;
|
Invoice invoice=null;
|
||||||
zii.doIgnoreCalculationErrors();
|
zii.doIgnoreCalculationErrors();
|
||||||
@@ -104,9 +107,9 @@ inputCII=new File("C:\\Users\\jstaerk\\workspace\\XMLExamples\\zfdiverses\\20250
|
|||||||
|
|
||||||
final TransactionCalculator calculator = new TransactionCalculator(invoice);
|
final TransactionCalculator calculator = new TransactionCalculator(invoice);
|
||||||
|
|
||||||
assertEquals(valueOf(521.91).stripTrailingZeros(), calculator.getGrandTotal().stripTrailingZeros());
|
assertEquals(valueOf(521.91).stripTrailingZeros(), calculator.getDuePayable().stripTrailingZeros());
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -221,9 +224,94 @@ inputCII=new File("C:\\Users\\jstaerk\\workspace\\XMLExamples\\zfdiverses\\20250
|
|||||||
invoice.addAllowance(new Allowance().setPercent(total_discount_percent).setTaxPercent(sales_tax_percent1).setReasonCode("95").setReason("Rabatte"));
|
invoice.addAllowance(new Allowance().setPercent(total_discount_percent).setTaxPercent(sales_tax_percent1).setReasonCode("95").setReason("Rabatte"));
|
||||||
}
|
}
|
||||||
TransactionCalculator calculator = new TransactionCalculator(invoice);
|
TransactionCalculator calculator = new TransactionCalculator(invoice);
|
||||||
assertEquals(valueOf(101.86).stripTrailingZeros(), calculator.getGrandTotal().stripTrailingZeros());
|
assertEquals(valueOf(307.18).stripTrailingZeros(), calculator.getGrandTotal().stripTrailingZeros());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSimpleItemPercentAllowance() {
|
||||||
|
/***
|
||||||
|
* a product with net 1.10 and qty 5 and relative item allowance of 10% should return 5 as line and grand total
|
||||||
|
*/
|
||||||
|
SimpleDateFormat sqlDate = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
|
||||||
|
Invoice invoice = new Invoice();
|
||||||
|
invoice.setDocumentName("Rechnung");
|
||||||
|
invoice.setNumber("777777");
|
||||||
|
try {
|
||||||
|
invoice.setIssueDate(sqlDate.parse("2020-12-31"));
|
||||||
|
invoice.setDetailedDeliveryPeriod(sqlDate.parse("2020-12-01 - 2020-12-31".split(" - ")[0]), sqlDate.parse("2020-12-01 - 2020-12-31".split(" - ")[1]));
|
||||||
|
invoice.setDeliveryDate(sqlDate.parse("2020-12-31"));
|
||||||
|
invoice.setDueDate(sqlDate.parse("2021-01-15"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Failed to set dates", e);
|
||||||
|
|
||||||
|
}
|
||||||
|
TradeParty sender = new TradeParty("Maier GmbH", "Musterweg 5", "11111", "Testung", "DE");
|
||||||
|
sender.addVATID("DE2222222222");
|
||||||
|
invoice.setSender(sender);
|
||||||
|
|
||||||
|
/* trade party (recipient) */
|
||||||
|
TradeParty recipient = new TradeParty("Teston GmbH" + " " + "Zentrale" + " " + "", "Testweg 5", "11111", "Testung", "DE");
|
||||||
|
recipient.setID("111111");
|
||||||
|
recipient.addVATID("DE111111111");
|
||||||
|
invoice.setRecipient(recipient);
|
||||||
|
|
||||||
|
/* item */
|
||||||
|
Product product;
|
||||||
|
Item item;
|
||||||
|
|
||||||
|
product = new Product("AAA", "", "H84", BigDecimal.ZERO);
|
||||||
|
item = new Item(product, new BigDecimal("1.10"), new BigDecimal(5.00));
|
||||||
|
|
||||||
|
item.addAllowance(new Allowance().setPercent(new BigDecimal(10)).setTaxPercent(BigDecimal.ZERO));
|
||||||
|
invoice.addItem(item);
|
||||||
|
|
||||||
|
TransactionCalculator calculator = new TransactionCalculator(invoice);
|
||||||
|
assertEquals(new BigDecimal(5), calculator.getGrandTotal().stripTrailingZeros());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSimpleItemTotalAllowance() {
|
||||||
|
/***
|
||||||
|
* a product with net 1 and qty 5 and absolute _item_ allowance of 1 should return 4 as line total, and grand total
|
||||||
|
*/
|
||||||
|
SimpleDateFormat sqlDate = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
|
||||||
|
Invoice invoice = new Invoice();
|
||||||
|
invoice.setDocumentName("Rechnung");
|
||||||
|
invoice.setNumber("777777");
|
||||||
|
try {
|
||||||
|
invoice.setIssueDate(sqlDate.parse("2020-12-31"));
|
||||||
|
invoice.setDetailedDeliveryPeriod(sqlDate.parse("2020-12-01 - 2020-12-31".split(" - ")[0]), sqlDate.parse("2020-12-01 - 2020-12-31".split(" - ")[1]));
|
||||||
|
invoice.setDeliveryDate(sqlDate.parse("2020-12-31"));
|
||||||
|
invoice.setDueDate(sqlDate.parse("2021-01-15"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Failed to set dates", e);
|
||||||
|
|
||||||
|
}
|
||||||
|
TradeParty sender = new TradeParty("Maier GmbH", "Musterweg 5", "11111", "Testung", "DE");
|
||||||
|
sender.addVATID("DE2222222222");
|
||||||
|
invoice.setSender(sender);
|
||||||
|
|
||||||
|
/* trade party (recipient) */
|
||||||
|
TradeParty recipient = new TradeParty("Teston GmbH" + " " + "Zentrale" + " " + "", "Testweg 5", "11111", "Testung", "DE");
|
||||||
|
recipient.setID("111111");
|
||||||
|
recipient.addVATID("DE111111111");
|
||||||
|
invoice.setRecipient(recipient);
|
||||||
|
|
||||||
|
/* item */
|
||||||
|
Product product;
|
||||||
|
Item item;
|
||||||
|
|
||||||
|
product = new Product("AAA", "", "H84", BigDecimal.ZERO);
|
||||||
|
item = new Item(product, new BigDecimal("1.00"), new BigDecimal(5.00));
|
||||||
|
|
||||||
|
item.addAllowance(new Allowance(new BigDecimal(1)).setTaxPercent(BigDecimal.ZERO));
|
||||||
|
invoice.addItem(item);
|
||||||
|
|
||||||
|
TransactionCalculator calculator = new TransactionCalculator(invoice);
|
||||||
|
assertEquals(new BigDecimal(4), calculator.getGrandTotal().stripTrailingZeros());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LineCalculator should not throw an exception when calculating a non-terminating decimal expansion
|
* LineCalculator should not throw an exception when calculating a non-terminating decimal expansion
|
||||||
* */
|
* */
|
||||||
|
|||||||
@@ -395,7 +395,7 @@ public class DeSerializationTest extends ResourceCase {
|
|||||||
try {
|
try {
|
||||||
Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class);
|
Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class);
|
||||||
TransactionCalculator tc=new TransactionCalculator(newInvoiceFromJSON);
|
TransactionCalculator tc=new TransactionCalculator(newInvoiceFromJSON);
|
||||||
assertEquals(new BigDecimal("19.52"),tc.getGrandTotal());
|
assertEquals(new BigDecimal("18.92"),tc.getGrandTotal());
|
||||||
|
|
||||||
} catch (JsonProcessingException e) {
|
} catch (JsonProcessingException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ public class ZF2PushTest extends TestCase {
|
|||||||
|
|
||||||
String senderDescription = "Kleinunternehmer";
|
String senderDescription = "Kleinunternehmer";
|
||||||
String taxID = "9990815";
|
String taxID = "9990815";
|
||||||
String theNote="oh lala";
|
String theNote = "oh lala";
|
||||||
BigDecimal price = new BigDecimal(priceStr);
|
BigDecimal price = new BigDecimal(priceStr);
|
||||||
try {
|
try {
|
||||||
InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||||
@@ -177,7 +177,7 @@ public class ZF2PushTest extends TestCase {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(i.getZFItems()[0].getNotesWithSubjectCode().get(0).getContent(),theNote);
|
assertEquals(i.getZFItems()[0].getNotesWithSubjectCode().get(0).getContent(), theNote);
|
||||||
assertEquals(senderDescription, i.getSender().getDescription());
|
assertEquals(senderDescription, i.getSender().getDescription());
|
||||||
|
|
||||||
// now check the contents (like MustangReaderTest)
|
// now check the contents (like MustangReaderTest)
|
||||||
@@ -255,16 +255,16 @@ public class ZF2PushTest extends TestCase {
|
|||||||
// ze.setTransaction(new Invoice().setDueDate(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().setDueDate(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)).addAllowance(new Allowance().setPercent(new BigDecimal(50)))));
|
// .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50)))));
|
||||||
|
|
||||||
Invoice i=new Invoice().setDueDate(new Date()).setIssueDate(new Date())
|
Invoice i = new Invoice().setDueDate(new Date()).setIssueDate(new Date())
|
||||||
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815"))
|
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815"))
|
||||||
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")
|
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")
|
||||||
.setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562")))
|
.setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562")))
|
||||||
.setNumber(number)
|
.setNumber(number)
|
||||||
.addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("AReason").setTaxPercent(new BigDecimal(19)))
|
.addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("AReason").setTaxPercent(new BigDecimal(19)))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance(new BigDecimal("0.1"))))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance(new BigDecimal("0.1")).setReasonCode("95")))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50))))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50)).setReason("In love with salesperson")))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(2.0)).addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("AnotherReason")))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(2.0)).addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("AnotherReason")))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addCharge(new Charge(new BigDecimal(1))).addAllowance(new Allowance(new BigDecimal("1"))));
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("Yet another reason")).addAllowance(new Allowance(new BigDecimal("1")).setReason("Something completely strange")));
|
||||||
ze.setTransaction(i);
|
ze.setTransaction(i);
|
||||||
|
|
||||||
|
|
||||||
@@ -275,21 +275,20 @@ public class ZF2PushTest extends TestCase {
|
|||||||
fail("IOException should not be raised");
|
fail("IOException should not be raised");
|
||||||
}
|
}
|
||||||
|
|
||||||
// now check the contents (like MustangReaderTest)
|
|
||||||
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_ITEMCHARGESALLOWANCESPDF);
|
|
||||||
|
|
||||||
assertEquals("EUR", zi.getInvoiceCurrencyCode());
|
|
||||||
assertTrue(zi.getUTF8().contains("0911623562")); // fax number
|
|
||||||
assertTrue(zi.getUTF8().contains("ABK"));
|
|
||||||
|
|
||||||
// Reading ZUGFeRD
|
|
||||||
assertEquals("19.52", zi.getAmount());
|
|
||||||
assertEquals(orgname, zi.getHolder());
|
|
||||||
assertEquals(number, zi.getForeignReference());
|
|
||||||
try {
|
try {
|
||||||
|
// now check the contents (like MustangReaderTest)
|
||||||
|
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_ITEMCHARGESALLOWANCESPDF);
|
||||||
|
assertEquals("EUR", zi.getInvoiceCurrencyCode());
|
||||||
|
assertTrue(zi.getUTF8().contains("0911623562")); // fax number
|
||||||
|
assertTrue(zi.getUTF8().contains("ABK"));
|
||||||
|
|
||||||
|
// Reading ZUGFeRD
|
||||||
|
assertEquals("18.92", zi.getAmount());
|
||||||
|
assertEquals(orgname, zi.getHolder());
|
||||||
|
assertEquals(number, zi.getForeignReference());
|
||||||
assertEquals(zi.getVersion(), 2);
|
assertEquals(zi.getVersion(), 2);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
fail("Exception should not be raised");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -595,7 +594,7 @@ public class ZF2PushTest extends TestCase {
|
|||||||
assertEquals(1, i.getInvoiceReferencedDocuments().size());
|
assertEquals(1, i.getInvoiceReferencedDocuments().size());
|
||||||
assertEquals("abcd1234", i.getInvoiceReferencedDocuments().get(0).getIssuerAssignedID());
|
assertEquals("abcd1234", i.getInvoiceReferencedDocuments().get(0).getIssuerAssignedID());
|
||||||
assertEquals("4304171000002", i.getRecipient().getGlobalID());
|
assertEquals("4304171000002", i.getRecipient().getGlobalID());
|
||||||
SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
|
||||||
assertEquals(occurrenceFrom, sdf.format(i.getDetailedDeliveryPeriodFrom()));
|
assertEquals(occurrenceFrom, sdf.format(i.getDetailedDeliveryPeriodFrom()));
|
||||||
assertEquals(occurrenceTo, sdf.format(i.getDetailedDeliveryPeriodTo()));
|
assertEquals(occurrenceTo, sdf.format(i.getDetailedDeliveryPeriodTo()));
|
||||||
assertEquals("2001015001325", i.getZFItems()[0].getProduct().getGlobalID());
|
assertEquals("2001015001325", i.getZFItems()[0].getProduct().getGlobalID());
|
||||||
@@ -629,7 +628,7 @@ public class ZF2PushTest extends TestCase {
|
|||||||
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815"))
|
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815"))
|
||||||
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE"))
|
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE"))
|
||||||
.setNumber(number)
|
.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))))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).addAllowance(new Allowance(BigDecimal.ONE)), 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)))
|
.addAllowance(new Allowance(new BigDecimal(600)).setTaxPercent(new BigDecimal(19)))
|
||||||
);
|
);
|
||||||
String theXML = new String(ze.getProvider().getXML());
|
String theXML = new String(ze.getProvider().getXML());
|
||||||
@@ -645,7 +644,7 @@ public class ZF2PushTest extends TestCase {
|
|||||||
assertEquals("EUR", zi.getInvoiceCurrencyCode());
|
assertEquals("EUR", zi.getInvoiceCurrencyCode());
|
||||||
|
|
||||||
// Reading ZUGFeRD
|
// Reading ZUGFeRD
|
||||||
assertEquals("4046.00", zi.getAmount());
|
assertEquals("10805.20", zi.getAmount());
|
||||||
assertEquals(orgname, zi.getHolder());
|
assertEquals(orgname, zi.getHolder());
|
||||||
assertEquals(number, zi.getForeignReference());
|
assertEquals(number, zi.getForeignReference());
|
||||||
try {
|
try {
|
||||||
@@ -675,8 +674,8 @@ public class ZF2PushTest extends TestCase {
|
|||||||
.setNumber(number)
|
.setNumber(number)
|
||||||
.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)), price, 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)), price, new BigDecimal(1.0)))
|
||||||
.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))))
|
.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)).setReasonCode("ABK")))
|
||||||
.addAllowance(new Allowance().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)))
|
.addAllowance(new Allowance().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)).setReason("Mengenrabatt"))
|
||||||
);
|
);
|
||||||
String theXML = new String(ze.getProvider().getXML());
|
String theXML = new String(ze.getProvider().getXML());
|
||||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||||
@@ -689,7 +688,7 @@ public class ZF2PushTest extends TestCase {
|
|||||||
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_RELATIVECHARGESALLOWANCESPDF);
|
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_RELATIVECHARGESALLOWANCESPDF);
|
||||||
|
|
||||||
assertEquals("CHF", zi.getInvoiceCurrencyCode());
|
assertEquals("CHF", zi.getInvoiceCurrencyCode());
|
||||||
assertEquals("6.25", zi.getAmount());
|
assertEquals("11.10", zi.getAmount());
|
||||||
assertEquals(orgname, zi.getHolder());
|
assertEquals(orgname, zi.getHolder());
|
||||||
assertEquals(number, zi.getForeignReference());
|
assertEquals(number, zi.getForeignReference());
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ public class ZF2ZInvoiceImporterTest extends ResourceCase {
|
|||||||
}
|
}
|
||||||
assertFalse(hasExceptions);
|
assertFalse(hasExceptions);
|
||||||
TransactionCalculator tc = new TransactionCalculator(invoice);
|
TransactionCalculator tc = new TransactionCalculator(invoice);
|
||||||
assertEquals(new BigDecimal("19.52"), tc.getGrandTotal());
|
assertEquals(new BigDecimal("18.92"), tc.getGrandTotal());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBasisQuantityImport() {
|
public void testBasisQuantityImport() {
|
||||||
|
|||||||
Reference in New Issue
Block a user