Merge branch 'ZUGFeRD:master' into fix-logback
This commit is contained in:
17
History.md
17
History.md
@@ -1,8 +1,25 @@
|
|||||||
|
- 639
|
||||||
|
- 633
|
||||||
|
-626,
|
||||||
|
-622,
|
||||||
|
-356
|
||||||
|
allow to add includedNotes with type
|
||||||
|
- - 645
|
||||||
|
- 631 multiple invoice referenced documents
|
||||||
|
- 629
|
||||||
|
- 630 #296 #565
|
||||||
|
-
|
||||||
|
|
||||||
|
2.15.2
|
||||||
|
=======
|
||||||
|
2024-12-19
|
||||||
- correcly write charge reason codes also for non-Xrechnung #617
|
- correcly write charge reason codes also for non-Xrechnung #617
|
||||||
- correctly import additional referenced documents into invoice/corrected setting of attachments from jackson
|
- correctly import additional referenced documents into invoice/corrected setting of attachments from jackson
|
||||||
- corrected parseException structure
|
- corrected parseException structure
|
||||||
- allow 1p0 as potential xmp version number
|
- allow 1p0 as potential xmp version number
|
||||||
- #618 import BT-20
|
- #618 import BT-20
|
||||||
|
- #599 add tax category code for free export
|
||||||
|
- #600 Fixes a problem where a stream was not safely closed
|
||||||
|
|
||||||
2.15.1
|
2.15.1
|
||||||
=======
|
=======
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
<version>2.15.2-SNAPSHOT</version>
|
<version>2.15.3-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
should also work for XRechnung/CII.
|
should also work for XRechnung/CII.
|
||||||
</name>
|
</name>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>2.15.2-SNAPSHOT</version>
|
<version>2.15.3-SNAPSHOT</version>
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.compiler.compilerVersion>11</maven.compiler.compilerVersion>
|
<maven.compiler.compilerVersion>11</maven.compiler.compilerVersion>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
<artifactId>validator</artifactId>
|
<artifactId>validator</artifactId>
|
||||||
<version>2.15.2-SNAPSHOT</version>
|
<version>2.15.3-SNAPSHOT</version>
|
||||||
<!-- prototypes of new mustangproject versions can be installed by referring to them and installed to the local repo from a jar file with
|
<!-- prototypes of new mustangproject versions can be installed by referring to them and installed to the local repo from a jar file with
|
||||||
mvn install:install-file -Dfile=mustang-1.5.4-SNAPSHOT.jar -DgroupId=org.mustangproject.ZUGFeRD -DartifactId=mustang -Dversion=1.5.4 -Dpackaging=jar -DgeneratePom=true
|
mvn install:install-file -Dfile=mustang-1.5.4-SNAPSHOT.jar -DgroupId=org.mustangproject.ZUGFeRD -DartifactId=mustang -Dversion=1.5.4 -Dpackaging=jar -DgeneratePom=true
|
||||||
-->
|
-->
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>logback-core</artifactId>
|
<artifactId>logback-core</artifactId>
|
||||||
<version>1.2.13</version>
|
<version>1.5.13</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<!-- This library is needed so that logback stderr output is sent to, well, stderr, otherwise it lands in stdout -->
|
<!-- This library is needed so that logback stderr output is sent to, well, stderr, otherwise it lands in stdout -->
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
package org.mustangproject.commandline;
|
package org.mustangproject.commandline;
|
||||||
|
|
||||||
import org.apache.commons.cli.*;
|
import org.apache.commons.cli.*;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.mustangproject.CII.CIIToUBL;
|
import org.mustangproject.CII.CIIToUBL;
|
||||||
import org.mustangproject.EStandard;
|
import org.mustangproject.EStandard;
|
||||||
import org.mustangproject.FileAttachment;
|
import org.mustangproject.FileAttachment;
|
||||||
@@ -84,6 +85,7 @@ public class Main {
|
|||||||
+ " [--logAppend <text>]: text to be added to log line\n"
|
+ " [--logAppend <text>]: text to be added to log line\n"
|
||||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||||
+ " [--source <filename>]: input PDF or XML file\n"
|
+ " [--source <filename>]: input PDF or XML file\n"
|
||||||
|
+ " [--log-as-pdf]: save log output as pdf\n"
|
||||||
+ " --action validateExpectInvalid validate directory expecting negative results \n"
|
+ " --action validateExpectInvalid validate directory expecting negative results \n"
|
||||||
+ " [--no-notices]: refrain from reporting notices\n"
|
+ " [--no-notices]: refrain from reporting notices\n"
|
||||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||||
@@ -357,6 +359,7 @@ public class Main {
|
|||||||
options.addOption(new Option("d", "directory", true, "which directory to operate on"));
|
options.addOption(new Option("d", "directory", true, "which directory to operate on"));
|
||||||
options.addOption(new Option("i", "ignorefileextension", false, "ignore non-matching file extensions"));
|
options.addOption(new Option("i", "ignorefileextension", false, "ignore non-matching file extensions"));
|
||||||
options.addOption(new Option("l", "listfromstdin", false, "take list of files from commandline"));
|
options.addOption(new Option("l", "listfromstdin", false, "take list of files from commandline"));
|
||||||
|
options.addOption(new Option("log-as-pdf", "log-as-pdf", false, "saving log output to pdf file"));
|
||||||
|
|
||||||
boolean optionsRecognized = false;
|
boolean optionsRecognized = false;
|
||||||
String action = "";
|
String action = "";
|
||||||
@@ -380,6 +383,7 @@ public class Main {
|
|||||||
String format = cmd.getOptionValue("format");
|
String format = cmd.getOptionValue("format");
|
||||||
String lang = cmd.getOptionValue("language");
|
String lang = cmd.getOptionValue("language");
|
||||||
Boolean noNotices = cmd.hasOption("no-notices");
|
Boolean noNotices = cmd.hasOption("no-notices");
|
||||||
|
Boolean LogAsPDF = cmd.hasOption("log-as-pdf");
|
||||||
|
|
||||||
String zugferdVersion = cmd.getOptionValue("version");
|
String zugferdVersion = cmd.getOptionValue("version");
|
||||||
String zugferdProfile = cmd.getOptionValue("profile");
|
String zugferdProfile = cmd.getOptionValue("profile");
|
||||||
@@ -427,7 +431,7 @@ public class Main {
|
|||||||
performUBL(sourceName, outName);
|
performUBL(sourceName, outName);
|
||||||
optionsRecognized = true;
|
optionsRecognized = true;
|
||||||
} else if ((action != null) && (action.equals("validate"))) {
|
} else if ((action != null) && (action.equals("validate"))) {
|
||||||
optionsRecognized = performValidate(sourceName, noNotices, cmd.getOptionValue("logAppend"));
|
optionsRecognized = performValidate(sourceName, noNotices, cmd.getOptionValue("logAppend"), LogAsPDF);
|
||||||
} else if ((action != null) && (action.equals("validateExpectValid"))) {
|
} else if ((action != null) && (action.equals("validateExpectValid"))) {
|
||||||
optionsRecognized = performValidateExpect(true, directoryName);
|
optionsRecognized = performValidateExpect(true, directoryName);
|
||||||
} else if ((action != null) && (action.equals("validateExpectInvalid"))) {
|
} else if ((action != null) && (action.equals("validateExpectInvalid"))) {
|
||||||
@@ -454,7 +458,7 @@ public class Main {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean performValidate(String sourceName, boolean noNotices, String logAppend) {
|
private static boolean performValidate(String sourceName, boolean noNotices, String logAppend, boolean createLogAsPDF) {
|
||||||
boolean optionsRecognized;
|
boolean optionsRecognized;
|
||||||
if (sourceName == null) {
|
if (sourceName == null) {
|
||||||
sourceName = getFilenameFromUser("Source PDF or XML", "invoice.pdf", "pdf|xml", true, false);
|
sourceName = getFilenameFromUser("Source PDF or XML", "invoice.pdf", "pdf|xml", true, false);
|
||||||
@@ -466,7 +470,16 @@ public class Main {
|
|||||||
if (noNotices) {
|
if (noNotices) {
|
||||||
zfv.disableNotices();
|
zfv.disableNotices();
|
||||||
}
|
}
|
||||||
System.out.println(zfv.validate(sourceName));
|
|
||||||
|
String validationResultXML = zfv.validate(sourceName);
|
||||||
|
System.out.println(validationResultXML);
|
||||||
|
|
||||||
|
if( createLogAsPDF) {
|
||||||
|
ValidationLogVisualizer vlvi = new ValidationLogVisualizer();
|
||||||
|
String fileBasename = FilenameUtils.getBaseName(sourceName);
|
||||||
|
|
||||||
|
vlvi.toPDF(validationResultXML, fileBasename + "_result.pdf");
|
||||||
|
}
|
||||||
optionsRecognized = !zfv.hasOptionsError();
|
optionsRecognized = !zfv.hasOptionsError();
|
||||||
if (!zfv.wasCompletelyValid()) {
|
if (!zfv.wasCompletelyValid()) {
|
||||||
System.exit(-1);
|
System.exit(-1);
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
<version>2.15.2-SNAPSHOT</version>
|
<version>2.15.3-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
<artifactId>library</artifactId>
|
<artifactId>library</artifactId>
|
||||||
<version>2.15.2-SNAPSHOT</version>
|
<version>2.15.3-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>Library to write, read and validate e-invoices (Factur-X, ZUGFeRD, Order-X, XRechnung/CII)</name>
|
<name>Library to write, read and validate e-invoices (Factur-X, ZUGFeRD, Order-X, XRechnung/CII)</name>
|
||||||
<description>FOSS Java library to read, write and validate european electronic invoices and orders in the UN/CEFACT
|
<description>FOSS Java library to read, write and validate european electronic invoices and orders in the UN/CEFACT
|
||||||
@@ -200,21 +200,51 @@
|
|||||||
</manifest>
|
</manifest>
|
||||||
<manifestSections>
|
<manifestSections>
|
||||||
<manifestSection>
|
<manifestSection>
|
||||||
<name>FreeSans.ttf</name>
|
<name>SourceSansPro-Regular.ttf</name>
|
||||||
<manifestEntries>
|
<manifestEntries>
|
||||||
<Content-Type>font/ttf</Content-Type>
|
<Content-Type>font/ttf</Content-Type>
|
||||||
</manifestEntries>
|
</manifestEntries>
|
||||||
</manifestSection>
|
</manifestSection>
|
||||||
<manifestSection>
|
<manifestSection>
|
||||||
<name>FreeSerif.ttf</name>
|
<name>SourceSansPro-It.ttf</name>
|
||||||
<manifestEntries>
|
<manifestEntries>
|
||||||
<Content-Type>application/x-font</Content-Type>
|
<Content-Type>font/ttf</Content-Type>
|
||||||
</manifestEntries>
|
</manifestEntries>
|
||||||
</manifestSection>
|
</manifestSection>
|
||||||
<manifestSection>
|
<manifestSection>
|
||||||
<name>Times-Bold.ttf</name>
|
<name>SourceSansPro-Bold.ttf</name>
|
||||||
<manifestEntries>
|
<manifestEntries>
|
||||||
<Content-Type>application/x-font</Content-Type>
|
<Content-Type>font/ttf</Content-Type>
|
||||||
|
</manifestEntries>
|
||||||
|
</manifestSection>
|
||||||
|
<manifestSection>
|
||||||
|
<name>SourceSansPro-BoldIt.ttf</name>
|
||||||
|
<manifestEntries>
|
||||||
|
<Content-Type>font/ttf</Content-Type>
|
||||||
|
</manifestEntries>
|
||||||
|
</manifestSection>
|
||||||
|
<manifestSection>
|
||||||
|
<name>SourceSerifPro-Regular.ttf</name>
|
||||||
|
<manifestEntries>
|
||||||
|
<Content-Type>font/ttf</Content-Type>
|
||||||
|
</manifestEntries>
|
||||||
|
</manifestSection>
|
||||||
|
<manifestSection>
|
||||||
|
<name>SourceSerifPro-It.ttf</name>
|
||||||
|
<manifestEntries>
|
||||||
|
<Content-Type>font/ttf</Content-Type>
|
||||||
|
</manifestEntries>
|
||||||
|
</manifestSection>
|
||||||
|
<manifestSection>
|
||||||
|
<name>SourceSerifPro-Bold.ttf</name>
|
||||||
|
<manifestEntries>
|
||||||
|
<Content-Type>font/ttf</Content-Type>
|
||||||
|
</manifestEntries>
|
||||||
|
</manifestSection>
|
||||||
|
<manifestSection>
|
||||||
|
<name>SourceSerifPro-BoldIt.ttf</name>
|
||||||
|
<manifestEntries>
|
||||||
|
<Content-Type>font/ttf</Content-Type>
|
||||||
</manifestEntries>
|
</manifestEntries>
|
||||||
</manifestSection>
|
</manifestSection>
|
||||||
</manifestSections>
|
</manifestSections>
|
||||||
|
|||||||
@@ -3,11 +3,14 @@ package org.mustangproject.Exceptions;
|
|||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* will be thrown if a invoice cant be reproduced numerically
|
* will be thrown if an invoice cant be reproduced numerically
|
||||||
*/
|
*/
|
||||||
public class ArithmetricException extends ParseException {
|
public class ArithmetricException extends ParseException {
|
||||||
public ArithmetricException() {
|
public ArithmetricException() {
|
||||||
super(
|
this("");
|
||||||
"Could not reproduce the invoice, this could mean that it could not be read properly", 0);
|
}
|
||||||
|
|
||||||
|
public ArithmetricException(String details) {
|
||||||
|
super("Could not reproduce the invoice. " + details, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
|||||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
public class Invoice implements IExportableTransaction {
|
public class Invoice implements IExportableTransaction {
|
||||||
|
|
||||||
protected String documentName = null, documentCode = null, number = null, ownOrganisationFullPlaintextInfo = null, referenceNumber = null, shipToOrganisationID = null, shipToOrganisationName = null, shipToStreet = null, shipToZIP = null, shipToLocation = null, shipToCountry = null, buyerOrderReferencedDocumentID = null, invoiceReferencedDocumentID = null, buyerOrderReferencedDocumentIssueDateTime = null, ownForeignOrganisationID = null, ownOrganisationName = null, currency = null, paymentTermDescription = null;
|
protected String documentName = null, documentCode = null, number = null, ownOrganisationFullPlaintextInfo = null, referenceNumber = null, shipToOrganisationID = null, shipToOrganisationName = null, shipToStreet = null, shipToZIP = null, shipToLocation = null, shipToCountry = null, buyerOrderReferencedDocumentID = null, buyerOrderReferencedDocumentIssueDateTime = null, ownForeignOrganisationID = null, ownOrganisationName = null, currency = null, paymentTermDescription = null;
|
||||||
protected Date issueDate = null, dueDate = null, deliveryDate = null;
|
protected Date issueDate = null, dueDate = null, deliveryDate = null;
|
||||||
protected TradeParty sender = null, recipient = null, deliveryAddress = null, payee = null;
|
protected TradeParty sender = null, recipient = null, deliveryAddress = null, payee = null;
|
||||||
protected ArrayList<CashDiscount> cashDiscounts = null;
|
protected ArrayList<CashDiscount> cashDiscounts = null;
|
||||||
@@ -57,7 +57,12 @@ public class Invoice implements IExportableTransaction {
|
|||||||
protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<>(),
|
protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<>(),
|
||||||
Charges = new ArrayList<>(), LogisticsServiceCharges = new ArrayList<>();
|
Charges = new ArrayList<>(), LogisticsServiceCharges = new ArrayList<>();
|
||||||
protected IZUGFeRDPaymentTerms paymentTerms = null;
|
protected IZUGFeRDPaymentTerms paymentTerms = null;
|
||||||
|
|
||||||
|
protected String invoiceReferencedDocumentID = null;
|
||||||
protected Date invoiceReferencedIssueDate;
|
protected Date invoiceReferencedIssueDate;
|
||||||
|
// New field for storing Invoiced Object Identifier (BG-3)
|
||||||
|
protected ArrayList<ReferencedDocument> invoiceReferencedDocuments = null;
|
||||||
|
|
||||||
protected String specifiedProcuringProjectID = null;
|
protected String specifiedProcuringProjectID = null;
|
||||||
protected String specifiedProcuringProjectName = null;
|
protected String specifiedProcuringProjectName = null;
|
||||||
protected String despatchAdviceReferencedDocumentID = null;
|
protected String despatchAdviceReferencedDocumentID = null;
|
||||||
@@ -148,6 +153,7 @@ public class Invoice implements IExportableTransaction {
|
|||||||
*/
|
*/
|
||||||
public Invoice setCorrection(String number) {
|
public Invoice setCorrection(String number) {
|
||||||
setInvoiceReferencedDocumentID(number);
|
setInvoiceReferencedDocumentID(number);
|
||||||
|
addInvoiceReferencedDocument(new ReferencedDocument(number));
|
||||||
documentCode = DocumentCodeTypeConstants.CORRECTEDINVOICE;
|
documentCode = DocumentCodeTypeConstants.CORRECTEDINVOICE;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -546,6 +552,26 @@ public class Invoice implements IExportableTransaction {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getter for BG-3
|
||||||
|
@Override
|
||||||
|
public ArrayList<ReferencedDocument> getInvoiceReferencedDocuments() {
|
||||||
|
return invoiceReferencedDocuments;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setter for BG-3
|
||||||
|
public void setInvoiceReferencedDocuments(ArrayList<ReferencedDocument> invoiceReferencedDocuments) {
|
||||||
|
this.invoiceReferencedDocuments = invoiceReferencedDocuments;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to add a single ReferencedDocument for BG-3
|
||||||
|
public Invoice addInvoiceReferencedDocument(ReferencedDocument doc) {
|
||||||
|
if (invoiceReferencedDocuments == null) {
|
||||||
|
invoiceReferencedDocuments = new ArrayList<>();
|
||||||
|
}
|
||||||
|
invoiceReferencedDocuments.add(doc);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IZUGFeRDAllowanceCharge[] getZFAllowances() {
|
public IZUGFeRDAllowanceCharge[] getZFAllowances() {
|
||||||
if (Allowances.isEmpty()) {
|
if (Allowances.isEmpty()) {
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
|
|
||||||
/***
|
/***
|
||||||
* Adds a item level addition to the price (will be multiplied by quantity)
|
* Adds a item level addition to the price (will be multiplied by quantity)
|
||||||
* @see org.mustangproject.Charge
|
* @see Charge
|
||||||
* @param izac a relative or absolute charge
|
* @param izac a relative or absolute charge
|
||||||
* @return fluent setter
|
* @return fluent setter
|
||||||
*/
|
*/
|
||||||
@@ -363,7 +363,7 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
|
|
||||||
/***
|
/***
|
||||||
* Adds a item level reduction the price (will be multiplied by quantity)
|
* Adds a item level reduction the price (will be multiplied by quantity)
|
||||||
* @see org.mustangproject.Allowance
|
* @see Allowance
|
||||||
* @param izac a relative or absolute allowance
|
* @param izac a relative or absolute allowance
|
||||||
* @return fluent setter
|
* @return fluent setter
|
||||||
*/
|
*/
|
||||||
@@ -383,10 +383,23 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
}
|
}
|
||||||
notes.add(text);
|
notes.add(text);
|
||||||
|
|
||||||
|
addNote(IncludedNote.unspecifiedNote(text));
|
||||||
|
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* adds categorized item level freetext fields (includednote)
|
||||||
|
* @param theNote IncludedNote to add
|
||||||
|
* @return fluent setter
|
||||||
|
*/
|
||||||
|
public Item addNote(IncludedNote theNote) {
|
||||||
|
|
||||||
if (includedNotes == null) {
|
if (includedNotes == null) {
|
||||||
includedNotes = new ArrayList<>();
|
includedNotes = new ArrayList<>();
|
||||||
}
|
}
|
||||||
includedNotes.add(IncludedNote.unspecifiedNote(text));
|
includedNotes.add(theNote);
|
||||||
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package org.mustangproject;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
import org.mustangproject.ZUGFeRD.IReferencedDocument;
|
import org.mustangproject.ZUGFeRD.IReferencedDocument;
|
||||||
import org.mustangproject.util.NodeMap;
|
import org.mustangproject.util.NodeMap;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
@@ -13,20 +15,33 @@ public class ReferencedDocument implements IReferencedDocument {
|
|||||||
String issuerAssignedID;
|
String issuerAssignedID;
|
||||||
String typeCode;
|
String typeCode;
|
||||||
String referenceTypeCode;
|
String referenceTypeCode;
|
||||||
|
Date formattedIssueDateTime;
|
||||||
|
|
||||||
public ReferencedDocument(String issuerAssignedID, String typeCode, String referenceTypeCode) {
|
public ReferencedDocument(String issuerAssignedID, String typeCode, String referenceTypeCode) {
|
||||||
this.issuerAssignedID = issuerAssignedID;
|
this(issuerAssignedID);
|
||||||
this.typeCode = typeCode;
|
this.typeCode = typeCode;
|
||||||
this.referenceTypeCode = referenceTypeCode;
|
this.referenceTypeCode = referenceTypeCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReferencedDocument(String issuerAssignedID, String referenceTypeCode) {
|
public ReferencedDocument(String issuerAssignedID, String typeCode, String referenceTypeCode, Date formattedIssueDateTime) {
|
||||||
this.issuerAssignedID = issuerAssignedID;
|
this(issuerAssignedID, typeCode, referenceTypeCode);
|
||||||
this.typeCode = "916"; // additional invoice related document
|
this.formattedIssueDateTime = formattedIssueDateTime;
|
||||||
this.referenceTypeCode = referenceTypeCode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
public ReferencedDocument(String issuerAssignedID, String referenceTypeCode) {
|
||||||
|
this(issuerAssignedID, "916", referenceTypeCode); // additional invoice related document
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReferencedDocument(String issuerAssingedID, Date formattedIssueDateTime) {
|
||||||
|
this(issuerAssingedID);
|
||||||
|
this.formattedIssueDateTime = formattedIssueDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReferencedDocument(String issuerAssignedID) {
|
||||||
|
this.issuerAssignedID = issuerAssignedID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
* sets an ID assigned by the sender
|
* sets an ID assigned by the sender
|
||||||
* @param issuerAssignedID the ID as a string :-)
|
* @param issuerAssignedID the ID as a string :-)
|
||||||
*/
|
*/
|
||||||
@@ -50,6 +65,15 @@ public class ReferencedDocument implements IReferencedDocument {
|
|||||||
this.referenceTypeCode = referenceTypeCode;
|
this.referenceTypeCode = referenceTypeCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* issue date of this line
|
||||||
|
*
|
||||||
|
* @param formattedIssueDateTime as Date
|
||||||
|
*/
|
||||||
|
public void setFormattedIssueDateTime(Date formattedIssueDateTime) {
|
||||||
|
this.formattedIssueDateTime = formattedIssueDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIssuerAssignedID() {
|
public String getIssuerAssignedID() {
|
||||||
return issuerAssignedID;
|
return issuerAssignedID;
|
||||||
@@ -65,6 +89,12 @@ public class ReferencedDocument implements IReferencedDocument {
|
|||||||
return referenceTypeCode;
|
return referenceTypeCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getFormattedIssueDateTime()
|
||||||
|
{
|
||||||
|
return formattedIssueDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
public static ReferencedDocument fromNode(Node node) {
|
public static ReferencedDocument fromNode(Node node) {
|
||||||
if (!node.hasChildNodes()) {
|
if (!node.hasChildNodes()) {
|
||||||
return null;
|
return null;
|
||||||
@@ -72,6 +102,7 @@ public class ReferencedDocument implements IReferencedDocument {
|
|||||||
NodeMap nodes = new NodeMap(node);
|
NodeMap nodes = new NodeMap(node);
|
||||||
return new ReferencedDocument(nodes.getAsStringOrNull("IssuerAssignedID", "ID"),
|
return new ReferencedDocument(nodes.getAsStringOrNull("IssuerAssignedID", "ID"),
|
||||||
nodes.getAsStringOrNull("TypeCode", "DocumentTypeCode"),
|
nodes.getAsStringOrNull("TypeCode", "DocumentTypeCode"),
|
||||||
nodes.getAsStringOrNull("ReferenceTypeCode"));
|
nodes.getAsStringOrNull("ReferenceTypeCode"),
|
||||||
|
XMLTools.tryDate(nodes.getAsStringOrNull("FormattedIssueDateTime")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,11 +30,13 @@ package org.mustangproject.ZUGFeRD;
|
|||||||
* */
|
* */
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.mustangproject.FileAttachment;
|
import org.mustangproject.FileAttachment;
|
||||||
import org.mustangproject.IncludedNote;
|
import org.mustangproject.IncludedNote;
|
||||||
|
import org.mustangproject.ReferencedDocument;
|
||||||
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
|
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@@ -424,14 +426,24 @@ public interface IExportableTransaction {
|
|||||||
*
|
*
|
||||||
* @return the ID of the document
|
* @return the ID of the document
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
default String getInvoiceReferencedDocumentID() {
|
default String getInvoiceReferencedDocumentID() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
default Date getInvoiceReferencedIssueDate() {
|
default Date getInvoiceReferencedIssueDate() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for BG-3
|
||||||
|
* @return list of documents
|
||||||
|
*/
|
||||||
|
default ArrayList<ReferencedDocument> getInvoiceReferencedDocuments() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the issue timestamp of the BuyerOrderReferencedDocument, which sits in
|
* get the issue timestamp of the BuyerOrderReferencedDocument, which sits in
|
||||||
* the ApplicableSupplyChainTradeAgreement
|
* the ApplicableSupplyChainTradeAgreement
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.mustangproject.ZUGFeRD;
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
public interface IReferencedDocument {
|
public interface IReferencedDocument {
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@@ -20,4 +22,12 @@ public interface IReferencedDocument {
|
|||||||
*/
|
*/
|
||||||
String getReferenceTypeCode();
|
String getReferenceTypeCode();
|
||||||
|
|
||||||
|
/***
|
||||||
|
*
|
||||||
|
* issue date of this line
|
||||||
|
*
|
||||||
|
* @return date of the issue
|
||||||
|
*/
|
||||||
|
Date getFormattedIssueDateTime();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -459,6 +459,19 @@ public class OXPullProvider extends ZUGFeRD2PullProvider {
|
|||||||
}
|
}
|
||||||
xml += "</ram:InvoiceReferencedDocument>";
|
xml += "</ram:InvoiceReferencedDocument>";
|
||||||
}
|
}
|
||||||
|
if (trans.getInvoiceReferencedDocuments() != null) {
|
||||||
|
for (var doc : trans.getInvoiceReferencedDocuments()) {
|
||||||
|
xml += "<ram:InvoiceReferencedDocument>"
|
||||||
|
+ "<ram:IssuerAssignedID>"
|
||||||
|
+ XMLTools.encodeXML(doc.getIssuerAssignedID()) + "</ram:IssuerAssignedID>";
|
||||||
|
if (doc.getFormattedIssueDateTime() != null) {
|
||||||
|
xml += "<ram:FormattedIssueDateTime>"
|
||||||
|
+ DATE.qdtFormat(doc.getFormattedIssueDateTime())
|
||||||
|
+ "</ram:FormattedIssueDateTime>";
|
||||||
|
}
|
||||||
|
xml += "</ram:InvoiceReferencedDocument>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xml += "</ram:ApplicableHeaderTradeSettlement>";
|
xml += "</ram:ApplicableHeaderTradeSettlement>";
|
||||||
// + " <IncludedSupplyChainTradeLineItem>"
|
// + " <IncludedSupplyChainTradeLineItem>"
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import static java.math.BigDecimal.ZERO;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@@ -91,17 +94,14 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getAllowanceChargeReasonForPercent(BigDecimal percent, IZUGFeRDAllowanceCharge[] charges) {
|
private String getAllowanceChargeReasonForPercent(BigDecimal percent, IZUGFeRDAllowanceCharge[] charges) {
|
||||||
String res = " ";
|
if (charges == null) {
|
||||||
if ((charges != null) && (charges.length > 0)) {
|
return "";
|
||||||
for (IZUGFeRDAllowanceCharge currentCharge : charges) {
|
|
||||||
if ((percent == null) || (currentCharge.getTaxPercent().compareTo(percent) == 0)
|
|
||||||
&& currentCharge.getReason() != null) {
|
|
||||||
res += currentCharge.getReason() + " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
res = res.substring(0, res.length() - 1);
|
return Arrays.stream(charges)
|
||||||
return res;
|
.filter(currentCharge -> (percent == null || currentCharge.getTaxPercent().compareTo(percent) == 0))
|
||||||
|
.map(IZUGFeRDAllowanceCharge::getReason)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.joining(" "));
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
|
import org.apache.fop.apps.*;
|
||||||
|
import org.apache.fop.apps.io.ResourceResolverFactory;
|
||||||
|
import org.apache.fop.configuration.Configuration;
|
||||||
|
import org.apache.fop.configuration.ConfigurationException;
|
||||||
|
import org.apache.fop.configuration.DefaultConfigurationBuilder;
|
||||||
|
import org.apache.xmlgraphics.util.MimeConstants;
|
||||||
|
import org.mustangproject.ClasspathResolverURIAdapter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.xml.transform.*;
|
||||||
|
import javax.xml.transform.sax.SAXResult;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class ValidationLogVisualizer {
|
||||||
|
public enum Language {
|
||||||
|
EN,
|
||||||
|
FR,
|
||||||
|
DE
|
||||||
|
}
|
||||||
|
|
||||||
|
static final ClassLoader CLASS_LOADER = ValidationLogVisualizer.class.getClassLoader();
|
||||||
|
private static final String RESOURCE_PATH = "";
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(ValidationLogVisualizer.class);
|
||||||
|
|
||||||
|
private TransformerFactory mFactory = null;
|
||||||
|
private Templates mXsltPDFTemplate = null;
|
||||||
|
|
||||||
|
|
||||||
|
public ValidationLogVisualizer() {
|
||||||
|
mFactory = new net.sf.saxon.TransformerFactoryImpl();
|
||||||
|
// fact = TransformerFactory.newInstance();
|
||||||
|
mFactory.setURIResolver(new ValidationLogVisualizer.ClasspathResourceURIResolver());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void applyXSLTToPDF(final String xmlContent, final OutputStream PDFOutstream)
|
||||||
|
throws TransformerException {
|
||||||
|
Transformer transformer = mXsltPDFTemplate.newTransformer();
|
||||||
|
|
||||||
|
transformer.transform(new StreamSource(new StringReader(xmlContent)), new StreamResult(PDFOutstream));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String toFOP(final String xmlContent)
|
||||||
|
throws TransformerException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (mXsltPDFTemplate == null) {
|
||||||
|
mXsltPDFTemplate = mFactory.newTemplates(
|
||||||
|
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/result-pdf.xsl")));
|
||||||
|
}
|
||||||
|
} catch (TransformerConfigurationException ex) {
|
||||||
|
LOGGER.error("Failed to init XSLT templates", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
applyXSLTToPDF(xmlContent, baos);
|
||||||
|
|
||||||
|
} catch (Exception e1) {
|
||||||
|
LOGGER.error("Failed to create PDF", e1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return baos.toString(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toPDF(String xmlLogfileContent, String pdfFilename) {
|
||||||
|
|
||||||
|
// the writing part
|
||||||
|
|
||||||
|
String result = null;
|
||||||
|
|
||||||
|
/* remove file endings so that tests can also pass after checking
|
||||||
|
out from git with arbitrary options (which may include CSRF changes)
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
result = this.toFOP(xmlLogfileContent);
|
||||||
|
} catch ( TransformerException e) {
|
||||||
|
LOGGER.error("Failed to apply FOP", e);
|
||||||
|
}
|
||||||
|
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
|
||||||
|
|
||||||
|
Configuration cfg = null;
|
||||||
|
try {
|
||||||
|
cfg = cfgBuilder.build(CLASS_LOADER.getResourceAsStream("fop-config.xconf"));
|
||||||
|
} catch (ConfigurationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
FopFactoryBuilder builder = new FopFactoryBuilder(new File(".").toURI(), new ClasspathResolverURIAdapter()).setConfiguration(cfg);
|
||||||
|
// Step 1: Construct a FopFactory by specifying a reference to the configuration file
|
||||||
|
// (reuse if you plan to render multiple documents!)
|
||||||
|
|
||||||
|
FopFactory fopFactory = builder.build();
|
||||||
|
|
||||||
|
fopFactory.getFontManager().setResourceResolver(
|
||||||
|
ResourceResolverFactory.createInternalResourceResolver(
|
||||||
|
new File(".").toURI(),
|
||||||
|
new ClasspathResolverURIAdapter()));
|
||||||
|
|
||||||
|
FOUserAgent userAgent = fopFactory.newFOUserAgent();
|
||||||
|
|
||||||
|
userAgent.getRendererOptions().put("pdf-a-mode", "PDF/A-3b");
|
||||||
|
|
||||||
|
// Step 2: Set up output stream.
|
||||||
|
// Note: Using BufferedOutputStream for performance reasons (helpful with FileOutputStreams).
|
||||||
|
|
||||||
|
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(pdfFilename))) {
|
||||||
|
|
||||||
|
// Step 3: Construct fop with desired output format
|
||||||
|
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent, out);
|
||||||
|
|
||||||
|
// Step 4: Setup JAXP using identity transformer
|
||||||
|
TransformerFactory factory = TransformerFactory.newInstance();
|
||||||
|
Transformer transformer = factory.newTransformer(); // identity transformer
|
||||||
|
|
||||||
|
// Step 5: Setup input and output for XSLT transformation
|
||||||
|
// Setup input stream
|
||||||
|
Source src = new StreamSource(new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8)));
|
||||||
|
|
||||||
|
// Resulting SAX events (the generated FO) must be piped through to FOP
|
||||||
|
Result res = new SAXResult(fop.getDefaultHandler());
|
||||||
|
|
||||||
|
// Step 6: Start XSLT transformation and FOP processing
|
||||||
|
transformer.transform(src, res);
|
||||||
|
|
||||||
|
} catch (FOPException | IOException | TransformerException e) {
|
||||||
|
LOGGER.error("Failed to create PDF", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ClasspathResourceURIResolver implements URIResolver {
|
||||||
|
ClasspathResourceURIResolver() {
|
||||||
|
// Do nothing, just prevents synthetic access warning.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Source resolve(String href, String base) throws TransformerException {
|
||||||
|
return new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/" + href));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -829,6 +829,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
xml += "<ram:Description>" + paymentTermsDescription + "</ram:Description>";
|
xml += "<ram:Description>" + paymentTermsDescription + "</ram:Description>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (trans.getDueDate() != null) {
|
||||||
|
xml += "<ram:DueDateDateTime>" // $NON-NLS-2$
|
||||||
|
+ DATE.udtFormat(trans.getDueDate())
|
||||||
|
+ "</ram:DueDateDateTime>";// 20130704
|
||||||
|
}
|
||||||
|
|
||||||
if (trans.getTradeSettlement() != null) {
|
if (trans.getTradeSettlement() != null) {
|
||||||
for (final IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) {
|
for (final IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) {
|
||||||
if ((payment != null) && (payment instanceof IZUGFeRDTradeSettlementDebit)) {
|
if ((payment != null) && (payment instanceof IZUGFeRDTradeSettlementDebit)) {
|
||||||
@@ -837,12 +843,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trans.getDueDate() != null) {
|
|
||||||
xml += "<ram:DueDateDateTime>" // $NON-NLS-2$
|
|
||||||
+ DATE.udtFormat(trans.getDueDate())
|
|
||||||
+ "</ram:DueDateDateTime>";// 20130704
|
|
||||||
|
|
||||||
}
|
|
||||||
xml += "</ram:SpecifiedTradePaymentTerms>";
|
xml += "</ram:SpecifiedTradePaymentTerms>";
|
||||||
} else {
|
} else {
|
||||||
xml += buildPaymentTermsXml();
|
xml += buildPaymentTermsXml();
|
||||||
@@ -893,6 +893,19 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
}
|
}
|
||||||
xml += "</ram:InvoiceReferencedDocument>";
|
xml += "</ram:InvoiceReferencedDocument>";
|
||||||
}
|
}
|
||||||
|
if (trans.getInvoiceReferencedDocuments() != null) {
|
||||||
|
for (var doc : trans.getInvoiceReferencedDocuments()) {
|
||||||
|
xml += "<ram:InvoiceReferencedDocument>"
|
||||||
|
+ "<ram:IssuerAssignedID>"
|
||||||
|
+ XMLTools.encodeXML(doc.getIssuerAssignedID()) + "</ram:IssuerAssignedID>";
|
||||||
|
if (doc.getFormattedIssueDateTime() != null) {
|
||||||
|
xml += "<ram:FormattedIssueDateTime>"
|
||||||
|
+ DATE.qdtFormat(doc.getFormattedIssueDateTime())
|
||||||
|
+ "</ram:FormattedIssueDateTime>";
|
||||||
|
}
|
||||||
|
xml += "</ram:InvoiceReferencedDocument>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xml += "</ram:ApplicableHeaderTradeSettlement>";
|
xml += "</ram:ApplicableHeaderTradeSettlement>";
|
||||||
// + "<IncludedSupplyChainTradeLineItem>\n"
|
// + "<IncludedSupplyChainTradeLineItem>\n"
|
||||||
|
|||||||
@@ -83,8 +83,9 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] filenameToByteArray(String pdfFilename) throws IOException {
|
protected byte[] filenameToByteArray(String pdfFilename) throws IOException {
|
||||||
FileInputStream fileInputStream = new FileInputStream(pdfFilename);
|
try (FileInputStream fileInputStream = new FileInputStream(pdfFilename)) {
|
||||||
return inputstreamToByteArray(fileInputStream);
|
return inputstreamToByteArray(fileInputStream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] inputstreamToByteArray(InputStream fileInputStream) throws IOException {
|
protected byte[] inputstreamToByteArray(InputStream fileInputStream) throws IOException {
|
||||||
|
|||||||
@@ -659,6 +659,7 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter {
|
|||||||
*
|
*
|
||||||
* @return a List of LineItem instances
|
* @return a List of LineItem instances
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public List<Item> getLineItemList() {
|
public List<Item> getLineItemList() {
|
||||||
final List<Node> nodeList = getLineItemNodes();
|
final List<Node> nodeList = getLineItemNodes();
|
||||||
final List<Item> lineItemList = new ArrayList<>();
|
final List<Item> lineItemList = new ArrayList<>();
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ import java.nio.file.StandardOpenOption;
|
|||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
|
||||||
public class ZUGFeRDInvoiceImporter {
|
public class ZUGFeRDInvoiceImporter {
|
||||||
|
|
||||||
@@ -472,9 +475,11 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
|
|
||||||
xpr = xpath.compile("//*[local-name()=\"SpecifiedTradeSettlementHeaderMonetarySummation\"]/*[local-name()=\"DuePayableAmount\"]|//*[local-name()=\"LegalMonetaryTotal\"]/*[local-name()=\"PayableAmount\"]");
|
xpr = xpath.compile("//*[local-name()=\"SpecifiedTradeSettlementHeaderMonetarySummation\"]/*[local-name()=\"DuePayableAmount\"]|//*[local-name()=\"LegalMonetaryTotal\"]/*[local-name()=\"PayableAmount\"]");
|
||||||
NodeList lineDueNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
NodeList lineDueNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||||
|
BigDecimal duePayableAmount = null;
|
||||||
if (lineDueNodes.getLength() > 0) {
|
if (lineDueNodes.getLength() > 0) {
|
||||||
|
duePayableAmount = new BigDecimal(XMLTools.trimOrNull(lineDueNodes.item(0)));
|
||||||
if (zpp instanceof CalculatedInvoice) {
|
if (zpp instanceof CalculatedInvoice) {
|
||||||
((CalculatedInvoice) zpp).setDuePayable(new BigDecimal(XMLTools.trimOrNull(lineDueNodes.item(0))));
|
((CalculatedInvoice) zpp).setDuePayable(duePayableAmount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -816,6 +821,23 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
}
|
}
|
||||||
zpp.setInvoiceReferencedDocumentID(extractString("//*[local-name()=\"InvoiceReferencedDocument\"]/*[local-name()=\"IssuerAssignedID\"]|//*[local-name()=\"BillingReference\"]/*[local-name()=\"InvoiceDocumentReference\"]/*[local-name()=\"ID\"]"));
|
zpp.setInvoiceReferencedDocumentID(extractString("//*[local-name()=\"InvoiceReferencedDocument\"]/*[local-name()=\"IssuerAssignedID\"]|//*[local-name()=\"BillingReference\"]/*[local-name()=\"InvoiceDocumentReference\"]/*[local-name()=\"ID\"]"));
|
||||||
|
|
||||||
|
xpr = xpath.compile("//*[local-name()=\"InvoiceReferencedDocument\"]");
|
||||||
|
NodeList nodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||||
|
|
||||||
|
if (nodes.getLength() != 0) {
|
||||||
|
for (int i = 0; i < nodes.getLength(); i++) {
|
||||||
|
|
||||||
|
Node currentItemNode = nodes.item(i);
|
||||||
|
ReferencedDocument doc = ReferencedDocument.fromNode(currentItemNode);
|
||||||
|
if (doc != null
|
||||||
|
&& (!Objects.equals(zpp.getInvoiceReferencedDocumentID(), doc.getIssuerAssignedID())
|
||||||
|
|| !Objects.equals(zpp.getInvoiceReferencedIssueDate(), doc.getFormattedIssueDateTime())))
|
||||||
|
{
|
||||||
|
zpp.addInvoiceReferencedDocument(doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
zpp.setOwnOrganisationName(extractString("//*[local-name()=\"SellerTradeParty\"]/*[local-name()=\"Name\"]|//*[local-name()=\"AccountingSupplierParty\"]/*[local-name()=\"Party\"]/*[local-name()=\"PartyName\"]").trim());
|
zpp.setOwnOrganisationName(extractString("//*[local-name()=\"SellerTradeParty\"]/*[local-name()=\"Name\"]|//*[local-name()=\"AccountingSupplierParty\"]/*[local-name()=\"Party\"]/*[local-name()=\"PartyName\"]").trim());
|
||||||
|
|
||||||
String rounding = extractString("//*[local-name()=\"SpecifiedTradeSettlementHeaderMonetarySummation\"]/*[local-name()=\"RoundingAmount\"]|//*[local-name()=\"LegalMonetaryTotal\"]/*[local-name()=\"Party\"]/*[local-name()=\"PayableRoundingAmount\"]");
|
String rounding = extractString("//*[local-name()=\"SpecifiedTradeSettlementHeaderMonetarySummation\"]/*[local-name()=\"RoundingAmount\"]|//*[local-name()=\"LegalMonetaryTotal\"]/*[local-name()=\"Party\"]/*[local-name()=\"PayableRoundingAmount\"]");
|
||||||
@@ -834,7 +856,7 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
xpr = xpath.compile("//*[local-name()=\"IncludedSupplyChainTradeLineItem\"]|//*[local-name()=\"InvoiceLine\"]");
|
xpr = xpath.compile("//*[local-name()=\"IncludedSupplyChainTradeLineItem\"]|//*[local-name()=\"InvoiceLine\"]");
|
||||||
NodeList nodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
nodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||||
|
|
||||||
if (nodes.getLength() != 0) {
|
if (nodes.getLength() != 0) {
|
||||||
for (int i = 0; i < nodes.getLength(); i++) {
|
for (int i = 0; i < nodes.getLength(); i++) {
|
||||||
@@ -938,8 +960,7 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
|
|
||||||
|
|
||||||
TransactionCalculator tc = new TransactionCalculator(zpp);
|
TransactionCalculator tc = new TransactionCalculator(zpp);
|
||||||
String expectedStringTotalGross = tc.getGrandTotal()
|
String calculatedPayableTotal = tc.getDuePayable().toPlainString();
|
||||||
.subtract(Objects.requireNonNullElse(zpp.getTotalPrepaidAmount(), BigDecimal.ZERO)).toPlainString();
|
|
||||||
EStandard whichType;
|
EStandard whichType;
|
||||||
try {
|
try {
|
||||||
whichType = getStandard();
|
whichType = getStandard();
|
||||||
@@ -947,10 +968,21 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
throw new StructureException("Could not find out if it's an invoice, order, or delivery advice", 0);
|
throw new StructureException("Could not find out if it's an invoice, order, or delivery advice", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((whichType != EStandard.despatchadvice)
|
if (whichType != EStandard.despatchadvice && !ignoreCalculationErrors) {
|
||||||
&& ((!expectedStringTotalGross.equals(XMLTools.nDigitFormat(expectedGrandTotal, 2)))
|
// Check calculation if document type allows it and calculation errors should not be ignored
|
||||||
&& (!ignoreCalculationErrors))) {
|
|
||||||
throw new ArithmetricException();
|
String payableTotalFromXml = XMLTools.nDigitFormat(Objects.requireNonNullElse(duePayableAmount, expectedGrandTotal), 2);
|
||||||
|
if (!calculatedPayableTotal.equals(payableTotalFromXml)) {
|
||||||
|
String moreDetails = "";
|
||||||
|
try {
|
||||||
|
moreDetails = " with tax basis " + tc.getTaxBasis() + " and with positions " + tc.getTotal() + " = "
|
||||||
|
+ Stream.of(tc.trans.getZFItems())
|
||||||
|
.map(item -> new LineCalculator(item).getItemTotalNetAmount().toPlainString())
|
||||||
|
.collect(Collectors.joining(" + "));
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
throw new ArithmetricException("Payable total in XML is " + payableTotalFromXml + ", but calculated total is " + calculatedPayableTotal + moreDetails);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return zpp;
|
return zpp;
|
||||||
@@ -1036,6 +1068,7 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
* for PDF embedded files in FX use getFileAttachmentsPDF()
|
* for PDF embedded files in FX use getFileAttachmentsPDF()
|
||||||
* @deprecated use invoice.getAdditionalReferencedDocuments
|
* @deprecated use invoice.getAdditionalReferencedDocuments
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public List<FileAttachment> getFileAttachmentsXML() {
|
public List<FileAttachment> getFileAttachmentsXML() {
|
||||||
return new ArrayList<>(Arrays.asList(importedInvoice.getAdditionalReferencedDocuments()));
|
return new ArrayList<>(Arrays.asList(importedInvoice.getAdditionalReferencedDocuments()));
|
||||||
}
|
}
|
||||||
@@ -1067,5 +1100,4 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
LOGGER.error(e.getMessage(), e);
|
LOGGER.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,42 +20,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.mustangproject.ZUGFeRD;
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
import java.io.BufferedOutputStream;
|
import com.helger.commons.io.stream.StreamHelper;
|
||||||
import java.io.ByteArrayInputStream;
|
import org.apache.commons.io.IOUtils;
|
||||||
import java.io.ByteArrayOutputStream;
|
import org.apache.fop.apps.*;
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.PipedInputStream;
|
|
||||||
import java.io.PipedOutputStream;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
import javax.xml.transform.Result;
|
|
||||||
import javax.xml.transform.Source;
|
|
||||||
import javax.xml.transform.Templates;
|
|
||||||
import javax.xml.transform.Transformer;
|
|
||||||
import javax.xml.transform.TransformerConfigurationException;
|
|
||||||
import javax.xml.transform.TransformerException;
|
|
||||||
import javax.xml.transform.TransformerFactory;
|
|
||||||
import javax.xml.transform.URIResolver;
|
|
||||||
import javax.xml.transform.sax.SAXResult;
|
|
||||||
import javax.xml.transform.stream.StreamResult;
|
|
||||||
import javax.xml.transform.stream.StreamSource;
|
|
||||||
|
|
||||||
import org.apache.fop.apps.FOPException;
|
|
||||||
import org.apache.fop.apps.FOUserAgent;
|
|
||||||
import org.apache.fop.apps.Fop;
|
|
||||||
import org.apache.fop.apps.FopFactory;
|
|
||||||
import org.apache.fop.apps.FopFactoryBuilder;
|
|
||||||
import org.apache.fop.apps.io.ResourceResolverFactory;
|
import org.apache.fop.apps.io.ResourceResolverFactory;
|
||||||
import org.apache.fop.configuration.Configuration;
|
import org.apache.fop.configuration.Configuration;
|
||||||
import org.apache.fop.configuration.ConfigurationException;
|
import org.apache.fop.configuration.ConfigurationException;
|
||||||
@@ -65,12 +32,19 @@ import org.mustangproject.ClasspathResolverURIAdapter;
|
|||||||
import org.mustangproject.EStandard;
|
import org.mustangproject.EStandard;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.helger.commons.io.stream.StreamHelper;
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.transform.*;
|
||||||
|
import javax.xml.transform.sax.SAXResult;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class ZUGFeRDVisualizer {
|
public class ZUGFeRDVisualizer {
|
||||||
|
|
||||||
@@ -113,7 +87,7 @@ public class ZUGFeRDVisualizer {
|
|||||||
* @param fis inputstream (will be consumed)
|
* @param fis inputstream (will be consumed)
|
||||||
* @return (facturx = cii)
|
* @return (facturx = cii)
|
||||||
*/
|
*/
|
||||||
public EStandard findOutStandardFromRootNode(InputStream fis) {
|
private EStandard findOutStandardFromRootNode(InputStream fis) {
|
||||||
|
|
||||||
String zf1Signature = "CrossIndustryDocument";
|
String zf1Signature = "CrossIndustryDocument";
|
||||||
String zf2Signature = "CrossIndustryInvoice";
|
String zf2Signature = "CrossIndustryInvoice";
|
||||||
@@ -144,106 +118,97 @@ public class ZUGFeRDVisualizer {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String visualize(String xmlFilename, Language lang)
|
public String visualize(String xmlFilename, Language lang) throws IOException, TransformerException {
|
||||||
throws FileNotFoundException, TransformerException, IOException, SAXException, ParserConfigurationException {
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (mXsltPDFTemplate == null) {
|
|
||||||
mXsltPDFTemplate = mFactory.newTemplates(
|
|
||||||
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xr-pdf.xsl")));
|
|
||||||
}
|
|
||||||
if (mXsltHTMLTemplate == null) {
|
|
||||||
mXsltHTMLTemplate = mFactory.newTemplates(new StreamSource(
|
|
||||||
CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xrechnung-html." + lang.name().toLowerCase() + ".xsl")));
|
|
||||||
}
|
|
||||||
if (mXsltZF1HTMLTemplate == null) {
|
|
||||||
mXsltZF1HTMLTemplate = mFactory.newTemplates(new StreamSource(
|
|
||||||
CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt")));
|
|
||||||
}
|
|
||||||
} catch (TransformerConfigurationException ex) {
|
|
||||||
LOGGER.error("Failed to init XSLT templates", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* *
|
|
||||||
* http://www.unece.org/fileadmin/DAM/cefact/xml/XML-Naming-And-Design-Rules-V2_1.pdf
|
|
||||||
* http://www.ferd-net.de/upload/Dokumente/FACTUR-X_ZUGFeRD_2p0_Teil1_Profil_EN16931_1p03.pdf
|
|
||||||
* http://countwordsfree.com/xmlviewer
|
|
||||||
*/
|
|
||||||
FileInputStream fis = new FileInputStream(xmlFilename);
|
FileInputStream fis = new FileInputStream(xmlFilename);
|
||||||
String fileContent = "";
|
return visualize(fis, lang);
|
||||||
try {
|
}
|
||||||
fileContent = new String(Files.readAllBytes(Paths.get(xmlFilename)), StandardCharsets.UTF_8);
|
|
||||||
} catch (IOException e2) {
|
|
||||||
LOGGER.error("Failed to read file content", e2);
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteArrayOutputStream iaos = new ByteArrayOutputStream();
|
public String visualize(InputStream inputXml, Language lang) throws IOException, TransformerException {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
initTemplates(lang);
|
||||||
|
|
||||||
boolean doPostProcessing = false;
|
String fileContent = new String(IOUtils.toByteArray(inputXml), StandardCharsets.UTF_8);
|
||||||
|
EStandard thestandard = findOutStandardFromRootNode(new ByteArrayInputStream(fileContent.getBytes(StandardCharsets.UTF_8)));
|
||||||
|
ByteArrayOutputStream htmlOutput = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
|
||||||
fis = new FileInputStream(xmlFilename); // fis wont reset() so re-read from beginning
|
ByteArrayInputStream xmlContentStream = new ByteArrayInputStream(fileContent.getBytes(StandardCharsets.UTF_8));
|
||||||
EStandard thestandard = findOutStandardFromRootNode(fis);
|
|
||||||
fis = new FileInputStream(xmlFilename); // fis wont reset() so re-read from beginning
|
|
||||||
|
|
||||||
if (thestandard == EStandard.zugferd) {
|
if (thestandard == EStandard.zugferd) {
|
||||||
applyZF1XSLT(fis, baos);
|
applyZF1XSLT(xmlContentStream, htmlOutput);
|
||||||
|
return htmlOutput.toString(StandardCharsets.UTF_8);
|
||||||
} else if (thestandard == EStandard.facturx) {
|
} else if (thestandard == EStandard.facturx) {
|
||||||
//zf2 or fx
|
//zf2 or fx
|
||||||
applyZF2XSLT(fis, iaos);
|
applyZF2XSLT(xmlContentStream, htmlOutput);
|
||||||
doPostProcessing = true;
|
|
||||||
} else if (thestandard == EStandard.ubl) {
|
} else if (thestandard == EStandard.ubl) {
|
||||||
//zf2 or fx
|
//zf2 or fx
|
||||||
applyUBL2XSLT(fis, iaos);
|
applyUBL2XSLT(xmlContentStream, htmlOutput);
|
||||||
doPostProcessing = true;
|
|
||||||
} else if (thestandard == EStandard.ubl_creditnote) {
|
} else if (thestandard == EStandard.ubl_creditnote) {
|
||||||
//zf2 or fx
|
//zf2 or fx
|
||||||
applyUBLCreditNote2XSLT(fis, iaos);
|
applyUBLCreditNote2XSLT(xmlContentStream, htmlOutput);
|
||||||
doPostProcessing = true;
|
|
||||||
} else if (thestandard == EStandard.orderx) {
|
} else if (thestandard == EStandard.orderx) {
|
||||||
//zf2 or fx
|
//zf2 or fx
|
||||||
applyCIO2XSLT(fis, iaos);
|
applyCIO2XSLT(xmlContentStream, htmlOutput);
|
||||||
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");
|
||||||
}
|
}
|
||||||
if (doPostProcessing) {
|
Optional<InputStream> in = copyStream(htmlOutput);
|
||||||
// take the copy of the stream and re-write it to an InputStream
|
ByteArrayOutputStream htmlOutStream = new ByteArrayOutputStream();
|
||||||
PipedInputStream in = new PipedInputStream();
|
if (in.isPresent()) {
|
||||||
PipedOutputStream out;
|
applyXSLTToHTML(in.get(), htmlOutStream);
|
||||||
try {
|
|
||||||
out = new PipedOutputStream(in);
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
// write the original OutputStream to the PipedOutputStream
|
|
||||||
// note that in order for the below method to work, you need
|
|
||||||
// to ensure that the data has finished writing to the
|
|
||||||
// ByteArrayOutputStream
|
|
||||||
iaos.writeTo(out);
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOGGER.error("Failed to write to stream", e);
|
|
||||||
} finally {
|
|
||||||
// close the PipedOutputStream here because we're done writing data
|
|
||||||
// once this thread has completed its run
|
|
||||||
StreamHelper.close(out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
applyXSLTToHTML(in, baos);
|
|
||||||
} catch (IOException e1) {
|
|
||||||
LOGGER.error("Failed to create HTML", e1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return baos.toString(StandardCharsets.UTF_8);
|
return htmlOutStream.toString(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: jstaerk: why not copy with that simple call: new ByteArrayInputStream(byteArrayOutputStream.toByteArray()) ?
|
||||||
|
*/
|
||||||
|
private Optional<InputStream> copyStream(ByteArrayOutputStream byteArrayOutputStream) {
|
||||||
|
// take the copy of the stream and re-write it to an InputStream
|
||||||
|
PipedInputStream in = new PipedInputStream();
|
||||||
|
try {
|
||||||
|
PipedOutputStream out = new PipedOutputStream(in);
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
// write the original OutputStream to the PipedOutputStream
|
||||||
|
// note that in order for the below method to work, you need
|
||||||
|
// to ensure that the data has finished writing to the
|
||||||
|
// ByteArrayOutputStream
|
||||||
|
byteArrayOutputStream.writeTo(out);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.error("Failed to write to stream", e);
|
||||||
|
} finally {
|
||||||
|
// close the PipedOutputStream here because we're done writing data
|
||||||
|
// once this thread has completed its run
|
||||||
|
StreamHelper.close(out);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
} catch (IOException e1) {
|
||||||
|
LOGGER.error("Failed to create HTML", e1);
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
return Optional.of(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void initTemplates(Language lang) throws TransformerConfigurationException {
|
||||||
|
if (mXsltXRTemplate == null) {
|
||||||
|
mXsltXRTemplate = mFactory.newTemplates(
|
||||||
|
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/cii-xr.xsl")));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mXsltHTMLTemplate == null) {
|
||||||
|
mXsltHTMLTemplate = mFactory.newTemplates(new StreamSource(
|
||||||
|
CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xrechnung-html." + lang.name().toLowerCase() + ".xsl")));
|
||||||
|
}
|
||||||
|
if (mXsltZF1HTMLTemplate == null) {
|
||||||
|
mXsltZF1HTMLTemplate = mFactory.newTemplates(new StreamSource(
|
||||||
|
CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String toFOP(String xmlFilename)
|
protected String toFOP(String xmlFilename)
|
||||||
throws FileNotFoundException, TransformerException {
|
throws IOException, TransformerException {
|
||||||
|
|
||||||
FileInputStream fis = new FileInputStream(xmlFilename);
|
FileInputStream fis = new FileInputStream(xmlFilename);
|
||||||
EStandard theStandard = findOutStandardFromRootNode(fis);
|
EStandard theStandard = findOutStandardFromRootNode(fis);
|
||||||
@@ -253,7 +218,7 @@ public class ZUGFeRDVisualizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected String toFOP(InputStream is, EStandard theStandard)
|
protected String toFOP(InputStream is, EStandard theStandard)
|
||||||
throws FileNotFoundException, TransformerException {
|
throws TransformerException, IOException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (mXsltPDFTemplate == null) {
|
if (mXsltPDFTemplate == null) {
|
||||||
@@ -265,7 +230,6 @@ public class ZUGFeRDVisualizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ByteArrayOutputStream iaos = new ByteArrayOutputStream();
|
ByteArrayOutputStream iaos = new ByteArrayOutputStream();
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
//zf2 or fx
|
//zf2 or fx
|
||||||
if (theStandard == EStandard.facturx) {
|
if (theStandard == EStandard.facturx) {
|
||||||
@@ -277,33 +241,11 @@ public class ZUGFeRDVisualizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PipedInputStream in = new PipedInputStream();
|
Optional<InputStream> in = copyStream(iaos);
|
||||||
PipedOutputStream out;
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
try {
|
if (in.isPresent()) {
|
||||||
out = new PipedOutputStream(in);
|
applyXSLTToPDF(in.get(), baos);
|
||||||
new Thread(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
// write the original OutputStream to the PipedOutputStream
|
|
||||||
// note that in order for the below method to work, you need
|
|
||||||
// to ensure that the data has finished writing to the
|
|
||||||
// ByteArrayOutputStream
|
|
||||||
iaos.writeTo(out);
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOGGER.error("Failed to write to stream", e);
|
|
||||||
} finally {
|
|
||||||
// close the PipedOutputStream here because we're done writing data
|
|
||||||
// once this thread has completed its run
|
|
||||||
StreamHelper.close(out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
applyXSLTToPDF(in, baos);
|
|
||||||
} catch (IOException e1) {
|
|
||||||
LOGGER.error("Failed to create PDF", e1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return baos.toString(StandardCharsets.UTF_8);
|
return baos.toString(StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +261,7 @@ public class ZUGFeRDVisualizer {
|
|||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
result = this.toFOP(XMLinputFile.getAbsolutePath());
|
result = this.toFOP(XMLinputFile.getAbsolutePath());
|
||||||
} catch (FileNotFoundException | TransformerException e) {
|
} catch (TransformerException | IOException e) {
|
||||||
LOGGER.error("Failed to apply FOP", e);
|
LOGGER.error("Failed to apply FOP", e);
|
||||||
}
|
}
|
||||||
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
|
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
|
||||||
@@ -373,7 +315,7 @@ public class ZUGFeRDVisualizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void applyZF2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
protected void applyZF2XSLT(final InputStream xmlFile, final OutputStream htmlOutStream)
|
||||||
throws TransformerException {
|
throws TransformerException {
|
||||||
if (mXsltXRTemplate == null) {
|
if (mXsltXRTemplate == null) {
|
||||||
mXsltXRTemplate = mFactory.newTemplates(
|
mXsltXRTemplate = mFactory.newTemplates(
|
||||||
@@ -382,10 +324,10 @@ public class ZUGFeRDVisualizer {
|
|||||||
}
|
}
|
||||||
Transformer transformer = mXsltXRTemplate.newTransformer();
|
Transformer transformer = mXsltXRTemplate.newTransformer();
|
||||||
|
|
||||||
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)
|
protected void applyCIO2XSLT(final InputStream xmlFile, final OutputStream htmlOutstream)
|
||||||
throws TransformerException {
|
throws TransformerException {
|
||||||
if (mXsltCIOTemplate == null) {
|
if (mXsltCIOTemplate == null) {
|
||||||
mXsltCIOTemplate = mFactory.newTemplates(
|
mXsltCIOTemplate = mFactory.newTemplates(
|
||||||
@@ -393,10 +335,10 @@ public class ZUGFeRDVisualizer {
|
|||||||
}
|
}
|
||||||
Transformer transformer = mXsltCIOTemplate.newTransformer();
|
Transformer transformer = mXsltCIOTemplate.newTransformer();
|
||||||
|
|
||||||
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
|
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) {
|
||||||
mXsltUBLTemplate = mFactory.newTemplates(
|
mXsltUBLTemplate = mFactory.newTemplates(
|
||||||
@@ -404,10 +346,10 @@ public class ZUGFeRDVisualizer {
|
|||||||
}
|
}
|
||||||
Transformer transformer = mXsltUBLTemplate.newTransformer();
|
Transformer transformer = mXsltUBLTemplate.newTransformer();
|
||||||
|
|
||||||
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
|
transformer.transform(new StreamSource(xmlFile), new StreamResult(htmlOutStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void applyUBLCreditNote2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
protected void applyUBLCreditNote2XSLT(final InputStream xmlFile, final OutputStream htmlOutStream)
|
||||||
throws TransformerException {
|
throws TransformerException {
|
||||||
if (mXsltUBLTemplate == null) {
|
if (mXsltUBLTemplate == null) {
|
||||||
mXsltUBLTemplate = mFactory.newTemplates(
|
mXsltUBLTemplate = mFactory.newTemplates(
|
||||||
@@ -415,28 +357,30 @@ public class ZUGFeRDVisualizer {
|
|||||||
}
|
}
|
||||||
Transformer transformer = mXsltUBLTemplate.newTransformer();
|
Transformer transformer = mXsltUBLTemplate.newTransformer();
|
||||||
|
|
||||||
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
|
transformer.transform(new StreamSource(xmlFile), new StreamResult(htmlOutStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void applyZF1XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
protected void applyZF1XSLT(final InputStream xmlFile, final OutputStream htmlOutStream)
|
||||||
throws TransformerException {
|
throws TransformerException {
|
||||||
Transformer transformer = mXsltZF1HTMLTemplate.newTransformer();
|
Transformer transformer = mXsltZF1HTMLTemplate.newTransformer();
|
||||||
|
|
||||||
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
|
transformer.transform(new StreamSource(xmlFile), new StreamResult(htmlOutStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void applyXSLTToHTML(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
protected void applyXSLTToHTML(final InputStream xmlFile, final OutputStream htmlOutStream)
|
||||||
throws TransformerException {
|
throws TransformerException, IOException {
|
||||||
Transformer transformer = mXsltHTMLTemplate.newTransformer();
|
Transformer transformer = mXsltHTMLTemplate.newTransformer();
|
||||||
|
|
||||||
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
|
transformer.transform(new StreamSource(xmlFile), new StreamResult(htmlOutStream));
|
||||||
|
xmlFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void applyXSLTToPDF(final InputStream xmlFile, final OutputStream PDFOutstream)
|
protected void applyXSLTToPDF(final InputStream xmlFile, final OutputStream PDFOutstream)
|
||||||
throws TransformerException {
|
throws TransformerException, IOException {
|
||||||
Transformer transformer = mXsltPDFTemplate.newTransformer();
|
Transformer transformer = mXsltPDFTemplate.newTransformer();
|
||||||
|
|
||||||
transformer.transform(new StreamSource(xmlFile), new StreamResult(PDFOutstream));
|
transformer.transform(new StreamSource(xmlFile), new StreamResult(PDFOutstream));
|
||||||
|
xmlFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ClasspathResourceURIResolver implements URIResolver {
|
private static class ClasspathResourceURIResolver implements URIResolver {
|
||||||
@@ -445,7 +389,7 @@ public class ZUGFeRDVisualizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Source resolve(String href, String base) throws TransformerException {
|
public Source resolve(String href, String base) {
|
||||||
return new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/" + href));
|
return new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/" + href));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ public class TaxCategoryCodeTypeConstants {
|
|||||||
public static final String ZEROTAXPRODUCTS = "Z";
|
public static final String ZEROTAXPRODUCTS = "Z";
|
||||||
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 final String FREEEXPORT = "G";
|
||||||
|
|
||||||
public static Set<String> CATEGORY_CODES_WITH_EXEMPTION_REASON = Stream.of(INTRACOMMUNITY, REVERSECHARGE, TAXEXEMPT).collect(Collectors.toSet());
|
public static Set<String> CATEGORY_CODES_WITH_EXEMPTION_REASON = Stream.of(INTRACOMMUNITY, REVERSECHARGE, TAXEXEMPT, FREEEXPORT).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
library/src/main/resources/fonts/SourceSansPro-Bold.ttf
Normal file
BIN
library/src/main/resources/fonts/SourceSansPro-Bold.ttf
Normal file
Binary file not shown.
BIN
library/src/main/resources/fonts/SourceSansPro-BoldIt.ttf
Normal file
BIN
library/src/main/resources/fonts/SourceSansPro-BoldIt.ttf
Normal file
Binary file not shown.
BIN
library/src/main/resources/fonts/SourceSansPro-It.ttf
Normal file
BIN
library/src/main/resources/fonts/SourceSansPro-It.ttf
Normal file
Binary file not shown.
BIN
library/src/main/resources/fonts/SourceSansPro-Regular.ttf
Normal file
BIN
library/src/main/resources/fonts/SourceSansPro-Regular.ttf
Normal file
Binary file not shown.
BIN
library/src/main/resources/fonts/SourceSerifPro-Bold.ttf
Normal file
BIN
library/src/main/resources/fonts/SourceSerifPro-Bold.ttf
Normal file
Binary file not shown.
BIN
library/src/main/resources/fonts/SourceSerifPro-BoldIt.ttf
Normal file
BIN
library/src/main/resources/fonts/SourceSerifPro-BoldIt.ttf
Normal file
Binary file not shown.
BIN
library/src/main/resources/fonts/SourceSerifPro-It.ttf
Normal file
BIN
library/src/main/resources/fonts/SourceSerifPro-It.ttf
Normal file
Binary file not shown.
BIN
library/src/main/resources/fonts/SourceSerifPro-Regular.ttf
Normal file
BIN
library/src/main/resources/fonts/SourceSerifPro-Regular.ttf
Normal file
Binary file not shown.
@@ -22,16 +22,36 @@
|
|||||||
<!-- etc. etc..... -->
|
<!-- etc. etc..... -->
|
||||||
|
|
||||||
<renderers>
|
<renderers>
|
||||||
<renderer mime="application/pdf">
|
<renderer mime="application/pdf">
|
||||||
<fonts><!-- https://xmlgraphics.apache.org/fop/1.1/fonts.html auto-embed -->
|
<fonts>
|
||||||
<auto-detect/>
|
<!-- https://xmlgraphics.apache.org/fop/1.1/fonts.html auto-embed -->
|
||||||
<font kerning="no" embed-url="classpath:FreeSans.ttf" embedding-mode="subset">
|
<auto-detect/>
|
||||||
<font-triplet name="SourceSerifPro" style="normal" weight="normal" />
|
<font kerning="yes" embed-url="classpath:fonts/SourceSansPro-Regular.ttf" embedding-mode="subset">
|
||||||
<font-triplet name="Times-Bold" style="normal" weight="normal" />
|
<font-triplet name="SourceSansPro" style="normal" weight="400"/>
|
||||||
</font>
|
</font>
|
||||||
</fonts>
|
<font kerning="yes" embed-url="classpath:fonts/SourceSansPro-It.ttf" embedding-mode="subset">
|
||||||
<output-profile>classpath:AdobeCompat-v2.icc</output-profile>
|
<font-triplet name="SourceSansPro" style="italic" weight="400"/>
|
||||||
</renderer>
|
</font>
|
||||||
</renderers>
|
<font kerning="yes" embed-url="classpath:fonts/SourceSansPro-Bold.ttf" embedding-mode="subset">
|
||||||
|
<font-triplet name="SourceSansPro" style="normal" weight="700"/>
|
||||||
|
</font>
|
||||||
|
<font kerning="yes" embed-url="classpath:fonts/SourceSansPro-BoldIt.ttf" embedding-mode="subset">
|
||||||
|
<font-triplet name="SourceSansPro" style="italic" weight="700"/>
|
||||||
|
</font>
|
||||||
|
<font kerning="yes" embed-url="classpath:fonts/SourceSerifPro-Regular.ttf" embedding-mode="subset">
|
||||||
|
<font-triplet name="SourceSerifPro" style="normal" weight="400"/>
|
||||||
|
</font>
|
||||||
|
<font kerning="yes" embed-url="classpath:fonts/SourceSerifPro-It.ttf" embedding-mode="subset">
|
||||||
|
<font-triplet name="SourceSerifPro" style="italic" weight="400"/>
|
||||||
|
</font>
|
||||||
|
<font kerning="yes" embed-url="classpath:fonts/SourceSerifPro-Bold.ttf" embedding-mode="subset">
|
||||||
|
<font-triplet name="SourceSerifPro" style="normal" weight="700"/>
|
||||||
|
</font>
|
||||||
|
<font kerning="yes" embed-url="classpath:fonts/SourceSerifPro-BoldIt.ttf" embedding-mode="subset">
|
||||||
|
<font-triplet name="SourceSerifPro" style="italic" weight="700"/>
|
||||||
|
</font>
|
||||||
|
</fonts>
|
||||||
|
<output-profile>classpath:AdobeCompat-v2.icc</output-profile>
|
||||||
|
</renderer>
|
||||||
|
</renderers>
|
||||||
</fop>
|
</fop>
|
||||||
|
|||||||
@@ -98,6 +98,8 @@
|
|||||||
select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ReceivingAdviceReferencedDocument/ram:IssuerAssignedID"/>
|
select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ReceivingAdviceReferencedDocument/ram:IssuerAssignedID"/>
|
||||||
<xsl:apply-templates mode="BT-16"
|
<xsl:apply-templates mode="BT-16"
|
||||||
select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:DespatchAdviceReferencedDocument/ram:IssuerAssignedID"/>
|
select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:DespatchAdviceReferencedDocument/ram:IssuerAssignedID"/>
|
||||||
|
<xsl:apply-templates mode="BT-X-202"
|
||||||
|
select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssuerAssignedID"/>
|
||||||
<xsl:apply-templates mode="BT-17"
|
<xsl:apply-templates mode="BT-17"
|
||||||
select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument/ram:IssuerAssignedID[following-sibling::ram:TypeCode='50']"/>
|
select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument/ram:IssuerAssignedID[following-sibling::ram:TypeCode='50']"/>
|
||||||
<xsl:apply-templates mode="BT-18"
|
<xsl:apply-templates mode="BT-18"
|
||||||
@@ -295,6 +297,14 @@
|
|||||||
<xr:Receiving_advice_reference>
|
<xr:Receiving_advice_reference>
|
||||||
<xsl:attribute name="xr:id" select="'BT-15'"/>
|
<xsl:attribute name="xr:id" select="'BT-15'"/>
|
||||||
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="../ram:FormattedIssueDateTime/qdt:DateTimeString[@format = '102']">
|
||||||
|
<xsl:call-template name="dateAsAttribute">
|
||||||
|
<xsl:with-param name="dateString" select="../ram:FormattedIssueDateTime/qdt:DateTimeString[@format = '102']"/>
|
||||||
|
<xsl:with-param name="attributeName" select="'bt-x-201'"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
<xsl:call-template name="document_reference"/>
|
<xsl:call-template name="document_reference"/>
|
||||||
</xr:Receiving_advice_reference>
|
</xr:Receiving_advice_reference>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
@@ -303,9 +313,33 @@
|
|||||||
<xr:Despatch_advice_reference>
|
<xr:Despatch_advice_reference>
|
||||||
<xsl:attribute name="xr:id" select="'BT-16'"/>
|
<xsl:attribute name="xr:id" select="'BT-16'"/>
|
||||||
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="../ram:FormattedIssueDateTime/qdt:DateTimeString[@format = '102']">
|
||||||
|
<xsl:call-template name="dateAsAttribute">
|
||||||
|
<xsl:with-param name="dateString" select="../ram:FormattedIssueDateTime/qdt:DateTimeString[@format = '102']"/>
|
||||||
|
<xsl:with-param name="attributeName" select="'bt-x-200'"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
<xsl:call-template name="document_reference"/>
|
<xsl:call-template name="document_reference"/>
|
||||||
</xr:Despatch_advice_reference>
|
</xr:Despatch_advice_reference>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
<xsl:template mode="BT-X-202"
|
||||||
|
match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssuerAssignedID">
|
||||||
|
<xr:Delivery_note_reference>
|
||||||
|
<xsl:attribute name="xr:id" select="'BT-X-202'"/>
|
||||||
|
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="../ram:FormattedIssueDateTime/qdt:DateTimeString[@format = '102']">
|
||||||
|
<xsl:call-template name="dateAsAttribute">
|
||||||
|
<xsl:with-param name="dateString" select="../ram:FormattedIssueDateTime/qdt:DateTimeString[@format = '102']"/>
|
||||||
|
<xsl:with-param name="attributeName" select="'bt-x-203'"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
<xsl:call-template name="document_reference"/>
|
||||||
|
</xr:Delivery_note_reference>
|
||||||
|
</xsl:template>
|
||||||
<xsl:template mode="BT-17"
|
<xsl:template mode="BT-17"
|
||||||
match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument/ram:IssuerAssignedID[following-sibling::ram:TypeCode='50']">
|
match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument/ram:IssuerAssignedID[following-sibling::ram:TypeCode='50']">
|
||||||
<xr:Tender_or_lot_reference>
|
<xr:Tender_or_lot_reference>
|
||||||
@@ -2437,8 +2471,9 @@
|
|||||||
<xsl:template name="text">
|
<xsl:template name="text">
|
||||||
<xsl:value-of select="."/>
|
<xsl:value-of select="."/>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template name="date">
|
<xsl:template name="date">
|
||||||
<xsl:variable name="normalizeddate" select="normalize-space(replace(., '-', ''))"/>
|
<xsl:variable name="normalizeddate" select="normalize-space(replace(., '-', ''))"/>
|
||||||
<xsl:choose>
|
<xsl:choose>
|
||||||
<xsl:when test="matches($normalizeddate, '^[0-9]{8}$')">
|
<xsl:when test="matches($normalizeddate, '^[0-9]{8}$')">
|
||||||
<xsl:value-of
|
<xsl:value-of
|
||||||
@@ -2453,6 +2488,24 @@
|
|||||||
</xsl:otherwise>
|
</xsl:otherwise>
|
||||||
</xsl:choose>
|
</xsl:choose>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
<xsl:template name="dateAsAttribute">
|
||||||
|
<xsl:param name="dateString"/>
|
||||||
|
<xsl:param name="attributeName" select="'date'"/>
|
||||||
|
<xsl:variable name="normalizeddate" select="normalize-space(replace($dateString, '-', ''))"/>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="matches($normalizeddate, '^[0-9]{8}$')">
|
||||||
|
<xsl:attribute name="{$attributeName}"
|
||||||
|
select="xs:date( concat(substring($normalizeddate,1,4), '-', substring($normalizeddate,5,2), '-', substring($normalizeddate,7,2) ) )"/>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>ILLEGAL DATE FORMAT: <para>Mit diesem Datentyp wird ein kalendarisches Datum
|
||||||
|
abgebildet, wie es in der ISO 8601 Spezifikation <quote>Calendar date complete representation</quote>
|
||||||
|
beschrieben ist (siehe ISO 8601:2004, Abschnitt 5.2.1.1). Das Datum beinhaltet keine Zeitangabe. Das
|
||||||
|
konkret zu verwendende Format ist abhängig von der genutzten Syntax.</para>
|
||||||
|
<para>Der Datentyp basiert auf dem Typ <quote>Date Time. Type</quote>, wie in ISO
|
||||||
|
15000-5:2014 Anhang B definiert.</para>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
</xsl:template>
|
||||||
<xsl:template name="identifier-with-scheme-and-version">
|
<xsl:template name="identifier-with-scheme-and-version">
|
||||||
<xsl:param name="schemeID" as="element()?"/>
|
<xsl:param name="schemeID" as="element()?"/>
|
||||||
<xsl:if test="@listID | @schemeID">
|
<xsl:if test="@listID | @schemeID">
|
||||||
|
|||||||
243
library/src/main/resources/stylesheets/result-pdf.xsl
Normal file
243
library/src/main/resources/stylesheets/result-pdf.xsl
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xsl:stylesheet xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions"
|
||||||
|
xmlns:fo="http://www.w3.org/1999/XSL/Format"
|
||||||
|
xmlns:pdf="http://xmlgraphics.apache.org/fop/extensions/pdf"
|
||||||
|
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||||
|
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||||
|
version="2.0">
|
||||||
|
<!-- Imports -->
|
||||||
|
<xsl:import href="common-xr.xsl"/>
|
||||||
|
<xsl:import href="xr-pdf/lib/konstanten.xsl"/>
|
||||||
|
<!--
|
||||||
|
FO engine used can be specified.
|
||||||
|
Specific extensions will be then enabled.
|
||||||
|
Supported values are:
|
||||||
|
axf - Antenna House XSL Formatter
|
||||||
|
fop - Apache FOP
|
||||||
|
-->
|
||||||
|
<xsl:param name="foengine"/>
|
||||||
|
<xsl:param name="axf.extensions"
|
||||||
|
select="if ($foengine eq 'axf') then true() else false()"/>
|
||||||
|
<xsl:param name="fop.extensions"
|
||||||
|
select="if ($foengine eq 'fop') then true() else false()"/>
|
||||||
|
<xsl:variable name="xml_result_color">
|
||||||
|
<xsl:if test="/validation/xml/summary/@status = 'valid'">
|
||||||
|
<xsl:text>green</xsl:text>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:if test="/validation/xml/summary/@status = 'invalid'">
|
||||||
|
<xsl:text>red</xsl:text>
|
||||||
|
</xsl:if>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:variable name="pdf_result_color">
|
||||||
|
<xsl:if test="/validation/pdf/summary/@status = 'valid'">
|
||||||
|
<xsl:text>green</xsl:text>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:if test="/validation/pdf/summary/@status = 'invalid'">
|
||||||
|
<xsl:text>red</xsl:text>
|
||||||
|
</xsl:if>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:variable name="pdf_result_text">
|
||||||
|
<xsl:if test="/validation/xml/summary/@status = 'valid'">
|
||||||
|
<xsl:text>Das ZUGFeRD-PDF ist valide.</xsl:text>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:if test="/validation/xml/summary/@status = 'invalid'">
|
||||||
|
<xsl:text>Das ZUGFeRD-PDF ist nicht valide.</xsl:text>
|
||||||
|
</xsl:if>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:variable name="result_text">
|
||||||
|
<xsl:if test="/validation/xml/summary/@status = 'valid'">
|
||||||
|
<xsl:text>Es wird empfohlen, das Dokument anzunehmen und weiterzuverarbeiten.</xsl:text>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:if test="/validation/xml/summary/@status = 'invalid'">
|
||||||
|
<xsl:text>Es wird empfohlen, das Dokument zurückzuweisen.</xsl:text>
|
||||||
|
</xsl:if>
|
||||||
|
</xsl:variable>
|
||||||
|
<xsl:template match="validation">
|
||||||
|
<fo:root language="{$lang}"
|
||||||
|
font-family="{$fontSans}">
|
||||||
|
<fo:layout-master-set>
|
||||||
|
<fo:simple-page-master master-name="DIN-A4"
|
||||||
|
page-height="297mm"
|
||||||
|
page-width="210mm">
|
||||||
|
<fo:region-body region-name="body"
|
||||||
|
margin="20mm 10mm 20mm 20mm"/>
|
||||||
|
</fo:simple-page-master>
|
||||||
|
</fo:layout-master-set>
|
||||||
|
<fo:page-sequence master-reference="DIN-A4">
|
||||||
|
<fo:flow flow-name="body">
|
||||||
|
<fo:block font-size="24px"
|
||||||
|
font-weight="bold">
|
||||||
|
<xsl:text>Prüfbericht</xsl:text>
|
||||||
|
</fo:block>
|
||||||
|
<xsl:call-template name="SubHeader">
|
||||||
|
<xsl:with-param name="text"
|
||||||
|
select=""Angaben zum geprüften Dokument""/>
|
||||||
|
<xsl:with-param name="color"
|
||||||
|
select=""black""/>
|
||||||
|
</xsl:call-template>
|
||||||
|
<fo:block>
|
||||||
|
<fo:block text-align="justify">
|
||||||
|
<fo:float float="right">
|
||||||
|
<fo:block>
|
||||||
|
<xsl:value-of select="/validation/@filename"/>
|
||||||
|
</fo:block>
|
||||||
|
</fo:float>
|
||||||
|
<xsl:text>Referenz:</xsl:text>
|
||||||
|
</fo:block>
|
||||||
|
</fo:block>
|
||||||
|
<fo:block>
|
||||||
|
<fo:block text-align="justify">
|
||||||
|
<fo:float float="right">
|
||||||
|
<fo:block>
|
||||||
|
<xsl:value-of select="/validation/@datetime"/>
|
||||||
|
</fo:block>
|
||||||
|
</fo:float>
|
||||||
|
<xsl:text>Zeitpunkt der Prüfung:</xsl:text>
|
||||||
|
</fo:block>
|
||||||
|
</fo:block>
|
||||||
|
<fo:block>
|
||||||
|
<fo:block text-align="justify">
|
||||||
|
<fo:float float="right">
|
||||||
|
<fo:block>
|
||||||
|
<xsl:value-of select="/validation/xml/info/profile"/>
|
||||||
|
</fo:block>
|
||||||
|
</fo:float>
|
||||||
|
<xsl:text>Erkannter Dokumenttyp:</xsl:text>
|
||||||
|
</fo:block>
|
||||||
|
</fo:block>
|
||||||
|
<xsl:apply-templates select="/validation/pdf"/>
|
||||||
|
<!--
|
||||||
|
<xsl:call-template name="SubHeader">
|
||||||
|
<xsl:with-param name="text"
|
||||||
|
select='"Konformitätsprüfung:"'/>
|
||||||
|
<xsl:with-param name="color"
|
||||||
|
select='"black"'/>
|
||||||
|
</xsl:call-template>
|
||||||
|
-->
|
||||||
|
<xsl:call-template name="SubHeader">
|
||||||
|
<xsl:with-param name="text"
|
||||||
|
select="concat('Bewertung: ', $result_text)"/>
|
||||||
|
<xsl:with-param name="color"
|
||||||
|
select="$xml_result_color"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
<fo:block>Validierungsergebnisse im Detail:</fo:block>
|
||||||
|
<fo:table>
|
||||||
|
<fo:table-column border-style="solid"/>
|
||||||
|
<fo:table-column border-style="solid"/>
|
||||||
|
<fo:table-column border-style="solid"/>
|
||||||
|
<fo:table-column column-width="70%"
|
||||||
|
border-style="solid"/>
|
||||||
|
<fo:table-header>
|
||||||
|
<fo:table-row background-color="#E0E0E0"
|
||||||
|
font-weight="bold">
|
||||||
|
<fo:table-cell>
|
||||||
|
<fo:block>Type</fo:block>
|
||||||
|
</fo:table-cell>
|
||||||
|
<fo:table-cell>
|
||||||
|
<fo:block>Code</fo:block>
|
||||||
|
</fo:table-cell>
|
||||||
|
<fo:table-cell>
|
||||||
|
<fo:block>Schwere</fo:block>
|
||||||
|
</fo:table-cell>
|
||||||
|
<fo:table-cell>
|
||||||
|
<fo:block>Text</fo:block>
|
||||||
|
</fo:table-cell>
|
||||||
|
</fo:table-row>
|
||||||
|
</fo:table-header>
|
||||||
|
<fo:table-body>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="/validation/xml/messages">
|
||||||
|
<xsl:apply-templates select="/validation/xml/messages"/>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<fo:table-row font-size="12px"
|
||||||
|
border-style="solid">
|
||||||
|
<fo:table-cell number-columns-spanned="4">
|
||||||
|
<fo:block text-align="center">Es gibt weder Hinweise noch Fehler.</fo:block>
|
||||||
|
</fo:table-cell>
|
||||||
|
</fo:table-row>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
</fo:table-body>
|
||||||
|
</fo:table>
|
||||||
|
</fo:flow>
|
||||||
|
</fo:page-sequence>
|
||||||
|
</fo:root>
|
||||||
|
</xsl:template>
|
||||||
|
<xsl:template match="notice|error">
|
||||||
|
<fo:table-row font-size="12px"
|
||||||
|
border-style="solid">
|
||||||
|
<fo:table-cell number-rows-spanned="2">
|
||||||
|
<fo:block>
|
||||||
|
<xsl:value-of select="@type"/>
|
||||||
|
</fo:block>
|
||||||
|
</fo:table-cell>
|
||||||
|
<fo:table-cell number-rows-spanned="2">
|
||||||
|
<fo:block>
|
||||||
|
<xsl:call-template name="SUBID">
|
||||||
|
<xsl:with-param name="myparam"
|
||||||
|
select="substring-after(.,' [ID ')"/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</fo:block>
|
||||||
|
</fo:table-cell>
|
||||||
|
<fo:table-cell number-rows-spanned="2">
|
||||||
|
<fo:block>
|
||||||
|
<xsl:choose>
|
||||||
|
<xsl:when test="name() = 'error'">
|
||||||
|
<xsl:attribute name="color">red</xsl:attribute>
|
||||||
|
<xsl:text>Fehler</xsl:text>
|
||||||
|
</xsl:when>
|
||||||
|
<xsl:otherwise>
|
||||||
|
<xsl:text>Hinweis</xsl:text>
|
||||||
|
</xsl:otherwise>
|
||||||
|
</xsl:choose>
|
||||||
|
</fo:block>
|
||||||
|
</fo:table-cell>
|
||||||
|
<fo:table-cell>
|
||||||
|
<fo:block>
|
||||||
|
<xsl:if test="name() = 'error'">
|
||||||
|
<xsl:attribute name="color">red</xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:value-of select="substring-before(.,' [ID')"/>
|
||||||
|
</fo:block>
|
||||||
|
</fo:table-cell>
|
||||||
|
</fo:table-row>
|
||||||
|
<fo:table-row font-size="10px"
|
||||||
|
border-style="solid">
|
||||||
|
<fo:table-cell>
|
||||||
|
<fo:block>
|
||||||
|
<xsl:if test="name() = 'error'">
|
||||||
|
<xsl:attribute name="color">red</xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:value-of select="concat('Pfad: ', @location)"/>
|
||||||
|
</fo:block>
|
||||||
|
</fo:table-cell>
|
||||||
|
</fo:table-row>
|
||||||
|
</xsl:template>
|
||||||
|
<xsl:template match="pdf">
|
||||||
|
<xsl:call-template name="SubHeader">
|
||||||
|
<xsl:with-param name="text"
|
||||||
|
select="concat('ZUGFeRD-PDF: ', $pdf_result_text)"/>
|
||||||
|
<xsl:with-param name="color"
|
||||||
|
select=""black""/>
|
||||||
|
</xsl:call-template>
|
||||||
|
</xsl:template>
|
||||||
|
<xsl:template name="SubHeader">
|
||||||
|
<xsl:param name="text"/>
|
||||||
|
<xsl:param name="color"/>
|
||||||
|
<fo:block color="{$color}"
|
||||||
|
background-color="#E0E0E0"
|
||||||
|
margin-bottom="10px"
|
||||||
|
padding="3px"
|
||||||
|
font-weight="bold"
|
||||||
|
margin-top="10px">
|
||||||
|
<xsl:value-of select="$text"/>
|
||||||
|
</fo:block>
|
||||||
|
</xsl:template>
|
||||||
|
<xsl:template name="SUBID">
|
||||||
|
<xsl:param name="myparam"/>
|
||||||
|
<xsl:variable name="myparam.end"
|
||||||
|
select="substring-before($myparam, ']')"/>
|
||||||
|
<xsl:value-of select="$myparam.end"/>
|
||||||
|
</xsl:template>
|
||||||
|
</xsl:stylesheet>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
== Schriften
|
== Schriften
|
||||||
=========================================================================== -->
|
=========================================================================== -->
|
||||||
|
|
||||||
<xsl:variable name="fontSans">SourceSerifPro</xsl:variable>
|
<xsl:variable name="fontSans">SourceSansPro</xsl:variable>
|
||||||
<xsl:variable name="fontSerif">SourceSerifPro</xsl:variable>
|
<xsl:variable name="fontSerif">SourceSerifPro</xsl:variable>
|
||||||
|
|
||||||
<xsl:variable name="amount-picture" select="xrf:_('amount-format')"/>
|
<xsl:variable name="amount-picture" select="xrf:_('amount-format')"/>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
<xsl:variable name="i18n.history" select="'Bearbeitungshistorie'"/>
|
<xsl:variable name="i18n.history" select="'Bearbeitungshistorie'"/>
|
||||||
<xsl:variable name="i18n.disclaimer" select="'Wir übernehmen keine Haftung für die Richtigkeit der Daten.'"/>
|
<xsl:variable name="i18n.disclaimer" select="'Wir übernehmen keine Haftung für die Richtigkeit der Daten.'"/>
|
||||||
<xsl:variable name="i18n.recipientInfo" select="'Informationen zum Käufer'"/>
|
<xsl:variable name="i18n.recipientInfo" select="'Informationen zum Käufer'"/>
|
||||||
|
<xsl:variable name="i18n.dateOf" select="' vom '"/>
|
||||||
<xsl:variable name="i18n.bt50" select="'Straße / Haus-Nr.'"/>
|
<xsl:variable name="i18n.bt50" select="'Straße / Haus-Nr.'"/>
|
||||||
<xsl:variable name="i18n.bt51" select="'Postfach'"/>
|
<xsl:variable name="i18n.bt51" select="'Postfach'"/>
|
||||||
<xsl:variable name="i18n.bt163" select="'Adresszusatz'"/>
|
<xsl:variable name="i18n.bt163" select="'Adresszusatz'"/>
|
||||||
@@ -197,6 +198,7 @@
|
|||||||
<xsl:variable name="i18n.bt17" select="'Vergabenummer'"/>
|
<xsl:variable name="i18n.bt17" select="'Vergabenummer'"/>
|
||||||
<xsl:variable name="i18n.bt15" select="'Kennung der Empfangsbestätigung'"/>
|
<xsl:variable name="i18n.bt15" select="'Kennung der Empfangsbestätigung'"/>
|
||||||
<xsl:variable name="i18n.bt16" select="'Kennung der Versandanzeige'"/>
|
<xsl:variable name="i18n.bt16" select="'Kennung der Versandanzeige'"/>
|
||||||
|
<xsl:variable name="i18n.btx202" select="'Kennung des Lieferscheins'"/>
|
||||||
<xsl:variable name="i18n.bt23" select="'Prozesskennung'"/>
|
<xsl:variable name="i18n.bt23" select="'Prozesskennung'"/>
|
||||||
<xsl:variable name="i18n.bt24" select="'Spezifikationskennung'"/>
|
<xsl:variable name="i18n.bt24" select="'Spezifikationskennung'"/>
|
||||||
<xsl:variable name="i18n.bt18" select="'Objektkennung'"/>
|
<xsl:variable name="i18n.bt18" select="'Objektkennung'"/>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
<xsl:variable name="i18n.history" select="'History'"/>
|
<xsl:variable name="i18n.history" select="'History'"/>
|
||||||
<xsl:variable name="i18n.disclaimer" select="'We accept no liability for the correctness of the data'"/>
|
<xsl:variable name="i18n.disclaimer" select="'We accept no liability for the correctness of the data'"/>
|
||||||
<xsl:variable name="i18n.recipientInfo" select="'Buyer Information'"/>
|
<xsl:variable name="i18n.recipientInfo" select="'Buyer Information'"/>
|
||||||
|
<xsl:variable name="i18n.dateOf" select="' from '"/>
|
||||||
<xsl:variable name="i18n.bt50" select="'Street / house number'"/>
|
<xsl:variable name="i18n.bt50" select="'Street / house number'"/>
|
||||||
<xsl:variable name="i18n.bt51" select="'PO Box'"/>
|
<xsl:variable name="i18n.bt51" select="'PO Box'"/>
|
||||||
<xsl:variable name="i18n.bt163" select="'Address Addition'"/>
|
<xsl:variable name="i18n.bt163" select="'Address Addition'"/>
|
||||||
@@ -197,6 +198,7 @@
|
|||||||
<xsl:variable name="i18n.bt17" select="'Assignment number'"/>
|
<xsl:variable name="i18n.bt17" select="'Assignment number'"/>
|
||||||
<xsl:variable name="i18n.bt15" select="'Receipt confirmation ID'"/>
|
<xsl:variable name="i18n.bt15" select="'Receipt confirmation ID'"/>
|
||||||
<xsl:variable name="i18n.bt16" select="'Dispatch note ID'"/>
|
<xsl:variable name="i18n.bt16" select="'Dispatch note ID'"/>
|
||||||
|
<xsl:variable name="i18n.btx202" select="'Delivery note ID'"/>
|
||||||
<xsl:variable name="i18n.bt23" select="'Process ID'"/>
|
<xsl:variable name="i18n.bt23" select="'Process ID'"/>
|
||||||
<xsl:variable name="i18n.bt24" select="'Specification ID'"/>
|
<xsl:variable name="i18n.bt24" select="'Specification ID'"/>
|
||||||
<xsl:variable name="i18n.bt18" select="'Object ID'"/>
|
<xsl:variable name="i18n.bt18" select="'Object ID'"/>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
<xsl:variable name="i18n.history" select="'Historique de traitement'"/>
|
<xsl:variable name="i18n.history" select="'Historique de traitement'"/>
|
||||||
<xsl:variable name="i18n.disclaimer" select="'Nous n''assumons aucune responsabilité quant à l''exactitude des données.'"/>
|
<xsl:variable name="i18n.disclaimer" select="'Nous n''assumons aucune responsabilité quant à l''exactitude des données.'"/>
|
||||||
<xsl:variable name="i18n.recipientInfo" select="'Informations sur l''acheteur'"/>
|
<xsl:variable name="i18n.recipientInfo" select="'Informations sur l''acheteur'"/>
|
||||||
|
<xsl:variable name="i18n.dateOf" select="' du '"/>
|
||||||
<xsl:variable name="i18n.bt50" select="'Rue / Numéro de maison'"/>
|
<xsl:variable name="i18n.bt50" select="'Rue / Numéro de maison'"/>
|
||||||
<xsl:variable name="i18n.bt51" select="'Boîte postale'"/>
|
<xsl:variable name="i18n.bt51" select="'Boîte postale'"/>
|
||||||
<xsl:variable name="i18n.bt163" select="'Supplément d''adresse'"/>
|
<xsl:variable name="i18n.bt163" select="'Supplément d''adresse'"/>
|
||||||
@@ -197,6 +198,7 @@
|
|||||||
<xsl:variable name="i18n.bt17" select="'Numéro d''attribution'"/>
|
<xsl:variable name="i18n.bt17" select="'Numéro d''attribution'"/>
|
||||||
<xsl:variable name="i18n.bt15" select="'Identifiant de l''accusé de réception'"/>
|
<xsl:variable name="i18n.bt15" select="'Identifiant de l''accusé de réception'"/>
|
||||||
<xsl:variable name="i18n.bt16" select="'Identifiant du bordereau d''expédition'"/>
|
<xsl:variable name="i18n.bt16" select="'Identifiant du bordereau d''expédition'"/>
|
||||||
|
<xsl:variable name="i18n.btx202" select="'Identifiant du bon de livraison'"/>
|
||||||
<xsl:variable name="i18n.bt23" select="'Identifiant processus'"/>
|
<xsl:variable name="i18n.bt23" select="'Identifiant processus'"/>
|
||||||
<xsl:variable name="i18n.bt24" select="'Identifiant spécification'"/>
|
<xsl:variable name="i18n.bt24" select="'Identifiant spécification'"/>
|
||||||
<xsl:variable name="i18n.bt18" select="'Identifiant objet'"/>
|
<xsl:variable name="i18n.bt18" select="'Identifiant objet'"/>
|
||||||
|
|||||||
@@ -1144,17 +1144,29 @@ function downloadData (element_id) {
|
|||||||
<xsl:apply-templates select="./xr:VAT_BREAKDOWN"/>
|
<xsl:apply-templates select="./xr:VAT_BREAKDOWN"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig">
|
<xsl:choose>
|
||||||
<xsl:apply-templates select="./xr:DOCUMENT_LEVEL_ALLOWANCES"/>
|
<xsl:when test="./xr:DOCUMENT_LEVEL_ALLOWANCES">
|
||||||
</div>
|
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig">
|
||||||
|
<xsl:apply-templates select="./xr:DOCUMENT_LEVEL_ALLOWANCES"/>
|
||||||
|
</div>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig">
|
<xsl:choose>
|
||||||
<xsl:apply-templates select="./xr:DOCUMENT_LEVEL_CHARGES"/>
|
<xsl:when test="./xr:DOCUMENT_LEVEL_CHARGES">
|
||||||
</div>
|
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig">
|
||||||
|
<xsl:apply-templates select="./xr:DOCUMENT_LEVEL_CHARGES"/>
|
||||||
|
</div>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig">
|
<xsl:choose>
|
||||||
<xsl:apply-templates select="./xr:LOGISTICS_SERVICE_CHARGES"/>
|
<xsl:when test="./xr:LOGISTICS_SERVICE_CHARGES">
|
||||||
</div>
|
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig">
|
||||||
|
<xsl:apply-templates select="./xr:LOGISTICS_SERVICE_CHARGES"/>
|
||||||
|
</div>
|
||||||
|
</xsl:when>
|
||||||
|
</xsl:choose>
|
||||||
|
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig first">
|
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig first">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
@@ -2182,11 +2194,24 @@ function downloadData (element_id) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende"><xsl:value-of select="$i18n.bt15"/>:</div>
|
<div class="boxdaten legende"><xsl:value-of select="$i18n.bt15"/>:</div>
|
||||||
<div id="BT-15" title="BT-15" class="boxdaten wert"><xsl:value-of select="xr:Receiving_advice_reference"/></div>
|
<div id="BT-15" title="BT-15" class="boxdaten wert">
|
||||||
|
<xsl:value-of select="xr:Receiving_advice_reference"/>
|
||||||
|
<xsl:if test="xr:Receiving_advice_reference/@bt-x-201"><xsl:value-of select="concat($i18n.dateOf, format-date(xr:Receiving_advice_reference/@bt-x-201,'[D].[M].[Y]'))"/></xsl:if>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende"><xsl:value-of select="$i18n.bt16"/>:</div>
|
<div class="boxdaten legende"><xsl:value-of select="$i18n.bt16"/>:</div>
|
||||||
<div id="BT-16" title="BT-16" class="boxdaten wert"><xsl:value-of select="xr:Despatch_advice_reference"/></div>
|
<div id="BT-16" title="BT-16" class="boxdaten wert">
|
||||||
|
<xsl:value-of select="xr:Despatch_advice_reference"/>
|
||||||
|
<xsl:if test="xr:Despatch_advice_reference/@bt-x-200"><xsl:value-of select="concat($i18n.dateOf, format-date(xr:Despatch_advice_reference/@bt-x-200,'[D].[M].[Y]'))"/></xsl:if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="boxzeile">
|
||||||
|
<div class="boxdaten legende"><xsl:value-of select="$i18n.btx202"/>:</div>
|
||||||
|
<div id="BT-X-202" title="BT-X-202" class="boxdaten wert">
|
||||||
|
<xsl:value-of select="xr:Delivery_note_reference"/>
|
||||||
|
<xsl:if test="xr:Delivery_note_reference/@bt-x-203"><xsl:value-of select="concat($i18n.dateOf, format-date(xr:Delivery_note_reference/@bt-x-203,'[D].[M].[Y]'))"/></xsl:if>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende"><xsl:value-of select="$i18n.bt23"/>:</div>
|
<div class="boxdaten legende"><xsl:value-of select="$i18n.bt23"/>:</div>
|
||||||
|
|||||||
@@ -166,11 +166,123 @@ public class DeSerializationTest extends ResourceCase {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDeserializedFiles() {
|
||||||
|
File inputUBL = getResourceAsFile("XRECHNUNG_Elektron.ubl.xml");
|
||||||
|
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter();
|
||||||
|
zii.doIgnoreCalculationErrors();
|
||||||
|
Invoice i = new Invoice();
|
||||||
|
String exText = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
zii.fromXML(new String(Files.readAllBytes(inputUBL.toPath()), StandardCharsets.UTF_8));
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
zii.extractInto(i);
|
||||||
|
String json = mapper.writeValueAsString(i);
|
||||||
|
Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class);
|
||||||
|
|
||||||
|
assertEquals("181301674", i.getNumber());
|
||||||
|
assertEquals(newInvoiceFromJSON.getNumber(), i.getNumber());
|
||||||
|
assertEquals(newInvoiceFromJSON.getAdditionalReferencedDocuments()[0].getFilename(), i.getAdditionalReferencedDocuments()[0].getFilename());
|
||||||
|
assertEquals(newInvoiceFromJSON.getAdditionalReferencedDocuments().length, 2);
|
||||||
|
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
exText = e.getMessage();
|
||||||
|
} catch (XPathExpressionException e) {
|
||||||
|
exText = e.getMessage();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
exText = e.getMessage();
|
||||||
|
}
|
||||||
|
assertNull(exText);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFileSerialization() {
|
||||||
|
|
||||||
|
String base64 = "b25ldHdvdGhyZWU=";
|
||||||
|
String json = "{\n" +
|
||||||
|
" \"additionalReferencedDocuments\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"data\": \"" + base64 + "\",\n" +
|
||||||
|
" \"description\": \"Additional file attachment\",\n" +
|
||||||
|
" \"filename\": \"text.txt\",\n" +
|
||||||
|
" \"mimetype\": \"text/plain\",\n" +
|
||||||
|
" \"relation\": \"Data\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
"],\n" +
|
||||||
|
"\n" +
|
||||||
|
" \"number\": \"471102\",\n" +
|
||||||
|
" \"currency\": \"EUR\",\n" +
|
||||||
|
" \"issueDate\": \"2018-03-04T00:00:00.000+01:00\",\n" +
|
||||||
|
" \"dueDate\": \"2018-03-04T00:00:00.000+01:00\",\n" +
|
||||||
|
" \"deliveryDate\": \"2018-03-04T00:00:00.000+01:00\",\n" +
|
||||||
|
" \"sender\": {\n" +
|
||||||
|
" \"name\": \"Lieferant GmbH\",\n" +
|
||||||
|
" \"zip\": \"80333\",\n" +
|
||||||
|
" \"street\": \"Lieferantenstraße 20\",\n" +
|
||||||
|
" \"location\": \"München\",\n" +
|
||||||
|
" \"country\": \"DE\",\n" +
|
||||||
|
" \"taxID\": \"201/113/40209\",\n" +
|
||||||
|
" \"vatID\": \"DE123456789\",\n" +
|
||||||
|
" \"globalID\": \"4000001123452\",\n" +
|
||||||
|
" \"globalIDScheme\": \"0088\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"recipient\": {\n" +
|
||||||
|
" \"name\": \"Kunden AG Mitte\",\n" +
|
||||||
|
" \"zip\": \"69876\",\n" +
|
||||||
|
" \"street\": \"Kundenstraße 15\",\n" +
|
||||||
|
" \"location\": \"Frankfurt\",\n" +
|
||||||
|
" \"country\": \"DE\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"zfitems\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"price\": 9.9,\n" +
|
||||||
|
" \"quantity\": 20,\n" +
|
||||||
|
" \"product\": {\n" +
|
||||||
|
" \"unit\": \"H87\",\n" +
|
||||||
|
" \"name\": \"Trennblätter A4\",\n" +
|
||||||
|
" \"description\": \"\",\n" +
|
||||||
|
" \"vatpercent\": 19,\n" +
|
||||||
|
" \"taxCategoryCode\": \"S\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"price\": 5.5,\n" +
|
||||||
|
" \"quantity\": 50,\n" +
|
||||||
|
" \"product\": {\n" +
|
||||||
|
" \"unit\": \"H87\",\n" +
|
||||||
|
" \"name\": \"Joghurt Banane\",\n" +
|
||||||
|
" \"description\": \"\",\n" +
|
||||||
|
" \"vatpercent\": 7,\n" +
|
||||||
|
" \"taxCategoryCode\": \"S\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class);
|
||||||
|
ZUGFeRD2PullProvider zf2p = new ZUGFeRD2PullProvider();
|
||||||
|
zf2p.setProfile(Profiles.getByName("XRechnung"));
|
||||||
|
zf2p.generateXML(newInvoiceFromJSON);
|
||||||
|
String theXML = new String(zf2p.getXML());
|
||||||
|
assertTrue(theXML.contains("<udt:DateTimeString format=\"102\">20180304</udt:DateTimeString>"));
|
||||||
|
assertTrue(theXML.contains(base64));
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail("No exception expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testFull300Roundtrip() {
|
public void testFull300Roundtrip() {
|
||||||
File inputCII = getResourceAsFile("not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.cii.xml");
|
File inputCII = getResourceAsFile("not_validating_full_invoice_based_onTest_EeISI_300_CENfullmodel.cii.xml");
|
||||||
|
|
||||||
Invoice i=new Invoice();
|
Invoice i = new Invoice();
|
||||||
String exText=null;
|
String exText = null;
|
||||||
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter();
|
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter();
|
||||||
zii.doIgnoreCalculationErrors();
|
zii.doIgnoreCalculationErrors();
|
||||||
try {
|
try {
|
||||||
@@ -180,15 +292,15 @@ public class DeSerializationTest extends ResourceCase {
|
|||||||
String json = mapper.writeValueAsString(i);
|
String json = mapper.writeValueAsString(i);
|
||||||
Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class);
|
Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class);
|
||||||
|
|
||||||
assertEquals("Test_EeISI_100",i.getNumber());
|
assertEquals("Test_EeISI_100", i.getNumber());
|
||||||
assertEquals(newInvoiceFromJSON.getNumber(),i.getNumber());
|
assertEquals(newInvoiceFromJSON.getNumber(), i.getNumber());
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
exText=e.getMessage();
|
exText = e.getMessage();
|
||||||
} catch (XPathExpressionException e) {
|
} catch (XPathExpressionException e) {
|
||||||
exText=e.getMessage();
|
exText = e.getMessage();
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
exText=e.getMessage();
|
exText = e.getMessage();
|
||||||
}
|
}
|
||||||
assertNull(exText);
|
assertNull(exText);
|
||||||
|
|
||||||
|
|||||||
@@ -22,10 +22,9 @@ package org.mustangproject.ZUGFeRD;
|
|||||||
|
|
||||||
import org.junit.FixMethodOrder;
|
import org.junit.FixMethodOrder;
|
||||||
import org.junit.runners.MethodSorters;
|
import org.junit.runners.MethodSorters;
|
||||||
|
import org.mustangproject.ZUGFeRD.ZUGFeRDVisualizer.Language;
|
||||||
import org.mustangproject.util.ByteArraySearcher;
|
import org.mustangproject.util.ByteArraySearcher;
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.transform.TransformerException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -40,155 +39,34 @@ public class VisualizationTest extends ResourceCase {
|
|||||||
final String TARGET_PDF_UBL = "./target/testout-Visualization-cii.pdf";
|
final String TARGET_PDF_UBL = "./target/testout-Visualization-cii.pdf";
|
||||||
|
|
||||||
public void testCIIVisualizationBasic() {
|
public void testCIIVisualizationBasic() {
|
||||||
|
this.runZUGFeRDVisualization("factur-x.xml", "factur-x-vis.fr.html", Language.FR);
|
||||||
// the writing part
|
|
||||||
String sourceFilename = "factur-x.xml";
|
|
||||||
File CIIinputFile = getResourceAsFile(sourceFilename);
|
|
||||||
|
|
||||||
String expected = null;
|
|
||||||
String result = null;
|
|
||||||
try {
|
|
||||||
ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer();
|
|
||||||
/* remove file endings so that tests can also pass after checking
|
|
||||||
out from git with arbitrary options (which may include CSRF changes)
|
|
||||||
*/
|
|
||||||
result = zvi.visualize(CIIinputFile.getAbsolutePath(), ZUGFeRDVisualizer.Language.FR)
|
|
||||||
.replace("\r", "")
|
|
||||||
.replace("\n", "")
|
|
||||||
.replace("\t", "")
|
|
||||||
.replace(" ", "");
|
|
||||||
|
|
||||||
File expectedResult = getResourceAsFile("factur-x-vis.fr.html");
|
|
||||||
expected = new String(Files.readAllBytes(expectedResult.toPath()), StandardCharsets.UTF_8)
|
|
||||||
.replace("\r", "")
|
|
||||||
.replace("\n", "")
|
|
||||||
.replace("\t", "")
|
|
||||||
.replace(" ", "");
|
|
||||||
// remove linebreaks as well...
|
|
||||||
|
|
||||||
} catch (UnsupportedOperationException e) {
|
|
||||||
fail("UnsupportedOperationException should not happen: " + e.getMessage());
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
fail("IllegalArgumentException should not happen: " + e.getMessage());
|
|
||||||
} catch (TransformerException e) {
|
|
||||||
fail("TransformerException should not happen: " + e.getMessage());
|
|
||||||
} catch (IOException e) {
|
|
||||||
fail("IOException should not happen: " + e.getMessage());
|
|
||||||
} catch (ParserConfigurationException e) {
|
|
||||||
fail("ParserConfigurationException should not happen: " + e.getMessage());
|
|
||||||
} catch (SAXException e) {
|
|
||||||
fail("SAXException should not happen: " + e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
assertNotNull(result);
|
|
||||||
// Reading ZUGFeRD
|
|
||||||
assertEquals(expected, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCIIVisualizationExtended() {
|
public void testCIIVisualizationExtended() {
|
||||||
|
this.runZUGFeRDVisualization("factur-x-extended.xml", "factur-x-vis-extended.de.html", Language.DE);
|
||||||
// the writing part
|
|
||||||
String sourceFilename = "factur-x-extended.xml";
|
|
||||||
File CIIinputFile = getResourceAsFile(sourceFilename);
|
|
||||||
|
|
||||||
String expected = null;
|
|
||||||
String result = null;
|
|
||||||
try {
|
|
||||||
ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer();
|
|
||||||
/* remove file endings so that tests can also pass after checking
|
|
||||||
out from git with arbitrary options (which may include CSRF changes)
|
|
||||||
*/
|
|
||||||
result = zvi.visualize(CIIinputFile.getAbsolutePath(), ZUGFeRDVisualizer.Language.DE).replace("\r", "").replace("\n", "")
|
|
||||||
.replace("\t", "")
|
|
||||||
.replace(" ", "");
|
|
||||||
|
|
||||||
File expectedResult = getResourceAsFile("factur-x-vis-extended.de.html");
|
|
||||||
expected = new String(Files.readAllBytes(expectedResult.toPath()), StandardCharsets.UTF_8).replace("\r", "").replace("\n", "")
|
|
||||||
.replace("\t", "")
|
|
||||||
.replace(" ", "");
|
|
||||||
// remove linebreaks as well...
|
|
||||||
|
|
||||||
} catch (UnsupportedOperationException e) {
|
|
||||||
fail("UnsupportedOperationException should not happen: " + e.getMessage());
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
fail("IllegalArgumentException should not happen: " + e.getMessage());
|
|
||||||
} catch (TransformerException e) {
|
|
||||||
fail("TransformerException should not happen: " + e.getMessage());
|
|
||||||
} catch (IOException e) {
|
|
||||||
fail("IOException should not happen: " + e.getMessage());
|
|
||||||
} catch (ParserConfigurationException e) {
|
|
||||||
fail("ParserConfigurationException should not happen: " + e.getMessage());
|
|
||||||
} catch (SAXException e) {
|
|
||||||
fail("SAXException should not happen: " + e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
assertNotNull(result);
|
|
||||||
// Reading ZUGFeRD
|
|
||||||
assertEquals(expected, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUBLCreditNoteVisualizationBasic() {
|
public void testUBLCreditNoteVisualizationBasic() {
|
||||||
|
this.runZUGFeRDVisualization("ubl-creditnote.xml", "factur-x-vis-ubl-creditnote.en.html", Language.EN);
|
||||||
// the writing part
|
|
||||||
File UBLinputFile = getResourceAsFile("ubl-creditnote.xml");
|
|
||||||
|
|
||||||
String expected = null;
|
|
||||||
String result = null;
|
|
||||||
try {
|
|
||||||
ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer();
|
|
||||||
/* remove file endings so that tests can also pass after checking
|
|
||||||
out from git with arbitrary options (which may include CSRF changes)
|
|
||||||
*/
|
|
||||||
result = zvi.visualize(UBLinputFile.getAbsolutePath(), ZUGFeRDVisualizer.Language.EN).replace("\r", "").replace("\n", "").replace("\t", "").replace(" ", "");
|
|
||||||
|
|
||||||
File expectedResult = getResourceAsFile("factur-x-vis-ubl-creditnote.en.html");
|
|
||||||
expected = new String(Files.readAllBytes(expectedResult.toPath()), StandardCharsets.UTF_8).replace("\r", "").replace("\n", "").replace("\t", "").replace(" ", "");
|
|
||||||
// remove linebreaks as well...
|
|
||||||
|
|
||||||
} catch (UnsupportedOperationException e) {
|
|
||||||
fail("UnsupportedOperationException should not happen: " + e.getMessage());
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
fail("IllegalArgumentException should not happen: " + e.getMessage());
|
|
||||||
} catch (TransformerException e) {
|
|
||||||
fail("TransformerException should not happen: " + e.getMessage());
|
|
||||||
} catch (IOException e) {
|
|
||||||
fail("IOException should not happen: " + e.getMessage());
|
|
||||||
} catch (ParserConfigurationException e) {
|
|
||||||
fail("ParserConfigurationException should not happen: " + e.getMessage());
|
|
||||||
} catch (SAXException e) {
|
|
||||||
fail("SAXException should not happen: " + e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
assertNotNull(result);
|
|
||||||
// Reading ZUGFeRD
|
|
||||||
assertEquals(expected, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testUBLVisualizationBasic() {
|
public void testUBLVisualizationBasic() {
|
||||||
|
this.runZUGFeRDVisualization("ubl/01.01a-INVOICE.ubl.xml", "factur-x-vis-ubl.en.html", Language.EN);
|
||||||
|
}
|
||||||
|
|
||||||
// the writing part
|
private void runZUGFeRDVisualization(String inputFilename, String resultFileName, Language lang) {
|
||||||
File UBLinputFile = getResourceAsFile("ubl/01.01a-INVOICE.ubl.xml");
|
File CIIinputFile = getResourceAsFile(inputFilename);
|
||||||
|
|
||||||
String expected = null;
|
String expected = null;
|
||||||
String result = null;
|
String result = null;
|
||||||
try {
|
try {
|
||||||
ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer();
|
ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer();
|
||||||
/* remove file endings so that tests can also pass after checking
|
result = zvi.visualize(CIIinputFile.getAbsolutePath(), lang);
|
||||||
out from git with arbitrary options (which may include CSRF changes)
|
Files.write(Paths.get("./target/testout-" + resultFileName), result.getBytes(StandardCharsets.UTF_8));
|
||||||
*/
|
|
||||||
result = zvi.visualize(UBLinputFile.getAbsolutePath(), ZUGFeRDVisualizer.Language.EN).replace("\r", "").replace("\n", "")
|
|
||||||
.replace("\t", "")
|
|
||||||
.replace(" ", "");
|
|
||||||
|
|
||||||
File expectedResult = getResourceAsFile("factur-x-vis-ubl.en.html");
|
File expectedResult = getResourceAsFile(resultFileName);
|
||||||
expected = new String(Files.readAllBytes(expectedResult.toPath()), StandardCharsets.UTF_8).replace("\r", "").replace("\n", "")
|
expected = new String(Files.readAllBytes(expectedResult.toPath()), StandardCharsets.UTF_8)
|
||||||
.replace("\t", "")
|
;
|
||||||
.replace(" ", "");
|
|
||||||
// remove linebreaks as well...
|
|
||||||
|
|
||||||
} catch (UnsupportedOperationException e) {
|
} catch (UnsupportedOperationException e) {
|
||||||
fail("UnsupportedOperationException should not happen: " + e.getMessage());
|
fail("UnsupportedOperationException should not happen: " + e.getMessage());
|
||||||
@@ -198,16 +76,20 @@ public class VisualizationTest extends ResourceCase {
|
|||||||
fail("TransformerException should not happen: " + e.getMessage());
|
fail("TransformerException should not happen: " + e.getMessage());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
fail("IOException should not happen: " + e.getMessage());
|
fail("IOException should not happen: " + e.getMessage());
|
||||||
} catch (ParserConfigurationException e) {
|
|
||||||
fail("ParserConfigurationException should not happen: " + e.getMessage());
|
|
||||||
} catch (SAXException e) {
|
|
||||||
fail("SAXException should not happen: " + e.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
// Reading ZUGFeRD
|
/* remove file endings so that tests can also pass after checking
|
||||||
assertEquals(expected, result);
|
out from git with arbitrary options (which may include CSRF changes)
|
||||||
|
*/
|
||||||
|
assertEquals(expected.replace("\r", "")
|
||||||
|
.replace("\n", "")
|
||||||
|
.replace("\t", "")
|
||||||
|
.replace(" ", ""), result.replace("\r", "")
|
||||||
|
.replace("\n", "")
|
||||||
|
.replace("\t", "")
|
||||||
|
.replace(" ", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPDFVisualizationCII() {
|
public void testPDFVisualizationCII() {
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ public class ZF2PushTest extends TestCase {
|
|||||||
.setNumber(number)
|
.setNumber(number)
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance(new BigDecimal("0.1"))))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance(new BigDecimal("0.1"))))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50))))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50))))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(2.0)).addCharge(new Charge(new BigDecimal(1)).setReasonCode("AK")))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(2.0)).addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK")))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addCharge(new Charge(new BigDecimal(1))).addAllowance(new Allowance(new BigDecimal("1"))))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addCharge(new Charge(new BigDecimal(1))).addAllowance(new Allowance(new BigDecimal("1"))))
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -542,7 +542,7 @@ public class ZF2PushTest extends TestCase {
|
|||||||
.addAllowance(new Allowance(new BigDecimal(0.2)).setReason("discount").setTaxPercent(new BigDecimal(16)))
|
.addAllowance(new Allowance(new BigDecimal(0.2)).setReason("discount").setTaxPercent(new BigDecimal(16)))
|
||||||
.addCashDiscount(new CashDiscount(new BigDecimal(2), 14))
|
.addCashDiscount(new CashDiscount(new BigDecimal(2), 14))
|
||||||
.setDeliveryDate(sdf.parse("2020-11-02")).setNumber(number).setVATDueDateTypeCode(EventTimeCodeTypeConstants.PAYMENT_DATE)
|
.setDeliveryDate(sdf.parse("2020-11-02")).setNumber(number).setVATDueDateTypeCode(EventTimeCodeTypeConstants.PAYMENT_DATE)
|
||||||
.setInvoiceReferencedDocumentID("abc123")
|
.setInvoiceReferencedDocumentID("abc123").addInvoiceReferencedDocument(new ReferencedDocument("abcd1234"))
|
||||||
);
|
);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -587,6 +587,8 @@ public class ZF2PushTest extends TestCase {
|
|||||||
Invoice i = zii.extractInvoice();
|
Invoice i = zii.extractInvoice();
|
||||||
|
|
||||||
assertEquals("abc123", i.getInvoiceReferencedDocumentID());
|
assertEquals("abc123", i.getInvoiceReferencedDocumentID());
|
||||||
|
assertEquals(1, i.getInvoiceReferencedDocuments().size());
|
||||||
|
assertEquals("abcd1234", i.getInvoiceReferencedDocuments().get(0).getIssuerAssignedID());
|
||||||
assertEquals("4304171000002", i.getRecipient().getGlobalID());
|
assertEquals("4304171000002", i.getRecipient().getGlobalID());
|
||||||
assertEquals("2001015001325", i.getZFItems()[0].getProduct().getGlobalID());
|
assertEquals("2001015001325", i.getZFItems()[0].getProduct().getGlobalID());
|
||||||
assertEquals(orgID, i.getSender().getID());
|
assertEquals(orgID, i.getSender().getID());
|
||||||
@@ -803,24 +805,5 @@ public class ZF2PushTest extends TestCase {
|
|||||||
match the read grand total */
|
match the read grand total */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void testRead() {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter("\\Users\\jstaerk\\temp\\1424413_anonymized.xml");
|
|
||||||
try {
|
|
||||||
Invoice i = zii.extractInvoice();
|
|
||||||
|
|
||||||
TransactionCalculator tc=new TransactionCalculator(i);
|
|
||||||
assertEquals(0,tc.getGrandTotal().compareTo(new BigDecimal("442.83")));
|
|
||||||
|
|
||||||
} catch (XPathExpressionException e) {
|
|
||||||
fail("XPathExpressionException should not be raised");
|
|
||||||
} catch (ParseException e) {
|
|
||||||
fail("ParseException should not be raised");
|
|
||||||
/* a parseException would also be fired if the calculated grand total does not
|
|
||||||
match the read grand total */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -466,4 +466,12 @@ public class ZF2ZInvoiceImporterTest extends ResourceCase {
|
|||||||
assertFalse(invoice.getZFItems()[0].getNotes() == null);
|
assertFalse(invoice.getZFItems()[0].getNotes() == null);
|
||||||
assertEquals(1, invoice.getZFItems()[0].getNotes().length);
|
assertEquals(1, invoice.getZFItems()[0].getNotes().length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testImportXRechnungWithoutCalculationErrors() throws FileNotFoundException, XPathExpressionException, ParseException {
|
||||||
|
File inputFile = getResourceAsFile("cii/02.03a-INVOICE_uncefact.xml");
|
||||||
|
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(new FileInputStream(inputFile));
|
||||||
|
|
||||||
|
assertEquals("0", zii.importedInvoice.getDuePayable().toPlainString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
309
library/src/test/resources/cii/02.03a-INVOICE_uncefact.xml
Normal file
309
library/src/test/resources/cii/02.03a-INVOICE_uncefact.xml
Normal file
File diff suppressed because one or more lines are too long
@@ -359,6 +359,9 @@ GLN 4304171000002
|
|||||||
</ram:ActualDeliverySupplyChainEvent>
|
</ram:ActualDeliverySupplyChainEvent>
|
||||||
<ram:DeliveryNoteReferencedDocument>
|
<ram:DeliveryNoteReferencedDocument>
|
||||||
<ram:IssuerAssignedID>L87654321012</ram:IssuerAssignedID>
|
<ram:IssuerAssignedID>L87654321012</ram:IssuerAssignedID>
|
||||||
|
<ram:FormattedIssueDateTime>
|
||||||
|
<qdt:DateTimeString format="102">20241031</qdt:DateTimeString>
|
||||||
|
</ram:FormattedIssueDateTime>
|
||||||
</ram:DeliveryNoteReferencedDocument>
|
</ram:DeliveryNoteReferencedDocument>
|
||||||
</ram:ApplicableHeaderTradeDelivery>
|
</ram:ApplicableHeaderTradeDelivery>
|
||||||
<ram:ApplicableHeaderTradeSettlement>
|
<ram:ApplicableHeaderTradeSettlement>
|
||||||
|
|||||||
@@ -1085,7 +1085,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="boxabstand"></div>
|
<div class="boxabstand"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig"></div>
|
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig">
|
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div id="uebersichtVersandkosten" class="box">
|
<div id="uebersichtVersandkosten" class="box">
|
||||||
@@ -2248,6 +2247,10 @@
|
|||||||
<div class="boxdaten legende">Kennung der Versandanzeige:</div>
|
<div class="boxdaten legende">Kennung der Versandanzeige:</div>
|
||||||
<div id="BT-16" title="BT-16" class="boxdaten wert"></div>
|
<div id="BT-16" title="BT-16" class="boxdaten wert"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="boxzeile">
|
||||||
|
<div class="boxdaten legende">Kennung des Lieferscheins:</div>
|
||||||
|
<div id="BT-X-202" title="BT-X-202" class="boxdaten wert">L87654321012 vom 31.10.2024</div>
|
||||||
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende">Prozesskennung:</div>
|
<div class="boxdaten legende">Prozesskennung:</div>
|
||||||
<div id="BT-23" title="BT-23" class="boxdaten wert"></div>
|
<div id="BT-23" title="BT-23" class="boxdaten wert"></div>
|
||||||
|
|||||||
@@ -1359,7 +1359,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="boxabstand"></div>
|
<div class="boxabstand"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig"></div>
|
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig first">
|
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig first">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div id="uebersichtZahlungsinformationen" class="box subBox">
|
<div id="uebersichtZahlungsinformationen" class="box subBox">
|
||||||
@@ -1556,7 +1555,7 @@
|
|||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Description:</div>
|
<div class="boxdaten legende ">Description:</div>
|
||||||
<div id="BT-154" title="BT-154" class="boxdaten wert">Processor: Intel Core 2 Duo SU9400 LV (1.4GHz). RAM:
|
<div id="BT-154" title="BT-154" class="boxdaten wert">Processor: Intel Core 2 Duo SU9400 LV (1.4GHz). RAM:
|
||||||
3MB. Screen 1440x900</div>
|
3MB. Screen 1440x900</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Part number:</div>
|
<div class="boxdaten legende ">Part number:</div>
|
||||||
@@ -2355,6 +2354,10 @@
|
|||||||
<div class="boxdaten legende">Dispatch note ID:</div>
|
<div class="boxdaten legende">Dispatch note ID:</div>
|
||||||
<div id="BT-16" title="BT-16" class="boxdaten wert"></div>
|
<div id="BT-16" title="BT-16" class="boxdaten wert"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="boxzeile">
|
||||||
|
<div class="boxdaten legende">Delivery note ID:</div>
|
||||||
|
<div id="BT-X-202" title="BT-X-202" class="boxdaten wert"></div>
|
||||||
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende">Process ID:</div>
|
<div class="boxdaten legende">Process ID:</div>
|
||||||
<div id="BT-23" title="BT-23" class="boxdaten wert"></div>
|
<div id="BT-23" title="BT-23" class="boxdaten wert"></div>
|
||||||
|
|||||||
@@ -1219,9 +1219,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig"></div>
|
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig"></div>
|
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig"></div>
|
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig first">
|
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig first">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div id="uebersichtZahlungsinformationen" class="box subBox">
|
<div id="uebersichtZahlungsinformationen" class="box subBox">
|
||||||
@@ -1755,6 +1752,10 @@
|
|||||||
<div class="boxdaten legende">Dispatch note ID:</div>
|
<div class="boxdaten legende">Dispatch note ID:</div>
|
||||||
<div id="BT-16" title="BT-16" class="boxdaten wert"></div>
|
<div id="BT-16" title="BT-16" class="boxdaten wert"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="boxzeile">
|
||||||
|
<div class="boxdaten legende">Delivery note ID:</div>
|
||||||
|
<div id="BT-X-202" title="BT-X-202" class="boxdaten wert"></div>
|
||||||
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende">Process ID:</div>
|
<div class="boxdaten legende">Process ID:</div>
|
||||||
<div id="BT-23" title="BT-23" class="boxdaten wert"></div>
|
<div id="BT-23" title="BT-23" class="boxdaten wert"></div>
|
||||||
|
|||||||
@@ -1250,9 +1250,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig"></div>
|
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig"></div>
|
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig"></div>
|
|
||||||
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig first">
|
<div class="boxtabelle boxabstandtop boxtabelleZweispaltig first">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div id="uebersichtZahlungsinformationen" class="box subBox">
|
<div id="uebersichtZahlungsinformationen" class="box subBox">
|
||||||
@@ -1927,6 +1924,10 @@
|
|||||||
<div class="boxdaten legende">Identifiant du bordereau d'expédition:</div>
|
<div class="boxdaten legende">Identifiant du bordereau d'expédition:</div>
|
||||||
<div id="BT-16" title="BT-16" class="boxdaten wert"></div>
|
<div id="BT-16" title="BT-16" class="boxdaten wert"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="boxzeile">
|
||||||
|
<div class="boxdaten legende">Identifiant du bon de livraison:</div>
|
||||||
|
<div id="BT-X-202" title="BT-X-202" class="boxdaten wert"></div>
|
||||||
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende">Identifiant processus:</div>
|
<div class="boxdaten legende">Identifiant processus:</div>
|
||||||
<div id="BT-23" title="BT-23" class="boxdaten wert"></div>
|
<div id="BT-23" title="BT-23" class="boxdaten wert"></div>
|
||||||
|
|||||||
3
pom.xml
3
pom.xml
@@ -3,8 +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.15.2-SNAPSHOT</version>
|
<version>2.15.3-SNAPSHOT</version> <packaging>pom</packaging>
|
||||||
<packaging>pom</packaging>
|
|
||||||
<name>Mustang</name>
|
<name>Mustang</name>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
<version>2.15.2-SNAPSHOT</version>
|
<version>2.15.3-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<name>Library to validate e-invoices (ZUGFeRD, Factur-X and Xrechnung)</name>
|
<name>Library to validate e-invoices (ZUGFeRD, Factur-X and Xrechnung)</name>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>2.15.2-SNAPSHOT</version>
|
<version>2.15.3-SNAPSHOT</version>
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<!-- for jargs -->
|
<!-- for jargs -->
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>library</artifactId>
|
<artifactId>library</artifactId>
|
||||||
<version>2.15.2-SNAPSHOT</version>
|
<version>2.15.3-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dom4j</groupId>
|
<groupId>org.dom4j</groupId>
|
||||||
|
|||||||
Reference in New Issue
Block a user