diff --git a/History.md b/History.md
index 248a960c..ccc1d053 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,10 @@
+595
+591
+577
+575
+573
+601
+
2.15.1
=======
- #566 Failed to parse PDF - Could not reproduce the invoice
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/library/src/main/java/org/mustangproject/IncludedNote.java b/library/src/main/java/org/mustangproject/IncludedNote.java
index db34e793..0bcf3133 100644
--- a/library/src/main/java/org/mustangproject/IncludedNote.java
+++ b/library/src/main/java/org/mustangproject/IncludedNote.java
@@ -9,77 +9,72 @@ import com.fasterxml.jackson.annotation.JsonInclude;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class IncludedNote {
- private String content;
+ private String content;
- private SubjectCode subjectCode;
+ private 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 = "";
+ 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 IncludedNote(String content, SubjectCode subjectCode) {
- this.content = content;
- this.subjectCode = subjectCode;
- }
+ public IncludedNote(String content, SubjectCode subjectCode) {
+ this.content = content;
+ this.subjectCode = subjectCode;
+ }
/**
* bean constructor
*/
- public IncludedNote() {
+ public IncludedNote() {
}
- public static IncludedNote generalNote(String content) {
- return new IncludedNote(content, SubjectCode.AAI);
- }
+ 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 regulatoryNote(String content) {
+ return new IncludedNote(content, SubjectCode.REG);
+ }
- public static IncludedNote legalNote(String content) {
- return new IncludedNote(content, SubjectCode.ABL);
- }
+ 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 customsNote(String content) {
+ return new IncludedNote(content, SubjectCode.CUS);
+ }
- public static IncludedNote sellerNote(String content) {
- return new IncludedNote(content, SubjectCode.SUR);
- }
+ 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 taxNote(String content) {
+ return new IncludedNote(content, SubjectCode.TXD);
+ }
- public static IncludedNote introductionNote(String content) {
- return new IncludedNote(content, SubjectCode.ACY);
- }
+ 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 discountBonusNote(String content) {
+ return new IncludedNote(content, SubjectCode.AAK);
+ }
- public static IncludedNote unspecifiedNote(String content) {
- return new IncludedNote(content, null);
- }
+ public static IncludedNote unspecifiedNote(String content) {
+ return new IncludedNote(content, null);
+ }
- public String getContent() {
- return content;
- }
+ public String getContent() {
+ return content;
+ }
- public IncludedNote setContent(String content) {
- this.content = content;
- return this;
-}
-
- public SubjectCode getSubjectCode() {
- return subjectCode;
- }
+ public SubjectCode getSubjectCode() {
+ return subjectCode;
+ }
public IncludedNote setSubjectCode(SubjectCode subjectCode) {
@@ -93,13 +88,13 @@ public class IncludedNote {
}
- 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 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/Product.java b/library/src/main/java/org/mustangproject/Product.java
index 83cf4543..cc19932d 100644
--- a/library/src/main/java/org/mustangproject/Product.java
+++ b/library/src/main/java/org/mustangproject/Product.java
@@ -23,9 +23,9 @@ 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;
@@ -61,8 +61,6 @@ public class Product implements IZUGFeRDExportableProduct {
});
-
-
nodeMap.getAsString("SellerAssignedID").ifPresent(this::setSellerAssignedID);
nodeMap.getAsString("BuyerAssignedID").ifPresent(this::setBuyerAssignedID);
nodeMap.getAsString("Name").ifPresent(this::setName);
@@ -155,7 +153,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;
}
@@ -177,7 +175,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;
}
@@ -304,18 +302,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
@@ -328,16 +330,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
diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java b/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java
index 2f997991..e319ec73 100644
--- a/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java
+++ b/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java
@@ -44,12 +44,18 @@ 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);
+
+ 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 = currentItem.getQuantity().multiply(getPrice()).divide(basisQuantity, 18, RoundingMode.HALF_UP)
+ itemTotalNetAmount = quantity.multiply(getPrice()).divide(basisQuantity, 18, RoundingMode.HALF_UP)
.subtract(allowanceItemTotal).setScale(2, RoundingMode.HALF_UP);
itemTotalVATAmount = itemTotalNetAmount.multiply(multiplicator);
}
diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java
index 0b7ca5e3..8740e157 100644
--- a/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java
+++ b/library/src/main/java/org/mustangproject/ZUGFeRD/TransactionCalculator.java
@@ -167,7 +167,11 @@ 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(),
diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java
index 8833161d..abff63bb 100644
--- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java
+++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java
@@ -558,7 +558,10 @@ public class ZUGFeRDInvoiceImporter {
// 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);
@@ -777,7 +780,7 @@ public class ZUGFeRDInvoiceImporter {
}
- 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);
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;
+ }
+
+ });
}
/**