Merge branch 'master' into InvoiceeInvoicer

This commit is contained in:
Frank Langelage
2025-11-01 15:29:54 +01:00
committed by GitHub
23 changed files with 869 additions and 28 deletions

View File

@@ -1,3 +1,14 @@
2.20.0
=======
2025-10-30
- upgrade to pdfbox 3.0.6
- #950 issues with nonshaded version: 2.19.1: ClassNotFoudException while running the PDFValidator
- #959 Added FactoorSharp to the list of valid pdf sources
- change return type of getCashDiscounts to CashDiscount object, not interface
- #923 Support for BT-17 (tender or lot reference)
- #960 incorrect calculation for product charges
2.19.1
=======
2025-10-09

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>org.mustangproject</groupId>
<artifactId>core</artifactId>
<version>2.19.2-SNAPSHOT</version>
<version>2.20.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Mustang-CLI</artifactId>
@@ -166,6 +166,7 @@
</includes>
</filter>
</filters>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>

View File

@@ -34,7 +34,7 @@ If you set up a Maven project, you can reference the mustang artifact like this:
<dependency>
<groupId>org.mustangproject</groupId>
<artifactId>validator</artifactId>
<version>2.17.0</version>
<version>2.20.0</version>
<classifier>shaded</classifier>
</dependency>
```

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>org.mustangproject</groupId>
<artifactId>core</artifactId>
<version>2.19.2-SNAPSHOT</version>
<version>2.20.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -274,6 +274,7 @@
</excludes>
</filter>
</filters>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>

View File

@@ -54,6 +54,7 @@ public class Invoice implements IExportableTransaction {
protected BigDecimal totalPrepaidAmount = null;
protected Date detailedDeliveryDateStart = null;
protected Date detailedDeliveryPeriodEnd = null;
protected IReferencedDocument tenderReference = null;
protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<>(),
Charges = new ArrayList<>(), LogisticsServiceCharges = new ArrayList<>();
@@ -135,8 +136,8 @@ public class Invoice implements IExportableTransaction {
}
@Override
public IZUGFeRDCashDiscount[] getCashDiscounts() {
return cashDiscounts.toArray(new IZUGFeRDCashDiscount[0]);
public CashDiscount[] getCashDiscounts() {
return cashDiscounts.toArray(new CashDiscount[0]);
}
@Override
@@ -144,6 +145,35 @@ public class Invoice implements IExportableTransaction {
return number;
}
@Override
/***
* BT-17
*/
public IReferencedDocument getTenderReferencedDocument() {
return tenderReference;
}
/***
* BT-17
* @param dr
* @return
*/
public Invoice setTenderReferencedDocument(ReferencedDocument dr) {
dr.setTypeCode("50");//50 is fixed for tender documents
tenderReference=dr;
return this;
}
public Invoice setTenderReferencedDocument(String ID) {
ReferencedDocument dr=new ReferencedDocument(ID);
setTenderReferencedDocument(dr);
return this;
}
public Invoice setNumber(String number) {
this.number = number;
return this;

View File

@@ -3,10 +3,7 @@ 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.IReferencedDocument;
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem;
import org.mustangproject.ZUGFeRD.LineCalculator;
import org.mustangproject.ZUGFeRD.*;
import org.mustangproject.util.NodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -90,6 +87,9 @@ public class Item implements IZUGFeRDExportableItem {
icnm.getAsNodeMap("ClassifiedTaxCategory")
.flatMap(m -> m.getAsBigDecimal("Percent"))
.ifPresent(product::setVATPercent);
});
itemMap.getAsNodeMap("AssociatedDocumentLineDocument")
.flatMap(icnm -> icnm.getAsString("LineID"))
@@ -132,6 +132,7 @@ public class Item implements IZUGFeRDExportableItem {
}
}
itemMap.getAsNodeMap("SpecifiedLineTradeAgreement", "SpecifiedSupplyChainTradeAgreement").ifPresent(icnm -> {
icnm.getAsNodeMap("BuyerOrderReferencedDocument")
.flatMap(bordNodes -> bordNodes.getAsString("LineID"))
@@ -622,6 +623,7 @@ public class Item implements IZUGFeRDExportableItem {
return detailedDeliveryPeriodTo;
}
public IZUGFeRDExportableItem addNotes(Collection<IncludedNote> notes) {
if (notes == null) {
return this;

View File

@@ -2,6 +2,7 @@ package org.mustangproject;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.util.Date;
import org.mustangproject.ZUGFeRD.IReferencedDocument;
@@ -17,6 +18,10 @@ public class ReferencedDocument implements IReferencedDocument {
String referenceTypeCode;
Date formattedIssueDateTime;
public ReferencedDocument() {
//bean
}
public ReferencedDocument(String issuerAssignedID, String typeCode, String referenceTypeCode) {
this(issuerAssignedID);
this.typeCode = typeCode;
@@ -51,6 +56,7 @@ public class ReferencedDocument implements IReferencedDocument {
/**
* which type is the document? e.g. "916" for additional invoice related
*
* @param typeCode as String, e.g. 916
*/
public void setTypeCode(String typeCode) {
@@ -59,6 +65,7 @@ public class ReferencedDocument implements IReferencedDocument {
/**
* type of the reference of this line, a UNTDID 1153 code
*
* @param referenceTypeCode three uppercase character reference type code as string
*/
public void setReferenceTypeCode(String referenceTypeCode) {
@@ -90,8 +97,7 @@ public class ReferencedDocument implements IReferencedDocument {
}
@Override
public Date getFormattedIssueDateTime()
{
public Date getFormattedIssueDateTime() {
return formattedIssueDateTime;
}
@@ -100,9 +106,20 @@ public class ReferencedDocument implements IReferencedDocument {
return null;
}
NodeMap nodes = new NodeMap(node);
return new ReferencedDocument(nodes.getAsStringOrNull("IssuerAssignedID", "ID"),
ReferencedDocument rd = new ReferencedDocument(nodes.getAsStringOrNull("IssuerAssignedID", "ID"),
nodes.getAsStringOrNull("TypeCode", "DocumentTypeCode"),
nodes.getAsStringOrNull("ReferenceTypeCode"),
XMLTools.tryDate(nodes.getAsStringOrNull("FormattedIssueDateTime")));
if (nodes.getAsStringOrNull("ID") != null) {
//sure sign for UBL: here ReferenceTypeCode is no element but a "schemeID" attribute to ID
Node idNode = nodes.getNode("ID").get();
if (idNode != null) {
Node schemeIDAttr = idNode.getAttributes().getNamedItem("schemeID");
if (schemeIDAttr != null) {
rd.setReferenceTypeCode(schemeIDAttr.getNodeValue());
}
}
}
return rd;
}
}

View File

@@ -215,6 +215,15 @@ public interface IExportableTransaction {
return null;
}
/**
* BT-17 tender or lot reference
*
* @return mandatory ID, optional Date
*/
default IReferencedDocument getTenderReferencedDocument() {
return null;
}
/**
* own name
*

View File

@@ -157,11 +157,11 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
/***
* specifies the item level delivery period (there is also one on document level),
* this will be included in a BillingSpecifiedPeriod element
* @return the beginning of the delivery period
*/
/***
* specifies the item level delivery period (there is also one on document level),
* this will be included in a BillingSpecifiedPeriod element
* @return the beginning of the delivery period
*/
default Date getDetailedDeliveryPeriodFrom() {
return null;
}

View File

@@ -73,7 +73,7 @@ public class LineCalculator {
}
if (currentItem.getProduct().getCharges()!=null) {
for (IZUGFeRDAllowanceCharge ccaf : currentItem.getProduct().getCharges()) {
delta = delta.subtract(ccaf.getTotalAmount(currentItem));
delta = delta.add(ccaf.getTotalAmount(currentItem));
}
}
}

View File

@@ -631,6 +631,18 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
}
}
if(trans.getTenderReferencedDocument() != null){
xml += "<ram:AdditionalReferencedDocument>"
+ "<ram:IssuerAssignedID>" + XMLTools.encodeXML(trans.getTenderReferencedDocument().getIssuerAssignedID()) + "</ram:IssuerAssignedID>"
+ "<ram:TypeCode>" + 50 + "</ram:TypeCode>";
if (trans.getTenderReferencedDocument().getFormattedIssueDateTime()!=null) {
final SimpleDateFormat dateFormat102 = new SimpleDateFormat("yyyyMMdd");
xml += "<ram:FormattedIssueDateTime><qdt:DateTimeString format=\"102\">"+XMLTools.encodeXML(dateFormat102.format(trans.getTenderReferencedDocument().getFormattedIssueDateTime()))+"</qdt:DateTimeString></ram:FormattedIssueDateTime>";
}
xml += "</ram:AdditionalReferencedDocument>";
}
if (trans.getSpecifiedProcuringProjectID() != null) {
xml += "<ram:SpecifiedProcuringProject>"
+ "<ram:ID>" + XMLTools.encodeXML(trans.getSpecifiedProcuringProjectID()) + "</ram:ID>";

View File

@@ -696,6 +696,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
if ((meta != null) && (meta.getLength() > 0)) {
try {
DomXmpParser xmpParser = new DomXmpParser();
xmpParser.setStrictParsing(false);
return xmpParser.parse(meta.toByteArray());
} catch (XmpParsingException e) {
throw new IOException(e);

View File

@@ -111,6 +111,7 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter {
if (metadata != null) {
try {
DomXmpParser xmpParser = new DomXmpParser();
xmpParser.setStrictParsing(false);
XMPMetadata xmp = xmpParser.parse(metadata.createInputStream());
PDFAIdentificationSchema pdfaSchema = xmp.getPDFAIdentificationSchema();

View File

@@ -612,6 +612,18 @@ public class ZUGFeRDInvoiceImporter {
if (!issueDateStr.isEmpty()) {
issueDate = parseDate(issueDateStr, "yyyy-MM-dd");
}
String tenderReference = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"OriginatorDocumentReference\"]/*[local-name()=\"ID\"]").trim();
String tenderReferenceDate = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"OriginatorDocumentReference\"]/*[local-name()=\"ID\"]").trim();
if((tenderReference != null)&&(!tenderReference.isEmpty())){
if((tenderReferenceDate != null)&&(!tenderReferenceDate.isEmpty())){
zpp.setTenderReferencedDocument(new ReferencedDocument(tenderReference, parseDate(tenderReferenceDate, "yyyy-MM-dd")));
} else {
zpp.setTenderReferencedDocument(tenderReference);
}
}
String dueDt = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"DueDate\"]").trim();
if (!dueDt.isEmpty()) {
dueDate = parseDate(dueDt, "yyyy-MM-dd");
@@ -677,6 +689,9 @@ public class ZUGFeRDInvoiceImporter {
NodeList headerTradeAgreementNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
String buyerOrderIssuerAssignedID = null;
String sellerOrderIssuerAssignedID = null;
String additionalReferencedDocument = null;
Date additionalReferencedDocumentDate = null;
for (int i = 0; i < headerTradeAgreementNodes.getLength(); i++) {
// XMLTools.trimOrNull(nodes.item(i)))) {
Node headerTradeAgreementNode = headerTradeAgreementNodes.item(i);
@@ -702,12 +717,55 @@ public class ZUGFeRDInvoiceImporter {
}
}
}
int typeC = 0;
additionalReferencedDocument=null;
additionalReferencedDocumentDate=null;
//Reading BT-17
if (headerTradeAgreementChilds.item(agreementChildIndex).getLocalName().equals("AdditionalReferencedDocument")) {
NodeList additionalChilds = headerTradeAgreementChilds.item(agreementChildIndex).getChildNodes();
for (int additionalChildIndex = 0; additionalChildIndex < additionalChilds.getLength(); additionalChildIndex++) {
if ((additionalChilds.item(additionalChildIndex).getLocalName() != null)
&& additionalChilds.item(additionalChildIndex).getLocalName().equals("TypeCode")) {
typeC = Integer.parseInt(XMLTools.trimOrNull(additionalChilds.item(additionalChildIndex)));
}
if ((additionalChilds.item(additionalChildIndex).getLocalName() != null)
&& (additionalChilds.item(additionalChildIndex).getLocalName().equals("IssuerAssignedID"))) {
additionalReferencedDocument = XMLTools.trimOrNull(additionalChilds.item(additionalChildIndex));
}
if ((additionalChilds.item(additionalChildIndex).getLocalName() != null)
&& (additionalChilds.item(additionalChildIndex).getLocalName().equals("FormattedIssueDateTime"))) {
NodeList FormattedIssueDateTimeChilds = additionalChilds.item(additionalChildIndex).getChildNodes();
for (int dateChildIndex = 0; dateChildIndex < FormattedIssueDateTimeChilds.getLength(); dateChildIndex++) {
if ((FormattedIssueDateTimeChilds.item(dateChildIndex).getLocalName() != null)
&& (FormattedIssueDateTimeChilds.item(dateChildIndex).getLocalName().equals("DateTimeString"))) {
additionalReferencedDocumentDate = XMLTools.tryDate(FormattedIssueDateTimeChilds.item(dateChildIndex));
}
}
}
}
if (typeC == 50) {
if (additionalReferencedDocument != null){
if (additionalReferencedDocumentDate!=null) {
zpp.setTenderReferencedDocument(new ReferencedDocument(additionalReferencedDocument, additionalReferencedDocumentDate));
} else {
zpp.setTenderReferencedDocument(additionalReferencedDocument);
}
}
}
}
}
}
}
String currency = extractString("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]/*[local-name()=\"InvoiceCurrencyCode\"]|//*[local-name()=\"DocumentCurrencyCode\"]");
zpp.setCurrency(currency);
@@ -950,6 +1008,7 @@ public class ZUGFeRDInvoiceImporter {
zpp.setDespatchAdviceReferencedDocumentID(s);
}
}
String invoiceReferencedDocumentID = extractString("//*[local-name()=\"InvoiceReferencedDocument\"]/*[local-name()=\"IssuerAssignedID\"]|//*[local-name()=\"BillingReference\"]/*[local-name()=\"InvoiceDocumentReference\"]/*[local-name()=\"ID\"]");
if (!invoiceReferencedDocumentID.isEmpty()) {
zpp.setInvoiceReferencedDocumentID(invoiceReferencedDocumentID);

View File

@@ -249,6 +249,54 @@ public class CalculationTest extends ResourceCase {
assertEquals(valueOf(101.85).stripTrailingZeros(), calculator.getGrandTotal().stripTrailingZeros());
}
@Test
public void testNullifyingAllowancesCharges() {
SimpleDateFormat sqlDate = new SimpleDateFormat("yyyy-MM-dd");
Invoice invoice = new Invoice();
invoice.setDocumentName("Rechnung");
invoice.setNumber("777777");
try {
invoice.setIssueDate(sqlDate.parse("2020-12-31"));
invoice.setDetailedDeliveryPeriod(sqlDate.parse("2020-12-01 - 2020-12-31".split(" - ")[0]), sqlDate.parse("2020-12-01 - 2020-12-31".split(" - ")[1]));
invoice.setDeliveryDate(sqlDate.parse("2020-12-31"));
invoice.setDueDate(sqlDate.parse("2021-01-15"));
} catch (Exception e) {
LOGGER.error("Failed to set dates", e);
}
/* trade party (sender) */
TradeParty sender = new TradeParty("Maier GmbH", "Musterweg 5", "11111", "Testung", "DE");
sender.addVATID("DE2222222222");
invoice.setSender(sender);
/* trade party (recipient) */
TradeParty recipient = new TradeParty("Teston GmbH" + " " + "Zentrale" + " " + "", "Testweg 5", "11111", "Testung", "DE");
recipient.setID("111111");
recipient.addVATID("DE111111111");
invoice.setRecipient(recipient);
/* item */
Product product;
Item item;
BigDecimal amount=new BigDecimal("10.00");
product = new Product("AAA", "", "H87", BigDecimal.ZERO).setSellerAssignedID("1AAA");
product.addCharge(new Charge(amount).setReasonCode("ZZZ").setReason("Zuschlag"));
product.addAllowance((Allowance) new Allowance(amount).setReasonCode("95").setReason("Rabatt"));
item = new Item(product, new BigDecimal("4.750"), new BigDecimal(1.00));
// set values for additional charge and discount used for next lines
item.addCharge(new Charge(amount).setReasonCode("ZZZ").setReason("Zuschlag"));
item.addAllowance((Allowance) new Allowance(amount).setReasonCode("95").setReason("Rabatt"));
invoice.addItem(item);
TransactionCalculator calculator = new TransactionCalculator(invoice);
assertEquals(valueOf(4.750).stripTrailingZeros(), calculator.getGrandTotal().stripTrailingZeros());
}
public void testSimpleItemPercentAllowance() {
/***
* a product with net 1.10 and qty 5 and relative item allowance of 10% should return 5 as line and grand total

View File

@@ -144,6 +144,38 @@ public class ZF2EdgeTest extends MustangReaderTestCase {
return "DE";
}
@Override
public IReferencedDocument getTenderReferencedDocument() {
return new IReferencedDocument() {
@Override
public String getIssuerAssignedID() {
return "983-jk-787";
}
@Override
public String getTypeCode() {
return "50";
}
@Override
public String getReferenceTypeCode() {
return "";
}
@Override
public Date getFormattedIssueDateTime() {
SimpleDateFormat sdf=new SimpleDateFormat("YYYY-mm-dd");
try {
return sdf.parse("2025-10-12");
} catch (ParseException e) {
// wont happen, I promise :-)
}
return null; // wont happen either
}
};
}
@Override
public String getOwnLocation() {
return "Stadthausen";

View File

@@ -596,6 +596,9 @@ public class ZF2PushTest extends TestCase {
try {
SchemedID gtin = new SchemedID("0160", "2001015001325");
SchemedID gln = new SchemedID("0088", "4304171000002");
ReferencedDocument dr1=new ReferencedDocument("90-kl-98798-C", sdf.parse("2025-10-12"));
ReferencedDocument dr2=new ReferencedDocument("90-kl-98798-C1", sdf.parse("2025-10-13"));
dr2.setReferenceTypeCode("AAG");
ze.setTransaction(new Invoice().setCurrency("CHF").addNote("document level 1/2").addNote("document level 2/2").setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setPaymentReference("Verwendungszweck").setDocumentName("Rechnung")
.setSellerOrderReferencedDocumentID("9384").setBuyerOrderReferencedDocumentID("28934")
.setDetailedDeliveryPeriod(new SimpleDateFormat("yyyyMMdd").parse(occurrenceFrom), new SimpleDateFormat("yyyyMMdd").parse(occurrenceTo))
@@ -604,12 +607,12 @@ public class ZF2PushTest extends TestCase {
.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"))
.setInvoicer( new TradeParty("Abweichender Rechnungssteller", "Teststr.12", "04711", "Entenhausen", "DE") )
.setInvoicee( new TradeParty("Abweichender Rechnungsempfänger", "Teststr.42", "00815", "Entenhausen", "DE") )
.addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(16)).addGlobalID(gtin).setSellerAssignedID("4711"), price, new BigDecimal(1.0)).setId("a123").addBuyerOrderReferencedDocumentID("orderId").addBuyerOrderReferencedDocumentLineID("xxx").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")))
.addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(16)).addGlobalID(gtin).setSellerAssignedID("4711"), price, new BigDecimal(1.0)).setId("a123").
addAdditionalReference(dr2).addBuyerOrderReferencedDocumentID("orderId").addBuyerOrderReferencedDocumentLineID("xxx").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))
.setTenderReferencedDocument(dr1)
.setDeliveryDate(sdf.parse("2020-11-02")).setNumber(number).setVATDueDateTypeCode(EventTimeCodeTypeConstants.PAYMENT_DATE)
.setInvoiceReferencedDocumentID("abc123").addInvoiceReferencedDocument(new ReferencedDocument("abcd1234"))
);

View File

@@ -20,6 +20,7 @@
*/
package org.mustangproject.ZUGFeRD;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
@@ -178,16 +179,79 @@ public class ZF2ZInvoiceImporterTest extends ResourceCase {
hasExceptions = true;
}
assertFalse(hasExceptions);
SimpleDateFormat sdf=new SimpleDateFormat("YYYY-MM-dd");
// Reading ZUGFeRD
assertEquals("4711", invoice.getZFItems()[0].getProduct().getSellerAssignedID());
assertEquals("9384", invoice.getSellerOrderReferencedDocumentID());
assertEquals("90-kl-98798-C", invoice.getTenderReferencedDocument().getIssuerAssignedID());
IReferencedDocument[] rd=invoice.getZFItems()[0].getAdditionalReferences();
assertEquals("90-kl-98798-C1", rd[0].getIssuerAssignedID());
assertEquals("AAG", rd[0].getReferenceTypeCode());
assertEquals("90-kl-98798-C", invoice.getTenderReferencedDocument().getIssuerAssignedID());
assertEquals("2025-10-12", sdf.format(invoice.getTenderReferencedDocument().getFormattedIssueDateTime()));
assertEquals("sender@test.org", invoice.getSender().getEmail());
assertEquals("recipient@test.org", invoice.getRecipient().getEmail());
assertEquals("28934", invoice.getBuyerOrderReferencedDocumentID());
}
public void testBT17InvoiceImport() {
boolean hasExceptions = false;
Invoice invoice = null;
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter("./target/testout-ZF2PushEdge.pdf");
try {
invoice = zii.extractInvoice();
} catch (XPathExpressionException | ParseException e) {
hasExceptions = true;
}
assertFalse(hasExceptions);
SimpleDateFormat sdf=new SimpleDateFormat("YYYY-MM-dd");
// Reading ZUGFeRD
assertEquals("90-kl-98798-C", invoice.getTenderReferencedDocument().getIssuerAssignedID());
assertNotNull(invoice.getTenderReferencedDocument().getFormattedIssueDateTime());
assertEquals("2025-10-12", sdf.format(invoice.getTenderReferencedDocument().getFormattedIssueDateTime()));
try {
zii.setInputStream(new FileInputStream(getResourceAsFile("cii/bt17-response_1760553749128.cii.xml")));
invoice = zii.extractInvoice();
} catch (XPathExpressionException | ParseException | FileNotFoundException e) {
hasExceptions = true;
}
assertFalse(hasExceptions);
// Reading ZUGFeRD
assertEquals("Testing1", invoice.getTenderReferencedDocument().getIssuerAssignedID());
}
public void testBT128InvoiceImport() {
boolean hasExceptions = false;
Invoice invoice = null;
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter();
try {
zii.setInputStream(new FileInputStream(getResourceAsFile("ubl/BT-128.ubl.xml")));
invoice = zii.extractInvoice();
} catch (XPathExpressionException | ParseException | FileNotFoundException e) {
hasExceptions = true;
}
assertFalse(hasExceptions);
SimpleDateFormat sdf=new SimpleDateFormat("YYYY-mm-dd");
// Reading ZUGFeRD
assertEquals("90-kl-98798-C1", invoice.getZFItems()[0].getAdditionalReferences()[0].getIssuerAssignedID());
assertEquals("AAG", invoice.getZFItems()[0].getAdditionalReferences()[0].getReferenceTypeCode());
}
public void testZF1Import() {
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter("./target/testout-MustangGnuaccountingBeispielRE-20171118_506zf1.pdf");

View File

@@ -0,0 +1,181 @@
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cec="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended</cbc:CustomizationID>
<cbc:ID>RE-20170509/505</cbc:ID>
<cbc:IssueDate>2017-05-09</cbc:IssueDate>
<cbc:DueDate>2022-02-28</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>USD</cbc:DocumentCurrencyCode>
<cbc:BuyerReference>AB321</cbc:BuyerReference>
<cac:DespatchDocumentReference>
<cbc:ID>123</cbc:ID>
</cac:DespatchDocumentReference>
<cac:OriginatorDocumentReference>
<cbc:ID>Testing1</cbc:ID>
</cac:OriginatorDocumentReference>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PostalAddress>
<cbc:StreetName>Ecke 12</cbc:StreetName>
<cbc:CityName>Stadthausen</cbc:CityName>
<cbc:PostalZone>12345</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>DE0815</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyTaxScheme>
<cbc:CompanyID>0815</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>FC</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Bei Spiel GmbH</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cac:PostalAddress>
<cbc:StreetName>Bahnstr. 42</cbc:StreetName>
<cbc:AdditionalStreetName>Hinterhaus</cbc:AdditionalStreetName>
<cbc:CityName>Spielkreis</cbc:CityName>
<cbc:PostalZone>88802</cbc:PostalZone>
<cac:AddressLine>
<cbc:Line>Zweiter Stock</cbc:Line>
</cac:AddressLine>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>DE999999999</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Theodor Est</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:Delivery>
<cbc:ActualDeliveryDate>2017-05-07</cbc:ActualDeliveryDate>
<cac:DeliveryLocation>
<cac:Address>
<cbc:StreetName>Bahnstr. 42</cbc:StreetName>
<cbc:AdditionalStreetName>Hinterhaus</cbc:AdditionalStreetName>
<cbc:CityName>Spielkreis</cbc:CityName>
<cbc:PostalZone>88802</cbc:PostalZone>
<cac:AddressLine>
<cbc:Line>Zweiter Stock</cbc:Line>
</cac:AddressLine>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:Address>
</cac:DeliveryLocation>
<cac:DeliveryParty>
<cac:PartyName>
<cbc:Name>Theodor Est</cbc:Name>
</cac:PartyName>
</cac:DeliveryParty>
</cac:Delivery>
<cac:PaymentMeans>
<cbc:PaymentMeansCode name="Credit Card">54</cbc:PaymentMeansCode>
</cac:PaymentMeans>
<cac:PaymentTerms>
<cbc:Note>14 Tage 2% Skonto, 30 Tage rein netto</cbc:Note>
</cac:PaymentTerms>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="USD">0</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="USD">337.6</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="USD">0</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>K</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cbc:TaxExemptionReason>Intra-community supply</cbc:TaxExemptionReason>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="USD">337.6</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="USD">337.6</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="USD">337.6</cbc:TaxInclusiveAmount>
<cbc:AllowanceTotalAmount currencyID="USD">0</cbc:AllowanceTotalAmount>
<cbc:ChargeTotalAmount currencyID="USD">0</cbc:ChargeTotalAmount>
<cbc:PrepaidAmount currencyID="USD">0</cbc:PrepaidAmount>
<cbc:PayableAmount currencyID="USD">337.6</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="HUR">1</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="USD">1.6</cbc:LineExtensionAmount>
<cac:DocumentReference>
<cbc:ID>1825</cbc:ID>
<cbc:DocumentTypeCode>130</cbc:DocumentTypeCode>
</cac:DocumentReference>
<cac:Item>
<cbc:Name>Künstlerische Gestaltung (Stunde): Einer Beispielrechnung</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>K</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="USD">160</cbc:PriceAmount>
<cbc:BaseQuantity>100</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>2</cbc:ID>
<cbc:InvoicedQuantity unitCode="C62">400</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="USD">316</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Name>Bestellerweiterung für E&amp;F Umbau</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>K</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="USD">0.79</cbc:PriceAmount>
<cbc:BaseQuantity>1</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>3</cbc:ID>
<cbc:InvoicedQuantity unitCode="LTR">200</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="USD">20</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Name>Heiße Luft pro Liter</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>K</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="USD">0.1</cbc:PriceAmount>
<cbc:BaseQuantity>1</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>
</Invoice>

View File

@@ -0,0 +1,365 @@
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cec="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
<cbc:ID>Test_EeISI_100</cbc:ID>
<cbc:IssueDate>2018-11-12</cbc:IssueDate>
<cbc:DueDate>2018-11-30</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:Note>#AAA#invoice note text</cbc:Note>
<cbc:Note>#AAA#invoice note text 2</cbc:Note>
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<cbc:TaxCurrencyCode>NOK</cbc:TaxCurrencyCode>
<cbc:AccountingCost>uvz</cbc:AccountingCost>
<cbc:BuyerReference>123</cbc:BuyerReference>
<cac:InvoicePeriod>
<cbc:StartDate>2018-11-12</cbc:StartDate>
<cbc:EndDate>2018-11-30</cbc:EndDate>
</cac:InvoicePeriod>
<cac:OrderReference>
<cbc:ID>abc</cbc:ID>
<cbc:SalesOrderID>def</cbc:SalesOrderID>
</cac:OrderReference>
<cac:BillingReference>
<cac:InvoiceDocumentReference>
<cbc:ID>abc123</cbc:ID>
<cbc:IssueDate>2018-10-04</cbc:IssueDate>
</cac:InvoiceDocumentReference>
</cac:BillingReference>
<cac:DespatchDocumentReference>
<cbc:ID>lmn</cbc:ID>
</cac:DespatchDocumentReference>
<cac:ReceiptDocumentReference>
<cbc:ID>ghi</cbc:ID>
</cac:ReceiptDocumentReference>
<cac:ContractDocumentReference>
<cbc:ID>789</cbc:ID>
</cac:ContractDocumentReference>
<cac:AdditionalDocumentReference>
<cbc:ID>Supporting document ref</cbc:ID>
<cbc:DocumentDescription>Supporting document descr</cbc:DocumentDescription>
<cac:Attachment>
<cbc:EmbeddedDocumentBinaryObject mimeCode="application/pdf" filename="filename0">ZGVmYXVsdA==</cbc:EmbeddedDocumentBinaryObject>
<cac:ExternalReference>
<cbc:URI>External document location</cbc:URI>
</cac:ExternalReference>
</cac:Attachment>
</cac:AdditionalDocumentReference>
<cac:AdditionalDocumentReference>
<cbc:ID schemeID="AAA">rst</cbc:ID>
<cbc:DocumentTypeCode>130</cbc:DocumentTypeCode>
</cac:AdditionalDocumentReference>
<cac:ProjectReference>
<cbc:ID>456</cbc:ID>
</cac:ProjectReference>
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="EM">Seller electronic address</cbc:EndpointID>
<cac:PartyIdentification>
<cbc:ID schemeID="0100">Seller identifier 1</cbc:ID>
</cac:PartyIdentification>
<cac:PartyIdentification>
<cbc:ID schemeID="0110">Seller identifier 2</cbc:ID>
</cac:PartyIdentification>
<cac:PartyName>
<cbc:Name>Seller trading name</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Seller address line 1</cbc:StreetName>
<cbc:AdditionalStreetName>Seller address line 2</cbc:AdditionalStreetName>
<cbc:CityName>Seller city</cbc:CityName>
<cbc:PostalZone>12345</cbc:PostalZone>
<cbc:CountrySubentity>Seller country subdivision</cbc:CountrySubentity>
<cac:AddressLine>
<cbc:Line>Seller address line 3</cbc:Line>
</cac:AddressLine>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>DE12345677</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyTaxScheme>
<cbc:CompanyID>DE49294093</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>FC</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Seller name</cbc:RegistrationName>
<cbc:CompanyLegalForm>Seller additional legal information</cbc:CompanyLegalForm>
</cac:PartyLegalEntity>
<cac:Contact>
<cbc:Name>Seller contact point</cbc:Name>
<cbc:Telephone>+41 345 654455</cbc:Telephone>
<cbc:ElectronicMail>seller@contact.de</cbc:ElectronicMail>
</cac:Contact>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="EM">Buyer electronic address</cbc:EndpointID>
<cac:PartyIdentification>
<cbc:ID schemeID="0190">Buyer identifier</cbc:ID>
</cac:PartyIdentification>
<cac:PartyName>
<cbc:Name>Buyer trading name</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Buyer address line 1</cbc:StreetName>
<cbc:AdditionalStreetName>Buyer address line 2</cbc:AdditionalStreetName>
<cbc:CityName>Buyer city</cbc:CityName>
<cbc:PostalZone>34562</cbc:PostalZone>
<cbc:CountrySubentity>Buyer country subdivision</cbc:CountrySubentity>
<cac:AddressLine>
<cbc:Line>Buyer address line 3</cbc:Line>
</cac:AddressLine>
<cac:Country>
<cbc:IdentificationCode>IE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>IE394838894</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Buyer name</cbc:RegistrationName>
<cbc:CompanyID schemeID="0089">Buyer legal registration identifier</cbc:CompanyID>
</cac:PartyLegalEntity>
<cac:Contact>
<cbc:Name>Buyer contact point</cbc:Name>
<cbc:Telephone>+353 2948584</cbc:Telephone>
<cbc:ElectronicMail>buyer@contact.ie</cbc:ElectronicMail>
</cac:Contact>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:PayeeParty>
<cac:PartyIdentification>
<cbc:ID schemeID="0098">Payee identifier</cbc:ID>
</cac:PartyIdentification>
<cac:PartyName>
<cbc:Name>Payee name</cbc:Name>
</cac:PartyName>
</cac:PayeeParty>
<cac:TaxRepresentativeParty>
<cac:PartyName>
<cbc:Name>Tax representative name</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Tax representative address line 1</cbc:StreetName>
<cbc:AdditionalStreetName>Tax representative address line 2</cbc:AdditionalStreetName>
<cbc:CityName>Tax representative city</cbc:CityName>
<cbc:PostalZone>23455</cbc:PostalZone>
<cbc:CountrySubentity>Tax representative country subdivision</cbc:CountrySubentity>
<cac:AddressLine>
<cbc:Line>Tax representative address line 3</cbc:Line>
</cac:AddressLine>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>DE3949053</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
</cac:TaxRepresentativeParty>
<cac:Delivery>
<cbc:ActualDeliveryDate>2018-12-04</cbc:ActualDeliveryDate>
<cac:DeliveryLocation>
<cbc:ID schemeID="0045">deliver location identifier</cbc:ID>
<cac:Address>
<cbc:StreetName>Deliver to address line 1</cbc:StreetName>
<cbc:AdditionalStreetName>Deliver to address line 2</cbc:AdditionalStreetName>
<cbc:CityName>Deliver to city</cbc:CityName>
<cbc:PostalZone>98765</cbc:PostalZone>
<cbc:CountrySubentity>Deliver to country subdivision</cbc:CountrySubentity>
<cac:AddressLine>
<cbc:Line>Deliver to address line 3</cbc:Line>
</cac:AddressLine>
<cac:Country>
<cbc:IdentificationCode>IE</cbc:IdentificationCode>
</cac:Country>
</cac:Address>
</cac:DeliveryLocation>
<cac:DeliveryParty>
<cac:PartyName>
<cbc:Name>Deliver to party name</cbc:Name>
</cac:PartyName>
</cac:DeliveryParty>
</cac:Delivery>
<cac:PaymentTerms>
<cbc:Note>total amount</cbc:Note>
</cac:PaymentTerms>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>95</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Doc allowance reason text</cbc:AllowanceChargeReason>
<cbc:MultiplierFactorNumeric>1.00</cbc:MultiplierFactorNumeric>
<cbc:Amount currencyID="EUR">10</cbc:Amount>
<cbc:BaseAmount currencyID="EUR">1000</cbc:BaseAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>5</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:AllowanceCharge>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>true</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>AAA</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Doc charge reason text</cbc:AllowanceChargeReason>
<cbc:MultiplierFactorNumeric>1.00</cbc:MultiplierFactorNumeric>
<cbc:Amount currencyID="EUR">10</cbc:Amount>
<cbc:BaseAmount currencyID="EUR">1000</cbc:BaseAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>5</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:AllowanceCharge>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">50</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">1000</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">50</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>5</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">1000</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">0</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>E</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cbc:TaxExemptionReasonCode>VATEX-EU-O</cbc:TaxExemptionReasonCode>
<cbc:TaxExemptionReason>Exemtion reason text</cbc:TaxExemptionReason>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="NOK">46</cbc:TaxAmount>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="EUR">200</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="EUR">200</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="EUR">205</cbc:TaxInclusiveAmount>
<cbc:AllowanceTotalAmount currencyID="EUR">10</cbc:AllowanceTotalAmount>
<cbc:ChargeTotalAmount currencyID="EUR">10</cbc:ChargeTotalAmount>
<cbc:PrepaidAmount currencyID="EUR">0</cbc:PrepaidAmount>
<cbc:PayableAmount currencyID="EUR">205</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1a</cbc:ID>
<cbc:Note>Invoice line note</cbc:Note>
<cbc:InvoicedQuantity unitCode="EA">10</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">1000</cbc:LineExtensionAmount>
<cbc:AccountingCost>6789</cbc:AccountingCost>
<cac:InvoicePeriod>
<cbc:StartDate>2018-11-12</cbc:StartDate>
<cbc:EndDate>2018-11-30</cbc:EndDate>
</cac:InvoicePeriod>
<cac:OrderLineReference>
<cbc:LineID>12345</cbc:LineID>
</cac:OrderLineReference>
<cac:DocumentReference>
<cbc:ID schemeID="AAG">90-kl-98798-C1</cbc:ID>
<cbc:DocumentTypeCode>130</cbc:DocumentTypeCode>
</cac:DocumentReference>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>95</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Invoice line allowance reason</cbc:AllowanceChargeReason>
<cbc:MultiplierFactorNumeric>1.00</cbc:MultiplierFactorNumeric>
<cbc:Amount currencyID="EUR">10</cbc:Amount>
<cbc:BaseAmount currencyID="EUR">1000</cbc:BaseAmount>
</cac:AllowanceCharge>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>true</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>AAA</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Invoice line charge reason</cbc:AllowanceChargeReason>
<cbc:MultiplierFactorNumeric>1.00</cbc:MultiplierFactorNumeric>
<cbc:Amount currencyID="EUR">10</cbc:Amount>
<cbc:BaseAmount currencyID="EUR">1000</cbc:BaseAmount>
</cac:AllowanceCharge>
<cac:Item>
<cbc:Description>Item description</cbc:Description>
<cbc:Name>Item name</cbc:Name>
<cac:BuyersItemIdentification>
<cbc:ID>Item buyer's identifier</cbc:ID>
</cac:BuyersItemIdentification>
<cac:SellersItemIdentification>
<cbc:ID>Item seller's identifier</cbc:ID>
</cac:SellersItemIdentification>
<cac:StandardItemIdentification>
<cbc:ID schemeID="0060">Item standar identifier</cbc:ID>
</cac:StandardItemIdentification>
<cac:OriginCountry>
<cbc:IdentificationCode>IT</cbc:IdentificationCode>
</cac:OriginCountry>
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="ZZZ" listVersionID="version0">Item classification identifier0</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>5</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
<cac:AdditionalItemProperty>
<cbc:Name>Color</cbc:Name>
<cbc:Value>Red</cbc:Value>
</cac:AdditionalItemProperty>
<cac:AdditionalItemProperty>
<cbc:Name>Size</cbc:Name>
<cbc:Value>L</cbc:Value>
</cac:AdditionalItemProperty>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">10</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="EA">1</cbc:BaseQuantity>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:Amount currencyID="EUR">1</cbc:Amount>
<cbc:BaseAmount currencyID="EUR">11</cbc:BaseAmount>
</cac:AllowanceCharge>
</cac:Price>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>1b</cbc:ID>
<cbc:InvoicedQuantity unitCode="EA">10</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">1000</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Name>Item name 2</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>E</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">10</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
</Invoice>

View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.mustangproject</groupId>
<artifactId>core</artifactId>
<version>2.19.2-SNAPSHOT</version>
<version>2.20.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Mustang</name>
@@ -71,7 +71,7 @@
<version.commons-io>2.20.0</version.commons-io><!-- from 2.16.1 -->
<version.jakarta.xml.bind>4.0.2</version.jakarta.xml.bind>
<version.net.sf.saxon>12.8</version.net.sf.saxon><!-- from 12.4 -->
<version.org.apache.pdfbox>3.0.5</version.org.apache.pdfbox>
<version.org.apache.pdfbox>3.0.6</version.org.apache.pdfbox>
<version.org.apache.xmlgraphics>2.11</version.org.apache.xmlgraphics><!-- from 2.10 -->
<version.org.codehaus.janino>3.1.12</version.org.codehaus.janino><!-- from 3.1.7 -->
<version.org.dom4j>2.1.5</version.org.dom4j><!-- from 2.1.4 -->
@@ -163,11 +163,11 @@
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
<url>https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<mailingLists>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>org.mustangproject</groupId>
<artifactId>core</artifactId>
<version>2.19.2-SNAPSHOT</version>
<version>2.20.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>validator</artifactId>
@@ -185,6 +185,7 @@
</includes>
</filter>
</filters>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>

View File

@@ -283,6 +283,7 @@ public class PDFValidator extends Validator {
final byte[] cibpdfbrewerSignature = "CIB pdf brewer".getBytes(StandardCharsets.UTF_8);
final byte[] lexofficeSignature = "lexoffice".getBytes(StandardCharsets.UTF_8);
final byte[] s2IndustriesSignature = "s2industries.ZUGFeRD.PDF".getBytes(StandardCharsets.UTF_8); // https://github.com/stephanstapel/ZUGFeRD-csharp
final byte[] factoorSharpSignature = "FactoorSharp".getBytes(StandardCharsets.UTF_8); // https://github.com/S2-Industries/FactoorSharp
final byte[] sevdeskSignature = "sevdesk".getBytes(StandardCharsets.UTF_8);
if (ByteArraySearcher.contains(fileContents, symtraxSignature)) {
@@ -305,6 +306,8 @@ public class PDFValidator extends Validator {
Signature = "Lexware office";
} else if (ByteArraySearcher.contains(fileContents, s2IndustriesSignature)) {
Signature = "ZUGFeRD.PDF-csharp";
} else if (ByteArraySearcher.contains(fileContents, factoorSharpSignature)) {
Signature = "FactoorSharp";
} else if (ByteArraySearcher.contains(fileContents, sevdeskSignature)) {
Signature = "sevdesk";
}