diff --git a/History.md b/History.md
index 90d1cdb4..62eeec43 100644
--- a/History.md
+++ b/History.md
@@ -1,21 +1,50 @@
+- correcly write charge reason codes also for non-Xrechnung #617
+- correctly import additional referenced documents into invoice/corrected setting of attachments from jackson
+- corrected parseException structure
+- allow 1p0 as potential xmp version number
+- #618 import BT-20
+
+2.15.1
+=======
+2024-12-07
+- #566 Failed to parse PDF - Could not reproduce the invoice
+- closes #579 prepaidamount is only read in UBL
+- #581 parse lineTotalAmount, TaxBasisAmount, duePayableAmount
+- #576 read lineid, #578 set lineid
+- log error ids, be able to access them from context
+- #503 import more ubl
+- allow jackson to run over more classes, e.g., DirectDebit, bean contructor for direct debit
+- allow json in document includedNotes and
+- #591 Import IncludedNotes also on item level
+- #595 Treat all fatal XR schematron rules as errors, not as warnings.
+- #577 dom4j: exclude all (optional) dependencies to avoid potential conflicts.
+- #575 Fix compilation problems.
+- #573 Feature/category code
+- #601 exceptions in metrics
+- #606 also parse BT-25
+
+
2.15.0
=======
-2024-
-- 435 use invoiceimporter as common technical basis also for zugferdimporter
+2024-11-18
+- #435 use invoiceimporter as common technical basis also for zugferdimporter
- also import delivery address
-- 527 metrics may raise error on some pdf files
-- 517 read product GlobalID
-- 380 Added test for input stream validation
-- 518 corrently validate more XRechnung versions
+- #527 metrics may raise error on some pdf files
+- #517 read product GlobalID
+- #380 Added test for input stream validation
+- #518 corrently validate more XRechnung versions
- make document charges and allowances serializable
-- 523 Verapdf claims PDF-A/3s created witth visualize are invalid
-- 530 duedate can not be set directly
-- 532 support validation warnings!
-- 534 new signature
-- 538 Mustang validator always claims PDF is invalid if flavour is PDF/A-3A
-- 555 be able to validate ubl credit notes
+- #523 Verapdf claims PDF-A/3s created witth visualize are invalid
+- #530 duedate can not be set directly
+- #532 support validation warnings!
+- #534 new signature
+- #538 Mustang validator always claims PDF is invalid if flavour is PDF/A-3A
+- #555 be able to validate ubl credit notes
- when parsing now distinguishing between the parseExceptions StructureException and ArithmetricException
-- Import IncludedNotes on invoice extraction #554
+- #554 Import IncludedNotes on invoice extraction
+- #542 Visualize SpecifiedLogisticsServiceCharge
+- #531 Support ZUGFeRD 2.3.2
+- #480 Support netherlands Euro
2.14.2
=======
diff --git a/Mustang-CLI/pom.xml b/Mustang-CLI/pom.xml
index 1c108da5..89e9f5fc 100644
--- a/Mustang-CLI/pom.xml
+++ b/Mustang-CLI/pom.xml
@@ -3,7 +3,7 @@
org.mustangproject
core
- 2.15.0-SNAPSHOT
+ 2.15.2-SNAPSHOT
4.0.0
org.mustangproject
@@ -12,7 +12,7 @@
should also work for XRechnung/CII.
jar
- 2.15.0-SNAPSHOT
+ 2.15.2-SNAPSHOT
UTF-8
11
@@ -23,7 +23,7 @@
org.mustangproject
validator
- 2.15.0-SNAPSHOT
+ 2.15.2-SNAPSHOT
diff --git a/Mustang-CLI/src/main/java/org/mustangproject/commandline/FileChecker.java b/Mustang-CLI/src/main/java/org/mustangproject/commandline/FileChecker.java
index 2a587c72..e0899108 100644
--- a/Mustang-CLI/src/main/java/org/mustangproject/commandline/FileChecker.java
+++ b/Mustang-CLI/src/main/java/org/mustangproject/commandline/FileChecker.java
@@ -51,7 +51,9 @@ public class FileChecker {
if ((!isPDF) && (!thisRun.shallIgnoreFileExt())) {
return false;
}
- ZUGFeRDImporter zi = new ZUGFeRDImporter(filename);
+ ZUGFeRDImporter zi = new ZUGFeRDImporter();
+ zi.doIgnoreCalculationErrors();
+ zi.setPDFFilename(filename);
try {
if (zi.canParse()) {
thisRun.incZUGFeRDCount(zi.getVersion());
diff --git a/README.md b/README.md
index f41a4671..43ea3671 100644
--- a/README.md
+++ b/README.md
@@ -32,9 +32,10 @@ If you set up a Maven project, you can reference the mustang artifact like this:
```xml
- org.mustangproject
- library
- 2.14.0
+ org.mustangproject
+ validator
+ 2.15.0
+ shaded
```
diff --git a/library/pom.xml b/library/pom.xml
index a6e875df..2c6a1284 100644
--- a/library/pom.xml
+++ b/library/pom.xml
@@ -3,13 +3,13 @@
org.mustangproject
core
- 2.15.0-SNAPSHOT
+ 2.15.2-SNAPSHOT
4.0.0
org.mustangproject
library
- 2.15.0-SNAPSHOT
+ 2.15.2-SNAPSHOT
jar
Library to write, read and validate e-invoices (Factur-X, ZUGFeRD, Order-X, XRechnung/CII)
FOSS Java library to read, write and validate european electronic invoices and orders in the UN/CEFACT
@@ -116,6 +116,12 @@
org.dom4j
dom4j
2.1.4
+
+
+ *
+ *
+
+
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 729d0f9b..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,13 +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) {
@@ -27,4 +37,37 @@ 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();
+ }
+ return lineTotalAmount;
+ }
+ public CalculatedInvoice setLineTotalAmount(BigDecimal total) {
+ lineTotalAmount=total;
+ return this;
+ }
+
}
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..61fdd20f 100644
--- a/library/src/main/java/org/mustangproject/ClassCode.java
+++ b/library/src/main/java/org/mustangproject/ClassCode.java
@@ -20,15 +20,19 @@
*/
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;
+ private String listID;
+ private String code;
private String listVersionID;
/**
@@ -54,6 +58,13 @@ public class ClassCode {
this(listID, code, null);
}
+ /***
+ * bean constructor
+ */
+ public ClassCode() {
+ }
+
+
/***
* Set the version for the scheme returned by {@link #getListID()}
* @param listVersionID the scheme version
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..ffa35c17 100644
--- a/library/src/main/java/org/mustangproject/DesignatedProductClassification.java
+++ b/library/src/main/java/org/mustangproject/DesignatedProductClassification.java
@@ -20,14 +20,18 @@
*/
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 ClassCode classCode;
private String className;
/**
@@ -50,6 +54,13 @@ public class DesignatedProductClassification implements IDesignatedProductClassi
this(classCode, null);
}
+ /**
+ * Bean constructor for schemed product descriptor
+ */
+ public DesignatedProductClassification() {
+ classCode = null;// we need this constructor for jackson, i.e. to be able to JSON
+ }
+
@Override
public ClassCode getClassCode() {
return classCode;
diff --git a/library/src/main/java/org/mustangproject/DirectDebit.java b/library/src/main/java/org/mustangproject/DirectDebit.java
index 4eef6cb3..86937a0f 100644
--- a/library/src/main/java/org/mustangproject/DirectDebit.java
+++ b/library/src/main/java/org/mustangproject/DirectDebit.java
@@ -1,20 +1,32 @@
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)
*/
- protected final String IBAN;
+ protected String IBAN;
/**
* Mandate reference identifier (BT-89)
*/
- protected final String mandate;
+ protected String mandate;
+
+ /**
+ * bean constructor
+ */
+ public DirectDebit() {
+ this.IBAN = "";
+ this.mandate = "";
+ }
/***
* constructor for normal use :-)
@@ -35,8 +47,18 @@ public class DirectDebit implements IZUGFeRDTradeSettlementDebit {
return this.IBAN;
}
+ public DirectDebit setIBAN(String iBAN) {
+ this.IBAN = iBAN;
+ return this;
+ }
+
@Override
public String getMandate() {
return this.mandate;
}
+
+ public DirectDebit setMandate(String mandate) {
+ this.mandate = mandate;
+ return this;
+ }
}
diff --git a/library/src/main/java/org/mustangproject/FileAttachment.java b/library/src/main/java/org/mustangproject/FileAttachment.java
index d17aa727..ed1fe39f 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;
@@ -8,12 +13,20 @@ public class FileAttachment {
protected String description;
protected byte[] data;
+
+ /***
+ * bean contructor
+ */
+ public FileAttachment() {
+
+ }
+
public FileAttachment(String filename, String mimetype, String relation, byte[] data) {
this.filename = filename;
this.mimetype = mimetype;
this.relation = relation;
this.data = data;
- description = "Additional file attachment";
+ this.description = "Additional file attachment";
}
public String getDescription() {
@@ -60,8 +73,4 @@ public class FileAttachment {
this.data = data;
return this;
}
-
-
-
-
}
diff --git a/library/src/main/java/org/mustangproject/IncludedNote.java b/library/src/main/java/org/mustangproject/IncludedNote.java
index 95536afb..0bcf3133 100644
--- a/library/src/main/java/org/mustangproject/IncludedNote.java
+++ b/library/src/main/java/org/mustangproject/IncludedNote.java
@@ -1,68 +1,100 @@
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 final String content;
- private final SubjectCode subjectCode;
+ private String content;
- private static final String INCLUDE_START = "";
- private static final String INCLUDE_END = "";
- private static final String CONTENT_START = "";
- private static final String CONTENT_END = "";
- private static final String SUBJECT_CODE_START = "";
- private static final String SUBJECT_CODE_END = "";
+ private SubjectCode subjectCode;
- private IncludedNote(String content, SubjectCode subjectCode) {
- this.content = content;
- this.subjectCode = subjectCode;
- }
+ private static final String INCLUDE_START = "";
+ private static final String INCLUDE_END = "";
+ private static final String CONTENT_START = "";
+ private static final String CONTENT_END = "";
+ private static final String SUBJECT_CODE_START = "";
+ private static final String SUBJECT_CODE_END = "";
- 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);
- }
+ public IncludedNote(String content, SubjectCode subjectCode) {
+ this.content = content;
+ this.subjectCode = subjectCode;
+ }
- public static IncludedNote unspecifiedNote(String content) {
- return new IncludedNote(content, null);
- }
+ /**
+ * bean constructor
+ */
+ public IncludedNote() {
- public String getContent() {
- return content;
- }
+ }
+
+ 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);
+ }
+
+ public static IncludedNote unspecifiedNote(String content) {
+ return new IncludedNote(content, null);
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public SubjectCode getSubjectCode() {
+ 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;
+ if (getSubjectCode() != null) {
+ result += SUBJECT_CODE_START + getSubjectCode() + SUBJECT_CODE_END;
+ }
+ return result + INCLUDE_END;
+ }
- public SubjectCode getSubjectCode() {
- return subjectCode;
- }
-
- public String toCiiXml(){
- String result = INCLUDE_START + CONTENT_START +
- XMLTools.encodeXML(getContent() )+ CONTENT_END;
- if (getSubjectCode() != null) {
- result += SUBJECT_CODE_START + getSubjectCode() + SUBJECT_CODE_END;
- }
- return result + INCLUDE_END;
- }
-
}
diff --git a/library/src/main/java/org/mustangproject/Invoice.java b/library/src/main/java/org/mustangproject/Invoice.java
index 346c5f43..648ba71f 100644
--- a/library/src/main/java/org/mustangproject/Invoice.java
+++ b/library/src/main/java/org/mustangproject/Invoice.java
@@ -21,10 +21,7 @@
package org.mustangproject;
import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.mustangproject.ZUGFeRD.*;
@@ -66,6 +63,7 @@ public class Invoice implements IExportableTransaction {
protected String despatchAdviceReferencedDocumentID = null;
protected String vatDueDateTypeCode = null;
protected String creditorReferenceID; // required when direct debit is used.
+ private BigDecimal roundingAmount=null;
public Invoice() {
ZFItems = new ArrayList<>();
@@ -115,6 +113,16 @@ public class Invoice implements IExportableTransaction {
}
+ /***
+ * setter in case e.g. jackson tries to map attachments (normal use embedFileInXML)
+ * @param fileArr Array of FileAttachments
+ * @return fluent setter
+ */
+ public Invoice setAdditionalReferencedDocuments(FileAttachment[] fileArr) {
+ xmlEmbeddedFiles = new ArrayList<>(Arrays.asList(fileArr));
+ return this;
+ }
+
@Override
public IZUGFeRDCashDiscount[] getCashDiscounts() {
return cashDiscounts.toArray(new IZUGFeRDCashDiscount[0]);
@@ -412,6 +420,11 @@ public class Invoice implements IExportableTransaction {
return includedNotes;
}
+ public Invoice setNotesWithSubjectCode(List theList) {
+ includedNotes=theList;
+ return this;
+ }
+
@Override
public String getCurrency() {
return currency;
@@ -467,6 +480,26 @@ public class Invoice implements IExportableTransaction {
return sender;
}
+ /***
+ * for currency rounding differences to 5ct e.g. in Netherlands ("Rappenrundung")
+ * @return null if not set, otherwise BigDecimal of Euros
+ */
+ @Override
+ public BigDecimal getRoundingAmount() {
+ return roundingAmount;
+ }
+
+ /***
+ * set the cent e.g. to reach the next 5ct mark for currencies in certain countries
+ * e.g. in the Netherlands ("Rappenrundung")
+ * @param amount
+ * @return fluent setter
+ */
+ public Invoice setRoundingAmount(BigDecimal amount) {
+ roundingAmount=amount;
+ return this;
+ }
+
/***
* sets a named sender contact
* @deprecated use setSender
@@ -524,8 +557,8 @@ public class Invoice implements IExportableTransaction {
/***
* this is wrong and only used from jackson
- * @param iza
- * @return
+ * @param iza the Array of allowances/charges
+ * @return fluent setter
*/
public Invoice setZFAllowances(Allowance[] iza) {
Allowances=new ArrayList<>();
@@ -548,8 +581,8 @@ public class Invoice implements IExportableTransaction {
/***
* this is wrong and only used from jackson
- * @param iza
- * @return
+ * @param iza the array of charges
+ * @return fluent setter
*/
public Invoice setZFCharges(Charge[] iza) {
Charges=new ArrayList<>();
diff --git a/library/src/main/java/org/mustangproject/Item.java b/library/src/main/java/org/mustangproject/Item.java
index d726ed08..249d5067 100644
--- a/library/src/main/java/org/mustangproject/Item.java
+++ b/library/src/main/java/org/mustangproject/Item.java
@@ -12,7 +12,11 @@ import org.w3c.dom.NodeList;
import java.math.BigDecimal;
import java.math.RoundingMode;
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
@@ -37,6 +41,8 @@ public class Item implements IZUGFeRDExportableItem {
protected ArrayList additionalReference = null;
protected ArrayList Allowances = new ArrayList<>();
protected ArrayList Charges = new ArrayList<>();
+ protected List includedNotes = null;
+ //protected HashMap attributes = new HashMap<>();
/***
* default constructor
@@ -64,11 +70,39 @@ 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);
});
+ itemMap.getAsNodeMap("AssociatedDocumentLineDocument").ifPresent(icnm -> {
+ icnm.getAsString("LineID").ifPresent(this::setId);
+ });
itemMap.getAsNodeMap("Price").ifPresent(icnm -> {
// ubl
@@ -83,21 +117,43 @@ 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.getAsString("ID")
+ .ifPresent(this::setId);
+
+
+ itemMap.getAsString("Note")
+ .ifPresent(this::addNote);
+
+
+
+
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")
@@ -125,6 +181,37 @@ public class Item implements IZUGFeRDExportableItem {
icnm.getAllNodes("AdditionalReferencedDocument").map(ReferencedDocument::fromNode).forEach(this::addAdditionalReference);
});
+
+ itemMap.getAsNodeMap("AssociatedDocumentLineDocument").ifPresent(adld -> {
+ List includedNotes = new ArrayList<>();
+ adld.getAllNodes("IncludedNote").forEach(item -> {
+ String subjectCode = "";
+ String content = null;
+ NodeList includedNodeChilds = item.getChildNodes();
+ for (int issueDateChildIndex = 0; issueDateChildIndex < includedNodeChilds.getLength(); issueDateChildIndex++) {
+ if ((includedNodeChilds.item(issueDateChildIndex).getLocalName() != null)
+ && (includedNodeChilds.item(issueDateChildIndex).getLocalName().equals("Content"))) {
+ content = XMLTools.trimOrNull(includedNodeChilds.item(issueDateChildIndex));
+ }
+ if ((includedNodeChilds.item(issueDateChildIndex).getLocalName() != null)
+ && (includedNodeChilds.item(issueDateChildIndex).getLocalName().equals("SubjectCode"))) {
+ subjectCode = XMLTools.trimOrNull(includedNodeChilds.item(issueDateChildIndex));
+ }
+ }
+ boolean foundCode = false;
+ for (SubjectCode code : SubjectCode.values()) {
+ if (code.toString().equals(subjectCode)) {
+ includedNotes.add(new IncludedNote(content, code));
+ foundCode = true;
+ break;
+ }
+ }
+ if (!foundCode) {
+ includedNotes.add(new IncludedNote(content, null));
+ }
+ });
+ addNotes(includedNotes);
+ });
}
public Item addReferencedLineID(String s) {
@@ -145,6 +232,11 @@ public class Item implements IZUGFeRDExportableItem {
return lineTotalAmount;
}
+ public Item setNotesWithSubjectCode(List theList) {
+ includedNotes=theList;
+ return this;
+ }
+
/**
* should only be set by calculator classes or maybe when reading from XML
*
@@ -290,6 +382,13 @@ public class Item implements IZUGFeRDExportableItem {
notes = new ArrayList<>();
}
notes.add(text);
+
+ if (includedNotes == null) {
+ includedNotes = new ArrayList<>();
+ }
+ includedNotes.add(IncludedNote.unspecifiedNote(text));
+
+
return this;
}
@@ -372,4 +471,19 @@ public class Item implements IZUGFeRDExportableItem {
return detailedDeliveryPeriodTo;
}
+ public IZUGFeRDExportableItem addNotes(Collection notes) {
+ if (notes == null) {
+ return this;
+ }
+ if (includedNotes == null) {
+ includedNotes = new ArrayList<>();
+ }
+ includedNotes.addAll(notes);
+ return this;
+ }
+
+ @Override
+ public List getNotesWithSubjectCode() {
+ return includedNotes;
+ }
}
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..4bbde404 100644
--- a/library/src/main/java/org/mustangproject/Product.java
+++ b/library/src/main/java/org/mustangproject/Product.java
@@ -2,10 +2,12 @@ package org.mustangproject;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonSetter;
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;
@@ -22,15 +24,16 @@ import java.util.Map;
public class Product implements IZUGFeRDExportableProduct {
protected String unit, name, sellerAssignedID, buyerAssignedID;
- protected String description="";
- protected String taxExemptionReason=null;
- protected String taxCategoryCode=null;
+ protected String description = "";
+ protected String taxExemptionReason = null;
+ protected String taxCategoryCode = null;
protected BigDecimal VATPercent;
protected boolean isReverseCharge = false;
protected boolean isIntraCommunitySupply = false;
protected SchemedID globalId = null;
protected String countryOfOrigin = null;
protected HashMap attributes = new HashMap<>();
+
protected List classifications = new ArrayList<>();
/***
@@ -59,11 +62,13 @@ 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
@@ -129,7 +155,7 @@ public class Product implements IZUGFeRDExportableProduct {
* @param taxExemptionReasonText String e.g. Kleinunternehmer gemäß §19 UStG https://github.com/ZUGFeRD/mustangproject/issues/463
* @return fluent setter
*/
- public Product setTaxExemptionReason(String taxExemptionReasonText) {
+ public Product setTaxExemptionReason(String taxExemptionReasonText) {
taxExemptionReason = taxExemptionReasonText;
return this;
}
@@ -151,7 +177,7 @@ public class Product implements IZUGFeRDExportableProduct {
* @param code e.g. S (normal tax), Z=zero rated, E (e.g. small business) or K (intrra community supply) see also https://github.com/ZUGFeRD/mustangproject/issues/463
* @return fluent setter
*/
- public Product setTaxCategoryCode(String code) {
+ public Product setTaxCategoryCode(String code) {
taxCategoryCode = code;
return this;
}
@@ -278,18 +304,22 @@ public class Product implements IZUGFeRDExportableProduct {
* @return fluent setter
*/
public Product setVATPercent(BigDecimal VATPercent) {
- this.VATPercent = VATPercent;
+ if (VATPercent == null) {
+ this.VATPercent = BigDecimal.ZERO;
+ } else {
+ this.VATPercent = VATPercent;
+ }
return this;
}
@Override
public String getCountryOfOrigin() {
- return this.countryOfOrigin;
+ return this.countryOfOrigin;
}
public Product setCountryOfOrigin(String countryOfOrigin) {
- this.countryOfOrigin = countryOfOrigin;
- return this;
+ this.countryOfOrigin = countryOfOrigin;
+ return this;
}
@Override
@@ -302,16 +332,16 @@ public class Product implements IZUGFeRDExportableProduct {
}
public Product setAttributes(Map attributes) {
- this.attributes.clear();
+ this.attributes.clear();
if (attributes != null) {
this.attributes.putAll(attributes);
}
- return this;
+ return this;
}
- public Product addAttribute(String name, String value ) {
- this.attributes.put(name, value);
- return this;
+ public Product addAttribute(String name, String value) {
+ this.attributes.put(name, value);
+ return this;
}
@Override
@@ -337,6 +367,23 @@ public class Product implements IZUGFeRDExportableProduct {
return this;
}
+
+ /**
+ * Provide Jackson a hint as to use DesignatedProductClassification for the
+ * IDesignatedProductClassification product classifications
+ *
+ * @param classifications the new set of classifications
+ * @return fluent setter
+ */
+ @JsonSetter("classifications")
+ public Product setClassificationsClass(DesignatedProductClassification[] classifications) {
+ this.classifications.clear();
+ if (classifications != null) {
+ this.classifications.addAll(Arrays.asList(classifications));
+ }
+ return this;
+ }
+
/**
* Add a {@link IDesignatedProductClassification} classification
*
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/SubjectCode.java b/library/src/main/java/org/mustangproject/SubjectCode.java
index c58070fd..808c09d4 100644
--- a/library/src/main/java/org/mustangproject/SubjectCode.java
+++ b/library/src/main/java/org/mustangproject/SubjectCode.java
@@ -36,5 +36,9 @@ public enum SubjectCode {
/**
* Discount and bonus agreements
*/
- AAK
+ AAK,
+ /**
+ * Vehicle licence number
+ */
+ ABZ
}
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/XMLTools.java b/library/src/main/java/org/mustangproject/XMLTools.java
index dbccd4b0..d890c3d1 100644
--- a/library/src/main/java/org/mustangproject/XMLTools.java
+++ b/library/src/main/java/org/mustangproject/XMLTools.java
@@ -92,7 +92,7 @@ public class XMLTools extends XMLWriter {
/***
* formats a number so that at least minDecimals are displayed but at the maximum maxDecimals are there, i.e.
* cuts potential 0s off the end until minDecimals
- * @param value
+ * @param value the value to be formatted
* @param maxDecimals number of maximal scale
* @param minDecimals number of minimal scale
* @return value as String with decimals in the specified range
@@ -138,7 +138,7 @@ public class XMLTools extends XMLWriter {
}
/***
- * relplaces some entities like < , > and & with their escaped pendant like <
+ * relplaces some entities like < , > and & with their escaped pendant like <
* @param s the string
* @return the "safe" string
*/
diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java
index f43b5f62..0a67a6be 100644
--- a/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java
+++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java
@@ -321,6 +321,15 @@ public interface IExportableTransaction {
return false;
}
+ /**
+ * supplier identification assigned by the costumer
+ *
+ * @return the sender's identification
+ */
+ default BigDecimal getRoundingAmount() {
+ return null;
+ }
+
/**
* get reference document number typically used for Invoice Corrections Will be
* added as IncludedNote in comfort profile
diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableItem.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableItem.java
index e5e25cae..45c210ea 100644
--- a/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableItem.java
+++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableItem.java
@@ -28,7 +28,9 @@ package org.mustangproject.ZUGFeRD;
import java.math.BigDecimal;
import java.util.Date;
+import java.util.List;
+import org.mustangproject.IncludedNote;
import org.mustangproject.Item;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
@@ -153,4 +155,21 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
return null;
}
+ /***
+ *
+ * @return the line ID
+ */
+ default String getId() {
+ return null;
+ }
+
+ /**
+ * A grouping of business terms to indicate accounting-relevant free texts including a qualification of these.
+ *
+ * The information are written to the same xml nodes like {@link #getNotes()} but with explicit subjectCode.
+ * @return list of the notes
+ */
+ default List getNotesWithSubjectCode() {
+ 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 f3e8aa2d..e319ec73 100644
--- a/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java
+++ b/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java
@@ -44,10 +44,20 @@ public class LineCalculator {
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(), 18, RoundingMode.HALF_UP)
+
+ BigDecimal quantity=BigDecimal.ZERO;
+ if ((currentItem!=null)&&(currentItem.getQuantity()!=null)) {
+ quantity=currentItem.getQuantity();
+ }
+
+ // Division/Zero occurred here.
+ // Used the setScale only because that's also done in getBasisQuantity
+ BigDecimal basisQuantity = currentItem.getBasisQuantity().compareTo(BigDecimal.ZERO) == 0
+ ? BigDecimal.ONE.setScale(4)
+ : currentItem.getBasisQuantity();
+ itemTotalNetAmount = quantity.multiply(getPrice()).divide(basisQuantity, 18, RoundingMode.HALF_UP)
.subtract(allowanceItemTotal).setScale(2, RoundingMode.HALF_UP);
itemTotalVATAmount = itemTotalNetAmount.multiply(multiplicator);
-
}
public BigDecimal getPrice() {
diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java
index 1e1f757f..8740e157 100644
--- a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java
+++ b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java
@@ -10,7 +10,7 @@ import java.util.stream.Stream;
/***
* The Transactioncalculator e.g. adds the line totals and applies VAT on whole
* invoices
- *
+ *
* @see LineCalculator
*/
public class TransactionCalculator implements IAbsoluteValueProvider {
@@ -27,7 +27,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
/***
* if something had already been paid in advance, this will get it from the
* transaction
- *
+ *
* @return prepaid amount
*/
protected BigDecimal getTotalPrepaid() {
@@ -41,19 +41,19 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
/***
* the invoice total with VAT, allowances and
* charges, WITHOUT considering prepaid amount
- *
+ *
* @return the invoice total including taxes
*/
public BigDecimal getGrandTotal() {
- final BigDecimal res = getTaxBasis();
+ BigDecimal basis = getTaxBasis();
return getVATPercentAmountMap().values().stream().map(VATAmount::getCalculated)
- .map(p -> p.setScale(2, RoundingMode.HALF_UP)).reduce(BigDecimal.ZERO, BigDecimal::add).add(res);
+ .map(p -> p.setScale(2, RoundingMode.HALF_UP)).reduce(BigDecimal.ZERO, BigDecimal::add).add(basis);
}
/***
* returns total of charges for this tax rate
- *
+ *
* @param percent a specific rate, or null for any rate
* @return the total amount
*/
@@ -77,7 +77,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
/***
* 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
*/
@@ -95,7 +95,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
if ((charges != null) && (charges.length > 0)) {
for (IZUGFeRDAllowanceCharge currentCharge : charges) {
if ((percent == null) || (currentCharge.getTaxPercent().compareTo(percent) == 0)
- && currentCharge.getReason() != null) {
+ && currentCharge.getReason() != null) {
res += currentCharge.getReason() + " ";
}
}
@@ -107,7 +107,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
/***
* 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
*/
@@ -122,7 +122,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
/***
* returns total of allowances for this tax rate
- *
+ *
* @param percent a specific rate, or null for any rate
* @return the total amount
*/
@@ -134,25 +134,25 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
/***
* 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);
+ .map(LineCalculator::getItemTotalNetAmount).reduce(ZERO, BigDecimal::add);
return dec;
}
/***
* returns the total net value of the invoice, including charges/allowances on
* document level
- *
+ *
* @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);
+ .subtract(getAllowancesForPercent(null).setScale(2, RoundingMode.HALF_UP))
+ .setScale(2, RoundingMode.HALF_UP);
}
/**
@@ -167,13 +167,17 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
final String vatDueDateTypeCode = trans.getVATDueDateTypeCode();
for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) {
- BigDecimal percent = currentItem.getProduct().getVATPercent();
+ BigDecimal percent = null;
+ if (currentItem.getProduct()!=null)
+ {
+ percent=currentItem.getProduct().getVATPercent();
+ }
if (percent != null) {
LineCalculator lc = new LineCalculator(currentItem);
VATAmount itemVATAmount = new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount(),
- currentItem.getProduct().getTaxCategoryCode(), vatDueDateTypeCode);
- String reasonText=currentItem.getProduct().getTaxExemptionReason();
- if (reasonText!=null) {
+ currentItem.getProduct().getTaxCategoryCode(), vatDueDateTypeCode);
+ String reasonText = currentItem.getProduct().getTaxExemptionReason();
+ if (reasonText != null) {
itemVATAmount.setVatExemptionReasonText(reasonText);
}
VATAmount current = hm.get(percent.stripTrailingZeros());
@@ -193,8 +197,8 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
VATAmount theAmount = hm.get(taxPercent.stripTrailingZeros());
if (theAmount == null) {
theAmount = new VATAmount(BigDecimal.ZERO, BigDecimal.ZERO,
- currentCharge.getCategoryCode() != null ? currentCharge.getCategoryCode() : "S",
- vatDueDateTypeCode);
+ currentCharge.getCategoryCode() != null ? currentCharge.getCategoryCode() : "S",
+ vatDueDateTypeCode);
}
theAmount.setBasis(theAmount.getBasis().add(currentCharge.getTotalAmount(this)));
BigDecimal factor = taxPercent.divide(new BigDecimal(100));
@@ -211,8 +215,8 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
VATAmount theAmount = hm.get(taxPercent.stripTrailingZeros());
if (theAmount == null) {
theAmount = new VATAmount(BigDecimal.ZERO, BigDecimal.ZERO,
- currentAllowance.getCategoryCode() != null ? currentAllowance.getCategoryCode() : "S",
- vatDueDateTypeCode);
+ currentAllowance.getCategoryCode() != null ? currentAllowance.getCategoryCode() : "S",
+ vatDueDateTypeCode);
}
theAmount.setBasis(theAmount.getBasis().subtract(currentAllowance.getTotalAmount(this)));
BigDecimal factor = taxPercent.divide(new BigDecimal(100));
@@ -239,4 +243,11 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
return getAllowancesForPercent(null).setScale(2, RoundingMode.HALF_UP);
}
+ public BigDecimal getDuePayable() {
+ BigDecimal res = getGrandTotal().subtract(getTotalPrepaid());
+ if (trans.getRoundingAmount() != null) {
+ res = res.add(trans.getRoundingAmount());
+ }
+ return res;
+ }
}
diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java
index 03ed3099..6bd4f95d 100644
--- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java
+++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java
@@ -277,11 +277,11 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
}
String reason = "";
- if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended") || profile == Profiles.getByName("XRechnung"))) {
+ if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended") || profile == Profiles.getByName("XRechnung")) || profile == Profiles.getByName("EN16931")) {
reason = "" + XMLTools.encodeXML(allowance.getReason()) + "";
}
String reasonCode = "";
- if ((allowance.getReasonCode() != null) && (profile == Profiles.getByName("XRechnung"))) {
+ if (allowance.getReasonCode() != null) {
// only in XRechnung profile
reasonCode = "" + allowance.getReasonCode() + "";
}
@@ -334,7 +334,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
this.trans = trans;
this.calc = new TransactionCalculator(trans);
- boolean hasDueDate = trans.getDueDate()!=null;
+ boolean hasDueDate = trans.getDueDate() != null;
final SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy");
String exemptionReason = "";
@@ -401,6 +401,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
int lineID = 0;
for (final IZUGFeRDExportableItem currentItem : trans.getZFItems()) {
lineID++;
+ String lineIDStr = Integer.toString(lineID);
+ if (currentItem.getId()!=null) {
+ lineIDStr=currentItem.getId();
+ }
if (currentItem.getProduct().getTaxExemptionReason() != null) {
exemptionReason = "" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + "";
}
@@ -408,7 +412,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if ((getProfile() != Profiles.getByName("Minimum")) && (getProfile() != Profiles.getByName("BasicWL"))) {
xml += "" +
""
- + "" + lineID + ""
+ + "" + lineIDStr + ""
+ buildItemNotes(currentItem)
+ ""
@@ -454,7 +458,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if (currentItem.getProduct().getClassifications() != null && currentItem.getProduct().getClassifications().length > 0) {
for (IDesignatedProductClassification classification : currentItem.getProduct().getClassifications()) {
xml += ""
- + "";
xml += "";
- if (getProfile() != Profiles.getByName("Minimum")) {
+ if ((getProfile() != Profiles.getByName("Minimum")) && (getProfile() != Profiles.getByName("BASICWL"))) {
xml += "" + currencyFormat(calc.getTotal()) + "";
xml += chargesTotalLine
+ allowanceTotalLine;
@@ -865,14 +869,18 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
// //
// currencyID=\"EUR\"
+ ""
- + currencyFormat(calc.getGrandTotal().subtract(calc.getTaxBasis())) + ""
- + "" + currencyFormat(calc.getGrandTotal()) + "";
+ + currencyFormat(calc.getGrandTotal().subtract(calc.getTaxBasis())) + "";
+ if (trans.getRoundingAmount() != null) {
+ xml += "" + currencyFormat(trans.getRoundingAmount()) + "";
+ }
+
+ xml += "" + currencyFormat(calc.getGrandTotal()) + "";
// //
// currencyID=\"EUR\"
if (getProfile() != Profiles.getByName("Minimum")) {
xml += "" + currencyFormat(calc.getTotalPrepaid()) + "";
}
- xml += "" + currencyFormat(calc.getGrandTotal().subtract(calc.getTotalPrepaid())) + ""
+ xml += "" + currencyFormat(calc.getDuePayable()) + ""
+ "";
if (trans.getInvoiceReferencedDocumentID() != null) {
xml += ""
diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java
index cebeb824..5189bee6 100644
--- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java
+++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java
@@ -262,7 +262,7 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter {
* @return the Payment Terms
*/
public String getPaymentTerms() {
- return extractString("//*[local-name() = 'SpecifiedTradePaymentTerms']//*[local-name() = 'Description']");
+ return importedInvoice.getPaymentTermDescription();
}
/**
@@ -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();
}
@@ -655,6 +655,7 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter {
/**
* returns a list of LineItems
+ * @deprecated use invoiceimporter getZFItems
*
* @return a List of LineItem instances
*/
@@ -742,6 +743,15 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter {
node = getNodeByName(node.getChildNodes(), "CalculatedAmount");
lineItem.setTax(XMLTools.tryBigDecimal(node));
}
+
+ node = getNodeByName(nn.getChildNodes(), "ApplicableTradeTax");
+ if (node != null) {
+ node = getNodeByName(node.getChildNodes(), "CategoryCode");
+ if(node != null){
+ lineItem.getProduct().setTaxCategoryCode(XMLTools.getNodeValue(node));
+ }
+ }
+
node = getNodeByName(nn.getChildNodes(), "BillingSpecifiedPeriod");
if (node != null) {
final Node start = getNodeByName(node.getChildNodes(), "StartDateTime");
diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java
index d9bd7e42..da10d8dd 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;
@@ -67,7 +68,6 @@ public class ZUGFeRDInvoiceImporter {
protected CalculatedInvoice importedInvoice = null;
protected boolean recalcPrice = false;
protected boolean ignoreCalculationErrors = false;
- protected ArrayList fileAttachments = new ArrayList<>();
public ZUGFeRDInvoiceImporter() {
//constructor for extending classes
@@ -101,7 +101,7 @@ public class ZUGFeRDInvoiceImporter {
/***
* return the file names of all files embedded into the PDF
- * @see for XML embedded files please use ZUGFeRDInvoiceImporter.getFileAttachmentsXML
+ * @see ZUGFeRDInvoiceImporter for XML embedded files please use ZUGFeRDInvoiceImporter.getFileAttachmentsXML
* @return a ArrayList of FileAttachments, empty if none
*/
public List getFileAttachmentsPDF() {
@@ -228,7 +228,7 @@ public class ZUGFeRDInvoiceImporter {
* set the xml of a CII invoice
* @param rawXML the xml string
* @param doParse automatically parse input for zugferdImporter (not ZUGFeRDInvoiceImporter)
- * @throws IOException
+ * @throws IOException if parsing xml throws it (unlikely its string based)
*/
public void setRawXML(byte[] rawXML, boolean doParse) throws IOException {
this.containsMeta = true;
@@ -238,7 +238,7 @@ public class ZUGFeRDInvoiceImporter {
try {
setDocument();
- } catch (ParserConfigurationException | SAXException e) {
+ } catch (ParserConfigurationException | SAXException | ParseException e) {
LOGGER.error("Failed to parse XML", e);
throw new ZUGFeRDExportException(e);
}
@@ -248,13 +248,13 @@ public class ZUGFeRDInvoiceImporter {
/***
* set the xml of a CII invoice, simple version
* @param rawXML the cii(?) as a string
- * @throws IOException
+ * @throws IOException if parsing xml throws it (unlikely its string based)
*/
public void setRawXML(byte[] rawXML) throws IOException {
setRawXML(rawXML, true);
}
- private void setDocument() throws ParserConfigurationException, IOException, SAXException {
+ private void setDocument() throws ParserConfigurationException, IOException, SAXException, ParseException {
final DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance();
xmlFact.setNamespaceAware(true);
final DocumentBuilder builder = xmlFact.newDocumentBuilder();
@@ -267,12 +267,14 @@ public class ZUGFeRDInvoiceImporter {
extractInto(importedInvoice);
} catch (XPathExpressionException e) {
throw new RuntimeException(e);
- } catch (ParseException e) {
- throw new RuntimeException(e);
}
}
}
+ 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
@@ -301,13 +303,129 @@ public class ZUGFeRDInvoiceImporter {
zpp.setDeliveryAddress(new TradeParty(deliveryNodes));
}
+ List includedNotes = new ArrayList<>();
+
+ //UBL...
+ XPathExpression UBLNotesEx = xpath.compile("/*[local-name()=\"Invoice\"]/*[local-name()=\"Note\"]");
+ NodeList UBLNotesNd = (NodeList) UBLNotesEx.evaluate(getDocument(), XPathConstants.NODESET);
+ if ((UBLNotesNd != null) && (UBLNotesNd.getLength() > 0)) {
+ for (int nodeIndex = 0; nodeIndex < UBLNotesNd.getLength(); nodeIndex++) {
+ includedNotes.add(IncludedNote.generalNote(UBLNotesNd.item(nodeIndex).getTextContent()));
+ }
+ zpp.addNotes(includedNotes);
+ }
+
+ 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 -> {
+ if (s.getAttributes().getNamedItem("schemeID") != null) {
+ 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,16 +442,47 @@ public class ZUGFeRDInvoiceImporter {
}
}
- xpr = xpath.compile("//*[local-name()=\"PrepaidAmount\"]");
+ 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) {
zpp.setTotalPrepaidAmount(new BigDecimal(XMLTools.trimOrNull(prepaidNodes.item(0))));
}
+
+ xpr = xpath.compile("//*[local-name()=\"SpecifiedTradeSettlementHeaderMonetarySummation\"]/*[local-name()=\"LineTotalAmount\"]|//*[local-name()=\"LegalMonetaryTotal\"]/*[local-name()=\"LineExtensionAmount\"]");
+ NodeList lineTotalNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
+ if (lineTotalNodes.getLength() > 0) {
+ if (zpp instanceof CalculatedInvoice) {
+ ((CalculatedInvoice) zpp).setLineTotalAmount(new BigDecimal(XMLTools.trimOrNull(lineTotalNodes.item(0))));
+ }
+ }
+
+ 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;
String despatchAdviceReferencedDocument = null;
+
for (int i = 0; i < ExchangedDocumentNodes.getLength(); i++) {
Node exchangedDocumentNode = ExchangedDocumentNodes.item(i);
NodeList exchangedDocumentChilds = exchangedDocumentNode.getChildNodes();
@@ -354,7 +503,6 @@ public class ZUGFeRDInvoiceImporter {
}
}
}
- List includedNotes = new ArrayList<>();
if ((item.getLocalName() != null) && (item.getLocalName().equals("IncludedNote"))) {
String subjectCode = "";
String content = null;
@@ -369,27 +517,48 @@ 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);
}
}
+ zpp.addNotes(includedNotes);
String rootNode = extractString("local-name(/*)");
if (rootNode.equals("Invoice")) {
// UBL...
number = extractString("//*[local-name()=\"Invoice\"]/*[local-name()=\"ID\"]").trim();
typeCode = extractString("//*[local-name()=\"Invoice\"]/*[local-name()=\"InvoiceTypeCode\"]").trim();
- issueDate = new SimpleDateFormat("yyyy-MM-dd").parse(extractString("//*[local-name()=\"Invoice\"]/*[local-name()=\"IssueDate\"]").trim());
+ String issueDateStr = extractString("//*[local-name()=\"Invoice\"]/*[local-name()=\"IssueDate\"]").trim();
+ if (issueDateStr.length()>0) {
+ issueDate = new SimpleDateFormat("yyyy-MM-dd").parse(issueDateStr);
+ }
String dueDt = extractString("//*[local-name()=\"Invoice\"]/*[local-name()=\"DueDate\"]").trim();
if (dueDt.length() > 0) {
dueDate = new SimpleDateFormat("yyyy-MM-dd").parse(dueDt);
@@ -399,7 +568,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++) {
@@ -471,9 +641,15 @@ 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);
+ String paymentTermsDescription = extractString("//*[local-name()=\"SpecifiedTradePaymentTerms\"]/*[local-name()=\"Description\"]|//*[local-name()=\"PaymentTerms\"]/*[local-name()=\"Note\"]");
+ if ((paymentTermsDescription!=null)&&(!paymentTermsDescription.isEmpty())) {
+ zpp.setPaymentTermDescription(paymentTermsDescription);
+ }
+
+
xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]|//*[local-name()=\"ApplicableSupplyChainTradeSettlement\"]");
NodeList headerTradeSettlementNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
List bankDetails = new ArrayList<>();
@@ -490,6 +666,9 @@ public class ZUGFeRDInvoiceImporter {
&& (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("Description"))) {
+ zpp.setPaymentTermDescription(paymentTermChilds.item(paymentTermChildIndex).getTextContent());
+ }
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++) {
@@ -590,10 +769,24 @@ 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);
+ zpp.setIssueDate(issueDate).setDueDate(dueDate).setDeliveryDate(deliveryDate).setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number).setDocumentCode(typeCode);
if ((directDebitMandateID != null) && (IBAN != null)) {
DirectDebit d = new DirectDebit(IBAN, directDebitMandateID);
@@ -608,24 +801,33 @@ 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.setInvoiceReferencedDocumentID(extractString("//*[local-name()=\"InvoiceReferencedDocument\"]/*[local-name()=\"IssuerAssignedID\"]|//*[local-name()=\"BillingReference\"]/*[local-name()=\"InvoiceDocumentReference\"]/*[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())) {
+ zpp.setRoundingAmount(new BigDecimal(rounding.trim()));
+ }
+
xpr = xpath.compile("//*[local-name()=\"BuyerReference\"]");
String buyerReference = null;
- prepaidNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
- if (prepaidNodes.getLength() > 0) {
- buyerReference = XMLTools.trimOrNull(prepaidNodes.item(0));
+ lineTotalNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
+ if (lineTotalNodes.getLength() > 0) {
+ buyerReference = XMLTools.trimOrNull(lineTotalNodes.item(0));
}
if (buyerReference != null) {
zpp.setReferenceNumber(buyerReference);
@@ -648,7 +850,7 @@ public class ZUGFeRDInvoiceImporter {
NodeList attachmentNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
for (int i = 0; i < attachmentNodes.getLength(); i++) {
FileAttachment fa = new FileAttachment(attachmentNodes.item(i).getAttributes().getNamedItem("filename").getNodeValue(), attachmentNodes.item(i).getAttributes().getNamedItem("mimeCode").getNodeValue(), "Data", Base64.getDecoder().decode(XMLTools.trimOrNull(attachmentNodes.item(i))));
- fileAttachments.add(fa);
+ zpp.embedFileInXML(fa);
// filename = "Aufmass.png" mimeCode = "image/png"
//EmbeddedDocumentBinaryObject cbc:EmbeddedDocumentBinaryObject mimeCode="image/png" filename="Aufmass.png"
}
@@ -657,7 +859,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();
@@ -671,24 +873,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));
}
}
@@ -724,6 +936,7 @@ public class ZUGFeRDInvoiceImporter {
}
+
TransactionCalculator tc = new TransactionCalculator(zpp);
String expectedStringTotalGross = tc.getGrandTotal()
.subtract(Objects.requireNonNullElse(zpp.getTotalPrepaidAmount(), BigDecimal.ZERO)).toPlainString();
@@ -821,9 +1034,10 @@ public class ZUGFeRDInvoiceImporter {
*
* @return the file attachments embedded in XML (using base64) decoded as byte array,
* for PDF embedded files in FX use getFileAttachmentsPDF()
+ * @deprecated use invoice.getAdditionalReferencedDocuments
*/
public List getFileAttachmentsXML() {
- return fileAttachments;
+ return new ArrayList<>(Arrays.asList(importedInvoice.getAdditionalReferencedDocuments()));
}
/***
diff --git a/library/src/main/java/org/mustangproject/util/NodeMap.java b/library/src/main/java/org/mustangproject/util/NodeMap.java
index 46b82a9a..77064d07 100644
--- a/library/src/main/java/org/mustangproject/util/NodeMap.java
+++ b/library/src/main/java/org/mustangproject/util/NodeMap.java
@@ -106,7 +106,14 @@ public class NodeMap {
* @return the text content of the matching node, converted to BigDecimal
*/
public Optional getAsBigDecimal(String... localNames) {
- return getNode(localNames).map(Node::getTextContent).map(s->new BigDecimal(s.trim()));
+ return getNode(localNames).map(Node::getTextContent).map(s->{
+ try {
+ return new BigDecimal(s.trim());
+ } catch (NumberFormatException e) {
+ return null;
+ }
+
+ });
}
/**
diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/DeSerializationTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/DeSerializationTest.java
index 7c6d409d..f2d16980 100644
--- a/library/src/test/java/org/mustangproject/ZUGFeRD/DeSerializationTest.java
+++ b/library/src/test/java/org/mustangproject/ZUGFeRD/DeSerializationTest.java
@@ -21,18 +21,29 @@
*/
package org.mustangproject.ZUGFeRD;
+import com.fasterxml.jackson.annotation.JsonInclude;
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 TestCase {
+public class DeSerializationTest extends ResourceCase {
public void testJackson() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
@@ -50,6 +61,33 @@ public class DeSerializationTest extends TestCase {
}
+ public void testInvoiceLine() throws JsonProcessingException {
+ File inputCII = getResourceAsFile("factur-x.xml");
+ boolean hasExceptions = false;
+
+ ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter();
+ try {
+ zii.fromXML(new String(Files.readAllBytes(inputCII.toPath()), StandardCharsets.UTF_8));
+
+ } catch (IOException e) {
+ hasExceptions = true;
+ }
+
+ CalculatedInvoice ci = new CalculatedInvoice();
+ try {
+ zii.extractInto(ci);
+ } catch (XPathExpressionException e) {
+ hasExceptions = true;
+ } catch (ParseException e) {
+ hasExceptions = true;
+ }
+ ObjectMapper mapper = new ObjectMapper();
+ String jsonArray = mapper.writeValueAsString(ci);
+ assertFalse(hasExceptions);
+ assertTrue(jsonArray.contains("lineTotalAmount"));
+
+ }
+
public void testAllowanceRead() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
@@ -121,14 +159,85 @@ public class DeSerializationTest extends TestCase {
" }\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 testFull300Roundtrip() {
+ File inputCII = getResourceAsFile("not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.cii.xml");
+ Invoice i=new Invoice();
+ String exText=null;
+ ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter();
+ zii.doIgnoreCalculationErrors();
+ try {
+ zii.fromXML(new String(Files.readAllBytes(inputCII.toPath()), StandardCharsets.UTF_8));
+ ObjectMapper mapper = new ObjectMapper();
+ zii.extractInto(i);
+ String json = mapper.writeValueAsString(i);
+ Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class);
+
+ assertEquals("Test_EeISI_100",i.getNumber());
+ assertEquals(newInvoiceFromJSON.getNumber(),i.getNumber());
+
+ } catch (IOException e) {
+ exText=e.getMessage();
+ } catch (XPathExpressionException e) {
+ exText=e.getMessage();
+ } catch (ParseException e) {
+ exText=e.getMessage();
+ }
+ assertNull(exText);
+
+
+ }
+
+ 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 {
@@ -186,4 +295,389 @@ public class DeSerializationTest extends TestCase {
}
+ 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/XRTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/XRTest.java
index 5a263eca..3efa4ccf 100644
--- a/library/src/test/java/org/mustangproject/ZUGFeRD/XRTest.java
+++ b/library/src/test/java/org/mustangproject/ZUGFeRD/XRTest.java
@@ -136,11 +136,11 @@ public class XRTest extends TestCase {
} catch (IOException e) {
fail("IOException not expected");
}
- List attachedFiles=zii.getFileAttachmentsXML();
+ FileAttachment[] attachedFiles=readInvoice.getAdditionalReferencedDocuments();
assertNotNull(attachedFiles);
- assertEquals(attachedFiles.size(), 1);
+ assertEquals(attachedFiles.length, 1);
- assertTrue(Arrays.equals(attachedFiles.get(0).getData(), b));
+ assertTrue(Arrays.equals(attachedFiles[0].getData(), b));
}
diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java
index be949c34..ce0ee767 100644
--- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java
+++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java
@@ -22,6 +22,7 @@
package org.mustangproject.ZUGFeRD;
import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
@@ -29,6 +30,7 @@ import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.List;
import org.mustangproject.*;
import org.junit.FixMethodOrder;
@@ -61,9 +63,9 @@ public class ZF2PushTest extends TestCase {
final String TARGET_REVERSECHARGEPDF = "./target/testout-ZF2PushReverseCharge.pdf";
public void testPushExport() {
- /***
- * This writes to a filename like an official sample, please consider when changing (probably better not?)
- */
+ /***
+ * This writes to a filename like an official sample, please consider when changing (probably better not?)
+ */
// the writing part
String orgname = "Bei Spiel GmbH";
String number = "RE-20201121/508";
@@ -88,6 +90,7 @@ public class ZF2PushTest extends TestCase {
.addItem(new Item(new Product("Design (hours)", "Of a sample invoice", "HUR", new BigDecimal(7)), price, new BigDecimal(1.0)))
.addItem(new Item(new Product("Ballons", "various colors, ~2000ml", "H87", new BigDecimal(19)), new BigDecimal("0.79"), new BigDecimal(400.0)))
.addItem(new Item(new Product("Hot air „heiße Luft“ (litres)", "", "LTR", new BigDecimal(19)), new BigDecimal("0.025"), new BigDecimal(800.0)))
+ .setRoundingAmount(new BigDecimal("1"))
);
ze.export(TARGET_PDF);
@@ -95,6 +98,15 @@ public class ZF2PushTest extends TestCase {
fail("Exception should not be raised");
}
+ ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(TARGET_PDF);
+ Invoice i = new Invoice();
+ try {
+ zii.extractInto(i);
+ } catch (XPathExpressionException e) {
+ throw new RuntimeException(e);
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
// now check the contents (like MustangReaderTest)
@@ -128,6 +140,7 @@ public class ZF2PushTest extends TestCase {
String senderDescription = "Kleinunternehmer";
String taxID = "9990815";
+ String theNote="oh lala";
BigDecimal price = new BigDecimal(priceStr);
try {
InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
@@ -145,7 +158,7 @@ public class ZF2PushTest extends TestCase {
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE4711")
.setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE")))
.setNumber(number)
- .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(0)).setTaxExemptionReason("Kleinunternehmer gemäß §19 UStG").setTaxCategoryCode("E"), price, new BigDecimal(1.0)))
+ .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(0)).setTaxExemptionReason("Kleinunternehmer gemäß §19 UStG").setTaxCategoryCode("E"), price, new BigDecimal(1.0)).addNote(theNote))
);
String theXML = new String(ze.getProvider().getXML());
assertTrue(theXML.contains(" note.getSubjectCode().equals(SubjectCode.ABZ)).findFirst().get().getContent());
+ }
+
+ @Test
+ public void testImportXRechnungPositionNote() throws FileNotFoundException, XPathExpressionException, ParseException {
+ File inputFile = getResourceAsFile("TESTXRECHNUNG_INVDSS_012015776085.XML");
+ ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(new FileInputStream(inputFile));
+
+ Invoice invoice = zii.extractInvoice();
+ assertEquals(1, invoice.getZFItems().length);
+ assertFalse(invoice.getZFItems()[0].getNotes() == null);
+ assertEquals(1, invoice.getZFItems()[0].getNotes().length);
+ }
}
diff --git a/library/src/test/resources/EN16931_1_Teilrechnung.pdf b/library/src/test/resources/EN16931_1_Teilrechnung.pdf
new file mode 100644
index 00000000..0bc3ea77
Binary files /dev/null and b/library/src/test/resources/EN16931_1_Teilrechnung.pdf differ
diff --git a/library/src/test/resources/TESTXRECHNUNG_INVDSS_012015776085.XML b/library/src/test/resources/TESTXRECHNUNG_INVDSS_012015776085.XML
new file mode 100644
index 00000000..1541326d
--- /dev/null
+++ b/library/src/test/resources/TESTXRECHNUNG_INVDSS_012015776085.XML
@@ -0,0 +1,157 @@
+
+ urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+ 2015776085
+ 2024-11-01
+ 380
+ #AAI# Wenn bereits bezahlt, nur zu den Akten legen. Für Verzug und Verzugszinsen gelten die Bestimmungen der §§ 286 - 288 BGB. Der Schuldner einer Entgeltforderung kommt spätestens in Verzug, wenn er nicht innerhalb von 30 Tagen nach Fälligkeit und Zugang einer Rechnung oder gleichwertigen Zahlungsaufstellung leistet. Die Lieferung von Waren und Fahrzeugen erfolgt unter Eigentumsvorbehalt.
+ #PAI# Rechnungsbetrag zahlbar ohne Abzug sofort nach Erhalt der Rechnung.
+ EUR
+ 02-ZZ987654-99
+
+ 2024-11-01
+ 2024-11-30
+
+
+ N/A
+
+
+ 63435555
+
+
+
+ DE238574172
+
+ Alphabet Fuhrparkmanagement GmbH
+
+
+ Lilienthalallee 26
+ München
+ 80786
+
+ DE
+
+
+
+ DE238574172
+
+ VAT
+
+
+
+ Alphabet Fuhrparkmanagement GmbH
+ HRB 181098
+
+
+ Yildiz Tolga
+ +49899--
+ Tolga.Yildiz@alphabet.de
+
+
+
+
+
+ N/A
+
+ 00987654
+
+
+ Muster GmbH
+
+
+ Musterweg 1
+ Kiel
+ 24105
+
+ DE
+
+
+
+ Muster GmbH
+
+
+ Mustermann Max
+
+
+
+
+ 2024-11-30
+
+ 00987654
+
+ Musterweg 1
+ Kiel
+ 24105
+
+ DE
+
+
+
+
+
+ Muster GmbH
+
+
+
+
+ 30
+
+ DE34700700100156919301
+ Alphabet Fuhrparkmanagement GmbH
+
+ DEUTDEMMXXX
+
+
+
+
+ Rechnungsbetrag zahlbar ohne Abzug sofort nach Erhalt der Rechnung.
+
+
+ 161.69
+
+ 851.00
+ 161.69
+
+ S
+ 19.00
+
+ VAT
+
+
+
+
+
+ 851.00
+ 851.00
+ 1012.69
+ 1012.69
+
+
+ 1
+ #AAI# Finanzrate vom 01.11.2024 bis 30.11.2024 #ABZ/Kennzeichen#SH-9 18E #AKG/Fahrgestellnummer#WBY51EJ080CR55555 #BA/Kilometerstand#0 #AKV/LeasingNr#63435555
+ 1.00
+ 851.00
+
+ 2024-11-01
+ 2024-11-30
+
+
+ FL-Rate
+ FL-Rate
+
+ 90101
+
+
+ S
+ 19.00
+
+ VAT
+
+
+
+
+ 851.00
+ 1.00
+
+
+
diff --git a/library/src/test/resources/ZTESTZUGFERD_1_INVDSS_012015738820PDF-1.pdf b/library/src/test/resources/ZTESTZUGFERD_1_INVDSS_012015738820PDF-1.pdf
new file mode 100644
index 00000000..7b220689
Binary files /dev/null and b/library/src/test/resources/ZTESTZUGFERD_1_INVDSS_012015738820PDF-1.pdf differ
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
-
-
-
diff --git a/library/src/test/resources/testout-ZF2new.ubl.xml b/library/src/test/resources/testout-ZF2new.ubl.xml
index 9be2f765..c1cd3bc5 100644
--- a/library/src/test/resources/testout-ZF2new.ubl.xml
+++ b/library/src/test/resources/testout-ZF2new.ubl.xml
@@ -123,6 +123,7 @@
1
+ Something
1
160
@@ -178,4 +179,4 @@
1
-
\ No newline at end of file
+
diff --git a/pom.xml b/pom.xml
index 1752f94e..a66ce931 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
org.mustangproject
core
- 2.15.0-SNAPSHOT
+ 2.15.2-SNAPSHOT
pom
Mustang
diff --git a/validator/pom.xml b/validator/pom.xml
index 362ce454..8fe7e62c 100644
--- a/validator/pom.xml
+++ b/validator/pom.xml
@@ -3,7 +3,7 @@
org.mustangproject
core
- 2.15.0-SNAPSHOT
+ 2.15.2-SNAPSHOT
4.0.0
org.mustangproject
@@ -11,7 +11,7 @@
Library to validate e-invoices (ZUGFeRD, Factur-X and Xrechnung)
jar
- 2.15.0-SNAPSHOT
+ 2.15.2-SNAPSHOT
@@ -38,12 +38,18 @@
${project.groupId}
library
- 2.15.0-SNAPSHOT
+ 2.15.2-SNAPSHOT
org.dom4j
dom4j
2.1.4
+
+
+ *
+ *
+
+
commons-io
@@ -224,10 +230,10 @@
- ${basedir}/src/main/resources/xslt/ZF_230/
+ src/main/resources/xslt/ZF_232/
- ${basedir}/src/main/resources/schematron/ZF_230/
+ ${basedir}/src/main/resources/schematron/ZF_232/
**/*.xml
diff --git a/validator/src/main/java/org/mustangproject/validator/PDFValidator.java b/validator/src/main/java/org/mustangproject/validator/PDFValidator.java
index c42caa9e..15a4108a 100644
--- a/validator/src/main/java/org/mustangproject/validator/PDFValidator.java
+++ b/validator/src/main/java/org/mustangproject/validator/PDFValidator.java
@@ -122,7 +122,9 @@ public class PDFValidator extends Validator {
}
// step 2 validate XMP
- final ZUGFeRDImporter zi = new ZUGFeRDImporter(inputStream);
+ final ZUGFeRDImporter zi = new ZUGFeRDImporter();
+ zi.doIgnoreCalculationErrors();//of course the calculation will still be schematron checked
+ zi.setInputStream(inputStream);
final String xmp = zi.getXMP();
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
@@ -239,7 +241,7 @@ public class PDFValidator extends Validator {
boolean versionValid = false;
for (int i = 0; i < nodes.getLength(); i++) {
- final String[] valueArray = {"1.0", "2p0", "1.2", "2.0", "2.1", "2.2", "2.3", "3.0"}; //1.2, 2.0, 2.1, 2.2, 2.3 and 3.0 are for xrechnung 1.2, 2p0 can be ZF 2.0, 2.1, 2.1.1
+ final String[] valueArray = {"1.0", "1p0", "2p0", "1.2", "2.0", "2.1", "2.2", "2.3", "3.0"}; //1.2, 2.0, 2.1, 2.2, 2.3 and 3.0 are for xrechnung 1.2, 2p0 can be ZF 2.0, 2.1, 2.1.1
if (stringArrayContains(valueArray, nodes.item(i).getTextContent())) {
versionValid = true;
@@ -265,6 +267,7 @@ public class PDFValidator extends Validator {
final byte[] pdfMachineSignature = "pdfMachine from Broadgun Software".getBytes(StandardCharsets.UTF_8);
final byte[] ghostscriptSignature = "%%Invocation:".getBytes(StandardCharsets.UTF_8);
final byte[] cibpdfbrewerSignature = "CIB pdf brewer".getBytes(StandardCharsets.UTF_8);
+ final byte[] lexofficeSignature = "lexoffice".getBytes(StandardCharsets.UTF_8);
if (ByteArraySearcher.contains(fileContents, symtraxSignature)) {
Signature = "Symtrax";
@@ -282,6 +285,8 @@ public class PDFValidator extends Validator {
Signature = "Ghostscript";
} else if (ByteArraySearcher.contains(fileContents, cibpdfbrewerSignature)) {
Signature = "CIB pdf brewer";
+ } else if (ByteArraySearcher.contains(fileContents, lexofficeSignature)) {
+ Signature = "Lexware office";
}
context.setSignature(Signature);
diff --git a/validator/src/main/java/org/mustangproject/validator/ValidationContext.java b/validator/src/main/java/org/mustangproject/validator/ValidationContext.java
index a74c9f1c..73b95f2e 100644
--- a/validator/src/main/java/org/mustangproject/validator/ValidationContext.java
+++ b/validator/src/main/java/org/mustangproject/validator/ValidationContext.java
@@ -135,6 +135,22 @@ public class ValidationContext {
return String.join(",", errorcodes);
}
+ /***
+ *
+ * @return the unique error IDs as comma separated string
+ */
+ public String getCSVIDResult() {
+ final ArrayList errorIDs = new ArrayList<>();
+ for (final ValidationResultItem validationResultItem : results) {
+ if (!validationResultItem.getID().isEmpty()) {
+ final String errorID=validationResultItem.getID();
+ errorIDs.add(errorID);
+
+ }
+ }
+ return String.join(",", errorIDs);
+ }
+
public void setInvalid() {
isValid = false;
}
diff --git a/validator/src/main/java/org/mustangproject/validator/ValidationResultItem.java b/validator/src/main/java/org/mustangproject/validator/ValidationResultItem.java
index d5a9b244..b0d6b5a1 100644
--- a/validator/src/main/java/org/mustangproject/validator/ValidationResultItem.java
+++ b/validator/src/main/java/org/mustangproject/validator/ValidationResultItem.java
@@ -12,6 +12,7 @@ public class ValidationResultItem {
protected String message, location=null;
protected int section =-1;
+ protected String id =""; // e.g. "FX-SCH-A-000026"
private ESeverity severity=ESeverity.error;
@@ -103,6 +104,15 @@ public class ValidationResultItem {
return severity;
}
+ public ValidationResultItem setID(String id) {
+ this.id=id;
+ return this;
+ }
+
+ public String getID() {
+ return id;
+ }
+
public int getSection() {
return section;
}
diff --git a/validator/src/main/java/org/mustangproject/validator/XMLValidator.java b/validator/src/main/java/org/mustangproject/validator/XMLValidator.java
index c2124b87..77061ab9 100644
--- a/validator/src/main/java/org/mustangproject/validator/XMLValidator.java
+++ b/validator/src/main/java/org/mustangproject/validator/XMLValidator.java
@@ -1,4 +1,5 @@
package org.mustangproject.validator;
+
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
@@ -69,15 +70,13 @@ public class XMLValidator extends Validator {
final ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(9)
.setPart(EPart.fx);
try (final StringWriter sw = new StringWriter();
- final PrintWriter pw = new PrintWriter(sw))
- {
- e.printStackTrace(pw);
- vri.setStacktrace(sw.toString());
- context.addResultItem(vri);
+ final PrintWriter pw = new PrintWriter(sw)) {
+ e.printStackTrace(pw);
+ vri.setStacktrace(sw.toString());
+ context.addResultItem(vri);
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
}
- catch (IOException ex) {
- throw new UncheckedIOException (ex);
- }
}
}
@@ -125,9 +124,9 @@ public class XMLValidator extends Validator {
if (zfXML.isEmpty()) {
final ValidationResultItem res = new ValidationResultItem(ESeverity.exception,
- "XML data not found in " + filename
- + ": did you specify a pdf or xml file and does the xml file contain an embedded XML file?")
- .setSection(3);
+ "XML data not found in " + filename
+ + ": did you specify a pdf or xml file and does the xml file contain an embedded XML file?")
+ .setSection(3);
context.addResultItem(res);
} else {
@@ -170,7 +169,7 @@ public class XMLValidator extends Validator {
// Create XPath object
final XPath xpath = xpathFactory.newXPath();
final XPathExpression expr = xpath.compile(
- "(//*[local-name()=\"GuidelineSpecifiedDocumentContextParameter\"]/*[local-name()=\"ID\"])/text()|//*[local-name()=\"CustomizationID\"]/text()");
+ "(//*[local-name()=\"GuidelineSpecifiedDocumentContextParameter\"]/*[local-name()=\"ID\"])/text()|//*[local-name()=\"CustomizationID\"]/text()");
// evaluate expression result on XML document
ndList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
@@ -190,8 +189,8 @@ public class XMLValidator extends Validator {
boolean isEN16931 = false;
boolean isExtended = false;
boolean isXRechnung = false;
- String currentZFVersionDir = "ZF_230";
- int mainSchematronSectionErrorTypeCode=4;
+ String currentZFVersionDir = "ZF_232";
+ int mainSchematronSectionErrorTypeCode = 4;
String xsltFilename = null;
// urn:ferd:CrossIndustryDocument:invoice:1p0:extended,
// urn:ferd:CrossIndustryDocument:invoice:1p0:comfort,
@@ -224,7 +223,7 @@ public class XMLValidator extends Validator {
isBasic = false;// basicwl also contains the string basic...
}
isEN16931 = matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017:compliant:factur-x.eu:1p0:en16931")
- || matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017");
+ || matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017");
isExtended = context.getProfile().contains("extended");
isXRechnung = context.getProfile().contains("xrechnung");
@@ -269,16 +268,16 @@ public class XMLValidator extends Validator {
// saxon java net.sf.saxon.Transform -o tcdl2.0.tsdtf.sch.tmp.xsl -s
// tcdl2.0.tsdtf.sch iso_svrl.xsl
- } else if (root.getLocalName().equalsIgnoreCase("Invoice") || root.getLocalName().equalsIgnoreCase("CreditNote") ) {
+ } else if (root.getLocalName().equalsIgnoreCase("Invoice") || root.getLocalName().equalsIgnoreCase("CreditNote")) {
context.setGeneration("2");
context.setFormat("UBL");
isXRechnung = context.getProfile().contains("xrechnung");
// UBL
LOGGER.debug("UBL");
- validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "UBL_21/maindoc/UBL-"+root.getLocalName()+"-2.1.xsd", 18, EPart.fx);
+ validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "UBL_21/maindoc/UBL-" + root.getLocalName() + "-2.1.xsd", 18, EPart.fx);
xsltFilename = "/xslt/en16931schematron/EN16931-UBL-validation.xslt";
- mainSchematronSectionErrorTypeCode=24;
+ mainSchematronSectionErrorTypeCode = 24;
if (isXRechnung) {
validateSchematron(zfXML, xsltFilename, 24, ESeverity.error);
@@ -287,14 +286,14 @@ public class XMLValidator extends Validator {
XRechnung is a EN16931 subset so the validation vis a vis FACTUR-X_EN16931.xslt=schematron also has to pass
* */
//validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "ZF_211/EN16931/FACTUR-X_EN16931.xsd", 18, EPart.fx);
- String xrVersion=context.getProfile().substring(context.getProfile().length()-3).replace(".","");
- if (!xrVersion.equals("12")&&!xrVersion.equals("20")&&!xrVersion.equals("21")&&!xrVersion.equals("22")&&!xrVersion.equals("23")&&!xrVersion.equals("30")) {
+ String xrVersion = context.getProfile().substring(context.getProfile().length() - 3).replace(".", "");
+ if (!xrVersion.equals("12") && !xrVersion.equals("20") && !xrVersion.equals("21") && !xrVersion.equals("22") && !xrVersion.equals("23") && !xrVersion.equals("30")) {
throw new Exception("Unsupported XR version");
}
- LOGGER.debug("is XRechnung v"+xrVersion);
- xsltFilename = "/xslt/XR_"+xrVersion+"/XRechnung-UBL-validation.xslt";
+ LOGGER.debug("is XRechnung v" + xrVersion);
+ xsltFilename = "/xslt/XR_" + xrVersion + "/XRechnung-UBL-validation.xslt";
XrechnungSeverity = ESeverity.error;
- mainSchematronSectionErrorTypeCode=27;
+ mainSchematronSectionErrorTypeCode = 27;
}
@@ -302,58 +301,58 @@ public class XMLValidator extends Validator {
context.setGeneration("1");
//
if ((!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:basic"))
- && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort"))
- && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:extended"))) {
+ && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort"))
+ && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:extended"))) {
context.addResultItem(new ValidationResultItem(ESeverity.error, "Unsupported profile type")
- .setSection(25).setPart(EPart.fx));
+ .setSection(25).setPart(EPart.fx));
}
validateSchema(zfXML.getBytes(StandardCharsets.UTF_8), "ZF_10/ZUGFeRD1p0.xsd", 18, EPart.fx);
xsltFilename = "/xslt/ZUGFeRD_1p0.xslt";
} else { // unknown document root
context.addResultItem(new ValidationResultItem(ESeverity.fatal, "Unsupported root element")
- .setSection(3).setPart(EPart.fx));
+ .setSection(3).setPart(EPart.fx));
}
if (context.getFormat().equals("CII")) {
if (context.getGeneration().equals("2")) {
if ((!matchesURI(context.getProfile(), "urn:factur-x.eu:1p0:minimum"))
- && (!matchesURI(context.getProfile(), "urn:zugferd.de:2p0:minimum"))
- && (!matchesURI(context.getProfile(), "urn:factur-x.eu:1p0:basicwl"))
- && (!matchesURI(context.getProfile(), "urn:zugferd.de:2p0:basicwl"))
- && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic"))
- && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017#compliant#urn:zugferd.de:2p0:basic"))
- && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017"))
- && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended"))
- && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended"))) {
+ && (!matchesURI(context.getProfile(), "urn:zugferd.de:2p0:minimum"))
+ && (!matchesURI(context.getProfile(), "urn:factur-x.eu:1p0:basicwl"))
+ && (!matchesURI(context.getProfile(), "urn:zugferd.de:2p0:basicwl"))
+ && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic"))
+ && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017#compliant#urn:zugferd.de:2p0:basic"))
+ && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017"))
+ && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended"))
+ && (!matchesURI(context.getProfile(), "urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended"))) {
context.addResultItem(
- new ValidationResultItem(ESeverity.error, "Unsupported profile type " + context.getProfile())
- .setSection(25).setPart(EPart.fx));
+ new ValidationResultItem(ESeverity.error, "Unsupported profile type " + context.getProfile())
+ .setSection(25).setPart(EPart.fx));
}
} else /** v1 */ {
if (isOrderX) {
//order-x 1.0
if ((!matchesURI(context.getProfile(), "urn:order-x.eu:1p0:basic"))
- && (!matchesURI(context.getProfile(), "urn:order-x.eu:1p0:comfort"))
- && (!matchesURI(context.getProfile(), "urn:order-x.eu:1p0:extended"))) {
+ && (!matchesURI(context.getProfile(), "urn:order-x.eu:1p0:comfort"))
+ && (!matchesURI(context.getProfile(), "urn:order-x.eu:1p0:extended"))) {
//zf 1.0
context.addResultItem(new ValidationResultItem(ESeverity.error, "Unsupported profile type")
- .setSection(25).setPart(EPart.fx));
+ .setSection(25).setPart(EPart.fx));
}
} else if ((!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:basic"))
- && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort"))
- && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:extended"))) {
+ && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort"))
+ && (!matchesURI(context.getProfile(), "urn:ferd:CrossIndustryDocument:invoice:1p0:extended"))) {
//zf 1.0
context.addResultItem(new ValidationResultItem(ESeverity.error, "Unsupported profile type")
- .setSection(25).setPart(EPart.fx));
+ .setSection(25).setPart(EPart.fx));
}
}
}
- if (xsltFilename!=null) {
+ if (xsltFilename != null) {
// main schematron validation
validateSchematron(zfXML, xsltFilename, mainSchematronSectionErrorTypeCode, ESeverity.error);
@@ -362,7 +361,7 @@ public class XMLValidator extends Validator {
if (context.getFormat().equals("CII")) {
if (context.getGeneration().equals("2")
- && (isBasic || isEN16931 || isXRechnung)) {
+ && (isBasic || isEN16931 || isXRechnung)) {
//additionally validate against CEN
validateSchematron(zfXML, "/xslt/en16931schematron/EN16931-CII-validation.xslt", 24, ESeverity.error);
if (!disableNotices || XrechnungSeverity != ESeverity.notice) {
@@ -376,7 +375,7 @@ public class XMLValidator extends Validator {
throw er;
} catch (final Exception e) {
final ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(22)
- .setPart(EPart.fx);
+ .setPart(EPart.fx);
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
@@ -388,8 +387,8 @@ public class XMLValidator extends Validator {
final long endTime = Calendar.getInstance().getTimeInMillis();
context.addCustomXML("" + ((context.getGeneration() != null) ? context.getGeneration() : "invalid")
- + "" + ((context.getProfile() != null) ? context.getProfile() : "invalid") +
- "" + firedRules + "" + failedRules + "" + "" + (endTime - startXMLTime) + "");
+ + "" + ((context.getProfile() != null) ? context.getProfile() : "invalid") +
+ "" + firedRules + "" + failedRules + "" + "" + (endTime - startXMLTime) + "");
}
@@ -424,11 +423,6 @@ public class XMLValidator extends Validator {
*/
public void validateSchematron(String xml, String xsltFilename, int section, ESeverity defaultSeverity) throws IrrecoverableValidationError {
ISchematronResource aResSCH = null;
- ESeverity severity=defaultSeverity;
- if (defaultSeverity!=ESeverity.notice) {
- severity=ESeverity.error;
- }
-
aResSCH = SchematronResourceXSLT.fromClassPath(xsltFilename);
if (aResSCH != null) {
@@ -439,7 +433,7 @@ public class XMLValidator extends Validator {
final SchematronOutputType sout;
try {
sout = aResSCH
- .applySchematronValidationToSVRL(new StreamSource(new StringReader(xml)));
+ .applySchematronValidationToSVRL(new StreamSource(new StringReader(xml)));
} catch (final Exception e) {
throw new IrrecoverableValidationError(e.getMessage());
}
@@ -453,6 +447,7 @@ public class XMLValidator extends Validator {
String thisFailText = "";
String thisFailID = "";
+ String thisFailIDStr = "";
String thisFailTest = "";
String thisFailLocation = "";
if (failedAsserts.getLength() > 0) {
@@ -461,7 +456,8 @@ public class XMLValidator extends Validator {
//nodes.item(i).getTextContent())) {
Node currentFailNode = failedAsserts.item(nodeIndex);
if (currentFailNode.getAttributes().getNamedItem("id") != null) {
- thisFailID = " [ID " + currentFailNode.getAttributes().getNamedItem("id").getNodeValue() + "]";
+ thisFailID = currentFailNode.getAttributes().getNamedItem("id").getNodeValue();
+ thisFailIDStr = " [ID " + thisFailID + "]";
}
if (currentFailNode.getAttributes().getNamedItem("test") != null) {
thisFailTest = currentFailNode.getAttributes().getNamedItem("test").getNodeValue();
@@ -470,14 +466,15 @@ public class XMLValidator extends Validator {
thisFailLocation = currentFailNode.getAttributes().getNamedItem("location").getNodeValue();
}
- if (currentFailNode.getAttributes().getNamedItem("flag") != null) {
+ ESeverity severity;
+ if (defaultSeverity == ESeverity.notice) {
+ severity = defaultSeverity;
+ } else if (currentFailNode.getAttributes().getNamedItem("flag") != null
+ && currentFailNode.getAttributes().getNamedItem("flag").getNodeValue().equals("warning")) {
// the XR issues warnings with flag=warning
- if (currentFailNode.getAttributes().getNamedItem("flag").getNodeValue().equals("warning")) {
- if (defaultSeverity!=ESeverity.notice) {
- severity=ESeverity.warning;
- }
- }
-
+ severity = ESeverity.warning;
+ } else {
+ severity = ESeverity.error;
}
NodeList failChilds = currentFailNode.getChildNodes();
@@ -494,9 +491,9 @@ public class XMLValidator extends Validator {
LOGGER.info("FailedAssert ", thisFailText);
- context.addResultItem(new ValidationResultItem(severity, thisFailText + thisFailID + " from " + xsltFilename + ")")
- .setLocation(thisFailLocation).setCriterion(thisFailTest).setSection(section)
- .setPart(EPart.fx));
+ context.addResultItem(new ValidationResultItem(severity, thisFailText + thisFailIDStr + " from " + xsltFilename + ")")
+ .setLocation(thisFailLocation).setCriterion(thisFailTest).setSection(section).setID(thisFailID)
+ .setPart(EPart.fx));
failedRules++;
}
@@ -527,7 +524,7 @@ public class XMLValidator extends Validator {
if (firedRules == 0) {
context.addResultItem(new ValidationResultItem(ESeverity.error, "No rules matched, XML to minimal?").setSection(26)
- .setPart(EPart.fx));
+ .setPart(EPart.fx));
}
// for (String currentString : sout.getText()) {
diff --git a/validator/src/main/java/org/mustangproject/validator/ZUGFeRDValidator.java b/validator/src/main/java/org/mustangproject/validator/ZUGFeRDValidator.java
index edd9a73d..d21317b1 100644
--- a/validator/src/main/java/org/mustangproject/validator/ZUGFeRDValidator.java
+++ b/validator/src/main/java/org/mustangproject/validator/ZUGFeRDValidator.java
@@ -318,7 +318,7 @@ public class ZUGFeRDValidator {
LOGGER.info("Parsed PDF:" + pdfResult + " XML:" + (xmlValidity ? "valid" : "invalid")
+ " Signature:" + Signature + " Checksum:" + sha1Checksum + " Profile:" + context.getProfile()
+ " Version:" + context.getGeneration() + " Took:" + duration + "ms Errors:[" + context.getCSVResult()
- + "] " + toBeAppended);
+ + "] ErrorIDs: [" + context.getCSVIDResult() + "]" + toBeAppended);
wasCompletelyValid = ((pdfValidity) && (xmlValidity));
return sw.toString();
}
diff --git a/validator/src/main/resources/schema/ZF_230/BASIC-WL/FACTUR-X_BASIC-WL.xsd b/validator/src/main/resources/schema/ZF_232/BASIC-WL/FACTUR-X_BASIC-WL.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/BASIC-WL/FACTUR-X_BASIC-WL.xsd
rename to validator/src/main/resources/schema/ZF_232/BASIC-WL/FACTUR-X_BASIC-WL.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd b/validator/src/main/resources/schema/ZF_232/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
rename to validator/src/main/resources/schema/ZF_232/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd b/validator/src/main/resources/schema/ZF_232/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
similarity index 98%
rename from validator/src/main/resources/schema/ZF_230/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
rename to validator/src/main/resources/schema/ZF_232/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
index 89d8a099..f6345542 100644
--- a/validator/src/main/resources/schema/ZF_230/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
+++ b/validator/src/main/resources/schema/ZF_232/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
@@ -5,8 +5,8 @@
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
targetNamespace="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
elementFormDefault="qualified">
-
-
+
+
diff --git a/validator/src/main/resources/schema/ZF_230/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd b/validator/src/main/resources/schema/ZF_232/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
rename to validator/src/main/resources/schema/ZF_232/BASIC-WL/FACTUR-X_BASIC-WL_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/BASIC/FACTUR-X_BASIC.xsd b/validator/src/main/resources/schema/ZF_232/BASIC/FACTUR-X_BASIC.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/BASIC/FACTUR-X_BASIC.xsd
rename to validator/src/main/resources/schema/ZF_232/BASIC/FACTUR-X_BASIC.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd b/validator/src/main/resources/schema/ZF_232/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
rename to validator/src/main/resources/schema/ZF_232/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd b/validator/src/main/resources/schema/ZF_232/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
similarity index 99%
rename from validator/src/main/resources/schema/ZF_230/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
rename to validator/src/main/resources/schema/ZF_232/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
index 35458e59..517d0fb0 100644
--- a/validator/src/main/resources/schema/ZF_230/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
+++ b/validator/src/main/resources/schema/ZF_232/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
@@ -5,8 +5,8 @@
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
targetNamespace="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
elementFormDefault="qualified">
-
-
+
+
diff --git a/validator/src/main/resources/schema/ZF_230/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd b/validator/src/main/resources/schema/ZF_232/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
rename to validator/src/main/resources/schema/ZF_232/BASIC/FACTUR-X_BASIC_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/EN16931/FACTUR-X_EN16931.xsd b/validator/src/main/resources/schema/ZF_232/EN16931/FACTUR-X_EN16931.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/EN16931/FACTUR-X_EN16931.xsd
rename to validator/src/main/resources/schema/ZF_232/EN16931/FACTUR-X_EN16931.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd b/validator/src/main/resources/schema/ZF_232/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
rename to validator/src/main/resources/schema/ZF_232/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd b/validator/src/main/resources/schema/ZF_232/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
similarity index 99%
rename from validator/src/main/resources/schema/ZF_230/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
rename to validator/src/main/resources/schema/ZF_232/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
index 62bcf3dd..b9dfd083 100644
--- a/validator/src/main/resources/schema/ZF_230/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
+++ b/validator/src/main/resources/schema/ZF_232/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
@@ -5,8 +5,8 @@
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
targetNamespace="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
elementFormDefault="qualified">
-
-
+
+
diff --git a/validator/src/main/resources/schema/ZF_230/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd b/validator/src/main/resources/schema/ZF_232/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
rename to validator/src/main/resources/schema/ZF_232/EN16931/FACTUR-X_EN16931_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/EXTENDED/FACTUR-X_EXTENDED.xsd b/validator/src/main/resources/schema/ZF_232/EXTENDED/FACTUR-X_EXTENDED.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/EXTENDED/FACTUR-X_EXTENDED.xsd
rename to validator/src/main/resources/schema/ZF_232/EXTENDED/FACTUR-X_EXTENDED.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd b/validator/src/main/resources/schema/ZF_232/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
rename to validator/src/main/resources/schema/ZF_232/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd b/validator/src/main/resources/schema/ZF_232/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
similarity index 99%
rename from validator/src/main/resources/schema/ZF_230/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
rename to validator/src/main/resources/schema/ZF_232/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
index 7e42a4f8..80ee1129 100644
--- a/validator/src/main/resources/schema/ZF_230/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
+++ b/validator/src/main/resources/schema/ZF_232/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
@@ -5,8 +5,8 @@
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
targetNamespace="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
elementFormDefault="qualified">
-
-
+
+
diff --git a/validator/src/main/resources/schema/ZF_230/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd b/validator/src/main/resources/schema/ZF_232/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
rename to validator/src/main/resources/schema/ZF_232/EXTENDED/FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/MINIMUM/FACTUR-X_MINIMUM.xsd b/validator/src/main/resources/schema/ZF_232/MINIMUM/FACTUR-X_MINIMUM.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/MINIMUM/FACTUR-X_MINIMUM.xsd
rename to validator/src/main/resources/schema/ZF_232/MINIMUM/FACTUR-X_MINIMUM.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd b/validator/src/main/resources/schema/ZF_232/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
rename to validator/src/main/resources/schema/ZF_232/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd
diff --git a/validator/src/main/resources/schema/ZF_230/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd b/validator/src/main/resources/schema/ZF_232/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
similarity index 97%
rename from validator/src/main/resources/schema/ZF_230/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
rename to validator/src/main/resources/schema/ZF_232/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
index 8fad95ed..389563bd 100644
--- a/validator/src/main/resources/schema/ZF_230/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
+++ b/validator/src/main/resources/schema/ZF_232/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd
@@ -5,8 +5,8 @@
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
targetNamespace="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
elementFormDefault="qualified">
-
-
+
+
diff --git a/validator/src/main/resources/schema/ZF_230/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd b/validator/src/main/resources/schema/ZF_232/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
similarity index 100%
rename from validator/src/main/resources/schema/ZF_230/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
rename to validator/src/main/resources/schema/ZF_232/MINIMUM/FACTUR-X_MINIMUM_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd
diff --git a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_BASIC-WL.sch b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_BASIC-WL.sch
similarity index 99%
rename from validator/src/main/resources/schematron/ZF_230/FACTUR-X_BASIC-WL.sch
rename to validator/src/main/resources/schematron/ZF_232/FACTUR-X_BASIC-WL.sch
index 9a08c305..29de139b 100644
--- a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_BASIC-WL.sch
+++ b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_BASIC-WL.sch
@@ -1,5 +1,5 @@
- Schema for Factur-X; 1.0.07; Accounting, BASIC without Lines
+ Schema for Factur-X; 1.07.2; Accounting, BASIC without Lines
@@ -164,7 +164,7 @@
[BR-AG-03]-An Invoice that contains a Document level allowance (BG-20) where the Document level allowance VAT category code (BT-95) is "IPSI" shall contain the Seller VAT Identifier (BT-31), the Seller Tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63).
-
+
[BR-AG-06]-In a Document level allowance (BG-20) where the Document level allowance VAT category code (BT-95) is "IPSI" the Document level allowance VAT rate (BT-96) shall be 0 (zero) or greater than zero.
@@ -236,7 +236,7 @@
[BR-AG-04]-An Invoice that contains a Document level charge (BG-21) where the Document level charge VAT category code (BT-102) is "IPSI" shall contain the Seller VAT Identifier (BT-31), the Seller Tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63).
-
+
[BR-AG-07]-In a Document level charge (BG-21) where the Document level charge VAT category code (BT-102) is "IPSI" the Document level charge VAT rate (BT-103) shall be 0 (zero) or greater than zero.
@@ -322,12 +322,16 @@
[BR-CO-27]-Either the IBAN or a Proprietary ID (BT-84) shall be used.
+
+
+
+ [BR-61]-If the Payment means type code (BT-81) means SEPA credit transfer, Local credit transfer or Non-SEPA international credit transfer, the Payment account identifier (BT-84) shall be present.
+
+
[BR-50]-A Payment account identifier (BT-84) shall be present if Credit transfer (BG-16) information is provided in the Invoice.
-
- [BR-61]-If the Payment means type code (BT-81) means SEPA credit transfer, Local credit transfer or Non-SEPA international credit transfer, the Payment account identifier (BT-84) shall be present.
diff --git a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_BASIC-WL_codedb.xml b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_BASIC-WL_codedb.xml
similarity index 98%
rename from validator/src/main/resources/schematron/ZF_230/FACTUR-X_BASIC-WL_codedb.xml
rename to validator/src/main/resources/schematron/ZF_232/FACTUR-X_BASIC-WL_codedb.xml
index cc567d65..b5fef2d7 100644
--- a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_BASIC-WL_codedb.xml
+++ b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_BASIC-WL_codedb.xml
@@ -2,6 +2,7 @@
+
@@ -692,6 +693,14 @@
+
+
+
+
+
+
+
+
@@ -919,6 +928,14 @@
+
+
+
+
+
+
+
+
@@ -1189,6 +1206,7 @@
+
@@ -1220,6 +1238,7 @@
+
@@ -1336,7 +1355,6 @@
-
@@ -1429,6 +1447,7 @@
+
@@ -1453,6 +1472,7 @@
+
@@ -1588,6 +1608,8 @@
+
+
@@ -1603,6 +1625,7 @@
+
@@ -1884,7 +1907,6 @@
-
@@ -1977,6 +1999,7 @@
+
@@ -2001,6 +2024,7 @@
+
@@ -2065,7 +2089,6 @@
-
@@ -2158,6 +2181,7 @@
+
@@ -2182,6 +2206,7 @@
+
diff --git a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_BASIC.sch b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_BASIC.sch
similarity index 99%
rename from validator/src/main/resources/schematron/ZF_230/FACTUR-X_BASIC.sch
rename to validator/src/main/resources/schematron/ZF_232/FACTUR-X_BASIC.sch
index dfaefe8b..9a8304eb 100644
--- a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_BASIC.sch
+++ b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_BASIC.sch
@@ -1,5 +1,5 @@
- Schema for Factur-X; 1.0.07; EN16931-COMPLIANT-BASIC
+ Schema for Factur-X; 1.07.2; EN16931-COMPLIANT-BASIC
@@ -118,7 +118,7 @@
[BR-65]-The Item classification identifier (BT-158) shall have a Scheme identifier.
[BR-CO-04]-Each Invoice line (BG-25) shall be categorized with an Invoiced item VAT category code (BT-151).
-
+
[BR-DEC-23]-The allowed maximum number of decimals for the Invoice line net amount (BT-131) is 2.
@@ -246,7 +246,7 @@
[BR-AG-03]-An Invoice that contains a Document level allowance (BG-20) where the Document level allowance VAT category code (BT-95) is "IPSI" shall contain the Seller VAT Identifier (BT-31), the Seller Tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63).
-
+
[BR-AG-06]-In a Document level allowance (BG-20) where the Document level allowance VAT category code (BT-95) is "IPSI" the Document level allowance VAT rate (BT-96) shall be 0 (zero) or greater than zero.
@@ -318,7 +318,7 @@
[BR-AG-04]-An Invoice that contains a Document level charge (BG-21) where the Document level charge VAT category code (BT-102) is "IPSI" shall contain the Seller VAT Identifier (BT-31), the Seller Tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63).
-
+
[BR-AG-07]-In a Document level charge (BG-21) where the Document level charge VAT category code (BT-102) is "IPSI" the Document level charge VAT rate (BT-103) shall be 0 (zero) or greater than zero.
@@ -406,12 +406,16 @@
[BR-CO-27]-Either the IBAN or a Proprietary ID (BT-84) shall be used.
+
+
+
+ [BR-61]-If the Payment means type code (BT-81) means SEPA credit transfer, Local credit transfer or Non-SEPA international credit transfer, the Payment account identifier (BT-84) shall be present.
+
+
[BR-50]-A Payment account identifier (BT-84) shall be present if Credit transfer (BG-16) information is provided in the Invoice.
-
- [BR-61]-If the Payment means type code (BT-81) means SEPA credit transfer, Local credit transfer or Non-SEPA international credit transfer, the Payment account identifier (BT-84) shall be present.
@@ -546,7 +550,7 @@
[BR-AG-02]-An Invoice that contains an Invoice line (BG-25) where the Invoiced item VAT category code (BT-151) is "IPSI" shall contain the Seller VAT Identifier (BT-31), the Seller tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63).
-
+
[BR-AG-05]-In an Invoice line (BG-25) where the Invoiced item VAT category code (BT-151) is "IPSI" the Invoiced item VAT rate (BT-152) shall be 0 (zero) or greater than zero.
diff --git a/validator/src/main/resources/xslt/ZF_230/FACTUR-X_BASIC_codedb.xml b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_BASIC_codedb.xml
similarity index 99%
rename from validator/src/main/resources/xslt/ZF_230/FACTUR-X_BASIC_codedb.xml
rename to validator/src/main/resources/schematron/ZF_232/FACTUR-X_BASIC_codedb.xml
index ce1fdffe..d8154cdc 100644
--- a/validator/src/main/resources/xslt/ZF_230/FACTUR-X_BASIC_codedb.xml
+++ b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_BASIC_codedb.xml
@@ -2,6 +2,7 @@
+
@@ -692,6 +693,14 @@
+
+
+
+
+
+
+
+
@@ -3298,6 +3307,14 @@
+
+
+
+
+
+
+
+
@@ -3525,6 +3542,14 @@
+
+
+
+
+
+
+
+
@@ -3795,6 +3820,7 @@
+
@@ -3826,6 +3852,7 @@
+
@@ -3942,7 +3969,6 @@
-
@@ -4035,6 +4061,7 @@
+
@@ -4059,6 +4086,7 @@
+
@@ -4180,6 +4208,8 @@
+
+
@@ -4195,6 +4225,7 @@
+
@@ -4476,7 +4507,6 @@
-
@@ -4569,6 +4599,7 @@
+
@@ -4593,6 +4624,7 @@
+
@@ -4657,7 +4689,6 @@
-
@@ -4750,6 +4781,7 @@
+
@@ -4774,6 +4806,7 @@
+
diff --git a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_EN16931.sch b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_EN16931.sch
similarity index 99%
rename from validator/src/main/resources/schematron/ZF_230/FACTUR-X_EN16931.sch
rename to validator/src/main/resources/schematron/ZF_232/FACTUR-X_EN16931.sch
index 179768be..86eefe5a 100644
--- a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_EN16931.sch
+++ b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_EN16931.sch
@@ -1,5 +1,5 @@
- Schema for Factur-X; 1.0.07; EN16931-COMPLIANT (FULLY)
+ Schema for Factur-X; 1.07.2; EN16931-COMPLIANT (FULLY)
@@ -130,7 +130,7 @@
[BR-65]-The Item classification identifier (BT-158) shall have a Scheme identifier.
[BR-CO-04]-Each Invoice line (BG-25) shall be categorized with an Invoiced item VAT category code (BT-151).
-
+
[BR-DEC-23]-The allowed maximum number of decimals for the Invoice line net amount (BT-131) is 2.
@@ -258,7 +258,7 @@
[BR-AG-03]-An Invoice that contains a Document level allowance (BG-20) where the Document level allowance VAT category code (BT-95) is "IPSI" shall contain the Seller VAT Identifier (BT-31), the Seller Tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63).
-
+
[BR-AG-06]-In a Document level allowance (BG-20) where the Document level allowance VAT category code (BT-95) is "IPSI" the Document level allowance VAT rate (BT-96) shall be 0 (zero) or greater than zero.
@@ -330,7 +330,7 @@
[BR-AG-04]-An Invoice that contains a Document level charge (BG-21) where the Document level charge VAT category code (BT-102) is "IPSI" shall contain the Seller VAT Identifier (BT-31), the Seller Tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63).
-
+
[BR-AG-07]-In a Document level charge (BG-21) where the Document level charge VAT category code (BT-102) is "IPSI" the Document level charge VAT rate (BT-103) shall be 0 (zero) or greater than zero.
@@ -418,12 +418,16 @@
[BR-CO-27]-Either the IBAN or a Proprietary ID (BT-84) shall be used.
+
+
+
+ [BR-61]-If the Payment means type code (BT-81) means SEPA credit transfer, Local credit transfer or Non-SEPA international credit transfer, the Payment account identifier (BT-84) shall be present.
+
+
[BR-50]-A Payment account identifier (BT-84) shall be present if Credit transfer (BG-16) information is provided in the Invoice.
-
- [BR-61]-If the Payment means type code (BT-81) means SEPA credit transfer, Local credit transfer or Non-SEPA international credit transfer, the Payment account identifier (BT-84) shall be present.
@@ -558,7 +562,7 @@
[BR-AG-02]-An Invoice that contains an Invoice line (BG-25) where the Invoiced item VAT category code (BT-151) is "IPSI" shall contain the Seller VAT Identifier (BT-31), the Seller tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63).
-
+
[BR-AG-05]-In an Invoice line (BG-25) where the Invoiced item VAT category code (BT-151) is "IPSI" the Invoiced item VAT rate (BT-152) shall be 0 (zero) or greater than zero.
diff --git a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_EN16931_codedb.xml b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_EN16931_codedb.xml
similarity index 99%
rename from validator/src/main/resources/schematron/ZF_230/FACTUR-X_EN16931_codedb.xml
rename to validator/src/main/resources/schematron/ZF_232/FACTUR-X_EN16931_codedb.xml
index d0ad2b33..ae1b08a2 100644
--- a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_EN16931_codedb.xml
+++ b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_EN16931_codedb.xml
@@ -692,6 +692,14 @@
+
+
+
+
+
+
+
+
@@ -4561,6 +4569,14 @@
+
+
+
+
+
+
+
+
@@ -4788,6 +4804,14 @@
+
+
+
+
+
+
+
+
@@ -4805,6 +4829,7 @@
+
@@ -4836,6 +4861,7 @@
+
@@ -4969,7 +4995,6 @@
-
@@ -5062,6 +5087,7 @@
+
@@ -5086,6 +5112,7 @@
+
@@ -5207,6 +5234,8 @@
+
+
@@ -5222,6 +5251,7 @@
+
@@ -5506,7 +5536,6 @@
-
@@ -5599,6 +5628,7 @@
+
@@ -5623,6 +5653,7 @@
+
@@ -5687,7 +5718,6 @@
-
@@ -5780,6 +5810,7 @@
+
@@ -5804,6 +5835,7 @@
+
diff --git a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_EXTENDED.sch b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_EXTENDED.sch
similarity index 98%
rename from validator/src/main/resources/schematron/ZF_230/FACTUR-X_EXTENDED.sch
rename to validator/src/main/resources/schematron/ZF_232/FACTUR-X_EXTENDED.sch
index c17c0359..75f84b54 100644
--- a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_EXTENDED.sch
+++ b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_EXTENDED.sch
@@ -1,5 +1,5 @@
- Schema for Factur-X; 1.0.07; EN16931-CONFORMANT-EXTENDED
+ Schema for Factur-X; 1.07.2; EN16931-CONFORMANT-EXTENDED
@@ -102,6 +102,12 @@
[BR-54]-Each Item attribute (BG-32) shall contain an Item attribute name (BT-160) and an Item attribute value (BT-161).
+
+
+
+ [BR-FXEXT-04]-To ensure automated processing of the article attributes without bilateral reconciliation, only values from the code list UNTDED 6313+Factur-X-Extension should be used.
+
+
@@ -138,7 +144,7 @@
[BR-65]-The Item classification identifier (BT-158) shall have a Scheme identifier.
[BR-CO-04]-Each Invoice line (BG-25) shall be categorized with an Invoiced item VAT category code (BT-151).
-
+
[BR-DEC-23]-The allowed maximum number of decimals for the Invoice line net amount (BT-131) is 2.
@@ -272,7 +278,7 @@
[BR-AG-03]-An Invoice that contains a Document level allowance (BG-20) where the Document level allowance VAT category code (BT-95) is "IPSI" shall contain the Seller VAT Identifier (BT-31), the Seller Tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63).
-
+
[BR-AG-06]-In a Document level allowance (BG-20) where the Document level allowance VAT category code (BT-95) is "IPSI" the Document level allowance VAT rate (BT-96) shall be 0 (zero) or greater than zero.
@@ -342,7 +348,7 @@
[BR-AG-04]-An Invoice that contains a Document level charge (BG-21) where the Document level charge VAT category code (BT-102) is "IPSI" shall contain the Seller VAT Identifier (BT-31), the Seller Tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63).
-
+
[BR-AG-07]-In a Document level charge (BG-21) where the Document level charge VAT category code (BT-102) is "IPSI" the Document level charge VAT rate (BT-103) shall be 0 (zero) or greater than zero.
@@ -380,9 +386,9 @@
[BR-14]-An Invoice shall have the Invoice total amount with VAT (BT-112).
[BR-15]-An Invoice shall have the Amount due for payment (BT-115).
-
+
[BR-FXEXT-CO-11]-Absolute Value of (Sum of allowances on document level (BT-107) - Σ Document level allowance amounts (BT-92))<= 0,01 * Number of Document level allowance amounts (BT-92).
-
+
[BR-FXEXT-CO-12]-Absolute Value of (Sum of charges on document level (BT-108) - Σ Document level charge amounts (BT-99) - Σ Logistics Service fee amounts (BT-x-272))<= 0,01 * (Number of Document level charge amounts (BT-99) + Number of Logistics Service fee amounts (BT-X-272)).
[BR-FXEXT-CO-13]-Absolute Value of (Invoice total amount without VAT (BT-109) - ∑ Invoice line net amounts (BT-131) + Σ Document level allowance amounts (BT-92) - Σ Document level charge amounts (BT-99)) <= 0,01 * (Number of line net amounts (BT-131) + Number of Document level allowance amounts (BT-92) + Number of Document level charge amounts (BT-99)).
@@ -428,12 +434,16 @@
[BR-CO-27]-Either the IBAN or a Proprietary ID (BT-84) shall be used.
+
+
+
+ [BR-61]-If the Payment means type code (BT-81) means SEPA credit transfer, Local credit transfer or Non-SEPA international credit transfer, the Payment account identifier (BT-84) shall be present.
+
+
[BR-50]-A Payment account identifier (BT-84) shall be present if Credit transfer (BG-16) information is provided in the Invoice.
-
- [BR-61]-If the Payment means type code (BT-81) means SEPA credit transfer, Local credit transfer or Non-SEPA international credit transfer, the Payment account identifier (BT-84) shall be present.
@@ -560,7 +570,7 @@
[BR-AG-02]-An Invoice that contains an Invoice line (BG-25) where the Invoiced item VAT category code (BT-151) is "IPSI" shall contain the Seller VAT Identifier (BT-31), the Seller tax registration identifier (BT-32) and/or the Seller tax representative VAT identifier (BT-63).
-
+
[BR-AG-05]-In an Invoice line (BG-25) where the Invoiced item VAT category code (BT-151) is "IPSI" the Invoiced item VAT rate (BT-152) shall be 0 (zero) or greater than zero.
@@ -1131,8 +1141,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -1165,8 +1175,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -1371,8 +1381,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -1405,8 +1415,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -1548,8 +1558,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -1582,8 +1592,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -1796,8 +1806,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -1830,8 +1840,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -2036,8 +2046,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -2070,8 +2080,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -2278,8 +2288,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -2312,8 +2322,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -2462,8 +2472,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -2496,8 +2506,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -2849,6 +2859,13 @@
Element 'ram:ModeCode' must occur exactly 1 times.
+
+
+
+
+ Value of 'ram:ModeCode' is not allowed.
+
+
@@ -2938,8 +2955,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -2972,8 +2989,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -3115,8 +3132,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -3149,8 +3166,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -3292,8 +3309,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -3326,8 +3343,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -3435,8 +3452,8 @@
-
-
+
+
Value of 'ram:DueDateTypeCode' is not allowed.
@@ -3473,8 +3490,8 @@
-
-
+
+
Value of '@format' is not allowed.
@@ -3531,8 +3548,8 @@
-
-
+
+
Value of 'ram:InvoiceCurrencyCode' is not allowed.
@@ -3589,8 +3606,8 @@
-
-
+
+
Value of 'ram:TypeCode' is not allowed.
@@ -3691,8 +3708,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -3725,8 +3742,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -3870,8 +3887,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -3904,8 +3921,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -4049,8 +4066,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -4083,8 +4100,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -4228,8 +4245,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -4262,8 +4279,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -4324,8 +4341,8 @@
-
-
+
+
Value of 'ram:TypeCode' is not allowed.
@@ -4480,8 +4497,8 @@
-
-
+
+
Value of 'ram:TypeCode' is not allowed.
@@ -4692,8 +4709,8 @@
-
-
+
+
Value of 'ram:ReasonCode' is not allowed.
@@ -4798,8 +4815,8 @@
-
-
+
+
Value of 'ram:ReasonCode' is not allowed.
@@ -4987,8 +5004,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -5021,8 +5038,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -5149,8 +5166,8 @@
-
-
+
+
Value of '@currencyID' is not allowed.
@@ -5162,8 +5179,8 @@
-
-
+
+
Value of '@currencyID' is not allowed.
@@ -5239,8 +5256,8 @@
-
-
+
+
Value of 'ram:TypeCode' is not allowed.
@@ -5259,22 +5276,22 @@
-
-
+
+
Value of 'ram:SourceCurrencyCode' is not allowed.
-
-
+
+
Value of 'ram:TargetCurrencyCode' is not allowed.
-
-
+
+
Value of 'ram:TaxCurrencyCode' is not allowed.
@@ -6273,8 +6290,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -6435,8 +6452,8 @@
-
-
+
+
Value of 'ram:CountryID' is not allowed.
@@ -6915,13 +6932,6 @@
Element 'ram:Value' must occur exactly 1 times.
-
-
-
-
- Value of 'ram:TypeCode' is not allowed.
-
-
@@ -6960,8 +6970,8 @@
-
-
+
+
Value of '@listID' is not allowed.
@@ -7010,6 +7020,13 @@
Attribute '@schemeID' is required in this context.
+
+
+
+
+ Value of '@schemeID' is not allowed.
+
+
@@ -7073,8 +7090,8 @@
-
-
+
+
Value of 'ram:ID' is not allowed.
diff --git a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_EXTENDED_codedb.xml b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_EXTENDED_codedb.xml
similarity index 95%
rename from validator/src/main/resources/schematron/ZF_230/FACTUR-X_EXTENDED_codedb.xml
rename to validator/src/main/resources/schematron/ZF_232/FACTUR-X_EXTENDED_codedb.xml
index c1e94944..62d10ca4 100644
--- a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_EXTENDED_codedb.xml
+++ b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_EXTENDED_codedb.xml
@@ -2,6 +2,7 @@
+
@@ -818,302 +819,16 @@
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1299,7 +1014,7 @@
-
+
@@ -1552,6 +1267,241 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4804,6 +4754,8 @@
+
+
@@ -4819,6 +4771,7 @@
+
@@ -5058,6 +5011,14 @@
+
+
+
+
+
+
+
+
@@ -5285,6 +5246,14 @@
+
+
+
+
+
+
+
+
@@ -5302,6 +5271,7 @@
+
@@ -5333,6 +5303,7 @@
+
@@ -5728,6 +5699,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -5789,7 +5772,6 @@
-
@@ -5882,6 +5864,7 @@
+
@@ -5906,9 +5889,10 @@
+
-
+
@@ -5994,15 +5978,15 @@
-
+
-
+
-
+
@@ -6023,7 +6007,7 @@
-
+
@@ -6203,187 +6187,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -6446,7 +6249,6 @@
-
@@ -6539,6 +6341,7 @@
+
@@ -6563,9 +6366,192 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -6622,7 +6608,7 @@
-
+
@@ -6631,7 +6617,7 @@
-
+
diff --git a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_MINIMUM.sch b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_MINIMUM.sch
similarity index 99%
rename from validator/src/main/resources/schematron/ZF_230/FACTUR-X_MINIMUM.sch
rename to validator/src/main/resources/schematron/ZF_232/FACTUR-X_MINIMUM.sch
index 82fde99f..dd86da5b 100644
--- a/validator/src/main/resources/schematron/ZF_230/FACTUR-X_MINIMUM.sch
+++ b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_MINIMUM.sch
@@ -1,5 +1,5 @@
- Schema for Factur-X; 1.0.07; Accounting, MINIMUM
+ Schema for Factur-X; 1.07.2; Accounting, MINIMUM
diff --git a/validator/src/main/resources/xslt/ZF_230/FACTUR-X_MINIMUM_codedb.xml b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_MINIMUM_codedb.xml
similarity index 98%
rename from validator/src/main/resources/xslt/ZF_230/FACTUR-X_MINIMUM_codedb.xml
rename to validator/src/main/resources/schematron/ZF_232/FACTUR-X_MINIMUM_codedb.xml
index 74a7b49c..c07e49f4 100644
--- a/validator/src/main/resources/xslt/ZF_230/FACTUR-X_MINIMUM_codedb.xml
+++ b/validator/src/main/resources/schematron/ZF_232/FACTUR-X_MINIMUM_codedb.xml
@@ -2,6 +2,7 @@
+
@@ -289,6 +290,14 @@
+
+
+
+
+
+
+
+
@@ -605,7 +614,6 @@
-
@@ -698,6 +706,7 @@
+
@@ -722,6 +731,7 @@
+
@@ -786,7 +796,6 @@
-
@@ -879,6 +888,7 @@
+
@@ -903,6 +913,7 @@
+
diff --git a/validator/src/main/resources/xslt/XR_22/XRechnung-CII-validation.xslt b/validator/src/main/resources/xslt/XR_22/XRechnung-CII-validation.xslt
index 58c2e721..a9d2063b 100644
--- a/validator/src/main/resources/xslt/XR_22/XRechnung-CII-validation.xslt
+++ b/validator/src/main/resources/xslt/XR_22/XRechnung-CII-validation.xslt
@@ -211,7 +211,7 @@
-
+
@@ -344,7 +344,7 @@
-
+
@@ -365,7 +365,7 @@
-
+
@@ -386,7 +386,7 @@
-
+
@@ -422,7 +422,7 @@
-
+
@@ -503,7 +503,7 @@
-
+
@@ -539,7 +539,7 @@
-
+
@@ -575,7 +575,7 @@
-
+
@@ -626,7 +626,7 @@
-
+
@@ -662,7 +662,7 @@
-
+
@@ -713,7 +713,7 @@
-
+
@@ -734,11 +734,11 @@
-
+
-
+
@@ -764,7 +764,7 @@
-
+
@@ -787,7 +787,7 @@
-
+
@@ -810,7 +810,7 @@
-
+
@@ -833,7 +833,7 @@
-
+
@@ -856,10 +856,10 @@
-
+
-
+
diff --git a/validator/src/main/resources/xslt/XR_23/XRechnung-CII-validation.xslt b/validator/src/main/resources/xslt/XR_23/XRechnung-CII-validation.xslt
index 9732db99..4306177e 100644
--- a/validator/src/main/resources/xslt/XR_23/XRechnung-CII-validation.xslt
+++ b/validator/src/main/resources/xslt/XR_23/XRechnung-CII-validation.xslt
@@ -214,7 +214,7 @@
-
+
@@ -396,7 +396,7 @@
-
+
@@ -417,7 +417,7 @@
-
+
@@ -438,7 +438,7 @@
-
+
@@ -474,7 +474,7 @@
-
+
@@ -555,7 +555,7 @@
-
+
@@ -591,7 +591,7 @@
-
+
@@ -627,7 +627,7 @@
-
+
@@ -678,7 +678,7 @@
-
+
@@ -714,7 +714,7 @@
-
+
@@ -765,7 +765,7 @@
-
+
@@ -786,11 +786,11 @@
-
+
-
+
@@ -816,7 +816,7 @@
-
+
@@ -839,7 +839,7 @@
-
+
@@ -862,7 +862,7 @@
-
+
@@ -885,7 +885,7 @@
-
+
@@ -908,10 +908,10 @@
-
+
-
+
diff --git a/validator/src/main/resources/xslt/ZF_230/FACTUR-X_BASIC-WL.xslt b/validator/src/main/resources/xslt/ZF_232/FACTUR-X_BASIC-WL.xslt
similarity index 97%
rename from validator/src/main/resources/xslt/ZF_230/FACTUR-X_BASIC-WL.xslt
rename to validator/src/main/resources/xslt/ZF_232/FACTUR-X_BASIC-WL.xslt
index 931cc737..36484a84 100644
--- a/validator/src/main/resources/xslt/ZF_230/FACTUR-X_BASIC-WL.xslt
+++ b/validator/src/main/resources/xslt/ZF_232/FACTUR-X_BASIC-WL.xslt
@@ -153,7 +153,7 @@
-
+
@@ -1522,11 +1522,18 @@
+
+
+
+
+
+
+
-Schema for Factur-X; 1.0.07; Accounting, BASIC without Lines
+Schema for Factur-X; 1.07.2; Accounting, BASIC without Lines
@@ -2450,9 +2457,9 @@
-
+
-
+
FX-SCH-A-000092
@@ -2837,9 +2844,9 @@
-
+
-
+
FX-SCH-A-000110
@@ -3373,23 +3380,8 @@
-
-
-
-
-
-
-
-
- FX-SCH-A-000133
-
-
-
-
- [BR-50]-A Payment account identifier (BT-84) shall be present if Credit transfer (BG-16) information is provided in the Invoice.
-
-
-
+
+
@@ -3416,7 +3408,35 @@
-
+
+
+
+
+
+
+
+
+ FX-SCH-A-000133
+
+
+
+
+ [BR-50]-A Payment account identifier (BT-84) shall be present if Credit transfer (BG-16) information is provided in the Invoice.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3433,18 +3453,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -3476,18 +3496,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -3519,18 +3539,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -3562,18 +3582,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -3635,18 +3655,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -3678,18 +3698,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -3721,18 +3741,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -3809,18 +3829,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4032,18 +4052,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4075,18 +4095,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4099,18 +4119,18 @@
Attribute @schemeID' marked as not used in the given context.
-
+
-
-
-
+
+
+
-
+
@@ -4142,18 +4162,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4171,18 +4191,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4199,18 +4219,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4228,18 +4248,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4257,18 +4277,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4300,18 +4320,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4328,18 +4348,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4352,18 +4372,18 @@
Attribute @schemeID' marked as not used in the given context.
-
+
-
-
-
+
+
+
-
+
@@ -4380,18 +4400,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4409,18 +4429,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4433,18 +4453,18 @@
Attribute @schemeID' marked as not used in the given context.
-
+
-
-
-
+
+
+
-
+
@@ -4476,18 +4496,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4504,30 +4524,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Element 'ram:FormattedIssueDateTime' is marked as not used in the given context.
-
-
@@ -4539,8 +4535,8 @@
-
-
+
+
@@ -4549,7 +4545,7 @@
- Attribute @schemeID' marked as not used in the given context.
+ Element 'ram:FormattedIssueDateTime' is marked as not used in the given context.
@@ -4563,7 +4559,31 @@
-
+
+
+
+
+
+
+
+
+
+
+ Attribute @schemeID' marked as not used in the given context.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4655,18 +4675,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4683,18 +4703,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4712,18 +4732,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4736,18 +4756,18 @@
Attribute @schemeID' marked as not used in the given context.
-
+
-
-
-
+
+
+
-
+
@@ -4779,18 +4799,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4808,18 +4828,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4837,18 +4857,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4861,18 +4881,18 @@
Element 'ram:TradingBusinessName' is marked as not used in the given context.
-
+
-
-
-
+
+
+
-
+
@@ -4889,18 +4909,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4917,18 +4937,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4946,18 +4966,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -4974,18 +4994,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5002,18 +5022,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5031,18 +5051,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5059,30 +5079,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Element 'ram:FormattedIssueDateTime' is marked as not used in the given context.
-
-
@@ -5094,8 +5090,8 @@
-
-
+
+
@@ -5104,7 +5100,7 @@
- Attribute @schemeID' marked as not used in the given context.
+ Element 'ram:FormattedIssueDateTime' is marked as not used in the given context.
@@ -5118,7 +5114,31 @@
-
+
+
+
+
+
+
+
+
+
+
+ Attribute @schemeID' marked as not used in the given context.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -5165,30 +5185,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Element 'ram:GlobalID' is marked as not used in the given context.
-
-
@@ -5200,8 +5196,8 @@
-
-
+
+
@@ -5210,7 +5206,7 @@
- Element 'ram:ID' is marked as not used in the given context.
+ Element 'ram:GlobalID' is marked as not used in the given context.
@@ -5224,7 +5220,31 @@
-
+
+
+
+
+
+
+
+
+
+
+ Element 'ram:ID' is marked as not used in the given context.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -5256,18 +5276,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5285,18 +5305,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5309,18 +5329,18 @@
Element 'ram:SpecifiedLegalOrganization' is marked as not used in the given context.
-
+
-
-
-
+
+
+
-
+
@@ -5337,18 +5357,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5365,18 +5385,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5394,18 +5414,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5418,18 +5438,18 @@
Element 'ram:URIUniversalCommunication' is marked as not used in the given context.
-
+
-
-
-
+
+
+
-
+
@@ -5506,18 +5526,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5534,18 +5554,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5563,18 +5583,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5587,18 +5607,18 @@
Attribute @schemeID' marked as not used in the given context.
-
+
-
-
-
+
+
+
-
+
@@ -5630,18 +5650,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5659,18 +5679,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5688,18 +5708,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5712,18 +5732,18 @@
Element variant 'ram:SpecifiedTaxRegistration[ not(ram:ID/@schemeID="VA") and not(ram:ID/@schemeID="FC")]' is marked as not used in the given context.
-
+
-
-
-
+
+
+
-
+
@@ -5740,18 +5760,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5768,18 +5788,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5796,18 +5816,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5824,18 +5844,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5852,18 +5872,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5880,18 +5900,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5909,18 +5929,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5937,18 +5957,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5965,18 +5985,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -5993,18 +6013,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6022,18 +6042,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6050,30 +6070,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Element 'ram:FormattedIssueDateTime' is marked as not used in the given context.
-
-
@@ -6085,8 +6081,8 @@
-
-
+
+
@@ -6095,7 +6091,7 @@
- Attribute @schemeID' marked as not used in the given context.
+ Element 'ram:FormattedIssueDateTime' is marked as not used in the given context.
@@ -6109,7 +6105,31 @@
-
+
+
+
+
+
+
+
+
+
+
+ Attribute @schemeID' marked as not used in the given context.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -6141,18 +6161,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6169,18 +6189,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6198,18 +6218,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6222,18 +6242,18 @@
Attribute @schemeID' marked as not used in the given context.
-
+
-
-
-
+
+
+
-
+
@@ -6265,18 +6285,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6294,30 +6314,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Element 'ram:SpecifiedLegalOrganization' is marked as not used in the given context.
-
-
@@ -6329,8 +6325,8 @@
-
-
+
+
@@ -6339,7 +6335,7 @@
- Element 'ram:SpecifiedTaxRegistration' is marked as not used in the given context.
+ Element 'ram:SpecifiedLegalOrganization' is marked as not used in the given context.
@@ -6353,8 +6349,8 @@
-
-
+
+
@@ -6363,7 +6359,7 @@
- Element 'ram:URIUniversalCommunication' is marked as not used in the given context.
+ Element 'ram:SpecifiedTaxRegistration' is marked as not used in the given context.
@@ -6377,7 +6373,31 @@
-
+
+
+
+
+
+
+
+
+
+
+ Element 'ram:URIUniversalCommunication' is marked as not used in the given context.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -6469,18 +6489,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6542,30 +6562,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Attribute @currencyID' marked as not used in the given context.
-
-
@@ -6577,8 +6573,8 @@
-
-
+
+
@@ -6601,7 +6597,31 @@
-
+
+
+
+
+
+
+
+
+
+
+ Attribute @currencyID' marked as not used in the given context.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -6619,18 +6639,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6648,18 +6668,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6677,18 +6697,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6706,18 +6726,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6734,18 +6754,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6763,18 +6783,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6791,18 +6811,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6820,18 +6840,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6844,18 +6864,18 @@
Attribute @schemeID' marked as not used in the given context.
-
+
-
-
-
+
+
+
-
+
@@ -6873,18 +6893,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6916,18 +6936,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6944,18 +6964,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6973,18 +6993,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -6997,18 +7017,18 @@
Attribute @schemeID' marked as not used in the given context.
-
+
-
-
-
+
+
+
-
+
@@ -7055,18 +7075,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -7083,18 +7103,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -7112,30 +7132,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Attribute @schemeID' marked as not used in the given context.
-
-
@@ -7147,8 +7143,8 @@
-
-
+
+
@@ -7157,7 +7153,7 @@
- Element 'ram:PostalTradeAddress' is marked as not used in the given context.
+ Attribute @schemeID' marked as not used in the given context.
@@ -7171,7 +7167,31 @@
-
+
+
+
+
+
+
+
+
+
+
+ Element 'ram:PostalTradeAddress' is marked as not used in the given context.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -7189,30 +7209,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Element 'ram:TradingBusinessName' is marked as not used in the given context.
-
-
@@ -7224,8 +7220,8 @@
-
-
+
+
@@ -7234,7 +7230,7 @@
- Element 'ram:SpecifiedTaxRegistration' is marked as not used in the given context.
+ Element 'ram:TradingBusinessName' is marked as not used in the given context.
@@ -7248,8 +7244,8 @@
-
-
+
+
@@ -7258,7 +7254,7 @@
- Element 'ram:URIUniversalCommunication' is marked as not used in the given context.
+ Element 'ram:SpecifiedTaxRegistration' is marked as not used in the given context.
@@ -7272,8 +7268,8 @@
-
-
+
+
@@ -7282,7 +7278,7 @@
- Attribute @schemeID' marked as not used in the given context.
+ Element 'ram:URIUniversalCommunication' is marked as not used in the given context.
@@ -7296,8 +7292,8 @@
-
-
+
+
@@ -7306,7 +7302,7 @@
- Element variant 'ram:SpecifiedTradeAllowanceCharge[ not(ram:ChargeIndicator/udt:Indicator="false") and not(ram:ChargeIndicator/udt:Indicator="true")]' is marked as not used in the given context.
+ Attribute @schemeID' marked as not used in the given context.
@@ -7320,7 +7316,31 @@
-
+
+
+
+
+
+
+
+
+
+
+ Element variant 'ram:SpecifiedTradeAllowanceCharge[ not(ram:ChargeIndicator/udt:Indicator="false") and not(ram:ChargeIndicator/udt:Indicator="true")]' is marked as not used in the given context.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -7367,30 +7387,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Attribute @currencyID' marked as not used in the given context.
-
-
@@ -7402,8 +7398,8 @@
-
-
+
+
@@ -7426,7 +7422,31 @@
-
+
+
+
+
+
+
+
+
+
+
+ Attribute @currencyID' marked as not used in the given context.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -7458,30 +7478,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Element 'ram:BasisAmount' is marked as not used in the given context.
-
-
@@ -7493,8 +7489,8 @@
-
-
+
+
@@ -7503,7 +7499,7 @@
- Element 'ram:CalculatedAmount' is marked as not used in the given context.
+ Element 'ram:BasisAmount' is marked as not used in the given context.
@@ -7517,7 +7513,31 @@
-
+
+
+
+
+
+
+
+
+
+
+ Element 'ram:CalculatedAmount' is marked as not used in the given context.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -7535,30 +7555,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Element 'ram:DueDateTypeCode' is marked as not used in the given context.
-
-
@@ -7570,8 +7566,8 @@
-
-
+
+
@@ -7580,7 +7576,7 @@
- Element 'ram:ExemptionReason' is marked as not used in the given context.
+ Element 'ram:DueDateTypeCode' is marked as not used in the given context.
@@ -7594,8 +7590,8 @@
-
-
+
+
@@ -7604,7 +7600,7 @@
- Element 'ram:ExemptionReasonCode' is marked as not used in the given context.
+ Element 'ram:ExemptionReason' is marked as not used in the given context.
@@ -7618,7 +7614,31 @@
-
+
+
+
+
+
+
+
+
+
+
+ Element 'ram:ExemptionReasonCode' is marked as not used in the given context.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -7636,18 +7656,18 @@
-
+
-
-
-
+
+
+
-
+
@@ -7665,18 +7685,18 @@
-
+
-
-
-
+
+
+
-
+