-
-
Notifications
You must be signed in to change notification settings - Fork 157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Charges on item level #568
base: master
Are you sure you want to change the base?
Changes from 1 commit
b74241f
2a8d448
34afa6a
74de80c
dde9eef
4181aed
8d2dc90
be2d072
dc4c06d
db72a80
85eaa89
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -646,89 +646,47 @@ public Invoice extractInto(Invoice zpp) throws XPathExpressionException, ParseEx | |
Item it = new Item(currentItemNode.getChildNodes(), recalcPrice); | ||
zpp.addItem(it); | ||
|
||
} | ||
|
||
// now handling base64 encoded attachments AttachmentBinaryObject=CII, EmbeddedDocumentBinaryObject=UBL | ||
xpr = xpath.compile("//*[local-name()=\"AttachmentBinaryObject\"]|//*[local-name()=\"EmbeddedDocumentBinaryObject\"]"); | ||
NodeList attachmentNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); | ||
for (int i = 0; i < attachmentNodes.getLength(); i++) { | ||
FileAttachment fa = new FileAttachment(attachmentNodes.item(i).getAttributes().getNamedItem("filename").getNodeValue(), attachmentNodes.item(i).getAttributes().getNamedItem("mimeCode").getNodeValue(), "Data", Base64.getDecoder().decode(XMLTools.trimOrNull(attachmentNodes.item(i)))); | ||
fileAttachments.add(fa); | ||
// filename = "Aufmass.png" mimeCode = "image/png" | ||
//EmbeddedDocumentBinaryObject cbc:EmbeddedDocumentBinaryObject mimeCode="image/png" filename="Aufmass.png" | ||
} | ||
|
||
// item level charges+allowances are not yet handled but a lower item price will | ||
// be read, | ||
// so the invoice remains arithmetically correct | ||
// -> parse document level charges+allowances | ||
xpr = xpath.compile("//*[local-name()=\"SpecifiedTradeAllowanceCharge\"]"); | ||
NodeList chargeNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); | ||
for (int i = 0; i < chargeNodes.getLength(); i++) { | ||
NodeList chargeNodeChilds = chargeNodes.item(i).getChildNodes(); | ||
boolean isCharge = true; | ||
String chargeAmount = null; | ||
String reason = null; | ||
String reasonCode = null; | ||
String taxPercent = null; | ||
for (int chargeChildIndex = 0; chargeChildIndex < chargeNodeChilds.getLength(); chargeChildIndex++) { | ||
String chargeChildName = chargeNodeChilds.item(chargeChildIndex).getLocalName(); | ||
if (chargeChildName != null) { | ||
|
||
if (chargeChildName.equals("ChargeIndicator")) { | ||
NodeList indicatorChilds = chargeNodeChilds.item(chargeChildIndex).getChildNodes(); | ||
for (int indicatorChildIndex = 0; indicatorChildIndex < indicatorChilds.getLength(); indicatorChildIndex++) { | ||
if ((indicatorChilds.item(indicatorChildIndex).getLocalName() != null) | ||
&& (indicatorChilds.item(indicatorChildIndex).getLocalName().equals("Indicator"))) { | ||
isCharge = XMLTools.trimOrNull(indicatorChilds.item(indicatorChildIndex)).equalsIgnoreCase("true"); | ||
} | ||
} | ||
} else if (chargeChildName.equals("ActualAmount")) { | ||
chargeAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex)); | ||
} else if (chargeChildName.equals("Reason")) { | ||
reason = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex)); | ||
} else if (chargeChildName.equals("ReasonCode")) { | ||
reasonCode = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex)); | ||
} else if (chargeChildName.equals("CategoryTradeTax")) { | ||
NodeList taxChilds = chargeNodeChilds.item(chargeChildIndex).getChildNodes(); | ||
for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) { | ||
String taxItemName = taxChilds.item(taxChildIndex).getLocalName(); | ||
if ((taxItemName != null) && (taxItemName.equals("RateApplicablePercent") || taxItemName.equals("ApplicablePercent"))) { | ||
taxPercent = XMLTools.trimOrNull(taxChilds.item(taxChildIndex)); | ||
} | ||
} | ||
} | ||
xpr = xpath.compile(".//*[local-name()=\"SpecifiedTradeAllowanceCharge\"]"); | ||
NodeList chargeNodes = (NodeList) xpr.evaluate(currentItemNode, XPathConstants.NODESET); | ||
for (int k = 0; k < chargeNodes.getLength(); k++) { | ||
NodeList chargeNodeChilds = chargeNodes.item(k).getChildNodes(); | ||
Charge c = parseCharge(chargeNodeChilds, false); | ||
if (c instanceof Allowance) { | ||
it.addTotalAllowance(c); | ||
} else { | ||
it.addCharge(c); | ||
} | ||
} | ||
} | ||
} | ||
|
||
if (isCharge) { | ||
Charge c = new Charge(new BigDecimal(chargeAmount)); | ||
if (reason != null) { | ||
c.setReason(reason); | ||
} | ||
if (reasonCode != null) { | ||
c.setReasonCode(reasonCode); | ||
} | ||
if (taxPercent != null) { | ||
c.setTaxPercent(new BigDecimal(taxPercent)); | ||
} | ||
zpp.addCharge(c); | ||
} else { | ||
Allowance a = new Allowance(new BigDecimal(chargeAmount)); | ||
if (reason != null) { | ||
a.setReason(reason); | ||
} | ||
if (reasonCode != null) { | ||
a.setReasonCode(reasonCode); | ||
} | ||
if (taxPercent != null) { | ||
a.setTaxPercent(new BigDecimal(taxPercent)); | ||
} | ||
zpp.addAllowance(a); | ||
} | ||
|
||
// now handling base64 encoded attachments AttachmentBinaryObject=CII, EmbeddedDocumentBinaryObject=UBL | ||
xpr = xpath.compile("//*[local-name()=\"AttachmentBinaryObject\"]|//*[local-name()=\"EmbeddedDocumentBinaryObject\"]"); | ||
NodeList attachmentNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); | ||
for (int i = 0; i < attachmentNodes.getLength(); i++) { | ||
FileAttachment fa = new FileAttachment(attachmentNodes.item(i).getAttributes().getNamedItem("filename").getNodeValue(), attachmentNodes.item(i).getAttributes().getNamedItem("mimeCode").getNodeValue(), "Data", Base64.getDecoder().decode(XMLTools.trimOrNull(attachmentNodes.item(i)))); | ||
fileAttachments.add(fa); | ||
// filename = "Aufmass.png" mimeCode = "image/png" | ||
//EmbeddedDocumentBinaryObject cbc:EmbeddedDocumentBinaryObject mimeCode="image/png" filename="Aufmass.png" | ||
} | ||
|
||
// item level charges+allowances are not yet handled but a lower item price will | ||
// be read, | ||
// so the invoice remains arithmetically correct | ||
// -> parse document level charges+allowances | ||
xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]//*[local-name()=\"SpecifiedTradeAllowanceCharge\"]"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added ApplicableHeaderTradeSettlement because we only want to have header level charges here |
||
NodeList chargeNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); | ||
for (int i = 0; i < chargeNodes.getLength(); i++) { | ||
NodeList chargeNodeChilds = chargeNodes.item(i).getChildNodes(); | ||
Charge c = parseCharge(chargeNodeChilds, true); | ||
if (c instanceof Allowance) { | ||
zpp.addAllowance(c); | ||
} else { | ||
zpp.addCharge(c); | ||
} | ||
} | ||
|
||
if (zpp.getZFItems() != null && zpp.getZFItems().length > 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was previously only done for if (nodes.getLength() != 0) |
||
TransactionCalculator tc = new TransactionCalculator(zpp); | ||
String expectedStringTotalGross = tc.getGrandTotal() | ||
.subtract(Objects.requireNonNullElse(zpp.getTotalPrepaidAmount(), BigDecimal.ZERO)).toPlainString(); | ||
|
@@ -749,6 +707,72 @@ public Invoice extractInto(Invoice zpp) throws XPathExpressionException, ParseEx | |
|
||
} | ||
|
||
/** | ||
* @param isHeader true = header level charge, false = item level charge | ||
*/ | ||
private Charge parseCharge(NodeList chargeNodeChilds, boolean isHeader) { | ||
boolean isCharge = true; | ||
String chargeAmount = null; | ||
String reason = null; | ||
String reasonCode = null; | ||
String taxPercent = null; | ||
for (int chargeChildIndex = 0; chargeChildIndex < chargeNodeChilds.getLength(); chargeChildIndex++) { | ||
String chargeChildName = chargeNodeChilds.item(chargeChildIndex).getLocalName(); | ||
if (chargeChildName != null) { | ||
|
||
if (chargeChildName.equals("ChargeIndicator")) { | ||
NodeList indicatorChilds = chargeNodeChilds.item(chargeChildIndex).getChildNodes(); | ||
for (int indicatorChildIndex = 0; indicatorChildIndex < indicatorChilds.getLength(); indicatorChildIndex++) { | ||
if ((indicatorChilds.item(indicatorChildIndex).getLocalName() != null) | ||
&& (indicatorChilds.item(indicatorChildIndex).getLocalName().equals("Indicator"))) { | ||
isCharge = XMLTools.trimOrNull(indicatorChilds.item(indicatorChildIndex)).equalsIgnoreCase("true"); | ||
} | ||
} | ||
} else if (chargeChildName.equals("ActualAmount")) { | ||
chargeAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex)); | ||
} else if (chargeChildName.equals("Reason")) { | ||
reason = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex)); | ||
} else if (chargeChildName.equals("ReasonCode")) { | ||
reasonCode = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex)); | ||
} else if (isHeader && chargeChildName.equals("CategoryTradeTax")) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added condition isHeader |
||
NodeList taxChilds = chargeNodeChilds.item(chargeChildIndex).getChildNodes(); | ||
for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) { | ||
String taxItemName = taxChilds.item(taxChildIndex).getLocalName(); | ||
if ((taxItemName != null) && (taxItemName.equals("RateApplicablePercent") || taxItemName.equals("ApplicablePercent"))) { | ||
taxPercent = XMLTools.trimOrNull(taxChilds.item(taxChildIndex)); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
if (isCharge) { | ||
Charge c = new Charge(new BigDecimal(chargeAmount)); | ||
if (reason != null) { | ||
c.setReason(reason); | ||
} | ||
if (reasonCode != null) { | ||
c.setReasonCode(reasonCode); | ||
} | ||
if (taxPercent != null) { | ||
c.setTaxPercent(new BigDecimal(taxPercent)); | ||
} | ||
return c; | ||
} else { | ||
Allowance a = new Allowance(new BigDecimal(chargeAmount)); | ||
if (reason != null) { | ||
a.setReason(reason); | ||
} | ||
if (reasonCode != null) { | ||
a.setReasonCode(reasonCode); | ||
} | ||
if (taxPercent != null) { | ||
a.setTaxPercent(new BigDecimal(taxPercent)); | ||
} | ||
return a; | ||
} | ||
} | ||
|
||
protected Document getDocument() { | ||
return document; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
basically moved everything below to new method parseCharge() without much changes. Ignoring whitespaces should make this diff easier to parse (?w=1)