Merge branch 'master' into POM-Cleanup

This commit is contained in:
David M
2024-09-14 14:30:39 +02:00
35 changed files with 3536 additions and 166 deletions

View File

@@ -1,14 +1,28 @@
- #420 - 461
- #441 - 463
2.13.0
=======
2024-08-28
- Item Attributes and Country of Origin missing on Product. #420
- Avoid NullPointerException if dueDate is not set. #441
- support reasoncodes #431
- Enhance Charges/Allowances with reasonCode. #432 - Enhance Charges/Allowances with reasonCode. #432
- Fix build warnings from editing and building. #415 - Fix build warnings from editing and building. #415
- ZUGFeRDVisualizer.toPDF(): generate PDF/A-3b. #400 - ZUGFeRDVisualizer.toPDF(): generate PDF/A-3b. #400
- allow access to invoice attachments via ZUGFeRDInvoiceImporter zii.getFileAttachmentsPDF() - allow access to invoice attachments via ZUGFeRDInvoiceImporter zii.getFileAttachmentsPDF()
and XML (zii.getFileAttachmentsXML) and XML (zii.getFileAttachmentsXML)
- #436 and #370. (langfr) - No interface for required field CreditorReferenceID #436 and
- X-Rechnung direct-debit missing mandatory field BT-90 #370. (langfr)
- refactor(ZUGFeRDVisualizer): improve PDF visualization performance #438 - refactor(ZUGFeRDVisualizer): improve PDF visualization performance #438
- product creation without description now possible empty description
- filename of embedded file was not xrechnung.xml when using profile xrechnung #452
- allow legalorganisation to have a tradingbusinessname #447
- JSon deserialization does not work with BankDetails #455
- Fix ClassCastException in CLI (Main.java). #451
- changed additional references by line from String to List and implemented it on Item #454
2.12.0 2.12.0
======= =======
2024-07-20 2024-07-20

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>org.mustangproject</groupId> <groupId>org.mustangproject</groupId>
<artifactId>core</artifactId> <artifactId>core</artifactId>
<version>2.13.1-SNAPSHOT</version> <version>2.14.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>Mustang-CLI</artifactId> <artifactId>Mustang-CLI</artifactId>

View File

@@ -722,9 +722,6 @@ public class Main {
((ZUGFeRDExporterFromPDFA) ze).ignorePDFAErrors(); ((ZUGFeRDExporterFromPDFA) ze).ignorePDFAErrors();
} }
} }
for (FileAttachment attachment : attachments) {
((ZUGFeRDExporterFromA3) ze).attachFile(attachment.getFilename(), attachment.getData(), attachment.getMimetype(), attachment.getRelation());
}
ze.load(pdfName); ze.load(pdfName);
ze.setProducer("Mustang-cli") ze.setProducer("Mustang-cli")
@@ -737,6 +734,10 @@ public class Main {
ze.setXML(Files.readAllBytes(Paths.get(xmlName))); ze.setXML(Files.readAllBytes(Paths.get(xmlName)));
for (FileAttachment attachment : attachments) {
ze.attachFile(attachment.getFilename(), attachment.getData(), attachment.getMimetype(), attachment.getRelation());
}
ze.export(outName); ze.export(outName);
System.out.println("Written to " + outName); System.out.println("Written to " + outName);

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.mustangproject</groupId> <groupId>org.mustangproject</groupId>
<artifactId>core</artifactId> <artifactId>core</artifactId>
<version>2.13.1-SNAPSHOT</version> <version>2.14.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>library</artifactId> <artifactId>library</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
@@ -207,7 +207,7 @@
<phase>package</phase> <phase>package</phase>
<configuration> <configuration>
<artifactSet> <artifactSet>
<excludes /> <excludes></excludes>
</artifactSet> </artifactSet>
</configuration> </configuration>
</execution> </execution>

View File

@@ -1,5 +1,7 @@
package org.mustangproject; package org.mustangproject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.mustangproject.ZUGFeRD.IZUGFeRDTradeSettlementPayment; import org.mustangproject.ZUGFeRD.IZUGFeRDTradeSettlementPayment;
/** /**
@@ -18,6 +20,10 @@ public class BankDetails implements IZUGFeRDTradeSettlementPayment {
* the "name" of the bank account (holder) * the "name" of the bank account (holder)
*/ */
protected String accountName=null; protected String accountName=null;
/***
* bean constructor
*/
public BankDetails() { }
/*** /***
* constructor for IBAN only :-) * constructor for IBAN only :-)
@@ -80,12 +86,14 @@ public class BankDetails implements IZUGFeRDTradeSettlementPayment {
* */ * */
@Override @Override
@Deprecated @Deprecated
@JsonIgnore
public String getOwnBIC() { public String getOwnBIC() {
return getBIC(); return getBIC();
} }
@Override @Override
@Deprecated @Deprecated
@JsonIgnore
public String getOwnIBAN() { public String getOwnIBAN() {
return getIBAN(); return getIBAN();
} }

View File

@@ -116,12 +116,20 @@ public class Charge implements IZUGFeRDAllowanceCharge {
@Override @Override
public BigDecimal getTotalAmount(IAbsoluteValueProvider currentItem) { public BigDecimal getTotalAmount(IAbsoluteValueProvider currentItem) {
if (percent!=null) {
return currentItem.getValue().multiply(getPercent().divide(new BigDecimal(100)));
} else if(totalAmount != null) {
return totalAmount;
} else {
throw new RuntimeException("percent must be set");
}
}
public BigDecimal getTotalAmount() {
if (totalAmount!=null) { if (totalAmount!=null) {
return totalAmount; return totalAmount;
} else if (percent!=null) {
return currentItem.getValue().multiply(getPercent().divide(new BigDecimal(100)));
} else { } else {
throw new RuntimeException("Either totalAmount or percent must be set"); throw new RuntimeException("totalAmount must be set");
} }
} }

View File

@@ -26,6 +26,7 @@ public class Item implements IZUGFeRDExportableItem {
protected Product product; protected Product product;
protected ArrayList<String> notes = null; protected ArrayList<String> notes = null;
protected ArrayList<ReferencedDocument> referencedDocuments = null; protected ArrayList<ReferencedDocument> referencedDocuments = null;
protected ArrayList<ReferencedDocument> additionalReference = null;
protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<>(), protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<>(),
Charges = new ArrayList<>(); Charges = new ArrayList<>();
@@ -63,6 +64,7 @@ public class Item implements IZUGFeRDExportableItem {
String referencedLineID = null; String referencedLineID = null;
ArrayList<ReferencedDocument> rdocs = null; ArrayList<ReferencedDocument> rdocs = null;
ArrayList<ReferencedDocument> addRefs = null;
// nodes.item(i).getTextContent())) { // nodes.item(i).getTextContent())) {
@@ -248,6 +250,35 @@ public class Item implements IZUGFeRDExportableItem {
} }
} }
} }
if (tradeSettlementName.equals("AdditionalReferencedDocument")) {
String IssuerAssignedID = "";
String TypeCode = "";
String ReferenceTypeCode = "";
NodeList refDocChilds = tradeSettlementChilds.item(tradeSettlementChildIndex).getChildNodes();
for (int refDocIndex = 0; refDocIndex < refDocChilds.getLength(); refDocIndex++) {
String localName = refDocChilds.item(refDocIndex).getLocalName();
if ((localName != null) && (localName.equals("IssuerAssignedID"))) {
IssuerAssignedID = refDocChilds.item(refDocIndex).getTextContent();
}
if ((localName != null) && (localName.equals("TypeCode"))) {
TypeCode = refDocChilds.item(refDocIndex).getTextContent();
}
if ((localName != null) && (localName.equals("ReferenceTypeCode"))) {
ReferenceTypeCode = refDocChilds.item(refDocIndex).getTextContent();
}
}
ReferencedDocument rd = new ReferencedDocument(IssuerAssignedID, TypeCode,
ReferenceTypeCode);
if (addRefs == null) {
addRefs = new ArrayList<>();
}
addRefs.add(rd);
}
} }
} }
} }
@@ -274,6 +305,11 @@ public class Item implements IZUGFeRDExportableItem {
addReferencedDocument(rdoc); addReferencedDocument(rdoc);
} }
} }
if (addRefs != null) {
for (ReferencedDocument rdoc : addRefs) {
addAdditionalReference(rdoc);
}
}
addReferencedLineID( referencedLineID ); addReferencedLineID( referencedLineID );
} }
@@ -465,6 +501,29 @@ public class Item implements IZUGFeRDExportableItem {
return referencedDocuments.toArray(new IReferencedDocument[0]); return referencedDocuments.toArray(new IReferencedDocument[0]);
} }
/***
* adds item level references along with their typecodes and issuerassignedIDs (contract ID, cost centre, ...)
* @param doc the ReferencedDocument to add
* @return fluent setter
*/
public Item addAdditionalReference(ReferencedDocument doc) {
if (additionalReference == null) {
additionalReference = new ArrayList<>();
}
additionalReference.add(doc);
return this;
}
@Override
public IReferencedDocument[] getAdditionalReferences() {
if (additionalReference == null) {
return null;
}
return additionalReference.toArray(new IReferencedDocument[0]);
}
/*** /***
* specify a item level delivery period * specify a item level delivery period
* (apart from the document level delivery period, and the document level * (apart from the document level delivery period, and the document level

View File

@@ -2,6 +2,8 @@ package org.mustangproject;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.mustangproject.ZUGFeRD.*; import org.mustangproject.ZUGFeRD.*;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/*** /***
* A organisation, i.e. usually a company * A organisation, i.e. usually a company
@@ -9,35 +11,68 @@ import org.mustangproject.ZUGFeRD.*;
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class LegalOrganisation implements IZUGFeRDLegalOrganisation { public class LegalOrganisation implements IZUGFeRDLegalOrganisation {
protected String ID = null; protected SchemedID schemedID = null;
protected String SchemeID = null; protected String tradingBusinessName = null;
public LegalOrganisation() { public LegalOrganisation() {
} }
public LegalOrganisation(String ID, String scheme) { public LegalOrganisation(String ID, String scheme) {
this.ID=ID; this.schemedID = new SchemedID(ID, scheme);
this.SchemeID=scheme; }
public LegalOrganisation(SchemedID schemedID, String tradingBusinessName) {
this.schemedID = schemedID;
this.tradingBusinessName=tradingBusinessName;
}
/***
* XML parsing constructor
* @param nodes the nodelist returned e.g. from xpath
*/
public LegalOrganisation(NodeList nodes) {
if (nodes.getLength() > 0) {
/*
will parse sth like
<ram:SpecifiedLegalOrganization>
<ram:ID schemeID="0002">4711</ram:ID>
<ram:TradingBusinessName>Test GmbH &amp; Co.KG</ram:TradingBusinessName>
</ram:SpecifiedLegalOrganization>
*/
for (int nodeIndex = 0; nodeIndex < nodes.getLength(); nodeIndex++) {
Node currentItemNode = nodes.item(nodeIndex);
if (currentItemNode.getLocalName() != null) {
if (currentItemNode.getLocalName().equals("GlobalID")) {
if (currentItemNode.getAttributes().getNamedItem("schemeID") != null) {
SchemedID gid = new SchemedID().setScheme(currentItemNode.getAttributes().getNamedItem("schemeID").getNodeValue()).setId(currentItemNode.getTextContent());
this.setSchemedID(gid);
}
}
if (currentItemNode.getLocalName().equals("TradingBusinessName")) {
setTradingBusinessName(currentItemNode.getFirstChild().getNodeValue());
}
}
}
}
} }
@Override @Override
public String getID() { public SchemedID getSchemedID() {
return ID; return this.schemedID;
} }
@Override @Override
public String getSchemeID() { public String getTradingBusinessName() {
return SchemeID; return this.tradingBusinessName;
} }
public LegalOrganisation setID(String id) { public LegalOrganisation setSchemedID(SchemedID schemedID) {
this.ID=id; this.schemedID = schemedID;
return this; return this;
} }
public LegalOrganisation setSchemeID(String scheme) { public LegalOrganisation setTradingBusinessName(String tradingBusinessName) {
SchemeID=scheme; this.tradingBusinessName = tradingBusinessName;
return this; return this;
} }
} }

View File

