Merge branch 'ZUGFeRD:master' into master

This commit is contained in:
Kemal Taskin
2024-12-04 15:55:13 +01:00
committed by GitHub
8 changed files with 108 additions and 82 deletions

View File

@@ -1,3 +1,10 @@
595
591
577
575
573
601
2.15.1
=======
- #566 Failed to parse PDF - Could not reproduce the invoice

View File

@@ -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());

View File

@@ -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 = "<ram:IncludedNote>";
private static final String INCLUDE_END = "</ram:IncludedNote>";
private static final String CONTENT_START = "<ram:Content>";
private static final String CONTENT_END = "</ram:Content>";
private static final String SUBJECT_CODE_START = "<ram:SubjectCode>";
private static final String SUBJECT_CODE_END = "</ram:SubjectCode>";
private static final String INCLUDE_START = "<ram:IncludedNote>";
private static final String INCLUDE_END = "</ram:IncludedNote>";
private static final String CONTENT_START = "<ram:Content>";
private static final String CONTENT_END = "</ram:Content>";
private static final String SUBJECT_CODE_START = "<ram:SubjectCode>";
private static final String SUBJECT_CODE_END = "</ram:SubjectCode>";
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;
}
}

View File

@@ -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<String, String> 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

View File

@@ -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);
}

View File

@@ -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(),

View File

@@ -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);

View File

@@ -106,7 +106,14 @@ public class NodeMap {
* @return the text content of the matching node, converted to BigDecimal
*/
public Optional<BigDecimal> 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;
}
});
}
/**