Updated ZUGFeRDImporter.java -> created getLineItemList() for reading LineItems from ZUGFeRD XML

Added Test

Added fields Item.java -> tax, grossPrice, lineTotalAmount, id, sellerAssignedID and buyerAssignedID, all with Getter&Setter

Added field in VATAmount.java -> applicablePercent with Getter&Setter
This commit is contained in:
Alexander Berndt
2020-05-28 15:03:27 +02:00
parent 566ead3c67
commit 02a6958865
4 changed files with 275 additions and 7 deletions

View File

@@ -7,7 +7,8 @@ import org.mustangproject.ZUGFeRD.IZUGFeRDExportableProduct;
import java.math.BigDecimal;
public class Item implements IZUGFeRDExportableItem {
protected BigDecimal price, quantity;
protected BigDecimal price, quantity, tax, grossPrice, lineTotalAmount;
protected String id, sellerAssignedID, buyerAssignedID;
protected Product product;
public Item(Product product, BigDecimal price, BigDecimal quantity) {
@@ -16,6 +17,60 @@ public class Item implements IZUGFeRDExportableItem {
this.product = product;
}
public BigDecimal getLineTotalAmount() {
return lineTotalAmount;
}
public Item setLineTotalAmount(BigDecimal lineTotalAmount) {
this.lineTotalAmount = lineTotalAmount;
return this;
}
public String getSellerAssignedID() {
return sellerAssignedID;
}
public Item setSellerAssignedID(String sellerAssignedID) {
this.sellerAssignedID = sellerAssignedID;
return this;
}
public String getBuyerAssignedID() {
return buyerAssignedID;
}
public Item setBuyerAssignedID(String buyerAssignedID) {
this.buyerAssignedID = buyerAssignedID;
return this;
}
public BigDecimal getGrossPrice() {
return grossPrice;
}
public Item setGrossPrice(BigDecimal grossPrice) {
this.grossPrice = grossPrice;
return this;
}
public BigDecimal getTax() {
return tax;
}
public Item setTax(BigDecimal tax) {
this.tax = tax;
return this;
}
public Item setId(String id) {
this.id = id;
return this;
}
public String getId() {
return id;
}
@Override
public BigDecimal getPrice() {
return price;
@@ -26,6 +81,8 @@ public class Item implements IZUGFeRDExportableItem {
return this;
}
@Override
public BigDecimal getQuantity() {
return quantity;

View File

@@ -38,10 +38,18 @@ public class VATAmount {
this.categoryCode = categoryCode;
}
BigDecimal basis, calculated;
BigDecimal basis, calculated, applicablePercent;
String categoryCode;
public BigDecimal getApplicablePercent() {
return applicablePercent;
}
public void setApplicablePercent(BigDecimal applicablePercent) {
this.applicablePercent = applicablePercent;
}
public BigDecimal getBasis() {
return basis;
}

View File

@@ -17,13 +17,11 @@ package org.mustangproject.ZUGFeRD;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -534,6 +532,165 @@ public class ZUGFeRDImporter {
return address;
}
/**
* returns a list of LineItems
* @return a List of LineItem instances
*/
public List<Item> getLineItemList() {
List<Node> nodeList = getLineItemNodes();
List<Item> lineItemList = new ArrayList<>();
for (Node n: nodeList
) {
Item lineItem = new Item(null, null, null);
lineItem.setProduct(new Product(null,null,null,null));
NodeList nl = n.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node nn = nl.item(i);
Node node = null;
switch (nn.getNodeName()) {
case "ram:SpecifiedLineTradeAgreement":
case "ram:SpecifiedSupplyChainTradeAgreement":
node = getNodeByName(nn.getChildNodes(), "ram:NetPriceProductTradePrice");
if (node != null) {
node = getNodeByName(node.getChildNodes(), "ram:ChargeAmount");
lineItem.setPrice(tryBigDecimal(getNodeValue(node)));
}
node = getNodeByName(nn.getChildNodes(), "ram:GrossPriceProductTradePrice");
if (node != null) {
node = getNodeByName(node.getChildNodes(), "ram:ChargeAmount");
lineItem.setGrossPrice(tryBigDecimal(getNodeValue(node)));
}
break;
case "ram:AssociatedDocumentLineDocument":
node = getNodeByName(nn.getChildNodes(), "ram:LineID");
lineItem.setId(getNodeValue(node));
break;
case "ram:SpecifiedTradeProduct":
node = getNodeByName(nn.getChildNodes(), "ram:SellerAssignedID");
lineItem.setSellerAssignedID(getNodeValue(node));
node = getNodeByName(nn.getChildNodes(), "ram:BuyerAssignedID");
lineItem.setBuyerAssignedID(getNodeValue(node));
node = getNodeByName(nn.getChildNodes(), "ram:Name");
lineItem.product.setName(getNodeValue(node));
node = getNodeByName(nn.getChildNodes(), "ram:Description");
lineItem.product.setDescription(getNodeValue(node));
break;
case "ram:SpecifiedLineTradeDelivery":
case "ram:SpecifiedSupplyChainTradeDelivery":
node = getNodeByName(nn.getChildNodes(), "ram:BilledQuantity");
lineItem.setQuantity(tryBigDecimal(getNodeValue(node)));
break;
case "ram:SpecifiedLineTradeSettlement":
node = getNodeByName(nn.getChildNodes(), "ram:ApplicableTradeTax");
if (node != null) {
node = getNodeByName(node.getChildNodes(), "ram:RateApplicablePercent");
lineItem.product.setVATPercent(tryBigDecimal(getNodeValue(node)));
}
node = getNodeByName(nn.getChildNodes(), "ram:ApplicableTradeTax");
if (node != null) {
node = getNodeByName(node.getChildNodes(), "ram:CalculatedAmount");
lineItem.setTax(tryBigDecimal(getNodeValue(node)));
}
node = getNodeByName(nn.getChildNodes(), "ram:SpecifiedTradeSettlementLineMonetarySummation");
if (node != null) {
node = getNodeByName(node.getChildNodes(), "ram:LineTotalAmount");
lineItem.setLineTotalAmount(tryBigDecimal(getNodeValue(node)));
}
break;
case "ram:SpecifiedSupplyChainTradeSettlement":
//ZF 1!
node = getNodeByName(nn.getChildNodes(), "ram:ApplicableTradeTax");
if (node != null) {
node = getNodeByName(node.getChildNodes(), "ram:ApplicablePercent");
lineItem.product.setVATPercent(tryBigDecimal(getNodeValue(node)));
}
node = getNodeByName(nn.getChildNodes(), "ram:ApplicableTradeTax");
if (node != null) {
node = getNodeByName(node.getChildNodes(), "ram:CalculatedAmount");
lineItem.setTax(tryBigDecimal(getNodeValue(node)));
}
node = getNodeByName(nn.getChildNodes(), "ram:SpecifiedTradeSettlementMonetarySummation");
if (node != null) {
node = getNodeByName(node.getChildNodes(), "ram:LineTotalAmount");
lineItem.setLineTotalAmount(tryBigDecimal(getNodeValue(node)));
}
break;
}
}
lineItemList.add(lineItem);
}
return lineItemList;
}
/**
* returns a List of LineItem Nodes from ZUGFeRD XML
* @return a List of Node instances
*/
public List<Node> getLineItemNodes() {
List<Node> lineItemNodes = new ArrayList<>();
NodeList nl = null;
try {
if (getVersion() == 1) {
nl = getNodeListByPath("//CrossIndustryDocument//SpecifiedSupplyChainTradeTransaction//IncludedSupplyChainTradeLineItem");
} else {
nl = getNodeListByPath("//CrossIndustryInvoice//SupplyChainTradeTransaction//IncludedSupplyChainTradeLineItem");
}
} catch (Exception e) {
e.printStackTrace();
}
for (int i = 0; i < nl.getLength(); i++) {
Node n = nl.item(i);
lineItemNodes.add(n);
}
return lineItemNodes;
}
/**
* Returns a node, found by name. If more nodes with the same name are present, the first occurence will be returned
* @param nl - A NodeList which may contains the searched node
* @param name The nodes name
* @return a Node or null, if nothing is found
*/
private Node getNodeByName(NodeList nl, String name) {
for (int i = 0; i < nl.getLength(); i++) {
if (nl.item(i).getNodeName() == name) {
return nl.item(i);
} else if (nl.item(i).getChildNodes().getLength() > 0) {
Node node = getNodeByName(nl.item(i).getChildNodes(), name);
if (node != null) {
return node;
}
}
}
return null;
}
/**
* Get a NodeList by providing an path
* @param path a compliable Path
* @return a Nodelist or null, if an error occurs
*/
public NodeList getNodeListByPath(String path) {
XPathFactory xpathFact = XPathFactory.newInstance();
@@ -549,4 +706,36 @@ public class ZUGFeRDImporter {
}
}
/**
* returns the value of an node
* @param node the Node to get the value from
* @return A String or empty String, if no value was found
*/
private String getNodeValue(Node node) {
if (node != null) {
if (node.getFirstChild() != null) {
return node.getFirstChild().getNodeValue();
}
}
return "";
}
/**
* tries to convert an String to BigDecimal.
* @param nodeValue The value as String
* @return a BigDecimal with the value provides as String or a BigDecimal with value 0.00 if an error occurs
*/
private BigDecimal tryBigDecimal(String nodeValue) {
try {
return new BigDecimal(nodeValue);
} catch (Exception e) {
e.printStackTrace();
try {
return new BigDecimal(Float.valueOf(nodeValue));
} catch (Exception ex) {
ex.printStackTrace();
return new BigDecimal("0.00");
}
}
}
}

View File

@@ -32,6 +32,7 @@ import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ZF2Test extends MustangReaderTestCase {
@@ -221,7 +222,20 @@ public class ZF2Test extends MustangReaderTestCase {
assertEquals(zi.getSellerTradePartyAddress().getCountrySubDivisionName(), null);
assertEquals(zi.getSellerTradePartyAddress().getCountryID(), "DE");
assertEquals(zi.getSellerTradePartyAddress().getCityName(), "Stadthausen");
List<org.mustangproject.ZUGFeRD.Item> li = zi.getLineItemList();
assertEquals(zi.getLineItemList().get(0).getId().toString(), "1");
assertEquals(zi.getLineItemList().get(0).getBuyerAssignedID(), "");
assertEquals(zi.getLineItemList().get(0).getSellerAssignedID(), "");
assertEquals(zi.getLineItemList().get(0).getLineTotalAmount().toString(), "160.00");
assertEquals(zi.getLineItemList().get(0).getQuantity().toString(), "1.0000");
assertEquals(zi.getLineItemList().get(0).getGrossPrice().toString(), "171.2000");
assertEquals(zi.getLineItemList().get(0).getBuyerAssignedID(), "");
assertEquals(zi.getLineItemList().get(0).product.getVATPercent().toString(), "7.00");
assertEquals(zi.getLineItemList().get(0).product.getName(), "Künstlerische Gestaltung (Stunde): Einer Beispielrechnung");
assertEquals(zi.getLineItemList().get(0).product.getDescription(), "");
int i = 1;
try {
assertEquals(zi.getVersion(), 2);
} catch (Exception e) {