diff --git a/History.md b/History.md index 099a75c8..248a960c 100644 --- a/History.md +++ b/History.md @@ -1,15 +1,17 @@ 2.15.1 ======= -- #566 -- have a bean contructor for direct debit --? lineTotalAmount is null +- #566 Failed to parse PDF - Could not reproduce the invoice ? be able to access ID in error message -? log error IDs -- closes #579 -- #581 -- #576 -- #578 +- closes #579 prepaidamount is only read in UBL +- #581 parse lineTotalAmount +- also parse TaxBasisAmount +- #576 read lineid, #578 set lineid - log error ids +- #503 import more ubl +- allow jackson to run over more classes, e.g., DirectDebit, bean contructor for direct debit +- allow json includedNotes +- support importing duePayableAmount + 2.15.0 ======= diff --git a/library/src/main/java/org/mustangproject/Allowance.java b/library/src/main/java/org/mustangproject/Allowance.java index 9c26d02e..e378f767 100644 --- a/library/src/main/java/org/mustangproject/Allowance.java +++ b/library/src/main/java/org/mustangproject/Allowance.java @@ -1,12 +1,16 @@ package org.mustangproject; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import java.math.BigDecimal; /*** * (absolute) allowances on item and document level */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class Allowance extends Charge { /*** diff --git a/library/src/main/java/org/mustangproject/BankDetails.java b/library/src/main/java/org/mustangproject/BankDetails.java index c6edcc86..a16976f3 100644 --- a/library/src/main/java/org/mustangproject/BankDetails.java +++ b/library/src/main/java/org/mustangproject/BankDetails.java @@ -2,11 +2,14 @@ package org.mustangproject; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import org.mustangproject.ZUGFeRD.IZUGFeRDTradeSettlementPayment; /** * provides e.g. the IBAN to transfer money to :-) */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class BankDetails implements IZUGFeRDTradeSettlementPayment { /** * the bank account number @@ -15,15 +18,17 @@ public class BankDetails implements IZUGFeRDTradeSettlementPayment { /** * BIC, I believe it's optional */ - protected String BIC=null; + protected String BIC = null; /** * the "name" of the bank account (holder) */ - protected String accountName=null; + protected String accountName = null; + /*** * bean constructor */ - public BankDetails() { } + public BankDetails() { + } /*** * constructor for IBAN only :-) @@ -32,6 +37,7 @@ public class BankDetails implements IZUGFeRDTradeSettlementPayment { public BankDetails(String IBAN) { this.IBAN = IBAN; } + /*** * constructor for normal use :-) * @param IBAN the IBAN as string @@ -55,6 +61,7 @@ public class BankDetails implements IZUGFeRDTradeSettlementPayment { * identify the IBAN. Of course you will specify your own IBAN in full length but * if you deduct from a customer's account you may e.g. leave out the first or last * digits so that nobody spying on the invoice gets to know the complete number + * * @param IBAN the "IBAN ID", i.e. the IBAN or parts of it * @return fluent setter */ @@ -81,9 +88,10 @@ public class BankDetails implements IZUGFeRDTradeSettlementPayment { return this; } - /*** - * getOwn... methods will be removed in the future in favor of Tradeparty (e.g. Sender) class - * */ + + /* + I'd really like to get rid of all those getOwn... methods some time but in this case they are in the interface :-( + */ @Override @Deprecated @JsonIgnore @@ -101,11 +109,12 @@ public class BankDetails implements IZUGFeRDTradeSettlementPayment { /** * set Holder + * * @param name account name (usually account holder if != sender) * @return fluent setter */ public BankDetails setAccountName(String name) { - accountName=name; + accountName = name; return this; } @@ -115,5 +124,4 @@ public class BankDetails implements IZUGFeRDTradeSettlementPayment { } - } diff --git a/library/src/main/java/org/mustangproject/CalculatedInvoice.java b/library/src/main/java/org/mustangproject/CalculatedInvoice.java index c6a24fb1..194441b1 100644 --- a/library/src/main/java/org/mustangproject/CalculatedInvoice.java +++ b/library/src/main/java/org/mustangproject/CalculatedInvoice.java @@ -2,6 +2,8 @@ package org.mustangproject; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import org.mustangproject.ZUGFeRD.TransactionCalculator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -9,15 +11,21 @@ import org.slf4j.LoggerFactory; import java.io.Serializable; import java.math.BigDecimal; +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class CalculatedInvoice extends Invoice implements Serializable { - protected BigDecimal grandTotal=null; protected BigDecimal lineTotalAmount=null; + protected BigDecimal duePayable=null; + protected BigDecimal grandTotal=null; + protected BigDecimal taxBasis=null; public void calculate() { TransactionCalculator tc=new TransactionCalculator(this); grandTotal=tc.getGrandTotal(); lineTotalAmount=tc.getValue(); + duePayable=tc.getDuePayable(); + taxBasis= tc.getTaxBasis(); } public BigDecimal getGrandTotal() { if (grandTotal==null) { @@ -29,6 +37,28 @@ public class CalculatedInvoice extends Invoice implements Serializable { grandTotal=grand; return this; } + public BigDecimal getTaxBasis() { + if (taxBasis==null) { + calculate(); + } + return taxBasis; + } + public CalculatedInvoice setTaxBasis(BigDecimal basis) { + taxBasis=basis; + return this; + } + + public BigDecimal getDuePayable() { + if (duePayable==null) { + calculate(); + } + return duePayable; + } + public CalculatedInvoice setDuePayable(BigDecimal due) { + duePayable=due; + return this; + } + public BigDecimal getLineTotalAmount() { if (lineTotalAmount==null) { calculate(); diff --git a/library/src/main/java/org/mustangproject/CashDiscount.java b/library/src/main/java/org/mustangproject/CashDiscount.java index c7fb7a03..2151489a 100644 --- a/library/src/main/java/org/mustangproject/CashDiscount.java +++ b/library/src/main/java/org/mustangproject/CashDiscount.java @@ -1,5 +1,7 @@ package org.mustangproject; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import org.mustangproject.ZUGFeRD.IZUGFeRDCashDiscount; import java.math.BigDecimal; @@ -7,6 +9,8 @@ import java.math.BigDecimal; /*** * A class to represent discounts for early payments ("Skonto") */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class CashDiscount implements IZUGFeRDCashDiscount { /*** @@ -31,6 +35,31 @@ public class CashDiscount implements IZUGFeRDCashDiscount { this.days = days; } + /*** + * bean contructor + */ + public CashDiscount() { + + } + + public BigDecimal getPercent() { + return percent; + } + + public CashDiscount setPercent(BigDecimal percent) { + this.percent = percent; + return this; + } + + public Integer getDays() { + return days; + } + + public CashDiscount setDays(Integer days) { + this.days = days; + return this; + } + /*** * @return this particular cash discount as cross industry invoice XML */ diff --git a/library/src/main/java/org/mustangproject/Charge.java b/library/src/main/java/org/mustangproject/Charge.java index 0e081397..6232611d 100644 --- a/library/src/main/java/org/mustangproject/Charge.java +++ b/library/src/main/java/org/mustangproject/Charge.java @@ -1,6 +1,8 @@ package org.mustangproject; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import org.mustangproject.ZUGFeRD.IAbsoluteValueProvider; import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge; @@ -9,6 +11,8 @@ import java.math.BigDecimal; /*** * Absolute and relative charges for document and item level */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class Charge implements IZUGFeRDAllowanceCharge { /** diff --git a/library/src/main/java/org/mustangproject/ClassCode.java b/library/src/main/java/org/mustangproject/ClassCode.java index 8b0a58cc..75fd59e9 100644 --- a/library/src/main/java/org/mustangproject/ClassCode.java +++ b/library/src/main/java/org/mustangproject/ClassCode.java @@ -20,12 +20,16 @@ */ package org.mustangproject; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** * A schemed classification for products. The scheme can be anything defined in UNTDID 7143. */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class ClassCode { private final String listID; private final String code; diff --git a/library/src/main/java/org/mustangproject/Contact.java b/library/src/main/java/org/mustangproject/Contact.java index f690d0d8..cead6f86 100644 --- a/library/src/main/java/org/mustangproject/Contact.java +++ b/library/src/main/java/org/mustangproject/Contact.java @@ -1,6 +1,7 @@ package org.mustangproject; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import org.mustangproject.ZUGFeRD.IZUGFeRDExportableContact; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -11,6 +12,7 @@ import org.w3c.dom.NodeList; * @see TradeParty */ @JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class Contact implements IZUGFeRDExportableContact { /** diff --git a/library/src/main/java/org/mustangproject/DesignatedProductClassification.java b/library/src/main/java/org/mustangproject/DesignatedProductClassification.java index ac74bf36..1917568d 100644 --- a/library/src/main/java/org/mustangproject/DesignatedProductClassification.java +++ b/library/src/main/java/org/mustangproject/DesignatedProductClassification.java @@ -20,12 +20,16 @@ */ package org.mustangproject; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import org.mustangproject.ZUGFeRD.IDesignatedProductClassification; /** * An implementation of {@link IDesignatedProductClassification} for describing a {@link org.mustangproject.Product} * */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class DesignatedProductClassification implements IDesignatedProductClassification { private final ClassCode classCode; private String className; diff --git a/library/src/main/java/org/mustangproject/DirectDebit.java b/library/src/main/java/org/mustangproject/DirectDebit.java index d90ba661..1eee28b8 100644 --- a/library/src/main/java/org/mustangproject/DirectDebit.java +++ b/library/src/main/java/org/mustangproject/DirectDebit.java @@ -1,10 +1,14 @@ package org.mustangproject; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import org.mustangproject.ZUGFeRD.IZUGFeRDTradeSettlementDebit; /** * provides e.g. the IBAN to transfer money to :-) */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class DirectDebit implements IZUGFeRDTradeSettlementDebit { /** * Debited account identifier (BT-91) diff --git a/library/src/main/java/org/mustangproject/FileAttachment.java b/library/src/main/java/org/mustangproject/FileAttachment.java index dfced588..a7446a54 100644 --- a/library/src/main/java/org/mustangproject/FileAttachment.java +++ b/library/src/main/java/org/mustangproject/FileAttachment.java @@ -1,5 +1,10 @@ package org.mustangproject; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class FileAttachment { protected String filename; diff --git a/library/src/main/java/org/mustangproject/IncludedNote.java b/library/src/main/java/org/mustangproject/IncludedNote.java index e721ffd1..111b4e72 100644 --- a/library/src/main/java/org/mustangproject/IncludedNote.java +++ b/library/src/main/java/org/mustangproject/IncludedNote.java @@ -1,10 +1,16 @@ package org.mustangproject; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + /** * A grouping of business terms to indicate accounting-relevant free texts including a qualification of these. */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class IncludedNote { private String content; + private SubjectCode subjectCode; private static final String INCLUDE_START = ""; @@ -29,24 +35,31 @@ public class IncludedNote { public static IncludedNote generalNote(String content) { return new IncludedNote(content, SubjectCode.AAI); } + public static IncludedNote regulatoryNote(String content) { return new IncludedNote(content, SubjectCode.REG); } + public static IncludedNote legalNote(String content) { return new IncludedNote(content, SubjectCode.ABL); } + public static IncludedNote customsNote(String content) { return new IncludedNote(content, SubjectCode.CUS); } + public static IncludedNote sellerNote(String content) { return new IncludedNote(content, SubjectCode.SUR); } + public static IncludedNote taxNote(String content) { return new IncludedNote(content, SubjectCode.TXD); } + public static IncludedNote introductionNote(String content) { return new IncludedNote(content, SubjectCode.ACY); } + public static IncludedNote discountBonusNote(String content) { return new IncludedNote(content, SubjectCode.AAK); } @@ -63,6 +76,18 @@ public class IncludedNote { return subjectCode; } + + public IncludedNote setSubjectCode(SubjectCode subjectCode) { + this.subjectCode = subjectCode; + return this; + } + + public IncludedNote setContent(String content) { + this.content = content; + return this; + } + + public String toCiiXml(){ String result = INCLUDE_START + CONTENT_START + XMLTools.encodeXML(getContent() )+ CONTENT_END; diff --git a/library/src/main/java/org/mustangproject/Invoice.java b/library/src/main/java/org/mustangproject/Invoice.java index 88e6cc53..10ba057f 100644 --- a/library/src/main/java/org/mustangproject/Invoice.java +++ b/library/src/main/java/org/mustangproject/Invoice.java @@ -413,6 +413,11 @@ public class Invoice implements IExportableTransaction { return includedNotes; } + public Invoice setNotesWithSubjectCode(List theList) { + includedNotes=theList; + return this; + } + @Override public String getCurrency() { return currency; diff --git a/library/src/main/java/org/mustangproject/Item.java b/library/src/main/java/org/mustangproject/Item.java index a5957e27..5d624adb 100644 --- a/library/src/main/java/org/mustangproject/Item.java +++ b/library/src/main/java/org/mustangproject/Item.java @@ -15,6 +15,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; +import java.util.HashMap; +import java.util.Map; /*** * describes any invoice line @@ -40,6 +42,7 @@ public class Item implements IZUGFeRDExportableItem { protected ArrayList Allowances = new ArrayList<>(); protected ArrayList Charges = new ArrayList<>(); protected List includedNotes = null; + //protected HashMap attributes = new HashMap<>(); /*** * default constructor @@ -67,8 +70,33 @@ public class Item implements IZUGFeRDExportableItem { // ubl //we need: name description unitcode //and we additionally have vat% - setProduct(new Product()); + + // 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())); icnm.getAsString("Name").ifPresent(product::setName); + icnm.getAsString("Description").ifPresent(product::setDescription); + + icnm.getAsNodeMap("SellersItemIdentification").ifPresent(SellersItemIdentification -> { + SellersItemIdentification.getAsString("ID").ifPresent(product::setSellerAssignedID); + }); + + icnm.getAsNodeMap("BuyersItemIdentification").ifPresent(BuyersItemIdentification -> { + 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")) .ifPresent(product::setVATPercent); }); @@ -89,21 +117,37 @@ public class Item implements IZUGFeRDExportableItem { product.setUnit(icn.getAttributes().getNamedItem("unitCode").getNodeValue()); }); + itemMap.getAllNodes("DocumentReference").map(ReferencedDocument::fromNode) + .forEach(this::addAdditionalReference); + + // ubl + + itemMap.getAsNodeMap("OrderLineReference") + // ubl + .flatMap(bordNodes -> bordNodes.getAsString("LineID")) + .ifPresent(this::addReferencedLineID); + + + + + itemMap.getAsNodeMap("SpecifiedLineTradeAgreement", "SpecifiedSupplyChainTradeAgreement").ifPresent(icnm -> { icnm.getAsNodeMap("BuyerOrderReferencedDocument") .flatMap(bordNodes -> bordNodes.getAsString("LineID")) .ifPresent(this::addReferencedLineID); + icnm.getAsNodeMap("NetPriceProductTradePrice").ifPresent(npptpNodes -> { npptpNodes.getAsBigDecimal("ChargeAmount").ifPresent(this::setPrice); npptpNodes.getAsBigDecimal("BasisQuantity").ifPresent(this::setBasisQuantity); }); - icnm.getAllNodes("AdditionalReferencedDocument").map(ReferencedDocument::fromNode) - .forEach(this::addReferencedDocument); + icnm.getAllNodes("AdditionalReferencedDocument").map(ReferencedDocument::fromNode). + forEach(this::addReferencedDocument); }); - itemMap.getNode("SpecifiedTradeProduct").map(Product::new).ifPresent(this::setProduct); + itemMap.getNode("SpecifiedTradeProduct").map(Product::new).ifPresent(this::setProduct);//CII + itemMap.getNode("SpecifiedTradeProduct").map(Product::new).ifPresent(this::setProduct);//UBL // RequestedQuantity is for Order-X, BilledQuantity for FX and ZF itemMap.getAsNodeMap("SpecifiedLineTradeDelivery", "SpecifiedSupplyChainTradeDelivery") diff --git a/library/src/main/java/org/mustangproject/LegalOrganisation.java b/library/src/main/java/org/mustangproject/LegalOrganisation.java index 95f61629..705420c2 100644 --- a/library/src/main/java/org/mustangproject/LegalOrganisation.java +++ b/library/src/main/java/org/mustangproject/LegalOrganisation.java @@ -1,6 +1,7 @@ package org.mustangproject; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import org.mustangproject.ZUGFeRD.*; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -9,6 +10,7 @@ import org.w3c.dom.NodeList; * A organisation, i.e. usually a company */ @JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class LegalOrganisation implements IZUGFeRDLegalOrganisation { protected SchemedID schemedID = null; diff --git a/library/src/main/java/org/mustangproject/Product.java b/library/src/main/java/org/mustangproject/Product.java index 1263d593..83cf4543 100644 --- a/library/src/main/java/org/mustangproject/Product.java +++ b/library/src/main/java/org/mustangproject/Product.java @@ -6,6 +6,7 @@ import org.mustangproject.ZUGFeRD.IDesignatedProductClassification; import org.mustangproject.ZUGFeRD.IZUGFeRDExportableProduct; import org.mustangproject.util.NodeMap; import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import java.math.BigDecimal; import java.util.ArrayList; @@ -59,11 +60,15 @@ public class Product implements IZUGFeRDExportableProduct { } }); + + + nodeMap.getAsString("SellerAssignedID").ifPresent(this::setSellerAssignedID); nodeMap.getAsString("BuyerAssignedID").ifPresent(this::setBuyerAssignedID); nodeMap.getAsString("Name").ifPresent(this::setName); nodeMap.getAsString("Description").ifPresent(this::setDescription); + nodeMap.getAsNodeMap("ApplicableProductCharacteristic").ifPresent(apcNodes -> { String key = apcNodes.getAsStringOrNull("Description"); String value = apcNodes.getAsStringOrNull("Value"); @@ -75,6 +80,26 @@ public class Product implements IZUGFeRDExportableProduct { } }); + + //UBL + nodeMap.getAsNodeMap("AdditionalItemProperty").ifPresent(aipNodes -> { + String name = aipNodes.getAsStringOrNull("Name"); + String val = aipNodes.getAsStringOrNull("Value"); + if (name != null && val != null) { + if (attributes == null) { + attributes = new HashMap<>(); + } + attributes.put(name, val); + } + }); + + nodeMap.getAsNodeMap("CommodityClassification").ifPresent(dpcNodes -> { + String className = dpcNodes.getAsStringOrNull("ClassName"); + dpcNodes.getNode("ItemClassificationCode").map(ClassCode::fromNode).ifPresent(classCode -> + classifications.add(new DesignatedProductClassification(classCode, className))); + }); + + //UBL nodeMap.getAsNodeMap("DesignatedProductClassification").ifPresent(dpcNodes -> { String className = dpcNodes.getAsStringOrNull("ClassName"); dpcNodes.getNode("ClassCode").map(ClassCode::fromNode).ifPresent(classCode -> @@ -115,6 +140,7 @@ public class Product implements IZUGFeRDExportableProduct { return this; } + /*** * * @return e.g. intra-commnunity supply or small business diff --git a/library/src/main/java/org/mustangproject/ReferencedDocument.java b/library/src/main/java/org/mustangproject/ReferencedDocument.java index 4d2151ca..9255017f 100644 --- a/library/src/main/java/org/mustangproject/ReferencedDocument.java +++ b/library/src/main/java/org/mustangproject/ReferencedDocument.java @@ -1,9 +1,13 @@ package org.mustangproject; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import org.mustangproject.ZUGFeRD.IReferencedDocument; import org.mustangproject.util.NodeMap; import org.w3c.dom.Node; +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class ReferencedDocument implements IReferencedDocument { String issuerAssignedID; @@ -22,7 +26,7 @@ public class ReferencedDocument implements IReferencedDocument { this.referenceTypeCode = referenceTypeCode; } - /*** + /*** * sets an ID assigned by the sender * @param issuerAssignedID the ID as a string :-) */ @@ -66,8 +70,8 @@ public class ReferencedDocument implements IReferencedDocument { return null; } NodeMap nodes = new NodeMap(node); - return new ReferencedDocument(nodes.getAsStringOrNull("IssuerAssignedID"), - nodes.getAsStringOrNull("TypeCode"), + return new ReferencedDocument(nodes.getAsStringOrNull("IssuerAssignedID", "ID"), + nodes.getAsStringOrNull("TypeCode", "DocumentTypeCode"), nodes.getAsStringOrNull("ReferenceTypeCode")); } } diff --git a/library/src/main/java/org/mustangproject/SchemedID.java b/library/src/main/java/org/mustangproject/SchemedID.java index 9df8a2d9..6cbac0ec 100644 --- a/library/src/main/java/org/mustangproject/SchemedID.java +++ b/library/src/main/java/org/mustangproject/SchemedID.java @@ -1,5 +1,11 @@ package org.mustangproject; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class SchemedID { protected String scheme; protected String id; diff --git a/library/src/main/java/org/mustangproject/TradeParty.java b/library/src/main/java/org/mustangproject/TradeParty.java index a45d57ba..73b1ae81 100644 --- a/library/src/main/java/org/mustangproject/TradeParty.java +++ b/library/src/main/java/org/mustangproject/TradeParty.java @@ -2,6 +2,7 @@ package org.mustangproject; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -16,6 +17,7 @@ import org.w3c.dom.NodeList; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + /*** * A organisation, i.e. usually a company */ @@ -62,6 +64,7 @@ public class TradeParty implements IZUGFeRDExportableTradeParty { } + protected void parseFromUBL(NodeList nodes) { if (nodes.getLength() > 0) { @@ -71,8 +74,34 @@ public class TradeParty implements IZUGFeRDExportableTradeParty { if (currentItemNode.getLocalName() != null) { String currentUBLChild = currentItemNode.getLocalName(); - if (currentUBLChild.equals("Party")) { +// if (currentUBLChild.equals("Delivery")) { +// NodeList delivery = currentItemNode.getChildNodes(); +// for (int deliveryIndex = 0; deliveryIndex < delivery.getLength(); deliveryIndex++) { +// if (delivery.item(deliveryIndex).getLocalName() != null) { +// Node currentNode = delivery.item(deliveryIndex); +// if (currentNode.getLocalName().equals("DeliveryLocation")) { +// NodeList deliveryLocation = currentNode.getChildNodes(); +// for (int deliveryLocationIndex = 0; deliveryLocationIndex < deliveryLocation.getLength(); deliveryLocationIndex++) { +// if (deliveryLocation.item(deliveryLocationIndex).getLocalName() != null) { +// if (deliveryLocation.item(deliveryLocationIndex).getLocalName().equals("ID")) { +// //Node currentNode = partyID.item(partyIDIndex); +// setID(deliveryLocation.item(deliveryLocationIndex).getTextContent()); +// if ((deliveryLocation.item(deliveryLocationIndex).getAttributes() != null && +// (deliveryLocation.item(deliveryLocationIndex).getAttributes().getNamedItem("schemeID") != null)) +// ) { +// SchemedID sID = new SchemedID().setScheme(deliveryLocation.item(deliveryLocationIndex).getAttributes().getNamedItem("schemeID").getTextContent()); +// addGlobalID(sID); +// } +// } +// } +// } +// } +// +// } +// } +// } + if (currentUBLChild.equals("Party")) { NodeList party = currentItemNode.getChildNodes(); for (int partyIndex = 0; partyIndex < party.getLength(); partyIndex++) { if (party.item(partyIndex).getLocalName() != null) { @@ -90,42 +119,64 @@ public class TradeParty implements IZUGFeRDExportableTradeParty { } } } + if (party.item(partyIndex).getLocalName().equals("EndpointID")) { + Node currentNode = party.item(partyIndex); + if ((currentNode.getAttributes() != null && + (currentNode.getAttributes().getNamedItem("schemeID") != null)) + && (party.item(partyIndex).getAttributes().getNamedItem("schemeID").getNodeValue().equals("EM")) + ) { + setEmail(currentNode.getTextContent()); + } - if (currentTopElementName.equals("PartyTaxScheme")) { - NodeList partyTaxScheme = party.item(partyIndex).getChildNodes(); - for (int partyTaxSchemeIndex = 0; partyTaxSchemeIndex < partyTaxScheme.getLength(); partyTaxSchemeIndex++) { - if (partyTaxScheme.item(partyTaxSchemeIndex).getLocalName() != null) { - if (partyTaxScheme.item(partyTaxSchemeIndex).getLocalName().equals("CompanyID")) { - setTaxID(partyTaxScheme.item(partyTaxSchemeIndex).getTextContent()); + } + if (currentTopElementName.equals("PartyIdentification")) { + NodeList partyID = party.item(partyIndex).getChildNodes(); + for (int partyIDIndex = 0; partyIDIndex < partyID.getLength(); partyIDIndex++) { + if (partyID.item(partyIDIndex).getLocalName() != null) { + if (partyID.item(partyIDIndex).getLocalName().equals("ID")) { + Node currentNode = partyID.item(partyIDIndex); + if ((currentNode.getAttributes() != null && + (currentNode.getAttributes().getNamedItem("schemeID") != null)) + ) { + SchemedID sID = new SchemedID().setScheme(currentNode.getAttributes().getNamedItem("schemeID").getTextContent()).setId(currentNode.getTextContent()); + addGlobalID(sID); + + } + else { + setID(currentNode.getTextContent()); + } } } + } } + + if (currentTopElementName.equals("PartyTaxScheme")) { + NodeList partyTaxScheme = party.item(partyIndex).getChildNodes(); + String CompanyId = null; + for (int partyTaxSchemeIndex = 0; partyTaxSchemeIndex < partyTaxScheme.getLength(); partyTaxSchemeIndex++) { + if (partyTaxScheme.item(partyTaxSchemeIndex).getLocalName() != null) { + if (partyTaxScheme.item(partyTaxSchemeIndex).getLocalName().equals("CompanyID")) { + CompanyId = (partyTaxScheme.item(partyTaxSchemeIndex).getTextContent()); + } + if (partyTaxScheme.item(partyTaxSchemeIndex).getLocalName().equals("TaxScheme")) { + NodeList taxSchemechilds = partyTaxScheme.item(partyTaxSchemeIndex).getChildNodes(); + for (int taxSchemechildsIndex = 0; taxSchemechildsIndex < taxSchemechilds.getLength(); taxSchemechildsIndex++) { + if (taxSchemechilds.item(taxSchemechildsIndex).getLocalName() != null) { + if (taxSchemechilds.item(taxSchemechildsIndex).getTextContent().equals("FC") || (taxSchemechilds.item(taxSchemechildsIndex).getTextContent().equals("NOVAT"))) { + setTaxID(CompanyId); + } else { + setVATID(CompanyId); + } + } + } + } + } + + } } -// if (currentTopElementName.equals("PartyTaxScheme")) { -// NodeList partyTaxScheme = party.item(partyIndex).getChildNodes(); -// for (int partyTaxSchemeIndex = 0; partyTaxSchemeIndex < partyTaxScheme.getLength(); partyTaxSchemeIndex++) { -// if (partyTaxScheme.item(partyTaxSchemeIndex).getLocalName() != null) { -// if (partyTaxScheme.item(partyTaxSchemeIndex).getLocalName().equals("TaxScheme")) { -// NodeList taxScheme = partyTaxScheme.item(partyTaxSchemeIndex).getChildNodes(); -// for (int taxSchemeIndex = 0 ; taxSchemeIndex < taxScheme.getLength(); taxSchemeIndex++) { -// if (taxScheme.item(taxSchemeIndex).getLocalName() != null) { -// if(taxScheme.item(taxSchemeIndex).getLocalName().equals("ID")){ -// if (partyTaxScheme.item(partyTaxSchemeIndex).getLocalName().equals("CompanyID")) { -// setTaxID(partyTaxScheme.item(partyTaxSchemeIndex).getTextContent()); -// } else { -// setVATID(partyTaxScheme.item(partyTaxSchemeIndex).getTextContent()); -// } -// } -// } -// } -// } -// -// } -// } -// } /* UBL only: formally it can have a name as well but BT27 party name *should* be stored in so overwrite if one exists @@ -133,17 +184,37 @@ public class TradeParty implements IZUGFeRDExportableTradeParty { if (currentTopElementName.equals("PartyLegalEntity")) { NodeList legal = party.item(partyIndex).getChildNodes(); + LegalOrganisation lo = null; for (int legalChildIndex = 0; legalChildIndex < legal.getLength(); legalChildIndex++) { if (legal.item(legalChildIndex).getLocalName() != null) { + if (legal.item(legalChildIndex).getLocalName().equals("RegistrationName")) { - setName(legal.item(legalChildIndex).getTextContent()); + if (lo == null) { + lo = new LegalOrganisation(); + } + lo.setTradingBusinessName(legal.item(legalChildIndex).getTextContent()); } if (legal.item(legalChildIndex).getLocalName().equals("CompanyLegalForm")) { setDescription(legal.item(legalChildIndex).getTextContent()); } + if (legal.item(legalChildIndex).getLocalName().equals("CompanyID")) { + if (lo == null) { + lo = new LegalOrganisation(); + } + if (legal.item(legalChildIndex).getAttributes().getNamedItem("schemeID")!=null) { + SchemedID sid = new SchemedID(legal.item(legalChildIndex).getAttributes().getNamedItem("schemeID").getNodeValue(), legal.item(legalChildIndex).getTextContent()); + lo.setSchemedID(sid); + } + } + // we dont have that attribute yet in the legalorganisation: CompanyLegalForm + if (lo != null) { + setLegalOrganisation(lo); + } + } } } + if (currentTopElementName.equals("PostalAddress")) { NodeList postal = party.item(partyIndex).getChildNodes(); @@ -191,8 +262,6 @@ public class TradeParty implements IZUGFeRDExportableTradeParty { } } - - } if (postal.item(postalChildIndex).getLocalName().equals("Name")) { setName(postal.item(postalChildIndex).getTextContent()); @@ -210,7 +279,6 @@ public class TradeParty implements IZUGFeRDExportableTradeParty { } } - } if (currentUBLChild.equals("GlobalID")) { @@ -224,57 +292,6 @@ public class TradeParty implements IZUGFeRDExportableTradeParty { NodeList contact = nodes.item(nodeIndex).getChildNodes(); setContact(new Contact(contact)); } - - if (currentUBLChild.equals("PostalTradeAddress")) { - NodeList postal = nodes.item(nodeIndex).getChildNodes(); - for (int postalChildIndex = 0; postalChildIndex < postal.getLength(); postalChildIndex++) { - if (postal.item(postalChildIndex).getLocalName() != null) { - if (postal.item(postalChildIndex).getLocalName().equals("LineOne")) { - setStreet(postal.item(postalChildIndex).getTextContent()); - } - if (postal.item(postalChildIndex).getLocalName().equals("LineTwo")) { - setAdditionalAddress(postal.item(postalChildIndex).getTextContent()); - } - if (postal.item(postalChildIndex).getLocalName().equals("LineThree")) { - setAdditionalAddressExtension(postal.item(postalChildIndex).getTextContent()); - } - if (postal.item(postalChildIndex).getLocalName().equals("CityName")) { - setLocation(postal.item(postalChildIndex).getTextContent()); - } - if (postal.item(postalChildIndex).getLocalName().equals("PostcodeCode")) { - setZIP(postal.item(postalChildIndex).getTextContent()); - } - if (postal.item(postalChildIndex).getLocalName().equals("CountryID")) { - setCountry(postal.item(postalChildIndex).getTextContent()); - } - - } - } - - } - - if (currentUBLChild.equals("PartyTaxScheme")) { - NodeList taxChilds = nodes.item(nodeIndex).getChildNodes(); - for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) { - if (taxChilds.item(taxChildIndex).getLocalName() != null) { - if ((taxChilds.item(taxChildIndex).getLocalName().equals("TaxScheme"))) { - if (taxChilds.item(taxChildIndex).getLocalName().equals("CompanyID")) { - if (taxChilds.item(taxChildIndex).getLocalName().equals("ID")) { - if (taxChilds.item(taxChildIndex).getLocalName().equals("CompanyID")) { - setVATID(taxChilds.item(taxChildIndex).getTextContent()); - } -// setTaxID(partyTaxScheme.item(partyTaxSchemeIndex).getTextContent()); - if (taxChilds.item(taxChildIndex).getAttributes().getNamedItem("ID").getNodeValue().equals("FC")) { - if (taxChilds.item(taxChildIndex).getLocalName().equals("CompanyID")) { - setTaxID(taxChilds.item(taxChildIndex).getTextContent()); - } - } - } - } - } - } - } - } } } } @@ -558,6 +575,7 @@ public class TradeParty implements IZUGFeRDExportableTradeParty { /** * primarily for invoiceimporter and JSON + * * @return the list of sepa mandates */ public List getDebitDetails() { diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java index 1eb1a6d2..0b7ca5e3 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java @@ -149,7 +149,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider { * * @return item sum +- charges/allowances */ - protected BigDecimal getTaxBasis() { + public 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); diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index a5d16dae..91f86690 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -343,6 +343,9 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter { * @return the sender's account IBAN code */ public String getIBAN() { + if ((importedInvoice==null)||(importedInvoice.getTradeSettlement()==null)) { + return null; + } for (IZUGFeRDTradeSettlement settlement : importedInvoice.getTradeSettlement()) { if (settlement instanceof IZUGFeRDTradeSettlementDebit) { return ((IZUGFeRDTradeSettlementDebit) settlement).getIBAN(); @@ -356,8 +359,6 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter { public String getHolder() { - - return extractString("//*[local-name() = 'SellerTradeParty']/*[local-name() = 'Name']"); } @@ -366,7 +367,6 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter { * @return the total payable amount */ public String getAmount() { - return importedInvoice.getGrandTotal().toPlainString(); } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java index a137a67f..12504210 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java @@ -11,6 +11,7 @@ import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile; import org.mustangproject.*; import org.mustangproject.Exceptions.ArithmetricException; import org.mustangproject.Exceptions.StructureException; +import org.mustangproject.util.NodeMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -273,6 +274,10 @@ public class ZUGFeRDInvoiceImporter { } } + public void setID(String id) { + String ud = id; + } + /*** * This will parse a XML into the given invoice object * @param zpp the invoice to be altered @@ -302,12 +307,116 @@ public class ZUGFeRDInvoiceImporter { } + //UBL... + XPathExpression shipExUBL = xpath.compile("//*[local-name()=\"Delivery\"]"); + Node deliveryNode = (Node) shipExUBL.evaluate(getDocument(), XPathConstants.NODE); + + if (deliveryNode != null) { + TradeParty delivery = new TradeParty(); + new NodeMap(deliveryNode).getAsNodeMap("DeliveryLocation").ifPresent( + deliveryLocationNodeMap -> { + + deliveryLocationNodeMap.getNode("ID").ifPresent(s -> { + SchemedID sID = new SchemedID().setScheme(s.getAttributes().getNamedItem("schemeID").getTextContent()).setId(s.getTextContent()); + delivery.addGlobalID(sID); + }); + deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> { + s.getAsString("StreetName").ifPresent(t -> delivery.setStreet(t)); + }); + deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> { + s.getAsString("AdditionalStreetName").ifPresent(t -> delivery.setAdditionalAddress(t)); + }); + deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> { + s.getAsString("CityName").ifPresent(t -> delivery.setLocation(t)); + }); + deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> { + s.getAsString("PostalZone").ifPresent(t -> delivery.setZIP(t)); + }); + deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> { + s.getAsNodeMap("Country").ifPresent(t -> t.getAsString("IdentificationCode").ifPresent(u -> delivery.setCountry(u))); + }); + deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> { + s.getAsNodeMap("AddressLine").ifPresent(t -> t.getAsString("Line").ifPresent(u -> delivery.setAdditionalAddressExtension(u))); + }); + deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> { + s.getAsString("AdditionalStreetName").ifPresent(t -> delivery.setAdditionalAddress(t)); + }); + deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> { + s.getAsString("AdditionalStreetName").ifPresent(t -> delivery.setAdditionalAddress(t)); + }); + }); + + + new NodeMap(deliveryNode).getAsNodeMap("DeliveryParty").ifPresent(partyMap -> { + partyMap.getAsNodeMap("PartyName").ifPresent(s -> { + s.getAsString("Name").ifPresent(t -> delivery.setName(t)); + }); + }); + 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(new TradeParty() + .setStreet(street) + .setAdditionalAddress(additionalStreet) + .setLocation(city) + .setZIP(postal) + .setAdditionalAddressExtension(line) + .setCountry(country) + .setName(name) + ); +*/ + + } + + xpr = xpath.compile("//*[local-name()=\"BuyerTradeParty\"]|//*[local-name()=\"AccountingCustomerParty\"]/*"); NodeList BuyerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); - xpr = xpath.compile("//*[local-name()=\"PayeeTradeParty\"]|//*[local-name()=\"PayeeParty\"]/*"); + xpr = xpath.compile("//*[local-name()=\"PayeeTradeParty\"]"); NodeList payeeNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + // UBL + XPathExpression shipPayee = xpath.compile("//*[local-name()=\"PayeeParty\"]/*"); + 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); + zpp.setPayee(new TradeParty(ublPayeeNodes)); +// TradeParty payee =new TradeParty(); +// NodeMap payeeID = new NodeMap(UBLpayeeNodes).getAsNodeMap("PartyIdentification").get(); +// if (payeeID !=null) { +// payeeID.getAsString("Name").ifPresent(t->payee.setName(t)); +// } +// if (payeeNodes != null) { +// TradeParty payee =new TradeParty(); +// NodeMap nodeMap = new NodeMap(payeeNodes).getAsNodeMap("PartyIdentification").get(); +// if (nodeMap != null) { +// nodeMap.getNode("ID").ifPresent(s -> { +// SchemedID sID = new SchemedID().setScheme(s.getAttributes().getNamedItem("schemeID").getTextContent()).setId(s.getTextContent()); +// payee.addGlobalID(sID); +// }); +// } +// } + + xpr = xpath.compile("//*[local-name()=\"ExchangedDocument\"]|//*[local-name()=\"HeaderExchangedDocument\"]"); NodeList ExchangedDocumentNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); @@ -324,6 +433,19 @@ public class ZUGFeRDInvoiceImporter { } } + xpr = xpath.compile("//*[local-name()=\"TaxBasisTotalAmount\"]|//*[local-name()=\"TaxExclusiveAmount\"]"); + BigDecimal expectedTaxBasis = null; + NodeList basisNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + if (basisNodes.getLength() > 0) { + expectedTaxBasis = new BigDecimal(XMLTools.trimOrNull(basisNodes.item(0))); + if (zpp instanceof CalculatedInvoice) { + // usually we would re-calculate the invoice to get expectedGrandTotal + // however, for "minimal" invoices or other invoices without lines + // this will not work + ((CalculatedInvoice) zpp).setTaxBasis(expectedTaxBasis); + } + } + xpr = xpath.compile("//*[local-name()=\"TotalPrepaidAmount\"]|//*[local-name()=\"PrepaidAmount\"]"); NodeList prepaidNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); if (prepaidNodes.getLength() > 0) { @@ -339,6 +461,14 @@ public class ZUGFeRDInvoiceImporter { } } + xpr = xpath.compile("//*[local-name()=\"SpecifiedTradeSettlementHeaderMonetarySummation\"]/*[local-name()=\"DuePayableAmount\"]|//*[local-name()=\"LegalMonetaryTotal\"]/*[local-name()=\"PayableAmount\"]"); + NodeList lineDueNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + if (lineDueNodes.getLength() > 0) { + if (zpp instanceof CalculatedInvoice) { + ((CalculatedInvoice) zpp).setDuePayable(new BigDecimal(XMLTools.trimOrNull(lineDueNodes.item(0)))); + } + } + Date issueDate = null; Date dueDate = null; Date deliveryDate = null; @@ -378,16 +508,34 @@ public class ZUGFeRDInvoiceImporter { subjectCode = XMLTools.trimOrNull(includedNodeChilds.item(issueDateChildIndex)); } } - switch (subjectCode){ - case "AAI": includedNotes.add(IncludedNote.generalNote(content)); break; - case "REG": includedNotes.add(IncludedNote.regulatoryNote(content)); break; - case "ABL": includedNotes.add(IncludedNote.legalNote(content)); break; - case "CUS": includedNotes.add(IncludedNote.customsNote(content)); break; - case "SUR": includedNotes.add(IncludedNote.sellerNote(content)); break; - case "TXD": includedNotes.add(IncludedNote.taxNote(content)); break; - case "ACY": includedNotes.add(IncludedNote.introductionNote(content)); break; - case "AAK": includedNotes.add(IncludedNote.discountBonusNote(content)); break; - default: includedNotes.add(IncludedNote.unspecifiedNote(content)); break; + switch (subjectCode) { + case "AAI": + includedNotes.add(IncludedNote.generalNote(content)); + break; + case "REG": + includedNotes.add(IncludedNote.regulatoryNote(content)); + break; + case "ABL": + includedNotes.add(IncludedNote.legalNote(content)); + break; + case "CUS": + includedNotes.add(IncludedNote.customsNote(content)); + break; + case "SUR": + includedNotes.add(IncludedNote.sellerNote(content)); + break; + case "TXD": + includedNotes.add(IncludedNote.taxNote(content)); + break; + case "ACY": + includedNotes.add(IncludedNote.introductionNote(content)); + break; + case "AAK": + includedNotes.add(IncludedNote.discountBonusNote(content)); + break; + default: + includedNotes.add(IncludedNote.unspecifiedNote(content)); + break; } } zpp.addNotes(includedNotes); @@ -408,7 +556,8 @@ public class ZUGFeRDInvoiceImporter { deliveryDate = new SimpleDateFormat("yyyy-MM-dd").parse(deliveryDt); } } - xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeDelivery\"]"); + + xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeDelivery\"]|//*[local-name()=\"Delivery\"]"); NodeList headerTradeDeliveryNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); for (int i = 0; i < headerTradeDeliveryNodes.getLength(); i++) { @@ -480,7 +629,7 @@ public class ZUGFeRDInvoiceImporter { } - String currency = extractString("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]/*[local-name()=\"InvoiceCurrencyCode\"]|//*[local-name()=\"DocumentCurrencyCode\"]") ; + String currency = extractString("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]/*[local-name()=\"InvoiceCurrencyCode\"]|//*[local-name()=\"DocumentCurrencyCode\"]"); zpp.setCurrency(currency); xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]|//*[local-name()=\"ApplicableSupplyChainTradeSettlement\"]"); @@ -599,7 +748,21 @@ 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) + && (paymentMeansChilds.item(meansChildIndex).getLocalName().equals("PaymentMandate"))) { + NodeList paymentMandateChilds = paymentMeansChilds.item(meansChildIndex).getChildNodes(); + for (int paymentMandateChildIndex = 0; paymentMandateChildIndex < paymentMandateChilds.getLength(); paymentMandateChildIndex++) { + if ((paymentMandateChilds.item(paymentMandateChildIndex).getLocalName() != null) && (paymentMandateChilds.item(paymentMandateChildIndex).getLocalName().equals("ID"))) { + directDebitMandateID = paymentMandateChilds.item(paymentMandateChildIndex).getTextContent(); + } + } + + } } + } zpp.setDueDate(dueDate).setDeliveryDate(deliveryDate).setIssueDate(issueDate).setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number).setDocumentCode(typeCode); @@ -617,21 +780,24 @@ public class ZUGFeRDInvoiceImporter { if (buyerOrderIssuerAssignedID != null) { zpp.setBuyerOrderReferencedDocumentID(buyerOrderIssuerAssignedID); - } - else { + } else { zpp.setBuyerOrderReferencedDocumentID(extractString("//*[local-name()=\"OrderReference\"]/*[local-name()=\"ID\"]")); } if (sellerOrderIssuerAssignedID != null) { zpp.setSellerOrderReferencedDocumentID(sellerOrderIssuerAssignedID); + } else { + zpp.setSellerOrderReferencedDocumentID(extractString("//*[local-name()=\"OrderReference\"]/*[local-name()=\"SalesOrderID\"]")); } if (despatchAdviceReferencedDocument != null) { zpp.setDespatchAdviceReferencedDocumentID(despatchAdviceReferencedDocument); + } else { + zpp.setDespatchAdviceReferencedDocumentID(extractString("//*[local-name()=\"DespatchDocumentReference\"]/*[local-name()=\"ID\"]")); } zpp.setOwnOrganisationName(extractString("//*[local-name()=\"SellerTradeParty\"]/*[local-name()=\"Name\"]|//*[local-name()=\"AccountingSupplierParty\"]/*[local-name()=\"Party\"]/*[local-name()=\"PartyName\"]").trim()); - String rounding=extractString("//*[local-name()=\"SpecifiedTradeSettlementHeaderMonetarySummation\"]/*[local-name()=\"RoundingAmount\"]|//*[local-name()=\"LegalMonetaryTotal\"]/*[local-name()=\"Party\"]/*[local-name()=\"PayableRoundingAmount\"]"); - if ((rounding!=null)&&(!rounding.isEmpty())) { + String rounding = extractString("//*[local-name()=\"SpecifiedTradeSettlementHeaderMonetarySummation\"]/*[local-name()=\"RoundingAmount\"]|//*[local-name()=\"LegalMonetaryTotal\"]/*[local-name()=\"Party\"]/*[local-name()=\"PayableRoundingAmount\"]"); + if ((rounding != null) && (!rounding.isEmpty())) { zpp.setRoundingAmount(new BigDecimal(rounding.trim())); } @@ -671,7 +837,7 @@ public class ZUGFeRDInvoiceImporter { // 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\"]|//*[local-name()=\"AllowanceCharge\"]");//CII and UBL NodeList chargeNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); for (int i = 0; i < chargeNodes.getLength(); i++) { NodeList chargeNodeChilds = chargeNodes.item(i).getChildNodes(); @@ -685,24 +851,34 @@ public class ZUGFeRDInvoiceImporter { 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"); + if (chargeNodeChilds.item(chargeChildIndex).getTextContent().trim().equalsIgnoreCase("false")) { + // UBL + isCharge = false; + } else if (chargeNodeChilds.item(chargeChildIndex).getTextContent().trim().equalsIgnoreCase("true")) { + // still UBL + isCharge = true; + } else { + //CII + 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")) { + + } else if (chargeChildName.equals("ActualAmount") || chargeChildName.equals("Amount")) { chargeAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex)); - } else if (chargeChildName.equals("Reason")) { + } else if (chargeChildName.equals("Reason") || chargeChildName.equals("AllowanceChargeReason")) { reason = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex)); - } else if (chargeChildName.equals("ReasonCode")) { + } else if (chargeChildName.equals("ReasonCode") || chargeChildName.equals("AllowanceChargeReasonCode")) { reasonCode = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex)); - } else if (chargeChildName.equals("CategoryTradeTax")) { + } else if (chargeChildName.equals("CategoryTradeTax") || chargeChildName.equals("TaxCategory")) { 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"))) { + if ((taxItemName != null) && (taxItemName.equals("RateApplicablePercent") || taxItemName.equals("ApplicablePercent") || taxItemName.equals("Percent"))) { taxPercent = XMLTools.trimOrNull(taxChilds.item(taxChildIndex)); } } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/DeSerializationTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/DeSerializationTest.java index 0dbd2dc0..a9c35c1b 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/DeSerializationTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/DeSerializationTest.java @@ -24,21 +24,25 @@ package org.mustangproject.ZUGFeRD; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import junit.framework.TestCase; +import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; import org.mustangproject.*; +import org.mustangproject.ZUGFeRD.model.EventTimeCodeTypeConstants; import javax.xml.xpath.XPathExpressionException; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.Date; @FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class DeSerializationTest extends ResourceCase { +public class DeSerializationTest extends ResourceCase { public void testJackson() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); @@ -68,7 +72,7 @@ public class DeSerializationTest extends ResourceCase { hasExceptions = true; } - CalculatedInvoice ci=new CalculatedInvoice(); + CalculatedInvoice ci = new CalculatedInvoice(); try { zii.extractInto(ci); } catch (XPathExpressionException e) { @@ -154,14 +158,57 @@ public class DeSerializationTest extends ResourceCase { " }\n" + " ]\n" + "}", Invoice.class); - TransactionCalculator tc=new TransactionCalculator(fromJSON); - assertEquals(tc.getGrandTotal(),new BigDecimal("234.43")); + TransactionCalculator tc = new TransactionCalculator(fromJSON); + assertEquals(tc.getGrandTotal(), new BigDecimal("234.43")); assertEquals(fromJSON.getNumber(), fromJSON.getNumber()); assertEquals(fromJSON.getZFItems().length, fromJSON.getZFItems().length); } + public void testIssuerAssignedIDRoundtrip() { + String occurrenceFrom = "20201001"; + String occurrenceTo = "20201005"; + String contractID = "376zreurzu0983"; + + String orgID = "0009845"; + String orgname = "Test company"; + String number = "123"; + String priceStr = "1.00"; + String taxID = "9990815"; + BigDecimal price = new BigDecimal(priceStr); + Invoice newInvoiceFromJSON = null; + boolean hasExceptions = false; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + try { + SchemedID gtin = new SchemedID("0160", "2001015001325"); + SchemedID gln = new SchemedID("0088", "4304171000002"); + Invoice i = new Invoice().setCurrency("CHF").addNote("document level 1/2").addNote("document level 2/2").setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()) + .setSellerOrderReferencedDocumentID("9384").setBuyerOrderReferencedDocumentID("28934") + .setDetailedDeliveryPeriod(new SimpleDateFormat("yyyyMMdd").parse(occurrenceFrom), new SimpleDateFormat("yyyyMMdd").parse(occurrenceTo)) + .setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID(taxID).setEmail("sender@test.org").setID(orgID).addVATID("DE0815")) + .setDeliveryAddress(new TradeParty("just the other side of the street", "teststr.12a", "55232", "Entenhausen", "DE").addVATID("DE47110")) + .setContractReferencedDocument(contractID) + .setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addGlobalID(gln).setEmail("recipient@test.org").addVATID("DE4711") + .setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE").setFax("++49555123456")).setAdditionalAddress("Hinterhaus 3")) + .addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(16)).addGlobalID(gtin).setSellerAssignedID("4711"), price, new BigDecimal(1.0)).setId("a123").addReferencedLineID("xxx").addNote("item level 1/1").addAllowance(new Allowance(new BigDecimal(0.02)).setReason("item discount").setTaxPercent(new BigDecimal(16))).setDetailedDeliveryPeriod(sdf.parse("2020-01-13"), sdf.parse("2020-01-15"))) + .addCharge(new Charge(new BigDecimal(0.5)).setReason("quick delivery charge").setTaxPercent(new BigDecimal(16))) + .addAllowance(new Allowance(new BigDecimal(0.2)).setReason("discount").setTaxPercent(new BigDecimal(16))) + .addCashDiscount(new CashDiscount(new BigDecimal(2), 14)) + .setDeliveryDate(sdf.parse("2020-11-02")).setNumber(number).setVATDueDateTypeCode(EventTimeCodeTypeConstants.PAYMENT_DATE); + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(i); + newInvoiceFromJSON = mapper.readValue(json, Invoice.class); + } catch (ParseException e) { + hasExceptions = true; + } catch (JsonProcessingException e) { + hasExceptions = true; + } + assertEquals(newInvoiceFromJSON.getBuyerOrderReferencedDocumentID(), "28934"); + assertFalse(hasExceptions); + + + } public void testDueDateRoundtrip() throws JsonProcessingException { @@ -219,4 +266,389 @@ public class DeSerializationTest extends ResourceCase { } + public void testDirectDebit() throws JsonProcessingException { + + ObjectMapper mapper = new ObjectMapper(); + + // [{"stringValue":"a","intValue":1,"booleanValue":true}, + // {"stringValue":"bc","intValue":3,"booleanValue":false}] + + boolean exceptions = false; + String theXML = ""; + try { + Invoice fromJSON = mapper.readValue("\n" + + "\t{\n" + + "\t\t\"documentCode\": \"380\",\n" + + "\t\t\"number\": \"F20220031\",\n" + + "\t\t\"referenceNumber\": \"SERVEXEC\",\n" + + "\t\t\"buyerOrderReferencedDocumentID\": \"PO201925478\",\n" + + "\t\t\"ownOrganisationName\": \"LE FOURNISSEUR\",\n" + + "\t\t\"currency\": \"EUR\",\n" + + "\t\t\"issueDate\": \"2022-01-30T23:00:00.000+00:00\",\n" + + "\t\t\"dueDate\": \"2022-03-01T23:00:00.000+00:00\",\n" + + "\t\t\"deliveryDate\": \"2022-01-27T23:00:00.000+00:00\",\n" + + "\t\t\"sender\": {\n" + + "\t\t\"name\": \"LE FOURNISSEUR\",\n" + + "\t\t\t\"zip\": \"75018\",\n" + + "\t\t\t\"street\": \"35 rue d'ici\",\n" + + "\t\t\t\"location\": \"PARIS\",\n" + + "\t\t\t\"country\": \"FR\",\n" + + "\t\t\t\"vatID\": \"FR11123456782\",\n" + + "\t\t\t\"additionalAddress\": \"Seller line 2\",\n" + + "\t\t\t\"additionalAddressExtension\": \"Seller line 3\",\n" + + "\t\t\t\"bankDetails\": [\n" + + "\t\t{\n" + + "\t\t\t\"accountName\": null,\n" + + "\t\t\t\"iban\": \"FR20 1254 2547 2569 8542 5874 698\",\n" + + "\t\t\t\"bic\": \"BIC_MONCOMPTE\"\n" + + "\t\t}\n" + + " ],\n" + + "\t\t\"debitDetails\": [\n" + + "\t\t{\n" + + "\t\t\t\"mandate\": \"MANDATE PT\",\n" + + "\t\t\t\"iban\": \"FR20 1254 2547 2569 8542 5874 698\"\n" + + "\t\t}\n" + + " ],\n" + + "\t\t\"contact\": {\n" + + "\t\t\t\"name\": \"M. CONTACT\",\n" + + "\t\t\t\t\"phone\": \"01 02 03 54 87\",\n" + + "\t\t\t\t\"email\": \"seller@seller.com\",\n" + + "\t\t\t\t\"zip\": null,\n" + + "\t\t\t\t\"street\": null,\n" + + "\t\t\t\t\"location\": null,\n" + + "\t\t\t\t\"country\": null,\n" + + "\t\t\t\t\"fax\": null,\n" + + "\t\t\t\t\"vatid\": null,\n" + + "\t\t\t\t\"id\": null,\n" + + "\t\t\t\t\"additionalAddress\": null\n" + + "\t\t},\n" + + "\t\t\"email\": \"moi@seller.com\",\n" + + "\t\t\t\"vatid\": \"FR11123456782\",\n" + + "\t\t\t\"id\": \"123\",\n" + + "\t\t\t\"legalOrganisation\": {\n" + + "\t\t\t\"schemedID\": null,\n" + + "\t\t\t\t\"tradingBusinessName\": \"SELLER TRADE NAME\"\n" + + "\t\t},\n" + + "\t\t\"globalID\": \"587451236587\",\n" + + "\t\t\t\"globalIDScheme\": \"0088\"\n" + + "\t},\n" + + "\t\t\"recipient\": {\n" + + "\t\t\"name\": \"LE CLIENT\",\n" + + "\t\t\t\"zip\": \"06000\",\n" + + "\t\t\t\"street\": \"MON ADRESSE LIGNE 1\",\n" + + "\t\t\t\"location\": \"MA VILLE\",\n" + + "\t\t\t\"country\": \"FR\",\n" + + "\t\t\t\"vatID\": \"FR 05 987 654 321\",\n" + + "\t\t\t\"additionalAddress\": \"Buyer line 2\",\n" + + "\t\t\t\"additionalAddressExtension\": \"Buyer line 3\",\n" + + "\t\t\t\"contact\": {\n" + + "\t\t\t\"name\": \"Buyer contact name\",\n" + + "\t\t\t\t\"phone\": \"01 01 25 45 87\",\n" + + "\t\t\t\t\"email\": \"buyer@buyer.com\",\n" + + "\t\t\t\t\"zip\": null,\n" + + "\t\t\t\t\"street\": null,\n" + + "\t\t\t\t\"location\": null,\n" + + "\t\t\t\t\"country\": null,\n" + + "\t\t\t\t\"fax\": null,\n" + + "\t\t\t\t\"vatid\": null,\n" + + "\t\t\t\t\"id\": null,\n" + + "\t\t\t\t\"additionalAddress\": null\n" + + "\t\t},\n" + + "\t\t\"email\": \"me@buyer.com\",\n" + + "\t\t\t\"vatid\": \"FR 05 987 654 321\",\n" + + "\t\t\t\"legalOrganisation\": {\n" + + "\t\t\t\"schemedID\": null,\n" + + "\t\t\t\t\"tradingBusinessName\": null\n" + + "\t\t},\n" + + "\t\t\"globalID\": \"3654789851\",\n" + + "\t\t\t\"globalIDScheme\": \"0088\"\n" + + "\t},\n" + + "\t\t\"deliveryAddress\": {\n" + + "\t\t\"name\": \"DEL Name\",\n" + + "\t\t\t\"zip\": \"06000\",\n" + + "\t\t\t\"street\": \"DEL ADRESSE LIGNE 1\",\n" + + "\t\t\t\"location\": \"NICE\",\n" + + "\t\t\t\"country\": \"FR\",\n" + + "\t\t\t\"additionalAddress\": \"DEL line 2\",\n" + + "\t\t\t\"id\": \"PRIVATE_ID_DEL\"\n" + + "\t},\n" + + "\t\t\"payee\": {\n" + + "\t\t\"name\": \"PAYEE NAME\",\n" + + "\t\t\t\"legalOrganisation\": {\n" + + "\t\t\t\"schemedID\": null,\n" + + "\t\t\t\t\"tradingBusinessName\": null\n" + + "\t\t},\n" + + "\t\t\"globalID\": \"587451236586\",\n" + + "\t\t\t\"globalIDScheme\": \"0088\"\n" + + "\t},\n" + + "\t\t\"sellerOrderReferencedDocumentID\": \"SALES REF 2547\",\n" + + "\t\t\"despatchAdviceReferencedDocumentID\": \"DESPADV002\",\n" + + "\t\t\"grandTotal\": 107.82,\n" + + "\t\t\"detailedDeliveryPeriodFrom\": \"2021-12-31T23:00:00.000+00:00\",\n" + + "\t\t\"detailedDeliveryPeriodTo\": \"2022-12-30T23:00:00.000+00:00\",\n" + + "\t\t\"notesWithSubjectCode\": [\n" + + "\t\t{\n" + + "\t\t\t\"content\": \"FOURNISSEUR F SARL au capital de 50 000 EUR\",\n" + + "\t\t\t\"subjectCode\": \"REG\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"content\": \"RCS MAVILLE 123 456 782\",\n" + + "\t\t\t\"subjectCode\": \"ABL\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"content\": \"35 ma rue a moi, code postal Ville Pays – contact@masociete.fr - www.masociete.fr – N° TVA : FR32 123 456 789\",\n" + + "\t\t\t\"subjectCode\": \"AAI\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"content\": \"Tout retard de paiement engendre une pénalité exigible à compter de la date d'échéance, calculée sur la base de trois fois le taux d'intérêt légal.\",\n" + + "\t\t\t\"subjectCode\": null\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"content\": \"Indemnité forfaitaire pour frais de recouvrement en cas de retard de paiement : 40 €.\",\n" + + "\t\t\t\"subjectCode\": null\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"content\": \"Les réglements reçus avant la date d'échéance ne donneront pas lieu à escompte.\",\n" + + "\t\t\t\"subjectCode\": null\n" + + "\t\t}\n" + + " ],\n" + + "\t\t\"zfallowances\": [\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": \"REMISE VOLUME\",\n" + + "\t\t\t\"reasonCode\": \"71\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": \"REMISE VOLUME\",\n" + + "\t\t\t\"reasonCode\": \"71\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": \"REMISE VOLUME\",\n" + + "\t\t\t\"reasonCode\": \"71\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": null,\n" + + "\t\t\t\"reasonCode\": \"100\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 2,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": \"REMISE VOLUME\",\n" + + "\t\t\t\"reasonCode\": \"71\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": \"REMISE VOLUME\",\n" + + "\t\t\t\"reasonCode\": \"71\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": \"REMISE VOLUME\",\n" + + "\t\t\t\"reasonCode\": \"71\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": null,\n" + + "\t\t\t\"reasonCode\": \"100\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1.4,\n" + + "\t\t\t\"taxPercent\": 20,\n" + + "\t\t\t\"reason\": \"REMISE COMMERCIALE\",\n" + + "\t\t\t\"reasonCode\": \"100\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1.2,\n" + + "\t\t\t\"taxPercent\": 10,\n" + + "\t\t\t\"reason\": \"REMISE COMMERCIALE\",\n" + + "\t\t\t\"reasonCode\": \"100\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t}\n" + + " ],\n" + + "\t\t\"zfcharges\": [\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": \"FRAIS PALETTE\",\n" + + "\t\t\t\"reasonCode\": null,\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": \"FRAIS PALETTE\",\n" + + "\t\t\t\"reasonCode\": null,\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": \"FRAIS PALETTE\",\n" + + "\t\t\t\"reasonCode\": null,\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": \"FRAIS PALETTE\",\n" + + "\t\t\t\"reasonCode\": null,\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": null,\n" + + "\t\t\t\"reasonCode\": \"ADL\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": \"FRAIS PALETTE\",\n" + + "\t\t\t\"reasonCode\": null,\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 1,\n" + + "\t\t\t\"taxPercent\": null,\n" + + "\t\t\t\"reason\": \"FRAIS PALETTE\",\n" + + "\t\t\t\"reasonCode\": null,\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 2.8,\n" + + "\t\t\t\"taxPercent\": 20,\n" + + "\t\t\t\"reason\": \"FRAIS DEPLACEMENT\",\n" + + "\t\t\t\"reasonCode\": \"FC\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"percent\": null,\n" + + "\t\t\t\"totalAmount\": 0.6,\n" + + "\t\t\t\"taxPercent\": 10,\n" + + "\t\t\t\"reason\": \"FRAIS DEPLACEMENT\",\n" + + "\t\t\t\"reasonCode\": \"ADR\",\n" + + "\t\t\t\"categoryCode\": \"S\"\n" + + "\t\t}\n" + + " ],\n" + + "\t\t\"tradeSettlement\": [\n" + + "\t\t{\n" + + "\t\t\t\"accountName\": null,\n" + + "\t\t\t\"iban\": \"FR20 1254 2547 2569 8542 5874 698\",\n" + + "\t\t\t\"bic\": \"BIC_MONCOMPTE\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"mandate\": \"MANDATE PT\",\n" + + "\t\t\t\"iban\": \"FR20 1254 2547 2569 8542 5874 698\"\n" + + "\t\t}\n" + + " ],\n" + + "\t\t\"zfitems\": [\n" + + "\t\t{\n" + + "\t\t\t\"price\": 60,\n" + + "\t\t\t\"quantity\": 1,\n" + + "\t\t\t\"basisQuantity\": 1,\n" + + "\t\t\t\"product\": {\n" + + "\t\t\t\"unit\": \"C62\",\n" + + "\t\t\t\t\"name\": \"REMBOURSEMENT AFFRANCHISSEMENT\",\n" + + "\t\t\t\t\"description\": \"Description\",\n" + + "\t\t\t\t\"taxCategoryCode\": \"Z\",\n" + + "\t\t\t\t\"vatpercent\": 0,\n" + + "\t\t\t\t\"reverseCharge\": false,\n" + + "\t\t\t\t\"intraCommunitySupply\": false,\n" + + "\t\t\t\t\"globalID\": \"598785412598745\",\n" + + "\t\t\t\t\"globalIDScheme\": \"0160\"\n" + + "\t\t},\n" + + "\t\t\t\"buyerOrderReferencedDocumentLineID\": \"1\",\n" + + "\t\t\t\"value\": 60\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"price\": 30,\n" + + "\t\t\t\"quantity\": 3,\n" + + "\t\t\t\"basisQuantity\": 3,\n" + + "\t\t\t\"product\": {\n" + + "\t\t\t\"unit\": \"C62\",\n" + + "\t\t\t\t\"name\": \"FOURNITURES DIVERSES\",\n" + + "\t\t\t\t\"description\": \"Description\",\n" + + "\t\t\t\t\"taxCategoryCode\": \"S\",\n" + + "\t\t\t\t\"vatpercent\": 20,\n" + + "\t\t\t\t\"reverseCharge\": false,\n" + + "\t\t\t\t\"intraCommunitySupply\": false\n" + + "\t\t},\n" + + "\t\t\t\"buyerOrderReferencedDocumentLineID\": \"3\",\n" + + "\t\t\t\"value\": 30\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"price\": 12,\n" + + "\t\t\t\"quantity\": 1,\n" + + "\t\t\t\"basisQuantity\": 1,\n" + + "\t\t\t\"product\": {\n" + + "\t\t\t\"unit\": \"C62\",\n" + + "\t\t\t\t\"name\": \"APPEL\",\n" + + "\t\t\t\t\"description\": \"Description\",\n" + + "\t\t\t\t\"taxCategoryCode\": \"S\",\n" + + "\t\t\t\t\"vatpercent\": 10,\n" + + "\t\t\t\t\"reverseCharge\": false,\n" + + "\t\t\t\t\"intraCommunitySupply\": false\n" + + "\t\t},\n" + + "\t\t\t\"buyerOrderReferencedDocumentLineID\": \"2\",\n" + + "\t\t\t\"value\": 12\n" + + "\t\t}\n" + + " ],\n" + + "\t\t\"ownStreet\": \"35 rue d'ici\",\n" + + "\t\t\"ownCountry\": \"FR\",\n" + + "\t\t\"ownZIP\": \"75018\",\n" + + "\t\t\"ownLocation\": \"PARIS\",\n" + + "\t\t\"ownVATID\": \"FR11123456782\",\n" + + "\t\t\"valid\": false\n" + + "\t}\n", Invoice.class); + ZUGFeRD2PullProvider zf2p = new ZUGFeRD2PullProvider(); + zf2p.setProfile(Profiles.getByName("XRechnung")); + zf2p.generateXML(fromJSON); + theXML = new String(zf2p.getXML()); + } catch (Exception e) { + exceptions = true; + } + assertTrue(theXML.contains("pour frais de recouvrement en cas de retard de paiement")); + assertFalse(exceptions); + + } + + } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java index f60029c1..64cd8871 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java @@ -281,12 +281,16 @@ public class ZF2ZInvoiceImporterTest extends ResourceCase { public void testXRImport() { boolean hasExceptions = false; - ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(); + ZUGFeRDImporter zii = new ZUGFeRDImporter(); + + int version=-1; try { zii.fromXML(new String(Files.readAllBytes(Paths.get("./target/testout-XR-Edge.xml")), StandardCharsets.UTF_8)); - + version=zii.getVersion(); } catch (IOException e) { hasExceptions = true; + } catch (Exception e) { + throw new RuntimeException(e); } Invoice invoice = null; @@ -296,8 +300,17 @@ public class ZF2ZInvoiceImporterTest extends ResourceCase { hasExceptions = true; } assertFalse(hasExceptions); + + + TransactionCalculator tc = new TransactionCalculator(invoice); assertEquals(new BigDecimal("1.00"), tc.getGrandTotal()); + + assertEquals(version,2); + assertTrue(new BigDecimal("1").compareTo(invoice.getZFItems()[0].getQuantity()) == 0); + LineCalculator lc=new LineCalculator(invoice.getZFItems()[0]); + assertTrue(new BigDecimal("1").compareTo(lc.getItemTotalNetAmount()) == 0); + assertTrue(invoice.getTradeSettlement().length == 1); assertTrue(invoice.getTradeSettlement()[0] instanceof IZUGFeRDTradeSettlementPayment); IZUGFeRDTradeSettlementPayment paym = (IZUGFeRDTradeSettlementPayment) invoice.getTradeSettlement()[0]; @@ -380,6 +393,62 @@ public class ZF2ZInvoiceImporterTest extends ResourceCase { } + /* +this would test if for all elements/attributes + * + + public void testEEISI_300_cii_Import() throws XPathExpressionException, ParseException { + boolean hasExceptions = false; + File inputCII = getResourceAsFile("not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.cii.xml"); + File inputUBL = getResourceAsFile("not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.ubl.xml"); + + + ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(); + zii.doIgnoreCalculationErrors(); + try { + zii.fromXML(new String(Files.readAllBytes(inputCII.toPath()), StandardCharsets.UTF_8)); + + } catch (IOException e) { + hasExceptions = true; + } + + Invoice invoiceUBL = null; + invoiceUBL = zii.extractInvoice(); + + try { + zii.ignoreCalculationErrors=true; + zii.fromXML(new String(Files.readAllBytes(inputUBL.toPath()), StandardCharsets.UTF_8)); + + } catch (IOException e) { + hasExceptions = true; + } + + Invoice invoiceCII = null; + try { + invoiceCII = zii.extractInvoice(); + ObjectMapper mapper = new ObjectMapper(); + String ubl=mapper.writeValueAsString(invoiceUBL).replace("," ,"\n"); + String cii=mapper.writeValueAsString(invoiceCII).replace("," ,"\n"); + + assertEquals(cii,ubl); + + + /* + Seller contact point + +41 345 654455 + seller@contact.de);* + } catch (XPathExpressionException | ParseException e) { + hasExceptions = true; + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + assertFalse(hasExceptions); + +// TransactionCalculator tc = new TransactionCalculator(invoiceCII); +// assertEquals(new BigDecimal("205.00"), tc.getGrandTotal()); + + } +*/ @Test public void testImportPrepaid() throws XPathExpressionException, ParseException { InputStream inputStream = this.getClass() @@ -395,11 +464,14 @@ public class ZF2ZInvoiceImporterTest extends ResourceCase { assertTrue(isBD); BigDecimal expectedPrepaid=new BigDecimal(50); BigDecimal expectedLineTotal=new BigDecimal("180.76"); + BigDecimal expectedDue=new BigDecimal("147.65"); if (isBD) { BigDecimal amread=invoice.getTotalPrepaidAmount(); - BigDecimal amline=invoice.getLineTotalAmount(); + BigDecimal importedLineTotal=invoice.getLineTotalAmount(); + BigDecimal importedDuePayable=invoice.getDuePayable(); assertTrue(amread.compareTo(expectedPrepaid) == 0); - assertTrue(amline.compareTo(expectedLineTotal) == 0); + assertTrue(importedLineTotal.compareTo(expectedLineTotal) == 0); + assertTrue(importedDuePayable.compareTo(expectedDue) == 0); } } diff --git a/library/src/test/resources/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.cii.xml b/library/src/test/resources/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.cii.xml index 1b88d4d4..8b5bb189 100644 --- a/library/src/test/resources/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.cii.xml +++ b/library/src/test/resources/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.cii.xml @@ -1,8 +1,5 @@ - + BT-23 Business Process Type @@ -19,11 +16,11 @@ invoice note text - AAA + #AAA# invoice note text 2 - AAA + #AAA# @@ -35,9 +32,7 @@ - Item standar identifier - - + Item standar identifier Item seller's identifier Item buyer's identifier Item name @@ -98,9 +93,9 @@ false 1.00 - 100.00 + 1000.00 10.00 - 95 + 55 Invoice line allowance reason @@ -108,17 +103,18 @@ true 1.00 - 100.00 + 1000.00 10.00 AAA Invoice line charge reason - 100.00 + 1000.00 Line object identifier 130 + 6789 @@ -147,7 +143,7 @@ 0.00 - 100.00 + 1000.00 @@ -159,7 +155,7 @@ Seller name Seller additional legal information - + Seller legal identifier Seller trading name @@ -181,7 +177,7 @@ Seller country subdivision - Seller electronic address + Seller electronic address DE12345677 @@ -216,7 +212,7 @@ Buyer country subdivision - Buyer electronic address + Buyer electronic address IE394838894 @@ -256,7 +252,7 @@ rst 130 - AAA + 0090 456 @@ -315,32 +311,32 @@ IT1212341234123412 Payment account name - - - + BSCTCH22 + - 5.00 + 50.00 VAT - 100.00 + 1000.00 S - + 29 5.00 0.00 VAT Exemtion reason text - 100.00 + 1000.00 E - VATEX-EU-O + Exemption reason code 29 0.00 @@ -357,9 +353,9 @@ false 1.00 - 100.00 + 1000.00 10.00 - 95 + 55 Doc allowance reason text VAT @@ -372,7 +368,7 @@ true 1.00 - 100.00 + 1000.00 10.00 AAA Doc charge reason text @@ -390,16 +386,16 @@ Mandate reference identifier - 200.00 + 2000.00 10.00 10.00 - 200.00 - 5.00 - 4.60 + 2000.00 + 50.00 + 46.00 0.00 - 205.00 + 2050.00 0.00 - 205.00 + 2050.00 abc123 diff --git a/library/src/test/resources/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.ubl.xml b/library/src/test/resources/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.ubl.xml index 6aec88d9..6e850cc1 100644 --- a/library/src/test/resources/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.ubl.xml +++ b/library/src/test/resources/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.ubl.xml @@ -1,365 +1,401 @@ - - urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0 - urn:fdc:peppol.eu:2017:poacc:billing:01:1.0 + + urn:cen.eu:en16931:2017 + BT-23 Business Process Type Test_EeISI_100 2018-11-12 2018-11-30 380 - #AAA#invoice note text - #AAA#invoice note text 2 + ##AAA##invoice note text + ##AAA##invoice note text 2 EUR NOK uvz 123 - 2018-11-12 - 2018-11-30 - - - abc - def - - - - abc123 - 2018-10-04 - - - - lmn - - - ghi - - - 789 - - - Supporting document ref - Supporting document descr - - ZGVmYXVsdA== - - External document location - - - - - rst - 130 - - - 456 - - - - Seller electronic address - - Seller identifier 1 - - - Seller identifier 2 - - - Seller trading name - - - Seller address line 1 - Seller address line 2 - Seller city - 12345 - Seller country subdivision - - Seller address line 3 - - - DE - - - - DE12345677 - - VAT - - - - DE49294093 - - FC - - - - Seller name - Seller additional legal information - - - Seller contact point - +41 345 654455 - seller@contact.de - - - - - - Buyer electronic address - - Buyer identifier - - - Buyer trading name - - - Buyer address line 1 - Buyer address line 2 - Buyer city - 34562 - Buyer country subdivision - - Buyer address line 3 - - - IE - - - - IE394838894 - - VAT - - - - Buyer name - Buyer legal registration identifier - - - Buyer contact point - +353 2948584 - buyer@contact.ie - - - - - - Payee identifier - - - Payee name - - - - - Tax representative name - - - Tax representative address line 1 - Tax representative address line 2 - Tax representative city - 23455 - Tax representative country subdivision - - Tax representative address line 3 - - - DE - - - - DE3949053 - - VAT - - - - - 2018-12-04 - - deliver location identifier - - Deliver to address line 1 - Deliver to address line 2 - Deliver to city - 98765 - Deliver to country subdivision - - Deliver to address line 3 - - - IE - - - - - - Deliver to party name - - - - - total amount - - - false - 95 - Doc allowance reason text - 1.00 - 10 - 1000 - - S - 5 - - VAT - - - - - true - AAA - Doc charge reason text - 1.00 - 10 - 1000 - - S - 5 - - VAT - - - - - 50 - - 1000 - 50 - - S - 5 - - VAT - - - - - 1000 - 0 - - E - 0 - VATEX-EU-O - Exemtion reason text - - VAT - - - - - - 46 - - - 200 - 200 - 205 - 10 - 10 - 0 - 205 - - - 1a - Invoice line note - 10 - 1000 - 6789 - 2018-11-12 2018-11-30 - - - 12345 - - - Line object identifier + 35 + + + abc + def + + + + abc123 + 2018-10-04 + + + + lmn + + + ghi + + + opq + + + 789 + + + rst 130 - - + + + Supporting document ref + Supporting document descr + + ZGVmYXVsdA== + + External document location + + + + + 456 + + + + Seller electronic address + + Seller identifier 1 + + + Seller identifier 2 + + + Seller trading name + + + Seller address line 1 + Seller address line 2 + Seller city + 12345 + Seller country subdivision + + Seller address line 3 + + + DE + + + + DE12345677 + + VAT + + + + DE49294093 + + NOVAT + + + + Seller name + Seller legal identifier + Seller additional legal information + + + Seller contact point + +41 345 654455 + seller@contact.de + + + + + + Buyer electronic address + + 0190:Buyer identifier + + + Buyer trading name + + + Buyer address line 1 + Buyer address line 2 + Buyer city + 34562 + Buyer country subdivision + + Buyer address line 3 + + + IE + + + + IE394838894 + + VAT + + + + Buyer name + Buyer legal registration identifier + + + Buyer contact point + +353 2948584 + buyer@contact.ie + + + + + + Payee identifier + + + Payee name + + + Payee legal registration identifier + + + + + Tax representative name + + + Tax representative address line 1 + Tax representative address line 2 + Tax representative city + 23455 + Tax representative country subdivision + + Tax representative address line 3 + + + DE + + + + DE3949053 + + VAT + + + + + 2018-12-04 + + deliver location identifier + + Deliver to address line 1 + Deliver to address line 2 + Deliver to city + 98765 + Deliver to country subdivision + + Deliver to address line 3 + + + IE + + + + + + Deliver to party name + + + + + 4 + Remittance information + + 1234 + mandatory network id + Payment card holder name + + + IT1212341234123412 + Payment account name + + BSCTCH22 + + + + IT1212341234123413 + Payment account name 2 + + BSCTCH22 + + + + Mandate reference identifier + + Debited account identifier + + + + + total amount + + false - 95 - Invoice line allowance reason - 1.00 - 10 - 1000 - - + 55 + Doc allowance reason text + 1.0000 + 10.00 + 1000.00 + + S + 5.00 + + VAT + + + + true AAA - Invoice line charge reason - 1.00 - 10 - 1000 - - - Item description - Item name - - Item buyer's identifier - - - Item seller's identifier - - - Item standar identifier - - - IT - - - Item classification identifier0 - - - S - 5 - - VAT - - - - Color - Red - - - Size - L - - - - 10 - 1 + Doc charge reason text + 1.0000 + 10.00 + 1000.00 + + S + 5.00 + + VAT + + + + + 46.00 + + + 50.00 + + 1000.00 + 50.00 + + S + 5.00 + + VAT + + + + + 1000.00 + 0.00 + + E + 0.00 + Exemption reason code + Exemtion reason text + + VAT + + + + + + 2000.00 + 2000.00 + 2050.00 + 10.00 + 10.00 + 2050.00 + + + 1a + Invoice line note + 10.00000000 + 1000.00 + 6789 + + 2018-11-12 + 2018-11-30 + + + 12345 + + + Line object identifier + 130 + - false - 1 - 11 + false + 55 + Invoice line allowance reason + 1 + 10 + 1000 - + + true + AAA + Invoice line charge reason + 1 + 10 + 1000 + + + Item description + Item name + + Item buyer's identifier + + + Item seller's identifier + + + Item standar identifier + + + IT + + + Item classification identifier0 + + + S + 5.00 + + VAT + + + + Color + Red + + + Size + L + + + + 10.00 + 1.00 + + false + 1 + 11 + + - 1b - 10 - 1000 - - Item name 2 - - E - 0 - - VAT - - - - - 10 - + 1b + 10.00000000 + 1000.00 + + Item name 2 + + E + 0.00 + + VAT + + + + + 10.00 + - + diff --git a/library/src/test/resources/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel2.ubl.xml b/library/src/test/resources/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel2.ubl.xml deleted file mode 100644 index 7e71103c..00000000 --- a/library/src/test/resources/not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel2.ubl.xml +++ /dev/null @@ -1,349 +0,0 @@ - - - urn:cen.eu:en16931:2017 - BT-23 Business Process Type - Test_EeISI_100 - 2018-11-12 - 2018-11-30 - 380 - ##AAA##invoice note text - ##AAA##invoice note text 2 - EUR - NOK - uvz - 123 - - 2018-11-12 - 2018-11-30 - 35 - - - abc - def - - - - abc123 - 2018-10-04 - - - - lmn - - - ghi - - - opq - - - 789 - - - rst - 130 - - - Supporting document ref - Supporting document descr - - ZGVmYXVsdA== - - External document location - - - - - 456 - - - - Seller electronic address - - Seller identifier 1 - - - Seller identifier 2 - - - Bank assigned creditor identifier - - - Seller trading name - - - Seller address line 1 - Seller address line 2 - Seller city - 12345 - Seller country subdivision - - Seller address line 3 - - - DE - - - - DE12345677 - - VAT - - - - DE49294093 - - NOVAT - - - - Seller name - Seller legal identifier - Seller additional legal information - - - Seller contact point - +41 345 654455 - seller@contact.de - - - - - - Buyer electronic address - - 0190:Buyer identifier - - - Buyer trading name - - - Buyer address line 1 - Buyer address line 2 - Buyer city - 34562 - Buyer country subdivision - - Buyer address line 3 - - - IE - - - - IE394838894 - - VAT - - - - Buyer name - Buyer legal registration identifier - - - Buyer contact point - +353 2948584 - buyer@contact.ie - - - - - - Payee identifier - - - Payee name - - - Payee legal registration identifier - - - - - Tax representative name - - - Tax representative address line 1 - Tax representative address line 2 - Tax representative city - 23455 - Tax representative country subdivision - - Tax representative address line 3 - - - DE - - - - DE3949053 - - VAT - - - - - 2018-12-04 - - deliver location identifier - - Deliver to address line 1 - Deliver to address line 2 - Deliver to city - 98765 - Deliver to country subdivision - - Deliver to address line 3 - - - IE - - - - - - Deliver to party name - - - - - 4 - Remittance information - - 1234 - mandatory network id - Payment card holder name - - - IT1212341234123412 - Payment account name - - BSCTCH22 - - - - IT1212341234123413 - Payment account name 2 - - BSCTCH22 - - - - Mandate reference identifier - - Debited account identifier - - - - - total amount - - - 50.00 - - 1000.00 - 50.00 - - S - 5.00 - - VAT - - - - - 1000.00 - 0.00 - - E - 0.00 - Exemption reason code - Exemtion reason text - - VAT - - - - - - 200.00 - 200.00 - 205.00 - 205.00 - - - 1a - Invoice line note - 10.00000000 - 1000.00 - 6789 - - 2018-11-12 - 2018-11-30 - - - 12345 - - - Line object identifier - 130 - - - Item description - Item name - - Item buyer's identifier - - - Item seller's identifier - - - Item standar identifier - - - IT - - - Item classification identifier0 - - - S - 5.00 - - VAT - - - - Color - Red - - - Size - L - - - - 10.00 - 1.00 - - - - - 1b - 10.00000000 - 100.00 - - Item name 2 - - E - 0.00 - - VAT - - - - - 10.00 - - -