diff --git a/library/src/main/java/org/mustangproject/Invoice.java b/library/src/main/java/org/mustangproject/Invoice.java index 038020a4..746c74b0 100644 --- a/library/src/main/java/org/mustangproject/Invoice.java +++ b/library/src/main/java/org/mustangproject/Invoice.java @@ -20,15 +20,21 @@ */ package org.mustangproject; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import org.mustangproject.ZUGFeRD.*; -import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants; - import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; +import org.mustangproject.ZUGFeRD.IExportableTransaction; +import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge; +import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem; +import org.mustangproject.ZUGFeRD.IZUGFeRDExportableTradeParty; +import org.mustangproject.ZUGFeRD.IZUGFeRDPaymentTerms; +import org.mustangproject.ZUGFeRD.IZUGFeRDTradeSettlement; +import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + /*** * An invoice, with fluent setters * @see IExportableTransaction if you want to implement an interface instead @@ -39,6 +45,8 @@ public class Invoice implements IExportableTransaction { protected String documentName = null, documentCode = null, number = null, ownOrganisationFullPlaintextInfo = null, referenceNumber = null, shipToOrganisationID = null, shipToOrganisationName = null, shipToStreet = null, shipToZIP = null, shipToLocation = null, shipToCountry = null, buyerOrderReferencedDocumentID = null, invoiceReferencedDocumentID = null, buyerOrderReferencedDocumentIssueDateTime = null, ownForeignOrganisationID = null, ownOrganisationName = null, currency = null, paymentTermDescription = null; protected Date issueDate = null, dueDate = null, deliveryDate = null; protected BigDecimal totalPrepaidAmount = null; + protected BigDecimal grandTotalAmount = null; + protected BigDecimal duePayableAmount = null; protected TradeParty sender = null, recipient = null, deliveryAddress = null; @JsonDeserialize(contentAs=Item.class) protected ArrayList ZFItems = null; @@ -433,6 +441,24 @@ public class Invoice implements IExportableTransaction { return this; } + public BigDecimal getGrandTotalAmount() { + return grandTotalAmount; + } + + public Invoice setGrandTotalAmount(BigDecimal grandTotalAmount) { + this.grandTotalAmount = grandTotalAmount; + return this; + } + + public BigDecimal getDuePayableAmount() { + return duePayableAmount; + } + + public Invoice setDuePayableAmount(BigDecimal duePayableAmount) { + this.duePayableAmount = duePayableAmount; + return this; + } + @Override public IZUGFeRDExportableTradeParty getSender() { return sender; @@ -445,6 +471,7 @@ public class Invoice implements IExportableTransaction { * @param ownContact the sender contact * @return fluent setter */ + @Deprecated public Invoice setOwnContact(Contact ownContact) { this.sender.setContact(ownContact); return this; @@ -689,4 +716,5 @@ public class Invoice implements IExportableTransaction { this.specifiedProcuringProjectName = specifiedProcuringProjectName; return this; } + } diff --git a/library/src/main/java/org/mustangproject/TradeParty.java b/library/src/main/java/org/mustangproject/TradeParty.java index 4399d726..396ae36a 100644 --- a/library/src/main/java/org/mustangproject/TradeParty.java +++ b/library/src/main/java/org/mustangproject/TradeParty.java @@ -5,11 +5,16 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import org.mustangproject.ZUGFeRD.*; +import org.mustangproject.ZUGFeRD.IZUGFeRDExportableContact; +import org.mustangproject.ZUGFeRD.IZUGFeRDExportableTradeParty; +import org.mustangproject.ZUGFeRD.IZUGFeRDLegalOrganisation; +import org.mustangproject.ZUGFeRD.IZUGFeRDTradeSettlement; +import org.mustangproject.ZUGFeRD.IZUGFeRDTradeSettlementDebit; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + /*** * A organisation, i.e. usually a company */ @@ -136,11 +141,17 @@ public class TradeParty implements IZUGFeRDExportableTradeParty { if (taxChilds.item(taxChildIndex).getLocalName() != null) { if ((taxChilds.item(taxChildIndex).getLocalName().equals("ID"))) { if (taxChilds.item(taxChildIndex).getAttributes().getNamedItem("schemeID") != null) { - if (taxChilds.item(taxChildIndex).getAttributes().getNamedItem("schemeID").getNodeValue().equals("VA")) { - setVATID(taxChilds.item(taxChildIndex).getFirstChild().getNodeValue()); - } - if (taxChilds.item(taxChildIndex).getAttributes().getNamedItem("schemeID").getNodeValue().equals("FC")) { - setTaxID(taxChilds.item(taxChildIndex).getFirstChild().getNodeValue()); + Node firstChild = taxChilds.item(taxChildIndex).getFirstChild(); + if (firstChild != null) + { + if (taxChilds.item(taxChildIndex).getAttributes() + .getNamedItem("schemeID").getNodeValue().equals("VA")) { + setVATID(firstChild.getNodeValue()); + } + if (taxChilds.item(taxChildIndex).getAttributes() + .getNamedItem("schemeID").getNodeValue().equals("FC")) { + setTaxID(firstChild.getNodeValue()); + } } } } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java index 18a512af..c88ecfd8 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java @@ -17,6 +17,7 @@ * *********************************************************************** */ package org.mustangproject.ZUGFeRD; + /** * Mustangproject's ZUGFeRD implementation * Neccessary interface for ZUGFeRD exporter @@ -26,7 +27,6 @@ package org.mustangproject.ZUGFeRD; * @author jstaerk * */ - import java.math.BigDecimal; import java.util.Date; @@ -34,11 +34,12 @@ import org.mustangproject.FileAttachment; import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants; /*** - * the interface of an transaction, e.g. an invoice, you want to create xml (potentially to be added to a PDF) - * for + * the interface of an transaction, e.g. an invoice, you want to create xml + * (potentially to be added to a PDF) for + * * @see org.mustangproject.Invoice */ -public interface IExportableTransaction { +public interface IExportableTransaction { /** * appears in /rsm:CrossIndustryDocument/rsm:HeaderExchangedDocument/ram:Name @@ -49,7 +50,6 @@ public interface IExportableTransaction { return "RECHNUNG"; } - /** * * @@ -59,7 +59,6 @@ public interface IExportableTransaction { return DocumentCodeTypeConstants.INVOICE; } - /** * Number, typically invoice number of the invoice * @@ -69,7 +68,6 @@ public interface IExportableTransaction { return null; } - /** * the date when the invoice was created * @@ -79,19 +77,20 @@ public interface IExportableTransaction { return null; } - /** - * this should be the full sender institution name, details, manager and tax registration. It is one of the few functions which may return null. e.g. + * this should be the full sender institution name, details, manager and tax + * registration. It is one of the few functions which may return null. e.g. *

- * Lieferant GmbH Lieferantenstraße 20 80333 München Deutschland Geschäftsführer: Hans Muster Handelsregisternummer: H A 123 + * Lieferant GmbH Lieferantenstraße 20 80333 München Deutschland + * Geschäftsführer: Hans Muster Handelsregisternummer: H A 123 * - * @return null or full sender institution name, details, manager and tax registration + * @return null or full sender institution name, details, manager and tax + * registration */ default String getOwnOrganisationFullPlaintextInfo() { return null; } - /** * when the invoice is to be paid * @@ -105,7 +104,6 @@ public interface IExportableTransaction { return null; } - /** * the sender of the invoice * @@ -115,10 +113,8 @@ public interface IExportableTransaction { return null; } - /** - * subject of the document e.g. invoice and order - * number as human readable text + * subject of the document e.g. invoice and order number as human readable text * * @return string with document subject */ @@ -130,20 +126,16 @@ public interface IExportableTransaction { return null; } - default IZUGFeRDAllowanceCharge[] getZFCharges() { return null; } - default IZUGFeRDAllowanceCharge[] getZFLogisticsServiceCharges() { return null; } - IZUGFeRDExportableItem[] getZFItems(); - /** * the recipient * @@ -151,9 +143,9 @@ public interface IExportableTransaction { */ IZUGFeRDExportableTradeParty getRecipient(); - /** * the creditors payment informations + * * @deprecated use getTradeSettlement * @return an array of IZUGFeRDTradeSettlementPayment */ @@ -161,6 +153,7 @@ public interface IExportableTransaction { default IZUGFeRDTradeSettlementPayment[] getTradeSettlementPayment() { return null; } + /** * the payment information for any payment means * @@ -170,35 +163,32 @@ public interface IExportableTransaction { return null; } - /** * Tax ID (not VAT ID) of the sender * * @return Tax ID (not VAT ID) of the sender */ default String getOwnTaxID() { - if (getSender()!=null) { + if (getSender() != null) { return getSender().getTaxID(); } else { return null; } } - /** * VAT ID (Umsatzsteueridentifikationsnummer) of the sender * * @return VAT ID (Umsatzsteueridentifikationsnummer) of the sender */ default String getOwnVATID() { - if (getSender()!=null) { + if (getSender() != null) { return getSender().getVATID(); } else { return null; } } - /** * supplier identification assigned by the costumer * @@ -208,42 +198,39 @@ public interface IExportableTransaction { return null; } - /** * own name * * @return the sender's organisation name */ default String getOwnOrganisationName() { - if (getSender()!=null) { + if (getSender() != null) { return getSender().getName(); } else { return null; } } - /** * own street address * * @return sender street address */ default String getOwnStreet() { - if (getSender()!=null) { + if (getSender() != null) { return getSender().getStreet(); } else { return null; } } - /** * own street postal code * * @return sender postal code */ default String getOwnZIP() { - if (getSender()!=null) { + if (getSender() != null) { return getSender().getZIP(); } else { return null; @@ -251,14 +238,13 @@ public interface IExportableTransaction { } - /** * own city * * @return the invoice sender's city */ default String getOwnLocation() { - if (getSender()!=null) { + if (getSender() != null) { return getSender().getLocation(); } else { return null; @@ -266,14 +252,13 @@ public interface IExportableTransaction { } - /** * own two digit country code * * @return the invoice senders two character country iso code */ default String getOwnCountry() { - if (getSender()!=null) { + if (getSender() != null) { return getSender().getCountry(); } else { return null; @@ -281,7 +266,6 @@ public interface IExportableTransaction { } - /** * get delivery date * @@ -289,7 +273,6 @@ public interface IExportableTransaction { */ Date getDeliveryDate(); - /** * get main invoice currency used on the invoice * @@ -299,7 +282,6 @@ public interface IExportableTransaction { return "EUR"; } - /** * get payment term descriptional text e.g. Bis zum 22.10.2015 ohne Abzug * @@ -329,7 +311,8 @@ public interface IExportableTransaction { } /** - * get reference document number typically used for Invoice Corrections Will be added as IncludedNote in comfort profile + * get reference document number typically used for Invoice Corrections Will be + * added as IncludedNote in comfort profile * * @return the ID of the document this document refers to */ @@ -337,9 +320,9 @@ public interface IExportableTransaction { return null; } - /** - * consignee identification (identification of the organisation the goods are shipped to [assigned by the costumer]) + * consignee identification (identification of the organisation the goods are + * shipped to [assigned by the costumer]) * * @return the sender's identification */ @@ -347,7 +330,6 @@ public interface IExportableTransaction { return null; } - /** * consignee name (name of the organisation the goods are shipped to) * @@ -357,9 +339,9 @@ public interface IExportableTransaction { return null; } - /** - * consignee street address (street of the organisation the goods are shipped to) + * consignee street address (street of the organisation the goods are shipped + * to) * * @return consignee street address */ @@ -367,9 +349,9 @@ public interface IExportableTransaction { return null; } - /** - * consignee street postal code (postal code of the organisation the goods are shipped to) + * consignee street postal code (postal code of the organisation the goods are + * shipped to) * * @return consignee postal code */ @@ -377,7 +359,6 @@ public interface IExportableTransaction { return null; } - /** * consignee city (city of the organisation the goods are shipped to) * @@ -387,9 +368,9 @@ public interface IExportableTransaction { return null; } - /** - * consignee two digit country code (country code of the organisation the goods are shipped to) + * consignee two digit country code (country code of the organisation the goods + * are shipped to) * * @return the consignee's two character country iso code */ @@ -397,17 +378,19 @@ public interface IExportableTransaction { return null; } - /** - * get the ID of the SellerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement/ApplicableHeaderTradeAgreement + * get the ID of the SellerOrderReferencedDocument, which sits in the + * ApplicableSupplyChainTradeAgreement/ApplicableHeaderTradeAgreement * * @return the ID of the document */ default String getSellerOrderReferencedDocumentID() { return null; } + /** - * get the ID of the BuyerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement + * get the ID of the BuyerOrderReferencedDocument, which sits in the + * ApplicableSupplyChainTradeAgreement * * @return the ID of the document */ @@ -416,7 +399,8 @@ public interface IExportableTransaction { } /** - * get the ID of the preceding invoice, which is e.g. to be corrected if this is a correction + * get the ID of the preceding invoice, which is e.g. to be corrected if this is + * a correction * * @return the ID of the document */ @@ -424,9 +408,13 @@ public interface IExportableTransaction { return null; } - default Date getInvoiceReferencedIssueDate(){return null;} + default Date getInvoiceReferencedIssueDate() { + return null; + } + /** - * get the issue timestamp of the BuyerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement + * get the issue timestamp of the BuyerOrderReferencedDocument, which sits in + * the ApplicableSupplyChainTradeAgreement * * @return the IssueDateTime in format CCYY-MM-DDTHH:MM:SS */ @@ -434,19 +422,21 @@ public interface IExportableTransaction { return null; } - /** - * get the TotalPrepaidAmount located in SpecifiedTradeSettlementMonetarySummation (v1) or SpecifiedTradeSettlementHeaderMonetarySummation (v2) + * get the TotalPrepaidAmount located in + * SpecifiedTradeSettlementMonetarySummation (v1) or + * SpecifiedTradeSettlementHeaderMonetarySummation (v2) * - * @return the total sum (incl. VAT) of prepayments, i.e. the difference between GrandTotalAmount and DuePayableAmount + * @return the total sum (incl. VAT) of prepayments, i.e. the difference between + * GrandTotalAmount and DuePayableAmount */ default BigDecimal getTotalPrepaidAmount() { return BigDecimal.ZERO; } - /*** * delivery address, i.e. ram:ShipToTradeParty (only supported for zf2) + * * @return the IZUGFeRDExportableTradeParty delivery address */ @@ -454,9 +444,10 @@ public interface IExportableTransaction { return null; } - /*** - * specifies the document level delivery period, will be included in a BillingSpecifiedPeriod element + * specifies the document level delivery period, will be included in a + * BillingSpecifiedPeriod element + * * @return the beginning of the delivery period */ default Date getDetailedDeliveryPeriodFrom() { @@ -464,7 +455,9 @@ public interface IExportableTransaction { } /*** - * specifies the document level delivery period, will be included in a BillingSpecifiedPeriod element + * specifies the document level delivery period, will be included in a + * BillingSpecifiedPeriod element + * * @return the end of the delivery period */ default Date getDetailedDeliveryPeriodTo() { @@ -472,8 +465,9 @@ public interface IExportableTransaction { } /** - * get additional referenced documents acccording to BG-24 XRechnung (Rechnungsbegruendende Unterlagen), - * i.e. ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument + * get additional referenced documents acccording to BG-24 XRechnung + * (Rechnungsbegruendende Unterlagen), i.e. + * ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument * * @return a array of objects from class FileAttachment */ @@ -484,19 +478,23 @@ public interface IExportableTransaction { default String getDespatchAdviceReferencedDocumentID() { return null; } + /*** * additional text description - * @return an array of strings of document wide "includedNotes" (descriptive text values) + * + * @return an array of strings of document wide "includedNotes" (descriptive + * text values) */ default String[] getNotes() { return null; } - default String getSpecifiedProcuringProjectName(){ + default String getSpecifiedProcuringProjectName() { return null; } - default String getSpecifiedProcuringProjectID(){ + default String getSpecifiedProcuringProjectID() { return null; } + } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java b/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java index fd9f3a4d..f1be32a3 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java @@ -7,10 +7,10 @@ import java.math.BigDecimal; * @see TransactionCalculator */ public class LineCalculator { - private BigDecimal price; - private BigDecimal priceGross; - private BigDecimal itemTotalNetAmount; - private BigDecimal itemTotalVATAmount; + private final BigDecimal price; + private final BigDecimal priceGross; + private final BigDecimal itemTotalNetAmount; + private final BigDecimal itemTotalVATAmount; private BigDecimal allowance = BigDecimal.ZERO; private BigDecimal charge = BigDecimal.ZERO; private BigDecimal allowanceItemTotal = BigDecimal.ZERO; @@ -33,7 +33,10 @@ public class LineCalculator { } } - BigDecimal multiplicator = currentItem.getProduct().getVATPercent().divide(BigDecimal.valueOf(100)); + BigDecimal vatPercent = currentItem.getProduct().getVATPercent(); + if (vatPercent == null) + vatPercent = BigDecimal.ZERO; + BigDecimal multiplicator = vatPercent.divide(BigDecimal.valueOf(100)); priceGross = currentItem.getPrice(); // see https://github.com/ZUGFeRD/mustangproject/issues/159 price = priceGross.subtract(allowance).add(charge); itemTotalNetAmount = currentItem.getQuantity().multiply(getPrice()).divide(currentItem.getBasisQuantity()) diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java index dc126ab4..282ced71 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java @@ -8,7 +8,9 @@ import java.util.HashMap; import java.util.stream.Stream; /*** - * The Transactioncalculator e.g. adds the line totals and applies VAT on whole invoices + * The Transactioncalculator e.g. adds the line totals and applies VAT on whole + * invoices + * * @see LineCalculator */ public class TransactionCalculator implements IAbsoluteValueProvider { @@ -23,7 +25,9 @@ public class TransactionCalculator implements IAbsoluteValueProvider { } /*** - * if something had already been paid in advance, this will get it from the transaction + * if something had already been paid in advance, this will get it from the + * transaction + * * @return prepaid amount */ protected BigDecimal getTotalPrepaid() { @@ -35,20 +39,21 @@ public class TransactionCalculator implements IAbsoluteValueProvider { } /*** - * the invoice total with VAT, corrected by prepaid amount, allowances and charges + * the invoice total with VAT, corrected by prepaid amount, allowances and + * charges + * * @return the invoice total including taxes */ public BigDecimal getGrandTotal() { final BigDecimal res = getTaxBasis(); - return getVATPercentAmountMap().values().stream() - .map(VATAmount::getCalculated) - .map(p -> p.setScale(2, RoundingMode.HALF_UP)) - .reduce(BigDecimal.ZERO, BigDecimal::add).add(res); + return getVATPercentAmountMap().values().stream().map(VATAmount::getCalculated) + .map(p -> p.setScale(2, RoundingMode.HALF_UP)).reduce(BigDecimal.ZERO, BigDecimal::add).add(res); } /*** * returns total of charges for this tax rate + * * @param percent a specific rate, or null for any rate * @return the total amount */ @@ -70,7 +75,9 @@ public class TransactionCalculator implements IAbsoluteValueProvider { } /*** - * returns a (potentially concatenated) string of charge reasons, or "Charges" if none are defined + * returns a (potentially concatenated) string of charge reasons, or "Charges" + * if none are defined + * * @param percent a specific rate, or null for any rate * @return the space separated String */ @@ -98,7 +105,9 @@ public class TransactionCalculator implements IAbsoluteValueProvider { } /*** - * returns a (potentially concatenated) string of allowance reasons, or "Allowances", if none are defined + * returns a (potentially concatenated) string of allowance reasons, or + * "Allowances", if none are defined + * * @param percent a specific rate, or null for any rate * @return the space separated String */ @@ -111,9 +120,9 @@ public class TransactionCalculator implements IAbsoluteValueProvider { return res; } - /*** * returns total of allowances for this tax rate + * * @param percent a specific rate, or null for any rate * @return the total amount */ @@ -123,24 +132,27 @@ public class TransactionCalculator implements IAbsoluteValueProvider { } /*** - * returns the total net value of all items, without document level charges/allowances + * returns the total net value of all items, without document level + * charges/allowances + * * @return item sum */ protected BigDecimal getTotal() { - BigDecimal dec = Stream.of(trans.getZFItems()) - .map(LineCalculator::new) - .map(LineCalculator::getItemTotalNetAmount) - .reduce(ZERO, BigDecimal::add); + BigDecimal dec = Stream.of(trans.getZFItems()).map(LineCalculator::new) + .map(LineCalculator::getItemTotalNetAmount).reduce(ZERO, BigDecimal::add); return dec; } /*** - * returns the total net value of the invoice, including charges/allowances on document - * level + * returns the total net value of the invoice, including charges/allowances on + * document level + * * @return item sum +- charges/allowances */ protected BigDecimal getTaxBasis() { - return getTotal().add(getChargesForPercent(null).setScale(2, RoundingMode.HALF_UP)).subtract(getAllowancesForPercent(null).setScale(2, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP); + return getTotal().add(getChargesForPercent(null).setScale(2, RoundingMode.HALF_UP)) + .subtract(getAllowancesForPercent(null).setScale(2, RoundingMode.HALF_UP)) + .setScale(2, RoundingMode.HALF_UP); } /** @@ -155,55 +167,69 @@ public class TransactionCalculator implements IAbsoluteValueProvider { for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { BigDecimal percent = currentItem.getProduct().getVATPercent(); - LineCalculator lc = new LineCalculator(currentItem); - VATAmount itemVATAmount = new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount(), - currentItem.getProduct().getTaxCategoryCode()); - VATAmount current = hm.get(percent.stripTrailingZeros()); - if (current == null) { - hm.put(percent.stripTrailingZeros(), itemVATAmount); - } else { - hm.put(percent.stripTrailingZeros(), current.add(itemVATAmount)); + if (percent != null) { + LineCalculator lc = new LineCalculator(currentItem); + VATAmount itemVATAmount = new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount(), + currentItem.getProduct().getTaxCategoryCode()); + VATAmount current = hm.get(percent.stripTrailingZeros()); + if (current == null) { + hm.put(percent.stripTrailingZeros(), itemVATAmount); + } else { + hm.put(percent.stripTrailingZeros(), current.add(itemVATAmount)); + } } } - IZUGFeRDAllowanceCharge[] charges = trans.getZFCharges(); if ((charges != null) && (charges.length > 0)) { for (IZUGFeRDAllowanceCharge currentCharge : charges) { - VATAmount theAmount = hm.get(currentCharge.getTaxPercent().stripTrailingZeros()); - if (theAmount == null) { - theAmount = new VATAmount(BigDecimal.ZERO, BigDecimal.ZERO, - currentCharge.getCategoryCode() != null ? currentCharge.getCategoryCode() : "S"); + BigDecimal taxPercent = currentCharge.getTaxPercent(); + if (taxPercent != null) { + VATAmount theAmount = hm.get(taxPercent.stripTrailingZeros()); + if (theAmount == null) { + theAmount = new VATAmount(BigDecimal.ZERO, BigDecimal.ZERO, + currentCharge.getCategoryCode() != null ? currentCharge.getCategoryCode() : "S"); + } + theAmount.setBasis(theAmount.getBasis().add(currentCharge.getTotalAmount(this))); + BigDecimal factor = taxPercent.divide(new BigDecimal(100)); + theAmount.setCalculated(theAmount.getBasis().multiply(factor)); + hm.put(taxPercent.stripTrailingZeros(), theAmount); } - 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().stripTrailingZeros(), theAmount); } } IZUGFeRDAllowanceCharge[] allowances = trans.getZFAllowances(); if ((allowances != null) && (allowances.length > 0)) { for (IZUGFeRDAllowanceCharge currentAllowance : allowances) { - VATAmount theAmount = hm.get(currentAllowance.getTaxPercent().stripTrailingZeros()); - if (theAmount == null) { - theAmount = new VATAmount(BigDecimal.ZERO, BigDecimal.ZERO, - currentAllowance.getCategoryCode() != null ? currentAllowance.getCategoryCode() : "S"); - } - theAmount.setBasis(theAmount.getBasis().subtract(currentAllowance.getTotalAmount(this))); - BigDecimal factor = currentAllowance.getTaxPercent().divide(new BigDecimal(100)); - theAmount.setCalculated(theAmount.getBasis().multiply(factor)); + BigDecimal taxPercent = currentAllowance.getTaxPercent(); + if (taxPercent != null) { + VATAmount theAmount = hm.get(taxPercent.stripTrailingZeros()); + if (theAmount == null) { + theAmount = new VATAmount(BigDecimal.ZERO, BigDecimal.ZERO, + currentAllowance.getCategoryCode() != null ? currentAllowance.getCategoryCode() : "S"); + } + theAmount.setBasis(theAmount.getBasis().subtract(currentAllowance.getTotalAmount(this))); + BigDecimal factor = taxPercent.divide(new BigDecimal(100)); + theAmount.setCalculated(theAmount.getBasis().multiply(factor)); - hm.put(currentAllowance.getTaxPercent().stripTrailingZeros(), theAmount); + hm.put(taxPercent.stripTrailingZeros(), theAmount); + } } } return hm; } - @Override public BigDecimal getValue() { return getTotal(); } + public BigDecimal getChargeTotal() { + return getChargesForPercent(null).setScale(2, RoundingMode.HALF_UP); + } + + public BigDecimal getAllowanceTotal() { + return getAllowancesForPercent(null).setScale(2, RoundingMode.HALF_UP); + } + } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java index d10cf8c6..7828849d 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java @@ -310,16 +310,19 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr xml += "" + "" + currencyFormat(calc.getTotal()) + "" // currencyID=\"EUR\" - + "0.00" // currencyID=\"EUR\" - + "0.00" // + + "" + + currencyFormat(calc.getChargeTotal()) + "" // currencyID=\"EUR\" + + "" + + currencyFormat(calc.getAllowanceTotal()) + "" // // currencyID=\"EUR\" // + " 5.80" // + " 14.73" - + "" + currencyFormat(calc.getTotal()) + "" + + "" + + currencyFormat(calc.getTaxBasis()) + "" // // // currencyID=\"EUR\" + "" - + currencyFormat(calc.getGrandTotal().subtract(calc.getTotal())) + "" + + currencyFormat(calc.getGrandTotal().subtract(calc.getTaxBasis())) + "" + "" + currencyFormat(calc.getGrandTotal()) + "" // // // currencyID=\"EUR\" diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index 7df95f14..bbf490f5 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -63,7 +63,7 @@ public class ZUGFeRDImporter { /** * map filenames of additional XML files to their contents */ - private HashMap additionalXMLs = new HashMap<>(); + private final HashMap additionalXMLs = new HashMap<>(); /** * Raw XML form of the extracted data - may be directly obtained. */ @@ -76,6 +76,7 @@ public class ZUGFeRDImporter { * parsed Document */ private Document document; + private Integer version; protected ZUGFeRDImporter() { @@ -193,6 +194,7 @@ public class ZUGFeRDImporter { public void setRawXML(byte[] rawXML) throws IOException { this.rawXML = rawXML; + this.version = null; try { setDocument(); } catch (ParserConfigurationException | SAXException e) { @@ -656,13 +658,16 @@ public class ZUGFeRDImporter { if (!containsMeta) { throw new Exception("Not yet parsed"); } - if (getUTF8().contains(" 0) { @@ -77,42 +88,57 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { Date deliveryDate = null; for (int i = 0; i < ExchangedDocumentNodes.getLength(); i++) { - //nodes.item(i).getTextContent())) { + // nodes.item(i).getTextContent())) { Node exchangedDocumentNode = ExchangedDocumentNodes.item(i); NodeList exchangedDocumentChilds = exchangedDocumentNode.getChildNodes(); - for (int documentChildIndex = 0; documentChildIndex < exchangedDocumentChilds.getLength(); documentChildIndex++) { - if ((exchangedDocumentChilds.item(documentChildIndex).getLocalName() != null) && (exchangedDocumentChilds.item(documentChildIndex).getLocalName().equals("ID"))) { - number = exchangedDocumentChilds.item(documentChildIndex).getTextContent(); + for (int documentChildIndex = 0; documentChildIndex < exchangedDocumentChilds + .getLength(); documentChildIndex++) { + Node item = exchangedDocumentChilds.item(documentChildIndex); + if ((item.getLocalName() != null) && (item.getLocalName().equals("ID"))) { + number = item.getTextContent(); } - if ((exchangedDocumentChilds.item(documentChildIndex).getLocalName() != null) && (exchangedDocumentChilds.item(documentChildIndex).getLocalName().equals("IssueDateTime"))) { - NodeList issueDateTimeChilds = exchangedDocumentChilds.item(documentChildIndex).getChildNodes(); - for (int issueDateChildIndex = 0; issueDateChildIndex < issueDateTimeChilds.getLength(); issueDateChildIndex++) { - if ((issueDateTimeChilds.item(issueDateChildIndex).getLocalName() != null) && (issueDateTimeChilds.item(issueDateChildIndex).getLocalName().equals("DateTimeString"))) { - issueDate = new SimpleDateFormat("yyyyMMdd").parse(issueDateTimeChilds.item(issueDateChildIndex).getTextContent()); + if ((item.getLocalName() != null) && (item.getLocalName().equals("IssueDateTime"))) { + NodeList issueDateTimeChilds = item.getChildNodes(); + for (int issueDateChildIndex = 0; issueDateChildIndex < issueDateTimeChilds + .getLength(); issueDateChildIndex++) { + if ((issueDateTimeChilds.item(issueDateChildIndex).getLocalName() != null) + && (issueDateTimeChilds.item(issueDateChildIndex).getLocalName() + .equals("DateTimeString"))) { + issueDate = new SimpleDateFormat("yyyyMMdd") + .parse(issueDateTimeChilds.item(issueDateChildIndex).getTextContent()); } } } } } - - xpr = xpath.compile( - "//*[local-name()=\"ApplicableHeaderTradeDelivery\"]"); + xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeDelivery\"]"); NodeList headerTradeDeliveryNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); for (int i = 0; i < headerTradeDeliveryNodes.getLength(); i++) { - //nodes.item(i).getTextContent())) { + // nodes.item(i).getTextContent())) { Node headerTradeDeliveryNode = headerTradeDeliveryNodes.item(i); NodeList headerTradeDeliveryChilds = headerTradeDeliveryNode.getChildNodes(); - for (int deliveryChildIndex = 0; deliveryChildIndex < headerTradeDeliveryChilds.getLength(); deliveryChildIndex++) { - if ((headerTradeDeliveryChilds.item(deliveryChildIndex).getLocalName() != null) && (headerTradeDeliveryChilds.item(deliveryChildIndex).getLocalName().equals("ActualDeliverySupplyChainEvent"))) { + for (int deliveryChildIndex = 0; deliveryChildIndex < headerTradeDeliveryChilds + .getLength(); deliveryChildIndex++) { + if ((headerTradeDeliveryChilds.item(deliveryChildIndex).getLocalName() != null) + && (headerTradeDeliveryChilds.item(deliveryChildIndex).getLocalName() + .equals("ActualDeliverySupplyChainEvent"))) { NodeList actualDeliveryChilds = headerTradeDeliveryChilds.item(deliveryChildIndex).getChildNodes(); - for (int actualDeliveryChildIndex = 0; actualDeliveryChildIndex < actualDeliveryChilds.getLength(); actualDeliveryChildIndex++) { - if ((actualDeliveryChilds.item(actualDeliveryChildIndex).getLocalName() != null) && (actualDeliveryChilds.item(actualDeliveryChildIndex).getLocalName().equals("OccurrenceDateTime"))) { - NodeList occurenceChilds = actualDeliveryChilds.item(actualDeliveryChildIndex).getChildNodes(); - for (int occurenceChildIndex = 0; occurenceChildIndex < occurenceChilds.getLength(); occurenceChildIndex++) { - if ((occurenceChilds.item(occurenceChildIndex).getLocalName() != null) && (occurenceChilds.item(occurenceChildIndex).getLocalName().equals("DateTimeString"))) { - deliveryDate = new SimpleDateFormat("yyyyMMdd").parse(occurenceChilds.item(occurenceChildIndex).getTextContent()); + for (int actualDeliveryChildIndex = 0; actualDeliveryChildIndex < actualDeliveryChilds + .getLength(); actualDeliveryChildIndex++) { + if ((actualDeliveryChilds.item(actualDeliveryChildIndex).getLocalName() != null) + && (actualDeliveryChilds.item(actualDeliveryChildIndex).getLocalName() + .equals("OccurrenceDateTime"))) { + NodeList occurenceChilds = actualDeliveryChilds.item(actualDeliveryChildIndex) + .getChildNodes(); + for (int occurenceChildIndex = 0; occurenceChildIndex < occurenceChilds + .getLength(); occurenceChildIndex++) { + if ((occurenceChilds.item(occurenceChildIndex).getLocalName() != null) + && (occurenceChilds.item(occurenceChildIndex).getLocalName() + .equals("DateTimeString"))) { + deliveryDate = new SimpleDateFormat("yyyyMMdd") + .parse(occurenceChilds.item(occurenceChildIndex).getTextContent()); } } } @@ -121,24 +147,30 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { } } - - xpr = xpath.compile( - "//*[local-name()=\"ApplicableHeaderTradeSettlement\"]"); + xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]"); NodeList headerTradeSettlementNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); for (int i = 0; i < headerTradeSettlementNodes.getLength(); i++) { - //nodes.item(i).getTextContent())) { + // nodes.item(i).getTextContent())) { Node headerTradeSettlementNode = headerTradeSettlementNodes.item(i); NodeList headerTradeSettlementChilds = headerTradeSettlementNode.getChildNodes(); - for (int settlementChildIndex = 0; settlementChildIndex < headerTradeSettlementChilds.getLength(); settlementChildIndex++) { - if ((headerTradeSettlementChilds.item(settlementChildIndex).getLocalName() != null) && (headerTradeSettlementChilds.item(settlementChildIndex).getLocalName().equals("SpecifiedTradePaymentTerms"))) { + for (int settlementChildIndex = 0; settlementChildIndex < headerTradeSettlementChilds + .getLength(); settlementChildIndex++) { + if ((headerTradeSettlementChilds.item(settlementChildIndex).getLocalName() != null) + && (headerTradeSettlementChilds.item(settlementChildIndex).getLocalName() + .equals("SpecifiedTradePaymentTerms"))) { NodeList paymentTermChilds = headerTradeSettlementChilds.item(settlementChildIndex).getChildNodes(); - for (int paymentTermChildIndex = 0; paymentTermChildIndex < paymentTermChilds.getLength(); paymentTermChildIndex++) { - if ((paymentTermChilds.item(paymentTermChildIndex).getLocalName() != null) && (paymentTermChilds.item(paymentTermChildIndex).getLocalName().equals("DueDateDateTime"))) { + for (int paymentTermChildIndex = 0; paymentTermChildIndex < paymentTermChilds + .getLength(); paymentTermChildIndex++) { + if ((paymentTermChilds.item(paymentTermChildIndex).getLocalName() != null) && (paymentTermChilds + .item(paymentTermChildIndex).getLocalName().equals("DueDateDateTime"))) { NodeList dueDateChilds = paymentTermChilds.item(paymentTermChildIndex).getChildNodes(); - for (int dueDateChildIndex = 0; dueDateChildIndex < dueDateChilds.getLength(); dueDateChildIndex++) { - if ((dueDateChilds.item(dueDateChildIndex).getLocalName() != null) && (dueDateChilds.item(dueDateChildIndex).getLocalName().equals("DateTimeString"))) { - dueDate = new SimpleDateFormat("yyyyMMdd").parse(dueDateChilds.item(dueDateChildIndex).getTextContent()); + for (int dueDateChildIndex = 0; dueDateChildIndex < dueDateChilds + .getLength(); dueDateChildIndex++) { + if ((dueDateChilds.item(dueDateChildIndex).getLocalName() != null) && (dueDateChilds + .item(dueDateChildIndex).getLocalName().equals("DateTimeString"))) { + dueDate = new SimpleDateFormat("yyyyMMdd") + .parse(dueDateChilds.item(dueDateChildIndex).getTextContent()); } } } @@ -147,11 +179,11 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { } } - zpp = new Invoice().setDueDate(dueDate).setDeliveryDate(deliveryDate).setIssueDate(issueDate).setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number); + zpp = new Invoice().setDueDate(dueDate).setDeliveryDate(deliveryDate).setIssueDate(issueDate) + .setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number); //.addItem(new Item(new Product("Testprodukt","","C62",BigDecimal.ZERO),amount,new BigDecimal(1.0))) zpp.setOwnOrganisationName(extractString("//*[local-name()=\"SellerTradeParty\"]/*[local-name()=\"Name\"]")); - xpr = xpath.compile( - "//*[local-name()=\"IncludedSupplyChainTradeLineItem\"]"); + xpr = xpath.compile("//*[local-name()=\"IncludedSupplyChainTradeLineItem\"]"); NodeList nodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); if (nodes.getLength() == 0) { @@ -163,39 +195,45 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { String description = ""; SchemedID gid = null; String quantity = "0"; - String vatPercent = "0"; + String vatPercent = null; String lineTotal = "0"; String unitCode = "0"; ArrayList rdocs = null; - //nodes.item(i).getTextContent())) { + // nodes.item(i).getTextContent())) { Node currentItemNode = nodes.item(i); NodeList itemChilds = currentItemNode.getChildNodes(); for (int itemChildIndex = 0; itemChildIndex < itemChilds.getLength(); itemChildIndex++) { - if ((itemChilds.item(itemChildIndex).getLocalName() != null) && (itemChilds.item(itemChildIndex).getLocalName().equals("SpecifiedLineTradeAgreement"))) { + String lineTrade = itemChilds.item(itemChildIndex).getLocalName(); + if ((lineTrade != null) && (lineTrade.equals("SpecifiedLineTradeAgreement") + || lineTrade.equals("SpecifiedSupplyChainTradeAgreement"))) { NodeList tradeLineChilds = itemChilds.item(itemChildIndex).getChildNodes(); - for (int tradeLineChildIndex = 0; tradeLineChildIndex < tradeLineChilds.getLength(); tradeLineChildIndex++) { + for (int tradeLineChildIndex = 0; tradeLineChildIndex < tradeLineChilds + .getLength(); tradeLineChildIndex++) { - if ((tradeLineChilds.item(tradeLineChildIndex).getLocalName() != null) && tradeLineChilds.item(tradeLineChildIndex).getLocalName().equals("AdditionalReferencedDocument")) { + if ((tradeLineChilds.item(tradeLineChildIndex).getLocalName() != null) && tradeLineChilds + .item(tradeLineChildIndex).getLocalName().equals("AdditionalReferencedDocument")) { String IssuerAssignedID = ""; String TypeCode = ""; String ReferenceTypeCode = ""; NodeList refDocChilds = tradeLineChilds.item(tradeLineChildIndex).getChildNodes(); for (int refDocIndex = 0; refDocIndex < refDocChilds.getLength(); refDocIndex++) { - if ((refDocChilds.item(refDocIndex).getLocalName() != null) && (refDocChilds.item(refDocIndex).getLocalName().equals("IssuerAssignedID"))) { + String localName = refDocChilds.item(refDocIndex).getLocalName(); + if ((localName != null) && (localName.equals("IssuerAssignedID"))) { IssuerAssignedID = refDocChilds.item(refDocIndex).getTextContent(); } - if ((refDocChilds.item(refDocIndex).getLocalName() != null) && (refDocChilds.item(refDocIndex).getLocalName().equals("TypeCode"))) { + if ((localName != null) && (localName.equals("TypeCode"))) { TypeCode = refDocChilds.item(refDocIndex).getTextContent(); } - if ((refDocChilds.item(refDocIndex).getLocalName() != null) && (refDocChilds.item(refDocIndex).getLocalName().equals("ReferenceTypeCode"))) { + if ((localName != null) && (localName.equals("ReferenceTypeCode"))) { ReferenceTypeCode = refDocChilds.item(refDocIndex).getTextContent(); } } - ReferencedDocument rd = new ReferencedDocument(IssuerAssignedID, TypeCode, ReferenceTypeCode); + ReferencedDocument rd = new ReferencedDocument(IssuerAssignedID, TypeCode, + ReferenceTypeCode); if (rdocs == null) { rdocs = new ArrayList(); } @@ -203,59 +241,87 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { } - if ((tradeLineChilds.item(tradeLineChildIndex).getLocalName() != null) && tradeLineChilds.item(tradeLineChildIndex).getLocalName().equals("NetPriceProductTradePrice")) { + if ((tradeLineChilds.item(tradeLineChildIndex).getLocalName() != null) && tradeLineChilds + .item(tradeLineChildIndex).getLocalName().equals("NetPriceProductTradePrice")) { NodeList netChilds = tradeLineChilds.item(tradeLineChildIndex).getChildNodes(); for (int netIndex = 0; netIndex < netChilds.getLength(); netIndex++) { - if ((netChilds.item(netIndex).getLocalName() != null) && (netChilds.item(netIndex).getLocalName().equals("ChargeAmount"))) { - price = netChilds.item(netIndex).getTextContent();//ChargeAmount + if ((netChilds.item(netIndex).getLocalName() != null) + && (netChilds.item(netIndex).getLocalName().equals("ChargeAmount"))) { + price = netChilds.item(netIndex).getTextContent();// ChargeAmount } } } } } - if ((itemChilds.item(itemChildIndex).getLocalName() != null) && (itemChilds.item(itemChildIndex).getLocalName().equals("SpecifiedLineTradeDelivery"))) { + if ((lineTrade != null) && (lineTrade.equals("SpecifiedLineTradeDelivery") + || lineTrade.equals("SpecifiedSupplyChainTradeDelivery"))) { NodeList tradeLineChilds = itemChilds.item(itemChildIndex).getChildNodes(); - for (int tradeLineChildIndex = 0; tradeLineChildIndex < tradeLineChilds.getLength(); tradeLineChildIndex++) { - if ((tradeLineChilds.item(tradeLineChildIndex).getLocalName() != null) && (tradeLineChilds.item(tradeLineChildIndex).getLocalName().equals("BilledQuantity") || tradeLineChilds.item(tradeLineChildIndex).getLocalName().equals("RequestedQuantity") || tradeLineChilds.item(tradeLineChildIndex).getLocalName().equals("DespatchedQuantity"))) { - //RequestedQuantity is for Order-X, BilledQuantity for FX and ZF + for (int tradeLineChildIndex = 0; tradeLineChildIndex < tradeLineChilds + .getLength(); tradeLineChildIndex++) { + String tradeName = tradeLineChilds.item(tradeLineChildIndex).getLocalName(); + if ((tradeName != null) + && (tradeName.equals("BilledQuantity") || tradeName.equals("RequestedQuantity") + || tradeName.equals("DespatchedQuantity"))) { + // RequestedQuantity is for Order-X, BilledQuantity for FX and ZF quantity = tradeLineChilds.item(tradeLineChildIndex).getTextContent(); - unitCode = tradeLineChilds.item(tradeLineChildIndex).getAttributes().getNamedItem("unitCode").getNodeValue(); + unitCode = tradeLineChilds.item(tradeLineChildIndex).getAttributes() + .getNamedItem("unitCode").getNodeValue(); } } } - if ((itemChilds.item(itemChildIndex).getLocalName() != null) && (itemChilds.item(itemChildIndex).getLocalName().equals("SpecifiedTradeProduct"))) { + if ((lineTrade != null) && (lineTrade.equals("SpecifiedTradeProduct"))) { NodeList tradeProductChilds = itemChilds.item(itemChildIndex).getChildNodes(); - for (int tradeProductChildIndex = 0; tradeProductChildIndex < tradeProductChilds.getLength(); tradeProductChildIndex++) { - if ((tradeProductChilds.item(tradeProductChildIndex).getLocalName() != null) && (tradeProductChilds.item(tradeProductChildIndex).getLocalName().equals("Name"))) { + for (int tradeProductChildIndex = 0; tradeProductChildIndex < tradeProductChilds + .getLength(); tradeProductChildIndex++) { + if ((tradeProductChilds.item(tradeProductChildIndex).getLocalName() != null) + && (tradeProductChilds.item(tradeProductChildIndex).getLocalName() + .equals("Name"))) { name = tradeProductChilds.item(tradeProductChildIndex).getTextContent(); } - if ((tradeProductChilds.item(tradeProductChildIndex).getLocalName() != null) && (tradeProductChilds.item(tradeProductChildIndex).getLocalName().equals("GlobalID"))) { - if (tradeProductChilds.item(tradeProductChildIndex).getAttributes().getNamedItem("schemeID") != null) { - gid = new SchemedID().setScheme(tradeProductChilds.item(tradeProductChildIndex).getAttributes().getNamedItem("schemeID").getNodeValue()).setId(tradeProductChilds.item(tradeProductChildIndex).getTextContent()); + if ((tradeProductChilds.item(tradeProductChildIndex).getLocalName() != null) + && (tradeProductChilds.item(tradeProductChildIndex).getLocalName() + .equals("GlobalID"))) { + if (tradeProductChilds.item(tradeProductChildIndex).getAttributes() + .getNamedItem("schemeID") != null) { + gid = new SchemedID() + .setScheme(tradeProductChilds.item(tradeProductChildIndex).getAttributes() + .getNamedItem("schemeID").getNodeValue()) + .setId(tradeProductChilds.item(tradeProductChildIndex).getTextContent()); } } } } - if ((itemChilds.item(itemChildIndex).getLocalName() != null) && (itemChilds.item(itemChildIndex).getLocalName().equals("SpecifiedLineTradeSettlement"))) { + if ((lineTrade != null) && (lineTrade.equals("SpecifiedLineTradeSettlement") + || lineTrade.equals("SpecifiedSupplyChainTradeSettlement"))) { NodeList tradeSettlementChilds = itemChilds.item(itemChildIndex).getChildNodes(); - for (int tradeSettlementChildIndex = 0; tradeSettlementChildIndex < tradeSettlementChilds.getLength(); tradeSettlementChildIndex++) { + for (int tradeSettlementChildIndex = 0; tradeSettlementChildIndex < tradeSettlementChilds + .getLength(); tradeSettlementChildIndex++) { - if (tradeSettlementChilds.item(tradeSettlementChildIndex).getLocalName() != null) { - if (tradeSettlementChilds.item(tradeSettlementChildIndex).getLocalName().equals("ApplicableTradeTax")) { - NodeList taxChilds = tradeSettlementChilds.item(tradeSettlementChildIndex).getChildNodes(); - for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) { - if ((taxChilds.item(taxChildIndex).getLocalName() != null) && (taxChilds.item(taxChildIndex).getLocalName().equals("RateApplicablePercent"))) { + String tradeSettlementName = tradeSettlementChilds.item(tradeSettlementChildIndex) + .getLocalName(); + if (tradeSettlementName != null) { + if (tradeSettlementName.equals("ApplicableTradeTax")) { + NodeList taxChilds = tradeSettlementChilds.item(tradeSettlementChildIndex) + .getChildNodes(); + for (int taxChildIndex = 0; taxChildIndex < taxChilds + .getLength(); taxChildIndex++) { + String taxChildName = taxChilds.item(taxChildIndex).getLocalName(); + if ((taxChildName != null) && (taxChildName.equals("RateApplicablePercent") + || taxChildName.equals("ApplicablePercent"))) { vatPercent = taxChilds.item(taxChildIndex).getTextContent(); } } } - if (tradeSettlementChilds.item(tradeSettlementChildIndex).getLocalName().equals("SpecifiedTradeSettlementLineMonetarySummation")) { - NodeList totalChilds = tradeSettlementChilds.item(tradeSettlementChildIndex).getChildNodes(); - for (int totalChildIndex = 0; totalChildIndex < totalChilds.getLength(); totalChildIndex++) { - if ((totalChilds.item(totalChildIndex).getLocalName() != null) && (totalChilds.item(totalChildIndex).getLocalName().equals("LineTotalAmount"))) { + if (tradeSettlementName.equals("SpecifiedTradeSettlementLineMonetarySummation")) { + NodeList totalChilds = tradeSettlementChilds.item(tradeSettlementChildIndex) + .getChildNodes(); + for (int totalChildIndex = 0; totalChildIndex < totalChilds + .getLength(); totalChildIndex++) { + if ((totalChilds.item(totalChildIndex).getLocalName() != null) && (totalChilds + .item(totalChildIndex).getLocalName().equals("LineTotalAmount"))) { lineTotal = totalChilds.item(totalChildIndex).getTextContent(); } } @@ -269,7 +335,8 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { if ((recalcPrice) && (!qty.equals(BigDecimal.ZERO))) { prc = new BigDecimal(lineTotal.trim()).divide(qty, 4, RoundingMode.HALF_UP); } - Product p = new Product(name, description, unitCode, new BigDecimal(vatPercent.trim())); + Product p = new Product(name, description, unitCode, + vatPercent == null ? null : new BigDecimal(vatPercent.trim())); if (gid != null) { p.addGlobalID(gid); } @@ -281,14 +348,13 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { } zpp.addItem(it); - } - // item level charges+allowances are not yet handled but a lower item price will be read, + // 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\"]"); + 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(); @@ -297,23 +363,30 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { String reason = null; String taxPercent = null; for (int chargeChildIndex = 0; chargeChildIndex < chargeNodeChilds.getLength(); chargeChildIndex++) { - if (chargeNodeChilds.item(chargeChildIndex).getLocalName() != null) { + String chargeChildName = chargeNodeChilds.item(chargeChildIndex).getLocalName(); + if (chargeChildName != null) { - if (chargeNodeChilds.item(chargeChildIndex).getLocalName().equals("ChargeIndicator")) { + 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 = indicatorChilds.item(indicatorChildIndex).getTextContent().equalsIgnoreCase("true"); + for (int indicatorChildIndex = 0; indicatorChildIndex < indicatorChilds + .getLength(); indicatorChildIndex++) { + if ((indicatorChilds.item(indicatorChildIndex).getLocalName() != null) + && (indicatorChilds.item(indicatorChildIndex).getLocalName() + .equals("Indicator"))) { + isCharge = indicatorChilds.item(indicatorChildIndex).getTextContent() + .equalsIgnoreCase("true"); } } - } else if (chargeNodeChilds.item(chargeChildIndex).getLocalName().equals("ActualAmount")) { + } else if (chargeChildName.equals("ActualAmount")) { chargeAmount = chargeNodeChilds.item(chargeChildIndex).getTextContent(); - } else if (chargeNodeChilds.item(chargeChildIndex).getLocalName().equals("Reason")) { + } else if (chargeChildName.equals("Reason")) { reason = chargeNodeChilds.item(chargeChildIndex).getTextContent(); - } else if (chargeNodeChilds.item(chargeChildIndex).getLocalName().equals("CategoryTradeTax")) { + } else if (chargeChildName.equals("CategoryTradeTax")) { NodeList taxChilds = chargeNodeChilds.item(chargeChildIndex).getChildNodes(); for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) { - if ((taxChilds.item(taxChildIndex).getLocalName() != null) && (taxChilds.item(taxChildIndex).getLocalName().equals("RateApplicablePercent"))) { + String taxItemName = taxChilds.item(taxChildIndex).getLocalName(); + if ((taxItemName != null) && (taxItemName.equals("RateApplicablePercent") + || taxItemName.equals("ApplicablePercent"))) { taxPercent = taxChilds.item(taxChildIndex).getTextContent(); } } @@ -321,7 +394,6 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { } } - if (isCharge) { Charge c = new Charge(new BigDecimal(chargeAmount)); if (reason != null) { @@ -347,6 +419,9 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { TransactionCalculator tc = new TransactionCalculator(zpp); String expectedStringTotalGross = tc.getGrandTotal().toPlainString(); + zpp.setGrandTotalAmount(tc.getGrandTotal()); + zpp.setTotalPrepaidAmount(tc.getTotalPrepaid()); + zpp.setDuePayableAmount(tc.getGrandTotal().add(tc.getTotalPrepaid().negate())); EStandard whichType; try { whichType = getStandard(); @@ -355,13 +430,15 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter { } - if ((whichType != EStandard.despatchadvice) && ((!expectedStringTotalGross.equals(XMLTools.nDigitFormat(expectedGrandTotal, 2))) && (!ignoreCalculationErrors))) { - throw new ParseException("Could not reproduce the invoice, this could mean that it could not be read properly", 0); + if ((whichType != EStandard.despatchadvice) + && ((!expectedStringTotalGross.equals(XMLTools.nDigitFormat(expectedGrandTotal, 2))) + && (!ignoreCalculationErrors))) { + throw new ParseException( + "Could not reproduce the invoice, this could mean that it could not be read properly", 0); } } return zpp; - } public void doRecalculateItemPricesFromLineTotals() {