Skip to content

Commit

Permalink
support item level allowances
Browse files Browse the repository at this point in the history
  • Loading branch information
Jochen Stärk authored and Jochen Stärk committed Sep 17, 2020
1 parent e227608 commit 060aa79
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -594,9 +594,9 @@ private static void performVisualization(String sourceName, String outName) {
System.out.println("ZUGFeRD XML source set to " + sourceName);
}
if (outName == null) {
outName = getFilenameFromUser("ZUGFeRD 2.0 HTML target", "factur-x.html", "html", false, true);
outName = getFilenameFromUser("HTML target file", "factur-x.html", "html", false, true);
} else {
System.out.println("ZUGFeRD 1.0 XML source set to " + outName);
System.out.println("HTML target set to " + outName);
}

// Verify params
Expand Down
3 changes: 2 additions & 1 deletion doc/development_documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ larger) and a commandline application using the latter
library.

The validator component embeds VeraPDF, a open-source
PDF/A-validator, via maven dependency and uses ph-schematron
PDF/A-validator, via maven dependency and uses standard java
checks against schema and ph-schematron for checks against the schematron
to validate the XML part of the invoices.

![architecture of the validator](ZUV-Architektur.svg "Graph of the architecture of the validator component")
Expand Down
5 changes: 5 additions & 0 deletions library/src/main/java/org/mustangproject/Allowance.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,9 @@ public Allowance(BigDecimal totalAmount, BigDecimal taxPercent, String reason, S
super(totalAmount, taxPercent, reason, categoryCode);

}

@Override
public boolean isCharge() {
return false;
}
}
5 changes: 5 additions & 0 deletions library/src/main/java/org/mustangproject/Charge.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ public BigDecimal getTaxPercent() {
return taxPercent;
}

@Override
public boolean isCharge() {
return true;
}


public Charge setCategoryCode(String categoryCode) {
this.categoryCode = categoryCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ default String getCategoryCode() {
return TaxCategoryCodeTypeConstants.STANDARDRATE;
}

public boolean isCharge();
}
25 changes: 22 additions & 3 deletions library/src/main/java/org/mustangproject/ZUGFeRD/LineCalc.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,34 @@

public class LineCalc {
private BigDecimal totalGross;
private BigDecimal price;
private BigDecimal priceGross;
private BigDecimal itemTotalNetAmount;
private BigDecimal itemTotalVATAmount;
private BigDecimal allowance=new BigDecimal(0);

public LineCalc(IZUGFeRDExportableItem currentItem) {

if (currentItem.getItemAllowances()!=null && currentItem.getItemAllowances().length>0) {
for (IZUGFeRDAllowanceCharge allowance:currentItem.getItemAllowances()) {
addAllowance(allowance.getTotalAmount());
}
}
BigDecimal multiplicator = currentItem.getProduct().getVATPercent().divide(new BigDecimal(100))
.add(new BigDecimal(1));
priceGross = currentItem.getPrice(); // see https://github.com/ZUGFeRD/mustangproject/issues/159
totalGross = currentItem.getQuantity().multiply(currentItem.getPrice()).divide(currentItem.getBasisQuantity())
price = priceGross.subtract(allowance);
totalGross = currentItem.getQuantity().multiply(getPrice()).divide(currentItem.getBasisQuantity())
.multiply(multiplicator);
itemTotalNetAmount = currentItem.getQuantity().multiply(currentItem.getPrice()).divide(currentItem.getBasisQuantity())
itemTotalNetAmount = currentItem.getQuantity().multiply(getPrice()).divide(currentItem.getBasisQuantity())
.setScale(2, BigDecimal.ROUND_HALF_UP);
itemTotalVATAmount = totalGross.subtract(itemTotalNetAmount);


}

public BigDecimal getPrice() {
return price;
}

public BigDecimal getItemTotalNetAmount() {
Expand All @@ -28,12 +43,16 @@ public BigDecimal getItemTotalVATAmount() {
}

public BigDecimal getItemTotalGrossAmount() {
return itemTotalVATAmount;
return itemTotalNetAmount;
}

public BigDecimal getPriceGross() {
return priceGross;
}
public void addAllowance(BigDecimal b) {
allowance=b;

}


}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.dom4j.DocumentHelper;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.mustangproject.Charge;
import org.mustangproject.XMLTools;

public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
Expand Down Expand Up @@ -121,7 +122,7 @@ private BigDecimal getTotal() {
BigDecimal res = new BigDecimal(0);
for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) {
LineCalc lc = new LineCalc(currentItem);
res = res.add(lc.getItemTotalNetAmount());
res = res.add(lc.getItemTotalGrossAmount());
}
return res;
}
Expand Down Expand Up @@ -286,6 +287,19 @@ public void generateXML(IExportableTransaction trans) {
xml = xml + " <ram:BuyerAssignedID>"
+ XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "</ram:BuyerAssignedID>\n";
}