@@ -11,7 +11,10 @@ import java.util.HashMap;
*/ */
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class Product implements IZUGFeRDExportableProduct { public class Product implements IZUGFeRDExportableProduct {
protected String unit, name, description, sellerAssignedID, buyerAssignedID; protected String unit, name, sellerAssignedID, buyerAssignedID;
protected String description="";
protected String taxExemptionReason=null;
protected String taxCategoryCode=null;
protected BigDecimal VATPercent; protected BigDecimal VATPercent;
protected boolean isReverseCharge = false; protected boolean isReverseCharge = false;
protected boolean isIntraCommunitySupply = false; protected boolean isIntraCommunitySupply = false;
@@ -65,6 +68,44 @@ public class Product implements IZUGFeRDExportableProduct {
return this; return this;
} }
/***
*
* @return e.g. intra-commnunity supply or small business
*/
@Override
public String getTaxExemptionReason() {
return taxExemptionReason;
}
/***
*
* @param taxExemptionReasonText String e.g. Kleinunternehmer gemäß §19 UStG https://github.com/ZUGFeRD/mustangproject/issues/463
* @return
*/
public Product setTaxExemptionReason(String taxExemptionReasonText) {
taxExemptionReason = taxExemptionReasonText;
return this;
}
/***
*
* @return e.g. S (normal tax), Z=zero rated, E (e.g. small business) or K (intrra community supply)
*/
@Override
public String getTaxCategoryCode() {
return taxCategoryCode;
}
/***
*
* @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
*/
public Product setTaxCategoryCode(String code) {
taxCategoryCode = code;
return this;
}
@Override @Override
public String getSellerAssignedID() { public String getSellerAssignedID() {

View File

@@ -23,6 +23,7 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
protected String name, zip, street, location, country; protected String name, zip, street, location, country;
protected String taxID = null, vatID = null; protected String taxID = null, vatID = null;
protected String ID = null; protected String ID = null;
protected String description = null;
protected String additionalAddress = null; protected String additionalAddress = null;
protected String additionalAddressExtension = null; protected String additionalAddressExtension = null;
protected List<BankDetails> bankDetails = new ArrayList<>(); protected List<BankDetails> bankDetails = new ArrayList<>();
@@ -66,14 +67,14 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
Node currentItemNode = nodes.item(nodeIndex); Node currentItemNode = nodes.item(nodeIndex);
if (currentItemNode.getLocalName() != null) { if (currentItemNode.getLocalName() != null) {
String debcurrentChild = currentItemNode.getLocalName(); String currentUBLChild = currentItemNode.getLocalName();
if (debcurrentChild.equals("Party")) { if (currentUBLChild.equals("Party")) {
NodeList party = currentItemNode.getChildNodes(); NodeList party = currentItemNode.getChildNodes();
for (int partyIndex = 0; partyIndex < party.getLength(); partyIndex++) { for (int partyIndex = 0; partyIndex < party.getLength(); partyIndex++) {
if (party.item(partyIndex).getLocalName() != null) { if (party.item(partyIndex).getLocalName() != null) {
String debCN = party.item(partyIndex).getLocalName(); String currentTopElementName = party.item(partyIndex).getLocalName();
if (debCN.equals("PartyName")) { if (currentTopElementName.equals("PartyName")) {
NodeList partyName = party.item(partyIndex).getChildNodes(); NodeList partyName = party.item(partyIndex).getChildNodes();
for (int partyNameIndex = 0; partyNameIndex < partyName.getLength(); partyNameIndex++) { for (int partyNameIndex = 0; partyNameIndex < partyName.getLength(); partyNameIndex++) {
@@ -86,7 +87,20 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
} }
} }
} }
if (debCN.equals("PostalAddress")) {
// UBL only: formally it can have a name as well but BT27 party name *should* be stored in
// so overwrite if one exists
if (currentTopElementName.equals("PartyLegalEntity")) {
NodeList legal = party.item(partyIndex).getChildNodes();
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 (currentTopElementName.equals("PostalAddress")) {
NodeList postal = party.item(partyIndex).getChildNodes(); NodeList postal = party.item(partyIndex).getChildNodes();
for (int postalChildIndex = 0; postalChildIndex < postal.getLength(); postalChildIndex++) { for (int postalChildIndex = 0; postalChildIndex < postal.getLength(); postalChildIndex++) {
@@ -144,7 +158,7 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
} }
} }
if (debCN.equals("Contact")) { if (currentTopElementName.equals("Contact")) {
NodeList contact = party.item(partyIndex).getChildNodes(); NodeList contact = party.item(partyIndex).getChildNodes();
setContact(new Contact(contact)); setContact(new Contact(contact));
@@ -155,19 +169,19 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
} }
if (debcurrentChild.equals("GlobalID")) { if (currentUBLChild.equals("GlobalID")) {
if (nodes.item(nodeIndex).getAttributes().getNamedItem("schemeID") != null) { if (nodes.item(nodeIndex).getAttributes().getNamedItem("schemeID") != null) {
SchemedID gid = new SchemedID().setScheme(nodes.item(nodeIndex).getAttributes().getNamedItem("schemeID").getNodeValue()).setId(nodes.item(nodeIndex).getTextContent()); SchemedID gid = new SchemedID().setScheme(nodes.item(nodeIndex).getAttributes().getNamedItem("schemeID").getNodeValue()).setId(nodes.item(nodeIndex).getTextContent());
addGlobalID(gid); addGlobalID(gid);
} }
} }
if (debcurrentChild.equals("DefinedTradeContact")) { if (currentUBLChild.equals("DefinedTradeContact")) {
NodeList contact = nodes.item(nodeIndex).getChildNodes(); NodeList contact = nodes.item(nodeIndex).getChildNodes();
setContact(new Contact(contact)); setContact(new Contact(contact));
} }
if (debcurrentChild.equals("PostalTradeAddress")) { if (currentUBLChild.equals("PostalTradeAddress")) {
NodeList postal = nodes.item(nodeIndex).getChildNodes(); NodeList postal = nodes.item(nodeIndex).getChildNodes();
for (int postalChildIndex = 0; postalChildIndex < postal.getLength(); postalChildIndex++) { for (int postalChildIndex = 0; postalChildIndex < postal.getLength(); postalChildIndex++) {
if (postal.item(postalChildIndex).getLocalName() != null) { if (postal.item(postalChildIndex).getLocalName() != null) {
@@ -195,7 +209,7 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
} }
if (debcurrentChild.equals("SpecifiedTaxRegistration")) { if (currentUBLChild.equals("SpecifiedTaxRegistration")) {
NodeList taxChilds = nodes.item(nodeIndex).getChildNodes(); NodeList taxChilds = nodes.item(nodeIndex).getChildNodes();
for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) { for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) {
if (taxChilds.item(taxChildIndex).getLocalName() != null) { if (taxChilds.item(taxChildIndex).getLocalName() != null) {
@@ -286,8 +300,8 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
for (int nodeIndex = 0; nodeIndex < nodes.getLength(); nodeIndex++) { for (int nodeIndex = 0; nodeIndex < nodes.getLength(); nodeIndex++) {
//nodes.item(i).getTextContent())) { //nodes.item(i).getTextContent())) {
String debLN = nodes.item(nodeIndex).getLocalName(); String topElementName = nodes.item(nodeIndex).getLocalName();
if (debLN.equals("Party")) { if (topElementName.equals("Party")) {
// take one step back and parse from top // take one step back and parse from top
parseFromUBL(nodes); parseFromUBL(nodes);
return; return;
@@ -302,12 +316,20 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
if (itemChilds.item(itemChildIndex).getLocalName().equals("Name")) { if (itemChilds.item(itemChildIndex).getLocalName().equals("Name")) {
setName(itemChilds.item(itemChildIndex).getTextContent()); setName(itemChilds.item(itemChildIndex).getTextContent());
} }
if (itemChilds.item(itemChildIndex).getLocalName().equals("Description")) {
setDescription(itemChilds.item(itemChildIndex).getTextContent());
}
if (itemChilds.item(itemChildIndex).getLocalName().equals("GlobalID")) { if (itemChilds.item(itemChildIndex).getLocalName().equals("GlobalID")) {
if (itemChilds.item(itemChildIndex).getAttributes().getNamedItem("schemeID") != null) { if (itemChilds.item(itemChildIndex).getAttributes().getNamedItem("schemeID") != null) {
SchemedID gid = new SchemedID().setScheme(itemChilds.item(itemChildIndex).getAttributes().getNamedItem("schemeID").getNodeValue()).setId(itemChilds.item(itemChildIndex).getTextContent()); SchemedID gid = new SchemedID().setScheme(itemChilds.item(itemChildIndex).getAttributes().getNamedItem("schemeID").getNodeValue()).setId(itemChilds.item(itemChildIndex).getTextContent());
addGlobalID(gid); addGlobalID(gid);
} }
} }
if (itemChilds.item(itemChildIndex).getLocalName().equals("SpecifiedLegalOrganization")) {
NodeList organization = itemChilds.item(itemChildIndex).getChildNodes();
setLegalOrganisation(new LegalOrganisation(organization));
}
if (itemChilds.item(itemChildIndex).getLocalName().equals("DefinedTradeContact")) { if (itemChilds.item(itemChildIndex).getLocalName().equals("DefinedTradeContact")) {
NodeList contact = itemChilds.item(itemChildIndex).getChildNodes(); NodeList contact = itemChilds.item(itemChildIndex).getChildNodes();
setContact(new Contact(contact)); setContact(new Contact(contact));
@@ -556,6 +578,26 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
} }
/***
*
* @return String the description, e.g. if it's a vat exempt company
*/
public String getDescription() {
return description;
}
/***
* required, usually done in the constructor: the complete name of the organisation
* @param description human readable description
* @return fluent setter
*/
public TradeParty setDescription(String description) {
this.description = description;
return this;
}
public String getZIP() { public String getZIP() {
return zip; return zip;
} }

View File

@@ -92,12 +92,22 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
/*** /***
* the ID of an additionally referenced document for this item * the ID of an additionally referenced document for this item
* @deprecated use {@link #getAdditionalReferences()} instead.
* @return the id as string * @return the id as string
*/ */
@Deprecated
default String getAdditionalReferencedDocumentID() { default String getAdditionalReferencedDocumentID() {
return null; return null;
} }
/***
* allows to specify multiple references (billing information)
* @return the referenced documents
*/
default IReferencedDocument[] getAdditionalReferences() {
return null;
}
/*** /***
* allows to specify multiple(!) referenced documents along with e.g. their typecodes * allows to specify multiple(!) referenced documents along with e.g. their typecodes

View File

@@ -112,12 +112,17 @@ public interface IZUGFeRDExportableTradeParty {
} }
/** /**
* First and last name of the recipient * e.g. first and last name of the owner
* *
* @return First and last name of the recipient * @return full name of the party
*/ */
String getName(); String getName();
/**
* @return description, e.g. if it's a small company
*/
default String getDescription() { return null; }
/** /**
* Postal code of the recipient * Postal code of the recipient
* *

View File

@@ -23,6 +23,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import jakarta.activation.DataSource; import jakarta.activation.DataSource;
import org.mustangproject.FileAttachment;
public interface IZUGFeRDExporter extends Closeable, IExporter { public interface IZUGFeRDExporter extends Closeable, IExporter {
/** /**
@@ -64,6 +65,8 @@ public interface IZUGFeRDExporter extends Closeable, IExporter {
public String getNamespaceForVersion(int ver); public String getNamespaceForVersion(int ver);
public String getPrefixForVersion(int ver) ; public String getPrefixForVersion(int ver) ;
public IZUGFeRDExporter disableAutoClose(boolean disableAutoClose); public IZUGFeRDExporter disableAutoClose(boolean disableAutoClose);
public void attachFile(FileAttachment file);
public void attachFile(String filename, byte[] data, String mimetype, String relation);
public IXMLProvider getProvider(); public IXMLProvider getProvider();
} }

View File

@@ -18,17 +18,19 @@
*********************************************************************** */ *********************************************************************** */
package org.mustangproject.ZUGFeRD; package org.mustangproject.ZUGFeRD;
public interface IZUGFeRDLegalOrganisation { import org.mustangproject.SchemedID;
/*** public interface IZUGFeRDLegalOrganisation {
*
* @return the ID of the legal organisation
*/
public String getID();
/** /**
* *
* @return the scheme attribute of the legal organization=the type of the identification, e.g. 0002=Siren * @return the scheme attribute of the legal organization=the type of the identification, e.g. 0002=Siren, and its value
*/ */
public String getSchemeID(); public SchemedID getSchemedID();
/***
*
* @return the TradingBusinessName of the legal organisation
*/
public String getTradingBusinessName();
} }

View File

@@ -18,12 +18,15 @@
*********************************************************************** */ *********************************************************************** */
package org.mustangproject.ZUGFeRD; package org.mustangproject.ZUGFeRD;
import com.fasterxml.jackson.annotation.JsonIgnore;
public interface IZUGFeRDTradeSettlement { public interface IZUGFeRDTradeSettlement {
/*** /***
* gets the applicableHeaderTradeSettlement * gets the applicableHeaderTradeSettlement
* @return zf2 xml * @return zf2 xml
*/ */
@JsonIgnore
String getSettlementXML(); String getSettlementXML();
@@ -31,6 +34,7 @@ public interface IZUGFeRDTradeSettlement {
* gets the applicableHeaderTradePayment * gets the applicableHeaderTradePayment
* @return zf2 xml * @return zf2 xml
*/ */
@JsonIgnore
default String getPaymentXML() { default String getPaymentXML() {
return null; return null;
} }

View File

@@ -18,6 +18,7 @@
*********************************************************************** */ *********************************************************************** */
package org.mustangproject.ZUGFeRD; package org.mustangproject.ZUGFeRD;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.mustangproject.XMLTools; import org.mustangproject.XMLTools;
public interface IZUGFeRDTradeSettlementPayment extends IZUGFeRDTradeSettlement { public interface IZUGFeRDTradeSettlementPayment extends IZUGFeRDTradeSettlement {
@@ -27,6 +28,7 @@ public interface IZUGFeRDTradeSettlementPayment extends IZUGFeRDTradeSettlement
* *
* @return payment information text * @return payment information text
*/ */
@JsonIgnore
default String getOwnPaymentInfoText() { default String getOwnPaymentInfoText() {
return null; return null;
} }
@@ -59,6 +61,7 @@ public interface IZUGFeRDTradeSettlementPayment extends IZUGFeRDTradeSettlement
@Override @Override
@JsonIgnore
default String getSettlementXML() { default String getSettlementXML() {
String accountNameStr=""; String accountNameStr="";
if (getAccountName()!=null) { if (getAccountName()!=null) {

View File

@@ -172,6 +172,10 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
LineCalculator lc = new LineCalculator(currentItem); LineCalculator lc = new LineCalculator(currentItem);
VATAmount itemVATAmount = new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount(), VATAmount itemVATAmount = new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount(),
currentItem.getProduct().getTaxCategoryCode(), vatDueDateTypeCode); currentItem.getProduct().getTaxCategoryCode(), vatDueDateTypeCode);
String reasonText=currentItem.getProduct().getTaxExemptionReason();
if (reasonText!=null) {
itemVATAmount.setVatExemptionReasonText(reasonText);
}
VATAmount current = hm.get(percent.stripTrailingZeros()); VATAmount current = hm.get(percent.stripTrailingZeros());
if (current == null) { if (current == null) {
hm.put(percent.stripTrailingZeros(), itemVATAmount); hm.put(percent.stripTrailingZeros(), itemVATAmount);

View File

@@ -32,6 +32,16 @@ import java.math.RoundingMode;
*/ */
public class VATAmount { public class VATAmount {
protected BigDecimal basis, calculated, applicablePercent;
protected String categoryCode;
protected String vatExemptionReasonText;
protected String dueDateTypeCode;
public VATAmount(BigDecimal basis, BigDecimal calculated, String categoryCode) { public VATAmount(BigDecimal basis, BigDecimal calculated, String categoryCode) {
super(); super();
this.basis = basis; this.basis = basis;
@@ -48,35 +58,41 @@ public class VATAmount {
this.dueDateTypeCode = dueDateTypeCode; this.dueDateTypeCode = dueDateTypeCode;
} }
BigDecimal basis, calculated, applicablePercent;
String categoryCode;
String dueDateTypeCode;
public BigDecimal getApplicablePercent() { public BigDecimal getApplicablePercent() {
return applicablePercent; return applicablePercent;
} }
public void setApplicablePercent(BigDecimal applicablePercent) { public VATAmount setApplicablePercent(BigDecimal applicablePercent) {
this.applicablePercent = applicablePercent; this.applicablePercent = applicablePercent;
return this;
} }
public BigDecimal getBasis() { public BigDecimal getBasis() {
return basis; return basis;
} }
public void setBasis(BigDecimal basis) { public VATAmount setBasis(BigDecimal basis) {
this.basis = basis.setScale(2, RoundingMode.HALF_UP); this.basis = basis.setScale(2, RoundingMode.HALF_UP);
return this;
} }
public BigDecimal getCalculated() { public BigDecimal getCalculated() {
return calculated; return calculated;
} }
public void setCalculated(BigDecimal calculated) { public VATAmount setCalculated(BigDecimal calculated) {
this.calculated = calculated; this.calculated = calculated;
return this;
}
public String getVatExemptionReasonText() {
return vatExemptionReasonText;
}
public VATAmount setVatExemptionReasonText(String theText) {
this.vatExemptionReasonText = theText;
return this;
} }
/** /**
@@ -94,24 +110,27 @@ public class VATAmount {
* @deprecated Use {@link #setCategoryCode(String)} instead * @deprecated Use {@link #setCategoryCode(String)} instead
*/ */
@Deprecated @Deprecated
public void setDocumentCode(String documentCode) { public VATAmount setDocumentCode(String documentCode) {
this.categoryCode = documentCode; this.categoryCode = documentCode;
return this;
} }
public String getCategoryCode() { public String getCategoryCode() {
return categoryCode; return categoryCode;
} }
public void setCategoryCode(String categoryCode) { public VATAmount setCategoryCode(String categoryCode) {
this.categoryCode = categoryCode; this.categoryCode = categoryCode;
return this;
} }
public String getDueDateTypeCode() { public String getDueDateTypeCode() {
return dueDateTypeCode; return dueDateTypeCode;
} }
public void setDueDateTypeCode(String dueDateTypeCode) { public VATAmount setDueDateTypeCode(String dueDateTypeCode) {
this.dueDateTypeCode = dueDateTypeCode; this.dueDateTypeCode = dueDateTypeCode;
return this;
} }
public VATAmount add(VATAmount v) { public VATAmount add(VATAmount v) {

View File

@@ -387,9 +387,10 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider {
+ "<ram:LineTotalAmount currencyID=\"" + trans.getCurrency() + "\">" + currencyFormat(lc.getItemTotalNetAmount()) + "<ram:LineTotalAmount currencyID=\"" + trans.getCurrency() + "\">" + currencyFormat(lc.getItemTotalNetAmount())
+ "</ram:LineTotalAmount>" + "</ram:LineTotalAmount>"
+ "</ram:SpecifiedTradeSettlementMonetarySummation>"; + "</ram:SpecifiedTradeSettlementMonetarySummation>";
if (currentItem.getAdditionalReferencedDocumentID() != null) { if (currentItem.getAdditionalReferences() != null) {
xml += "<ram:AdditionalReferencedDocument><ram:ID>" + currentItem.getAdditionalReferences()[0].getIssuerAssignedID() + "</ram:ID><ram:TypeCode>130</ram:TypeCode></ram:AdditionalReferencedDocument>";
} else if (currentItem.getAdditionalReferencedDocumentID() != null) {
xml += "<ram:AdditionalReferencedDocument><ram:ID>" + currentItem.getAdditionalReferencedDocumentID() + "</ram:ID><ram:TypeCode>130</ram:TypeCode></ram:AdditionalReferencedDocument>"; xml += "<ram:AdditionalReferencedDocument><ram:ID>" + currentItem.getAdditionalReferencedDocumentID() + "</ram:ID><ram:TypeCode>130</ram:TypeCode></ram:AdditionalReferencedDocument>";
} }
xml += "</ram:SpecifiedSupplyChainTradeSettlement>" xml += "</ram:SpecifiedSupplyChainTradeSettlement>"
+ "<ram:SpecifiedTradeProduct>"; + "<ram:SpecifiedTradeProduct>";

View File

@@ -51,7 +51,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class ZUGFeRD2PullProvider implements IXMLProvider { public class ZUGFeRD2PullProvider implements IXMLProvider {
private static final Logger LOGGER = LoggerFactory.getLogger (ZUGFeRD2PullProvider.class); private static final Logger LOGGER = LoggerFactory.getLogger(ZUGFeRD2PullProvider.class);
protected byte[] zugferdData; protected byte[] zugferdData;
protected IExportableTransaction trans; protected IExportableTransaction trans;
@@ -93,7 +93,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
try { try {
document = DocumentHelper.parseText(new String(zugferdData)); document = DocumentHelper.parseText(new String(zugferdData));
} catch (final DocumentException e1) { } catch (final DocumentException e1) {
LOGGER.error ("Failed to parse ZUGFeRD data", e1); LOGGER.error("Failed to parse ZUGFeRD data", e1);
} }
try { try {
final OutputFormat format = OutputFormat.createPrettyPrint(); final OutputFormat format = OutputFormat.createPrettyPrint();
@@ -103,7 +103,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
res = sw.toString().getBytes(StandardCharsets.UTF_8); res = sw.toString().getBytes(StandardCharsets.UTF_8);
} catch (final IOException e) { } catch (final IOException e) {
LOGGER.error ("Failed to write ZUGFeRD data", e); LOGGER.error("Failed to write ZUGFeRD data", e);
} }
return res; return res;
@@ -138,14 +138,21 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
+ XMLTools.encodeXML(party.getGlobalID()) + "</ram:GlobalID>"; + XMLTools.encodeXML(party.getGlobalID()) + "</ram:GlobalID>";
} }
xml += "<ram:Name>" + XMLTools.encodeXML(party.getName()) + "</ram:Name>"; xml += "<ram:Name>" + XMLTools.encodeXML(party.getName()) + "</ram:Name>";
if (party.getDescription() != null) {
xml += "<ram:Description>" + XMLTools.encodeXML(party.getDescription()) + "</ram:Description>";
}
if (party.getLegalOrganisation() != null) { if (party.getLegalOrganisation() != null) {
xml += "<ram:SpecifiedLegalOrganization> "; xml += "<ram:SpecifiedLegalOrganization> ";
xml += "<ram:ID schemeID=\"" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemeID()) + "\">" + XMLTools.encodeXML(party.getLegalOrganisation().getID()) + "</ram:ID>"; if (party.getLegalOrganisation().getSchemedID() != null) {
xml += "<ram:ID schemeID=\"" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getScheme()) + "\">" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getID()) + "</ram:ID>";
}
if (party.getLegalOrganisation().getTradingBusinessName() != null) {
xml += "<ram:TradingBusinessName>" + XMLTools.encodeXML(party.getLegalOrganisation().getTradingBusinessName()) + "</ram:TradingBusinessName>";
}
xml += "</ram:SpecifiedLegalOrganization>"; xml += "</ram:SpecifiedLegalOrganization>";
} }
if ((party.getContact() != null) && (isSender || profile == Profiles.getByName("Extended") || profile == Profiles.getByName("XRechnung"))) { if ((party.getContact() != null) && (isSender || profile == Profiles.getByName("EN16931") || profile == Profiles.getByName("Extended") || profile == Profiles.getByName("XRechnung"))) {
xml += "<ram:DefinedTradeContact>"; xml += "<ram:DefinedTradeContact>";
if (party.getContact().getName() != null) { if (party.getContact().getName() != null) {
xml += "<ram:PersonName>" + XMLTools.encodeXML(party.getContact().getName()) xml += "<ram:PersonName>" + XMLTools.encodeXML(party.getContact().getName())
@@ -318,7 +325,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
paymentTermsDescription += discount.getAsXRechnung(); paymentTermsDescription += discount.getAsXRechnung();
} }
} else if ((paymentTermsDescription == null) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CORRECTEDINVOICE) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE)) { } else if ((paymentTermsDescription == null) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CORRECTEDINVOICE) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE)) {
if ( trans.getDueDate() != null ) { if (trans.getDueDate() != null) {
paymentTermsDescription = "Please remit until " + germanDateFormat.format(trans.getDueDate()); paymentTermsDescription = "Please remit until " + germanDateFormat.format(trans.getDueDate());
} }
} }
@@ -417,7 +424,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
"</ram:Description>"; "</ram:Description>";
} }
if (currentItem.getProduct().getAttributes() != null) { if (currentItem.getProduct().getAttributes() != null) {
for ( Entry<String, String> entry : currentItem.getProduct().getAttributes().entrySet() ) { for (Entry<String, String> entry : currentItem.getProduct().getAttributes().entrySet()) {
xml += "<ram:ApplicableProductCharacteristic>" + xml += "<ram:ApplicableProductCharacteristic>" +
"<ram:Description>" + XMLTools.encodeXML(entry.getKey()) + "</ram:Description>" + "<ram:Description>" + XMLTools.encodeXML(entry.getKey()) + "</ram:Description>" +
"<ram:Value>" + XMLTools.encodeXML(entry.getValue()) + "</ram:Value>" + "<ram:Value>" + XMLTools.encodeXML(entry.getValue()) + "</ram:Value>" +
@@ -426,8 +433,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
} }
if (currentItem.getProduct().getCountryOfOrigin() != null) { if (currentItem.getProduct().getCountryOfOrigin() != null) {
xml += "<ram:OriginTradeCountry><ram:ID>" + xml += "<ram:OriginTradeCountry><ram:ID>" +
XMLTools.encodeXML(currentItem.getProduct().getCountryOfOrigin()) + XMLTools.encodeXML(currentItem.getProduct().getCountryOfOrigin()) +
"</ram:ID></ram:OriginTradeCountry>"; "</ram:ID></ram:OriginTradeCountry>";
} }
xml += "</ram:SpecifiedTradeProduct>" xml += "</ram:SpecifiedTradeProduct>"
@@ -498,9 +505,16 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
+ "<ram:LineTotalAmount>" + currencyFormat(lc.getItemTotalNetAmount()) + "<ram:LineTotalAmount>" + currencyFormat(lc.getItemTotalNetAmount())
+ "</ram:LineTotalAmount>" // currencyID=\"EUR\" + "</ram:LineTotalAmount>" // currencyID=\"EUR\"
+ "</ram:SpecifiedTradeSettlementLineMonetarySummation>"; + "</ram:SpecifiedTradeSettlementLineMonetarySummation>";
if (currentItem.getAdditionalReferencedDocumentID() != null) { if (currentItem.getAdditionalReferences() != null) {
for (final IReferencedDocument currentReference : currentItem.getAdditionalReferences()) {
xml += "<ram:AdditionalReferencedDocument>" +
"<ram:IssuerAssignedID>" + XMLTools.encodeXML(currentReference.getIssuerAssignedID()) + "</ram:IssuerAssignedID>" +
"<ram:TypeCode>130</ram:TypeCode>" +
"<ram:ReferenceTypeCode>" + XMLTools.encodeXML(currentReference.getReferenceTypeCode()) + "</ram:ReferenceTypeCode>" +
"</ram:AdditionalReferencedDocument>";
}
} else if (currentItem.getAdditionalReferencedDocumentID() != null) {
xml += "<ram:AdditionalReferencedDocument><ram:IssuerAssignedID>" + currentItem.getAdditionalReferencedDocumentID() + "</ram:IssuerAssignedID><ram:TypeCode>130</ram:TypeCode></ram:AdditionalReferencedDocument>"; xml += "<ram:AdditionalReferencedDocument><ram:IssuerAssignedID>" + currentItem.getAdditionalReferencedDocumentID() + "</ram:IssuerAssignedID><ram:TypeCode>130</ram:TypeCode></ram:AdditionalReferencedDocument>";
} }
xml += "</ram:SpecifiedLineTradeSettlement>" xml += "</ram:SpecifiedLineTradeSettlement>"
+ "</ram:IncludedSupplyChainTradeLineItem>"; + "</ram:IncludedSupplyChainTradeLineItem>";
@@ -640,12 +654,17 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
final String amountDueDateTypeCode = amount.getDueDateTypeCode(); final String amountDueDateTypeCode = amount.getDueDateTypeCode();
final boolean displayExemptionReason = CATEGORY_CODES_WITH_EXEMPTION_REASON.contains(amountCategoryCode); final boolean displayExemptionReason = CATEGORY_CODES_WITH_EXEMPTION_REASON.contains(amountCategoryCode);
if (getProfile() != Profiles.getByName("Minimum")) { if (getProfile() != Profiles.getByName("Minimum")) {
String exemptionReasonTextXML = "";
if ((displayExemptionReason) && (amount.getVatExemptionReasonText() != null)) {
exemptionReasonTextXML = "<ram:ExemptionReason>" + XMLTools.encodeXML(amount.getVatExemptionReasonText()) + "</ram:ExemptionReason>";
}
xml += "<ram:ApplicableTradeTax>" xml += "<ram:ApplicableTradeTax>"
+ "<ram:CalculatedAmount>" + currencyFormat(amount.getCalculated()) + "<ram:CalculatedAmount>" + currencyFormat(amount.getCalculated())
+ "</ram:CalculatedAmount>" //currencyID=\"EUR\" + "</ram:CalculatedAmount>" //currencyID=\"EUR\"
+ "<ram:TypeCode>VAT</ram:TypeCode>" + "<ram:TypeCode>VAT</ram:TypeCode>"
+ (displayExemptionReason ? exemptionReason : "") + exemptionReasonTextXML
+ "<ram:BasisAmount>" + currencyFormat(amount.getBasis()) + "</ram:BasisAmount>" // currencyID=\"EUR\" + "<ram:BasisAmount>" + currencyFormat(amount.getBasis()) + "</ram:BasisAmount>" // currencyID=\"EUR\"
+ "<ram:CategoryCode>" + amountCategoryCode + "</ram:CategoryCode>" + "<ram:CategoryCode>" + amountCategoryCode + "</ram:CategoryCode>"
+ (amountDueDateTypeCode != null ? "<ram:DueDateTypeCode>" + amountDueDateTypeCode + "</ram:DueDateTypeCode>" : "") + (amountDueDateTypeCode != null ? "<ram:DueDateTypeCode>" + amountDueDateTypeCode + "</ram:DueDateTypeCode>" : "")
@@ -667,7 +686,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if ((trans.getZFCharges() != null) && (trans.getZFCharges().length > 0)) { if ((trans.getZFCharges() != null) && (trans.getZFCharges().length > 0)) {
if (profile == Profiles.getByName("XRechnung")) { if (profile == Profiles.getByName("XRechnung")) {
for(IZUGFeRDAllowanceCharge charge : trans.getZFCharges()) { for (IZUGFeRDAllowanceCharge charge : trans.getZFCharges()) {
xml += "<ram:SpecifiedTradeAllowanceCharge>" + xml += "<ram:SpecifiedTradeAllowanceCharge>" +
"<ram:ChargeIndicator>" + "<ram:ChargeIndicator>" +
"<udt:Indicator>true</udt:Indicator>" + "<udt:Indicator>true</udt:Indicator>" +
@@ -710,7 +729,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if ((trans.getZFAllowances() != null) && (trans.getZFAllowances().length > 0)) { if ((trans.getZFAllowances() != null) && (trans.getZFAllowances().length > 0)) {
if (profile == Profiles.getByName("XRechnung")) { if (profile == Profiles.getByName("XRechnung")) {
for(IZUGFeRDAllowanceCharge allowance : trans.getZFAllowances()) { for (IZUGFeRDAllowanceCharge allowance : trans.getZFAllowances()) {
xml += "<ram:SpecifiedTradeAllowanceCharge>" + xml += "<ram:SpecifiedTradeAllowanceCharge>" +
"<ram:ChargeIndicator>" + "<ram:ChargeIndicator>" +
"<udt:Indicator>false</udt:Indicator>" + "<udt:Indicator>false</udt:Indicator>" +

View File

@@ -85,6 +85,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
this.ignorePDFAErrors = true; this.ignorePDFAErrors = true;
return this; return this;
} }
protected PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE; protected PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE;
protected ArrayList<FileAttachment> fileAttachments = new ArrayList<>(); protected ArrayList<FileAttachment> fileAttachments = new ArrayList<>();
@@ -223,17 +224,16 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
* @return the filename of the file to be embedded * @return the filename of the file to be embedded
*/ */
public String getFilenameForVersion(int ver, Profile profile) { public String getFilenameForVersion(int ver, Profile profile) {
if (profile.getName().equals("XRECHNUNG")) {
return "xrechnung.xml";
}
if (isFacturX) { if (isFacturX) {
return "factur-x.xml"; return "factur-x.xml";
} else { } else {
if (ver == 1) { if (ver == 1) {
return "ZUGFeRD-invoice.xml"; return "ZUGFeRD-invoice.xml";
} else { } else {
if (profile.getName().equals("XRECHNUNG")) { return "zugferd-invoice.xml";
return "xrechnung.xml";
} else {
return "zugferd-invoice.xml";
}
} }
} }
} }
@@ -247,7 +247,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
* @deprecated It's now the default anyway * @deprecated It's now the default anyway
*/ */
@Deprecated @Deprecated
public ZUGFeRDExporterFromA3 setFacturX() { public ZUGFeRDExporterFromA3 setFacturX() {
isFacturX = true; isFacturX = true;
return this; return this;
} }
@@ -260,10 +260,9 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
* *
* @param XRechnungVersion the XRechnung version * @param XRechnungVersion the XRechnung version
*/ */
public void setXRechnungSpecificVersion(String XRechnungVersion) public void setXRechnungSpecificVersion(String XRechnungVersion) {
{ this.XRechnungVersion = XRechnungVersion;
this.XRechnungVersion = XRechnungVersion; }
}
/*** /***
@@ -308,13 +307,13 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
* @throws IOException if anything is wrong in the target location * @throws IOException if anything is wrong in the target location
*/ */
@Override @Override
public void export(String ZUGFeRDfilename) throws IOException { public void export(String ZUGFeRDfilename) throws IOException {
if (!documentPrepared) { if (!documentPrepared) {
prepareDocument(); prepareDocument();
} }
if ((!fileAttached) && (attachZUGFeRDHeaders)) { if ((!fileAttached) && (attachZUGFeRDHeaders)) {
throw new IOException( throw new IOException(
"File must be attached (usually with setTransaction) before perfoming this operation"); "File must be attached (usually with setTransaction) before perfoming this operation");
} }
doc.save(ZUGFeRDfilename, CompressParameters.NO_COMPRESSION); doc.save(ZUGFeRDfilename, CompressParameters.NO_COMPRESSION);
if (!disableAutoClose) { if (!disableAutoClose) {
@@ -336,13 +335,13 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
* @throws IOException if anything is wrong in the OutputStream * @throws IOException if anything is wrong in the OutputStream
*/ */
@Override @Override
public void export(OutputStream output) throws IOException { public void export(OutputStream output) throws IOException {
if (!documentPrepared) { if (!documentPrepared) {
prepareDocument(); prepareDocument();
} }
if ((!fileAttached) && (attachZUGFeRDHeaders)) { if ((!fileAttached) && (attachZUGFeRDHeaders)) {
throw new IOException( throw new IOException(
"File must be attached (usually with setTransaction) before perfoming this operation"); "File must be attached (usually with setTransaction) before perfoming this operation");
} }
doc.save(output, CompressParameters.NO_COMPRESSION); doc.save(output, CompressParameters.NO_COMPRESSION);
if (!disableAutoClose) { if (!disableAutoClose) {
@@ -440,7 +439,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
cosArray.add(fs); cosArray.add(fs);
doc.getDocumentCatalog().getCOSObject().setItem("AF", cosArray); doc.getDocumentCatalog().getCOSObject().setItem("AF", cosArray);
} else if ((AFEntry instanceof COSObject) && } else if ((AFEntry instanceof COSObject) &&
((COSObject) AFEntry).getObject() instanceof COSArray) { ((COSObject) AFEntry).getObject() instanceof COSArray) {
COSArray cosArray = (COSArray) ((COSObject) AFEntry).getObject(); COSArray cosArray = (COSArray) ((COSObject) AFEntry).getObject();
cosArray.add(fs); cosArray.add(fs);
} else { } else {
@@ -534,19 +533,18 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
*/ */
protected void addXMP(XMPMetadata metadata) { protected void addXMP(XMPMetadata metadata) {
String metaDataVersion = null; // default will be used String metaDataVersion = null; // default will be used
// The XRechnung version may be settable from outside. // The XRechnung version may be settable from outside.
if ((this.XRechnungVersion != null) && (this.profile != null) && if ((this.XRechnungVersion != null) && (this.profile != null) &&
this.profile.getName().equalsIgnoreCase(Profiles.getByName("XRECHNUNG").getName())) this.profile.getName().equalsIgnoreCase(Profiles.getByName("XRECHNUNG").getName())) {
{ metaDataVersion = this.XRechnungVersion;
metaDataVersion = this.XRechnungVersion; }
}
if (attachZUGFeRDHeaders) { if (attachZUGFeRDHeaders) {
XMPSchemaZugferd zf = new XMPSchemaZugferd(metadata, ZFVersion, isFacturX, xmlProvider.getProfile(), XMPSchemaZugferd zf = new XMPSchemaZugferd(metadata, ZFVersion, isFacturX, xmlProvider.getProfile(),
getNamespaceForVersion(ZFVersion), getPrefixForVersion(ZFVersion), getNamespaceForVersion(ZFVersion), getPrefixForVersion(ZFVersion),
getFilenameForVersion(ZFVersion, xmlProvider.getProfile()), metaDataVersion); getFilenameForVersion(ZFVersion, xmlProvider.getProfile()), metaDataVersion);
metadata.addSchema(zf); metadata.addSchema(zf);
} }
@@ -557,8 +555,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
} }
private void removeCidSet(PDDocument doc) private void removeCidSet(PDDocument doc)
throws IOException throws IOException {
{
// https://github.com/ZUGFeRD/mustangproject/issues/249 // https://github.com/ZUGFeRD/mustangproject/issues/249
COSName cidSet = COSName.getPDFName("CIDSet"); COSName cidSet = COSName.getPDFName("CIDSet");
@@ -577,8 +574,8 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
PDType0Font typedFont = (PDType0Font) pdFont; PDType0Font typedFont = (PDType0Font) pdFont;
if (typedFont.getDescendantFont() instanceof PDCIDFontType2) { if (typedFont.getDescendantFont() instanceof PDCIDFontType2) {
@SuppressWarnings ("unused") @SuppressWarnings("unused")
PDCIDFontType2 f = (PDCIDFontType2) typedFont.getDescendantFont(); PDCIDFontType2 f = (PDCIDFontType2) typedFont.getDescendantFont();
PDFontDescriptor fontDescriptor = pdFont.getFontDescriptor(); PDFontDescriptor fontDescriptor = pdFont.getFontDescriptor();
fontDescriptor.getCOSObject().removeItem(cidSet); fontDescriptor.getCOSObject().removeItem(cidSet);
@@ -637,7 +634,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
* @throws IOException if anything is wrong with already loaded PDF * @throws IOException if anything is wrong with already loaded PDF
*/ */
@Override @Override
public IExporter setTransaction(IExportableTransaction trans) throws IOException { public IExporter setTransaction(IExportableTransaction trans) throws IOException {
this.trans = trans; this.trans = trans;
return prepare(); return prepare();
} }
@@ -647,22 +644,20 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
xmlProvider.generateXML(trans); xmlProvider.generateXML(trans);
String filename = getFilenameForVersion(ZFVersion, xmlProvider.getProfile()); String filename = getFilenameForVersion(ZFVersion, xmlProvider.getProfile());
String relationship = "Alternative"; String relationship = "Alternative";
// ZUGFeRD 2.1.1 Technical Supplement | Part A | 2.2.2. Data Relationship // ZUGFeRD 2.1.1 Technical Supplement | Part A | 2.2.2. Data Relationship
// See documentation ZUGFeRD211_EN/Documentation/ZUGFeRD-2.1.1 - Specification_TA_Part-A.pdf // See documentation ZUGFeRD211_EN/Documentation/ZUGFeRD-2.1.1 - Specification_TA_Part-A.pdf
// https://www.ferd-net.de/standards/zugferd-2.1.1/index.html // https://www.ferd-net.de/standards/zugferd-2.1.1/index.html
if ((this.profile != null) && (ZFVersion >= 2)) if ((this.profile != null) && (ZFVersion >= 2)) {
{ if (this.profile.getName().equalsIgnoreCase(Profiles.getByName("MINIMUM").getName()) ||
if (this.profile.getName().equalsIgnoreCase(Profiles.getByName("MINIMUM").getName()) || this.profile.getName().equalsIgnoreCase(Profiles.getByName("BASICWL").getName())) {
this.profile.getName().equalsIgnoreCase(Profiles.getByName("BASICWL").getName())) relationship = "Data";
{ }
relationship = "Data"; }
}
}
PDFAttachGenericFile(doc, filename, relationship, PDFAttachGenericFile(doc, filename, relationship,
"Invoice metadata conforming to ZUGFeRD standard (http://www.ferd-net.de/front_content.php?idcat=231&lang=4)", "Invoice metadata conforming to ZUGFeRD standard (http://www.ferd-net.de/front_content.php?idcat=231&lang=4)",
"text/xml", xmlProvider.getXML()); "text/xml", xmlProvider.getXML());
for (FileAttachment attachment : fileAttachments) { for (FileAttachment attachment : fileAttachments) {
PDFAttachGenericFile(doc, attachment.getFilename(), attachment.getRelation(), attachment.getDescription(), attachment.getMimetype(), attachment.getData()); PDFAttachGenericFile(doc, attachment.getFilename(), attachment.getRelation(), attachment.getDescription(), attachment.getMimetype(), attachment.getData());
@@ -674,12 +669,12 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
/** /**
* Reads the XMPMetadata from the PDDocument, if it exists. * Reads the XMPMetadata from the PDDocument, if it exists.
* Otherwise creates XMPMetadata. * Otherwise creates XMPMetadata.
*
* @return the finished XMPMetadata object * @return the finished XMPMetadata object
* @throws IOException when e.g. XmpParsingException * @throws IOException when e.g. XmpParsingException
*/ */
protected XMPMetadata getXmpMetadata() protected XMPMetadata getXmpMetadata()
throws IOException throws IOException {
{
PDMetadata meta = doc.getDocumentCatalog().getMetadata(); PDMetadata meta = doc.getDocumentCatalog().getMetadata();
if ((meta != null) && (meta.getLength() > 0)) { if ((meta != null) && (meta.getLength() > 0)) {
try { try {
@@ -701,6 +696,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
/** /**
* Sets the producer if the overwrite flag is set or the producer is not already set. * Sets the producer if the overwrite flag is set or the producer is not already set.
* Sets the PDFVersion to 1.4 if the field is empty. * Sets the PDFVersion to 1.4 if the field is empty.
*
* @param xmp the metadata as XML * @param xmp the metadata as XML
*/ */
protected void writeAdobePDFSchema(XMPMetadata xmp) { protected void writeAdobePDFSchema(XMPMetadata xmp) {
@@ -823,11 +819,11 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
/** /**
* Adds an OutputIntent and the sRGB color profile if no OutputIntent exist * Adds an OutputIntent and the sRGB color profile if no OutputIntent exist
*
* @throws IOException if the ICC file cannot be read or attached to doc * @throws IOException if the ICC file cannot be read or attached to doc
*/ */
protected void addSRGBOutputIntend() protected void addSRGBOutputIntend()
throws IOException throws IOException {
{
if (!doc.getDocumentCatalog().getOutputIntents().isEmpty()) { if (!doc.getDocumentCatalog().getOutputIntents().isEmpty()) {
return; return;
} }
@@ -892,12 +888,12 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
public ZUGFeRDExporterFromA3 setZUGFeRDVersion(EStandard est, int version) { public ZUGFeRDExporterFromA3 setZUGFeRDVersion(EStandard est, int version) {
this.ZFVersion = version; this.ZFVersion = version;
if ((version<1) || (version>2)) { if ((version < 1) || (version > 2)) {
throw new IllegalArgumentException("Version not supported"); throw new IllegalArgumentException("Version not supported");
} }
int generation=version; int generation = version;
if ((est==EStandard.facturx)&&(version==1)) { if ((est == EStandard.facturx) && (version == 1)) {
generation=2; generation = 2;
} }
if (generation == 1) { if (generation == 1) {
ZUGFeRD1PullProvider z1p = new ZUGFeRD1PullProvider(); ZUGFeRD1PullProvider z1p = new ZUGFeRD1PullProvider();

View File

@@ -34,6 +34,7 @@ import org.apache.xmpbox.XMPMetadata;
import org.apache.xmpbox.schema.PDFAIdentificationSchema; import org.apache.xmpbox.schema.PDFAIdentificationSchema;
import org.apache.xmpbox.xml.DomXmpParser; import org.apache.xmpbox.xml.DomXmpParser;
import org.apache.xmpbox.xml.XmpParsingException; import org.apache.xmpbox.xml.XmpParsingException;
import org.mustangproject.FileAttachment;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -72,7 +73,8 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter {
} }
protected IZUGFeRDExporter getExporter() {
public IZUGFeRDExporter getExporter() {
if (theExporter==null) { if (theExporter==null) {
throw new RuntimeException("In ZUGFeRDExporterFromPDFA, source must always be loaded before other operations are performed."); throw new RuntimeException("In ZUGFeRDExporterFromPDFA, source must always be loaded before other operations are performed.");
} }
@@ -247,5 +249,14 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter {
public void export(OutputStream output) throws IOException { public void export(OutputStream output) throws IOException {
getExporter().export(output); getExporter().export(output);
} }
public void attachFile(FileAttachment file) {
theExporter.attachFile(file);
}
public void attachFile(String filename, byte[] data, String mimetype, String relation) {
theExporter.attachFile(filename, data, mimetype, relation);
}
} }

View File

@@ -104,7 +104,7 @@ public class ZUGFeRDImporter {
/*** /***
* return the file names of all files embedded into the PDF * return the file names of all files embedded into the PDF
* @see for XML embedded files please use ZUGFeRDInvoiceImporter.getFileAttachmentsXML * for XML embedded files please use ZUGFeRDInvoiceImporter.getFileAttachmentsXML
* @return a ArrayList of FileAttachments, empty if none * @return a ArrayList of FileAttachments, empty if none
*/ */
public List<FileAttachment> getFileAttachmentsPDF() { public List<FileAttachment> getFileAttachmentsPDF() {

View File

@@ -423,7 +423,7 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter {
/*** /***
* *
* @return the file attachments embedded in XML (using base64) decoded as byte array, * @return the file attachments embedded in XML (using base64) decoded as byte array,
* @see for PDF embedded files in FX use getFileAttachmentsPDF() * for PDF embedded files in FX use getFileAttachmentsPDF()
*/ */
public List<FileAttachment> getFileAttachmentsXML() { public List<FileAttachment> getFileAttachmentsXML() {
return fileAttachments; return fileAttachments;

View File

@@ -96,6 +96,7 @@ public class ZUGFeRDVisualizer {
private TransformerFactory mFactory = null; private TransformerFactory mFactory = null;
private Templates mXsltXRTemplate = null; private Templates mXsltXRTemplate = null;
private Templates mXsltUBLTemplate = null; private Templates mXsltUBLTemplate = null;
private Templates mXsltCIOTemplate = null;
private Templates mXsltHTMLTemplate = null; private Templates mXsltHTMLTemplate = null;
private Templates mXsltPDFTemplate = null; private Templates mXsltPDFTemplate = null;
private Templates mXsltZF1HTMLTemplate = null; private Templates mXsltZF1HTMLTemplate = null;
@@ -151,6 +152,8 @@ public class ZUGFeRDVisualizer {
String zf2Signature = "CrossIndustryInvoice"; String zf2Signature = "CrossIndustryInvoice";
String ublSignature = "Invoice"; String ublSignature = "Invoice";
String ublCreditNoteSignature = "CreditNote"; String ublCreditNoteSignature = "CreditNote";
String cioSignature = "SCRDMCCBDACIOMessageStructure" +
"";
boolean doPostProcessing = false; boolean doPostProcessing = false;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
@@ -173,6 +176,10 @@ public class ZUGFeRDVisualizer {
//zf2 or fx //zf2 or fx
applyUBLCreditNote2XSLT(fis, iaos); applyUBLCreditNote2XSLT(fis, iaos);
doPostProcessing = true; doPostProcessing = true;
} else if (root.getLocalName().equals(cioSignature)) {
//zf2 or fx
applyCIO2XSLT(fis, iaos);
doPostProcessing = true;
} else { } else {
throw new IllegalArgumentException("File does not look like CII or UBL"); throw new IllegalArgumentException("File does not look like CII or UBL");
} }
@@ -277,20 +284,6 @@ public class ZUGFeRDVisualizer {
} catch (FileNotFoundException | TransformerException e) { } catch (FileNotFoundException | TransformerException e) {
LOGGER.error("Failed to apply FOP", e); LOGGER.error("Failed to apply FOP", e);
} }
/*
FopConfParser parser = null;
try {
//parsing configuration
parser = new FopConfParser(CLASS_LOADER.getResourceAsStream("fop-config.xconf"), new URI("file:///"));
} catch (SAXException e) {
throw new UncheckedIOException(new IOException(e));
} catch (IOException e) {
throw new UncheckedIOException(e);
} catch (URISyntaxException e) {
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
}*/
// FopFactoryBuilder builder = parser.getFopFactoryBuilder();
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder(); DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
Configuration cfg = null; Configuration cfg = null;
@@ -351,6 +344,17 @@ public class ZUGFeRDVisualizer {
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream)); transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
} }
protected void applyCIO2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
throws TransformerException {
if (mXsltCIOTemplate == null) {
mXsltCIOTemplate = mFactory.newTemplates(
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/cio-xr.xsl")));
}
Transformer transformer = mXsltCIOTemplate.newTransformer();
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
}
protected void applyUBL2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream) protected void applyUBL2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
throws TransformerException { throws TransformerException {
if (mXsltUBLTemplate == null) { if (mXsltUBLTemplate == null) {

View File

@@ -30,5 +30,5 @@ public class TaxCategoryCodeTypeConstants {
public static final String UNTAXEDSERVICE = "O"; public static final String UNTAXEDSERVICE = "O";
public static final String INTRACOMMUNITY = "K"; public static final String INTRACOMMUNITY = "K";
public static Set<String> CATEGORY_CODES_WITH_EXEMPTION_REASON = Stream.of(INTRACOMMUNITY, REVERSECHARGE).collect(Collectors.toSet()); public static Set<String> CATEGORY_CODES_WITH_EXEMPTION_REASON = Stream.of(INTRACOMMUNITY, REVERSECHARGE, TAXEXEMPT).collect(Collectors.toSet());
} }

File diff suppressed because it is too large Load Diff

View File

@@ -36,7 +36,7 @@ public class DeSerializationTest extends TestCase {
public void testJackson() throws JsonProcessingException { public void testJackson() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
Invoice i = new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty("some org", "teststr", "55232", "teststadt", "DE").addTaxID("taxID")).setOwnVATID("DE0815").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("0185").addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal("1"), new BigDecimal(1.0))); Invoice i = new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty("some org", "teststr", "55232", "teststadt", "DE").addTaxID("taxID").addBankDetails(new BankDetails("DE3600000123456", "ABCDEFG1001").setAccountName("Donald Duck"))).setOwnVATID("DE0815").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("0185").addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal("1"), new BigDecimal(1.0)));
String jsonArray = mapper.writeValueAsString(i); String jsonArray = mapper.writeValueAsString(i);
// [{"stringValue":"a","intValue":1,"booleanValue":true}, // [{"stringValue":"a","intValue":1,"booleanValue":true},

View File

@@ -36,7 +36,8 @@ import java.util.Date;
*/ */
public class ProfilesMinimumBasicWLTest extends TestCase { public class ProfilesMinimumBasicWLTest extends TestCase {
final String TARGET_PDF_FX_MINIMUM = "./target/testout-Minimum.pdf"; final String TARGET_PDF_FX_MINIMUM_INV = "./target/testout-Minimum-INV.pdf";
final String TARGET_PDF_FX_MINIMUM_CN = "./target/testout-Minimum-CN.pdf";
public void testMinimumCreditNote() { public void testMinimumCreditNote() {
String ownNumber = "NUMFACTURE"; String ownNumber = "NUMFACTURE";
@@ -67,7 +68,7 @@ public class ProfilesMinimumBasicWLTest extends TestCase {
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(123), new BigDecimal(1))) .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(123), new BigDecimal(1)))
.setCreditNote(); .setCreditNote();
ze.setTransaction(i); ze.setTransaction(i);
ze.export(TARGET_PDF_FX_MINIMUM); ze.export(TARGET_PDF_FX_MINIMUM_CN);
// check for pdf-a schema extension // check for pdf-a schema extension
// assertFalse(pdfContent.indexOf("<zf:ConformanceLevel>EN 16931</zf:ConformanceLevel>") == -1); // assertFalse(pdfContent.indexOf("<zf:ConformanceLevel>EN 16931</zf:ConformanceLevel>") == -1);
@@ -79,7 +80,7 @@ public class ProfilesMinimumBasicWLTest extends TestCase {
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF_FX_MINIMUM); ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF_FX_MINIMUM_CN);
// Reading ZUGFeRD // Reading ZUGFeRD
assertEquals("146.37",zi.getAmount()); assertEquals("146.37",zi.getAmount());
@@ -121,7 +122,7 @@ public class ProfilesMinimumBasicWLTest extends TestCase {
.setNumber(ownNumber).setTotalPrepaidAmount(new BigDecimal("1")) .setNumber(ownNumber).setTotalPrepaidAmount(new BigDecimal("1"))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(123), new BigDecimal(1))); .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(123), new BigDecimal(1)));
ze.setTransaction(i); ze.setTransaction(i);
ze.export(TARGET_PDF_FX_MINIMUM); ze.export(TARGET_PDF_FX_MINIMUM_INV);
// check for pdf-a schema extension // check for pdf-a schema extension
// assertFalse(pdfContent.indexOf("<zf:ConformanceLevel>EN 16931</zf:ConformanceLevel>") == -1); // assertFalse(pdfContent.indexOf("<zf:ConformanceLevel>EN 16931</zf:ConformanceLevel>") == -1);
@@ -133,7 +134,7 @@ public class ProfilesMinimumBasicWLTest extends TestCase {
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF_FX_MINIMUM); ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF_FX_MINIMUM_INV);
// Reading ZUGFeRD // Reading ZUGFeRD
assertEquals("145.37",zi.getAmount()); assertEquals("145.37",zi.getAmount());

View File

@@ -60,7 +60,9 @@ public class ZF2PushTest extends TestCase {
final String TARGET_REVERSECHARGEPDF = "./target/testout-ZF2PushReverseCharge.pdf"; final String TARGET_REVERSECHARGEPDF = "./target/testout-ZF2PushReverseCharge.pdf";
public void testPushExport() { public void testPushExport() {
/***
* This writes to a filename like an official sample, please consider when changing (probably better not?)
*/
// the writing part // the writing part
String orgname = "Bei Spiel GmbH"; String orgname = "Bei Spiel GmbH";
String number = "RE-20201121/508"; String number = "RE-20201121/508";
@@ -92,10 +94,14 @@ public class ZF2PushTest extends TestCase {
fail("Exception should not be raised"); fail("Exception should not be raised");
} }
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF); ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF);
assertTrue(zi.getUTF8().contains("DE88200800000970375700")); //the iban assertTrue(zi.getUTF8().contains("DE88200800000970375700")); //the iban
assertTrue(zi.getUTF8().contains("Max Mustermann")); //account holder assertTrue(zi.getUTF8().contains("Max Mustermann")); //account holder
assertTrue(zi.getUTF8().contains("DueDateDateTime")); //account holder
assertTrue(zi.getUTF8().contains("20201212")); //account holder
assertTrue(zi.getUTF8().contains("<rsm:CrossIndustryInvoice")); assertTrue(zi.getUTF8().contains("<rsm:CrossIndustryInvoice"));
@@ -118,6 +124,8 @@ public class ZF2PushTest extends TestCase {
String orgname = "Test company"; String orgname = "Test company";
String number = "123"; String number = "123";
String priceStr = "1.00"; String priceStr = "1.00";
String senderDescription = "Kleinunternehmer";
String taxID = "9990815"; String taxID = "9990815";
BigDecimal price = new BigDecimal(priceStr); BigDecimal price = new BigDecimal(priceStr);
try { try {
@@ -132,11 +140,11 @@ public class ZF2PushTest extends TestCase {
ze.attachFile("one.pdf", b, "application/pdf", "Alternative"); ze.attachFile("one.pdf", b, "application/pdf", "Alternative");
ze.attachFile("two.pdf", b, "application/pdf", "Alternative"); ze.attachFile("two.pdf", b, "application/pdf", "Alternative");
ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()) ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date())
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID(taxID).addVATID("DE0815")) .setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID(taxID).addVATID("DE0815").setDescription(senderDescription))
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE4711") .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"))) .setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE")))
.setNumber(number) .setNumber(number)
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), 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)))
); );
String theXML = new String(ze.getProvider().getXML()); String theXML = new String(ze.getProvider().getXML());
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice")); assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
@@ -144,6 +152,16 @@ public class ZF2PushTest extends TestCase {
} catch (IOException e) { } catch (IOException e) {
fail("IOException should not be raised"); fail("IOException should not be raised");
} }
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(TARGET_ATTACHMENTSPDF);
Invoice i= null;
try {
i = zii.extractInvoice();
} catch (XPathExpressionException e) {
throw new RuntimeException(e);
} catch (ParseException e) {
throw new RuntimeException(e);
}
assertEquals(senderDescription,i.getSender().getDescription());
// now check the contents (like MustangReaderTest) // now check the contents (like MustangReaderTest)
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_ATTACHMENTSPDF); ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_ATTACHMENTSPDF);
@@ -152,7 +170,7 @@ public class ZF2PushTest extends TestCase {
assertTrue(zi.getUTF8().contains(taxID)); assertTrue(zi.getUTF8().contains(taxID));
// Reading ZUGFeRD // Reading ZUGFeRD
assertEquals("1.19", zi.getAmount()); assertEquals("1.00", zi.getAmount());
assertEquals(orgname, zi.getHolder()); assertEquals(orgname, zi.getHolder());
assertEquals(number, zi.getForeignReference()); assertEquals(number, zi.getForeignReference());
try { try {

View File

@@ -0,0 +1,815 @@
<!--Sample file Order-x.xml - COMFORT Profile, created by Cyrille Sautereau, Admarel-->
<rsm:SCRDMCCBDACIOMessageStructure
xmlns:rsm="urn:un:unece:uncefact:data:SCRDMCCBDACIOMessageStructure:100"
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:128"
xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:128"
xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:128"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<rsm:ExchangedDocumentContext>
<ram:TestIndicator>
<udt:Indicator>false</udt:Indicator>
</ram:TestIndicator>
<ram:BusinessProcessSpecifiedDocumentContextParameter>
<ram:ID>A1</ram:ID>
</ram:BusinessProcessSpecifiedDocumentContextParameter>
<ram:GuidelineSpecifiedDocumentContextParameter>
<ram:ID>urn:order-x.eu:1p0:comfort</ram:ID>
</ram:GuidelineSpecifiedDocumentContextParameter>
</rsm:ExchangedDocumentContext>
<rsm:ExchangedDocument>
<ram:ID>PO123456789</ram:ID>
<ram:Name>Doc Name</ram:Name>
<ram:TypeCode>220</ram:TypeCode>
<ram:IssueDateTime>
<udt:DateTimeString format="203">202003311232</udt:DateTimeString>
</ram:IssueDateTime>
<ram:CopyIndicator>
<udt:Indicator>false</udt:Indicator>
</ram:CopyIndicator>
<ram:PurposeCode>9</ram:PurposeCode>
<ram:RequestedResponseTypeCode>AC</ram:RequestedResponseTypeCode>
<ram:IncludedNote>
<ram:Content>Content of Note</ram:Content>
<ram:SubjectCode>AAI</ram:SubjectCode>
</ram:IncludedNote>
<ram:EffectiveSpecifiedPeriod>
<ram:StartDateTime>
<udt:DateTimeString format="102">20200331</udt:DateTimeString>
</ram:StartDateTime>
<ram:EndDateTime>
<udt:DateTimeString format="102">20200630</udt:DateTimeString>
</ram:EndDateTime>
</ram:EffectiveSpecifiedPeriod>
</rsm:ExchangedDocument>
<rsm:SupplyChainTradeTransaction>
<ram:IncludedSupplyChainTradeLineItem>
<ram:AssociatedDocumentLineDocument>
<ram:LineID>1</ram:LineID>
<ram:IncludedNote>
<ram:Content>WEEE Tax of 0,50 euros per item included</ram:Content>
<ram:SubjectCode>TXD</ram:SubjectCode>
</ram:IncludedNote>
</ram:AssociatedDocumentLineDocument>
<ram:SpecifiedTradeProduct>
<ram:GlobalID schemeID="0160">1234567890123</ram:GlobalID>
<ram:SellerAssignedID>987654321</ram:SellerAssignedID>
<ram:BuyerAssignedID>654987321</ram:BuyerAssignedID>
<ram:Name>Product Name</ram:Name>
<ram:Description>Product Description</ram:Description>
<ram:BatchID>Product Batch ID (lot ID)</ram:BatchID>
<ram:BrandName>Product Brand Name</ram:BrandName>
<ram:ApplicableProductCharacteristic>
<ram:TypeCode>Characteristic_Code</ram:TypeCode>
<ram:Description>Characteristic Description</ram:Description>
<ram:Value>5 meters</ram:Value>
</ram:ApplicableProductCharacteristic>
<ram:DesignatedProductClassification>
<ram:ClassCode listID="TST">Class_code</ram:ClassCode>
<ram:ClassName>Name Class Codification</ram:ClassName>
</ram:DesignatedProductClassification>
<ram:IndividualTradeProductInstance>
<ram:BatchID>Product Instances Batch ID</ram:BatchID>
<ram:SerialID>Product Instances Supplier Serial ID</ram:SerialID>
</ram:IndividualTradeProductInstance>
<ram:ApplicableSupplyChainPackaging>
<ram:TypeCode>7B</ram:TypeCode>
<ram:LinearSpatialDimension>
<ram:WidthMeasure unitCode="MTR">5</ram:WidthMeasure>
<ram:LengthMeasure unitCode="MTR">3</ram:LengthMeasure>
<ram:HeightMeasure unitCode="MTR">1</ram:HeightMeasure>
</ram:LinearSpatialDimension>
</ram:ApplicableSupplyChainPackaging>
<ram:OriginTradeCountry>
<ram:ID>FR</ram:ID>
</ram:OriginTradeCountry>
<ram:AdditionalReferenceReferencedDocument>
<ram:IssuerAssignedID>ADD_REF_PROD_ID</ram:IssuerAssignedID>
<ram:URIID>ADD_REF_PROD_URIID</ram:URIID>
<ram:TypeCode>6</ram:TypeCode>
<ram:Name>ADD_REF_PROD_Desc</ram:Name>
</ram:AdditionalReferenceReferencedDocument>
</ram:SpecifiedTradeProduct>
<ram:SpecifiedLineTradeAgreement>
<ram:BuyerOrderReferencedDocument>
<ram:LineID>1</ram:LineID>
</ram:BuyerOrderReferencedDocument>
<ram:QuotationReferencedDocument>
<ram:IssuerAssignedID>QUOT_125487</ram:IssuerAssignedID>
<ram:LineID>3</ram:LineID>
</ram:QuotationReferencedDocument>
<ram:AdditionalReferencedDocument>
<ram:IssuerAssignedID>ADD_REF_DOC_ID</ram:IssuerAssignedID>
<ram:URIID>ADD_REF_DOC_URIID</ram:URIID>
<ram:LineID>5</ram:LineID>
<ram:TypeCode>916</ram:TypeCode>
<ram:Name>ADD_REF_DOC_Desc</ram:Name>
</ram:AdditionalReferencedDocument>
<ram:AdditionalReferencedDocument>
<ram:IssuerAssignedID>OBJECT_125487</ram:IssuerAssignedID>
<ram:TypeCode>130</ram:TypeCode>
<ram:ReferenceTypeCode>AWV</ram:ReferenceTypeCode>
</ram:AdditionalReferencedDocument>
<ram:GrossPriceProductTradePrice>
<ram:ChargeAmount>10.50</ram:ChargeAmount>
<ram:BasisQuantity unitCode="C62">1.00</ram:BasisQuantity>
<ram:AppliedTradeAllowanceCharge>
<ram:ChargeIndicator>
<udt:Indicator>false</udt:Indicator>
</ram:ChargeIndicator>
<ram:ActualAmount>1.00</ram:ActualAmount>
<ram:ReasonCode>95</ram:ReasonCode>
<ram:Reason>DISCOUNT</ram:Reason>
</ram:AppliedTradeAllowanceCharge>
<ram:AppliedTradeAllowanceCharge>
<ram:ChargeIndicator>
<udt:Indicator>true</udt:Indicator>
</ram:ChargeIndicator>
<ram:ActualAmount>0.50</ram:ActualAmount>
<ram:ReasonCode>AEW</ram:ReasonCode>
<ram:Reason>WEEE</ram:Reason>
</ram:AppliedTradeAllowanceCharge>
</ram:GrossPriceProductTradePrice>
<ram:NetPriceProductTradePrice>
<ram:ChargeAmount>10.00</ram:ChargeAmount>
<ram:BasisQuantity unitCode="C62">1.00</ram:BasisQuantity>
</ram:NetPriceProductTradePrice>
<ram:CatalogueReferencedDocument>
<ram:IssuerAssignedID>CATALOG_REF_ID</ram:IssuerAssignedID>
<ram:LineID>2</ram:LineID>
</ram:CatalogueReferencedDocument>
<ram:BlanketOrderReferencedDocument>
<ram:LineID>2</ram:LineID>
</ram:BlanketOrderReferencedDocument>
</ram:SpecifiedLineTradeAgreement>
<ram:SpecifiedLineTradeDelivery>
<ram:PartialDeliveryAllowedIndicator>
<udt:Indicator>true</udt:Indicator>
</ram:PartialDeliveryAllowedIndicator>
<ram:RequestedQuantity unitCode="C62">6</ram:RequestedQuantity>
<ram:PackageQuantity unitCode="C62">3</ram:PackageQuantity>
<ram:PerPackageUnitQuantity unitCode="C62">2</ram:PerPackageUnitQuantity>
<ram:RequestedDeliverySupplyChainEvent>
<ram:OccurrenceSpecifiedPeriod>
<ram:StartDateTime>
<udt:DateTimeString format="203">202004150900</udt:DateTimeString>
</ram:StartDateTime>
<ram:EndDateTime>
<udt:DateTimeString format="203">202004301800</udt:DateTimeString>
</ram:EndDateTime>
</ram:OccurrenceSpecifiedPeriod>
</ram:RequestedDeliverySupplyChainEvent>
</ram:SpecifiedLineTradeDelivery>
<ram:SpecifiedLineTradeSettlement>
<ram:ApplicableTradeTax>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>20.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:SpecifiedTradeAllowanceCharge>
<ram:ChargeIndicator>
<udt:Indicator>false</udt:Indicator>
</ram:ChargeIndicator>
<ram:CalculationPercent>10.00</ram:CalculationPercent>
<ram:BasisAmount>60.00</ram:BasisAmount>
<ram:ActualAmount>6.00</ram:ActualAmount>
<ram:ReasonCode>64</ram:ReasonCode>
<ram:Reason>SPECIAL AGREEMENT</ram:Reason>
</ram:SpecifiedTradeAllowanceCharge>
<ram:SpecifiedTradeAllowanceCharge>
<ram:ChargeIndicator>
<udt:Indicator>true</udt:Indicator>
</ram:ChargeIndicator>
<ram:CalculationPercent>10.00</ram:CalculationPercent>
<ram:BasisAmount>60.00</ram:BasisAmount>
<ram:ActualAmount>6.00</ram:ActualAmount>
<ram:ReasonCode>FC</ram:ReasonCode>
<ram:Reason>FREIGHT SERVICES</ram:Reason>
</ram:SpecifiedTradeAllowanceCharge>
<ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:LineTotalAmount>60.00</ram:LineTotalAmount>
</ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:ReceivableSpecifiedTradeAccountingAccount>
<ram:ID>BUYER_ACCOUNTING_REF</ram:ID>
</ram:ReceivableSpecifiedTradeAccountingAccount>
</ram:SpecifiedLineTradeSettlement>
</ram:IncludedSupplyChainTradeLineItem>
<ram:IncludedSupplyChainTradeLineItem>
<ram:AssociatedDocumentLineDocument>
<ram:LineID>2</ram:LineID>
<ram:IncludedNote>
<ram:Content>WEEE Tax of 0,50 euros per item included</ram:Content>
<ram:SubjectCode>TXD</ram:SubjectCode>
</ram:IncludedNote>
</ram:AssociatedDocumentLineDocument>
<ram:SpecifiedTradeProduct>
<ram:GlobalID schemeID="0160">548796523</ram:GlobalID>
<ram:SellerAssignedID>598632147</ram:SellerAssignedID>
<ram:BuyerAssignedID>698569856</ram:BuyerAssignedID>
<ram:Name>Product Name</ram:Name>
<ram:Description>Product Description</ram:Description>
<ram:BatchID>Product Batch ID (lot ID)</ram:BatchID>
<ram:BrandName>Product Brand Name</ram:BrandName>
<ram:ApplicableProductCharacteristic>
<ram:TypeCode>Characteristic_Code</ram:TypeCode>
<ram:Description>Characteristic Description</ram:Description>
<ram:Value>3 meters</ram:Value>
</ram:ApplicableProductCharacteristic>
<ram:DesignatedProductClassification>
<ram:ClassCode listID="TST">Class_code</ram:ClassCode>
<ram:ClassName>Name Class Codification</ram:ClassName>
</ram:DesignatedProductClassification>
<ram:IndividualTradeProductInstance>
<ram:BatchID>Product Instances Batch ID</ram:BatchID>
<ram:SerialID>Product Instances Supplier Serial ID</ram:SerialID>
</ram:IndividualTradeProductInstance>
<ram:ApplicableSupplyChainPackaging>
<ram:TypeCode>7B</ram:TypeCode>
<ram:LinearSpatialDimension>
<ram:WidthMeasure unitCode="MTR">2</ram:WidthMeasure>
<ram:LengthMeasure unitCode="MTR">1</ram:LengthMeasure>
<ram:HeightMeasure unitCode="MTR">3</ram:HeightMeasure>
</ram:LinearSpatialDimension>
</ram:ApplicableSupplyChainPackaging>
<ram:OriginTradeCountry>
<ram:ID>FR</ram:ID>
</ram:OriginTradeCountry>
<ram:AdditionalReferenceReferencedDocument>
<ram:IssuerAssignedID>ADD_REF_PROD_ID</ram:IssuerAssignedID>
<ram:URIID>ADD_REF_PROD_URIID</ram:URIID>
<ram:TypeCode>6</ram:TypeCode>
<ram:Name>ADD_REF_PROD_Desc</ram:Name>
</ram:AdditionalReferenceReferencedDocument>
</ram:SpecifiedTradeProduct>
<ram:SpecifiedLineTradeAgreement>
<ram:BuyerOrderReferencedDocument>
<ram:LineID>3</ram:LineID>
</ram:BuyerOrderReferencedDocument>
<ram:QuotationReferencedDocument>
<ram:IssuerAssignedID>QUOT_125487</ram:IssuerAssignedID>
<ram:LineID>2</ram:LineID>
</ram:QuotationReferencedDocument>
<ram:AdditionalReferencedDocument>
<ram:IssuerAssignedID>ADD_REF_DOC_ID</ram:IssuerAssignedID>
<ram:URIID>ADD_REF_DOC_URIID</ram:URIID>
<ram:LineID>5</ram:LineID>
<ram:TypeCode>916</ram:TypeCode>
<ram:Name>ADD_REF_DOC_Desc</ram:Name>
</ram:AdditionalReferencedDocument>
<ram:AdditionalReferencedDocument>
<ram:IssuerAssignedID>OBJECT_125487</ram:IssuerAssignedID>
<ram:TypeCode>130</ram:TypeCode>
<ram:ReferenceTypeCode>AWV</ram:ReferenceTypeCode>
</ram:AdditionalReferencedDocument>
<ram:GrossPriceProductTradePrice>
<ram:ChargeAmount>19.50</ram:ChargeAmount>
<ram:BasisQuantity unitCode="C62">2</ram:BasisQuantity>
<ram:AppliedTradeAllowanceCharge>
<ram:ChargeIndicator>
<udt:Indicator>true</udt:Indicator>
</ram:ChargeIndicator>
<ram:ActualAmount>0.50</ram:ActualAmount>
<ram:ReasonCode>AEW</ram:ReasonCode>
<ram:Reason>WEEE TAX</ram:Reason>
</ram:AppliedTradeAllowanceCharge>
</ram:GrossPriceProductTradePrice>
<ram:NetPriceProductTradePrice>
<ram:ChargeAmount>20.00</ram:ChargeAmount>
<ram:BasisQuantity unitCode="C62">2</ram:BasisQuantity>
</ram:NetPriceProductTradePrice>
<ram:CatalogueReferencedDocument>
<ram:IssuerAssignedID>CATALOG_REF_ID</ram:IssuerAssignedID>
<ram:LineID>2</ram:LineID>
</ram:CatalogueReferencedDocument>
<ram:BlanketOrderReferencedDocument>
<ram:LineID>3</ram:LineID>
</ram:BlanketOrderReferencedDocument>
</ram:SpecifiedLineTradeAgreement>
<ram:SpecifiedLineTradeDelivery>
<ram:PartialDeliveryAllowedIndicator>
<udt:Indicator>true</udt:Indicator>
</ram:PartialDeliveryAllowedIndicator>
<ram:RequestedQuantity unitCode="C62">10.00</ram:RequestedQuantity>
<ram:PackageQuantity unitCode="C62">5</ram:PackageQuantity>
<ram:PerPackageUnitQuantity unitCode="C62">2</ram:PerPackageUnitQuantity>
<ram:RequestedDeliverySupplyChainEvent>
<ram:OccurrenceDateTime>
<udt:DateTimeString format="102">20200415</udt:DateTimeString>
</ram:OccurrenceDateTime>
</ram:RequestedDeliverySupplyChainEvent>
</ram:SpecifiedLineTradeDelivery>
<ram:SpecifiedLineTradeSettlement>
<ram:ApplicableTradeTax>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>20.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:SpecifiedTradeAllowanceCharge>
<ram:ChargeIndicator>
<udt:Indicator>false</udt:Indicator>
</ram:ChargeIndicator>
<ram:CalculationPercent>1.00</ram:CalculationPercent>
<ram:BasisAmount>100.00</ram:BasisAmount>
<ram:ActualAmount>1.00</ram:ActualAmount>
<ram:ReasonCode>64</ram:ReasonCode>
<ram:Reason>SPECIAL AGREEMENT</ram:Reason>
</ram:SpecifiedTradeAllowanceCharge>
<ram:SpecifiedTradeAllowanceCharge>
<ram:ChargeIndicator>
<udt:Indicator>true</udt:Indicator>
</ram:ChargeIndicator>
<ram:CalculationPercent>1.00</ram:CalculationPercent>
<ram:BasisAmount>100.00</ram:BasisAmount>
<ram:ActualAmount>1.00</ram:ActualAmount>
<ram:ReasonCode>FC</ram:ReasonCode>
<ram:Reason>FREIGHT SERVICES</ram:Reason>
</ram:SpecifiedTradeAllowanceCharge>
<ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:LineTotalAmount>100.00</ram:LineTotalAmount>
</ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:ReceivableSpecifiedTradeAccountingAccount>
<ram:ID>BUYER_ACCOUNTING_REF</ram:ID>
</ram:ReceivableSpecifiedTradeAccountingAccount>
</ram:SpecifiedLineTradeSettlement>
</ram:IncludedSupplyChainTradeLineItem>
<ram:IncludedSupplyChainTradeLineItem>
<ram:AssociatedDocumentLineDocument>
<ram:LineID>3</ram:LineID>
<ram:IncludedNote>
<ram:Content>Content of Note</ram:Content>
<ram:SubjectCode>AAI</ram:SubjectCode>
</ram:IncludedNote>
</ram:AssociatedDocumentLineDocument>
<ram:SpecifiedTradeProduct>
<ram:GlobalID schemeID="0160">854721548</ram:GlobalID>
<ram:SellerAssignedID>698325417</ram:SellerAssignedID>
<ram:BuyerAssignedID>598674321</ram:BuyerAssignedID>
<ram:Name>Product Name</ram:Name>
<ram:Description>Product Description</ram:Description>
<ram:BatchID>Product Batch ID (lot ID)</ram:BatchID>
<ram:BrandName>Product Brand Name</ram:BrandName>
<ram:ApplicableProductCharacteristic>
<ram:TypeCode>Characteristic_Code</ram:TypeCode>
<ram:Description>Characteristic Description</ram:Description>
<ram:Value>3 meters</ram:Value>
</ram:ApplicableProductCharacteristic>
<ram:DesignatedProductClassification>
<ram:ClassCode listID="TST">Class_code</ram:ClassCode>
<ram:ClassName>Name Class Codification</ram:ClassName>
</ram:DesignatedProductClassification>
<ram:IndividualTradeProductInstance>
<ram:BatchID>Product Instances Batch ID</ram:BatchID>
<ram:SerialID>Product Instances Supplier Serial ID</ram:SerialID>
</ram:IndividualTradeProductInstance>
<ram:ApplicableSupplyChainPackaging>
<ram:TypeCode>7B</ram:TypeCode>
<ram:LinearSpatialDimension>
<ram:WidthMeasure unitCode="MTR">2</ram:WidthMeasure>
<ram:LengthMeasure unitCode="MTR">1</ram:LengthMeasure>
<ram:HeightMeasure unitCode="MTR">3</ram:HeightMeasure>
</ram:LinearSpatialDimension>
</ram:ApplicableSupplyChainPackaging>
<ram:OriginTradeCountry>
<ram:ID>FR</ram:ID>
</ram:OriginTradeCountry>
<ram:AdditionalReferenceReferencedDocument>
<ram:IssuerAssignedID>ADD_REF_PROD_ID</ram:IssuerAssignedID>
<ram:URIID>ADD_REF_PROD_URIID</ram:URIID>
<ram:TypeCode>6</ram:TypeCode>
<ram:Name>ADD_REF_PROD_Desc</ram:Name>
</ram:AdditionalReferenceReferencedDocument>
</ram:SpecifiedTradeProduct>
<ram:SpecifiedLineTradeAgreement>
<ram:BuyerOrderReferencedDocument>
<ram:LineID>4</ram:LineID>
</ram:BuyerOrderReferencedDocument>
<ram:QuotationReferencedDocument>
<ram:IssuerAssignedID>QUOT_125487</ram:IssuerAssignedID>
<ram:LineID>1</ram:LineID>
</ram:QuotationReferencedDocument>
<ram:AdditionalReferencedDocument>
<ram:IssuerAssignedID>ADD_REF_DOC_ID</ram:IssuerAssignedID>
<ram:URIID>ADD_REF_DOC_URIID</ram:URIID>
<ram:LineID>5</ram:LineID>
<ram:TypeCode>916</ram:TypeCode>
<ram:Name>ADD_REF_DOC_Desc</ram:Name>
</ram:AdditionalReferencedDocument>
<ram:AdditionalReferencedDocument>
<ram:IssuerAssignedID>OBJECT_125487</ram:IssuerAssignedID>
<ram:TypeCode>130</ram:TypeCode>
<ram:ReferenceTypeCode>AWV</ram:ReferenceTypeCode>
</ram:AdditionalReferencedDocument>
<ram:GrossPriceProductTradePrice>
<ram:ChargeAmount>30</ram:ChargeAmount>
<ram:BasisQuantity unitCode="C62">1</ram:BasisQuantity>
<ram:AppliedTradeAllowanceCharge>
<ram:ChargeIndicator>
<udt:Indicator>false</udt:Indicator>
</ram:ChargeIndicator>
<ram:ActualAmount>5</ram:ActualAmount>
</ram:AppliedTradeAllowanceCharge>
</ram:GrossPriceProductTradePrice>
<ram:NetPriceProductTradePrice>
<ram:ChargeAmount>25</ram:ChargeAmount>
<ram:BasisQuantity unitCode="C62">1</ram:BasisQuantity>
</ram:NetPriceProductTradePrice>
<ram:CatalogueReferencedDocument>
<ram:IssuerAssignedID>CATALOG_REF_ID</ram:IssuerAssignedID>
<ram:LineID>5</ram:LineID>
</ram:CatalogueReferencedDocument>
<ram:BlanketOrderReferencedDocument>
<ram:LineID>4</ram:LineID>
</ram:BlanketOrderReferencedDocument>
</ram:SpecifiedLineTradeAgreement>
<ram:SpecifiedLineTradeDelivery>
<ram:PartialDeliveryAllowedIndicator>
<udt:Indicator>true</udt:Indicator>
</ram:PartialDeliveryAllowedIndicator>
<ram:RequestedQuantity unitCode="C62">6</ram:RequestedQuantity>
<ram:PackageQuantity unitCode="C62">3</ram:PackageQuantity>
<ram:PerPackageUnitQuantity unitCode="C62">2</ram:PerPackageUnitQuantity>
<ram:RequestedDeliverySupplyChainEvent>
<ram:OccurrenceSpecifiedPeriod>
<ram:StartDateTime>
<udt:DateTimeString format="102">20200415</udt:DateTimeString>
</ram:StartDateTime>
<ram:EndDateTime>
<udt:DateTimeString format="102">20200430</udt:DateTimeString>
</ram:EndDateTime>
</ram:OccurrenceSpecifiedPeriod>
</ram:RequestedDeliverySupplyChainEvent>
</ram:SpecifiedLineTradeDelivery>
<ram:SpecifiedLineTradeSettlement>
<ram:ApplicableTradeTax>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>20.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:SpecifiedTradeAllowanceCharge>
<ram:ChargeIndicator>
<udt:Indicator>false</udt:Indicator>
</ram:ChargeIndicator>
<ram:CalculationPercent>10.00</ram:CalculationPercent>
<ram:BasisAmount>150.00</ram:BasisAmount>
<ram:ActualAmount>15.00</ram:ActualAmount>
<ram:ReasonCode>64</ram:ReasonCode>
<ram:Reason>SPECIAL AGREEMENT</ram:Reason>
</ram:SpecifiedTradeAllowanceCharge>
<ram:SpecifiedTradeAllowanceCharge>
<ram:ChargeIndicator>
<udt:Indicator>true</udt:Indicator>
</ram:ChargeIndicator>
<ram:CalculationPercent>10.00</ram:CalculationPercent>
<ram:BasisAmount>150.00</ram:BasisAmount>
<ram:ActualAmount>15.00</ram:ActualAmount>
<ram:ReasonCode>FC</ram:ReasonCode>
<ram:Reason>FREIGHT SERVICES</ram:Reason>
</ram:SpecifiedTradeAllowanceCharge>
<ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:LineTotalAmount>150.00</ram:LineTotalAmount>
</ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:ReceivableSpecifiedTradeAccountingAccount>
<ram:ID>BUYER_ACCOUNTING_REF</ram:ID>
</ram:ReceivableSpecifiedTradeAccountingAccount>
</ram:SpecifiedLineTradeSettlement>
</ram:IncludedSupplyChainTradeLineItem>
<ram:ApplicableHeaderTradeAgreement>
<ram:BuyerReference>BUYER_REF_BU123</ram:BuyerReference>
<ram:SellerTradeParty>
<ram:ID>SUPPLIER_ID_321654</ram:ID>
<ram:GlobalID schemeID="0088">123654879</ram:GlobalID>
<ram:Name>SELLER_NAME</ram:Name>
<ram:Description>SELLER_ADD_LEGAL_INFORMATION</ram:Description>
<ram:SpecifiedLegalOrganization>
<ram:ID schemeID="0002">123456789</ram:ID>
<ram:TradingBusinessName>SELLER_TRADING_NAME</ram:TradingBusinessName>
</ram:SpecifiedLegalOrganization>
<ram:DefinedTradeContact>
<ram:PersonName>SELLER_CONTACT_NAME</ram:PersonName>
<ram:DepartmentName>SELLER_CONTACT_DEP</ram:DepartmentName>
<ram:TypeCode>SR</ram:TypeCode>
<ram:TelephoneUniversalCommunication>
<ram:CompleteNumber>+33 6 25 64 98 75</ram:CompleteNumber>
</ram:TelephoneUniversalCommunication>
<ram:EmailURIUniversalCommunication>
<ram:URIID>contact@seller.com</ram:URIID>
</ram:EmailURIUniversalCommunication>
</ram:DefinedTradeContact>
<ram:PostalTradeAddress>
<ram:PostcodeCode>75001</ram:PostcodeCode>
<ram:LineOne>SELLER_ADDR_1</ram:LineOne>
<ram:LineTwo>SELLER_ADDR_2</ram:LineTwo>
<ram:LineThree>SELLER_ADDR_3</ram:LineThree>
<ram:CityName>SELLER_CITY</ram:CityName>
<ram:CountryID>FR</ram:CountryID>
</ram:PostalTradeAddress>
<ram:URIUniversalCommunication>
<ram:URIID schemeID="EM">sales@seller.com</ram:URIID>
</ram:URIUniversalCommunication>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">FR 32 123 456 789</ram:ID>
</ram:SpecifiedTaxRegistration>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="FC">SELLER_TAX_ID</ram:ID>
</ram:SpecifiedTaxRegistration>
</ram:SellerTradeParty>
<ram:BuyerTradeParty>
<ram:ID>BY_ID_9587456</ram:ID>
<ram:GlobalID schemeID="0088">98765432179</ram:GlobalID>
<ram:Name>BUYER_NAME</ram:Name>
<ram:SpecifiedLegalOrganization>
<ram:ID schemeID="0002">987654321</ram:ID>
<ram:TradingBusinessName>BUYER_TRADING_NAME</ram:TradingBusinessName>
</ram:SpecifiedLegalOrganization>
<ram:DefinedTradeContact>
<ram:PersonName>BUYER_CONTACT_NAME</ram:PersonName>
<ram:DepartmentName>BUYER_CONTACT_DEP</ram:DepartmentName>
<ram:TypeCode>LB</ram:TypeCode>
<ram:TelephoneUniversalCommunication>
<ram:CompleteNumber>+33 6 65 98 75 32</ram:CompleteNumber>
</ram:TelephoneUniversalCommunication>
<ram:EmailURIUniversalCommunication>
<ram:URIID>contact@buyer.com</ram:URIID>
</ram:EmailURIUniversalCommunication>
</ram:DefinedTradeContact>
<ram:PostalTradeAddress>
<ram:PostcodeCode>69001</ram:PostcodeCode>
<ram:LineOne>BUYER_ADDR_1</ram:LineOne>
<ram:LineTwo>BUYER_ADDR_2</ram:LineTwo>
<ram:LineThree>BUYER_ADDR_3</ram:LineThree>
<ram:CityName>BUYER_CITY</ram:CityName>
<ram:CountryID>FR</ram:CountryID>
</ram:PostalTradeAddress>
<ram:URIUniversalCommunication>
<ram:URIID schemeID="EM">operation@buyer.com</ram:URIID>
</ram:URIUniversalCommunication>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">FR 05 987 654 321</ram:ID>
</ram:SpecifiedTaxRegistration>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="FC">BUYER_TAX_ID</ram:ID>
</ram:SpecifiedTaxRegistration>
</ram:BuyerTradeParty>
<ram:BuyerRequisitionerTradeParty>
<ram:ID>BUYER_REQ_ID_25987</ram:ID>
<ram:GlobalID schemeID="0088">654987321</ram:GlobalID>
<ram:Name>BUYER_REQ_NAME</ram:Name>
<ram:SpecifiedLegalOrganization>
<ram:ID schemeID="0002">654987321</ram:ID>
<ram:TradingBusinessName>BUYER_REQ_TRADING_NAME</ram:TradingBusinessName>
</ram:SpecifiedLegalOrganization>
<ram:DefinedTradeContact>
<ram:PersonName>BUYER_REQ_CONTACT_NAME</ram:PersonName>
<ram:DepartmentName>BUYER_REQ_CONTACT_DEP</ram:DepartmentName>
<ram:TypeCode>PD</ram:TypeCode>
<ram:TelephoneUniversalCommunication>
<ram:CompleteNumber>+33 6 54 98 65 32</ram:CompleteNumber>
</ram:TelephoneUniversalCommunication>
<ram:EmailURIUniversalCommunication>
<ram:URIID>requisitioner@buyer.com</ram:URIID>
</ram:EmailURIUniversalCommunication>
</ram:DefinedTradeContact>
<ram:PostalTradeAddress>
<ram:PostcodeCode>69001</ram:PostcodeCode>
<ram:LineOne>BUYER_REQ_ADDR_1</ram:LineOne>
<ram:LineTwo>BUYER_REQ_ADDR_2</ram:LineTwo>
<ram:LineThree>BUYER_REQ_ADDR_3</ram:LineThree>
<ram:CityName>BUYER_REQ_CITY</ram:CityName>
<ram:CountryID>FR</ram:CountryID>
</ram:PostalTradeAddress>
<ram:URIUniversalCommunication>
<ram:URIID schemeID="EM">purchase@buyer.com</ram:URIID>
</ram:URIUniversalCommunication>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">FR 92 654 987 321</ram:ID>
</ram:SpecifiedTaxRegistration>
</ram:BuyerRequisitionerTradeParty>
<ram:ApplicableTradeDeliveryTerms>
<ram:DeliveryTypeCode>FCA</ram:DeliveryTypeCode>
<ram:Description>Free Carrier</ram:Description>
<ram:FunctionCode>7</ram:FunctionCode>
<ram:RelevantTradeLocation>
<ram:ID>DEL_TERMS_LOC_ID</ram:ID>
<ram:Name>DEL_TERMS_LOC_Name</ram:Name>
</ram:RelevantTradeLocation>
</ram:ApplicableTradeDeliveryTerms>
<ram:SellerOrderReferencedDocument>
<ram:IssuerAssignedID>SALES_REF_ID_459875</ram:IssuerAssignedID>
</ram:SellerOrderReferencedDocument>
<ram:BuyerOrderReferencedDocument>
<ram:IssuerAssignedID>PO123456789</ram:IssuerAssignedID>
</ram:BuyerOrderReferencedDocument>
<ram:QuotationReferencedDocument>
<ram:IssuerAssignedID>QUOT_125487</ram:IssuerAssignedID>
</ram:QuotationReferencedDocument>
<ram:ContractReferencedDocument>
<ram:IssuerAssignedID>CONTRACT_2020-25987</ram:IssuerAssignedID>
</ram:ContractReferencedDocument>
<ram:RequisitionReferencedDocument>
<ram:IssuerAssignedID>REQ_875498</ram:IssuerAssignedID>
</ram:RequisitionReferencedDocument>
<ram:AdditionalReferencedDocument>
<ram:IssuerAssignedID>ADD_REF_DOC_ID</ram:IssuerAssignedID>
<ram:URIID>ADD_REF_DOC_URIID</ram:URIID>
<ram:TypeCode>916</ram:TypeCode>
<ram:Name>ADD_REF_DOC_Desc</ram:Name>
</ram:AdditionalReferencedDocument>
<ram:AdditionalReferencedDocument>
<ram:IssuerAssignedID>TENDER_ID</ram:IssuerAssignedID>
<ram:TypeCode>50</ram:TypeCode>
</ram:AdditionalReferencedDocument>
<ram:AdditionalReferencedDocument>
<ram:IssuerAssignedID>OBJECT_ID</ram:IssuerAssignedID>
<ram:TypeCode>130</ram:TypeCode>
<ram:ReferenceTypeCode>AWV</ram:ReferenceTypeCode>
</ram:AdditionalReferencedDocument>
<ram:CatalogueReferencedDocument>
<ram:IssuerAssignedID>CATALOG_ID</ram:IssuerAssignedID>
</ram:CatalogueReferencedDocument>
<ram:BlanketOrderReferencedDocument>
<ram:IssuerAssignedID>BLANKET_ORDER_ID</ram:IssuerAssignedID>
</ram:BlanketOrderReferencedDocument>
<ram:PreviousOrderChangeReferencedDocument>
<ram:IssuerAssignedID>PREV_ORDER_C_ID</ram:IssuerAssignedID>
</ram:PreviousOrderChangeReferencedDocument>
<ram:PreviousOrderResponseReferencedDocument>
<ram:IssuerAssignedID>PREV_ORDER_R_ID</ram:IssuerAssignedID>
</ram:PreviousOrderResponseReferencedDocument>
<ram:SpecifiedProcuringProject>
<ram:ID>PROJECT_ID</ram:ID>
<ram:Name>Project Reference</ram:Name>
</ram:SpecifiedProcuringProject>
</ram:ApplicableHeaderTradeAgreement>
<ram:ApplicableHeaderTradeDelivery>
<ram:ShipToTradeParty>
<ram:ID>SHIP_TO_ID</ram:ID>
<ram:GlobalID schemeID="0088">5897546912</ram:GlobalID>
<ram:Name>SHIP_TO_NAME</ram:Name>
<ram:SpecifiedLegalOrganization>
<ram:ID schemeID="0002">951632874</ram:ID>
<ram:TradingBusinessName>SHIP_TO_TRADING_NAME</ram:TradingBusinessName>
</ram:SpecifiedLegalOrganization>
<ram:DefinedTradeContact>
<ram:PersonName>SHIP_TO_CONTACT_NAME</ram:PersonName>
<ram:DepartmentName>SHIP_TO_CONTACT_DEP</ram:DepartmentName>
<ram:TypeCode>SD</ram:TypeCode>
<ram:TelephoneUniversalCommunication>
<ram:CompleteNumber>+33 6 85 96 32 41</ram:CompleteNumber>
</ram:TelephoneUniversalCommunication>
<ram:EmailURIUniversalCommunication>
<ram:URIID>shipto@customer.com</ram:URIID>
</ram:EmailURIUniversalCommunication>
</ram:DefinedTradeContact>
<ram:PostalTradeAddress>
<ram:PostcodeCode>69003</ram:PostcodeCode>
<ram:LineOne>SHIP_TO_ADDR_1</ram:LineOne>
<ram:LineTwo>SHIP_TO_ADDR_2</ram:LineTwo>
<ram:LineThree>SHIP_TO_ADDR_3</ram:LineThree>
<ram:CityName>SHIP_TO_CITY</ram:CityName>
<ram:CountryID>FR</ram:CountryID>
</ram:PostalTradeAddress>
<ram:URIUniversalCommunication>
<ram:URIID schemeID="EM">delivery@buyer.com</ram:URIID>
</ram:URIUniversalCommunication>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">FR 66 951 632 874</ram:ID>
</ram:SpecifiedTaxRegistration>
</ram:ShipToTradeParty>
<ram:ShipFromTradeParty>
<ram:ID>SHIP_FROM_ID</ram:ID>
<ram:GlobalID schemeID="0088">875496123</ram:GlobalID>
<ram:Name>SHIP_FROM_NAME</ram:Name>
<ram:SpecifiedLegalOrganization>
<ram:ID schemeID="0002">548963127</ram:ID>
<ram:TradingBusinessName>SHIP_FROM_TRADING_NAME</ram:TradingBusinessName>
</ram:SpecifiedLegalOrganization>
<ram:DefinedTradeContact>
<ram:PersonName>SHIP_FROM_CONTACT_NAME</ram:PersonName>
<ram:DepartmentName>SHIP_FROM_CONTACT_DEP</ram:DepartmentName>
<ram:TypeCode>SD</ram:TypeCode>
<ram:TelephoneUniversalCommunication>
<ram:CompleteNumber>+33 6 85 96 32 41</ram:CompleteNumber>
</ram:TelephoneUniversalCommunication>
<ram:EmailURIUniversalCommunication>
<ram:URIID>shipfrom@seller.com</ram:URIID>
</ram:EmailURIUniversalCommunication>
</ram:DefinedTradeContact>
<ram:PostalTradeAddress>
<ram:PostcodeCode>75003</ram:PostcodeCode>
<ram:LineOne>SHIP_FROM_ADDR_1</ram:LineOne>
<ram:LineTwo>SHIP_FROM_ADDR_2</ram:LineTwo>
<ram:LineThree>SHIP_FROM_ADDR_3</ram:LineThree>
<ram:CityName>SHIP_FROM_CITY</ram:CityName>
<ram:CountryID>FR</ram:CountryID>
</ram:PostalTradeAddress>
<ram:URIUniversalCommunication>
<ram:URIID>warehouse@seller.com</ram:URIID>
</ram:URIUniversalCommunication>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">FR 16 548 963 127</ram:ID>
</ram:SpecifiedTaxRegistration>
</ram:ShipFromTradeParty>
<ram:RequestedDeliverySupplyChainEvent>
<ram:OccurrenceDateTime>
<udt:DateTimeString format="102">20200415</udt:DateTimeString>
</ram:OccurrenceDateTime>
<ram:OccurrenceSpecifiedPeriod>
<ram:StartDateTime>
<udt:DateTimeString format="203">202004150900</udt:DateTimeString>
</ram:StartDateTime>
<ram:EndDateTime>
<udt:DateTimeString format="203">202004301800</udt:DateTimeString>
</ram:EndDateTime>
</ram:OccurrenceSpecifiedPeriod>
</ram:RequestedDeliverySupplyChainEvent>
</ram:ApplicableHeaderTradeDelivery>
<ram:ApplicableHeaderTradeSettlement>
<ram:OrderCurrencyCode>EUR</ram:OrderCurrencyCode>
<ram:InvoiceeTradeParty>
<ram:ID>INVOICEE_ID_9587456</ram:ID>
<ram:GlobalID schemeID="0088">98765432179</ram:GlobalID>
<ram:Name>INVOICEE_NAME</ram:Name>
<ram:SpecifiedLegalOrganization>
<ram:ID schemeID="0002">987654321</ram:ID>
<ram:TradingBusinessName>INVOICEE_TRADING_NAME</ram:TradingBusinessName>
</ram:SpecifiedLegalOrganization>
<ram:DefinedTradeContact>
<ram:PersonName>INVOICEE_CONTACT_NAME</ram:PersonName>
<ram:DepartmentName>INVOICEE_CONTACT_DEP</ram:DepartmentName>
<ram:TypeCode>LB</ram:TypeCode>
<ram:TelephoneUniversalCommunication>
<ram:CompleteNumber>+33 6 65 98 75 32</ram:CompleteNumber>
</ram:TelephoneUniversalCommunication>
<ram:EmailURIUniversalCommunication>
<ram:URIID>invoicee@buyer.com</ram:URIID>
</ram:EmailURIUniversalCommunication>
</ram:DefinedTradeContact>
<ram:PostalTradeAddress>
<ram:PostcodeCode>69001</ram:PostcodeCode>
<ram:LineOne>INVOICEE_ADDR_1</ram:LineOne>
<ram:LineTwo>INVOICEE_ADDR_2</ram:LineTwo>
<ram:LineThree>INVOICEE_ADDR_3</ram:LineThree>
<ram:CityName>INVOICEE_CITY</ram:CityName>
<ram:CountryID>FR</ram:CountryID>
</ram:PostalTradeAddress>
<ram:URIUniversalCommunication>
<ram:URIID schemeID="EM">invoicee@buyer.com</ram:URIID>
</ram:URIUniversalCommunication>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">FR 05 987 654 321</ram:ID>
</ram:SpecifiedTaxRegistration>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="FC">INVOICEE_TAX_ID</ram:ID>
</ram:SpecifiedTaxRegistration>
</ram:InvoiceeTradeParty>
<ram:SpecifiedTradeSettlementPaymentMeans>
<ram:TypeCode>30</ram:TypeCode>
<ram:Information>Credit Transfer</ram:Information>
</ram:SpecifiedTradeSettlementPaymentMeans>
<ram:SpecifiedTradeAllowanceCharge>
<ram:ChargeIndicator>
<udt:Indicator>false</udt:Indicator>
</ram:ChargeIndicator>
<ram:CalculationPercent>10.00</ram:CalculationPercent>
<ram:BasisAmount>310</ram:BasisAmount>
<ram:ActualAmount>31.00</ram:ActualAmount>
<ram:ReasonCode>64</ram:ReasonCode>
<ram:Reason>SPECIAL AGREEMENT</ram:Reason>
<ram:CategoryTradeTax>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>20.00</ram:RateApplicablePercent>
</ram:CategoryTradeTax>
</ram:SpecifiedTradeAllowanceCharge>
<ram:SpecifiedTradeAllowanceCharge>
<ram:ChargeIndicator>
<udt:Indicator>true</udt:Indicator>
</ram:ChargeIndicator>
<ram:CalculationPercent>10.00</ram:CalculationPercent>
<ram:BasisAmount>210.00</ram:BasisAmount>
<ram:ActualAmount>21.00</ram:ActualAmount>
<ram:ReasonCode>FC</ram:ReasonCode>
<ram:Reason>FREIGHT SERVICES</ram:Reason>
<ram:CategoryTradeTax>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>20.00</ram:RateApplicablePercent>
</ram:CategoryTradeTax>
</ram:SpecifiedTradeAllowanceCharge>
<ram:SpecifiedTradePaymentTerms>
<ram:Description>PAYMENT_TERMS_DESC</ram:Description>
</ram:SpecifiedTradePaymentTerms>
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
<ram:LineTotalAmount>310.00</ram:LineTotalAmount>
<ram:ChargeTotalAmount>21.00</ram:ChargeTotalAmount>
<ram:AllowanceTotalAmount>31.00</ram:AllowanceTotalAmount>
<ram:TaxBasisTotalAmount>300.00</ram:TaxBasisTotalAmount>
<ram:TaxTotalAmount currencyID="EUR">60.00</ram:TaxTotalAmount>
<ram:GrandTotalAmount>360.00</ram:GrandTotalAmount>
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
<ram:ReceivableSpecifiedTradeAccountingAccount>
<ram:ID>BUYER_ACCOUNT_REF</ram:ID>
</ram:ReceivableSpecifiedTradeAccountingAccount>
</ram:ApplicableHeaderTradeSettlement>
</rsm:SupplyChainTradeTransaction>
</rsm:SCRDMCCBDACIOMessageStructure>

View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.mustangproject</groupId> <groupId>org.mustangproject</groupId>
<artifactId>core</artifactId> <artifactId>core</artifactId>
<version>2.13.1-SNAPSHOT</version> <version>2.14.0-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>Mustang</name> <name>Mustang</name>
@@ -83,8 +83,7 @@
<connection>scm:git:https://github.com/ZUGFeRD/mustangproject.git</connection> <connection>scm:git:https://github.com/ZUGFeRD/mustangproject.git</connection>
<developerConnection>scm:git:https://github.com/ZUGFeRD/mustangproject.git</developerConnection> <developerConnection>scm:git:https://github.com/ZUGFeRD/mustangproject.git</developerConnection>
<url>https://github.com/ZUGFeRD/mustangproject</url> <url>https://github.com/ZUGFeRD/mustangproject</url>
<tag>HEAD</tag> </scm>
</scm>
<distributionManagement> <distributionManagement>
<repository> <repository>
@@ -248,7 +247,7 @@
<phase>package</phase> <phase>package</phase>
<configuration> <configuration>
<artifactSet> <artifactSet>
<excludes /> <excludes></excludes>
</artifactSet> </artifactSet>
</configuration> </configuration>
</execution> </execution>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>org.mustangproject</groupId> <groupId>org.mustangproject</groupId>
<artifactId>core</artifactId> <artifactId>core</artifactId>
<version>2.13.1-SNAPSHOT</version> <version>2.14.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>validator</artifactId> <artifactId>validator</artifactId>

View File

@@ -244,8 +244,31 @@ public class LibraryTest extends ResourceCase {
.isEqualTo(0); .isEqualTo(0);
} }
public void testMinimumProfileValidity() { public void testMinimumProfileValidityInvoice() {
File tempFile = new File("../library/target/testout-Minimum.pdf"); File tempFile = new File("../library/target/testout-Minimum-INV.pdf");
ZUGFeRDValidator zfv = new ZUGFeRDValidator();
String res = zfv.validate(tempFile.getAbsolutePath());
assertThat(res).valueByXPath("count(//error)")
.asInt()
.isEqualTo(0);
assertThat(res).valueByXPath("/validation/summary/@status")
.asString()
.isEqualTo("valid");// expect to be valid because XR notices are, well, only notices
assertThat(res).valueByXPath("/validation/xml/summary/@status")
.asString()
.isEqualTo("valid");
/** end of errors due to version mismatch*/
assertThat(res).valueByXPath("count(//notice)")
.asInt()
.isEqualTo(0);
}
public void testMinimumProfileValidityCreditNote() {
File tempFile = new File("../library/target/testout-Minimum-CN.pdf");
ZUGFeRDValidator zfv = new ZUGFeRDValidator(); ZUGFeRDValidator zfv = new ZUGFeRDValidator();
String res = zfv.validate(tempFile.getAbsolutePath()); String res = zfv.validate(tempFile.getAbsolutePath());