String allowanceStr=" <ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit())
+ "\">" + quantityFormat(currentItem.getBasisQuantity()) +"</ram:BasisQuantity>\n";
if (currentItem.getItemAllowances()!=null && currentItem.getItemAllowances().length>0) {
for (IZUGFeRDAllowanceCharge allowance:currentItem.getItemAllowances()) {
if (allowance.isCharge()) {
throw new RuntimeException("Item level charges are not yet implemented");
} else {
allowanceStr= "<ram:AppliedTradeAllowanceCharge><ram:ChargeIndicator><udt:Indicator>false</udt:Indicator></ram:ChargeIndicator><ram:ActualAmount>"+priceFormat(allowance.getTotalAmount())+"</ram:ActualAmount></ram:AppliedTradeAllowanceCharge>";
}
}
}

xml = xml + " <ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>\n" //$NON-NLS-2$
+ " <ram:Description>" + XMLTools.encodeXML(currentItem.getProduct().getDescription())
+ "</ram:Description>\n"
Expand All @@ -295,16 +309,15 @@ public void generateXML(IExportableTransaction trans) {
+ " <ram:GrossPriceProductTradePrice>\n"
+ " <ram:ChargeAmount>" + priceFormat(lc.getPriceGross())
+ "</ram:ChargeAmount>\n" //currencyID=\"EUR\"
+ " <ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit())
+ "\">" + quantityFormat(currentItem.getBasisQuantity()) +"</ram:BasisQuantity>\n"
+ allowanceStr
// + " <AppliedTradeAllowanceCharge>\n"
// + " <ChargeIndicator>false</ChargeIndicator>\n"
// + " <ActualAmount currencyID=\"EUR\">0.6667</ActualAmount>\n"
// + " <Reason>Rabatt</Reason>\n"
// + " </AppliedTradeAllowanceCharge>\n"
+ " </ram:GrossPriceProductTradePrice>\n"
+ " <ram:NetPriceProductTradePrice>\n"
+ " <ram:ChargeAmount>" + priceFormat(currentItem.getPrice())
+ " <ram:ChargeAmount>" + priceFormat(lc.getPrice())
+ "</ram:ChargeAmount>\n" // currencyID=\"EUR\"
+ " <ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit())
+ "\">" + quantityFormat(currentItem.getBasisQuantity()) +"</ram:BasisQuantity>\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class IZUGFeRDAllowanceChargeImpl implements IZUGFeRDAllowanceCharge {
private BigDecimal totalAmount;
private String reason;
private BigDecimal taxPercent;
boolean isCharge=true;

@Override
public BigDecimal getTotalAmount() {
Expand All @@ -40,6 +41,16 @@ public BigDecimal getTaxPercent() {
return taxPercent;
}

@Override
public boolean isCharge() {
return isCharge;
}

public IZUGFeRDAllowanceChargeImpl setAllowance() {
isCharge = false;
return this;
}

public IZUGFeRDAllowanceChargeImpl setTotalAmount(BigDecimal totalAmount) {
this.totalAmount = totalAmount;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,9 @@ public void testItemChargesAllowancesExport() {
.load(SOURCE_PDF)) {

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)).addCharge(new Charge(new BigDecimal(0.1),new BigDecimal(0), "","K")))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance(new BigDecimal(0.07),new BigDecimal(0), "","K")))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance(new BigDecimal(0.07),new BigDecimal(0), "","K")).addCharge(new Charge(new BigDecimal(0.1),new BigDecimal(0), "","K")))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance(new BigDecimal(0.1),new BigDecimal(0), "","K")))
.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)), amount, new BigDecimal(1.0)))

);
String theXML = new String(ze.getProvider().getXML());
Expand All @@ -154,7 +154,7 @@ public void testItemChargesAllowancesExport() {
assertTrue(zi.getUTF8().contains("EUR"));

// Reading ZUGFeRD
assertEquals("10.71", zi.getAmount());
assertEquals("10.59", zi.getAmount());
assertEquals(zi.getHolder(), orgname);
assertEquals(zi.getForeignReference(), number);
try {
Expand Down

0 comments on commit 060aa79

Please sign in to comment.