Merge branch 'mustang-master' into forked-master
This commit is contained in:
2
.github/workflows/maven.yml
vendored
2
.github/workflows/maven.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
- uses: actions/setup-java@v3 # the log states the default ~/.m2/toolchains.xml is being created pointing to the JDK
|
||||
with:
|
||||
distribution: 'adopt' # for latest JDKs use temurin https://blog.adoptopenjdk.net/2021/08/goodbye-adoptopenjdk-hello-adoptium/
|
||||
java-version: '8'
|
||||
java-version: '11'
|
||||
cache: 'maven' #cache/restore any dependencies to improve the workflow execution time
|
||||
- name: Build with Maven
|
||||
run: mvn -B package --file pom.xml
|
||||
40
History.md
40
History.md
@@ -1,3 +1,43 @@
|
||||
2.12.0
|
||||
=======
|
||||
2024-07-20
|
||||
|
||||
- support pdf export/visualization to PDF, thanks to Heavenfighter #387 allow embedd fonts from jar-file for pdf creation #388
|
||||
- Fix #389: ClassCastException: ZUGFeRDExporterFromA3
|
||||
- jakarta support #372
|
||||
- Upgrade to PDFBox 3 #373
|
||||
- Requires Java 11
|
||||
- #397 Build succeeds but file is unusable on alpine/docker
|
||||
- #392 CLI: action combine: --ignorefileextension to ignore PDF/A input file errors dosen't work
|
||||
- for CLI combine, fx is now default
|
||||
- set profile to XR if XR is imported #395
|
||||
- Powershell compatibility: added --no-additional-attachments command line option for better batch processing:
|
||||
In cmd also --attachments "" worked but in powershell it was hard to figure out that one had to use --attachments '""'
|
||||
- Be able to validate XRechnung/UBL files #337
|
||||
- ph-schematron aktualisiert, logback zugungsten log4j entfernt #402
|
||||
- java.util Logging zugungsten log4j entfernt #407
|
||||
- ZF extended no longer requires deliverydate #411
|
||||
- Return all BankDetails from parsed CII xml. Closes #408.
|
||||
- ubl visualization: do not require ubl namespace prefix #416
|
||||
|
||||
2.11.0
|
||||
=======
|
||||
2024-05-22
|
||||
|
||||
- EN16931 validation 1.3.12 codelists v11 #357
|
||||
- Fonts removed #358
|
||||
- xrechnungimporter to read from filename, inputstream
|
||||
- invoice's getSender/getRecipient() now return tradeparty no IZUGFeRDExportableTradeParty
|
||||
- (first) IBAN is now parsed into sender's getBankDetails
|
||||
- zugferdimporter to accept xml files
|
||||
- UBL importer to also parse contacts
|
||||
- https://github.com/ZUGFeRD/mustangproject/pull/369
|
||||
- support inputstreams https://github.com/ZUGFeRD/mustangproject/pull/379
|
||||
- #314 ZUGFeRDInvoiceImporter additional constructur
|
||||
- add XML cash discount write support (new class, previously only possible for XRechnung, not ZF Extended, using a manually encoded setPaymentTermDescription)
|
||||
- surrendered to XRechnung 3 compromises, e.g. no longer put gross amount if it does not deviate from net
|
||||
- be able to programmatically access validation messages https://github.com/ZUGFeRD/mustangproject/pull/382
|
||||
|
||||
2.10.0
|
||||
=======
|
||||
2023-12-30
|
||||
|
||||
@@ -1,258 +1,244 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.mustangproject</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>2.12.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.mustangproject</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>2.9.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.mustangproject</groupId>
|
||||
<artifactId>Mustang-CLI</artifactId>
|
||||
<name>e-invoices commandline tool, allowing to create(embed), split and validate Factur-X/ZUGFeRD files. Validation should also work for XRechnung/CII. </name>
|
||||
<packaging>jar</packaging>
|
||||
<version>2.9.1-SNAPSHOT</version>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.compilerVersion>8</maven.compiler.compilerVersion>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.mustangproject</groupId>
|
||||
<artifactId>validator</artifactId>
|
||||
<version>2.9.1-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
|
||||
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
|
||||
-->
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
|
||||
<dependency><!-- apache commons cli to parse command line -->
|
||||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
<version>1.5.0</version>
|
||||
</dependency>
|
||||
<artifactId>Mustang-CLI</artifactId>
|
||||
<name>e-invoices commandline tool, allowing to create(embed), split and validate Factur-X/ZUGFeRD files. Validation
|
||||
should also work for XRechnung/CII.
|
||||
</name>
|
||||
<packaging>jar</packaging>
|
||||
<version>2.12.0-SNAPSHOT</version>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.compilerVersion>11</maven.compiler.compilerVersion>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.mustangproject</groupId>
|
||||
<artifactId>validator</artifactId>
|
||||
<version>2.12.0-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
|
||||
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
|
||||
-->
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
|
||||
<dependency><!-- apache commons cli to parse command line -->
|
||||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
<version>1.8.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.riversun</groupId>
|
||||
<artifactId>bigdoc</artifactId>
|
||||
<version>0.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.9.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
<version>5.9.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- for directory validation: -->
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-core</artifactId>
|
||||
<version>2.9.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-assertj</artifactId>
|
||||
<version>2.9.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.10.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
<version>5.10.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- for directory validation: -->
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-core</artifactId>
|
||||
<version>2.10.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-assertj</artifactId>
|
||||
<version>2.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- /directory validation: -->
|
||||
<!-- /directory validation: -->
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
<version>4.0.2</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<!-- mvn help:effective-pom will otherwise tell it just defaults
|
||||
to 2.3.2 - which does not release in the maven repo, and neither shows any
|
||||
error message :-( -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<!-- mvn help:effective-pom will otherwise tell it just defaults
|
||||
to 2.3.2 - which does not release in the maven repo, and neither shows any
|
||||
error message :-( -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<runOrder>alphabetical</runOrder>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<runOrder>alphabetical</runOrder>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- allow getImplementationVersion for the pom.xml -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
|
||||
</manifest>
|
||||
<manifestSections>
|
||||
<manifestSection>
|
||||
<name>FreeSans.ttf</name>
|
||||
<manifestEntries>
|
||||
<Content-Type>font/ttf</Content-Type>
|
||||
</manifestEntries>
|
||||
</manifestSection>
|
||||
<manifestSection>
|
||||
<name>FreeSerif.ttf</name>
|
||||
<manifestEntries>
|
||||
<Content-Type>application/x-font</Content-Type>
|
||||
</manifestEntries>
|
||||
</manifestSection>
|
||||
<manifestSection>
|
||||
<name>Times-Bold.ttf</name>
|
||||
<manifestEntries>
|
||||
<Content-Type>application/x-font</Content-Type>
|
||||
</manifestEntries>
|
||||
</manifestSection>
|
||||
</manifestSections>
|
||||
<!-- allow getImplementationVersion for the pom.xml -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.4.2</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
|
||||
</manifest>
|
||||
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<mainClass>org.mustangproject.commandline.main</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<!-- http://stackoverflow.com/questions/574594/how-can-i-create-an-executable-jar-with-dependencies-using-maven
|
||||
mvn clean compile assembly:single -->
|
||||
<!-- or whatever version you use -->
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.4.3</version>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>org.mustangproject.commandline.Main</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>LICENSE</exclude>
|
||||
<exclude>NOTICE</exclude>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>log4j:log4j</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>commons-logging:commons-logging</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>com.sun.xml.bind:jaxb-impl</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes />
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile> <!-- enforce building binaries with Java 1.8 for Maven Central, otherwise using them e.g. as jar will
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<mainClass>org.mustangproject.commandline.main</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<!-- http://stackoverflow.com/questions/574594/how-can-i-create-an-executable-jar-with-dependencies-using-maven
|
||||
mvn clean compile assembly:single -->
|
||||
<!-- or whatever version you use -->
|
||||
<source>11</source>
|
||||
<target>11</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>org.mustangproject.commandline.Main</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>LICENSE</exclude>
|
||||
<exclude>NOTICE</exclude>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>log4j:log4j</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>commons-logging:commons-logging</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>com.sun.xml.bind:jaxb-impl</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes/>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile> <!-- enforce building binaries with Java 1.8 for Maven Central, otherwise using them e.g. as jar will
|
||||
throw a version exception, triggered automatically on mvn release:release (hopefully) and requires an according
|
||||
~/.m2/toolchains.xml file, @see doc/development_documentation.md -->
|
||||
<id>release-sign-artifacts</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>performRelease</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-toolchains-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>toolchain</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<toolchains>
|
||||
<jdk>
|
||||
<version>8</version>
|
||||
<vendor>adopt</vendor>
|
||||
</jdk>
|
||||
</toolchains>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
<comments>A business-friendly OSS license</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Jochen Stärk</name>
|
||||
<email>jstaerk@usegroup.de</email>
|
||||
<roles>
|
||||
<role>architect</role>
|
||||
<role>developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
</developers>
|
||||
<id>release-sign-artifacts</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>performRelease</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-toolchains-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>toolchain</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<toolchains>
|
||||
<jdk>
|
||||
<version>11</version>
|
||||
<vendor>adopt</vendor>
|
||||
</jdk>
|
||||
</toolchains>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
<comments>A business-friendly OSS license</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Jochen Stärk</name>
|
||||
<email>jstaerk@usegroup.de</email>
|
||||
<roles>
|
||||
<role>architect</role>
|
||||
<role>developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
</developers>
|
||||
</project>
|
||||
|
||||
@@ -36,64 +36,66 @@ import java.util.ArrayList;
|
||||
|
||||
public class Main {
|
||||
private static org.slf4j.Logger LOGGER; // log output
|
||||
|
||||
private static void printUsage() {
|
||||
System.err.println(getUsage());
|
||||
}
|
||||
|
||||
private static String getUsage() {
|
||||
return "Usage: --action metrics|combine|extract|a3only|ubl|validate|validateExpectInvalid|validateExpectValid|visualize [-d,--directory] [-l,--listfromstdin] [-i,--ignore fileextension, PDF/A errors] [--disable-file-logging] | [-h,--help] \r\n"
|
||||
+ " --action license display open source license and notice\n"
|
||||
+ " --action metrics\n"
|
||||
+ " -d, --directory count ZUGFeRD files in directory to be scanned\n"
|
||||
+ " If it is a directory, it will recurse.\n"
|
||||
+ " -l, --listfromstdin count ZUGFeRD files from a list of linefeed separated files on runtime.\n"
|
||||
+ " It will start once a blank line has been entered.\n" + "\n"
|
||||
+ " Additional parameter for both count operations\n"
|
||||
+ " [-i, --ignorefileextension] Check for all files (*.*) instead of PDF files only (*.pdf) in metrics, ignore PDF/A input file errors in combine\n"
|
||||
+ " [--disable-file-logging] disable logging to file.\n"
|
||||
+ " --action extract extract Factur-X PDF to XML file\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " [--source <filename>]: set input PDF file\n"
|
||||
+ " [--out <filename>]: set output XML file\n"
|
||||
+ " --action a3only upgrade from PDF/A1 to A3 only (no ZUGFeRD data attached)\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " [--source <filename>]: set input PDF file\n"
|
||||
+ " [--out <filename>]: set output PDF file\n"
|
||||
+ " --action combine combine XML and PDF file to Factur-X PDF file\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " [--source <filename>]: set input PDF file\n"
|
||||
+ " [--source-xml <filename>]: set input XML file\n"
|
||||
+ " [--out <filename>]: set output PDF file\n"
|
||||
+ " [--format <fx|zf|ox|da>]: set Factur-X, ZUGFeRD, Order-X or Cross Industry Despatch Advice\n"
|
||||
+ " [--version <1|2>]: set ZUGFeRD version\n"
|
||||
+ " [--profile <...>]: set ZUGFeRD profile\n"
|
||||
+ " For ZUGFeRD v1 or Order-X: <B>ASIC, <C>OMFORT or EX<T>ENDED\n"
|
||||
+ " For ZUGFeRD v2: <M>INIMUM, BASIC <W>L, <B>ASIC, <C>IUS, <E>N16931, <X>Rechnung, EX<T>ENDED\n"
|
||||
+ " [--attachments <filenames>]: list of file attachments (passing a single empty file name prevents prompting)\n"
|
||||
+ " --action ubl convert UN/CEFACT 2016b CII XML to UBL XML\n"
|
||||
+ " [--source <filename>]: set input XML file\n"
|
||||
+ " [--out <filename>]: set output XML file\n"
|
||||
+ " --action upgrade upgrade ZUGFeRD XML to ZUGFeRD 2 XML\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " [--source <filename>]: set input XML ZUGFeRD 1 file\n"
|
||||
+ " [--out <filename>]: set output XML ZUGFeRD 2 file\n"
|
||||
+ " --action validate validate XML or PDF file \n"
|
||||
+ " [--no-notices]: refrain from reporting notices\n"
|
||||
+ " [--logAppend <text>]: text to be added to log line\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " [--source <filename>]: input PDF or XML file\n"
|
||||
+ " --action validateExpectInvalid validate directory expecting negative results \n"
|
||||
+ " [--no-notices]: refrain from reporting notices\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " -d, --directory to check recursively\n"
|
||||
+ " --action validateExpectValid validate directory expecting positive results \n"
|
||||
+ " [--no-notices]: refrain from reporting notices\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " -d, --directory to check recursively \n"
|
||||
+ " --action visualize convert XML to HTML \n"
|
||||
+ " [--language <lang>]: set output lang (en, fr or de)\n"
|
||||
+ " [--source <filename>]: set input XML file\n"
|
||||
+ " [--out <filename>]: set output HTML file\n"
|
||||
+ " --action license display open source license and notice\n"
|
||||
+ " --action metrics\n"
|
||||
+ " -d, --directory count ZUGFeRD files in directory to be scanned\n"
|
||||
+ " If it is a directory, it will recurse.\n"
|
||||
+ " -l, --listfromstdin count ZUGFeRD files from a list of linefeed separated files on runtime.\n"
|
||||
+ " It will start once a blank line has been entered.\n" + "\n"
|
||||
+ " Additional parameter for both count operations\n"
|
||||
+ " [-i, --ignorefileextension] Check for all files (*.*) instead of PDF files only (*.pdf) in metrics, ignore PDF/A input file errors in combine\n"
|
||||
+ " [--disable-file-logging] disable logging to file.\n"
|
||||
+ " --action extract extract Factur-X PDF to XML file\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " [--source <filename>]: set input PDF file\n"
|
||||
+ " [--out <filename>]: set output XML file\n"
|
||||
+ " --action a3only upgrade from PDF/A1 to A3 only (no ZUGFeRD data attached)\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " [--source <filename>]: set input PDF file\n"
|
||||
+ " [--out <filename>]: set output PDF file\n"
|
||||
+ " --action combine combine XML and PDF file to Factur-X PDF file\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " [--source <filename>]: set input PDF file\n"
|
||||
+ " [--source-xml <filename>]: set input XML file\n"
|
||||
+ " [--out <filename>]: set output PDF file\n"
|
||||
+ " [--format <fx|zf|ox|da>]: set Factur-X, ZUGFeRD, Order-X or Cross Industry Despatch Advice\n"
|
||||
+ " [--version <1|2>]: set ZUGFeRD version\n"
|
||||
+ " [--profile <...>]: set ZUGFeRD profile\n"
|
||||
+ " For ZUGFeRD v1 or Order-X: <B>ASIC, <C>OMFORT or EX<T>ENDED\n"
|
||||
+ " For ZUGFeRD v2: <M>INIMUM, BASIC <W>L, <B>ASIC, <C>IUS, <E>N16931, <X>Rechnung, EX<T>ENDED\n"
|
||||
+ " [--attachments <filenames>]: list of file attachments (passing a single empty file name prevents prompting)\n"
|
||||
+ " [--no-additional-attachments]: prevent prompting for attachments\n"
|
||||
+ " --action ubl convert UN/CEFACT 2016b CII XML to UBL XML\n"
|
||||
+ " [--source <filename>]: set input XML file\n"
|
||||
+ " [--out <filename>]: set output XML file\n"
|
||||
+ " --action upgrade upgrade ZUGFeRD XML to ZUGFeRD 2 XML\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " [--source <filename>]: set input XML ZUGFeRD 1 file\n"
|
||||
+ " [--out <filename>]: set output XML ZUGFeRD 2 file\n"
|
||||
+ " --action validate validate XML or PDF file \n"
|
||||
+ " [--no-notices]: refrain from reporting notices\n"
|
||||
+ " [--logAppend <text>]: text to be added to log line\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " [--source <filename>]: input PDF or XML file\n"
|
||||
+ " --action validateExpectInvalid validate directory expecting negative results \n"
|
||||
+ " [--no-notices]: refrain from reporting notices\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " -d, --directory to check recursively\n"
|
||||
+ " --action validateExpectValid validate directory expecting positive results \n"
|
||||
+ " [--no-notices]: refrain from reporting notices\n"
|
||||
+ " Additional parameters (optional - user will be prompted if not defined)\n"
|
||||
+ " -d, --directory to check recursively \n"
|
||||
+ " --action visualize convert XML to HTML \n"
|
||||
+ " [--language <lang>]: set output lang (en, fr or de)\n"
|
||||
+ " [--source <filename>]: set input XML file\n"
|
||||
+ " [--out <filename>]: set output HTML file\n"
|
||||
+ " --action pdf convert XML to PDF \n"
|
||||
+ " [--source <filename>]: set input XML file\n"
|
||||
+ " [--out <filename>]: set output PDF file\n"
|
||||
@@ -330,32 +332,36 @@ public class Main {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
CommandLine cmd;
|
||||
CommandLineParser parser = new BasicParser();
|
||||
CommandLineParser parser = new DefaultParser();
|
||||
|
||||
// create Options object
|
||||
Options options = new Options();
|
||||
|
||||
options.addOption(new Option("h", "help", false, "display usage"));
|
||||
options.addOption(new Option("a", "action", true, "which action to perform"));
|
||||
options.addOption(new Option("f", "format", true, "which format to output"));
|
||||
options.addOption(new Option("", "version", true, "which version of the standard to use"));
|
||||
options.addOption(new Option("", "profile", true, "which profile of the standard to use"));
|
||||
Option attachmentOpt = new Option("", "attachments", true, "File attachments");
|
||||
options.addOption(new Option("version", "version", true, "which version of the standard to use"));
|
||||
options.addOption(new Option("profile", "profile", true, "which profile of the standard to use"));
|
||||
options.addOption(new Option("no-additional-attachments", "no-additional-attachments", false, "prevent prompting for attachments"));
|
||||
Option attachmentOpt = new Option("attachments", "attachments", true, "File attachments");
|
||||
attachmentOpt.setValueSeparator(',');
|
||||
attachmentOpt.setArgs(Option.UNLIMITED_VALUES);
|
||||
|
||||
options.addOption(attachmentOpt);
|
||||
options.addOption(new Option("", "source",true, "which source file to use"));
|
||||
options.addOption(new Option("", "source-xml",true, "which source file to use"));
|
||||
options.addOption(new Option("", "language",true, "output language (en, de or fr)"));
|
||||
options.addOption(new Option("", "out",true, "which output file to write to"));
|
||||
options.addOption(new Option("", "no-notices",false, "suppress non-fatal errors"));
|
||||
options.addOption(new Option("", "logAppend",true, "freeform text to be appended to log messages"));
|
||||
options.addOption(new Option("", "disable-file-logging", false, "suppress logging to file"));
|
||||
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("l", "listfromstdin",false, "take list of files from commandline"));
|
||||
boolean optionsRecognized=false;
|
||||
options.addOption(new Option("source", "source", true, "which source file to use"));
|
||||
options.addOption(new Option("source-xml", "source-xml", true, "which source file to use"));
|
||||
options.addOption(new Option("language", "language", true, "output language (en, de or fr)"));
|
||||
options.addOption(new Option("out", "out", true, "which output file to write to"));
|
||||
options.addOption(new Option("no-notices", "no-notices", false, "suppress non-fatal errors"));
|
||||
options.addOption(new Option("logAppend", "logAppend", true, "freeform text to be appended to log messages"));
|
||||
options.addOption(new Option("disable-file-logging", "disable-file-logging", false, "suppress logging to file"));
|
||||
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("l", "listfromstdin", false, "take list of files from commandline"));
|
||||
|
||||
boolean optionsRecognized = false;
|
||||
String action = "";
|
||||
Boolean disableFileLogging = false;
|
||||
|
||||
Boolean disableFileLogging = false;
|
||||
try {
|
||||
cmd = parser.parse(options, args);
|
||||
|
||||
@@ -364,7 +370,8 @@ public class Main {
|
||||
String directoryName = cmd.getOptionValue("directory");
|
||||
Boolean filesFromStdIn = cmd.hasOption("listfromstdin");//((Number)cmdLine.getParsedOptionValue("integer-option")).intValue();
|
||||
Boolean ignoreFileExt = cmd.hasOption("ignorefileextension");
|
||||
Boolean helpRequested = cmd.hasOption("help") || ((action!=null)&&(action.equals("help")));
|
||||
Boolean noAttachments = cmd.hasOption("no-additional-attachments");
|
||||
Boolean helpRequested = cmd.hasOption("help") || ((action != null) && (action.equals("help")));
|
||||
disableFileLogging = cmd.hasOption("disable-file-logging");
|
||||
|
||||
String sourceName = cmd.getOptionValue("source");
|
||||
@@ -380,14 +387,12 @@ public class Main {
|
||||
String[] attachmentFilenames = cmd.hasOption("attachments") ? cmd.getOptionValues("attachments") : null;
|
||||
|
||||
|
||||
|
||||
|
||||
ArrayList<FileAttachment> attachments=new ArrayList <>();
|
||||
ArrayList<FileAttachment> attachments = new ArrayList<>();
|
||||
/*
|
||||
setting system property to disable FILE appender and
|
||||
suppress creation of files and folders.
|
||||
*/
|
||||
System.setProperty("FILE_APPENDER_ENABLED", ((Boolean)(disableFileLogging==false)).toString());
|
||||
System.setProperty("FILE_APPENDER_ENABLED", ((Boolean) (disableFileLogging == false)).toString());
|
||||
|
||||
LOGGER = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
|
||||
|
||||
@@ -401,7 +406,7 @@ public class Main {
|
||||
performMetrics(directoryName, filesFromStdIn, ignoreFileExt);
|
||||
optionsRecognized = true;
|
||||
} else if ((action != null) && (action.equals("combine"))) {
|
||||
performCombine(sourceName, sourceXMLName, outName, format, zugferdVersion, zugferdProfile, ignoreFileExt, attachmentFilenames, attachments);
|
||||
performCombine(sourceName, sourceXMLName, outName, format, zugferdVersion, zugferdProfile, ignoreFileExt, attachmentFilenames, attachments, noAttachments);
|
||||
optionsRecognized = true;
|
||||
} else if ((action != null) && (action.equals("extract"))) {
|
||||
performExtract(sourceName, outName);
|
||||
@@ -422,7 +427,7 @@ public class Main {
|
||||
performUBL(sourceName, outName);
|
||||
optionsRecognized = true;
|
||||
} else if ((action != null) && (action.equals("validate"))) {
|
||||
optionsRecognized = performValidate(sourceName, noNotices != null && noNotices, cmd.getOptionValue("logAppend"));
|
||||
optionsRecognized = performValidate(sourceName, noNotices, cmd.getOptionValue("logAppend"));
|
||||
} else if ((action != null) && (action.equals("validateExpectValid"))) {
|
||||
optionsRecognized = performValidateExpect(true, directoryName);
|
||||
} else if ((action != null) && (action.equals("validateExpectInvalid"))) {
|
||||
@@ -439,7 +444,11 @@ public class Main {
|
||||
System.exit(2);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
} else {
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
@@ -510,10 +519,11 @@ public class Main {
|
||||
ensureFileNotExists(outName);
|
||||
|
||||
// All params are good! continue...
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().convertOnly().load(pdfName);
|
||||
|
||||
ze.export(outName);
|
||||
System.out.println("Written to " + outName);
|
||||
try (ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1()) {
|
||||
ze.convertOnly().load(pdfName);
|
||||
ze.export(outName);
|
||||
System.out.println("Written to " + outName);
|
||||
}
|
||||
}
|
||||
|
||||
private static void performExtract(String pdfName, String xmlName) throws IOException {
|
||||
@@ -546,7 +556,7 @@ public class Main {
|
||||
}
|
||||
|
||||
private static void performCombine(String pdfName, String xmlName, String outName, String format, String zfVersion,
|
||||
String zfProfile, Boolean ignoreInputErrors, String[] attachmentFilenames, ArrayList<FileAttachment> attachments) throws Exception {
|
||||
String zfProfile, Boolean ignoreInputErrors, String[] attachmentFilenames, ArrayList<FileAttachment> attachments, Boolean noAttachments) throws Exception {
|
||||
/*
|
||||
* ZUGFeRDExporter ze= new ZUGFeRDExporterFromA1Factory()
|
||||
* .setProducer("toecount") .setCreator(System.getProperty("user.name"))
|
||||
@@ -576,12 +586,14 @@ public class Main {
|
||||
|
||||
if (attachmentFilenames == null) {
|
||||
byte attachmentContents[] = null;
|
||||
String attachmentFilename, attachmentMime, attachmentDescription;
|
||||
attachmentFilename = getFilenameFromUser("Additional file attachments filename (empty for none)", "", "pdf", true, false);
|
||||
if (attachmentFilename.length() != 0) {
|
||||
attachmentContents = Files.readAllBytes(Paths.get(attachmentFilename));
|
||||
attachmentMime = Files.probeContentType(Paths.get(attachmentFilename));
|
||||
attachments.add(new FileAttachment(attachmentFilename, attachmentMime, "Data", attachmentContents));
|
||||
String attachmentFilename, attachmentMime;
|
||||
if (!noAttachments) {
|
||||
attachmentFilename = getFilenameFromUser("Additional file attachments filename (empty for none)", "", "pdf", true, false);
|
||||
if (attachmentFilename.length() != 0) {
|
||||
attachmentContents = Files.readAllBytes(Paths.get(attachmentFilename));
|
||||
attachmentMime = Files.probeContentType(Paths.get(attachmentFilename));
|
||||
attachments.add(new FileAttachment(attachmentFilename, attachmentMime, "Data", attachmentContents));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < attachmentFilenames.length; i++) {
|
||||
@@ -597,7 +609,7 @@ public class Main {
|
||||
|
||||
if (format == null) {
|
||||
try {
|
||||
format = getStringFromUser("Format (fx=Factur-X, zf=ZUGFeRD, ox=Order-X, da=Cross Industry Despatch Advice)", "zf", "fx|zf|ox|da");
|
||||
format = getStringFromUser("Format (fx=Factur-X, zf=ZUGFeRD, ox=Order-X, da=Cross Industry Despatch Advice)", "fx", "fx|zf|ox|da");
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
@@ -607,7 +619,7 @@ public class Main {
|
||||
|
||||
if (zfVersion == null) {
|
||||
try {
|
||||
zfVersion = getStringFromUser("Version (1 or 2)", Integer.toString(ZUGFeRDExporterFromA3.DefaultZUGFeRDVersion), "1|2");
|
||||
zfVersion = getStringFromUser("Version (1 or 2)", "1", "1|2");//fx default version is 1
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
@@ -691,41 +703,33 @@ public class Main {
|
||||
IZUGFeRDExporter ze = null;
|
||||
// All params are good! continue...
|
||||
if (format.equals("ox")) {
|
||||
ze = new OXExporterFromA1().setProducer("Mustang-cli")
|
||||
.setZUGFeRDVersion(zfIntVersion)
|
||||
.setCreator(System.getProperty("user.name")).setProfile(zfConformanceLevelProfile);
|
||||
ze = new OXExporterFromA1();
|
||||
if (ignoreInputErrors) {
|
||||
((OXExporterFromA1) ze).ignorePDFAErrors();
|
||||
}
|
||||
|
||||
} else if (format.equals("da")) {
|
||||
ze = new DXExporterFromA1().setProducer("Mustang-cli")
|
||||
.setZUGFeRDVersion(zfIntVersion)
|
||||
.setCreator(System.getProperty("user.name")).setProfile(zfConformanceLevelProfile);
|
||||
|
||||
ze = new DXExporterFromA1();
|
||||
if (ignoreInputErrors) {
|
||||
((DXExporterFromA1) ze).ignorePDFAErrors();
|
||||
}
|
||||
|
||||
} else {
|
||||
if (format.equals("fx")) {
|
||||
zfIntVersion=2;// actually we are talking of generation, not version
|
||||
zfIntVersion = 2;// actually we are talking of generation, not version
|
||||
// so even if someone correctly requested factur-x 1 internally we call it zugferd 2 :-(
|
||||
}
|
||||
ze = new ZUGFeRDExporterFromPDFA().load(pdfName);
|
||||
|
||||
ze.setProducer("Mustang-cli")
|
||||
.setZUGFeRDVersion(zfIntVersion)
|
||||
.setCreator(System.getProperty("user.name")).setProfile(zfConformanceLevelProfile);
|
||||
ze = new ZUGFeRDExporterFromPDFA();
|
||||
if (ignoreInputErrors) {
|
||||
((ZUGFeRDExporterFromA1) ze).ignorePDFAErrors();
|
||||
((ZUGFeRDExporterFromPDFA) ze).ignorePDFAErrors();
|
||||
}
|
||||
}
|
||||
for (FileAttachment attachment : attachments) {
|
||||
((ZUGFeRDExporterFromA3) ze).attachFile(attachment.getFilename(), attachment.getData(), attachment.getMimetype(), attachment.getRelation());
|
||||
}
|
||||
|
||||
// ze = ze.load(pdfName);
|
||||
ze.load(pdfName);
|
||||
ze.setProducer("Mustang-cli")
|
||||
.setZUGFeRDVersion(zfIntVersion)
|
||||
.setCreator(System.getProperty("user.name")).setProfile(zfConformanceLevelProfile);
|
||||
|
||||
if (format.equals("zf")) {
|
||||
ze.disableFacturX();
|
||||
@@ -737,7 +741,9 @@ public class Main {
|
||||
System.out.println("Written to " + outName);
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -837,14 +843,9 @@ public class Main {
|
||||
} else {
|
||||
zvi.toPDF(sourceName, outName);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
} catch (TransformerException e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
System.out.println("Written to " + outName);
|
||||
|
||||
@@ -871,11 +872,8 @@ public class Main {
|
||||
* @throws Exception e.g. if the specified resource does not exist at the specified location
|
||||
*/
|
||||
static public String ExportResource(String resourceName) throws Exception {
|
||||
InputStream stream = null;
|
||||
OutputStream resStreamOut = null;
|
||||
String jarFolder;
|
||||
try {
|
||||
stream = Main.class.getResourceAsStream(resourceName);//note that each / is a directory down in the "jar tree" been the jar the root of the tree
|
||||
try (InputStream stream = Main.class.getResourceAsStream(resourceName)) {//note that each / is a directory down in the "jar tree" been the jar the root of the tree
|
||||
if (stream == null) {
|
||||
throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file.");
|
||||
}
|
||||
@@ -883,15 +881,11 @@ public class Main {
|
||||
int readBytes;
|
||||
byte[] buffer = new byte[4096];
|
||||
jarFolder = System.getProperty("user.dir");
|
||||
resStreamOut = new FileOutputStream(jarFolder + resourceName);
|
||||
while ((readBytes = stream.read(buffer)) > 0) {
|
||||
resStreamOut.write(buffer, 0, readBytes);
|
||||
try (FileOutputStream resStreamOut = new FileOutputStream(jarFolder + resourceName)) {
|
||||
while ((readBytes = stream.read(buffer)) > 0) {
|
||||
resStreamOut.write(buffer, 0, readBytes);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw ex;
|
||||
} finally {
|
||||
stream.close();
|
||||
resStreamOut.close();
|
||||
}
|
||||
|
||||
return jarFolder + resourceName;
|
||||
@@ -913,7 +907,8 @@ public class Main {
|
||||
if (fileName == null)
|
||||
return false;
|
||||
File f = new File(fileName);
|
||||
return f.exists();
|
||||
// "exists" also returns true for directories
|
||||
return f.isFile();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,9 +14,6 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xmlunit.builder.Input;
|
||||
import org.xmlunit.xpath.JAXPXPathEngine;
|
||||
import org.xmlunit.xpath.XPathEngine;
|
||||
import org.mustangproject.validator.ZUGFeRDValidator;
|
||||
|
||||
import static org.xmlunit.assertj.XmlAssert.assertThat;
|
||||
@@ -50,25 +47,23 @@ public class ValidatorFileWalker
|
||||
Date date = new Date();
|
||||
String expectedString="valid";
|
||||
if (!expectValid) {
|
||||
expectedString="invalid";
|
||||
}
|
||||
expectedString="invalid";
|
||||
}
|
||||
if ((attr!=null)&&(attr.isRegularFile())) {
|
||||
if (matcher.matches(file.getFileName())) {
|
||||
boolean thisResultValid=true;
|
||||
String thisResultString=" valid";
|
||||
try {
|
||||
assertThat(zul.validate(file.toAbsolutePath().toString())).valueByXPath("/validation/summary/@status")
|
||||
.asString()
|
||||
.isEqualTo(expectedString);
|
||||
|
||||
} catch (AssertionError ae) {
|
||||
thisResultValid=false;
|
||||
thisResultString="invalid";
|
||||
allValid=false;
|
||||
}
|
||||
LOGGER.info(String.format("\n@%s Testing file %d: %s (%s)", dateFormat.format(date), fileCount++, thisResultString, file));
|
||||
|
||||
}
|
||||
try {
|
||||
assertThat(zul.validate(file.toAbsolutePath().toString())).valueByXPath("/validation/summary/@status")
|
||||
.asString()
|
||||
.isEqualTo(expectedString);
|
||||
|
||||
} catch (AssertionError ae) {
|
||||
thisResultString="invalid";
|
||||
allValid=false;
|
||||
}
|
||||
LOGGER.info(String.format("\n@%s Testing file %d: %s (%s)", dateFormat.format(date), fileCount++, thisResultString, file));
|
||||
|
||||
}
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
36
README.md
36
README.md
@@ -4,33 +4,53 @@ Mustangproject
|
||||
|
||||
Source code repository for the [Mustang project](http://www.mustangproject.org/) open source java PDF invoice metadata library in ZUGFeRD format.
|
||||
|
||||
License
|
||||
Build
|
||||
-----
|
||||
|
||||
Subject to the Apache license http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
These are the recommended dependencies for the project:
|
||||
|
||||
Running
|
||||
-----
|
||||
- OpenJDK 21.0.2 2024-01-16
|
||||
- Apache Maven 3.9.6
|
||||
|
||||
This project requires Maven to run. Build project with "mvn clean install". This will build the project, test it and install the artifacts to local cache. After that the mustang jar can be used.
|
||||
You can build the project with:
|
||||
|
||||
More information in [the mustang documentation](https://github.com/ZUGFeRD/mustangproject/blob/master/doc/ZugferdDev.en.pdf?raw=true).
|
||||
```shell
|
||||
mvn clean install
|
||||
```
|
||||
|
||||
This will run the tests, build the project artefacts, and install the artifacts to the local
|
||||
cache. After that the mustang JAR can be used.
|
||||
|
||||
More information on how to develop **on** mustang:
|
||||
|
||||
- [Developer documentation](https://github.com/ZUGFeRD/mustangproject/blob/master/doc/development_documentation.md)
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
If you setup a Maven project, you can grab the artifacts using
|
||||
If you set up a Maven project, you can reference the mustang artifact like this:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.mustangproject</groupId>
|
||||
<artifactId>library</artifactId>
|
||||
<version>2.10.0</version>
|
||||
<version>2.12.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
Further docs on how to develop **with** mustang:
|
||||
|
||||
- [ZugferdDev.en.pdf](https://github.com/ZUGFeRD/mustangproject/blob/master/doc/ZugferdDev.en.pdf?raw=true): The English mustang user documentation.
|
||||
- [ZugferdDev.de.pdf](https://github.com/ZUGFeRD/mustangproject/blob/master/doc/ZugferdDev.de.pdf?raw=true): The German mustang user documentation.
|
||||
- [Usage examples](https://www.mustangproject.org/use/): Read and write electronic invoices.
|
||||
- [Mustang classes](https://www.mustangproject.org/invoice-class/): Using the mustang classes.
|
||||
|
||||
Contact
|
||||
-----
|
||||
|
||||
Developer: Jochen Stärk. For questions please contact Jochen at jstaerk [at] usegroup.de
|
||||
|
||||
License
|
||||
-----
|
||||
|
||||
Subject to the [Apache-2.0 license](http://www.apache.org/licenses/LICENSE-2.0.html).
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,373 +0,0 @@
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
@@ -1,26 +0,0 @@
|
||||
= Demo Documentation Component B
|
||||
// URLs
|
||||
:url-project: https://antora.org
|
||||
:url-docs: https://docs.antora.org
|
||||
:url-org: https://gitlab.com/antora
|
||||
:url-group: {url-org}/demo
|
||||
:url-demo-site: https://antora.gitlab.io/demo/docs-site
|
||||
:url-site-readme: {url-group}/docs-site/blob/master/README.adoc
|
||||
:url-opendevise: https://opendevise.com
|
||||
|
||||
Component B is an example of a documentation component.
|
||||
It is used by the {url-demo-site}[Antora Demo site].
|
||||
The playbook and instructions for the Demo site are located in the {url-site-readme}[Demo site playbook project].
|
||||
|
||||
== Resources
|
||||
|
||||
* {url-project}[Antora Project Site]
|
||||
* {url-docs}[Antora Docs]
|
||||
* {url-org}[Antora Repositories]
|
||||
|
||||
== Copyright and License
|
||||
|
||||
Copyright (C) 2017-present by OpenDevise Inc. and the individual contributors to Antora.
|
||||
|
||||
Use of this software is granted under the terms of the https://www.mozilla.org/en-US/MPL/2.0/[Mozilla Public License Version 2.0] (MPL-2.0).
|
||||
See link:LICENSE[] to find the full license text.
|
||||
@@ -1,21 +0,0 @@
|
||||
# This file represents "software".
|
||||
# This file helps show that documentation files can be in the same repository as software.
|
||||
|
||||
rescue => ex
|
||||
begin
|
||||
context = %(asciidoctor: FAILED: #{attrs['docfile'] || '<stdin>'}: Failed to load AsciiDoc document)
|
||||
if ex.respond_to? :exception
|
||||
# The original message must be explicitely preserved when wrapping a Ruby exception
|
||||
wrapped_ex = ex.exception %(#{context} - #{ex.message})
|
||||
# JRuby automatically sets backtrace, but not MRI
|
||||
wrapped_ex.set_backtrace ex.backtrace
|
||||
else
|
||||
# Likely a Java exception class
|
||||
wrapped_ex = ex.class.new context, ex
|
||||
wrapped_ex.stack_trace = ex.stack_trace
|
||||
end
|
||||
rescue
|
||||
wrapped_ex = ex
|
||||
end
|
||||
raise wrapped_ex
|
||||
end
|
||||
@@ -1,7 +0,0 @@
|
||||
name: mustang
|
||||
title: Mustang Library
|
||||
version: 2.6.1
|
||||
prerelease: -beta.1
|
||||
nav:
|
||||
- modules/ROOT/nav.adoc
|
||||
- modules/module-one/nav.adoc
|
||||
@@ -1 +0,0 @@
|
||||
* xref:index.adoc[]
|
||||
@@ -1,33 +0,0 @@
|
||||
= Welcome to Component B!
|
||||
:navtitle: Welcome
|
||||
|
||||
This is the automatic start page for version *{page-component-display-version}* of Component B.
|
||||
|
||||
Component B is one of two documentation components in the Antora Demo.
|
||||
The other docs component, Component A, can be accessed using the component selector menu (aka component drawer) at the bottom of the menu on the left side of the page.
|
||||
|
||||
== Page source
|
||||
|
||||
This page is sourced from the AsciiDoc file named [.path]_index.adoc_ that is located at [.path]_demo-component-b/docs/modules/ROOT/pages_.
|
||||
|
||||
=== Why is this the home page of Component B?
|
||||
|
||||
This page is automatically used as the start page of Component B because it is stored in the ROOT module and named [.path]_index.adoc_.
|
||||
|
||||
=== Why is this the home page of the Antora Demo site?
|
||||
|
||||
This page is used as the home page for the Antora Demo because it is assigned as the site `start_page` in the Demo site's playbook file [.path]_site.yml_.
|
||||
|
||||
== Cross reference syntax to target this page
|
||||
|
||||
To create a cross reference *to this page from another page in the ROOT module of Component B*, the xref syntax would be `\xref:index.adoc[]`.
|
||||
|
||||
To create a cross reference *to this page from a page in Module One of Component B*, the xref syntax would be `\xref:ROOT:index.adoc[]`.
|
||||
|
||||
=== Always target the latest version of this page
|
||||
|
||||
To create a cross reference *to the latest version of this page from a page in Component A*, the xref syntax would be `\xref:component-b::index.adoc[]`.
|
||||
|
||||
=== Target a specific version of this page
|
||||
|
||||
To create a cross reference *to version 1.0 of this page from a page in Component A*, the xref syntax would be `\xref:1.0@component-b::index.adoc[]`.
|
||||
@@ -1 +0,0 @@
|
||||
* xref:overview.adoc[]
|
||||
@@ -1,21 +0,0 @@
|
||||
= Module One Overview
|
||||
|
||||
This is version *{page-component-display-version}* of Module One in Component B.
|
||||
|
||||
== Page source
|
||||
|
||||
This page is sourced from [.path]_demo-component-b/docs/modules/module-one/pages/overview.adoc_.
|
||||
|
||||
== Cross reference syntax to target this page
|
||||
|
||||
To create a cross reference *to this page from another page in Module One*, the xref syntax would be `\xref:overview.adoc[]`.
|
||||
|
||||
To create a cross reference *to this page from a page in the ROOT module of Component B*, the xref syntax would be `\xref:module-one:overview.adoc[]`.
|
||||
|
||||
=== Always target the latest version of this page
|
||||
|
||||
To create a cross reference *to the latest version of this page from a page in Component A*, the xref syntax would be `\xref:component-b:module-one:overview.adoc[]`.
|
||||
|
||||
=== Target a specific version of this page
|
||||
|
||||
To create a cross reference *to version 1.0 of this page from a page in Component A*, the xref syntax would be `\xref:1.0@component-b:module-one:overview.adoc[]`.
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
## General approach
|
||||
## Typical process
|
||||
|
||||
1. build
|
||||
|
||||
@@ -29,6 +29,18 @@ If you do a pull request, please do a feature branch, e.g. if you are working on
|
||||
Most of mustang is a library, adding (autmated junit) test cases is often not only the most sustainable but also the fastest way to see if new/changed functionality works. If something is changed so that old test cases break on purpose please do not just remove them but take the time to fix the test cases
|
||||
|
||||
|
||||
## Typical workflow
|
||||
|
||||
If e.g. new elements or attributes are added, they are often added
|
||||
* in the object so that a developer can use them
|
||||
* in the interface so that a old fashioned developer could use them as well
|
||||
* in the pullprovider so that it actually finds it's way into the XML
|
||||
* in at least one test (the ...edgeTest are supposed to handle edge cases, ~all bells and whistles, maybe it fits there), after the test has been run this should at least once be
|
||||
* validated. If that works one can start implementing the
|
||||
* reading part (along with tests), then it needs to be
|
||||
* documented e.g. on the homepage and
|
||||
* communicated, at the very least by mentioning it in the history.md
|
||||
|
||||
## Architecture
|
||||
|
||||
Mustang contains a library to read/write e-invoices,
|
||||
@@ -155,16 +167,16 @@ In .m2 also need a toolchains.xml which defines a Sun JDK 1.8 target like the fo
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<toolchains>
|
||||
<!-- JDK toolchains -->
|
||||
<toolchain>
|
||||
<type>jdk</type>
|
||||
<provides>
|
||||
<version>8</version>
|
||||
<vendor>adopt</vendor>
|
||||
</provides>
|
||||
<configuration>
|
||||
<jdkHome>C:\Program Files\Eclipse Adoptium\jdk-8.0.352.8-hotspot</jdkHome>
|
||||
</configuration>
|
||||
</toolchain>
|
||||
<toolchain>
|
||||
<type>jdk</type>
|
||||
<provides>
|
||||
<version>11</version>
|
||||
<vendor>adopt</vendor>
|
||||
</provides>
|
||||
<configuration>
|
||||
<jdkHome>C:\Program Files\Eclipse Adoptium\jdk-11.0.23.9-hotspot</jdkHome>
|
||||
</configuration>
|
||||
</toolchain>
|
||||
|
||||
</toolchains>
|
||||
```
|
||||
|
||||
183
doc/mustang-validation.xsd
Normal file
183
doc/mustang-validation.xsd
Normal file
@@ -0,0 +1,183 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
|
||||
<xs:element name="validation">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="pdf"/>
|
||||
<xs:element ref="messages"/>
|
||||
<xs:element ref="summary"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="datetime" use="required"/>
|
||||
<xs:attribute name="filename" use="required" type="xs:NCName"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="pdf">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="report"/>
|
||||
<xs:element ref="info"/>
|
||||
<xs:element ref="messages"/>
|
||||
<xs:element ref="summary"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="report">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="buildInformation"/>
|
||||
<xs:element ref="jobs"/>
|
||||
<xs:element ref="batchSummary"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="buildInformation">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element maxOccurs="unbounded" ref="releaseDetails"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="releaseDetails">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="buildDate" use="required" type="xs:dateTime"/>
|
||||
<xs:attribute name="id" use="required" type="xs:NCName"/>
|
||||
<xs:attribute name="version" use="required" type="xs:NMTOKEN"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="jobs">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="job"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="job">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="item"/>
|
||||
<xs:element ref="validationReport"/>
|
||||
<xs:element ref="duration"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="item">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="name"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="size" use="required" type="xs:integer"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="name" type="xs:string"/>
|
||||
<xs:element name="validationReport">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="details"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="isCompliant" use="required" type="xs:boolean"/>
|
||||
<xs:attribute name="profileName" use="required"/>
|
||||
<xs:attribute name="statement" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="details">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="failedChecks" use="required" type="xs:integer"/>
|
||||
<xs:attribute name="failedRules" use="required" type="xs:integer"/>
|
||||
<xs:attribute name="passedChecks" use="required" type="xs:integer"/>
|
||||
<xs:attribute name="passedRules" use="required" type="xs:integer"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="batchSummary">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="validationReports"/>
|
||||
<xs:element ref="featureReports"/>
|
||||
<xs:element ref="repairReports"/>
|
||||
<xs:element ref="duration"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="encrypted" use="required" type="xs:integer"/>
|
||||
<xs:attribute name="failedToParse" use="required" type="xs:integer"/>
|
||||
<xs:attribute name="outOfMemory" use="required" type="xs:integer"/>
|
||||
<xs:attribute name="totalJobs" use="required" type="xs:integer"/>
|
||||
<xs:attribute name="veraExceptions" use="required" type="xs:integer"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="validationReports">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:integer">
|
||||
<xs:attribute name="compliant" use="required" type="xs:integer"/>
|
||||
<xs:attribute name="failedJobs" use="required" type="xs:integer"/>
|
||||
<xs:attribute name="nonCompliant" use="required" type="xs:integer"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="featureReports">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:integer">
|
||||
<xs:attribute name="failedJobs" use="required" type="xs:integer"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="repairReports">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:integer">
|
||||
<xs:attribute name="failedJobs" use="required" type="xs:integer"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="info">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref="signature"/>
|
||||
<xs:element ref="duration"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="signature" type="xs:NCName"/>
|
||||
<xs:element name="duration">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:NMTOKEN">
|
||||
<xs:attribute name="finish" type="xs:integer"/>
|
||||
<xs:attribute name="start" type="xs:integer"/>
|
||||
<xs:attribute name="unit" type="xs:NCName"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="messages">
|
||||
<xs:complexType>
|
||||
<xs:choice>
|
||||
<xs:element ref="exception"/>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" ref="error"/>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" ref="notice"/>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="exception">
|
||||
<xs:complexType mixed="true">
|
||||
<xs:attribute name="type" use="required" type="xs:integer"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="error">
|
||||
<xs:complexType mixed="true">
|
||||
<xs:attribute name="type" use="required" type="xs:integer"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="notice">
|
||||
<xs:complexType mixed="true">
|
||||
<xs:attribute name="type" use="required" type="xs:integer"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="summary">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="status" use="required" type="xs:NCName"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
679
library/pom.xml
679
library/pom.xml
@@ -1,345 +1,364 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.mustangproject</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>2.12.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.mustangproject</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>2.9.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.mustangproject</groupId>
|
||||
<artifactId>library</artifactId>
|
||||
<version>2.9.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<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 Cross Industry Invoice based formats Factur-X/ZUGFeRD, XRechnung and Order-X in your invoice PDFs.
|
||||
<artifactId>library</artifactId>
|
||||
<version>2.12.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<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
|
||||
Cross Industry Invoice based formats Factur-X/ZUGFeRD, XRechnung and Order-X in your invoice PDFs.
|
||||
</description>
|
||||
<url>http://www.mustangproject.org/</url>
|
||||
<scm>
|
||||
<connection>scm:git:https://github.com/ZUGFeRD/mustangproject.git</connection>
|
||||
<developerConnection>scm:git:https://github.com/ZUGFeRD/mustangproject.git</developerConnection>
|
||||
<url>https://github.com/ZUGFeRD/mustangproject</url>
|
||||
<tag>core-2.3.2</tag>
|
||||
</scm>
|
||||
<repositories>
|
||||
<repository><!-- for jargs -->
|
||||
<id>sonatype-oss-public</id>
|
||||
<url>https://oss.sonatype.org/content/groups/public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>internal.repo</id>
|
||||
<name>Temporary Staging Repository</name>
|
||||
<url>file://${project.build.directory}/mvn-repo</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<github.global.server>github</github.global.server>
|
||||
<additionalparam>-Xdoclint:none</additionalparam>
|
||||
<!-- Skip error check for javadoc -->
|
||||
<maven.compiler.compilerVersion>8</maven.compiler.compilerVersion>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<maven.deploy.skip>true</maven.deploy.skip><!-- do deploy to maven central, parent project does not and inherits -->
|
||||
<url>http://www.mustangproject.org/</url>
|
||||
<scm>
|
||||
<connection>scm:git:https://github.com/ZUGFeRD/mustangproject.git</connection>
|
||||
<developerConnection>scm:git:https://github.com/ZUGFeRD/mustangproject.git</developerConnection>
|
||||
<url>https://github.com/ZUGFeRD/mustangproject</url>
|
||||
<tag>core-2.3.2</tag>
|
||||
</scm>
|
||||
<repositories>
|
||||
<repository><!-- for jargs -->
|
||||
<id>sonatype-oss-public</id>
|
||||
<url>https://oss.sonatype.org/content/groups/public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>internal.repo</id>
|
||||
<name>Temporary Staging Repository</name>
|
||||
<url>file://${project.build.directory}/mvn-repo</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<github.global.server>github</github.global.server>
|
||||
<additionalparam>-Xdoclint:none</additionalparam>
|
||||
<!-- Skip error check for javadoc -->
|
||||
<maven.compiler.compilerVersion>11</maven.compiler.compilerVersion>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.deploy.skip>true
|
||||
</maven.deploy.skip><!-- do deploy to maven central, parent project does not and inherits -->
|
||||
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- https://mvnrepository.com/artifact/net.sf.saxon/Saxon-HE -->
|
||||
<dependency>
|
||||
<groupId>net.sf.saxon</groupId>
|
||||
<artifactId>Saxon-HE</artifactId>
|
||||
<version>9.9.0-1</version>
|
||||
</dependency><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.14.2</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.xmlgraphics/fop -->
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlgraphics</groupId>
|
||||
<artifactId>fop</artifactId>
|
||||
<version>2.9</version>
|
||||
</dependency>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>2.0.9</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/net.sf.saxon/Saxon-HE -->
|
||||
<dependency>
|
||||
<groupId>net.sf.saxon</groupId>
|
||||
<artifactId>Saxon-HE</artifactId>
|
||||
<version>12.4</version>
|
||||
</dependency><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.17.1</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.xmlgraphics/fop -->
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlgraphics</groupId>
|
||||
<artifactId>fop</artifactId>
|
||||
<version>2.9</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>xml-apis</groupId>
|
||||
<artifactId>xml-apis</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>activation</artifactId>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
<version>4.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.angus</groupId>
|
||||
<artifactId>angus-activation</artifactId>
|
||||
<version>2.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>preflight</artifactId>
|
||||
<version>2.0.27</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>pdfbox</artifactId>
|
||||
<version>2.0.27</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dom4j</groupId>
|
||||
<artifactId>dom4j</artifactId>
|
||||
<version>2.1.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.9.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
<version>5.9.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- CII to UBL conversion -->
|
||||
<dependency>
|
||||
<groupId>com.helger</groupId>
|
||||
<artifactId>en16931-cii2ubl</artifactId>
|
||||
<version>1.4.10</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.glassfish.jaxb/jaxb-runtime -->
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
<version>2.3.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-core</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-assertj</artifactId>
|
||||
<version>2.9.1</version>
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>preflight</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>pdfbox</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dom4j</groupId>
|
||||
<artifactId>dom4j</artifactId>
|
||||
<version>2.1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.10.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- API -->
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
<version>2.3.3</version>
|
||||
</dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
<version>5.10.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<runOrder>alphabetical</runOrder>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<!-- http://stackoverflow.com/questions/574594/how-can-i-create-an-executable-jar-with-dependencies-using-maven
|
||||
<!-- CII to UBL conversion -->
|
||||
<dependency>
|
||||
<groupId>com.helger</groupId>
|
||||
<artifactId>en16931-cii2ubl</artifactId>
|
||||
<version>2.2.4</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.glassfish.jaxb/jaxb-runtime -->
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
<version>4.0.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-core</artifactId>
|
||||
<version>2.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-assertj</artifactId>
|
||||
<version>2.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>2.0.9</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<runOrder>alphabetical</runOrder>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<!-- http://stackoverflow.com/questions/574594/how-can-i-create-an-executable-jar-with-dependencies-using-maven
|
||||
mvn clean compile assembly:single -->
|
||||
<!-- or whatever version you use -->
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/logback.xml</exclude>
|
||||
</excludes>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
</manifest>
|
||||
<manifestSections>
|
||||
<manifestSection>
|
||||
<name>FreeSans.ttf</name>
|
||||
<manifestEntries>
|
||||
<Content-Type>font/ttf</Content-Type>
|
||||
</manifestEntries>
|
||||
</manifestSection>
|
||||
<manifestSection>
|
||||
<name>FreeSerif.ttf</name>
|
||||
<manifestEntries>
|
||||
<Content-Type>application/x-font</Content-Type>
|
||||
</manifestEntries>
|
||||
</manifestSection>
|
||||
<manifestSection>
|
||||
<name>Times-Bold.ttf</name>
|
||||
<manifestEntries>
|
||||
<Content-Type>application/x-font</Content-Type>
|
||||
</manifestEntries>
|
||||
</manifestSection>
|
||||
</manifestSections>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<configuration>
|
||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||
<minimizeJar>false</minimizeJar><!-- no longer java 11 compatible if set to true because it removes e.g. javax/xml/bind/annotation/XmlSchema-->
|
||||
<filters>
|
||||
<!-- or whatever version you use -->
|
||||
<source>11</source>
|
||||
<target>11</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/logback.xml</exclude>
|
||||
</excludes>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
</manifest>
|
||||
<manifestSections>
|
||||
<manifestSection>
|
||||
<name>FreeSans.ttf</name>
|
||||
<manifestEntries>
|
||||
<Content-Type>font/ttf</Content-Type>
|
||||
</manifestEntries>
|
||||
</manifestSection>
|
||||
<manifestSection>
|
||||
<name>FreeSerif.ttf</name>
|
||||
<manifestEntries>
|
||||
<Content-Type>application/x-font</Content-Type>
|
||||
</manifestEntries>
|
||||
</manifestSection>
|
||||
<manifestSection>
|
||||
<name>Times-Bold.ttf</name>
|
||||
<manifestEntries>
|
||||
<Content-Type>application/x-font</Content-Type>
|
||||
</manifestEntries>
|
||||
</manifestSection>
|
||||
</manifestSections>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<configuration>
|
||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||
<minimizeJar>false
|
||||
</minimizeJar><!-- no longer java 11 compatible if set to true because it removes e.g. javax/xml/bind/annotation/XmlSchema-->
|
||||
<filters>
|
||||
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>log4j:log4j</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>commons-logging:commons-logging</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<!--exclude>classworlds:classworlds</exclude> <exclude>junit:junit</exclude>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>log4j:log4j</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>commons-logging:commons-logging</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<!--exclude>classworlds:classworlds</exclude> <exclude>junit:junit</exclude>
|
||||
<exclude>jmock:*</exclude> <exclude>*:xml-apis</exclude> <exclude>org.apache.maven:lib:tests</exclude>
|
||||
<exclude>log4j:log4j:jar:</exclude -->
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>templating-maven-plugin</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>filtering-java-templates</id>
|
||||
<goals>
|
||||
<goal>filter-sources</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>templating-maven-plugin</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>filtering-java-templates</id>
|
||||
<goals>
|
||||
<goal>filter-sources</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
<profiles>
|
||||
<profile> <!-- enforce building binaries with Java 1.8 for Maven Central, otherwise using them e.g. as jar will throw a version exception-->
|
||||
<id>release-sign-artifacts</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>performRelease</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-toolchains-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>toolchain</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<toolchains>
|
||||
<jdk>
|
||||
<version>8</version>
|
||||
<vendor>adopt</vendor>
|
||||
</jdk>
|
||||
</toolchains>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<mailingLists>
|
||||
<mailingList>
|
||||
<name>User List</name>
|
||||
<archive>https://groups.google.com/forum/?hl=de#!forum/mustangproject</archive>
|
||||
</mailingList>
|
||||
</mailingLists>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
<comments>A business-friendly OSS license</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Jochen Stärk</name>
|
||||
<email>jstaerk@usegroup.de</email>
|
||||
<roles>
|
||||
<role>architect</role>
|
||||
<role>developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Alexander Schmidt</name>
|
||||
<email>schmidt.alexander@mail.de</email>
|
||||
<roles>
|
||||
<role>developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
</developers>
|
||||
<profiles>
|
||||
<profile> <!-- enforce building binaries with Java 1.8 for Maven Central, otherwise using them e.g. as jar will throw a version exception-->
|
||||
<id>release-sign-artifacts</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>performRelease</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-toolchains-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>toolchain</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<toolchains>
|
||||
<jdk>
|
||||
<version>11</version>
|
||||
<vendor>adopt</vendor>
|
||||
</jdk>
|
||||
</toolchains>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<mailingLists>
|
||||
<mailingList>
|
||||
<name>User List</name>
|
||||
<archive>https://groups.google.com/forum/?hl=de#!forum/mustangproject</archive>
|
||||
</mailingList>
|
||||
</mailingLists>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
<comments>A business-friendly OSS license</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Jochen Stärk</name>
|
||||
<email>jstaerk@usegroup.de</email>
|
||||
<roles>
|
||||
<role>architect</role>
|
||||
<role>developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Alexander Schmidt</name>
|
||||
<email>schmidt.alexander@mail.de</email>
|
||||
<roles>
|
||||
<role>developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
</developers>
|
||||
</project>
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package org.mustangproject;
|
||||
|
||||
import org.mustangproject.ZUGFeRD.IExportableTransaction;
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/***
|
||||
* (absolute) allowances on item and document level
|
||||
*/
|
||||
public class Allowance extends Charge implements IZUGFeRDAllowanceCharge {
|
||||
public class Allowance extends Charge {
|
||||
|
||||
/***
|
||||
* bean constructor
|
||||
|
||||
@@ -5,9 +5,7 @@ import java.io.Serializable;
|
||||
|
||||
import com.helger.commons.error.list.ErrorList;
|
||||
import com.helger.en16931.cii2ubl.CIIToUBL23Converter;
|
||||
import com.helger.ubl21.UBL21Writer;
|
||||
import com.helger.ubl22.UBL22Writer;
|
||||
import com.helger.ubl23.UBL23Writer;
|
||||
import com.helger.ubl23.UBL23Marshaller;
|
||||
|
||||
/***
|
||||
* converts a Cross Industry Invoice XML file to a UBL XML file
|
||||
@@ -23,39 +21,15 @@ public class CIIToUBL {
|
||||
final ErrorList occurred=new ErrorList();
|
||||
final CIIToUBL23Converter cc=new CIIToUBL23Converter();
|
||||
final Serializable aUBL = cc.convertCIItoUBL(input, occurred);
|
||||
if (aUBL instanceof oasis.names.specification.ubl.schema.xsd.invoice_21.InvoiceType)
|
||||
if (aUBL instanceof oasis.names.specification.ubl.schema.xsd.invoice_23.InvoiceType)
|
||||
{
|
||||
UBL21Writer.invoice ()
|
||||
.setFormattedOutput (true)
|
||||
.write ((oasis.names.specification.ubl.schema.xsd.invoice_21.InvoiceType) aUBL, output);
|
||||
}
|
||||
else if (aUBL instanceof oasis.names.specification.ubl.schema.xsd.creditnote_21.CreditNoteType)
|
||||
{
|
||||
UBL21Writer.creditNote ()
|
||||
.setFormattedOutput (true)
|
||||
.write ((oasis.names.specification.ubl.schema.xsd.creditnote_21.CreditNoteType) aUBL, output);
|
||||
}
|
||||
else if (aUBL instanceof oasis.names.specification.ubl.schema.xsd.invoice_22.InvoiceType)
|
||||
{
|
||||
UBL22Writer.invoice ()
|
||||
.setFormattedOutput (true)
|
||||
.write ((oasis.names.specification.ubl.schema.xsd.invoice_22.InvoiceType) aUBL, output);
|
||||
}
|
||||
else if (aUBL instanceof oasis.names.specification.ubl.schema.xsd.creditnote_22.CreditNoteType)
|
||||
{
|
||||
UBL22Writer.creditNote ()
|
||||
.setFormattedOutput (true)
|
||||
.write ((oasis.names.specification.ubl.schema.xsd.creditnote_22.CreditNoteType) aUBL, output);
|
||||
}
|
||||
else if (aUBL instanceof oasis.names.specification.ubl.schema.xsd.invoice_23.InvoiceType)
|
||||
{
|
||||
UBL23Writer.invoice ()
|
||||
UBL23Marshaller.invoice ()
|
||||
.setFormattedOutput (true)
|
||||
.write ((oasis.names.specification.ubl.schema.xsd.invoice_23.InvoiceType) aUBL, output);
|
||||
}
|
||||
else if (aUBL instanceof oasis.names.specification.ubl.schema.xsd.creditnote_23.CreditNoteType)
|
||||
{
|
||||
UBL23Writer.creditNote ()
|
||||
UBL23Marshaller.creditNote ()
|
||||
.setFormattedOutput (true)
|
||||
.write ((oasis.names.specification.ubl.schema.xsd.creditnote_23.CreditNoteType) aUBL, output);
|
||||
}
|
||||
|
||||
59
library/src/main/java/org/mustangproject/CashDiscount.java
Normal file
59
library/src/main/java/org/mustangproject/CashDiscount.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package org.mustangproject;
|
||||
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDCashDiscount;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/***
|
||||
* A class to represent discounts for early payments ("Skonto")
|
||||
*/
|
||||
public class CashDiscount implements IZUGFeRDCashDiscount {
|
||||
|
||||
/***
|
||||
* the reduction percent allowed in the period
|
||||
*/
|
||||
protected BigDecimal percent;
|
||||
/***
|
||||
* the period (usually days) count how long the percent apply
|
||||
*/
|
||||
protected Integer days=null;
|
||||
|
||||
/***
|
||||
* Create a cash discount (skonto) with the specified height in the specified period.
|
||||
* Should someone add more period types than just "days" there
|
||||
* is be space for a (optional) third parameter
|
||||
*
|
||||
* @param percent max 3 decimals "behind the dot", more precision is currently ignored
|
||||
* @param days the count of the periods (usually days) the percentage applies
|
||||
*/
|
||||
public CashDiscount(BigDecimal percent, int days) {
|
||||
this.percent = percent;
|
||||
this.days = days;
|
||||
}
|
||||
|
||||
/***
|
||||
* @return this particular cash discount as cross industry invoice XML
|
||||
*/
|
||||
public String getAsCII() {
|
||||
return "<ram:SpecifiedTradePaymentTerms>"+
|
||||
"<ram:Description>Cash Discount</ram:Description>"+
|
||||
" <ram:ApplicableTradePaymentDiscountTerms>"+
|
||||
" <ram:BasisPeriodMeasure unitCode=\"DAY\">"+days+"</ram:BasisPeriodMeasure>"+
|
||||
" <ram:CalculationPercent>"+XMLTools.nDigitFormat(percent,3)+"</ram:CalculationPercent>"+
|
||||
" </ram:ApplicableTradePaymentDiscountTerms>"+
|
||||
"</ram:SpecifiedTradePaymentTerms>";
|
||||
}
|
||||
|
||||
/***
|
||||
* since EN16931 voted not to have (or even allow) cash discounts in their core invoice the german
|
||||
* XRechnung CIUS defined it's own proprietary format for a freetext field
|
||||
* @return this particular cash discount in proprietary xrechnung format
|
||||
*/
|
||||
public String getAsXRechnung() {
|
||||
return "#SKONTO#TAGE="+days+"#PROZENT="+XMLTools.nDigitFormat(percent,2)+"#\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
package org.mustangproject;
|
||||
|
||||
import org.mustangproject.ZUGFeRD.IAbsoluteValueProvider;
|
||||
import org.mustangproject.ZUGFeRD.IExportableTransaction;
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
|
||||
@@ -111,10 +111,10 @@ public class Contact implements IZUGFeRDExportableContact {
|
||||
Node currentItemNode = nodes.item(nodeIndex);
|
||||
if (currentItemNode.getLocalName() != null) {
|
||||
|
||||
if (currentItemNode.getLocalName().equals("PersonName")) {
|
||||
if (currentItemNode.getLocalName().equals("PersonName")/*CII*/||currentItemNode.getLocalName().equals("Name")/*UBL*/) {
|
||||
setName(currentItemNode.getFirstChild().getNodeValue());
|
||||
}
|
||||
if (currentItemNode.getLocalName().equals("TelephoneUniversalCommunication")) {
|
||||
if (currentItemNode.getLocalName().equals("TelephoneUniversalCommunication")) { /*CII*/
|
||||
NodeList tel = currentItemNode.getChildNodes();
|
||||
for (int telChildIndex = 0; telChildIndex < tel.getLength(); telChildIndex++) {
|
||||
if (tel.item(telChildIndex).getLocalName() != null) {
|
||||
@@ -123,8 +123,10 @@ public class Contact implements IZUGFeRDExportableContact {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (currentItemNode.getLocalName().equals("Telephone")) { /* UBL */
|
||||
setPhone(currentItemNode.getTextContent());
|
||||
}
|
||||
if (currentItemNode.getLocalName().equals("EmailURIUniversalCommunication")) {
|
||||
if (currentItemNode.getLocalName().equals("EmailURIUniversalCommunication")) { /* CII */
|
||||
NodeList email = currentItemNode.getChildNodes();
|
||||
for (int emailChildIndex = 0; emailChildIndex < email.getLength(); emailChildIndex++) {
|
||||
if (email.item(emailChildIndex).getLocalName() != null) {
|
||||
@@ -133,6 +135,8 @@ public class Contact implements IZUGFeRDExportableContact {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (currentItemNode.getLocalName().equals("ElectronicMail")) { /* UBL */
|
||||
setEMail(currentItemNode.getTextContent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,7 @@ import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.mustangproject.ZUGFeRD.IExportableTransaction;
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem;
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableTradeParty;
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDPaymentTerms;
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDTradeSettlement;
|
||||
import org.mustangproject.ZUGFeRD.*;
|
||||
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
@@ -47,20 +42,21 @@ 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 Date issueDate = null, dueDate = null, deliveryDate = null;
|
||||
protected TradeParty sender = null, recipient = null, deliveryAddress = null;
|
||||
@JsonDeserialize(contentAs=Item.class)
|
||||
protected ArrayList<CashDiscount> cashDiscounts = null;
|
||||
@JsonDeserialize(contentAs = Item.class)
|
||||
protected ArrayList<IZUGFeRDExportableItem> ZFItems = null;
|
||||
protected ArrayList<String> notes = null;
|
||||
private List<IncludedNote> includedNotes = null;
|
||||
protected String sellerOrderReferencedDocumentID;
|
||||
private List<IncludedNote> includedNotes = null;
|
||||
protected String sellerOrderReferencedDocumentID;
|
||||
protected String contractReferencedDocument = null;
|
||||
protected ArrayList<FileAttachment> xmlEmbeddedFiles=null;
|
||||
protected ArrayList<FileAttachment> xmlEmbeddedFiles = null;
|
||||
|
||||
protected BigDecimal totalPrepaidAmount = null;
|
||||
protected Date detailedDeliveryDateStart = null;
|
||||
protected Date detailedDeliveryPeriodEnd = null;
|
||||
|
||||
protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<>(),
|
||||
Charges = new ArrayList<>(), LogisticsServiceCharges = new ArrayList<>();
|
||||
Charges = new ArrayList<>(), LogisticsServiceCharges = new ArrayList<>();
|
||||
protected IZUGFeRDPaymentTerms paymentTerms = null;
|
||||
protected Date invoiceReferencedIssueDate;
|
||||
protected String specifiedProcuringProjectID = null;
|
||||
@@ -70,6 +66,7 @@ public class Invoice implements IExportableTransaction {
|
||||
|
||||
public Invoice() {
|
||||
ZFItems = new ArrayList<>();
|
||||
cashDiscounts = new ArrayList<>();
|
||||
setCurrency("EUR");
|
||||
}
|
||||
|
||||
@@ -79,7 +76,7 @@ public class Invoice implements IExportableTransaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContractReferencedDocument() {
|
||||
public String getContractReferencedDocument() {
|
||||
return contractReferencedDocument;
|
||||
}
|
||||
|
||||
@@ -100,14 +97,14 @@ public class Invoice implements IExportableTransaction {
|
||||
|
||||
public Invoice embedFileInXML(FileAttachment fa) {
|
||||
if (xmlEmbeddedFiles == null) {
|
||||
xmlEmbeddedFiles= new ArrayList<>();
|
||||
xmlEmbeddedFiles = new ArrayList<>();
|
||||
}
|
||||
xmlEmbeddedFiles.add(fa);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileAttachment[] getAdditionalReferencedDocuments() {
|
||||
public FileAttachment[] getAdditionalReferencedDocuments() {
|
||||
if (xmlEmbeddedFiles == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -115,6 +112,10 @@ public class Invoice implements IExportableTransaction {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IZUGFeRDCashDiscount[] getCashDiscounts() {
|
||||
return cashDiscounts.toArray(new IZUGFeRDCashDiscount[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNumber() {
|
||||
@@ -139,6 +140,7 @@ public class Invoice implements IExportableTransaction {
|
||||
documentCode = DocumentCodeTypeConstants.CORRECTEDINVOICE;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Invoice setCreditNote() {
|
||||
documentCode = DocumentCodeTypeConstants.CREDITNOTE;
|
||||
return this;
|
||||
@@ -229,16 +231,18 @@ public class Invoice implements IExportableTransaction {
|
||||
public String getBuyerOrderReferencedDocumentID() {
|
||||
return buyerOrderReferencedDocumentID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSellerOrderReferencedDocumentID() {
|
||||
return sellerOrderReferencedDocumentID;
|
||||
}
|
||||
|
||||
|
||||
public Invoice setSellerOrderReferencedDocumentID(String sellerOrderReferencedDocumentID) {
|
||||
this.sellerOrderReferencedDocumentID = sellerOrderReferencedDocumentID;
|
||||
return this;
|
||||
}
|
||||
public Invoice setSellerOrderReferencedDocumentID(String sellerOrderReferencedDocumentID) {
|
||||
this.sellerOrderReferencedDocumentID = sellerOrderReferencedDocumentID;
|
||||
return this;
|
||||
}
|
||||
|
||||
/***
|
||||
* usually the order number
|
||||
* @param buyerOrderReferencedDocumentID string with number
|
||||
@@ -258,22 +262,23 @@ public class Invoice implements IExportableTransaction {
|
||||
this.invoiceReferencedDocumentID = invoiceReferencedDocumentID;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInvoiceReferencedDocumentID() {
|
||||
return invoiceReferencedDocumentID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getInvoiceReferencedIssueDate() {
|
||||
return invoiceReferencedIssueDate;
|
||||
}
|
||||
@Override
|
||||
public Date getInvoiceReferencedIssueDate() {
|
||||
return invoiceReferencedIssueDate;
|
||||
}
|
||||
|
||||
public Invoice setInvoiceReferencedIssueDate(Date issueDate) {
|
||||
this.invoiceReferencedIssueDate = issueDate;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Invoice setInvoiceReferencedIssueDate(Date issueDate) {
|
||||
this.invoiceReferencedIssueDate = issueDate;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBuyerOrderReferencedDocumentIssueDateTime() {
|
||||
return buyerOrderReferencedDocumentIssueDateTime;
|
||||
}
|
||||
@@ -285,7 +290,7 @@ public class Invoice implements IExportableTransaction {
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice setTotalPrepaidAmount(BigDecimal prepaid) {
|
||||
totalPrepaidAmount=prepaid;
|
||||
totalPrepaidAmount = prepaid;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -380,13 +385,13 @@ public class Invoice implements IExportableTransaction {
|
||||
|
||||
|
||||
@Override
|
||||
public String getOwnLocation() {
|
||||
public String getOwnLocation() {
|
||||
return sender.getLocation();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getOwnCountry() {
|
||||
public String getOwnCountry() {
|
||||
return sender.getCountry();
|
||||
}
|
||||
|
||||
@@ -399,12 +404,12 @@ public class Invoice implements IExportableTransaction {
|
||||
return notes.toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IncludedNote> getNotesWithSubjectCode() {
|
||||
return includedNotes;
|
||||
}
|
||||
@Override
|
||||
public List<IncludedNote> getNotesWithSubjectCode() {
|
||||
return includedNotes;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
@@ -455,7 +460,7 @@ public class Invoice implements IExportableTransaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IZUGFeRDExportableTradeParty getSender() {
|
||||
public TradeParty getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
@@ -473,13 +478,14 @@ public class Invoice implements IExportableTransaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IZUGFeRDExportableTradeParty getRecipient() {
|
||||
public TradeParty getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
/**
|
||||
* required.
|
||||
* sets the invoice receiving institution = invoicee
|
||||
*
|
||||
* @param recipient the invoicee organisation
|
||||
* @return fluent setter
|
||||
*/
|
||||
@@ -491,6 +497,7 @@ public class Invoice implements IExportableTransaction {
|
||||
/**
|
||||
* required.
|
||||
* sets the invoicing institution = invoicer
|
||||
*
|
||||
* @param sender the invoicer
|
||||
* @return fluent setter
|
||||
*/
|
||||
@@ -508,8 +515,8 @@ public class Invoice implements IExportableTransaction {
|
||||
if (Allowances.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return Allowances.toArray(new IZUGFeRDAllowanceCharge[0]);
|
||||
}
|
||||
return Allowances.toArray(new IZUGFeRDAllowanceCharge[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -518,8 +525,8 @@ public class Invoice implements IExportableTransaction {
|
||||
if (Charges.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return Charges.toArray(new IZUGFeRDAllowanceCharge[0]);
|
||||
}
|
||||
return Charges.toArray(new IZUGFeRDAllowanceCharge[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -528,8 +535,8 @@ public class Invoice implements IExportableTransaction {
|
||||
if (LogisticsServiceCharges.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return LogisticsServiceCharges.toArray(new IZUGFeRDAllowanceCharge[0]);
|
||||
}
|
||||
return LogisticsServiceCharges.toArray(new IZUGFeRDAllowanceCharge[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -540,7 +547,7 @@ public class Invoice implements IExportableTransaction {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ((TradeParty) getSender()).getAsTradeSettlement();
|
||||
return getSender().getAsTradeSettlement();
|
||||
|
||||
}
|
||||
|
||||
@@ -569,22 +576,33 @@ public class Invoice implements IExportableTransaction {
|
||||
this.deliveryAddress = deliveryAddress;
|
||||
return this;
|
||||
}
|
||||
/***
|
||||
* Adds a cash discount (skonto)
|
||||
* @param c the CashDiscount percent/period combination
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addCashDiscount(CashDiscount c) {
|
||||
this.cashDiscounts.add(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IZUGFeRDExportableItem[] getZFItems() {
|
||||
return ZFItems.toArray(new IZUGFeRDExportableItem[0]);
|
||||
}
|
||||
|
||||
public void setZFItems(ArrayList<IZUGFeRDExportableItem> ims) {
|
||||
ZFItems=ims;
|
||||
public void setZFItems(ArrayList<IZUGFeRDExportableItem> ims) {
|
||||
ZFItems = ims;
|
||||
}
|
||||
|
||||
/**
|
||||
* required
|
||||
* adds invoice "lines" :-)
|
||||
* @see Item
|
||||
*
|
||||
* @param item the invoice line
|
||||
* @return fluent setter
|
||||
* @see Item
|
||||
*/
|
||||
public Invoice addItem(IZUGFeRDExportableItem item) {
|
||||
ZFItems.add(item);
|
||||
@@ -669,6 +687,7 @@ public class Invoice implements IExportableTransaction {
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element
|
||||
*
|
||||
* @param text freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
@@ -679,129 +698,138 @@ public class Invoice implements IExportableTransaction {
|
||||
notes.add(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Invoice addNotes(Collection<IncludedNote> notes) {
|
||||
if (notes == null) {
|
||||
return this;
|
||||
}
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.addAll(notes);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#AAI}
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addGeneralNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.generalNote(content));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#REG}
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addRegulatoryNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.regulatoryNote(content));
|
||||
return this;
|
||||
}
|
||||
public Invoice addNotes(Collection<IncludedNote> notes) {
|
||||
if (notes == null) {
|
||||
return this;
|
||||
}
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.addAll(notes);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#ABL}
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addLegalNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.legalNote(content));
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#AAI}
|
||||
*
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addGeneralNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.generalNote(content));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#CUS}
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addCustomsNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.customsNote(content));
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#REG}
|
||||
*
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addRegulatoryNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.regulatoryNote(content));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#SUR}
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addSellerNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.sellerNote(content));
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#ABL}
|
||||
*
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addLegalNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.legalNote(content));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#CUS}
|
||||
*
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addCustomsNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.customsNote(content));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#SUR}
|
||||
*
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addSellerNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.sellerNote(content));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#TXD}
|
||||
*
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addTaxNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.taxNote(content));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#ACY}
|
||||
*
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addIntroductionNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.introductionNote(content));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#AAK}
|
||||
*
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addDiscountBonusNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.discountBonusNote(content));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#TXD}
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addTaxNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.taxNote(content));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#ACY}
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addIntroductionNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.introductionNote(content));
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* adds a free text paragraph, which will become an includedNote element with explicit
|
||||
* subjectCode {@link SubjectCode#AAK}
|
||||
* @param content freeform UTF8 plain text
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice addDiscountBonusNote(String content) {
|
||||
if (includedNotes == null) {
|
||||
includedNotes = new ArrayList<>();
|
||||
}
|
||||
includedNotes.add(IncludedNote.discountBonusNote(content));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSpecifiedProcuringProjectID() {
|
||||
return specifiedProcuringProjectID;
|
||||
@@ -841,6 +869,7 @@ public class Invoice implements IExportableTransaction {
|
||||
|
||||
/**
|
||||
* Decide when the VAT should be collected.
|
||||
*
|
||||
* @param vatDueDateTypeCode use EventTimeCodeTypeConstants
|
||||
* @return fluent setter
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.mustangproject;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import org.apache.fop.util.XMLUtil;
|
||||
import org.mustangproject.ZUGFeRD.IReferencedDocument;
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem;
|
||||
@@ -12,7 +11,6 @@ import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/***
|
||||
* describes any invoice line
|
||||
@@ -28,8 +26,8 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
protected Product product;
|
||||
protected ArrayList<String> notes = null;
|
||||
protected ArrayList<ReferencedDocument> referencedDocuments = null;
|
||||
protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<IZUGFeRDAllowanceCharge>(),
|
||||
Charges = new ArrayList<IZUGFeRDAllowanceCharge>();
|
||||
protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<>(),
|
||||
Charges = new ArrayList<>();
|
||||
|
||||
/***
|
||||
* default constructor
|
||||
@@ -62,6 +60,7 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
String vatPercent = null;
|
||||
String lineTotal = "0";
|
||||
String unitCode = "0";
|
||||
String referencedLineID = null;
|
||||
|
||||
ArrayList<ReferencedDocument> rdocs = null;
|
||||
|
||||
@@ -138,12 +137,22 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
ReferencedDocument rd = new ReferencedDocument(IssuerAssignedID, TypeCode,
|
||||
ReferenceTypeCode);
|
||||
if (rdocs == null) {
|
||||
rdocs = new ArrayList<ReferencedDocument>();
|
||||
rdocs = new ArrayList<>();
|
||||
}
|
||||
rdocs.add(rd);
|
||||
|
||||
}
|
||||
|
||||
if ((tradeLineChilds.item(tradeLineChildIndex).getLocalName() != null) && tradeLineChilds.item(tradeLineChildIndex).getLocalName().equals("BuyerOrderReferencedDocument")) {
|
||||
NodeList docChilds = tradeLineChilds.item(tradeLineChildIndex).getChildNodes();
|
||||
for (int docIndex = 0; docIndex < docChilds.getLength(); docIndex++) {
|
||||
String localName = docChilds.item(docIndex).getLocalName();
|
||||
if ((localName != null) && (localName.equals("LineID"))) {
|
||||
referencedLineID = docChilds.item(docIndex).getTextContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((tradeLineChilds.item(tradeLineChildIndex).getLocalName() != null) && tradeLineChilds
|
||||
.item(tradeLineChildIndex).getLocalName().equals("NetPriceProductTradePrice")) {
|
||||
NodeList netChilds = tradeLineChilds.item(tradeLineChildIndex).getChildNodes();
|
||||
@@ -265,6 +274,7 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
addReferencedDocument(rdoc);
|
||||
}
|
||||
}
|
||||
addReferencedLineID( referencedLineID );
|
||||
}
|
||||
|
||||
|
||||
@@ -428,7 +438,7 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
*/
|
||||
public Item addNote(String text) {
|
||||
if (notes == null) {
|
||||
notes = new ArrayList<String>();
|
||||
notes = new ArrayList<>();
|
||||
}
|
||||
notes.add(text);
|
||||
return this;
|
||||
@@ -441,7 +451,7 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
*/
|
||||
public Item addReferencedDocument(ReferencedDocument doc) {
|
||||
if (referencedDocuments == null) {
|
||||
referencedDocuments = new ArrayList<ReferencedDocument>();
|
||||
referencedDocuments = new ArrayList<>();
|
||||
}
|
||||
referencedDocuments.add(doc);
|
||||
return this;
|
||||
|
||||
@@ -2,13 +2,6 @@ package org.mustangproject;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import org.mustangproject.ZUGFeRD.*;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/***
|
||||
* A organisation, i.e. usually a company
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableProduct;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
|
||||
/***
|
||||
* describes a product, good or service used in an invoice item line
|
||||
@@ -15,6 +16,8 @@ public class Product implements IZUGFeRDExportableProduct {
|
||||
protected boolean isReverseCharge = false;
|
||||
protected boolean isIntraCommunitySupply = false;
|
||||
protected SchemedID globalId = null;
|
||||
protected String countryOfOrigin = null;
|
||||
protected HashMap<String, String> attributes = null;
|
||||
|
||||
/***
|
||||
* default constructor
|
||||
@@ -63,6 +66,7 @@ public class Product implements IZUGFeRDExportableProduct {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getSellerAssignedID() {
|
||||
return sellerAssignedID;
|
||||
}
|
||||
@@ -77,6 +81,7 @@ public class Product implements IZUGFeRDExportableProduct {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBuyerAssignedID() {
|
||||
return buyerAssignedID;
|
||||
}
|
||||
@@ -183,4 +188,32 @@ public class Product implements IZUGFeRDExportableProduct {
|
||||
this.VATPercent = VATPercent;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCountryOfOrigin() {
|
||||
return this.countryOfOrigin;
|
||||
}
|
||||
|
||||
public Product setCountryOfOrigin(String countryOfOrigin) {
|
||||
this.countryOfOrigin = countryOfOrigin;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<String, String> getAttributes() {
|
||||
return this.attributes;
|
||||
}
|
||||
|
||||
public Product setAttributes(HashMap<String, String> attributes) {
|
||||
this.attributes = attributes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Product addAttribute(String name, String value ) {
|
||||
if ( this.attributes == null ) {
|
||||
this.attributes = new HashMap<>();
|
||||
}
|
||||
this.attributes.put(name, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,154 +65,159 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
|
||||
for (int nodeIndex = 0; nodeIndex < nodes.getLength(); nodeIndex++) {
|
||||
//nodes.item(i).getTextContent())) {
|
||||
Node currentItemNode = nodes.item(nodeIndex);
|
||||
NodeList itemChilds = currentItemNode.getChildNodes();
|
||||
for (int itemChildIndex = 0; itemChildIndex < itemChilds.getLength(); itemChildIndex++) {
|
||||
if (itemChilds.item(itemChildIndex).getLocalName() != null) {
|
||||
|
||||
if (itemChilds.item(itemChildIndex).getLocalName().equals("Party")) {
|
||||
if (currentItemNode.getLocalName() != null) {
|
||||
String debcurrentChild = currentItemNode.getLocalName();
|
||||
if (debcurrentChild.equals("Party")) {
|
||||
|
||||
NodeList party = itemChilds.item(itemChildIndex).getChildNodes();
|
||||
for (int partyIndex = 0; partyIndex < party.getLength(); partyIndex++) {
|
||||
if (party.item(partyIndex).getLocalName() != null) {
|
||||
NodeList party = currentItemNode.getChildNodes();
|
||||
for (int partyIndex = 0; partyIndex < party.getLength(); partyIndex++) {
|
||||
if (party.item(partyIndex).getLocalName() != null) {
|
||||
String debCN = party.item(partyIndex).getLocalName();
|
||||
if (debCN.equals("PartyName")) {
|
||||
|
||||
if (party.item(partyIndex).getLocalName().equals("PartyName")) {
|
||||
|
||||
NodeList partyName = party.item(partyIndex).getChildNodes();
|
||||
for (int partyNameIndex = 0; partyNameIndex < partyName.getLength(); partyNameIndex++) {
|
||||
if (partyName.item(partyNameIndex).getLocalName() != null) {
|
||||
|
||||
if (partyName.item(partyNameIndex).getLocalName().equals("Name")) {
|
||||
setName(partyName.item(partyNameIndex).getTextContent());
|
||||
}
|
||||
NodeList partyName = party.item(partyIndex).getChildNodes();
|
||||
for (int partyNameIndex = 0; partyNameIndex < partyName.getLength(); partyNameIndex++) {
|
||||
if (partyName.item(partyNameIndex).getLocalName() != null) {
|
||||
|
||||
if (partyName.item(partyNameIndex).getLocalName().equals("Name")) {
|
||||
setName(partyName.item(partyNameIndex).getTextContent());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (party.item(partyIndex).getLocalName().equals("PostalAddress")) {
|
||||
}
|
||||
if (debCN.equals("PostalAddress")) {
|
||||
|
||||
NodeList postal = party.item(partyIndex).getChildNodes();
|
||||
for (int postalChildIndex = 0; postalChildIndex < postal.getLength(); postalChildIndex++) {
|
||||
if (postal.item(postalChildIndex).getLocalName() != null) {
|
||||
NodeList postal = party.item(partyIndex).getChildNodes();
|
||||
for (int postalChildIndex = 0; postalChildIndex < postal.getLength(); postalChildIndex++) {
|
||||
if (postal.item(postalChildIndex).getLocalName() != null) {
|
||||
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("StreetName")) {
|
||||
setStreet(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("AdditionalStreetName")) {
|
||||
setAdditionalAddress(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
//unknow correspondence if (postal.item(postalChildIndex).getLocalName().equals("LineThree")) {
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("StreetName")) {
|
||||
setStreet(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("AdditionalStreetName")) {
|
||||
setAdditionalAddress(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
//unknow correspondence if (postal.item(postalChildIndex).getLocalName().equals("LineThree")) {
|
||||
|
||||
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("CityName")) {
|
||||
setLocation(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("PostalZone")) {
|
||||
setZIP(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("Country")) {
|
||||
NodeList country = postal.item(postalChildIndex).getChildNodes();
|
||||
for (int countryIndex = 0; countryIndex < country.getLength(); countryIndex++) {
|
||||
if (country.item(countryIndex).getLocalName() != null) {
|
||||
|
||||
if (country.item(countryIndex).getLocalName().equals("IdentificationCode")) {
|
||||
setCountry(country.item(countryIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("CityName")) {
|
||||
setLocation(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("PostalZone")) {
|
||||
setZIP(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("Country")) {
|
||||
NodeList country = postal.item(postalChildIndex).getChildNodes();
|
||||
for (int countryIndex = 0; countryIndex < country.getLength(); countryIndex++) {
|
||||
if (country.item(countryIndex).getLocalName() != null) {
|
||||
|
||||
if (country.item(countryIndex).getLocalName().equals("IdentificationCode")) {
|
||||
setCountry(country.item(countryIndex).getTextContent());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("AddressLine")) {
|
||||
NodeList AddressLine = postal.item(postalChildIndex).getChildNodes();
|
||||
for (int lineIndex = 0; lineIndex < AddressLine.getLength(); lineIndex++) {
|
||||
if (AddressLine.item(lineIndex).getLocalName() != null) {
|
||||
|
||||
if (AddressLine.item(lineIndex).getLocalName().equals("Line")) {
|
||||
setAdditionalAddressExtension(AddressLine.item(lineIndex).getTextContent());
|
||||
}
|
||||
}
|
||||
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("AddressLine")) {
|
||||
NodeList AddressLine = postal.item(postalChildIndex).getChildNodes();
|
||||
for (int lineIndex = 0; lineIndex < AddressLine.getLength(); lineIndex++) {
|
||||
if (AddressLine.item(lineIndex).getLocalName() != null) {
|
||||
|
||||
if (AddressLine.item(lineIndex).getLocalName().equals("Line")) {
|
||||
setAdditionalAddressExtension(AddressLine.item(lineIndex).getTextContent());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("Name")) {
|
||||
setName(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("Name")) {
|
||||
setName(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (itemChilds.item(itemChildIndex).getLocalName().equals("GlobalID")) {
|
||||
if (itemChilds.item(itemChildIndex).getAttributes().getNamedItem("schemeID") != null) {
|
||||
SchemedID gid = new SchemedID().setScheme(itemChilds.item(itemChildIndex).getAttributes().getNamedItem("schemeID").getNodeValue()).setId(itemChilds.item(itemChildIndex).getTextContent());
|
||||
addGlobalID(gid);
|
||||
}
|
||||
|
||||
}
|
||||
if (itemChilds.item(itemChildIndex).getLocalName().equals("DefinedTradeContact")) {
|
||||
NodeList contact = itemChilds.item(itemChildIndex).getChildNodes();
|
||||
setContact(new Contact(contact));
|
||||
}
|
||||
|
||||
if (itemChilds.item(itemChildIndex).getLocalName().equals("PostalTradeAddress")) {
|
||||
NodeList postal = itemChilds.item(itemChildIndex).getChildNodes();
|
||||
for (int postalChildIndex = 0; postalChildIndex < postal.getLength(); postalChildIndex++) {
|
||||
if (postal.item(postalChildIndex).getLocalName() != null) {
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("LineOne")) {
|
||||
setStreet(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("LineTwo")) {
|
||||
setAdditionalAddress(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("LineThree")) {
|
||||
setAdditionalAddressExtension(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("CityName")) {
|
||||
setLocation(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("PostcodeCode")) {
|
||||
setZIP(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("CountryID")) {
|
||||
setCountry(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (debCN.equals("Contact")) {
|
||||
NodeList contact = party.item(partyIndex).getChildNodes();
|
||||
setContact(new Contact(contact));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (itemChilds.item(itemChildIndex).getLocalName().equals("SpecifiedTaxRegistration")) {
|
||||
NodeList taxChilds = itemChilds.item(itemChildIndex).getChildNodes();
|
||||
for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) {
|
||||
if (taxChilds.item(taxChildIndex).getLocalName() != null) {
|
||||
if ((taxChilds.item(taxChildIndex).getLocalName().equals("ID"))) {
|
||||
if (taxChilds.item(taxChildIndex).getAttributes().getNamedItem("schemeID") != null) {
|
||||
Node firstChild = taxChilds.item(taxChildIndex).getFirstChild();
|
||||
if (firstChild != null) {
|
||||
if (taxChilds.item(taxChildIndex).getAttributes()
|
||||
.getNamedItem("schemeID").getNodeValue().equals("VA")) {
|
||||
setVATID(firstChild.getNodeValue());
|
||||
}
|
||||
if (taxChilds.item(taxChildIndex).getAttributes()
|
||||
.getNamedItem("schemeID").getNodeValue().equals("FC")) {
|
||||
setTaxID(firstChild.getNodeValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (debcurrentChild.equals("GlobalID")) {
|
||||
if (nodes.item(nodeIndex).getAttributes().getNamedItem("schemeID") != null) {
|
||||
SchemedID gid = new SchemedID().setScheme(nodes.item(nodeIndex).getAttributes().getNamedItem("schemeID").getNodeValue()).setId(nodes.item(nodeIndex).getTextContent());
|
||||
addGlobalID(gid);
|
||||
}
|
||||
|
||||
}
|
||||
if (debcurrentChild.equals("DefinedTradeContact")) {
|
||||
NodeList contact = nodes.item(nodeIndex).getChildNodes();
|
||||
setContact(new Contact(contact));
|
||||
}
|
||||
|
||||
if (debcurrentChild.equals("PostalTradeAddress")) {
|
||||
NodeList postal = nodes.item(nodeIndex).getChildNodes();
|
||||
for (int postalChildIndex = 0; postalChildIndex < postal.getLength(); postalChildIndex++) {
|
||||
if (postal.item(postalChildIndex).getLocalName() != null) {
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("LineOne")) {
|
||||
setStreet(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("LineTwo")) {
|
||||
setAdditionalAddress(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("LineThree")) {
|
||||
setAdditionalAddressExtension(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("CityName")) {
|
||||
setLocation(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("PostcodeCode")) {
|
||||
setZIP(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("CountryID")) {
|
||||
setCountry(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (debcurrentChild.equals("SpecifiedTaxRegistration")) {
|
||||
NodeList taxChilds = nodes.item(nodeIndex).getChildNodes();
|
||||
for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) {
|
||||
if (taxChilds.item(taxChildIndex).getLocalName() != null) {
|
||||
if ((taxChilds.item(taxChildIndex).getLocalName().equals("ID"))) {
|
||||
if (taxChilds.item(taxChildIndex).getAttributes().getNamedItem("schemeID") != null) {
|
||||
Node firstChild = taxChilds.item(taxChildIndex).getFirstChild();
|
||||
if (firstChild != null) {
|
||||
if (taxChilds.item(taxChildIndex).getAttributes()
|
||||
.getNamedItem("schemeID").getNodeValue().equals("VA")) {
|
||||
setVATID(firstChild.getNodeValue());
|
||||
}
|
||||
if (taxChilds.item(taxChildIndex).getAttributes()
|
||||
.getNamedItem("schemeID").getNodeValue().equals("FC")) {
|
||||
setTaxID(firstChild.getNodeValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,15 +289,16 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
|
||||
|
||||
for (int nodeIndex = 0; nodeIndex < nodes.getLength(); nodeIndex++) {
|
||||
//nodes.item(i).getTextContent())) {
|
||||
String debLN = nodes.item(nodeIndex).getLocalName();
|
||||
if (debLN.equals("Party")) {
|
||||
// take one step back and parse from top
|
||||
parseFromUBL(nodes);
|
||||
return;
|
||||
}
|
||||
Node currentItemNode = nodes.item(nodeIndex);
|
||||
NodeList itemChilds = currentItemNode.getChildNodes();
|
||||
for (int itemChildIndex = 0; itemChildIndex < itemChilds.getLength(); itemChildIndex++) {
|
||||
if (itemChilds.item(itemChildIndex).getLocalName() != null) {
|
||||
|
||||
if (itemChilds.item(itemChildIndex).getLocalName().equals("Party")) {
|
||||
parseFromUBL(nodes);
|
||||
return;
|
||||
}
|
||||
if (itemChilds.item(itemChildIndex).getLocalName().equals("Name")) {
|
||||
setName(itemChilds.item(itemChildIndex).getTextContent());
|
||||
}
|
||||
@@ -328,10 +334,8 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
|
||||
if (postal.item(postalChildIndex).getLocalName().equals("CountryID")) {
|
||||
setCountry(postal.item(postalChildIndex).getTextContent());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (itemChilds.item(itemChildIndex).getLocalName().equals("URIUniversalCommunication")) {
|
||||
NodeList URIchilds = itemChilds.item(itemChildIndex).getChildNodes();
|
||||
@@ -419,8 +423,9 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
|
||||
|
||||
|
||||
/***
|
||||
* sets the email of the organization (not the one of the contact person)
|
||||
* (while setEmail has to be defined here getEmail comes from IZUGFeRDExportableTradeParty)
|
||||
* sets the email of the organization (not the one of the contact person)
|
||||
* (while setEmail has to be defined here getEmail comes from IZUGFeRDExportableTradeParty)
|
||||
* @param eMail address of institution (not contact)
|
||||
* @return fluent setter
|
||||
*/
|
||||
public TradeParty setEmail(String eMail) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.mustangproject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.AbstractList;
|
||||
@@ -8,39 +9,47 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.RandomAccess;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
public class XMLTools extends XMLWriter {
|
||||
@Override
|
||||
public String escapeAttributeEntities(String s) {
|
||||
public String escapeAttributeEntities(String s) {
|
||||
return super.escapeAttributeEntities(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeElementEntities(String s) {
|
||||
public String escapeElementEntities(String s) {
|
||||
return super.escapeElementEntities(s);
|
||||
|
||||
}
|
||||
|
||||
public static List<Node> asList(NodeList n) {
|
||||
return n.getLength()==0?
|
||||
Collections.<Node>emptyList(): new NodeListWrapper(n);
|
||||
return n.getLength() == 0 ?
|
||||
Collections.<Node>emptyList() : new NodeListWrapper(n);
|
||||
}
|
||||
|
||||
static final class NodeListWrapper extends AbstractList<Node>
|
||||
implements RandomAccess {
|
||||
private final NodeList list;
|
||||
|
||||
NodeListWrapper(NodeList l) {
|
||||
list=l;
|
||||
list = l;
|
||||
}
|
||||
public Node get(int index) {
|
||||
|
||||
@Override
|
||||
public Node get(int index) {
|
||||
return list.item(index);
|
||||
}
|
||||
public int size() {
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return list.getLength();
|
||||
}
|
||||
}
|
||||
|
||||
public static String nDigitFormat(BigDecimal value, int scale) {
|
||||
/*
|
||||
* I needed 123,45, locale independent.I tried
|
||||
@@ -63,9 +72,9 @@ public class XMLTools extends XMLWriter {
|
||||
|
||||
|
||||
public static String encodeXML(CharSequence s) {
|
||||
if (s == null) {
|
||||
return "";
|
||||
}
|
||||
if (s == null) {
|
||||
return "";
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final int len = s.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
@@ -112,36 +121,6 @@ public class XMLTools extends XMLWriter {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the Byte Order Mark size and thus allows to skips over a BOM
|
||||
* at the beginning of the given ByteArrayInputStream, if one exists.
|
||||
*
|
||||
* @param is the ByteArrayInputStream used
|
||||
* @throws IOException if can not be read from is
|
||||
* @see <a href="https://www.w3.org/TR/xml/#sec-guessing">Autodetection of Character Encodings</a>
|
||||
*
|
||||
public static int guessBOMSize(ByteArrayInputStream is) throws IOException {
|
||||
byte[] pad = new byte[4];
|
||||
is.read(pad);
|
||||
is.reset();
|
||||
int test2 = ((pad[0] & 0xFF) << 8) | (pad[1] & 0xFF);
|
||||
int test3 = ((test2 & 0xFFFF) << 8) | (pad[2] & 0xFF);
|
||||
int test4 = ((test3 & 0xFFFFFF) << 8) | (pad[3] & 0xFF);
|
||||
//
|
||||
if (test4 == 0x0000FEFF || test4 == 0xFFFE0000 || test4 == 0x0000FFFE || test4 == 0xFEFF0000) {
|
||||
// UCS-4: BOM takes 4 bytes
|
||||
return 4;
|
||||
} else if (test3 == 0xEFBBFF) {
|
||||
// UTF-8: BOM takes 3 bytes
|
||||
return 3;
|
||||
} else if (test2 == 0xFEFF || test2 == 0xFFFE) {
|
||||
// UTF-16: BOM takes 2 bytes
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
/***
|
||||
* removes utf8 byte order marks from byte arrays, in case one is there
|
||||
* @param zugferdRaw the CII XML
|
||||
@@ -149,6 +128,7 @@ public class XMLTools extends XMLWriter {
|
||||
*/
|
||||
public static byte[] removeBOM(byte[] zugferdRaw) {
|
||||
final byte[] zugferdData;
|
||||
// This handles the UTF-8 BOM
|
||||
if ((zugferdRaw[0] == (byte) 0xEF) && (zugferdRaw[1] == (byte) 0xBB) && (zugferdRaw[2] == (byte) 0xBF)) {
|
||||
// I don't like BOMs, lets remove it
|
||||
zugferdData = new byte[zugferdRaw.length - 3];
|
||||
@@ -159,5 +139,8 @@ public class XMLTools extends XMLWriter {
|
||||
return zugferdData;
|
||||
}
|
||||
|
||||
public static byte[] getBytesFromStream(InputStream fileinput) throws IOException {
|
||||
return IOUtils.toByteArray (fileinput);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,18 +22,18 @@ package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import static org.mustangproject.ZUGFeRD.ZUGFeRDDateFormat.DATE;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.mustangproject.*;
|
||||
import org.mustangproject.EStandard;
|
||||
import org.mustangproject.FileAttachment;
|
||||
import org.mustangproject.Invoice;
|
||||
import org.mustangproject.XMLTools;
|
||||
|
||||
public class DAPullProvider extends ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
public class DAPullProvider extends ZUGFeRD2PullProvider {
|
||||
|
||||
protected IExportableTransaction trans;
|
||||
private String paymentTermsDescription;
|
||||
protected Profile profile = Profiles.getByName(EStandard.despatchadvice,"pilot", 1);
|
||||
|
||||
|
||||
@@ -249,13 +249,9 @@ public class DAPullProvider extends ZUGFeRD2PullProvider implements IXMLProvider
|
||||
+ "</SCRDMCCBDACIDAMessageStructure>";
|
||||
|
||||
final byte[] zugferdRaw;
|
||||
try {
|
||||
zugferdRaw = xml.getBytes("UTF-8");
|
||||
zugferdRaw = xml.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
zugferdData = XMLTools.removeBOM(zugferdRaw);
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
Logger.getLogger(OXPullProvider.class.getName()).log(Level.SEVERE, null, e);
|
||||
}
|
||||
zugferdData = XMLTools.removeBOM(zugferdRaw);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,31 +19,35 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
|
||||
import org.apache.pdfbox.preflight.PreflightDocument;
|
||||
import org.apache.pdfbox.preflight.exception.ValidationException;
|
||||
import org.apache.pdfbox.preflight.parser.PreflightParser;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class DXExporterFromA1 extends DXExporterFromA3 implements IZUGFeRDExporter {
|
||||
import org.apache.pdfbox.preflight.PreflightDocument;
|
||||
import org.apache.pdfbox.preflight.ValidationResult;
|
||||
import org.apache.pdfbox.preflight.exception.ValidationException;
|
||||
import org.apache.pdfbox.preflight.parser.PreflightParser;
|
||||
|
||||
import jakarta.activation.DataSource;
|
||||
|
||||
public class DXExporterFromA1 extends DXExporterFromA3 {
|
||||
protected boolean ignorePDFAErrors = false;
|
||||
|
||||
public DXExporterFromA1 ignorePDFAErrors() {
|
||||
@Override
|
||||
public DXExporterFromA1 ignorePDFAErrors() {
|
||||
this.ignorePDFAErrors = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
private static boolean isValidA1(DataSource dataSource) throws IOException {
|
||||
return getPDFAParserValidationResult(new PreflightParser(dataSource));
|
||||
return getPDFAParserValidationResult(PreflightParserHelper.createPreflightParser (dataSource));
|
||||
}
|
||||
/***
|
||||
* internal helper function: get namespace for order-x
|
||||
* @param ver the delivery-x version
|
||||
* @return the URN of the namespace
|
||||
*/
|
||||
public String getNamespaceForVersion(int ver) {
|
||||
@Override
|
||||
public String getNamespaceForVersion(int ver) {
|
||||
// As of late 2022 the Delivery-X standard is not yet published. See specification:
|
||||
// Die digitale Ablösung des Papier-Lieferscheins, Version 1.1, April 2022
|
||||
// Chapter 7.1 XMP-Erweiterungsschema für PDF/A-3
|
||||
@@ -55,7 +59,8 @@ public class DXExporterFromA1 extends DXExporterFromA3 implements IZUGFeRDExport
|
||||
* @param ver the ox version
|
||||
* @return the namespace prefix as string, without colon
|
||||
*/
|
||||
public String getPrefixForVersion(int ver) {
|
||||
@Override
|
||||
public String getPrefixForVersion(int ver) {
|
||||
return "fx";
|
||||
}
|
||||
|
||||
@@ -65,19 +70,19 @@ public class DXExporterFromA1 extends DXExporterFromA3 implements IZUGFeRDExport
|
||||
* NonSequentialParser. Some additional controls are present to check a set of
|
||||
* PDF/A requirements. (Stream length consistency, EOL after some Keyword...)
|
||||
*/
|
||||
parser.parse();// might add a Format.PDF_A1A as parameter and iterate through A1 and A3
|
||||
|
||||
try (PreflightDocument document = parser.getPreflightDocument()) {
|
||||
// might add a Format.PDF_A1A as parameter and iterate through A1 and A3
|
||||
|
||||
try (PreflightDocument document = (PreflightDocument) parser.parse()) {
|
||||
/*
|
||||
* Once the syntax validation is done, the parser can provide a
|
||||
* PreflightDocument (that inherits from PDDocument) This document process the
|
||||
* end of PDF/A validation.
|
||||
*/
|
||||
|
||||
document.validate();
|
||||
ValidationResult res = document.validate();
|
||||
|
||||
// Get validation result
|
||||
return document.getResult().isValid();
|
||||
return res.isValid();
|
||||
} catch (ValidationException e) {
|
||||
/*
|
||||
* the parse method can throw a SyntaxValidationException if the PDF file can't
|
||||
@@ -89,14 +94,17 @@ public class DXExporterFromA1 extends DXExporterFromA3 implements IZUGFeRDExport
|
||||
}
|
||||
|
||||
|
||||
public DXExporterFromA1 setProfile(Profile p) {
|
||||
@Override
|
||||
public DXExporterFromA1 setProfile(Profile p) {
|
||||
return (DXExporterFromA1)super.setProfile(p);
|
||||
}
|
||||
public DXExporterFromA1 setProfile(String profileName) {
|
||||
@Override
|
||||
public DXExporterFromA1 setProfile(String profileName) {
|
||||
return (DXExporterFromA1)super.setProfile(profileName);
|
||||
}
|
||||
|
||||
public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException {
|
||||
@Override
|
||||
public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException {
|
||||
if (!ignorePDFAErrors && !isValidA1(dataSource)) {
|
||||
throw new IOException("File is not a valid PDF/A input file");
|
||||
}
|
||||
@@ -108,32 +116,41 @@ public class DXExporterFromA1 extends DXExporterFromA3 implements IZUGFeRDExport
|
||||
|
||||
}
|
||||
|
||||
public DXExporterFromA1 load(String pdfFilename) throws IOException {
|
||||
@Override
|
||||
public DXExporterFromA1 load(String pdfFilename) throws IOException {
|
||||
return (DXExporterFromA1) super.load(pdfFilename);
|
||||
}
|
||||
public DXExporterFromA1 load(byte[] pdfBinary) throws IOException {
|
||||
@Override
|
||||
public DXExporterFromA1 load(byte[] pdfBinary) throws IOException {
|
||||
return (DXExporterFromA1) super.load(pdfBinary);
|
||||
}
|
||||
public DXExporterFromA1 load(InputStream pdfSource) throws IOException{
|
||||
@Override
|
||||
public DXExporterFromA1 load(InputStream pdfSource) throws IOException{
|
||||
return (DXExporterFromA1) super.load(pdfSource);
|
||||
}
|
||||
public DXExporterFromA1 setCreator(String creator) {
|
||||
@Override
|
||||
public DXExporterFromA1 setCreator(String creator) {
|
||||
return (DXExporterFromA1) super.setCreator(creator);
|
||||
}
|
||||
public DXExporterFromA1 setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||
@Override
|
||||
public DXExporterFromA1 setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||
return (DXExporterFromA1) super.setConformanceLevel(newLevel);
|
||||
}
|
||||
public DXExporterFromA1 setProducer(String producer){
|
||||
@Override
|
||||
public DXExporterFromA1 setProducer(String producer){
|
||||
return (DXExporterFromA1) super.setProducer(producer);
|
||||
}
|
||||
public DXExporterFromA1 setZUGFeRDVersion(int version){
|
||||
@Override
|
||||
public DXExporterFromA1 setZUGFeRDVersion(int version){
|
||||
return (DXExporterFromA1) super.setZUGFeRDVersion(version);
|
||||
}
|
||||
public DXExporterFromA1 setXML(byte[] zugferdData) throws IOException{
|
||||
@Override
|
||||
public DXExporterFromA1 setXML(byte[] zugferdData) throws IOException{
|
||||
return (DXExporterFromA1) super.setXML(zugferdData);
|
||||
}
|
||||
|
||||
public DXExporterFromA1 disableAutoClose(boolean disableAutoClose){
|
||||
@Override
|
||||
public DXExporterFromA1 disableAutoClose(boolean disableAutoClose){
|
||||
return (DXExporterFromA1) super.disableAutoClose(disableAutoClose);
|
||||
}
|
||||
public DXExporterFromA1 convertOnly() {
|
||||
|
||||
@@ -20,16 +20,38 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import org.apache.pdfbox.cos.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.cos.COSArray;
|
||||
import org.apache.pdfbox.cos.COSBase;
|
||||
import org.apache.pdfbox.cos.COSDictionary;
|
||||
import org.apache.pdfbox.cos.COSName;
|
||||
import org.apache.pdfbox.cos.COSObject;
|
||||
import org.apache.pdfbox.io.IOUtils;
|
||||
import org.apache.pdfbox.pdmodel.*;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
|
||||
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
|
||||
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
||||
import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDMarkInfo;
|
||||
import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDStructureTreeRoot;
|
||||
import org.apache.pdfbox.pdmodel.graphics.color.PDOutputIntent;
|
||||
import org.apache.pdfbox.preflight.utils.ByteArrayDataSource;
|
||||
import org.apache.xmpbox.XMPMetadata;
|
||||
import org.apache.xmpbox.schema.AdobePDFSchema;
|
||||
import org.apache.xmpbox.schema.DublinCoreSchema;
|
||||
@@ -43,16 +65,13 @@ import org.apache.xmpbox.xml.XmpSerializer;
|
||||
import org.mustangproject.EStandard;
|
||||
import org.mustangproject.FileAttachment;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import javax.activation.FileDataSource;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import jakarta.activation.DataSource;
|
||||
import jakarta.activation.FileDataSource;
|
||||
|
||||
public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
|
||||
protected PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE;
|
||||
protected ArrayList<FileAttachment> fileAttachments = new ArrayList<FileAttachment>();
|
||||
protected ArrayList<FileAttachment> fileAttachments = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* This flag controls whether or not the metadata is overwritten, or kind of merged.
|
||||
@@ -108,9 +127,6 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
protected String despatchAdviceDocumentType = "DESPATCHADVICE";
|
||||
|
||||
|
||||
private HashMap<String, byte[]> additionalXMLs = new HashMap<String, byte[]>();
|
||||
|
||||
|
||||
private boolean attachZUGFeRDHeaders = true;
|
||||
|
||||
/**
|
||||
@@ -119,7 +135,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
*
|
||||
* @param pdfFilename filename of an PDF/A1 compliant document
|
||||
*/
|
||||
public DXExporterFromA3 load(String pdfFilename) throws IOException {
|
||||
@Override
|
||||
public DXExporterFromA3 load(String pdfFilename) throws IOException {
|
||||
|
||||
ensurePDFIsValid(new FileDataSource(pdfFilename));
|
||||
try (FileInputStream pdf = new FileInputStream(pdfFilename)) {
|
||||
@@ -127,11 +144,13 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
}
|
||||
}
|
||||
|
||||
public IXMLProvider getProvider() {
|
||||
@Override
|
||||
public IXMLProvider getProvider() {
|
||||
return xmlProvider;
|
||||
}
|
||||
|
||||
public DXExporterFromA3 setProfile(Profile p) {
|
||||
@Override
|
||||
public DXExporterFromA3 setProfile(Profile p) {
|
||||
this.profile = p;
|
||||
if (xmlProvider != null) {
|
||||
xmlProvider.setProfile(p);
|
||||
@@ -139,7 +158,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return this;
|
||||
}
|
||||
|
||||
public DXExporterFromA3 setProfile(String profilename) {
|
||||
@Override
|
||||
public DXExporterFromA3 setProfile(String profilename) {
|
||||
this.profile = Profiles.getByName(profilename);
|
||||
|
||||
if (xmlProvider != null) {
|
||||
@@ -148,7 +168,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return this;
|
||||
}
|
||||
|
||||
public DXExporterFromA3 addAdditionalFile(String name, byte[] content) {
|
||||
@Override
|
||||
public DXExporterFromA3 addAdditionalFile(String name, byte[] content) {
|
||||
fileAttachments.add(new FileAttachment(name, "text/xml", "Supplement", content).setDescription("ZUGFeRD extension/additional data"));
|
||||
return this;
|
||||
}
|
||||
@@ -161,9 +182,10 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
*
|
||||
* @param pdfBinary binary of a PDF/A1 compliant document
|
||||
*/
|
||||
public DXExporterFromA3 load(byte[] pdfBinary) throws IOException {
|
||||
@Override
|
||||
public DXExporterFromA3 load(byte[] pdfBinary) throws IOException {
|
||||
ensurePDFIsValid(new ByteArrayDataSource(new ByteArrayInputStream(pdfBinary)));
|
||||
doc = PDDocument.load(pdfBinary);
|
||||
doc = Loader.loadPDF(pdfBinary);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -171,11 +193,13 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
super();
|
||||
}
|
||||
|
||||
public void attachFile(FileAttachment file) {
|
||||
@Override
|
||||
public void attachFile(FileAttachment file) {
|
||||
fileAttachments.add(file);
|
||||
}
|
||||
|
||||
public void attachFile(String filename, byte[] data, String mimetype, String relation) {
|
||||
@Override
|
||||
public void attachFile(String filename, byte[] data, String mimetype, String relation) {
|
||||
FileAttachment fa = new FileAttachment(filename, mimetype, relation, data);
|
||||
fileAttachments.add(fa);
|
||||
}
|
||||
@@ -185,7 +209,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* @param ZUGFeRDfilename the pdf file name
|
||||
* @throws IOException if anything is wrong in the target location
|
||||
*/
|
||||
public void export(String ZUGFeRDfilename) throws IOException {
|
||||
@Override
|
||||
public void export(String ZUGFeRDfilename) throws IOException {
|
||||
if (!documentPrepared) {
|
||||
prepareDocument();
|
||||
}
|
||||
@@ -212,7 +237,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* @param output the OutputStream
|
||||
* @throws IOException if anything is wrong in the OutputStream
|
||||
*/
|
||||
public void export(OutputStream output) throws IOException {
|
||||
@Override
|
||||
public void export(OutputStream output) throws IOException {
|
||||
if (!documentPrepared) {
|
||||
prepareDocument();
|
||||
}
|
||||
@@ -238,7 +264,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* @param data the binary data of the file/attachment
|
||||
* @throws IOException if anything is wrong with filename
|
||||
*/
|
||||
public void PDFAttachGenericFile(String filename, String relationship, String description,
|
||||
@Override
|
||||
public void PDFAttachGenericFile(String filename, String relationship, String description,
|
||||
String subType, byte[] data) throws IOException {
|
||||
PDFAttachGenericFile(this.doc, filename, relationship, description, subType, data);
|
||||
}
|
||||
@@ -255,7 +282,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* @param data the binary data of the file/attachment
|
||||
* @throws IOException if anything is wrong with filename
|
||||
*/
|
||||
public void PDFAttachGenericFile(PDDocument doc, String filename, String relationship, String description,
|
||||
@Override
|
||||
public void PDFAttachGenericFile(PDDocument doc, String filename, String relationship, String description,
|
||||
String subType, byte[] data) throws IOException {
|
||||
fileAttached = true;
|
||||
|
||||
@@ -274,7 +302,7 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
ef.setSize(data.length);
|
||||
ef.setCreationDate(new GregorianCalendar());
|
||||
|
||||
ef.setModDate(GregorianCalendar.getInstance());
|
||||
ef.setModDate(Calendar.getInstance());
|
||||
|
||||
fs.setEmbeddedFile(ef);
|
||||
|
||||
@@ -306,7 +334,7 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
doc.getDocumentCatalog().setNames(names);
|
||||
|
||||
// AF entry (Array) in catalog with the FileSpec
|
||||
COSBase AFEntry = (COSBase) doc.getDocumentCatalog().getCOSObject().getItem("AF");
|
||||
COSBase AFEntry = doc.getDocumentCatalog().getCOSObject().getItem("AF");
|
||||
if ((AFEntry == null)) {
|
||||
COSArray cosArray = new COSArray();
|
||||
cosArray.add(fs);
|
||||
@@ -332,7 +360,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* @param zugferdData XML data to be set as a byte array (XML file in raw form).
|
||||
* @throws IOException (should not happen)
|
||||
*/
|
||||
public DXExporterFromA3 setXML(byte[] zugferdData) throws IOException {
|
||||
@Override
|
||||
public DXExporterFromA3 setXML(byte[] zugferdData) throws IOException {
|
||||
CustomXMLProvider cus = new CustomXMLProvider();
|
||||
// As of late 2022 the Delivery-X standard is not yet published. See specification:
|
||||
// Die digitale Ablösung des Papier-Lieferscheins, Version 1.1, April 2022
|
||||
@@ -353,11 +382,13 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
*
|
||||
* @param pdfSource source to read a PDF/A1 compliant document from
|
||||
*/
|
||||
public DXExporterFromA3 load(InputStream pdfSource) throws IOException {
|
||||
@Override
|
||||
public DXExporterFromA3 load(InputStream pdfSource) throws IOException {
|
||||
return load(readAllBytes(pdfSource));
|
||||
}
|
||||
|
||||
public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException {
|
||||
@Override
|
||||
public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -380,23 +411,27 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* <p>
|
||||
* Feel free to pass "A" as new level if you know what you are doing :-)
|
||||
*/
|
||||
public DXExporterFromA3 setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||
@Override
|
||||
public DXExporterFromA3 setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||
conformanceLevel = newLevel;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public DXExporterFromA3 setCreator(String creator) {
|
||||
@Override
|
||||
public DXExporterFromA3 setCreator(String creator) {
|
||||
this.creator = creator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DXExporterFromA3 setCreatorTool(String creatorTool) {
|
||||
@Override
|
||||
public DXExporterFromA3 setCreatorTool(String creatorTool) {
|
||||
this.creatorTool = creatorTool;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DXExporterFromA3 setProducer(String producer) {
|
||||
@Override
|
||||
public DXExporterFromA3 setProducer(String producer) {
|
||||
this.producer = producer;
|
||||
return this;
|
||||
}
|
||||
@@ -415,7 +450,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return this;
|
||||
}
|
||||
|
||||
protected DXExporterFromA3 setAttachZUGFeRDHeaders(boolean attachHeaders) {
|
||||
@Override
|
||||
protected DXExporterFromA3 setAttachZUGFeRDHeaders(boolean attachHeaders) {
|
||||
this.attachZUGFeRDHeaders = attachHeaders;
|
||||
return this;
|
||||
}
|
||||
@@ -428,7 +464,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
*
|
||||
* @param metadata the PDFbox XMPMetadata object
|
||||
*/
|
||||
protected void addXMP(XMPMetadata metadata) {
|
||||
@Override
|
||||
protected void addXMP(XMPMetadata metadata) {
|
||||
|
||||
if (attachZUGFeRDHeaders) {
|
||||
// As of late 2022 the Delivery-X standard is not yet published. See specification:
|
||||
@@ -459,12 +496,14 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* <code>setZUGFeRDXMLData(byte[] zugferdData)</code>
|
||||
* @throws IOException if anything is wrong with already loaded PDF
|
||||
*/
|
||||
public IExporter setTransaction(IExportableTransaction trans) throws IOException {
|
||||
@Override
|
||||
public IExporter setTransaction(IExportableTransaction trans) throws IOException {
|
||||
this.trans = trans;
|
||||
return prepare();
|
||||
}
|
||||
|
||||
public IExporter prepare() throws IOException {
|
||||
@Override
|
||||
public IExporter prepare() throws IOException {
|
||||
prepareDocument();
|
||||
xmlProvider.generateXML(trans);
|
||||
String filename = "cida.xml";
|
||||
@@ -483,7 +522,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* Reads the XMPMetadata from the PDDocument, if it exists.
|
||||
* Otherwise creates XMPMetadata.
|
||||
*/
|
||||
protected XMPMetadata getXmpMetadata() throws IOException {
|
||||
@Override
|
||||
protected XMPMetadata getXmpMetadata() throws IOException {
|
||||
PDMetadata meta = doc.getDocumentCatalog().getMetadata();
|
||||
if ((meta != null) && (meta.getLength() > 0)) {
|
||||
try {
|
||||
@@ -496,7 +536,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return XMPMetadata.createXMPMetadata();
|
||||
}
|
||||
|
||||
protected byte[] serializeXmpMetadata(XMPMetadata xmpMetadata) throws TransformerException {
|
||||
@Override
|
||||
protected byte[] serializeXmpMetadata(XMPMetadata xmpMetadata) throws TransformerException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
new XmpSerializer().serialize(xmpMetadata, buffer, true); // see https://github.com/ZUGFeRD/mustangproject/issues/44
|
||||
return buffer.toByteArray();
|
||||
@@ -506,7 +547,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* Sets the producer if the overwrite flag is set or the producer is not already set.
|
||||
* Sets the PDFVersion to 1.4 if the field is empty.
|
||||
*/
|
||||
protected void writeAdobePDFSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected void writeAdobePDFSchema(XMPMetadata xmp) {
|
||||
AdobePDFSchema pdf = getAdobePDFSchema(xmp);
|
||||
if (overwrite || isEmpty(pdf.getProducer()))
|
||||
pdf.setProducer(producer);
|
||||
@@ -516,7 +558,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* Returns the AdobePDFSchema from the XMPMetadata if it exists.
|
||||
* If the overwrite flag is set or no AdobePDFSchema exists in the XMPMetadata, it is created, added and returned.
|
||||
*/
|
||||
protected AdobePDFSchema getAdobePDFSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected AdobePDFSchema getAdobePDFSchema(XMPMetadata xmp) {
|
||||
AdobePDFSchema pdf = xmp.getAdobePDFSchema();
|
||||
if (pdf != null)
|
||||
if (overwrite)
|
||||
@@ -526,7 +569,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return xmp.createAndAddAdobePDFSchema();
|
||||
}
|
||||
|
||||
protected void writePDFAIdentificationSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected void writePDFAIdentificationSchema(XMPMetadata xmp) {
|
||||
PDFAIdentificationSchema pdfaid = getPDFAIdentificationSchema(xmp);
|
||||
if (overwrite || isEmpty(pdfaid.getConformance())) {
|
||||
try {
|
||||
@@ -541,17 +585,19 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
pdfaid.setPart(3);
|
||||
}
|
||||
|
||||
protected PDFAIdentificationSchema getPDFAIdentificationSchema(XMPMetadata xmp) {
|
||||
PDFAIdentificationSchema pdfaid = xmp.getPDFIdentificationSchema();
|
||||
@Override
|
||||
protected PDFAIdentificationSchema getPDFAIdentificationSchema(XMPMetadata xmp) {
|
||||
PDFAIdentificationSchema pdfaid = xmp.getPDFAIdentificationSchema();
|
||||
if (pdfaid != null)
|
||||
if (overwrite)
|
||||
xmp.removeSchema(pdfaid);
|
||||
else
|
||||
return pdfaid;
|
||||
return xmp.createAndAddPFAIdentificationSchema();
|
||||
return xmp.createAndAddPDFAIdentificationSchema();
|
||||
}
|
||||
|
||||
protected void writeDublinCoreSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected void writeDublinCoreSchema(XMPMetadata xmp) {
|
||||
DublinCoreSchema dc = getDublinCoreSchema(xmp);
|
||||
if (dc.getFormat() == null)
|
||||
dc.setFormat("application/pdf");
|
||||
@@ -574,7 +620,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
}
|
||||
}
|
||||
|
||||
protected DublinCoreSchema getDublinCoreSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected DublinCoreSchema getDublinCoreSchema(XMPMetadata xmp) {
|
||||
DublinCoreSchema dc = xmp.getDublinCoreSchema();
|
||||
if (dc != null)
|
||||
if (overwrite)
|
||||
@@ -584,15 +631,17 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return xmp.createAndAddDublinCoreSchema();
|
||||
}
|
||||
|
||||
protected void writeXMLBasicSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected void writeXMLBasicSchema(XMPMetadata xmp) {
|
||||
XMPBasicSchema xsb = getXmpBasicSchema(xmp);
|
||||
if (overwrite || isEmpty(xsb.getCreatorTool()) || "UnknownApplication".equals(xsb.getCreatorTool()))
|
||||
xsb.setCreatorTool(creatorTool);
|
||||
if (overwrite || xsb.getCreateDate() == null)
|
||||
xsb.setCreateDate(GregorianCalendar.getInstance());
|
||||
xsb.setCreateDate(Calendar.getInstance());
|
||||
}
|
||||
|
||||
protected XMPBasicSchema getXmpBasicSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected XMPBasicSchema getXmpBasicSchema(XMPMetadata xmp) {
|
||||
XMPBasicSchema xsb = xmp.getXMPBasicSchema();
|
||||
if (xsb != null)
|
||||
if (overwrite)
|
||||
@@ -602,7 +651,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return xmp.createAndAddXMPBasicSchema();
|
||||
}
|
||||
|
||||
protected void writeDocumentInformation() {
|
||||
@Override
|
||||
protected void writeDocumentInformation() {
|
||||
String fullProducer = producer + " (via mustangproject.org " + Version.VERSION + ")";
|
||||
PDDocumentInformation info = doc.getDocumentInformation();
|
||||
if (overwrite || info.getCreationDate() == null)
|
||||
@@ -624,7 +674,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
/**
|
||||
* Adds an OutputIntent and the sRGB color profile if no OutputIntent exist
|
||||
*/
|
||||
protected void addSRGBOutputIntend() throws IOException {
|
||||
@Override
|
||||
protected void addSRGBOutputIntend() throws IOException {
|
||||
if (!doc.getDocumentCatalog().getOutputIntents().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -647,7 +698,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
/**
|
||||
* Adds a MarkInfo element to the PDF if it doesn't already exist and sets it as marked.
|
||||
*/
|
||||
protected void setMarked() {
|
||||
@Override
|
||||
protected void setMarked() {
|
||||
PDDocumentCatalog catalog = doc.getDocumentCatalog();
|
||||
if (catalog.getMarkInfo() == null) {
|
||||
catalog.setMarkInfo(new PDMarkInfo(doc.getPages().getCOSObject()));
|
||||
@@ -658,7 +710,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
/**
|
||||
* Adds a StructureTreeRoot element to the PDF if it doesn't already exist.
|
||||
*/
|
||||
protected void addStructureTreeRoot() {
|
||||
@Override
|
||||
protected void addStructureTreeRoot() {
|
||||
if (doc.getDocumentCatalog().getStructureTreeRoot() == null) {
|
||||
doc.getDocumentCatalog().setStructureTreeRoot(new PDStructureTreeRoot());
|
||||
}
|
||||
@@ -668,19 +721,22 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
/**
|
||||
* @return if pdf file will be automatically closed after adding ZF
|
||||
*/
|
||||
public boolean isAutoCloseDisabled() {
|
||||
@Override
|
||||
public boolean isAutoCloseDisabled() {
|
||||
return disableAutoClose;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param disableAutoClose prevent PDF file from being closed after adding ZF
|
||||
*/
|
||||
public DXExporterFromA3 disableAutoClose(boolean disableAutoClose) {
|
||||
@Override
|
||||
public DXExporterFromA3 disableAutoClose(boolean disableAutoClose) {
|
||||
this.disableAutoClose = disableAutoClose;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void setXMLProvider(IXMLProvider p) {
|
||||
@Override
|
||||
protected void setXMLProvider(IXMLProvider p) {
|
||||
this.xmlProvider = p;
|
||||
if (profile != null) {
|
||||
xmlProvider.setProfile(profile);
|
||||
|
||||
@@ -20,31 +20,10 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import org.apache.pdfbox.cos.*;
|
||||
import org.apache.pdfbox.io.IOUtils;
|
||||
import org.apache.pdfbox.pdmodel.*;
|
||||
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
||||
import org.apache.pdfbox.preflight.PreflightDocument;
|
||||
import org.apache.pdfbox.preflight.exception.ValidationException;
|
||||
import org.apache.pdfbox.preflight.parser.PreflightParser;
|
||||
import org.apache.pdfbox.preflight.utils.ByteArrayDataSource;
|
||||
import org.apache.xmpbox.XMPMetadata;
|
||||
import org.apache.xmpbox.schema.AdobePDFSchema;
|
||||
import org.apache.xmpbox.schema.DublinCoreSchema;
|
||||
import org.apache.xmpbox.schema.PDFAIdentificationSchema;
|
||||
import org.apache.xmpbox.schema.XMPBasicSchema;
|
||||
import org.apache.xmpbox.type.BadFieldValueException;
|
||||
import org.apache.xmpbox.xml.XmpSerializer;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import javax.activation.FileDataSource;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.io.*;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class EinLieferscheinExporter implements IExporter {
|
||||
IXMLProvider xmlProvider;
|
||||
|
||||
@@ -140,6 +140,11 @@ public interface IExportableTransaction {
|
||||
return null;
|
||||
}
|
||||
|
||||
default IZUGFeRDCashDiscount[] getCashDiscounts() { return null; }
|
||||
|
||||
/***
|
||||
* @return the invoice line items with the positions
|
||||
*/
|
||||
IZUGFeRDExportableItem[] getZFItems();
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
*********************************************************************** */
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants;
|
||||
|
||||
/**
|
||||
* The interface for allowances or charges, to be used by the pullprovider
|
||||
* @author AlexanderSchmidt
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
public interface IZUGFeRDCashDiscount {
|
||||
|
||||
|
||||
/***
|
||||
* @return this particular cash discount as cross industry invoice XML
|
||||
*/
|
||||
public String getAsCII();
|
||||
|
||||
/***
|
||||
* since EN16931 voted not to have (or even allow) cash discounts in their core invoice the german
|
||||
* XRechnung CIUS defined it's own proprietary format for a freetext field
|
||||
* @return this particular cash discount in proprietary xrechnung format
|
||||
*/
|
||||
public String getAsXRechnung();
|
||||
|
||||
}
|
||||
@@ -26,12 +26,13 @@ package org.mustangproject.ZUGFeRD;
|
||||
* @author jstaerk
|
||||
* */
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import org.mustangproject.Item;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import org.mustangproject.Item;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
@JsonDeserialize(as = Item.class)
|
||||
public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
|
||||
IZUGFeRDExportableProduct getProduct();
|
||||
@@ -140,6 +141,6 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
|
||||
*/
|
||||
default IZUGFeRDAllowanceCharge[] getItemTotalAllowances() {
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants;
|
||||
|
||||
@@ -156,4 +157,12 @@ public interface IZUGFeRDExportableProduct {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
default String getCountryOfOrigin() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default HashMap<String, String> getAttributes() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import org.mustangproject.TradeParty;
|
||||
|
||||
/**
|
||||
* Mustangproject's ZUGFeRD implementation neccessary interface for ZUGFeRD exporter Licensed under the APLv2
|
||||
*
|
||||
|
||||
@@ -18,11 +18,12 @@
|
||||
*********************************************************************** */
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import jakarta.activation.DataSource;
|
||||
|
||||
public interface IZUGFeRDExporter extends Closeable, IExporter {
|
||||
/**
|
||||
* factory: loads a PDF file and returns an appropriate exporter
|
||||
|
||||
@@ -18,11 +18,6 @@
|
||||
*********************************************************************** */
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public interface IZUGFeRDLegalOrganisation {
|
||||
|
||||
/***
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
/***
|
||||
* the linecalculator does the math within an item line, and e.g. calculates quantity*price.
|
||||
@@ -40,7 +41,7 @@ public class LineCalculator {
|
||||
priceGross = currentItem.getPrice(); // see https://github.com/ZUGFeRD/mustangproject/issues/159
|
||||
price = priceGross.subtract(allowance).add(charge);
|
||||
itemTotalNetAmount = currentItem.getQuantity().multiply(getPrice()).divide(currentItem.getBasisQuantity())
|
||||
.subtract(allowanceItemTotal).setScale(2, BigDecimal.ROUND_HALF_UP);
|
||||
.subtract(allowanceItemTotal).setScale(2, RoundingMode.HALF_UP);
|
||||
itemTotalVATAmount = itemTotalNetAmount.multiply(multiplicator);
|
||||
|
||||
}
|
||||
|
||||
@@ -19,31 +19,35 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
|
||||
import org.apache.pdfbox.preflight.PreflightDocument;
|
||||
import org.apache.pdfbox.preflight.exception.ValidationException;
|
||||
import org.apache.pdfbox.preflight.parser.PreflightParser;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class OXExporterFromA1 extends OXExporterFromA3 implements IZUGFeRDExporter {
|
||||
import org.apache.pdfbox.preflight.PreflightDocument;
|
||||
import org.apache.pdfbox.preflight.ValidationResult;
|
||||
import org.apache.pdfbox.preflight.exception.ValidationException;
|
||||
import org.apache.pdfbox.preflight.parser.PreflightParser;
|
||||
|
||||
import jakarta.activation.DataSource;
|
||||
|
||||
public class OXExporterFromA1 extends OXExporterFromA3 {
|
||||
protected boolean ignorePDFAErrors = false;
|
||||
|
||||
public OXExporterFromA1 ignorePDFAErrors() {
|
||||
@Override
|
||||
public OXExporterFromA1 ignorePDFAErrors() {
|
||||
this.ignorePDFAErrors = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
private static boolean isValidA1(DataSource dataSource) throws IOException {
|
||||
return getPDFAParserValidationResult(new PreflightParser(dataSource));
|
||||
return getPDFAParserValidationResult(PreflightParserHelper.createPreflightParser(dataSource));
|
||||
}
|
||||
/***
|
||||
* internal helper function: get namespace for order-x
|
||||
* @param ver the order-x version
|
||||
* @return the URN of the namespace
|
||||
*/
|
||||
public String getNamespaceForVersion(int ver) {
|
||||
@Override
|
||||
public String getNamespaceForVersion(int ver) {
|
||||
return "urn:factur-x:pdfa:CrossIndustryDocument:1p0#";
|
||||
}
|
||||
/***
|
||||
@@ -51,7 +55,8 @@ public class OXExporterFromA1 extends OXExporterFromA3 implements IZUGFeRDExport
|
||||
* @param ver the ox version
|
||||
* @return the namespace prefix as string, without colon
|
||||
*/
|
||||
public String getPrefixForVersion(int ver) {
|
||||
@Override
|
||||
public String getPrefixForVersion(int ver) {
|
||||
return "fx";
|
||||
}
|
||||
|
||||
@@ -61,19 +66,19 @@ public class OXExporterFromA1 extends OXExporterFromA3 implements IZUGFeRDExport
|
||||
* NonSequentialParser. Some additional controls are present to check a set of
|
||||
* PDF/A requirements. (Stream length consistency, EOL after some Keyword...)
|
||||
*/
|
||||
parser.parse();// might add a Format.PDF_A1A as parameter and iterate through A1 and A3
|
||||
// might add a Format.PDF_A1A as parameter and iterate through A1 and A3
|
||||
|
||||
try (PreflightDocument document = parser.getPreflightDocument()) {
|
||||
try (PreflightDocument document = (PreflightDocument) parser.parse()) {
|
||||
/*
|
||||
* Once the syntax validation is done, the parser can provide a
|
||||
* PreflightDocument (that inherits from PDDocument) This document process the
|
||||
* end of PDF/A validation.
|
||||
*/
|
||||
|
||||
document.validate();
|
||||
ValidationResult res = document.validate();
|
||||
|
||||
// Get validation result
|
||||
return document.getResult().isValid();
|
||||
return res.isValid();
|
||||
} catch (ValidationException e) {
|
||||
/*
|
||||
* the parse method can throw a SyntaxValidationException if the PDF file can't
|
||||
@@ -85,14 +90,17 @@ public class OXExporterFromA1 extends OXExporterFromA3 implements IZUGFeRDExport
|
||||
}
|
||||
|
||||
|
||||
public OXExporterFromA1 setProfile(Profile p) {
|
||||
@Override
|
||||
public OXExporterFromA1 setProfile(Profile p) {
|
||||
return (OXExporterFromA1)super.setProfile(p);
|
||||
}
|
||||
public OXExporterFromA1 setProfile(String profileName) {
|
||||
@Override
|
||||
public OXExporterFromA1 setProfile(String profileName) {
|
||||
return (OXExporterFromA1)super.setProfile(profileName);
|
||||
}
|
||||
|
||||
public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException {
|
||||
@Override
|
||||
public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException {
|
||||
if (!ignorePDFAErrors && !isValidA1(dataSource)) {
|
||||
throw new IOException("File is not a valid PDF/A input file");
|
||||
}
|
||||
@@ -104,32 +112,41 @@ public class OXExporterFromA1 extends OXExporterFromA3 implements IZUGFeRDExport
|
||||
|
||||
}
|
||||
|
||||
public OXExporterFromA1 load(String pdfFilename) throws IOException {
|
||||
@Override
|
||||
public OXExporterFromA1 load(String pdfFilename) throws IOException {
|
||||
return (OXExporterFromA1) super.load(pdfFilename);
|
||||
}
|
||||
public OXExporterFromA1 load(byte[] pdfBinary) throws IOException {
|
||||
@Override
|
||||
public OXExporterFromA1 load(byte[] pdfBinary) throws IOException {
|
||||
return (OXExporterFromA1) super.load(pdfBinary);
|
||||
}
|
||||
public OXExporterFromA1 load(InputStream pdfSource) throws IOException{
|
||||
@Override
|
||||
public OXExporterFromA1 load(InputStream pdfSource) throws IOException{
|
||||
return (OXExporterFromA1) super.load(pdfSource);
|
||||
}
|
||||
public OXExporterFromA1 setCreator(String creator) {
|
||||
@Override
|
||||
public OXExporterFromA1 setCreator(String creator) {
|
||||
return (OXExporterFromA1) super.setCreator(creator);
|
||||
}
|
||||
public OXExporterFromA1 setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||
@Override
|
||||
public OXExporterFromA1 setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||
return (OXExporterFromA1) super.setConformanceLevel(newLevel);
|
||||
}
|
||||
public OXExporterFromA1 setProducer(String producer){
|
||||
@Override
|
||||
public OXExporterFromA1 setProducer(String producer){
|
||||
return (OXExporterFromA1) super.setProducer(producer);
|
||||
}
|
||||
public OXExporterFromA1 setZUGFeRDVersion(int version){
|
||||
@Override
|
||||
public OXExporterFromA1 setZUGFeRDVersion(int version){
|
||||
return (OXExporterFromA1) super.setZUGFeRDVersion(version);
|
||||
}
|
||||
public OXExporterFromA1 setXML(byte[] zugferdData) throws IOException{
|
||||
@Override
|
||||
public OXExporterFromA1 setXML(byte[] zugferdData) throws IOException{
|
||||
return (OXExporterFromA1) super.setXML(zugferdData);
|
||||
}
|
||||
|
||||
public OXExporterFromA1 disableAutoClose(boolean disableAutoClose){
|
||||
@Override
|
||||
public OXExporterFromA1 disableAutoClose(boolean disableAutoClose){
|
||||
return (OXExporterFromA1) super.disableAutoClose(disableAutoClose);
|
||||
}
|
||||
public OXExporterFromA1 convertOnly() {
|
||||
|
||||
@@ -20,20 +20,38 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import org.apache.pdfbox.cos.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.cos.COSArray;
|
||||
import org.apache.pdfbox.cos.COSBase;
|
||||
import org.apache.pdfbox.cos.COSDictionary;
|
||||
import org.apache.pdfbox.cos.COSName;
|
||||
import org.apache.pdfbox.cos.COSObject;
|
||||
import org.apache.pdfbox.io.IOUtils;
|
||||
import org.apache.pdfbox.pdmodel.*;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
|
||||
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
|
||||
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
||||
import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDMarkInfo;
|
||||
import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDStructureTreeRoot;
|
||||
import org.apache.pdfbox.pdmodel.font.PDCIDFontType2;
|
||||
import org.apache.pdfbox.pdmodel.font.PDFont;
|
||||
import org.apache.pdfbox.pdmodel.font.PDFontDescriptor;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType0Font;
|
||||
import org.apache.pdfbox.pdmodel.graphics.color.PDOutputIntent;
|
||||
import org.apache.pdfbox.preflight.utils.ByteArrayDataSource;
|
||||
import org.apache.xmpbox.XMPMetadata;
|
||||
import org.apache.xmpbox.schema.AdobePDFSchema;
|
||||
import org.apache.xmpbox.schema.DublinCoreSchema;
|
||||
@@ -47,16 +65,13 @@ import org.apache.xmpbox.xml.XmpSerializer;
|
||||
import org.mustangproject.EStandard;
|
||||
import org.mustangproject.FileAttachment;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import javax.activation.FileDataSource;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import jakarta.activation.DataSource;
|
||||
import jakarta.activation.FileDataSource;
|
||||
|
||||
public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
|
||||
protected PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE;
|
||||
protected ArrayList<FileAttachment> fileAttachments = new ArrayList<FileAttachment>();
|
||||
protected ArrayList<FileAttachment> fileAttachments = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* This flag controls whether or not the metadata is overwritten, or kind of merged.
|
||||
@@ -112,9 +127,6 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
protected String orderXDocumentType = "ORDER";
|
||||
|
||||
|
||||
private HashMap<String, byte[]> additionalXMLs = new HashMap<String, byte[]>();
|
||||
|
||||
|
||||
private boolean attachZUGFeRDHeaders = true;
|
||||
|
||||
/**
|
||||
@@ -123,7 +135,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
*
|
||||
* @param pdfFilename filename of an PDF/A1 compliant document
|
||||
*/
|
||||
public OXExporterFromA3 load(String pdfFilename) throws IOException {
|
||||
@Override
|
||||
public OXExporterFromA3 load(String pdfFilename) throws IOException {
|
||||
|
||||
ensurePDFIsValid(new FileDataSource(pdfFilename));
|
||||
try (FileInputStream pdf = new FileInputStream(pdfFilename)) {
|
||||
@@ -131,11 +144,13 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
}
|
||||
}
|
||||
|
||||
public IXMLProvider getProvider() {
|
||||
@Override
|
||||
public IXMLProvider getProvider() {
|
||||
return xmlProvider;
|
||||
}
|
||||
|
||||
public OXExporterFromA3 setProfile(Profile p) {
|
||||
@Override
|
||||
public OXExporterFromA3 setProfile(Profile p) {
|
||||
this.profile = p;
|
||||
if (xmlProvider != null) {
|
||||
xmlProvider.setProfile(p);
|
||||
@@ -143,7 +158,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return this;
|
||||
}
|
||||
|
||||
public OXExporterFromA3 setProfile(String profilename) {
|
||||
@Override
|
||||
public OXExporterFromA3 setProfile(String profilename) {
|
||||
this.profile = Profiles.getByName(profilename);
|
||||
|
||||
if (xmlProvider != null) {
|
||||
@@ -152,7 +168,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return this;
|
||||
}
|
||||
|
||||
public OXExporterFromA3 addAdditionalFile(String name, byte[] content) {
|
||||
@Override
|
||||
public OXExporterFromA3 addAdditionalFile(String name, byte[] content) {
|
||||
fileAttachments.add(new FileAttachment(name, "text/xml", "Supplement", content).setDescription("ZUGFeRD extension/additional data"));
|
||||
return this;
|
||||
}
|
||||
@@ -165,9 +182,10 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
*
|
||||
* @param pdfBinary binary of a PDF/A1 compliant document
|
||||
*/
|
||||
public OXExporterFromA3 load(byte[] pdfBinary) throws IOException {
|
||||
@Override
|
||||
public OXExporterFromA3 load(byte[] pdfBinary) throws IOException {
|
||||
ensurePDFIsValid(new ByteArrayDataSource(new ByteArrayInputStream(pdfBinary)));
|
||||
doc = PDDocument.load(pdfBinary);
|
||||
doc = Loader.loadPDF(pdfBinary);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -175,11 +193,13 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
super();
|
||||
}
|
||||
|
||||
public void attachFile(FileAttachment file) {
|
||||
@Override
|
||||
public void attachFile(FileAttachment file) {
|
||||
fileAttachments.add(file);
|
||||
}
|
||||
|
||||
public void attachFile(String filename, byte[] data, String mimetype, String relation) {
|
||||
@Override
|
||||
public void attachFile(String filename, byte[] data, String mimetype, String relation) {
|
||||
FileAttachment fa = new FileAttachment(filename, mimetype, relation, data);
|
||||
fileAttachments.add(fa);
|
||||
}
|
||||
@@ -189,7 +209,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* @param ZUGFeRDfilename the pdf file name
|
||||
* @throws IOException if anything is wrong in the target location
|
||||
*/
|
||||
public void export(String ZUGFeRDfilename) throws IOException {
|
||||
@Override
|
||||
public void export(String ZUGFeRDfilename) throws IOException {
|
||||
if (!documentPrepared) {
|
||||
prepareDocument();
|
||||
}
|
||||
@@ -216,7 +237,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* @param output the OutputStream
|
||||
* @throws IOException if anything is wrong in the OutputStream
|
||||
*/
|
||||
public void export(OutputStream output) throws IOException {
|
||||
@Override
|
||||
public void export(OutputStream output) throws IOException {
|
||||
if (!documentPrepared) {
|
||||
prepareDocument();
|
||||
}
|
||||
@@ -242,7 +264,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* @param data the binary data of the file/attachment
|
||||
* @throws java.io.IOException if anything is wrong with filename
|
||||
*/
|
||||
public void PDFAttachGenericFile(String filename, String relationship, String description,
|
||||
@Override
|
||||
public void PDFAttachGenericFile(String filename, String relationship, String description,
|
||||
String subType, byte[] data) throws IOException {
|
||||
PDFAttachGenericFile(this.doc, filename, relationship, description, subType, data);
|
||||
}
|
||||
@@ -259,7 +282,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* @param data the binary data of the file/attachment
|
||||
* @throws IOException if anything is wrong with filename
|
||||
*/
|
||||
public void PDFAttachGenericFile(PDDocument doc, String filename, String relationship, String description,
|
||||
@Override
|
||||
public void PDFAttachGenericFile(PDDocument doc, String filename, String relationship, String description,
|
||||
String subType, byte[] data) throws IOException {
|
||||
fileAttached = true;
|
||||
|
||||
@@ -278,7 +302,7 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
ef.setSize(data.length);
|
||||
ef.setCreationDate(new GregorianCalendar());
|
||||
|
||||
ef.setModDate(GregorianCalendar.getInstance());
|
||||
ef.setModDate(Calendar.getInstance());
|
||||
|
||||
fs.setEmbeddedFile(ef);
|
||||
|
||||
@@ -310,7 +334,7 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
doc.getDocumentCatalog().setNames(names);
|
||||
|
||||
// AF entry (Array) in catalog with the FileSpec
|
||||
COSBase AFEntry = (COSBase) doc.getDocumentCatalog().getCOSObject().getItem("AF");
|
||||
COSBase AFEntry = doc.getDocumentCatalog().getCOSObject().getItem("AF");
|
||||
if ((AFEntry == null)) {
|
||||
COSArray cosArray = new COSArray();
|
||||
cosArray.add(fs);
|
||||
@@ -336,7 +360,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* @param zugferdData XML data to be set as a byte array (XML file in raw form).
|
||||
* @throws IOException (should not happen)
|
||||
*/
|
||||
public OXExporterFromA3 setXML(byte[] zugferdData) throws IOException {
|
||||
@Override
|
||||
public OXExporterFromA3 setXML(byte[] zugferdData) throws IOException {
|
||||
CustomXMLProvider cus = new CustomXMLProvider();
|
||||
cus.setXML(zugferdData);
|
||||
this.setXMLProvider(cus);
|
||||
@@ -351,11 +376,13 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
*
|
||||
* @param pdfSource source to read a PDF/A1 compliant document from
|
||||
*/
|
||||
public OXExporterFromA3 load(InputStream pdfSource) throws IOException {
|
||||
@Override
|
||||
public OXExporterFromA3 load(InputStream pdfSource) throws IOException {
|
||||
return load(readAllBytes(pdfSource));
|
||||
}
|
||||
|
||||
public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException {
|
||||
@Override
|
||||
public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -378,23 +405,27 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* <p>
|
||||
* Feel free to pass "A" as new level if you know what you are doing :-)
|
||||
*/
|
||||
public OXExporterFromA3 setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||
@Override
|
||||
public OXExporterFromA3 setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||
conformanceLevel = newLevel;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public OXExporterFromA3 setCreator(String creator) {
|
||||
@Override
|
||||
public OXExporterFromA3 setCreator(String creator) {
|
||||
this.creator = creator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OXExporterFromA3 setCreatorTool(String creatorTool) {
|
||||
@Override
|
||||
public OXExporterFromA3 setCreatorTool(String creatorTool) {
|
||||
this.creatorTool = creatorTool;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OXExporterFromA3 setProducer(String producer) {
|
||||
@Override
|
||||
public OXExporterFromA3 setProducer(String producer) {
|
||||
this.producer = producer;
|
||||
return this;
|
||||
}
|
||||
@@ -413,7 +444,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return this;
|
||||
}
|
||||
|
||||
protected OXExporterFromA3 setAttachZUGFeRDHeaders(boolean attachHeaders) {
|
||||
@Override
|
||||
protected OXExporterFromA3 setAttachZUGFeRDHeaders(boolean attachHeaders) {
|
||||
this.attachZUGFeRDHeaders = attachHeaders;
|
||||
return this;
|
||||
}
|
||||
@@ -426,7 +458,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
*
|
||||
* @param metadata the PDFbox XMPMetadata object
|
||||
*/
|
||||
protected void addXMP(XMPMetadata metadata) {
|
||||
@Override
|
||||
protected void addXMP(XMPMetadata metadata) {
|
||||
|
||||
if (attachZUGFeRDHeaders) {
|
||||
XMPSchemaZugferd zf = new XMPSchemaZugferd(metadata, 1, true, xmlProvider.getProfile(),
|
||||
@@ -453,12 +486,14 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* <code>setZUGFeRDXMLData(byte[] zugferdData)</code>
|
||||
* @throws IOException if anything is wrong with already loaded PDF
|
||||
*/
|
||||
public IExporter setTransaction(IExportableTransaction trans) throws IOException {
|
||||
@Override
|
||||
public IExporter setTransaction(IExportableTransaction trans) throws IOException {
|
||||
this.trans = trans;
|
||||
return prepare();
|
||||
}
|
||||
|
||||
public IExporter prepare() throws IOException {
|
||||
@Override
|
||||
public IExporter prepare() throws IOException {
|
||||
prepareDocument();
|
||||
xmlProvider.generateXML(trans);
|
||||
String filename = "order-x.xml";
|
||||
@@ -477,7 +512,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* Reads the XMPMetadata from the PDDocument, if it exists.
|
||||
* Otherwise creates XMPMetadata.
|
||||
*/
|
||||
protected XMPMetadata getXmpMetadata() throws IOException {
|
||||
@Override
|
||||
protected XMPMetadata getXmpMetadata() throws IOException {
|
||||
PDMetadata meta = doc.getDocumentCatalog().getMetadata();
|
||||
if ((meta != null) && (meta.getLength() > 0)) {
|
||||
try {
|
||||
@@ -490,7 +526,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return XMPMetadata.createXMPMetadata();
|
||||
}
|
||||
|
||||
protected byte[] serializeXmpMetadata(XMPMetadata xmpMetadata) throws TransformerException {
|
||||
@Override
|
||||
protected byte[] serializeXmpMetadata(XMPMetadata xmpMetadata) throws TransformerException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
new XmpSerializer().serialize(xmpMetadata, buffer, true); // see https://github.com/ZUGFeRD/mustangproject/issues/44
|
||||
return buffer.toByteArray();
|
||||
@@ -500,7 +537,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* Sets the producer if the overwrite flag is set or the producer is not already set.
|
||||
* Sets the PDFVersion to 1.4 if the field is empty.
|
||||
*/
|
||||
protected void writeAdobePDFSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected void writeAdobePDFSchema(XMPMetadata xmp) {
|
||||
AdobePDFSchema pdf = getAdobePDFSchema(xmp);
|
||||
if (overwrite || isEmpty(pdf.getProducer()))
|
||||
pdf.setProducer(producer);
|
||||
@@ -510,7 +548,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
* Returns the AdobePDFSchema from the XMPMetadata if it exists.
|
||||
* If the overwrite flag is set or no AdobePDFSchema exists in the XMPMetadata, it is created, added and returned.
|
||||
*/
|
||||
protected AdobePDFSchema getAdobePDFSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected AdobePDFSchema getAdobePDFSchema(XMPMetadata xmp) {
|
||||
AdobePDFSchema pdf = xmp.getAdobePDFSchema();
|
||||
if (pdf != null)
|
||||
if (overwrite)
|
||||
@@ -520,7 +559,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return xmp.createAndAddAdobePDFSchema();
|
||||
}
|
||||
|
||||
protected void writePDFAIdentificationSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected void writePDFAIdentificationSchema(XMPMetadata xmp) {
|
||||
PDFAIdentificationSchema pdfaid = getPDFAIdentificationSchema(xmp);
|
||||
if (overwrite || isEmpty(pdfaid.getConformance())) {
|
||||
try {
|
||||
@@ -535,17 +575,19 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
pdfaid.setPart(3);
|
||||
}
|
||||
|
||||
protected PDFAIdentificationSchema getPDFAIdentificationSchema(XMPMetadata xmp) {
|
||||
PDFAIdentificationSchema pdfaid = xmp.getPDFIdentificationSchema();
|
||||
@Override
|
||||
protected PDFAIdentificationSchema getPDFAIdentificationSchema(XMPMetadata xmp) {
|
||||
PDFAIdentificationSchema pdfaid = xmp.getPDFAIdentificationSchema();
|
||||
if (pdfaid != null)
|
||||
if (overwrite)
|
||||
xmp.removeSchema(pdfaid);
|
||||
else
|
||||
return pdfaid;
|
||||
return xmp.createAndAddPFAIdentificationSchema();
|
||||
return xmp.createAndAddPDFAIdentificationSchema();
|
||||
}
|
||||
|
||||
protected void writeDublinCoreSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected void writeDublinCoreSchema(XMPMetadata xmp) {
|
||||
DublinCoreSchema dc = getDublinCoreSchema(xmp);
|
||||
if (dc.getFormat() == null)
|
||||
dc.setFormat("application/pdf");
|
||||
@@ -568,7 +610,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
}
|
||||
}
|
||||
|
||||
protected DublinCoreSchema getDublinCoreSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected DublinCoreSchema getDublinCoreSchema(XMPMetadata xmp) {
|
||||
DublinCoreSchema dc = xmp.getDublinCoreSchema();
|
||||
if (dc != null)
|
||||
if (overwrite)
|
||||
@@ -578,15 +621,17 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return xmp.createAndAddDublinCoreSchema();
|
||||
}
|
||||
|
||||
protected void writeXMLBasicSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected void writeXMLBasicSchema(XMPMetadata xmp) {
|
||||
XMPBasicSchema xsb = getXmpBasicSchema(xmp);
|
||||
if (overwrite || isEmpty(xsb.getCreatorTool()) || "UnknownApplication".equals(xsb.getCreatorTool()))
|
||||
xsb.setCreatorTool(creatorTool);
|
||||
if (overwrite || xsb.getCreateDate() == null)
|
||||
xsb.setCreateDate(GregorianCalendar.getInstance());
|
||||
xsb.setCreateDate(Calendar.getInstance());
|
||||
}
|
||||
|
||||
protected XMPBasicSchema getXmpBasicSchema(XMPMetadata xmp) {
|
||||
@Override
|
||||
protected XMPBasicSchema getXmpBasicSchema(XMPMetadata xmp) {
|
||||
XMPBasicSchema xsb = xmp.getXMPBasicSchema();
|
||||
if (xsb != null)
|
||||
if (overwrite)
|
||||
@@ -596,7 +641,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return xmp.createAndAddXMPBasicSchema();
|
||||
}
|
||||
|
||||
protected void writeDocumentInformation() {
|
||||
@Override
|
||||
protected void writeDocumentInformation() {
|
||||
String fullProducer = producer + " (via mustangproject.org " + Version.VERSION + ")";
|
||||
PDDocumentInformation info = doc.getDocumentInformation();
|
||||
if (overwrite || info.getCreationDate() == null)
|
||||
@@ -618,7 +664,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
/**
|
||||
* Adds an OutputIntent and the sRGB color profile if no OutputIntent exist
|
||||
*/
|
||||
protected void addSRGBOutputIntend() throws IOException {
|
||||
@Override
|
||||
protected void addSRGBOutputIntend() throws IOException {
|
||||
if (!doc.getDocumentCatalog().getOutputIntents().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -641,7 +688,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
/**
|
||||
* Adds a MarkInfo element to the PDF if it doesn't already exist and sets it as marked.
|
||||
*/
|
||||
protected void setMarked() {
|
||||
@Override
|
||||
protected void setMarked() {
|
||||
PDDocumentCatalog catalog = doc.getDocumentCatalog();
|
||||
if (catalog.getMarkInfo() == null) {
|
||||
catalog.setMarkInfo(new PDMarkInfo(doc.getPages().getCOSObject()));
|
||||
@@ -652,7 +700,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
/**
|
||||
* Adds a StructureTreeRoot element to the PDF if it doesn't already exist.
|
||||
*/
|
||||
protected void addStructureTreeRoot() {
|
||||
@Override
|
||||
protected void addStructureTreeRoot() {
|
||||
if (doc.getDocumentCatalog().getStructureTreeRoot() == null) {
|
||||
doc.getDocumentCatalog().setStructureTreeRoot(new PDStructureTreeRoot());
|
||||
}
|
||||
@@ -662,19 +711,22 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
/**
|
||||
* @return if pdf file will be automatically closed after adding ZF
|
||||
*/
|
||||
public boolean isAutoCloseDisabled() {
|
||||
@Override
|
||||
public boolean isAutoCloseDisabled() {
|
||||
return disableAutoClose;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param disableAutoClose prevent PDF file from being closed after adding ZF
|
||||
*/
|
||||
public OXExporterFromA3 disableAutoClose(boolean disableAutoClose) {
|
||||
@Override
|
||||
public OXExporterFromA3 disableAutoClose(boolean disableAutoClose) {
|
||||
this.disableAutoClose = disableAutoClose;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void setXMLProvider(IXMLProvider p) {
|
||||
@Override
|
||||
protected void setXMLProvider(IXMLProvider p) {
|
||||
this.xmlProvider = p;
|
||||
if (profile != null) {
|
||||
xmlProvider.setProfile(profile);
|
||||
|
||||
@@ -22,26 +22,19 @@ package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import static org.mustangproject.ZUGFeRD.ZUGFeRDDateFormat.DATE;
|
||||
import static org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants.CORRECTEDINVOICE;
|
||||
import static org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants.CATEGORY_CODES_WITH_EXEMPTION_REASON;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.mustangproject.EStandard;
|
||||
import org.mustangproject.FileAttachment;
|
||||
import org.mustangproject.IncludedNote;
|
||||
import org.mustangproject.XMLTools;
|
||||
|
||||
public class OXPullProvider extends ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
public class OXPullProvider extends ZUGFeRD2PullProvider {
|
||||
|
||||
protected IExportableTransaction trans;
|
||||
protected TransactionCalculator calc;
|
||||
@@ -333,17 +326,19 @@ public class OXPullProvider extends ZUGFeRD2PullProvider implements IXMLProvider
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((trans.getDocumentCode() == CORRECTEDINVOICE)/*||(trans.getDocumentCode() == DocumentCodeTypeConstants.CREDITNOTE)*/) {
|
||||
hasDueDate = false;
|
||||
if (trans.getDocumentCode() != null) {
|
||||
if ((trans.getDocumentCode().equals(CORRECTEDINVOICE))/*||(trans.getDocumentCode().equals (DocumentCodeTypeConstants.CREDITNOTE))*/) {
|
||||
hasDueDate = false;
|
||||
}
|
||||
}
|
||||
|
||||
final Map<BigDecimal, VATAmount> VATPercentAmountMap = calc.getVATPercentAmountMap();
|
||||
for (final BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) {
|
||||
final VATAmount amount = VATPercentAmountMap.get(currentTaxPercent);
|
||||
if (amount != null) {
|
||||
final String amountCategoryCode = amount.getCategoryCode();
|
||||
/*final String amountCategoryCode = amount.getCategoryCode();
|
||||
final boolean displayExemptionReason = CATEGORY_CODES_WITH_EXEMPTION_REASON.contains(amountCategoryCode);
|
||||
/* xml += "<ram:ApplicableTradeTax>\n"
|
||||
xml += "<ram:ApplicableTradeTax>\n"
|
||||
+ "<ram:CalculatedAmount>" + currencyFormat(amount.getCalculated())
|
||||
+ "</ram:CalculatedAmount>\n" //currencyID=\"EUR\"
|
||||
+ "<ram:TypeCode>VAT</ram:TypeCode>\n"
|
||||
@@ -479,13 +474,9 @@ public class OXPullProvider extends ZUGFeRD2PullProvider implements IXMLProvider
|
||||
+ "</rsm:SCRDMCCBDACIOMessageStructure>";
|
||||
|
||||
final byte[] zugferdRaw;
|
||||
try {
|
||||
zugferdRaw = xml.getBytes("UTF-8");
|
||||
zugferdRaw = xml.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
zugferdData = XMLTools.removeBOM(zugferdRaw);
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
Logger.getLogger(OXPullProvider.class.getName()).log(Level.SEVERE, null, e);
|
||||
}
|
||||
zugferdData = XMLTools.removeBOM(zugferdRaw);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.pdfbox.io.IOUtils;
|
||||
import org.apache.pdfbox.preflight.parser.PreflightParser;
|
||||
|
||||
import jakarta.activation.DataSource;
|
||||
|
||||
// Copied from PDFBox preflight 2.0.x
|
||||
final class ByteArrayDataSource implements DataSource
|
||||
{
|
||||
private ByteArrayOutputStream data;
|
||||
private String type = null;
|
||||
private String name = null;
|
||||
|
||||
public ByteArrayDataSource (InputStream is) throws IOException
|
||||
{
|
||||
data = new ByteArrayOutputStream ();
|
||||
IOUtils.copy (is, data);
|
||||
IOUtils.closeQuietly (is);
|
||||
}
|
||||
|
||||
public String getContentType ()
|
||||
{
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* the type to set
|
||||
*/
|
||||
public void setType (String type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name to set
|
||||
*/
|
||||
public void setName (String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public InputStream getInputStream () throws IOException
|
||||
{
|
||||
return new ByteArrayInputStream (data.toByteArray ());
|
||||
}
|
||||
|
||||
public String getName ()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream () throws IOException
|
||||
{
|
||||
this.data = new ByteArrayOutputStream ();
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to create an API similar to the 2.x one
|
||||
final class PreflightParserHelper
|
||||
{
|
||||
private static File createTmpFile (InputStream input) throws IOException
|
||||
{
|
||||
FileOutputStream fos = null;
|
||||
try
|
||||
{
|
||||
File tmpFile = File.createTempFile ("mustang-pdf", ".pdf");
|
||||
fos = new FileOutputStream (tmpFile);
|
||||
IOUtils.copy (input, fos);
|
||||
return tmpFile;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtils.closeQuietly (input);
|
||||
IOUtils.closeQuietly (fos);
|
||||
}
|
||||
}
|
||||
|
||||
public static PreflightParser createPreflightParser (DataSource dataSource) throws IOException
|
||||
{
|
||||
return new PreflightParser (createTmpFile (dataSource.getInputStream ()));
|
||||
}
|
||||
}
|
||||
|
||||
final class PDFBoxUpdateMitigation
|
||||
{
|
||||
// Dummy for the name only
|
||||
}
|
||||
@@ -20,12 +20,12 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import org.mustangproject.EStandard;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.mustangproject.EStandard;
|
||||
|
||||
public class Profiles {
|
||||
static Map<String, Profile> zf2Map = Stream.of(new Object[][]{
|
||||
{"MINIMUM", new Profile("MINIMUM", "urn:factur-x.eu:1p0:minimum")},
|
||||
|
||||
@@ -20,33 +20,23 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.DocumentHelper;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.mustangproject.EStandard;
|
||||
import org.mustangproject.FileAttachment;
|
||||
import org.mustangproject.TradeParty;
|
||||
import org.mustangproject.XMLTools;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.mustangproject.ZUGFeRD.ZUGFeRDDateFormat.DATE;
|
||||
import static org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants.CORRECTEDINVOICE;
|
||||
import static org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants.CATEGORY_CODES_WITH_EXEMPTION_REASON;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class UBLDAPullProvider implements IXMLProvider {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger (UBLDAPullProvider.class);
|
||||
|
||||
protected IExportableTransaction trans;
|
||||
protected TransactionCalculator calc;
|
||||
@@ -96,13 +86,9 @@ public class UBLDAPullProvider implements IXMLProvider {
|
||||
}
|
||||
xml += "</DespatchAdvice>\n";
|
||||
final byte[] ublRaw;
|
||||
try {
|
||||
ublRaw = xml.getBytes("UTF-8");
|
||||
ublRaw = xml.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
ublData = XMLTools.removeBOM(ublRaw);
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
Logger.getLogger(UBLDAPullProvider.class.getName()).log(Level.SEVERE, null, e);
|
||||
}
|
||||
ublData = XMLTools.removeBOM(ublRaw);
|
||||
}
|
||||
|
||||
public String getPartyXML(IZUGFeRDExportableTradeParty tp) {
|
||||
@@ -133,7 +119,7 @@ public class UBLDAPullProvider implements IXMLProvider {
|
||||
try {
|
||||
document = DocumentHelper.parseText(new String(ublData));
|
||||
} catch (final DocumentException e1) {
|
||||
Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e1);
|
||||
LOGGER.error ("Failed to parse UBL", e1);
|
||||
}
|
||||
try {
|
||||
final OutputFormat format = OutputFormat.createPrettyPrint();
|
||||
@@ -143,7 +129,7 @@ public class UBLDAPullProvider implements IXMLProvider {
|
||||
res = sw.toString().getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
} catch (final IOException e) {
|
||||
Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e);
|
||||
LOGGER.error ("Failed to write XML", e);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import javax.xml.transform.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Templates;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.URIResolver;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.*;
|
||||
|
||||
|
||||
/***
|
||||
@@ -31,9 +42,8 @@ public class XMLUpgrader {
|
||||
* @return String the updated XML
|
||||
* @throws FileNotFoundException if the source could not be found
|
||||
* @throws TransformerException if the source could not be transformed
|
||||
* @throws UnsupportedEncodingException if the source was not utf8
|
||||
*/
|
||||
public String migrateFromV1ToV2(String xmlFilename) throws FileNotFoundException, TransformerException, UnsupportedEncodingException {
|
||||
public String migrateFromV1ToV2(String xmlFilename) throws FileNotFoundException, TransformerException {
|
||||
/**
|
||||
* *
|
||||
* http://www.unece.org/fileadmin/DAM/cefact/xml/XML-Naming-And-Design-Rules-V2_1.pdf
|
||||
@@ -45,7 +55,7 @@ public class XMLUpgrader {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
applySchematronXsl(new FileInputStream(xmlFilename), baos);
|
||||
String res = null;
|
||||
res = baos.toString("UTF-8");
|
||||
res = baos.toString(StandardCharsets.UTF_8);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,15 @@ package org.mustangproject.ZUGFeRD;
|
||||
import org.apache.xmpbox.XMPMetadata;
|
||||
import org.apache.xmpbox.XmpConstants;
|
||||
import org.apache.xmpbox.schema.PDFAExtensionSchema;
|
||||
import org.apache.xmpbox.type.*;
|
||||
import org.apache.xmpbox.type.ArrayProperty;
|
||||
import org.apache.xmpbox.type.Attribute;
|
||||
import org.apache.xmpbox.type.Cardinality;
|
||||
import org.apache.xmpbox.type.ChoiceType;
|
||||
import org.apache.xmpbox.type.DefinedStructuredType;
|
||||
import org.apache.xmpbox.type.PDFAPropertyType;
|
||||
import org.apache.xmpbox.type.PDFASchemaType;
|
||||
import org.apache.xmpbox.type.StructuredType;
|
||||
import org.apache.xmpbox.type.TextType;
|
||||
import org.mustangproject.EStandard;
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,31 +20,10 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import org.apache.pdfbox.cos.*;
|
||||
import org.apache.pdfbox.io.IOUtils;
|
||||
import org.apache.pdfbox.pdmodel.*;
|
||||
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
||||
import org.apache.pdfbox.preflight.PreflightDocument;
|
||||
import org.apache.pdfbox.preflight.exception.ValidationException;
|
||||
import org.apache.pdfbox.preflight.parser.PreflightParser;
|
||||
import org.apache.pdfbox.preflight.utils.ByteArrayDataSource;
|
||||
import org.apache.xmpbox.XMPMetadata;
|
||||
import org.apache.xmpbox.schema.AdobePDFSchema;
|
||||
import org.apache.xmpbox.schema.DublinCoreSchema;
|
||||
import org.apache.xmpbox.schema.PDFAIdentificationSchema;
|
||||
import org.apache.xmpbox.schema.XMPBasicSchema;
|
||||
import org.apache.xmpbox.type.BadFieldValueException;
|
||||
import org.apache.xmpbox.xml.XmpSerializer;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import javax.activation.FileDataSource;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.io.*;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class XRExporter implements IExporter {
|
||||
IXMLProvider xmlProvider;
|
||||
|
||||
@@ -1,21 +1,54 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.mustangproject.XMLTools;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class XRechnungImporter extends ZUGFeRDImporter {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger (XRechnungImporter.class);
|
||||
|
||||
public XRechnungImporter(byte[] rawXml) {
|
||||
super();
|
||||
public XRechnungImporter(byte[] rawXml) {
|
||||
super();
|
||||
|
||||
try {
|
||||
setRawXML(rawXml);
|
||||
containsMeta = true;
|
||||
} catch (final IOException e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
throw new ZUGFeRDExportException(e);
|
||||
try {
|
||||
setRawXML(rawXml);
|
||||
containsMeta = true;
|
||||
} catch (final IOException e) {
|
||||
LOGGER.error ("Failed to set raw XML", e);
|
||||
throw new ZUGFeRDExportException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public XRechnungImporter(String filename) {
|
||||
super();
|
||||
|
||||
try {
|
||||
setRawXML(Files.readAllBytes(Paths.get(filename)));
|
||||
containsMeta = true;
|
||||
} catch (final IOException e) {
|
||||
LOGGER.error ("Failed to set raw XML", e);
|
||||
throw new ZUGFeRDExportException(e);
|
||||
}
|
||||
|
||||
}
|
||||
public XRechnungImporter(InputStream fileinput) {
|
||||
super();
|
||||
|
||||
try {
|
||||
setRawXML(XMLTools.getBytesFromStream(fileinput));
|
||||
containsMeta = true;
|
||||
} catch (final IOException e) {
|
||||
LOGGER.error ("Failed to set raw XML", e);
|
||||
throw new ZUGFeRDExportException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
@@ -39,9 +37,11 @@ import org.dom4j.DocumentHelper;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.mustangproject.XMLTools;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
|
||||
public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger (ZUGFeRD1PullProvider.class);
|
||||
|
||||
//// MAIN CLASS
|
||||
|
||||
@@ -93,17 +93,17 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
|
||||
try {
|
||||
document = DocumentHelper.parseText(new String(zugferdData));
|
||||
} catch (final DocumentException e1) {
|
||||
Logger.getLogger(ZUGFeRD1PullProvider.class.getName()).log(Level.SEVERE, null, e1);
|
||||
LOGGER.error ("Failed to parse ZUGFeRD data", e1);
|
||||
}
|
||||
try {
|
||||
final OutputFormat format = OutputFormat.createPrettyPrint();
|
||||
format.setTrimText(false);
|
||||
final XMLWriter writer = new XMLWriter(sw, format);
|
||||
writer.write(document);
|
||||
res = sw.toString().getBytes("UTF-8");
|
||||
res = sw.toString().getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
} catch (final IOException e) {
|
||||
Logger.getLogger(ZUGFeRD1PullProvider.class.getName()).log(Level.SEVERE, null, e);
|
||||
LOGGER.error ("Failed to write ZUGFeRD data", e);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -25,7 +25,6 @@ import static org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants.CATE
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -35,9 +34,8 @@ import java.util.Base64;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.dom4j.Document;
|
||||
@@ -49,8 +47,11 @@ import org.mustangproject.FileAttachment;
|
||||
import org.mustangproject.IncludedNote;
|
||||
import org.mustangproject.XMLTools;
|
||||
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger (ZUGFeRD2PullProvider.class);
|
||||
|
||||
protected byte[] zugferdData;
|
||||
protected IExportableTransaction trans;
|
||||
@@ -92,7 +93,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
try {
|
||||
document = DocumentHelper.parseText(new String(zugferdData));
|
||||
} catch (final DocumentException e1) {
|
||||
Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e1);
|
||||
LOGGER.error ("Failed to parse ZUGFeRD data", e1);
|
||||
}
|
||||
try {
|
||||
final OutputFormat format = OutputFormat.createPrettyPrint();
|
||||
@@ -102,7 +103,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
res = sw.toString().getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
} catch (final IOException e) {
|
||||
Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e);
|
||||
LOGGER.error ("Failed to write ZUGFeRD data", e);
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -290,11 +291,21 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
paymentTermsDescription = XMLTools.encodeXML(trans.getPaymentTermDescription());
|
||||
}
|
||||
|
||||
if ((paymentTermsDescription == null) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CORRECTEDINVOICE) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE)) {
|
||||
paymentTermsDescription = "Zahlbar ohne Abzug bis " + germanDateFormat.format(trans.getDueDate());
|
||||
|
||||
if ((profile == Profiles.getByName("XRechnung")) && (trans.getCashDiscounts() != null) && (trans.getCashDiscounts().length > 0)) {
|
||||
for (IZUGFeRDCashDiscount discount : trans.getCashDiscounts()
|
||||
) {
|
||||
if (paymentTermsDescription == null) {
|
||||
paymentTermsDescription = "";
|
||||
}
|
||||
paymentTermsDescription += discount.getAsXRechnung();
|
||||
}
|
||||
} else if ((paymentTermsDescription == null) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CORRECTEDINVOICE) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE)) {
|
||||
paymentTermsDescription = "Please remit until " + germanDateFormat.format(trans.getDueDate());
|
||||
|
||||
}
|
||||
|
||||
|
||||
String typecode = "380";
|
||||
if (trans.getDocumentCode() != null) {
|
||||
typecode = trans.getDocumentCode();
|
||||
@@ -387,6 +398,19 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
XMLTools.encodeXML(currentItem.getProduct().getDescription()) +
|
||||
"</ram:Description>";
|
||||
}
|
||||
if (currentItem.getProduct().getAttributes() != null) {
|
||||
for ( Entry<String, String> entry : currentItem.getProduct().getAttributes().entrySet() ) {
|
||||
xml += "<ram:ApplicableProductCharacteristic>" +
|
||||
"<ram:Description>" + XMLTools.encodeXML(entry.getKey()) + "</ram:Description>" +
|
||||
"<ram:Value>" + XMLTools.encodeXML(entry.getValue()) + "</ram:Value>" +
|
||||
"</ram:ApplicableProductCharacteristic>";
|
||||
}
|
||||
}
|
||||
if (currentItem.getProduct().getCountryOfOrigin() != null) {
|
||||
xml += "<ram:OriginTradeCountry><ram:ID>" +
|
||||
XMLTools.encodeXML(currentItem.getProduct().getCountryOfOrigin()) +
|
||||
"</ram:ID></ram:OriginTradeCountry>";
|
||||
}
|
||||
xml += "</ram:SpecifiedTradeProduct>"
|
||||
|
||||
+ "<ram:SpecifiedLineTradeAgreement>";
|
||||
@@ -404,19 +428,23 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
+ "<ram:LineID>" + XMLTools.encodeXML(currentItem.getBuyerOrderReferencedDocumentLineID()) + "</ram:LineID>"
|
||||
+ "</ram:BuyerOrderReferencedDocument>";
|
||||
}
|
||||
xml += "<ram:GrossPriceProductTradePrice>"
|
||||
+ "<ram:ChargeAmount>" + priceFormat(lc.getPriceGross())
|
||||
+ "</ram:ChargeAmount>" //currencyID=\"EUR\"
|
||||
+ "<ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit())
|
||||
+ "\">" + quantityFormat(currentItem.getBasisQuantity()) + "</ram:BasisQuantity>"
|
||||
+ allowanceChargeStr
|
||||
// + " <AppliedTradeAllowanceCharge>"
|
||||
// + " <ChargeIndicator>false</ChargeIndicator>"
|
||||
// + " <ActualAmount currencyID=\"EUR\">0.6667</ActualAmount>"
|
||||
// + " <Reason>Rabatt</Reason>"
|
||||
// + " </AppliedTradeAllowanceCharge>"
|
||||
+ "</ram:GrossPriceProductTradePrice>"
|
||||
+ "<ram:NetPriceProductTradePrice>"
|
||||
|
||||
if (!allowanceChargeStr.isEmpty()) {
|
||||
xml += "<ram:GrossPriceProductTradePrice>"
|
||||
+ "<ram:ChargeAmount>" + priceFormat(lc.getPriceGross())
|
||||
+ "</ram:ChargeAmount>" //currencyID=\"EUR\"
|
||||
+ "<ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit())
|
||||
+ "\">" + quantityFormat(currentItem.getBasisQuantity()) + "</ram:BasisQuantity>"
|
||||
+ allowanceChargeStr
|
||||
// + " <AppliedTradeAllowanceCharge>"
|
||||
// + " <ChargeIndicator>false</ChargeIndicator>"
|
||||
// + " <ActualAmount currencyID=\"EUR\">0.6667</ActualAmount>"
|
||||
// + " <Reason>Rabatt</Reason>"
|
||||
// + " </AppliedTradeAllowanceCharge>"
|
||||
+ "</ram:GrossPriceProductTradePrice>";
|
||||
}
|
||||
|
||||
xml += "<ram:NetPriceProductTradePrice>"
|
||||
+ "<ram:ChargeAmount>" + priceFormat(lc.getPrice())
|
||||
+ "</ram:ChargeAmount>" // currencyID=\"EUR\"
|
||||
+ "<ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit())
|
||||
@@ -536,10 +564,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
xml += "</ram:OccurrenceDateTime>";
|
||||
xml += " </ram:ActualDeliverySupplyChainEvent>";
|
||||
|
||||
} else {
|
||||
if ((trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE) && (getProfile() != Profiles.getByName("Minimum"))) {
|
||||
throw new IllegalStateException("No delivery date provided");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* + "<DeliveryNoteReferencedDocument>" +
|
||||
@@ -685,6 +709,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
} else {
|
||||
xml += buildPaymentTermsXml();
|
||||
}
|
||||
if ((profile == Profiles.getByName("Extended")) && (trans.getCashDiscounts() != null) && (trans.getCashDiscounts().length > 0)) {
|
||||
for (IZUGFeRDCashDiscount discount : trans.getCashDiscounts()
|
||||
) {
|
||||
xml += discount.getAsCII();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final String allowanceTotalLine = "<ram:AllowanceTotalAmount>" + currencyFormat(calc.getAllowancesForPercent(null)) + "</ram:AllowanceTotalAmount>";
|
||||
@@ -736,13 +766,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
+ "</rsm:CrossIndustryInvoice>";
|
||||
|
||||
final byte[] zugferdRaw;
|
||||
try {
|
||||
zugferdRaw = xml.getBytes("UTF-8");
|
||||
zugferdRaw = xml.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
zugferdData = XMLTools.removeBOM(zugferdRaw);
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e);
|
||||
}
|
||||
zugferdData = XMLTools.removeBOM(zugferdRaw);
|
||||
}
|
||||
|
||||
protected String buildItemNotes(IZUGFeRDExportableItem currentItem) {
|
||||
|
||||
@@ -19,25 +19,21 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.pdfbox.preflight.PreflightDocument;
|
||||
import org.apache.pdfbox.preflight.ValidationResult;
|
||||
import org.apache.pdfbox.preflight.exception.ValidationException;
|
||||
import org.apache.pdfbox.preflight.parser.PreflightParser;
|
||||
import org.mustangproject.EStandard;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import jakarta.activation.DataSource;
|
||||
|
||||
public class ZUGFeRDExporterFromA1 extends ZUGFeRDExporterFromA3 implements IZUGFeRDExporter {
|
||||
protected boolean ignorePDFAErrors = false;
|
||||
|
||||
public ZUGFeRDExporterFromA1 ignorePDFAErrors() {
|
||||
this.ignorePDFAErrors = true;
|
||||
return this;
|
||||
}
|
||||
public class ZUGFeRDExporterFromA1 extends ZUGFeRDExporterFromA3 {
|
||||
|
||||
private static boolean isValidA1(DataSource dataSource) throws IOException {
|
||||
return getPDFAParserValidationResult(new PreflightParser(dataSource));
|
||||
return getPDFAParserValidationResult(PreflightParserHelper.createPreflightParser(dataSource));
|
||||
}
|
||||
|
||||
private static boolean getPDFAParserValidationResult(PreflightParser parser) throws IOException {
|
||||
@@ -46,19 +42,19 @@ public class ZUGFeRDExporterFromA1 extends ZUGFeRDExporterFromA3 implements IZUG
|
||||
* NonSequentialParser. Some additional controls are present to check a set of
|
||||
* PDF/A requirements. (Stream length consistency, EOL after some Keyword...)
|
||||
*/
|
||||
parser.parse();// might add a Format.PDF_A1A as parameter and iterate through A1 and A3
|
||||
// might add a Format.PDF_A1A as parameter and iterate through A1 and A3
|
||||
|
||||
try (PreflightDocument document = parser.getPreflightDocument()) {
|
||||
try (PreflightDocument document = (PreflightDocument) parser.parse()) {
|
||||
/*
|
||||
* Once the syntax validation is done, the parser can provide a
|
||||
* PreflightDocument (that inherits from PDDocument) This document process the
|
||||
* end of PDF/A validation.
|
||||
*/
|
||||
|
||||
document.validate();
|
||||
ValidationResult res = document.validate();
|
||||
|
||||
// Get validation result
|
||||
return document.getResult().isValid();
|
||||
return res.isValid();
|
||||
} catch (ValidationException e) {
|
||||
/*
|
||||
* the parse method can throw a SyntaxValidationException if the PDF file can't
|
||||
@@ -70,14 +66,17 @@ public class ZUGFeRDExporterFromA1 extends ZUGFeRDExporterFromA3 implements IZUG
|
||||
}
|
||||
|
||||
|
||||
public ZUGFeRDExporterFromA1 setProfile(Profile p) {
|
||||
@Override
|
||||
public ZUGFeRDExporterFromA1 setProfile(Profile p) {
|
||||
return (ZUGFeRDExporterFromA1)super.setProfile(p);
|
||||
}
|
||||
public ZUGFeRDExporterFromA1 setProfile(String profileName) {
|
||||
@Override
|
||||
public ZUGFeRDExporterFromA1 setProfile(String profileName) {
|
||||
return (ZUGFeRDExporterFromA1)super.setProfile(profileName);
|
||||
}
|
||||
|
||||
public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException {
|
||||
@Override
|
||||
public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException {
|
||||
if (!ignorePDFAErrors && !isValidA1(dataSource)) {
|
||||
throw new IOException("File is not a valid PDF/A-1 input file");
|
||||
}
|
||||
@@ -85,35 +84,45 @@ public class ZUGFeRDExporterFromA1 extends ZUGFeRDExporterFromA3 implements IZUG
|
||||
}
|
||||
|
||||
|
||||
public ZUGFeRDExporterFromA1 load(String pdfFilename) throws IOException {
|
||||
@Override
|
||||
public ZUGFeRDExporterFromA1 load(String pdfFilename) throws IOException {
|
||||
return (ZUGFeRDExporterFromA1) super.load(pdfFilename);
|
||||
}
|
||||
public ZUGFeRDExporterFromA1 load(byte[] pdfBinary) throws IOException {
|
||||
@Override
|
||||
public ZUGFeRDExporterFromA1 load(byte[] pdfBinary) throws IOException {
|
||||
return (ZUGFeRDExporterFromA1) super.load(pdfBinary);
|
||||
}
|
||||
public ZUGFeRDExporterFromA1 load(InputStream pdfSource) throws IOException{
|
||||
@Override
|
||||
public ZUGFeRDExporterFromA1 load(InputStream pdfSource) throws IOException{
|
||||
return (ZUGFeRDExporterFromA1) super.load(pdfSource);
|
||||
}
|
||||
public ZUGFeRDExporterFromA1 setCreator(String creator) {
|
||||
@Override
|
||||
public ZUGFeRDExporterFromA1 setCreator(String creator) {
|
||||
return (ZUGFeRDExporterFromA1) super.setCreator(creator);
|
||||
}
|
||||
public ZUGFeRDExporterFromA1 setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||
@Override
|
||||
public ZUGFeRDExporterFromA1 setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||
return (ZUGFeRDExporterFromA1) super.setConformanceLevel(newLevel);
|
||||
}
|
||||
public ZUGFeRDExporterFromA1 setProducer(String producer){
|
||||
@Override
|
||||
public ZUGFeRDExporterFromA1 setProducer(String producer){
|
||||
return (ZUGFeRDExporterFromA1) super.setProducer(producer);
|
||||
}
|
||||
public ZUGFeRDExporterFromA1 setZUGFeRDVersion(EStandard est, int version){
|
||||
@Override
|
||||
public ZUGFeRDExporterFromA1 setZUGFeRDVersion(EStandard est, int version){
|
||||
return (ZUGFeRDExporterFromA1) super.setZUGFeRDVersion(est, version);
|
||||
}
|
||||
public ZUGFeRDExporterFromA1 setZUGFeRDVersion(int version){
|
||||
@Override
|
||||
public ZUGFeRDExporterFromA1 setZUGFeRDVersion(int version){
|
||||
return (ZUGFeRDExporterFromA1) super.setZUGFeRDVersion(version);
|
||||
}
|
||||
public ZUGFeRDExporterFromA1 setXML(byte[] zugferdData) throws IOException{
|
||||
@Override
|
||||
public ZUGFeRDExporterFromA1 setXML(byte[] zugferdData) throws IOException{
|
||||
return (ZUGFeRDExporterFromA1) super.setXML(zugferdData);
|
||||
}
|
||||
|
||||
public ZUGFeRDExporterFromA1 disableAutoClose(boolean disableAutoClose){
|
||||
@Override
|
||||
public ZUGFeRDExporterFromA1 disableAutoClose(boolean disableAutoClose){
|
||||
return (ZUGFeRDExporterFromA1) super.disableAutoClose(disableAutoClose);
|
||||
}
|
||||
public ZUGFeRDExporterFromA1 convertOnly() {
|
||||
|
||||
@@ -20,9 +20,35 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import org.apache.pdfbox.cos.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.cos.COSArray;
|
||||
import org.apache.pdfbox.cos.COSBase;
|
||||
import org.apache.pdfbox.cos.COSDictionary;
|
||||
import org.apache.pdfbox.cos.COSName;
|
||||
import org.apache.pdfbox.cos.COSObject;
|
||||
import org.apache.pdfbox.io.IOUtils;
|
||||
import org.apache.pdfbox.pdmodel.*;
|
||||
import org.apache.pdfbox.pdfwriter.compress.CompressParameters;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
|
||||
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDResources;
|
||||
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
||||
@@ -33,7 +59,6 @@ import org.apache.pdfbox.pdmodel.font.PDFont;
|
||||
import org.apache.pdfbox.pdmodel.font.PDFontDescriptor;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType0Font;
|
||||
import org.apache.pdfbox.pdmodel.graphics.color.PDOutputIntent;
|
||||
import org.apache.pdfbox.preflight.utils.ByteArrayDataSource;
|
||||
import org.apache.xmpbox.XMPMetadata;
|
||||
import org.apache.xmpbox.schema.AdobePDFSchema;
|
||||
import org.apache.xmpbox.schema.DublinCoreSchema;
|
||||
@@ -47,19 +72,21 @@ import org.apache.xmpbox.xml.XmpSerializer;
|
||||
import org.mustangproject.EStandard;
|
||||
import org.mustangproject.FileAttachment;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import javax.activation.FileDataSource;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import jakarta.activation.DataSource;
|
||||
import jakarta.activation.FileDataSource;
|
||||
|
||||
public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporter, IExporter, Closeable {
|
||||
public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporter {
|
||||
private boolean isFacturX = true;
|
||||
|
||||
public static final int DefaultZUGFeRDVersion = 2;
|
||||
protected boolean ignorePDFAErrors = false;
|
||||
|
||||
public ZUGFeRDExporterFromA3 ignorePDFAErrors() {
|
||||
this.ignorePDFAErrors = true;
|
||||
return this;
|
||||
}
|
||||
protected PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE;
|
||||
protected ArrayList<FileAttachment> fileAttachments = new ArrayList<FileAttachment>();
|
||||
protected ArrayList<FileAttachment> fileAttachments = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* This flag controls whether or not the metadata is overwritten, or kind of merged.
|
||||
@@ -111,9 +138,6 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
|
||||
protected PDDocument doc;
|
||||
|
||||
private HashMap<String, byte[]> additionalXMLs = new HashMap<String, byte[]>();
|
||||
|
||||
|
||||
protected int ZFVersion = DefaultZUGFeRDVersion;
|
||||
private boolean attachZUGFeRDHeaders = true;
|
||||
|
||||
@@ -220,9 +244,10 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
* Generate ZF2.1 files with filename factur-x.xml
|
||||
*
|
||||
* @return this (fluent setter)
|
||||
* @deprecated
|
||||
* @deprecated It's now the default anyway
|
||||
*/
|
||||
public ZUGFeRDExporterFromA3 setFacturX() {
|
||||
@Deprecated
|
||||
public ZUGFeRDExporterFromA3 setFacturX() {
|
||||
isFacturX = true;
|
||||
return this;
|
||||
}
|
||||
@@ -258,7 +283,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
*/
|
||||
public ZUGFeRDExporterFromA3 load(byte[] pdfBinary) throws IOException {
|
||||
ensurePDFIsValid(new ByteArrayDataSource(new ByteArrayInputStream(pdfBinary)));
|
||||
doc = PDDocument.load(pdfBinary);
|
||||
doc = Loader.loadPDF(pdfBinary);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -282,7 +307,8 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
* @param ZUGFeRDfilename the pdf file name
|
||||
* @throws IOException if anything is wrong in the target location
|
||||
*/
|
||||
public void export(String ZUGFeRDfilename) throws IOException {
|
||||
@Override
|
||||
public void export(String ZUGFeRDfilename) throws IOException {
|
||||
if (!documentPrepared) {
|
||||
prepareDocument();
|
||||
}
|
||||
@@ -290,7 +316,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
throw new IOException(
|
||||
"File must be attached (usually with setTransaction) before perfoming this operation");
|
||||
}
|
||||
doc.save(ZUGFeRDfilename);
|
||||
doc.save(ZUGFeRDfilename, CompressParameters.NO_COMPRESSION);
|
||||
if (!disableAutoClose) {
|
||||
close();
|
||||
}
|
||||
@@ -309,7 +335,8 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
* @param output the OutputStream
|
||||
* @throws IOException if anything is wrong in the OutputStream
|
||||
*/
|
||||
public void export(OutputStream output) throws IOException {
|
||||
@Override
|
||||
public void export(OutputStream output) throws IOException {
|
||||
if (!documentPrepared) {
|
||||
prepareDocument();
|
||||
}
|
||||
@@ -317,7 +344,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
throw new IOException(
|
||||
"File must be attached (usually with setTransaction) before perfoming this operation");
|
||||
}
|
||||
doc.save(output);
|
||||
doc.save(output, CompressParameters.NO_COMPRESSION);
|
||||
if (!disableAutoClose) {
|
||||
close();
|
||||
}
|
||||
@@ -371,7 +398,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
ef.setSize(data.length);
|
||||
ef.setCreationDate(new GregorianCalendar());
|
||||
|
||||
ef.setModDate(GregorianCalendar.getInstance());
|
||||
ef.setModDate(Calendar.getInstance());
|
||||
|
||||
fs.setEmbeddedFile(ef);
|
||||
|
||||
@@ -403,7 +430,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
doc.getDocumentCatalog().setNames(names);
|
||||
|
||||
// AF entry (Array) in catalog with the FileSpec
|
||||
COSBase AFEntry = (COSBase) doc.getDocumentCatalog().getCOSObject().getItem("AF");
|
||||
COSBase AFEntry = doc.getDocumentCatalog().getCOSObject().getItem("AF");
|
||||
if ((AFEntry == null)) {
|
||||
COSArray cosArray = new COSArray();
|
||||
cosArray.add(fs);
|
||||
@@ -529,7 +556,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
metadata.addSchema(pdfaex);
|
||||
}
|
||||
|
||||
private void removeCidSet(PDDocumentCatalog catalog, PDDocument doc)
|
||||
private void removeCidSet(PDDocument doc)
|
||||
throws IOException
|
||||
{
|
||||
// https://github.com/ZUGFeRD/mustangproject/issues/249
|
||||
@@ -550,7 +577,8 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
PDType0Font typedFont = (PDType0Font) pdFont;
|
||||
|
||||
if (typedFont.getDescendantFont() instanceof PDCIDFontType2) {
|
||||
PDCIDFontType2 f = (PDCIDFontType2) typedFont.getDescendantFont();
|
||||
@SuppressWarnings ("unused")
|
||||
PDCIDFontType2 f = (PDCIDFontType2) typedFont.getDescendantFont();
|
||||
PDFontDescriptor fontDescriptor = pdFont.getFontDescriptor();
|
||||
|
||||
fontDescriptor.getCOSObject().removeItem(cidSet);
|
||||
@@ -571,7 +599,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
metadata = new PDMetadata(doc);
|
||||
cat.setMetadata(metadata);
|
||||
|
||||
removeCidSet(cat, doc);
|
||||
removeCidSet(doc);
|
||||
xmp = getXmpMetadata();
|
||||
writeAdobePDFSchema(xmp);
|
||||
writePDFAIdentificationSchema(xmp);
|
||||
@@ -608,7 +636,8 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
* <code>setZUGFeRDXMLData(byte[] zugferdData)</code>
|
||||
* @throws IOException if anything is wrong with already loaded PDF
|
||||
*/
|
||||
public IExporter setTransaction(IExportableTransaction trans) throws IOException {
|
||||
@Override
|
||||
public IExporter setTransaction(IExportableTransaction trans) throws IOException {
|
||||
this.trans = trans;
|
||||
return prepare();
|
||||
}
|
||||
@@ -713,13 +742,13 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
}
|
||||
|
||||
protected PDFAIdentificationSchema getPDFAIdentificationSchema(XMPMetadata xmp) {
|
||||
PDFAIdentificationSchema pdfaid = xmp.getPDFIdentificationSchema();
|
||||
PDFAIdentificationSchema pdfaid = xmp.getPDFAIdentificationSchema();
|
||||
if (pdfaid != null)
|
||||
if (overwrite)
|
||||
xmp.removeSchema(pdfaid);
|
||||
else
|
||||
return pdfaid;
|
||||
return xmp.createAndAddPFAIdentificationSchema();
|
||||
return xmp.createAndAddPDFAIdentificationSchema();
|
||||
}
|
||||
|
||||
protected void writeDublinCoreSchema(XMPMetadata xmp) {
|
||||
@@ -760,7 +789,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
if (overwrite || isEmpty(xsb.getCreatorTool()) || "UnknownApplication".equals(xsb.getCreatorTool()))
|
||||
xsb.setCreatorTool(creatorTool);
|
||||
if (overwrite || xsb.getCreateDate() == null)
|
||||
xsb.setCreateDate(GregorianCalendar.getInstance());
|
||||
xsb.setCreateDate(Calendar.getInstance());
|
||||
}
|
||||
|
||||
protected XMPBasicSchema getXmpBasicSchema(XMPMetadata xmp) {
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
||||
@@ -30,8 +37,7 @@ import org.apache.xmpbox.xml.XmpParsingException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import java.io.*;
|
||||
import jakarta.activation.DataSource;
|
||||
|
||||
/***
|
||||
* Auto-detects the source PDF-A-Version and acts accordingly
|
||||
@@ -43,14 +49,28 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter {
|
||||
|
||||
protected IZUGFeRDExporter theExporter;
|
||||
|
||||
protected boolean ignorePDFAErrors = false;
|
||||
|
||||
public ZUGFeRDExporterFromPDFA ignorePDFAErrors() {
|
||||
this.ignorePDFAErrors = true;
|
||||
return this;
|
||||
}
|
||||
protected void determineAndSetExporter(int PDFAVersion) {
|
||||
if (PDFAVersion == 3) {
|
||||
theExporter = new ZUGFeRDExporterFromA3();
|
||||
if (ignorePDFAErrors) {
|
||||
((ZUGFeRDExporterFromA3)theExporter).ignorePDFAErrors();
|
||||
}
|
||||
} else if (PDFAVersion == 1) {
|
||||
theExporter = new ZUGFeRDExporterFromA1();
|
||||
if (ignorePDFAErrors) {
|
||||
((ZUGFeRDExporterFromA1)theExporter).ignorePDFAErrors();
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("PDF-A version not supported");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
protected IZUGFeRDExporter getExporter() {
|
||||
if (theExporter==null) {
|
||||
@@ -79,7 +99,7 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter {
|
||||
* @throws IOException
|
||||
*/
|
||||
private int getPDFAVersion(byte[] byteArrayInputStream) throws IOException {
|
||||
PDDocument document = PDDocument.load(byteArrayInputStream);
|
||||
PDDocument document = Loader.loadPDF(byteArrayInputStream);
|
||||
PDDocumentCatalog catalog = document.getDocumentCatalog();
|
||||
PDMetadata metadata = catalog.getMetadata();
|
||||
// the PDF version we could get through the document but we want the PDF-A version,
|
||||
@@ -89,7 +109,7 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter {
|
||||
DomXmpParser xmpParser = new DomXmpParser();
|
||||
XMPMetadata xmp = xmpParser.parse(metadata.createInputStream());
|
||||
|
||||
PDFAIdentificationSchema pdfaSchema = xmp.getPDFIdentificationSchema();
|
||||
PDFAIdentificationSchema pdfaSchema = xmp.getPDFAIdentificationSchema();
|
||||
if (pdfaSchema != null) {
|
||||
return pdfaSchema.getPart();
|
||||
}
|
||||
@@ -147,16 +167,16 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter {
|
||||
return getExporter().setCreator(creator);
|
||||
}
|
||||
|
||||
public ZUGFeRDExporterFromPDFA setProfile(Profile p) {
|
||||
return (ZUGFeRDExporterFromPDFA) getExporter().setProfile(p);
|
||||
public IZUGFeRDExporter setProfile(Profile p) {
|
||||
return getExporter().setProfile(p);
|
||||
}
|
||||
|
||||
public ZUGFeRDExporterFromPDFA setProfile(String profileName) {
|
||||
public IZUGFeRDExporter setProfile(String profileName) {
|
||||
Profile p = Profiles.getByName(profileName);
|
||||
if (p==null) {
|
||||
throw new RuntimeException("Profile not found.");
|
||||
}
|
||||
return (ZUGFeRDExporterFromPDFA) getExporter().setProfile(p);
|
||||
return getExporter().setProfile(p);
|
||||
}
|
||||
|
||||
public IZUGFeRDExporter setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||
|
||||
@@ -14,22 +14,19 @@ package org.mustangproject.ZUGFeRD;
|
||||
* @author jstaerk
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
@@ -40,6 +37,8 @@ import javax.xml.xpath.XPathExpression;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
|
||||
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
|
||||
@@ -49,12 +48,16 @@ import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
||||
import org.mustangproject.EStandard;
|
||||
import org.mustangproject.Item;
|
||||
import org.mustangproject.Product;
|
||||
import org.mustangproject.XMLTools;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class ZUGFeRDImporter {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger (ZUGFeRDImporter.class);
|
||||
|
||||
/**
|
||||
* if metadata has been found
|
||||
@@ -80,14 +83,14 @@ public class ZUGFeRDImporter {
|
||||
|
||||
|
||||
protected ZUGFeRDImporter() {
|
||||
//constructor for extending classes
|
||||
//constructor for extending classes
|
||||
}
|
||||
|
||||
|
||||
public ZUGFeRDImporter(String pdfFilename) {
|
||||
try (InputStream bis = Files.newInputStream(Paths.get(pdfFilename), StandardOpenOption.READ)) {
|
||||
extractLowLevel(bis);
|
||||
} catch (final IOException e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
LOGGER.error ("Failed to extract ZUGFeRD data", e);
|
||||
throw new ZUGFeRDExportException(e);
|
||||
}
|
||||
}
|
||||
@@ -97,7 +100,7 @@ public class ZUGFeRDImporter {
|
||||
try {
|
||||
extractLowLevel(pdfStream);
|
||||
} catch (final IOException e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
LOGGER.error ("Failed to extract ZUGFeRD data", e);
|
||||
throw new ZUGFeRDExportException(e);
|
||||
}
|
||||
}
|
||||
@@ -106,41 +109,59 @@ public class ZUGFeRDImporter {
|
||||
/**
|
||||
* Extracts a ZUGFeRD invoice from a PDF document represented by an input stream. Errors are reported via exception handling.
|
||||
*
|
||||
* @param pdfStream a inputstream of a pdf file
|
||||
* @param inStream a inputstream of a pdf file
|
||||
*/
|
||||
private void extractLowLevel(InputStream pdfStream) throws IOException {
|
||||
try (PDDocument doc = PDDocument.load(pdfStream)) {
|
||||
// PDDocumentInformation info = doc.getDocumentInformation();
|
||||
final PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog());
|
||||
//start
|
||||
private void extractLowLevel(InputStream inStream) throws IOException {
|
||||
BufferedInputStream pdfStream = new BufferedInputStream(inStream);
|
||||
byte[] pad = new byte[4];
|
||||
pdfStream.mark(0);
|
||||
pdfStream.read(pad);
|
||||
pdfStream.reset();
|
||||
byte[] pdfSignature = {'%', 'P', 'D', 'F'};
|
||||
if (Arrays.equals(pad, pdfSignature)) { // we have a pdf
|
||||
|
||||
if (doc.getDocumentCatalog() == null || doc.getDocumentCatalog().getMetadata() == null) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.INFO, "no-xmlpart");
|
||||
return;
|
||||
}
|
||||
|
||||
final InputStream XMP = doc.getDocumentCatalog().getMetadata().exportXMPMetadata();
|
||||
xmpString = convertStreamToString(XMP);
|
||||
try (PDDocument doc = Loader.loadPDF(IOUtils.toByteArray (pdfStream))) {
|
||||
// PDDocumentInformation info = doc.getDocumentInformation();
|
||||
final PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog());
|
||||
//start
|
||||
|
||||
final PDEmbeddedFilesNameTreeNode etn = names.getEmbeddedFiles();
|
||||
if (etn == null) {
|
||||
return;
|
||||
}
|
||||
if (doc.getDocumentCatalog() == null || doc.getDocumentCatalog().getMetadata() == null) {
|
||||
LOGGER.info("no-xmlpart");
|
||||
return;
|
||||
}
|
||||
|
||||
final Map<String, PDComplexFileSpecification> efMap = etn.getNames();
|
||||
// String filePath = "/tmp/";
|
||||
final InputStream XMP = doc.getDocumentCatalog().getMetadata().exportXMPMetadata();
|
||||
xmpString = convertStreamToString(XMP);
|
||||
|
||||
if (efMap != null) {
|
||||
extractFiles(efMap); // see
|
||||
// https://memorynotfound.com/apache-pdfbox-extract-embedded-file-pdf-document/
|
||||
} else {
|
||||
final PDEmbeddedFilesNameTreeNode etn = names.getEmbeddedFiles();
|
||||
if (etn == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<PDNameTreeNode<PDComplexFileSpecification>> kids = etn.getKids();
|
||||
for (final PDNameTreeNode<PDComplexFileSpecification> node : kids) {
|
||||
final Map<String, PDComplexFileSpecification> namesL = node.getNames();
|
||||
extractFiles(namesL);
|
||||
final Map<String, PDComplexFileSpecification> efMap = etn.getNames();
|
||||
// String filePath = "/tmp/";
|
||||
|
||||
if (efMap != null) {
|
||||
extractFiles(efMap); // see
|
||||
// https://memorynotfound.com/apache-pdfbox-extract-embedded-file-pdf-document/
|
||||
} else {
|
||||
|
||||
final List<PDNameTreeNode<PDComplexFileSpecification>> kids = etn.getKids();
|
||||
if (kids == null) {
|
||||
return;
|
||||
}
|
||||
for (final PDNameTreeNode<PDComplexFileSpecification> node : kids) {
|
||||
final Map<String, PDComplexFileSpecification> namesL = node.getNames();
|
||||
extractFiles(namesL);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no PDF probably XML
|
||||
containsMeta = true;
|
||||
setRawXML(XMLTools.getBytesFromStream(pdfStream));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +208,7 @@ public class ZUGFeRDImporter {
|
||||
xmlFact.setNamespaceAware(true);
|
||||
final DocumentBuilder builder = xmlFact.newDocumentBuilder();
|
||||
final ByteArrayInputStream is = new ByteArrayInputStream(rawXML);
|
||||
/// is.skip(guessBOMSize(is));
|
||||
/// is.skip(guessBOMSize(is));
|
||||
document = builder.parse(is);
|
||||
}
|
||||
|
||||
@@ -198,14 +219,12 @@ public class ZUGFeRDImporter {
|
||||
try {
|
||||
setDocument();
|
||||
} catch (ParserConfigurationException | SAXException e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
LOGGER.error ("Failed to parse XML", e);
|
||||
throw new ZUGFeRDExportException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
protected String extractString(String xpathStr) {
|
||||
if (!containsMeta) {
|
||||
throw new ZUGFeRDExportException("No suitable data/ZUGFeRD file could be found.");
|
||||
@@ -217,7 +236,7 @@ public class ZUGFeRDImporter {
|
||||
final XPath xpath = xpathFact.newXPath();
|
||||
result = xpath.evaluate(xpathStr, document);
|
||||
} catch (final XPathExpressionException e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
LOGGER.error ("Failed to evaluate XPath", e);
|
||||
throw new ZUGFeRDExportException(e);
|
||||
}
|
||||
return result;
|
||||
@@ -248,7 +267,11 @@ public class ZUGFeRDImporter {
|
||||
* @return the ZUGFeRD Profile
|
||||
*/
|
||||
public String getZUGFeRDProfil() {
|
||||
switch (extractString("//*[local-name() = 'GuidelineSpecifiedDocumentContextParameter']//*[local-name() = 'ID']")) {
|
||||
String guideline = extractString("//*[local-name() = 'GuidelineSpecifiedDocumentContextParameter']//*[local-name() = 'ID']");
|
||||
if(guideline.contains("xrechnung")) {
|
||||
return "XRECHNUNG";
|
||||
}
|
||||
switch (guideline) {
|
||||
case "urn:cen.eu:en16931:2017":
|
||||
case "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort":
|
||||
return "COMFORT";
|
||||
@@ -262,9 +285,9 @@ public class ZUGFeRDImporter {
|
||||
case "urn:ferd:CrossIndustryDocument:invoice:1p0:extended":
|
||||
case "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended":
|
||||
return "EXTENDED";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -278,8 +301,7 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = 'ApplicableHeaderTradeSettlement']//*[local-name() = 'InvoiceCurrencyCode']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -298,7 +320,7 @@ public class ZUGFeRDImporter {
|
||||
return extractIssuerAssignedID("SellerOrderReferencedDocument");
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @return the IssuerAssigned ID
|
||||
*/
|
||||
public String getContractOrderReferencedDocumentIssuerAssignedID() {
|
||||
@@ -313,7 +335,7 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = '" + propertyName + "']//*[local-name() = 'IssuerAssignedID']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -336,25 +358,26 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = 'ExchangedDocument']//*[local-name() = 'IssueDateTime']//*[local-name() = 'DateTimeString']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public Date getDetailedDeliveryPeriodFrom(){
|
||||
final String toParse = extractString(
|
||||
"//*[local-name() = 'ApplicableHeaderTradeSettlement']" +
|
||||
"//*[local-name() = 'BillingSpecifiedPeriod']" +
|
||||
"//*[local-name() = 'StartDateTime']//*[local-name() = 'DateTimeString']");
|
||||
return tryDate(toParse);
|
||||
}
|
||||
public Date getDetailedDeliveryPeriodTo(){
|
||||
final String toParse = extractString(
|
||||
"//*[local-name() = 'ApplicableHeaderTradeSettlement']" +
|
||||
"//*[local-name() = 'BillingSpecifiedPeriod']" +
|
||||
"//*[local-name() = 'EndDateTime']//*[local-name() = 'DateTimeString']");
|
||||
return tryDate(toParse);
|
||||
}
|
||||
|
||||
public Date getDetailedDeliveryPeriodFrom() {
|
||||
final String toParse = extractString(
|
||||
"//*[local-name() = 'ApplicableHeaderTradeSettlement']" +
|
||||
"//*[local-name() = 'BillingSpecifiedPeriod']" +
|
||||
"//*[local-name() = 'StartDateTime']//*[local-name() = 'DateTimeString']");
|
||||
return tryDate(toParse);
|
||||
}
|
||||
|
||||
public Date getDetailedDeliveryPeriodTo() {
|
||||
final String toParse = extractString(
|
||||
"//*[local-name() = 'ApplicableHeaderTradeSettlement']" +
|
||||
"//*[local-name() = 'BillingSpecifiedPeriod']" +
|
||||
"//*[local-name() = 'EndDateTime']//*[local-name() = 'DateTimeString']");
|
||||
return tryDate(toParse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the TaxBasisTotalAmount
|
||||
@@ -367,7 +390,7 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']//*[local-name() = 'TaxBasisTotalAmount']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -383,7 +406,7 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']//*[local-name() = 'TaxTotalAmount']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -399,7 +422,7 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']//*[local-name() = 'RoundingAmount']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -415,7 +438,7 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']//*[local-name() = 'TotalPrepaidAmount']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -453,7 +476,7 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = 'ExchangedDocument']//*[local-name() = 'IncludedNote']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -463,7 +486,9 @@ public class ZUGFeRDImporter {
|
||||
*/
|
||||
public String getBuyerTradePartyName() {
|
||||
return extractString("//*[local-name() = 'BuyerTradeParty']//*[local-name() = 'Name']");
|
||||
} /**
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the BuyerTradeParty Name
|
||||
*/
|
||||
public String getDeliveryTradePartyName() {
|
||||
@@ -471,7 +496,6 @@ public class ZUGFeRDImporter {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return the line Total Amount
|
||||
*/
|
||||
@@ -483,7 +507,7 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']//*[local-name() = 'LineTotalAmount']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -506,7 +530,7 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = 'ActualDeliverySupplyChainEvent']//*[local-name() = 'OccurrenceDateTime']//*[local-name() = 'DateTimeString']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -522,13 +546,12 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = 'ExchangedDocument']//*[local-name() = 'ID']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return the document code
|
||||
*/
|
||||
@@ -540,7 +563,7 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = 'ExchangedDocument']/*[local-name() = 'TypeCode']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -557,7 +580,7 @@ public class ZUGFeRDImporter {
|
||||
return extractString("//*[local-name() = 'ApplicableHeaderTradeAgreement']/*[local-name() = 'BuyerReference']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -600,7 +623,7 @@ public class ZUGFeRDImporter {
|
||||
if (result == null || result.isEmpty()) {
|
||||
|
||||
/* fx/zf would be SpecifiedTradeSettlementMonetarySummation
|
||||
* but ox is SpecifiedTradeSettlementHeaderMonetarySummation...*/
|
||||
* but ox is SpecifiedTradeSettlementHeaderMonetarySummation...*/
|
||||
result = extractString("//*[local-name() = 'GrandTotalAmount']");
|
||||
}
|
||||
return result;
|
||||
@@ -664,7 +687,7 @@ public class ZUGFeRDImporter {
|
||||
throw new Exception("Not yet parsed");
|
||||
}
|
||||
final String head = getUTF8();
|
||||
String rootNode=extractString("local-name(/*)");
|
||||
String rootNode = extractString("local-name(/*)");
|
||||
if (rootNode.equals("CrossIndustryDocument")) {
|
||||
return EStandard.zugferd;
|
||||
} else if (rootNode.equals("Invoice")) {
|
||||
@@ -680,26 +703,26 @@ public class ZUGFeRDImporter {
|
||||
throw new Exception("ZUGFeRD version could not be determined");
|
||||
|
||||
}
|
||||
|
||||
public int getVersion() throws Exception {
|
||||
if (!containsMeta) {
|
||||
throw new Exception("Not yet parsed");
|
||||
}
|
||||
if (version != null) {
|
||||
return version;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
final String head = getUTF8();
|
||||
if (head.contains("<rsm:CrossIndustryDocument") //
|
||||
|| head.contains("<CrossIndustryDocument") //
|
||||
|| head.contains("<SCRDMCCBDACIDAMessageStructure") //
|
||||
|| head.contains("<rsm:SCRDMCCBDACIOMessageStructure")) { //
|
||||
|| head.contains("<CrossIndustryDocument") //
|
||||
|| head.contains("<SCRDMCCBDACIDAMessageStructure") //
|
||||
|| head.contains("<rsm:SCRDMCCBDACIOMessageStructure")) { //
|
||||
version = 1;
|
||||
} else if (head.contains("<rsm:CrossIndustryInvoice")) {
|
||||
version = 2;
|
||||
} else {
|
||||
throw new Exception("ZUGFeRD version could not be determined");
|
||||
}
|
||||
else {
|
||||
throw new Exception("ZUGFeRD version could not be determined");
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
@@ -719,12 +742,12 @@ public class ZUGFeRDImporter {
|
||||
final byte[] bomlessData;
|
||||
|
||||
if ((rawXML[0] == (byte) 0xEF)
|
||||
&& (rawXML[1] == (byte) 0xBB)
|
||||
&& (rawXML[2] == (byte) 0xBF)) {
|
||||
&& (rawXML[1] == (byte) 0xBB)
|
||||
&& (rawXML[2] == (byte) 0xBF)) {
|
||||
// I don't like BOMs, lets remove it
|
||||
bomlessData = new byte[rawXML.length - 3];
|
||||
System.arraycopy(rawXML, 3, bomlessData, 0,
|
||||
rawXML.length - 3);
|
||||
rawXML.length - 3);
|
||||
} else {
|
||||
bomlessData = rawXML;
|
||||
}
|
||||
@@ -754,19 +777,21 @@ public class ZUGFeRDImporter {
|
||||
// indication if zugferd is present - better than just invoice
|
||||
final String meta = getMeta();
|
||||
return (meta != null) && (meta.length() > 0) && ((meta.contains("SpecifiedExchangedDocumentContext")
|
||||
/* ZF1 */ || meta.contains("ExchangedDocumentContext") /* ZF2 */));
|
||||
/* ZF1 */ || meta.contains("ExchangedDocumentContext") /* ZF2 */));
|
||||
}
|
||||
|
||||
|
||||
static String convertStreamToString(java.io.InputStream is) {
|
||||
// source https://stackoverflow.com/questions/309424/how-do-i-read-convert-an-inputstream-into-a-string-in-java referring to
|
||||
// https://community.oracle.com/blogs/pat/2004/10/23/stupid-scanner-tricks
|
||||
final Scanner s = new Scanner(is, "UTF-8").useDelimiter("\\A");
|
||||
return s.hasNext() ? s.next() : "";
|
||||
try {
|
||||
return IOUtils.toString(is, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an instance of PostalTradeAddress for SellerTradeParty section
|
||||
*
|
||||
* @return an instance of PostalTradeAddress
|
||||
*/
|
||||
public PostalTradeAddress getBuyerTradePartyAddress() {
|
||||
@@ -780,7 +805,7 @@ public class ZUGFeRDImporter {
|
||||
nl = getNodeListByPath("//*[local-name() = 'CrossIndustryInvoice']//*[local-name() = 'SupplyChainTradeTransaction']//*[local-name() = 'ApplicableHeaderTradeAgreement']//*[local-name() = 'BuyerTradeParty']//*[local-name() = 'PostalTradeAddress']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -789,6 +814,7 @@ public class ZUGFeRDImporter {
|
||||
|
||||
/**
|
||||
* returns an instance of PostalTradeAddress for SellerTradeParty section
|
||||
*
|
||||
* @return an instance of PostalTradeAddress
|
||||
*/
|
||||
public PostalTradeAddress getSellerTradePartyAddress() {
|
||||
@@ -801,15 +827,16 @@ public class ZUGFeRDImporter {
|
||||
nl = getNodeListByPath("//*[local-name() = 'CrossIndustryInvoice']//*[local-name() = 'SupplyChainTradeTransaction']//*[local-name() = 'ApplicableHeaderTradeAgreement']//*[local-name() = 'SellerTradeParty']//*[local-name() = 'PostalTradeAddress']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return null;
|
||||
}
|
||||
|
||||
return getAddressFromNodeList(nl);
|
||||
}
|
||||
|
||||
/**
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an instance of PostalTradeAddress for ShipToTradeParty section
|
||||
*
|
||||
* @return an instance of PostalTradeAddress
|
||||
*/
|
||||
public PostalTradeAddress getDeliveryTradePartyAddress() {
|
||||
@@ -822,7 +849,7 @@ public class ZUGFeRDImporter {
|
||||
nl = getNodeListByPath("//*[local-name() = 'CrossIndustryInvoice']//*[local-name() = 'SupplyChainTradeTransaction']//*[local-name() = 'ApplicableHeaderTradeDelivery']//*[local-name() = 'ShipToTradeParty']//*[local-name() = 'PostalTradeAddress']");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -839,7 +866,7 @@ public class ZUGFeRDImporter {
|
||||
for (int j = 0; j < nodes.getLength(); j++) {
|
||||
n = nodes.item(j);
|
||||
final short nodeType = n.getNodeType();
|
||||
if ((nodeType==Node.ELEMENT_NODE)&&(n.getLocalName()!=null)){
|
||||
if ((nodeType == Node.ELEMENT_NODE) && (n.getLocalName() != null)) {
|
||||
switch (n.getLocalName()) {
|
||||
case "PostcodeCode":
|
||||
address.setPostCodeCode("");
|
||||
@@ -893,21 +920,22 @@ public class ZUGFeRDImporter {
|
||||
|
||||
/**
|
||||
* returns a list of LineItems
|
||||
*
|
||||
* @return a List of LineItem instances
|
||||
*/
|
||||
public List<Item> getLineItemList() {
|
||||
final List<Node> nodeList = getLineItemNodes();
|
||||
final List<Item> lineItemList = new ArrayList<>();
|
||||
|
||||
for (final Node n: nodeList) {
|
||||
for (final Node n : nodeList) {
|
||||
final Item lineItem = new Item(null, null, null);
|
||||
lineItem.setProduct(new Product(null,null,null,null));
|
||||
lineItem.setProduct(new Product(null, null, null, null));
|
||||
|
||||
final NodeList nl = n.getChildNodes();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
final Node nn = nl.item(i);
|
||||
Node node = null;
|
||||
if (nn.getLocalName()!=null) {
|
||||
if (nn.getLocalName() != null) {
|
||||
switch (nn.getLocalName()) {
|
||||
case "SpecifiedLineTradeAgreement":
|
||||
case "SpecifiedSupplyChainTradeAgreement":
|
||||
@@ -975,17 +1003,17 @@ public class ZUGFeRDImporter {
|
||||
node = getNodeByName(nn.getChildNodes(), "BillingSpecifiedPeriod");
|
||||
if (node != null) {
|
||||
final Node start = getNodeByName(node.getChildNodes(), "StartDateTime");
|
||||
Node dateTimeStart = null;
|
||||
if(start != null) {
|
||||
dateTimeStart = getNodeByName(start.getChildNodes(), "DateTimeString");
|
||||
}
|
||||
final Node end = getNodeByName(node.getChildNodes(), "EndDateTime");
|
||||
Node dateTimeEnd = null;
|
||||
if(end != null) {
|
||||
dateTimeEnd = getNodeByName(end.getChildNodes(), "DateTimeString");
|
||||
}
|
||||
lineItem.setDetailedDeliveryPeriod(tryDate(dateTimeStart), tryDate(dateTimeEnd));
|
||||
}
|
||||
Node dateTimeStart = null;
|
||||
if (start != null) {
|
||||
dateTimeStart = getNodeByName(start.getChildNodes(), "DateTimeString");
|
||||
}
|
||||
final Node end = getNodeByName(node.getChildNodes(), "EndDateTime");
|
||||
Node dateTimeEnd = null;
|
||||
if (end != null) {
|
||||
dateTimeEnd = getNodeByName(end.getChildNodes(), "DateTimeString");
|
||||
}
|
||||
lineItem.setDetailedDeliveryPeriod(tryDate(dateTimeStart), tryDate(dateTimeEnd));
|
||||
}
|
||||
|
||||
node = getNodeByName(nn.getChildNodes(), "SpecifiedTradeSettlementLineMonetarySummation");
|
||||
if (node != null) {
|
||||
@@ -1024,16 +1052,17 @@ public class ZUGFeRDImporter {
|
||||
|
||||
/**
|
||||
* returns a List of LineItem Nodes from ZUGFeRD XML
|
||||
*
|
||||
* @return a List of Node instances
|
||||
*/
|
||||
public List<Node> getLineItemNodes() {
|
||||
final List<Node> lineItemNodes = new ArrayList<>();
|
||||
NodeList nl = null;
|
||||
try {
|
||||
nl = getNodeListByPath("//*[local-name() = 'IncludedSupplyChainTradeLineItem']");
|
||||
nl = getNodeListByPath("//*[local-name() = 'IncludedSupplyChainTradeLineItem']");
|
||||
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
// Exception was already logged
|
||||
}
|
||||
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
@@ -1045,13 +1074,14 @@ public class ZUGFeRDImporter {
|
||||
|
||||
/**
|
||||
* Returns a node, found by name. If more nodes with the same name are present, the first occurence will be returned
|
||||
* @param nl - A NodeList which may contains the searched node
|
||||
*
|
||||
* @param nl - A NodeList which may contains the searched node
|
||||
* @param name The nodes name
|
||||
* @return a Node or null, if nothing is found
|
||||
*/
|
||||
private Node getNodeByName(NodeList nl, String name) {
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
if ((nl.item(i).getLocalName()!=null)&&(nl.item(i).getLocalName().equals(name))) {
|
||||
if ((nl.item(i).getLocalName() != null) && (nl.item(i).getLocalName().equals(name))) {
|
||||
return nl.item(i);
|
||||
} else if (nl.item(i).getChildNodes().getLength() > 0) {
|
||||
final Node node = getNodeByName(nl.item(i).getChildNodes(), name);
|
||||
@@ -1065,6 +1095,7 @@ public class ZUGFeRDImporter {
|
||||
|
||||
/**
|
||||
* Get a NodeList by providing an path
|
||||
*
|
||||
* @param path a compliable Path
|
||||
* @return a Nodelist or null, if an error occurs
|
||||
*/
|
||||
@@ -1078,25 +1109,27 @@ public class ZUGFeRDImporter {
|
||||
final XPathExpression xpr = xPath.compile(s);
|
||||
return (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
} catch (final Exception e) {
|
||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||
LOGGER.error("Failed to evaluate XPath", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the value of an node
|
||||
*
|
||||
* @param node the Node to get the value from
|
||||
* @return A String or empty String, if no value was found
|
||||
*/
|
||||
private String getNodeValue(Node node) {
|
||||
if (node != null && node.getFirstChild() != null) {
|
||||
return node.getFirstChild().getNodeValue();
|
||||
}
|
||||
if (node != null && node.getFirstChild() != null) {
|
||||
return node.getFirstChild().getNodeValue();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* tries to convert an String to BigDecimal.
|
||||
*
|
||||
* @param nodeValue The value as String
|
||||
* @return a BigDecimal with the value provides as String or a BigDecimal with value 0.00 if an error occurs
|
||||
*/
|
||||
@@ -1111,20 +1144,21 @@ public class ZUGFeRDImporter {
|
||||
}
|
||||
}
|
||||
}
|
||||
private Date tryDate(Node node) {
|
||||
final String nodeValue = getNodeValue(node);
|
||||
if (nodeValue.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return tryDate(nodeValue);
|
||||
}
|
||||
|
||||
private static Date tryDate(String toParse) {
|
||||
final SimpleDateFormat formatter = ZUGFeRDDateFormat.DATE.getFormatter();
|
||||
try {
|
||||
return formatter.parse(toParse);
|
||||
} catch (final Exception e) {
|
||||
return null;
|
||||
private Date tryDate(Node node) {
|
||||
final String nodeValue = getNodeValue(node);
|
||||
if (nodeValue.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return tryDate(nodeValue);
|
||||
}
|
||||
|
||||
private static Date tryDate(String toParse) {
|
||||
final SimpleDateFormat formatter = ZUGFeRDDateFormat.DATE.getFormatter();
|
||||
try {
|
||||
return formatter.parse(toParse);
|
||||
} catch (final Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ package org.mustangproject.ZUGFeRD;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
@@ -17,13 +17,11 @@ import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.mustangproject.Allowance;
|
||||
import org.mustangproject.BankDetails;
|
||||
import org.mustangproject.Charge;
|
||||
import org.mustangproject.EStandard;
|
||||
import org.mustangproject.Invoice;
|
||||
import org.mustangproject.Item;
|
||||
import org.mustangproject.Product;
|
||||
import org.mustangproject.ReferencedDocument;
|
||||
import org.mustangproject.SchemedID;
|
||||
import org.mustangproject.TradeParty;
|
||||
import org.mustangproject.XMLTools;
|
||||
import org.slf4j.Logger;
|
||||
@@ -75,10 +73,10 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter {
|
||||
*/
|
||||
XPathFactory xpathFact = XPathFactory.newInstance();
|
||||
XPath xpath = xpathFact.newXPath();
|
||||
XPathExpression xpr = xpath.compile("//*[local-name()=\"SellerTradeParty\"]|//*[local-name()=\"AccountingSupplierParty\"]");
|
||||
XPathExpression xpr = xpath.compile("//*[local-name()=\"SellerTradeParty\"]|//*[local-name()=\"AccountingSupplierParty\"]/*");
|
||||
NodeList SellerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
|
||||
xpr = xpath.compile("//*[local-name()=\"BuyerTradeParty\"]|//*[local-name()=\"AccountingCustomerParty\"]");
|
||||
xpr = xpath.compile("//*[local-name()=\"BuyerTradeParty\"]|//*[local-name()=\"AccountingCustomerParty\"]/*");
|
||||
NodeList BuyerNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
xpr = xpath.compile("//*[local-name()=\"ExchangedDocument\"]|//*[local-name()=\"HeaderExchangedDocument\"]");
|
||||
NodeList ExchangedDocumentNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
@@ -118,17 +116,22 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter {
|
||||
}
|
||||
}
|
||||
}
|
||||
String rootNode=extractString("local-name(/*)");
|
||||
if (rootNode.equals("Invoice"))
|
||||
{
|
||||
// UBL...
|
||||
String rootNode = extractString("local-name(/*)");
|
||||
if (rootNode.equals("Invoice")) {
|
||||
// UBL...
|
||||
number = extractString("//*[local-name()=\"Invoice\"]/*[local-name()=\"ID\"]").trim();
|
||||
issueDate=new SimpleDateFormat("yyyy-MM-dd")
|
||||
issueDate = new SimpleDateFormat("yyyy-MM-dd")
|
||||
.parse(extractString("//*[local-name()=\"Invoice\"]/*[local-name()=\"IssueDate\"]").trim());
|
||||
dueDate=new SimpleDateFormat("yyyy-MM-dd")
|
||||
.parse(extractString("//*[local-name()=\"Invoice\"]/*[local-name()=\"DueDate\"]").trim());
|
||||
deliveryDate=new SimpleDateFormat("yyyy-MM-dd")
|
||||
.parse(extractString("//*[local-name()=\"Delivery\"]/*[local-name()=\"ActualDeliveryDate\"]").trim());
|
||||
String dueDt = extractString("//*[local-name()=\"Invoice\"]/*[local-name()=\"DueDate\"]").trim();
|
||||
if (dueDt.length() > 0) {
|
||||
dueDate = new SimpleDateFormat("yyyy-MM-dd")
|
||||
.parse(dueDt);
|
||||
}
|
||||
String deliveryDt = extractString("//*[local-name()=\"Delivery\"]/*[local-name()=\"ActualDeliveryDate\"]").trim();
|
||||
if (deliveryDt.length() > 0) {
|
||||
deliveryDate = new SimpleDateFormat("yyyy-MM-dd")
|
||||
.parse(deliveryDt);
|
||||
}
|
||||
}
|
||||
xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeDelivery\"]");
|
||||
NodeList headerTradeDeliveryNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
@@ -208,6 +211,7 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter {
|
||||
|
||||
xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]|//*[local-name()=\"ApplicableSupplyChainTradeSettlement\"]");
|
||||
NodeList headerTradeSettlementNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
List<BankDetails> bankDetails = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < headerTradeSettlementNodes.getLength(); i++) {
|
||||
// nodes.item(i).getTextContent())) {
|
||||
@@ -235,11 +239,81 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((headerTradeSettlementChilds.item(settlementChildIndex).getLocalName() != null)
|
||||
&& (headerTradeSettlementChilds.item(settlementChildIndex).getLocalName()
|
||||
.equals("SpecifiedTradeSettlementPaymentMeans"))) {
|
||||
NodeList paymentMeansChilds = headerTradeSettlementChilds.item(settlementChildIndex).getChildNodes();
|
||||
for (int paymentMeansChildIndex = 0; paymentMeansChildIndex < paymentMeansChilds
|
||||
.getLength(); paymentMeansChildIndex++) {
|
||||
String IBAN = null, BIC = null;
|
||||
if ((paymentMeansChilds.item(paymentMeansChildIndex).getLocalName() != null) && (paymentMeansChilds
|
||||
.item(paymentMeansChildIndex).getLocalName().equals("PayeePartyCreditorFinancialAccount"))) {
|
||||
NodeList accountChilds = paymentMeansChilds.item(paymentMeansChildIndex).getChildNodes();
|
||||
for (int accountChildIndex = 0; accountChildIndex < accountChilds
|
||||
.getLength(); accountChildIndex++) {
|
||||
if ((accountChilds.item(accountChildIndex).getLocalName() != null) && (accountChilds
|
||||
.item(accountChildIndex).getLocalName().equals("IBANID"))) {//CII
|
||||
IBAN = accountChilds.item(accountChildIndex).getTextContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((paymentMeansChilds.item(paymentMeansChildIndex).getLocalName() != null) && (paymentMeansChilds
|
||||
.item(paymentMeansChildIndex).getLocalName().equals("PayeePartyCreditorFinancialInstitution"))) {
|
||||
NodeList accountChilds = paymentMeansChilds.item(paymentMeansChildIndex).getChildNodes();
|
||||
for (int accountChildIndex = 0; accountChildIndex < accountChilds
|
||||
.getLength(); accountChildIndex++) {
|
||||
if ((accountChilds.item(accountChildIndex).getLocalName() != null) && (accountChilds
|
||||
.item(accountChildIndex).getLocalName().equals("BICID"))) {//CII
|
||||
BIC = accountChilds.item(accountChildIndex).getTextContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (IBAN != null) {
|
||||
BankDetails bd = new BankDetails(IBAN);
|
||||
if (BIC != null) {
|
||||
bd.setBIC(BIC);
|
||||
}
|
||||
bankDetails.add(bd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
xpr = xpath.compile("//*[local-name()=\"PaymentMeans\"]"); //UBL only
|
||||
NodeList paymentMeansNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
|
||||
for (int i = 0; i < paymentMeansNodes.getLength(); i++) {
|
||||
// nodes.item(i).getTextContent())) {
|
||||
Node paymentMeansNode = paymentMeansNodes.item(i);
|
||||
NodeList paymentMeansChilds = paymentMeansNode.getChildNodes();
|
||||
for (int meansChildIndex = 0; meansChildIndex < paymentMeansChilds
|
||||
.getLength(); meansChildIndex++) {
|
||||
if ((paymentMeansChilds.item(meansChildIndex).getLocalName() != null)
|
||||
&& (paymentMeansChilds.item(meansChildIndex).getLocalName()
|
||||
.equals("PayeeFinancialAccount"))) {
|
||||
NodeList paymentTermChilds = paymentMeansChilds.item(meansChildIndex).getChildNodes();
|
||||
for (int paymentTermChildIndex = 0; paymentTermChildIndex < paymentTermChilds
|
||||
.getLength(); paymentTermChildIndex++) {
|
||||
if ((paymentTermChilds.item(paymentTermChildIndex).getLocalName() != null) && (paymentTermChilds
|
||||
.item(paymentTermChildIndex).getLocalName().equals("ID"))) {
|
||||
String IBAN = paymentTermChilds.item(paymentTermChildIndex).getTextContent();
|
||||
if (IBAN != null) {
|
||||
BankDetails bd = new BankDetails(IBAN);
|
||||
bankDetails.add(bd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zpp.setDueDate(dueDate).setDeliveryDate(deliveryDate).setIssueDate(issueDate)
|
||||
.setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number);
|
||||
bankDetails.forEach(bankDetail -> zpp.getSender().addBankDetails(bankDetail));
|
||||
|
||||
if (buyerOrderIssuerAssignedID != null) {
|
||||
zpp.setBuyerOrderReferencedDocumentID(buyerOrderIssuerAssignedID);
|
||||
}
|
||||
@@ -263,8 +337,7 @@ public class ZUGFeRDInvoiceImporter extends ZUGFeRDImporter {
|
||||
xpr = xpath.compile("//*[local-name()=\"IncludedSupplyChainTradeLineItem\"]|//*[local-name()=\"InvoiceLine\"]");
|
||||
NodeList nodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
|
||||
if (nodes.getLength() == 0) {
|
||||
} else {
|
||||
if (nodes.getLength() != 0) {
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
|
||||
Node currentItemNode = nodes.item(i);
|
||||
|
||||
@@ -20,28 +20,56 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import org.apache.fop.apps.*;
|
||||
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.CII.CIIToUBL;
|
||||
import org.mustangproject.ClasspathResolverURIAdapter;
|
||||
import org.xml.sax.SAXException;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
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.transform.*;
|
||||
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 java.io.*;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
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.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 com.helger.commons.io.stream.StreamHelper;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class ZUGFeRDVisualizer {
|
||||
|
||||
@@ -53,7 +81,7 @@ public class ZUGFeRDVisualizer {
|
||||
|
||||
static final ClassLoader CLASS_LOADER = ZUGFeRDVisualizer.class.getClassLoader();
|
||||
private static final String RESOURCE_PATH = "";
|
||||
private static final Logger LOG = Logger.getLogger(ZUGFeRDVisualizer.class.getName());
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ZUGFeRDVisualizer.class);
|
||||
// private static File createTempFileResult(final Transformer transformer, final
|
||||
// StreamSource toTransform,
|
||||
// final String suffix) throws TransformerException, IOException {
|
||||
@@ -79,27 +107,27 @@ public class ZUGFeRDVisualizer {
|
||||
}
|
||||
|
||||
public String visualize(String xmlFilename, Language lang)
|
||||
throws FileNotFoundException, TransformerException, UnsupportedEncodingException {
|
||||
throws FileNotFoundException, TransformerException, IOException, SAXException, ParserConfigurationException {
|
||||
|
||||
try {
|
||||
if (mXsltXRTemplate == null) {
|
||||
mXsltXRTemplate = mFactory.newTemplates(
|
||||
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/cii-xr.xsl")));
|
||||
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/cii-xr.xsl")));
|
||||
}
|
||||
if (mXsltPDFTemplate == null) {
|
||||
mXsltPDFTemplate = mFactory.newTemplates(
|
||||
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xr-pdf.xsl")));
|
||||
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")));
|
||||
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")));
|
||||
CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt")));
|
||||
}
|
||||
} catch (TransformerConfigurationException ex) {
|
||||
LOG.log(Level.SEVERE, null, ex);
|
||||
LOGGER.error("Failed to init XSLT templates", ex);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,35 +141,40 @@ public class ZUGFeRDVisualizer {
|
||||
try {
|
||||
fileContent = new String(Files.readAllBytes(Paths.get(xmlFilename)), StandardCharsets.UTF_8);
|
||||
} catch (IOException e2) {
|
||||
LOG.log(Level.SEVERE, null, e2);
|
||||
LOGGER.error("Failed to read file content", e2);
|
||||
}
|
||||
|
||||
ByteArrayOutputStream iaos = new ByteArrayOutputStream();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
String zf1Signature = "rsm:CrossIndustryDocument";
|
||||
String zf2Signature = "rsm:CrossIndustryInvoice";
|
||||
String ublSignature = "ubl:Invoice";
|
||||
String ublCreditNoteSignature = "ubl:CreditNote";
|
||||
String zf1Signature = "CrossIndustryDocument";
|
||||
String zf2Signature = "CrossIndustryInvoice";
|
||||
String ublSignature = "Invoice";
|
||||
String ublCreditNoteSignature = "CreditNote";
|
||||
boolean doPostProcessing = false;
|
||||
if (fileContent.contains(zf1Signature)) {
|
||||
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setNamespaceAware(true);
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
Document doc = db.parse(new InputSource(fis));
|
||||
Element root = doc.getDocumentElement();
|
||||
fis = new FileInputStream(xmlFilename); // fis wont reset() so re-read from beginning
|
||||
if (root.getLocalName().equals(zf1Signature)) {
|
||||
applyZF1XSLT(fis, baos);
|
||||
|
||||
} else if (fileContent.contains(zf2Signature)) {
|
||||
|
||||
} else if (root.getLocalName().equals(zf2Signature)) {
|
||||
//zf2 or fx
|
||||
applyZF2XSLT(fis, iaos);
|
||||
doPostProcessing = true;
|
||||
} else if (fileContent.contains(ublSignature)) {
|
||||
} else if (root.getLocalName().equals(ublSignature)) {
|
||||
//zf2 or fx
|
||||
applyUBL2XSLT(fis, iaos);
|
||||
doPostProcessing = true;
|
||||
|
||||
} else if (fileContent.contains(ublCreditNoteSignature)) {
|
||||
} else if (root.getLocalName().equals(ublCreditNoteSignature)) {
|
||||
//zf2 or fx
|
||||
applyUBLCreditNote2XSLT(fis, iaos);
|
||||
doPostProcessing = true;
|
||||
|
||||
} else {
|
||||
throw new IllegalArgumentException("File does not look like CII or UBL");
|
||||
}
|
||||
if (doPostProcessing) {
|
||||
// take the copy of the stream and re-write it to an InputStream
|
||||
@@ -158,54 +191,46 @@ public class ZUGFeRDVisualizer {
|
||||
// ByteArrayOutputStream
|
||||
iaos.writeTo(out);
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.SEVERE, null, 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
|
||||
if (out != null) {
|
||||
// close the PipedOutputStream cleanly
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
LOG.log(Level.SEVERE, null, e);
|
||||
}
|
||||
}
|
||||
StreamHelper.close(out);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
applyXSLTToHTML(in, baos);
|
||||
} catch (IOException e1) {
|
||||
LOG.log(Level.SEVERE, null, e1);
|
||||
LOGGER.error("Failed to create HTML", e1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return baos.toString("UTF-8");
|
||||
return baos.toString(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
protected String toFOP(String xmlFilename)
|
||||
throws FileNotFoundException, TransformerException, UnsupportedEncodingException {
|
||||
throws FileNotFoundException, TransformerException {
|
||||
|
||||
try {
|
||||
if (mXsltXRTemplate == null) {
|
||||
mXsltXRTemplate = mFactory.newTemplates(
|
||||
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/cii-xr.xsl")));
|
||||
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/cii-xr.xsl")));
|
||||
}
|
||||
if (mXsltPDFTemplate == null) {
|
||||
mXsltPDFTemplate = mFactory.newTemplates(
|
||||
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xr-pdf.xsl")));
|
||||
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xr-pdf.xsl")));
|
||||
}
|
||||
} catch (TransformerConfigurationException ex) {
|
||||
LOG.log(Level.SEVERE, null, ex);
|
||||
LOGGER.error("Failed to init XSLT templates", ex);
|
||||
}
|
||||
|
||||
FileInputStream fis = new FileInputStream(xmlFilename);
|
||||
String fileContent = "";
|
||||
try {
|
||||
fileContent = new String(Files.readAllBytes(Paths.get(xmlFilename)), StandardCharsets.UTF_8);
|
||||
// TODO why are we reading the whole file here and discarding the content?
|
||||
new String(Files.readAllBytes(Paths.get(xmlFilename)), StandardCharsets.UTF_8);
|
||||
} catch (IOException e2) {
|
||||
LOG.log(Level.SEVERE, null, e2);
|
||||
LOGGER.error("Failed to read file", e2);
|
||||
}
|
||||
|
||||
ByteArrayOutputStream iaos = new ByteArrayOutputStream();
|
||||
@@ -227,39 +252,28 @@ public class ZUGFeRDVisualizer {
|
||||
// ByteArrayOutputStream
|
||||
iaos.writeTo(out);
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.SEVERE, null, 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
|
||||
if (out != null) {
|
||||
// close the PipedOutputStream cleanly
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
LOG.log(Level.SEVERE, null, e);
|
||||
}
|
||||
}
|
||||
StreamHelper.close(out);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
applyXSLTToPDF(in, baos);
|
||||
} catch (IOException e1) {
|
||||
LOG.log(Level.SEVERE, null, e1);
|
||||
LOGGER.error("Failed to create PDF", e1);
|
||||
}
|
||||
|
||||
|
||||
return baos.toString("UTF-8");
|
||||
return baos.toString(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public void toPDF(String xmlFilename, String pdfFilename) {
|
||||
|
||||
// the writing part
|
||||
CIIToUBL c2u = new CIIToUBL();
|
||||
String sourceFilename = "factur-x.xml";
|
||||
File CIIinputFile = new File(xmlFilename);
|
||||
|
||||
String expected = null;
|
||||
String result = null;
|
||||
|
||||
ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer();
|
||||
@@ -268,12 +282,8 @@ public class ZUGFeRDVisualizer {
|
||||
*/
|
||||
try {
|
||||
result = zvi.toFOP(CIIinputFile.getAbsolutePath());
|
||||
} catch (FileNotFoundException e) {
|
||||
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||
} catch (TransformerException e) {
|
||||
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||
} catch (FileNotFoundException | TransformerException e) {
|
||||
LOGGER.error("Failed to apply FOP", e);
|
||||
}
|
||||
/*
|
||||
FopConfParser parser = null;
|
||||
@@ -304,6 +314,11 @@ public class ZUGFeRDVisualizer {
|
||||
|
||||
FopFactory fopFactory = builder.build();//FopFactory.newInstance(new File("c:\\Users\\jstaerk\\temp\\fop-config.xconf"));
|
||||
|
||||
fopFactory.getFontManager().setResourceResolver(
|
||||
ResourceResolverFactory.createInternalResourceResolver(
|
||||
new File(".").toURI(),
|
||||
new ClasspathResolverURIAdapter()));
|
||||
|
||||
FOUserAgent userAgent = fopFactory.newFOUserAgent();
|
||||
|
||||
userAgent.getRendererOptions().put("pdf-a-mode", "PDF/A-1b");
|
||||
@@ -332,31 +347,23 @@ public class ZUGFeRDVisualizer {
|
||||
|
||||
//Files.write(Paths.get("C:\\Users\\jstaerk\\temp\\fop.pdf"), res.toString().getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
} catch (FOPException e) {
|
||||
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||
} catch (TransformerConfigurationException e) {
|
||||
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||
} catch (IOException e) {
|
||||
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||
} catch (TransformerException e) {
|
||||
Logger.getLogger(ZUGFeRDVisualizer.class.getName()).log(Level.SEVERE, null, e);
|
||||
} catch (FOPException | IOException | TransformerException e) {
|
||||
LOGGER.error("Failed to create PDF", e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected void applyZF2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
||||
throws TransformerException {
|
||||
throws TransformerException {
|
||||
Transformer transformer = mXsltXRTemplate.newTransformer();
|
||||
|
||||
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
|
||||
}
|
||||
|
||||
protected void applyUBL2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
||||
throws TransformerException {
|
||||
throws TransformerException {
|
||||
if (mXsltUBLTemplate == null) {
|
||||
mXsltUBLTemplate = mFactory.newTemplates(
|
||||
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/ubl-invoice-xr.xsl")));
|
||||
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/ubl-invoice-xr.xsl")));
|
||||
}
|
||||
Transformer transformer = mXsltUBLTemplate.newTransformer();
|
||||
|
||||
@@ -364,10 +371,10 @@ public class ZUGFeRDVisualizer {
|
||||
}
|
||||
|
||||
protected void applyUBLCreditNote2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
||||
throws TransformerException {
|
||||
throws TransformerException {
|
||||
if (mXsltUBLTemplate == null) {
|
||||
mXsltUBLTemplate = mFactory.newTemplates(
|
||||
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/ubl-creditnote-xr.xsl")));
|
||||
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/ubl-creditnote-xr.xsl")));
|
||||
}
|
||||
Transformer transformer = mXsltUBLTemplate.newTransformer();
|
||||
|
||||
@@ -375,21 +382,21 @@ public class ZUGFeRDVisualizer {
|
||||
}
|
||||
|
||||
protected void applyZF1XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
||||
throws TransformerException {
|
||||
throws TransformerException {
|
||||
Transformer transformer = mXsltZF1HTMLTemplate.newTransformer();
|
||||
|
||||
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
|
||||
}
|
||||
|
||||
protected void applyXSLTToHTML(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
||||
throws TransformerException {
|
||||
throws TransformerException {
|
||||
Transformer transformer = mXsltHTMLTemplate.newTransformer();
|
||||
|
||||
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
|
||||
}
|
||||
|
||||
protected void applyXSLTToPDF(final InputStream xmlFile, final OutputStream PDFOutstream)
|
||||
throws TransformerException {
|
||||
throws TransformerException {
|
||||
Transformer transformer = mXsltPDFTemplate.newTransformer();
|
||||
|
||||
transformer.transform(new StreamSource(xmlFile), new StreamResult(PDFOutstream));
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -25,7 +25,7 @@
|
||||
<renderer mime="application/pdf">
|
||||
<fonts><!-- https://xmlgraphics.apache.org/fop/1.1/fonts.html auto-embed -->
|
||||
<auto-detect/>
|
||||
<font kerning="no" embed-url="FreeSans.ttf" embedding-mode="subset">
|
||||
<font kerning="no" embed-url="classpath:FreeSans.ttf" embedding-mode="subset">
|
||||
<font-triplet name="SourceSerifPro" style="normal" weight="normal" />
|
||||
<font-triplet name="Times-Bold" style="normal" weight="normal" />
|
||||
</font>
|
||||
|
||||
Binary file not shown.
@@ -22,6 +22,7 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
@@ -65,7 +66,7 @@ public class BackwardCompatibilityTest extends TestCase implements IExportableTr
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ze.export(baos);
|
||||
ze.close();
|
||||
String pdfContent = baos.toString("UTF-8");
|
||||
String pdfContent = baos.toString(StandardCharsets.UTF_8);
|
||||
assertFalse(pdfContent.indexOf("(via mustangproject.org") == -1);
|
||||
// check for pdf-a schema extension
|
||||
// assertFalse(pdfContent.indexOf("<zf:ConformanceLevel>EN 16931</zf:ConformanceLevel>") == -1);
|
||||
@@ -105,7 +106,7 @@ public class BackwardCompatibilityTest extends TestCase implements IExportableTr
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ze.export(baos);
|
||||
ze.close();
|
||||
String pdfContent = baos.toString("UTF-8");
|
||||
String pdfContent = baos.toString(StandardCharsets.UTF_8);
|
||||
assertFalse(pdfContent.indexOf("(via mustangproject.org") == -1);
|
||||
// check for pdf-a schema extension
|
||||
// assertFalse(pdfContent.indexOf("<zf:ConformanceLevel>EN 16931</zf:ConformanceLevel>") == -1);
|
||||
@@ -143,7 +144,7 @@ public class BackwardCompatibilityTest extends TestCase implements IExportableTr
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ze.export(baos);
|
||||
ze.close();
|
||||
String pdfContent = baos.toString("UTF-8");
|
||||
String pdfContent = baos.toString(StandardCharsets.UTF_8);
|
||||
assertFalse(pdfContent.indexOf("(via mustangproject.org") == -1);
|
||||
// check for pdf-a schema extension
|
||||
// assertFalse(pdfContent.indexOf("<zf:ConformanceLevel>EN 16931</zf:ConformanceLevel>") == -1);
|
||||
@@ -316,7 +317,7 @@ public class BackwardCompatibilityTest extends TestCase implements IExportableTr
|
||||
|
||||
|
||||
//
|
||||
public IZUGFeRDTradeSettlementPayment[] getTradeSettlementPayment() {
|
||||
public IZUGFeRDTradeSettlementPayment[] getTradeSettlementPayment() {
|
||||
Payment P = new Payment();
|
||||
IZUGFeRDTradeSettlementPayment[] allP = new Payment[1];
|
||||
allP[0] = P;
|
||||
|
||||
@@ -22,16 +22,7 @@ import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.runners.MethodSorters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import org.mustangproject.XMLTools;
|
||||
|
||||
public class BaseTest extends TestCase {
|
||||
|
||||
@@ -6,17 +6,18 @@ import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mustangproject.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/***
|
||||
* tests the linecalculator and transactioncalculator classes
|
||||
*
|
||||
*/
|
||||
public class CalculationTest {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger (CalculationTest.class);
|
||||
|
||||
@Test
|
||||
public void testLineCalculator_simpleAmounts_resultInValidVATAmount() {
|
||||
@@ -92,7 +93,7 @@ public class CalculationTest {
|
||||
invoice.setDeliveryDate(sqlDate.parse("2020-12-31"));
|
||||
invoice.setDueDate(sqlDate.parse("2021-01-15"));
|
||||
} catch (Exception e) {
|
||||
Logger.getLogger(CalculationTest.class.getName()).log(Level.SEVERE, null, e);
|
||||
LOGGER.error("Failed to set dates", e);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ import java.util.GregorianCalendar;
|
||||
import static org.xmlunit.assertj.XmlAssert.assertThat;
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class DXTest extends MustangReaderTestCase implements IExportableTransaction {
|
||||
public class DXTest extends MustangReaderTestCase {
|
||||
final String TARGET_PDF = "./target/testout-DX.pdf";
|
||||
final String TARGET_XML = "./target/testout-DX.xml";
|
||||
|
||||
|
||||
@@ -21,12 +21,9 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import junit.framework.TestCase;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.mustangproject.*;
|
||||
|
||||
@@ -256,13 +256,13 @@ public class MustangReaderWriterCustomXMLTest extends TestCase {
|
||||
"</ram:ApplicableHeaderTradeSettlement>\n" +
|
||||
"</rsm:SupplyChainTradeTransaction>\n" +
|
||||
"</rsm:CrossIndustryInvoice>";
|
||||
zea1.setXML(ownZUGFeRDXML.getBytes("UTF-8"));
|
||||
zea1.setXML(ownZUGFeRDXML.getBytes(StandardCharsets.UTF_8));
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
zea1.disableAutoClose(true);
|
||||
zea1.export(TARGET_PDF);
|
||||
zea1.export(baos);
|
||||
zea1.close();
|
||||
String pdfContent = baos.toString("UTF-8");
|
||||
String pdfContent = baos.toString(StandardCharsets.UTF_8);
|
||||
assertFalse(pdfContent.indexOf("(via mustangproject.org") == -1);
|
||||
assertFalse(pdfContent.indexOf("<fx:ConformanceLevel>EN 16931</fx:ConformanceLevel>") == -1);
|
||||
|
||||
@@ -437,14 +437,14 @@ public class MustangReaderWriterCustomXMLTest extends TestCase {
|
||||
+ "<ram:Name>Heiße Luft pro Liter</ram:Name>\n" + "<ram:Description/>\n"
|
||||
+ "</ram:SpecifiedTradeProduct>\n" + "</ram:IncludedSupplyChainTradeLineItem>\n"
|
||||
+ "</rsm:SpecifiedSupplyChainTradeTransaction>\n" + "</rsm:CrossIndustryDocument>";
|
||||
zea1.setXML(ownZUGFeRDXML.getBytes("UTF-8"));
|
||||
zea1.setXML(ownZUGFeRDXML.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
zea1.disableAutoClose(true);
|
||||
zea1.export(TARGET_PDF);
|
||||
zea1.export(baos);
|
||||
zea1.close();
|
||||
String pdfContent = baos.toString("UTF-8");
|
||||
String pdfContent = baos.toString(StandardCharsets.UTF_8);
|
||||
assertFalse(pdfContent.indexOf("(via mustangproject.org") == -1);
|
||||
assertFalse(pdfContent.indexOf("<zf:ConformanceLevel>BASIC</zf:ConformanceLevel>") == -1);
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ package org.mustangproject.ZUGFeRD;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
||||
import org.apache.xmpbox.XMPMetadata;
|
||||
@@ -42,7 +43,7 @@ import java.util.GregorianCalendar;
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class MustangReaderWriterEdgeTest extends MustangReaderTestCase {
|
||||
protected class EasyRecipientTradeParty extends RecipientTradeParty implements IZUGFeRDExportableTradeParty {
|
||||
protected class EasyRecipientTradeParty extends RecipientTradeParty {
|
||||
// Not testing extended profile here, lineThree not possible
|
||||
@Override
|
||||
public String getAdditionalAddressExtension() {
|
||||
@@ -252,7 +253,7 @@ public class MustangReaderWriterEdgeTest extends MustangReaderTestCase {
|
||||
setupPdfUnderTest(SOURCE_PDF, TARGET_PDF);
|
||||
|
||||
// now check the contents
|
||||
PDDocument doc = PDDocument.load(new File(TARGET_PDF));
|
||||
PDDocument doc = Loader.loadPDF(new File(TARGET_PDF));
|
||||
PDMetadata meta = doc.getDocumentCatalog().getMetadata();
|
||||
assertNotNull("The pdf must contain XMPMetadata", meta);
|
||||
|
||||
@@ -262,7 +263,7 @@ public class MustangReaderWriterEdgeTest extends MustangReaderTestCase {
|
||||
DomXmpParser xmpParser = new DomXmpParser();
|
||||
XMPMetadata xmp = xmpParser.parse(xmpBytes);
|
||||
|
||||
PDFAIdentificationSchema pdfai = xmp.getPDFIdentificationSchema();
|
||||
PDFAIdentificationSchema pdfai = xmp.getPDFAIdentificationSchema();
|
||||
assertNotNull("The pdf must contain a PDFIdentificationSchema", pdfai);
|
||||
|
||||
assertTrue("The PDF/A conformance must be A, B or U",
|
||||
|
||||
@@ -21,6 +21,7 @@ package org.mustangproject.ZUGFeRD;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
||||
import org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException;
|
||||
@@ -38,6 +39,7 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
@@ -328,13 +330,13 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
||||
}
|
||||
|
||||
private void checkPdfA3B(File tempFile) throws IOException, InvalidPasswordException {
|
||||
try (PDDocument doc = PDDocument.load(tempFile)) {
|
||||
try (PDDocument doc = Loader.loadPDF(tempFile)) {
|
||||
PDMetadata metadata = doc.getDocumentCatalog().getMetadata();
|
||||
InputStream exportXMPMetadata = metadata.exportXMPMetadata();
|
||||
byte[] xmpBytes = new byte[exportXMPMetadata.available()];
|
||||
exportXMPMetadata.read(xmpBytes);
|
||||
final XMPMetadata xmp = new DomXmpParser().parse(xmpBytes);
|
||||
PDFAIdentificationSchema pdfaid = xmp.getPDFIdentificationSchema();
|
||||
PDFAIdentificationSchema pdfaid = xmp.getPDFAIdentificationSchema();
|
||||
assertEquals(pdfaid.getPart().intValue(), 3);
|
||||
assertEquals(pdfaid.getConformance(), "U");
|
||||
} catch (XmpParsingException e) {
|
||||
@@ -367,7 +369,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ze.export(baos);
|
||||
ze.close();
|
||||
String pdfContent = baos.toString("UTF-8");
|
||||
String pdfContent = baos.toString(StandardCharsets.UTF_8);
|
||||
assertFalse(pdfContent.indexOf("(via mustangproject.org") == -1);
|
||||
// check for pdf-a schema extension
|
||||
// assertFalse(pdfContent.indexOf("<zf:ConformanceLevel>EN 16931</zf:ConformanceLevel>") == -1);
|
||||
@@ -411,7 +413,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ze.export(baos);
|
||||
ze.close();
|
||||
String pdfContent = baos.toString("UTF-8");
|
||||
String pdfContent = baos.toString(StandardCharsets.UTF_8);
|
||||
assertFalse(pdfContent.indexOf(DocumentContextParameterTypeConstants.BASIC) >= 0);
|
||||
assertFalse(pdfContent.indexOf(DocumentContextParameterTypeConstants.EXTENDED) >= 0);
|
||||
assertTrue(pdfContent.indexOf(DocumentContextParameterTypeConstants.COMFORT) >= 0);
|
||||
@@ -447,7 +449,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ze.export(baos);
|
||||
ze.close();
|
||||
String pdfContent = baos.toString("UTF-8");
|
||||
String pdfContent = baos.toString(StandardCharsets.UTF_8);
|
||||
assertFalse(pdfContent.indexOf("(via mustangproject.org") == -1);
|
||||
// check for pdf-a schema extension
|
||||
assertFalse(pdfContent.indexOf("<fx:ConformanceLevel>EN 16931</fx:ConformanceLevel>") == -1);
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.junit.runners.MethodSorters;
|
||||
import org.mustangproject.*;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
@@ -42,7 +41,7 @@ import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class OXTest extends MustangReaderTestCase implements IExportableTransaction {
|
||||
public class OXTest extends MustangReaderTestCase {
|
||||
final String TARGET_PDF = "./target/testout-OX.pdf";
|
||||
final String TARGET_PDF_EDGE = "./target/testout-OX-edge.pdf";
|
||||
final String TARGET_XML = "./target/testout-OX.xml";
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
|
||||
/**
|
||||
* *********************************************************************
|
||||
* <p>
|
||||
* Copyright 2019 Jochen Staerk
|
||||
* <p>
|
||||
* Use is subject to license terms.
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* <p>
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* <p>
|
||||
* **********************************************************************
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.mustangproject.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class PreValidationTest extends TestCase {
|
||||
final String TARGET_PDF = "./target/testout-Preval.pdf";
|
||||
final String SOURCE_PDF = "/veraPDFtestsuite6-7-11-t01-fail-a.pdf";
|
||||
|
||||
public void testFailIgnore() {
|
||||
|
||||
// the writing part
|
||||
|
||||
|
||||
boolean hasEx = false;
|
||||
try (InputStream source = this.getClass()
|
||||
.getResourceAsStream(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2)
|
||||
.load(source);
|
||||
ze.setTransaction(createInvoice());
|
||||
|
||||
ze.export(TARGET_PDF);
|
||||
} catch (IOException e) {
|
||||
hasEx = true;
|
||||
}
|
||||
assertTrue(hasEx);
|
||||
hasEx = false;
|
||||
try (InputStream source = this.getClass()
|
||||
.getResourceAsStream(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors().load(source);
|
||||
|
||||
ze.setProducer("My Application").setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).
|
||||
setTransaction(createInvoice());
|
||||
ze.export(TARGET_PDF);
|
||||
} catch (IOException e) {
|
||||
hasEx = true;
|
||||
}
|
||||
assertFalse(hasEx);
|
||||
}
|
||||
|
||||
private Invoice createInvoice() {
|
||||
String orgname = "Test company";
|
||||
String number = "123";
|
||||
String amountStr = "1.00";
|
||||
BigDecimal amount = new BigDecimal(amountStr);
|
||||
return new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date())
|
||||
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("DE4711").addVATID("DE0815").setEmail("info@example.org").setContact(new Contact("Hans Test", "+49123456789", "test@example.org")).addBankDetails(new BankDetails("DE12500105170648489890", "COBADEFXXX")))
|
||||
.setRecipient(new TradeParty("Theodor Est", "Bahnstr. 42", "88802", "Spielkreis", "DE"))
|
||||
.setReferenceNumber("991-01484-64")//leitweg-id
|
||||
// not using any VAT, this is also a test of zero-rated goods:
|
||||
.setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", BigDecimal.ZERO), amount, new BigDecimal(1.0)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,13 +23,10 @@ package org.mustangproject.ZUGFeRD;
|
||||
import junit.framework.TestCase;
|
||||
import org.mustangproject.*;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
/***
|
||||
* This is a test to confirm the minimum steps to implement a interface are still sufficient
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -9,6 +11,7 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Ignore
|
||||
public class ResourceCase extends TestCase {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ResourceCase.class.getCanonicalName()); // log output is
|
||||
|
||||
|
||||
@@ -22,15 +22,16 @@ import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* This test utility class is providing usability functions to test file resources
|
||||
*/
|
||||
public class ResourceUtilities {
|
||||
private static final Logger LOG = Logger.getLogger(ResourceUtilities.class.getName());
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger (ResourceUtilities.class);
|
||||
|
||||
/**
|
||||
* Loading a File into a String using a certain encoding and file path
|
||||
@@ -73,7 +74,7 @@ public class ResourceUtilities {
|
||||
uri = ResourceUtilities.class.getClassLoader().getResource(relativeFilePath).toURI();
|
||||
uri = new URI(toExternalForm(uri));
|
||||
} catch (URISyntaxException ex) {
|
||||
LOG.log(Level.SEVERE, null, ex);
|
||||
LOGGER.error("Failed to parse URI", ex);
|
||||
}
|
||||
if (uri == null) {
|
||||
throw new FileNotFoundException("Could not find the file '" + relativeFilePath + "'!");
|
||||
@@ -129,7 +130,7 @@ public class ResourceUtilities {
|
||||
try {
|
||||
filepath = ResourceUtilities.class.getClassLoader().getResource("").toURI().getPath() + relativeFilePath;
|
||||
} catch (URISyntaxException ex) {
|
||||
LOG.log(Level.SEVERE, null, ex);
|
||||
LOGGER.error("Failed to parse URI", ex);
|
||||
}
|
||||
return new File(filepath);
|
||||
}
|
||||
@@ -142,7 +143,7 @@ public class ResourceUtilities {
|
||||
try {
|
||||
testFolder = ResourceUtilities.class.getClassLoader().getResource("").toURI().getPath();
|
||||
} catch (URISyntaxException ex) {
|
||||
LOG.log(Level.SEVERE, null, ex);
|
||||
LOGGER.error("Failed to parse URI", ex);
|
||||
}
|
||||
return testFolder;
|
||||
}
|
||||
@@ -206,7 +207,7 @@ public class ResourceUtilities {
|
||||
try {
|
||||
ret = new URI(sb.toString()).toASCIIString();
|
||||
} catch (URISyntaxException ex) {
|
||||
LOG.log(Level.SEVERE, null, ex);
|
||||
LOGGER.error("Failed to parse URI", ex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -21,13 +21,12 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
@@ -41,6 +40,8 @@ import org.mustangproject.Item;
|
||||
import org.mustangproject.Product;
|
||||
import org.mustangproject.TradeParty;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
public class UBLTest extends ResourceCase {
|
||||
final String TARGET_XML = "./target/testout-1Lieferschein.xml";
|
||||
|
||||
@@ -89,7 +90,7 @@ public class UBLTest extends ResourceCase {
|
||||
final ByteArrayOutputStream baos=new ByteArrayOutputStream();
|
||||
oe.export(baos);
|
||||
|
||||
final String theXML = baos.toString("UTF-8");
|
||||
final String theXML = baos.toString(StandardCharsets.UTF_8);
|
||||
assertTrue(theXML.contains("<DespatchAdvice"));
|
||||
Files.write(Paths.get(TARGET_XML), theXML.getBytes(StandardCharsets.UTF_8));
|
||||
} catch (final IOException e) {
|
||||
@@ -98,4 +99,76 @@ public class UBLTest extends ResourceCase {
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testEdgeInvoiceImportUBL() {
|
||||
|
||||
File UBLinputFile = getResourceAsFile("ubl/01.01a-INVOICE.ubl.xml");
|
||||
boolean hasExceptions = false;
|
||||
|
||||
ZUGFeRDInvoiceImporter zii = null;
|
||||
Invoice invoice = null;
|
||||
try {
|
||||
zii = new ZUGFeRDInvoiceImporter(new FileInputStream(UBLinputFile));
|
||||
invoice = zii.extractInvoice();
|
||||
} catch (XPathExpressionException | ParseException | FileNotFoundException e) {
|
||||
hasExceptions = true;
|
||||
}
|
||||
assertFalse(hasExceptions);
|
||||
// Reading ZUGFeRD
|
||||
assertEquals(new BigDecimal("288.79"), invoice.getZFItems()[0].getPrice());
|
||||
assertEquals("04011000-12345-03", invoice.getReferenceNumber());
|
||||
assertEquals("seller@email.de", invoice.getSender().getContact().getEMail());
|
||||
assertEquals("12345", invoice.getRecipient().getZIP());
|
||||
assertEquals("DE75512108001245126199", invoice.getSender().getBankDetails().get(0).getIBAN());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* public void testInvoiceImportOtherUBL() {
|
||||
|
||||
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_1_Teilrechnung.ubl.xml");
|
||||
// File UBLinputFile = getResourceAsFile("ubl/EN16931_2_Teilrechnung.ubl.xml");
|
||||
/* File UBLinputFile = getResourceAsFile("ubl/EN16931_AbweichenderZahlungsempf.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Betriebskostenabrechnung.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Einfach.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Einfach_DueDate.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Einfach_negativePaymentDue.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Elektron.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_ElektronischeAdresse.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Gutschrift.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Haftpflichtversicherung_Versicherungssteuer.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Innergemeinschaftliche_Lieferungen.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Kraftfahrversicherung_Bruttopreise.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Miete.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_OEPNV.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Physiotherapeut.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Rabatte.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Rechnungskorrektur.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_RechnungsUebertragung.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Reisekostenabrechnung.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_Sachversicherung_berechneter_Steuersatz.ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/EN16931_SEPA_Prenotification.ubl.xml");
|
||||
|
||||
|
||||
|
||||
boolean hasExceptions = false;
|
||||
|
||||
ZUGFeRDInvoiceImporter zii = null;
|
||||
Invoice invoice = null;
|
||||
try {
|
||||
zii = new ZUGFeRDInvoiceImporter(new FileInputStream(UBLinputFile));
|
||||
invoice = zii.extractInvoice();
|
||||
} catch (XPathExpressionException | ParseException | FileNotFoundException e) {
|
||||
hasExceptions = true;
|
||||
}
|
||||
assertFalse(hasExceptions);
|
||||
// Reading ZUGFeRD
|
||||
assertEquals(new BigDecimal("288.79"), invoice.getZFItems()[0].getPrice());
|
||||
assertEquals("04011000-12345-03", invoice.getReferenceNumber());
|
||||
assertEquals("seller@email.de", invoice.getSender().getContact().getEMail());
|
||||
assertEquals("12345", invoice.getRecipient().getZIP());
|
||||
assertEquals("DE75512108001245126199", invoice.getSender().getBankDetails().get(0).getIBAN());
|
||||
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -19,24 +19,9 @@
|
||||
*********************************************************************** */
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.mustangproject.Contact;
|
||||
import org.mustangproject.Invoice;
|
||||
import org.mustangproject.Item;
|
||||
import org.mustangproject.Product;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class UXTest extends TestCase {
|
||||
|
||||
@@ -19,16 +19,12 @@
|
||||
*********************************************************************** */
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import org.apache.fop.apps.*;
|
||||
import org.apache.xmlgraphics.util.MimeConstants;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.mustangproject.CII.CIIToUBL;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
@@ -63,19 +59,20 @@ public class VisualizationTest extends ResourceCase {
|
||||
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);
|
||||
assertNotNull(result);
|
||||
// Reading ZUGFeRD
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
public void testUBLCreditNoteVisualizationBasic() {
|
||||
|
||||
// the writing part
|
||||
CIIToUBL c2u = new CIIToUBL();
|
||||
String sourceFilename = "factur-x.xml";
|
||||
File UBLinputFile = getResourceAsFile("ubl-creditnote.xml");
|
||||
|
||||
String expected = null;
|
||||
@@ -85,10 +82,10 @@ public class VisualizationTest extends ResourceCase {
|
||||
/* 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","");
|
||||
result = zvi.visualize(UBLinputFile.getAbsolutePath(),ZUGFeRDVisualizer.Language.EN).replace("\r","").replace("\n","").replace(" ","").replace("\t","");
|
||||
|
||||
File expectedResult=getResourceAsFile("factur-x-vis-ubl-creditnote.en.html");
|
||||
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("\r","").replace("\n","").replace(" ","").replace("\t","");
|
||||
// remove linebreaks as well...
|
||||
|
||||
} catch (UnsupportedOperationException e) {
|
||||
@@ -99,20 +96,21 @@ public class VisualizationTest extends ResourceCase {
|
||||
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);
|
||||
assertNotNull(result);
|
||||
// Reading ZUGFeRD
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
public void testUBLVisualizationBasic() {
|
||||
|
||||
// the writing part
|
||||
CIIToUBL c2u = new CIIToUBL();
|
||||
String sourceFilename = "factur-x.xml";
|
||||
File UBLinputFile = getResourceAsFile("01.01a-INVOICE_ubl.xml");
|
||||
File UBLinputFile = getResourceAsFile("ubl/01.01a-INVOICE.ubl.xml");
|
||||
|
||||
String expected = null;
|
||||
String result = null;
|
||||
@@ -135,11 +133,14 @@ public class VisualizationTest extends ResourceCase {
|
||||
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);
|
||||
assertNotNull(result);
|
||||
// Reading ZUGFeRD
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@@ -32,9 +32,6 @@ import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.xmlunit.assertj.XmlAssert.assertThat;
|
||||
@@ -88,10 +85,11 @@ public class XRTest extends TestCase {
|
||||
Invoice i = new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date())
|
||||
.setSender(new TradeParty(orgname,"teststr","55232","teststadt","DE").setEmail("sender@example.com").addTaxID("DE4711").addVATID("DE0815").setContact(new Contact("Hans Test","+49123456789","test@example.org")).addBankDetails(new BankDetails("DE12500105170648489890","COBADEFXXX")))
|
||||
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").setEmail("recipient@sample.org"))
|
||||
.addCashDiscount(new CashDiscount(new BigDecimal(2),7))
|
||||
.addCashDiscount(new CashDiscount(new BigDecimal(3),14))
|
||||
.setReferenceNumber("991-01484-64")//leitweg-id
|
||||
// not using any VAT, this is also a test of zero-rated goods:
|
||||
.setNumber(number).setPaymentTermDescription("#SKONTO#TAGE=14#PROZENT=2.25#\n" +
|
||||
"#SKONTO#TAGE=28#PROZENT=1.00#\n").addItem(new Item(new Product("Testprodukt", "", "C62", BigDecimal.ZERO), amount, new BigDecimal(1.0)))
|
||||
.setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", BigDecimal.ZERO), amount, new BigDecimal(1.0)))
|
||||
.embedFileInXML(fe1);
|
||||
|
||||
|
||||
@@ -101,6 +99,7 @@ public class XRTest extends TestCase {
|
||||
zf2p.generateXML(i);
|
||||
String theXML = new String(zf2p.getXML(), StandardCharsets.UTF_8);
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
assertTrue(theXML.contains("#SKONTO#"));
|
||||
assertThat(theXML).valueByXPath("count(//*[local-name()='IncludedSupplyChainTradeLineItem'])")
|
||||
.asInt()
|
||||
.isEqualTo(1); //2 errors are OK because there is a known bug
|
||||
|
||||
@@ -37,7 +37,7 @@ import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class ZF2EdgeTest extends MustangReaderTestCase implements IExportableTransaction {
|
||||
public class ZF2EdgeTest extends MustangReaderTestCase {
|
||||
final String TARGET_PDF = "./target/testout-ZF2newEdge.pdf";
|
||||
|
||||
protected class EdgeProduct implements IZUGFeRDExportableProduct {
|
||||
@@ -293,12 +293,15 @@ public class ZF2EdgeTest extends MustangReaderTestCase implements IExportableTra
|
||||
|
||||
// the writing part
|
||||
|
||||
try (InputStream SOURCE_PDF = this.getClass()
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("Extended")).ignorePDFAErrors()
|
||||
.load(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();ze.ignorePDFAErrors();
|
||||
ze.load(SOURCE_PDF);
|
||||
ze.setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("Extended"));
|
||||
|
||||
ze.setTransaction(this);
|
||||
String theXML = new String(ze.getProvider().getXML(), StandardCharsets.UTF_8);
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
@@ -322,7 +325,7 @@ public class ZF2EdgeTest extends MustangReaderTestCase implements IExportableTra
|
||||
assertTrue(resultXML.contains("<ram:IssuerAssignedID>123</ram:IssuerAssignedID>"));
|
||||
|
||||
// Reading ZUGFeRD
|
||||
assertEquals("337.60", zi.getAmount());;
|
||||
assertEquals("337.60", zi.getAmount());
|
||||
assertEquals(zi.getHolder(), getOwnOrganisationName());
|
||||
assertEquals(zi.getForeignReference(), getNumber());
|
||||
try {
|
||||
|
||||
@@ -21,9 +21,11 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
@@ -35,9 +37,6 @@ import org.junit.runners.MethodSorters;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.mustangproject.ZUGFeRD.model.EventTimeCodeTypeConstants;
|
||||
import org.xmlunit.builder.Input;
|
||||
import org.xmlunit.xpath.JAXPXPathEngine;
|
||||
import org.xmlunit.xpath.XPathEngine;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
@@ -54,6 +53,7 @@ public class ZF2PushTest extends TestCase {
|
||||
final String TARGET_CHARGESALLOWANCESPDF = "./target/testout-ZF2PushChargesAllowances.pdf";
|
||||
final String TARGET_RELATIVECHARGESALLOWANCESPDF = "./target/testout-ZF2PushRelativeChargesAllowances.pdf";
|
||||
final String TARGET_ATTACHMENTSPDF = "./target/testout-ZF2PushAttachments.pdf";
|
||||
final String TARGET_BANKPDF = "./target/testout-ZF2PushBank.pdf";
|
||||
final String TARGET_PUSHEDGE = "./target/testout-ZF2PushEdge.pdf";
|
||||
final String TARGET_INTRACOMMUNITYSUPPLYPDF = "./target/testout-ZF2PushIntraCommunitySupply.pdf";
|
||||
final String TARGET_REVERSECHARGEPDF = "./target/testout-ZF2PushReverseCharge.pdf";
|
||||
@@ -68,28 +68,29 @@ public class ZF2PushTest extends TestCase {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
BigDecimal price = new BigDecimal(priceStr);
|
||||
try (InputStream SOURCE_PDF = this.getClass()
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20201121_508blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).ignorePDFAErrors()
|
||||
.load(SOURCE_PDF)) {
|
||||
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors();
|
||||
ze.load(SOURCE_PDF);
|
||||
ze.setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2);
|
||||
ze.setTransaction(new Invoice().setDueDate(sdf.parse("2020-12-12")).setIssueDate(sdf.parse("2020-11-21")).setDeliveryDate(sdf.parse("2020-11-10"))
|
||||
.setSender(new TradeParty(orgname, "Ecke 12", "12345", "Stadthausen", "DE").addBankDetails(new BankDetails("DE88200800000970375700", "COBADEFFXXX").setAccountName("Max Mustermann")).addVATID("DE136695976"))
|
||||
.setRecipient(new TradeParty("Theodor Est", "Bahnstr. 42", "88802", "Spielkreis", "DE")
|
||||
.setContact(new Contact("Ingmar N. Fo", "(555) 23 78-23", "info@localhost.local")).setID("2"))
|
||||
.setNumber(number)
|
||||
.setReferenceNumber("AB321")
|
||||
.addItem(new Item(new Product("Design (hours)", "Of a sample invoice", "HUR", new BigDecimal(7)), price, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Ballons", "various colors, ~2000ml", "H87", new BigDecimal(19)), new BigDecimal("0.79"), new BigDecimal(400.0)))
|
||||
.addItem(new Item(new Product("Hot air „heiße Luft“ (litres)", "", "LTR", new BigDecimal(19)), new BigDecimal("0.025"), new BigDecimal(800.0)))
|
||||
.setSender(new TradeParty(orgname, "Ecke 12", "12345", "Stadthausen", "DE").addBankDetails(new BankDetails("DE88200800000970375700", "COBADEFFXXX").setAccountName("Max Mustermann")).addVATID("DE136695976"))
|
||||
.setRecipient(new TradeParty("Theodor Est", "Bahnstr. 42", "88802", "Spielkreis", "DE")
|
||||
.setContact(new Contact("Ingmar N. Fo", "(555) 23 78-23", "info@localhost.local")).setID("2"))
|
||||
.setNumber(number)
|
||||
.setReferenceNumber("AB321")
|
||||
.addItem(new Item(new Product("Design (hours)", "Of a sample invoice", "HUR", new BigDecimal(7)), price, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Ballons", "various colors, ~2000ml", "H87", new BigDecimal(19)), new BigDecimal("0.79"), new BigDecimal(400.0)))
|
||||
.addItem(new Item(new Product("Hot air „heiße Luft“ (litres)", "", "LTR", new BigDecimal(19)), new BigDecimal("0.025"), new BigDecimal(800.0)))
|
||||
);
|
||||
|
||||
ze.export(TARGET_PDF);
|
||||
} catch (IOException | ParseException e) {
|
||||
fail("Exception should not be raised in testPushExport");
|
||||
fail("Exception should not be raised");
|
||||
}
|
||||
|
||||
// now check the contents (like MustangReaderTest)
|
||||
@@ -121,24 +122,26 @@ public class ZF2PushTest extends TestCase {
|
||||
String priceStr = "1.00";
|
||||
String taxID = "9990815";
|
||||
BigDecimal price = new BigDecimal(priceStr);
|
||||
try (InputStream SOURCE_PDF = this.getClass()
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).ignorePDFAErrors()
|
||||
.load(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors();
|
||||
ze.load(SOURCE_PDF);
|
||||
ze.setProducer("My Application").setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2);
|
||||
|
||||
byte[] b = {12, 13};
|
||||
ze.attachFile("one.pdf", b, "application/pdf", "Alternative");
|
||||
ze.attachFile("two.pdf", b, "application/pdf", "Alternative");
|
||||
ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID(taxID)).setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE4711").setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE"))).setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
||||
ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID(taxID).addVATID("DE0815")).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE4711").setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE"))).setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
||||
|
||||
);
|
||||
String theXML = new String(ze.getProvider().getXML());
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
ze.export(TARGET_ATTACHMENTSPDF);
|
||||
} catch (IOException e) {
|
||||
fail("IOException should not be raised in testEdgeExport");
|
||||
fail("IOException should not be raised");
|
||||
}
|
||||
|
||||
// now check the contents (like MustangReaderTest)
|
||||
@@ -158,6 +161,47 @@ public class ZF2PushTest extends TestCase {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testBankTransferExport() {
|
||||
|
||||
String orgname = "Test company";
|
||||
String number = "123";
|
||||
String priceStr = "1.00";
|
||||
String taxID = "9990815";
|
||||
BigDecimal price = new BigDecimal(priceStr);
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors().load(SOURCE_PDF);
|
||||
ze.setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2);
|
||||
|
||||
String IBAN = "DE999888777";
|
||||
String BIC = "COBADEFXXX";
|
||||
BankDetails bd = new BankDetails(IBAN, BIC);
|
||||
ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addBankDetails(bd).addTaxID(taxID).addVATID("DE0815")).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE4711").setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE"))).setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
||||
|
||||
);
|
||||
String theXML = new String(ze.getProvider().getXML());
|
||||
Invoice read = new Invoice();
|
||||
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(new ByteArrayInputStream(theXML.getBytes(StandardCharsets.UTF_8)));
|
||||
zii.extractInto(read);
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
|
||||
//assertEquals(IBAN,read.getSender().getBankDetails().get(0).getIBAN());
|
||||
ze.export(TARGET_BANKPDF);
|
||||
} catch (IOException e) {
|
||||
fail("IOException should not be raised");
|
||||
} catch (XPathExpressionException e) {
|
||||
fail("XPathException should not be raised");
|
||||
} catch (ParseException e) {
|
||||
fail("ParseException should not be raised");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testItemChargesAllowancesExport() {
|
||||
@@ -166,21 +210,23 @@ public class ZF2PushTest extends TestCase {
|
||||
String number = "123";
|
||||
String amountStr = "3.00";
|
||||
BigDecimal amount = new BigDecimal(amountStr);
|
||||
try (InputStream SOURCE_PDF = this.getClass()
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile("extended").ignorePDFAErrors()
|
||||
.load(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors().load(SOURCE_PDF);
|
||||
ze.setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile("extended");
|
||||
// ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname,"teststr", "55232","teststadt","DE")).setOwnTaxID("4711").setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number)
|
||||
// .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50)))));
|
||||
|
||||
|
||||
ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE")).setOwnTaxID("4711").setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562"))).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().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))))
|
||||
.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"))))
|
||||
ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815")).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562"))).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().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))))
|
||||
.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"))))
|
||||
|
||||
);
|
||||
|
||||
@@ -188,7 +234,7 @@ public class ZF2PushTest extends TestCase {
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
ze.export(TARGET_ITEMCHARGESALLOWANCESPDF);
|
||||
} catch (IOException e) {
|
||||
fail("IOException should not be raised in testEdgeExport");
|
||||
fail("IOException should not be raised");
|
||||
}
|
||||
|
||||
// now check the contents (like MustangReaderTest)
|
||||
@@ -217,32 +263,34 @@ public class ZF2PushTest extends TestCase {
|
||||
String number = "123";
|
||||
String amountStr = "3.00";
|
||||
BigDecimal amount = new BigDecimal(amountStr);
|
||||
try (InputStream SOURCE_PDF = this.getClass()
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile("extended").ignorePDFAErrors()
|
||||
.load(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors().load(SOURCE_PDF);
|
||||
ze.setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile("extended");
|
||||
// ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname,"teststr", "55232","teststadt","DE")).setOwnTaxID("4711").setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number)
|
||||
// .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50)))));
|
||||
|
||||
|
||||
ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date())
|
||||
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addVATID("DE0815")).setOwnTaxID("4711")
|
||||
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0816").setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562")))
|
||||
.setDeliveryAddress(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0816"))
|
||||
.setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setIntraCommunitySupply(), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setIntraCommunitySupply(), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setIntraCommunitySupply(), amount, new BigDecimal(2.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setIntraCommunitySupply(), amount, new BigDecimal(1.0)))
|
||||
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addVATID("DE0815").addTaxID ("4711"))
|
||||
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0816").setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562")))
|
||||
.setDeliveryAddress(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0816"))
|
||||
.setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setIntraCommunitySupply(), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setIntraCommunitySupply(), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setIntraCommunitySupply(), amount, new BigDecimal(2.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setIntraCommunitySupply(), amount, new BigDecimal(1.0)))
|
||||
);
|
||||
|
||||
String theXML = new String(ze.getProvider().getXML());
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
ze.export(TARGET_INTRACOMMUNITYSUPPLYPDF);
|
||||
} catch (IOException e) {
|
||||
fail("IOException should not be raised in testEdgeExport");
|
||||
fail("IOException should not be raised");
|
||||
}
|
||||
|
||||
// now check the contents (like MustangReaderTest)
|
||||
@@ -270,28 +318,31 @@ public class ZF2PushTest extends TestCase {
|
||||
String number = "123";
|
||||
String amountStr = "3.00";
|
||||
BigDecimal amount = new BigDecimal(amountStr);
|
||||
try (InputStream SOURCE_PDF = this.getClass()
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile("extended").ignorePDFAErrors()
|
||||
.load(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors().load(SOURCE_PDF);
|
||||
ze.setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile("extended");
|
||||
|
||||
// ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname,"teststr", "55232","teststadt","DE")).setOwnTaxID("4711").setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number)
|
||||
// .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50)))));
|
||||
|
||||
|
||||
ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addVATID("DE0815")).setOwnTaxID("4711").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0816").setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562"))).setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setReverseCharge(), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setReverseCharge(), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setReverseCharge(), amount, new BigDecimal(2.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setReverseCharge(), amount, new BigDecimal(1.0)))
|
||||
ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addVATID("DE0815").addTaxID("4711")).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0816").setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562"))).setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setReverseCharge(), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setReverseCharge(), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setReverseCharge(), amount, new BigDecimal(2.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).setReverseCharge(), amount, new BigDecimal(1.0)))
|
||||
);
|
||||
|
||||
String theXML = new String(ze.getProvider().getXML());
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
ze.export(TARGET_REVERSECHARGEPDF);
|
||||
} catch (IOException e) {
|
||||
fail("IOException should not be raised in testEdgeExport");
|
||||
fail("IOException should not be raised");
|
||||
}
|
||||
|
||||
// now check the contents (like MustangReaderTest)
|
||||
@@ -312,32 +363,36 @@ public class ZF2PushTest extends TestCase {
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testChargesAllowancesExport() {
|
||||
|
||||
String orgname = "Test company";
|
||||
String number = "123";
|
||||
String amountStr = "3.00";
|
||||
BigDecimal amount = new BigDecimal(amountStr);
|
||||
try (InputStream SOURCE_PDF = this.getClass()
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("en16931")).ignorePDFAErrors()
|
||||
.load(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors()
|
||||
.load(SOURCE_PDF);
|
||||
ze.setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("en16931"));
|
||||
|
||||
ze.setTransaction(new Invoice().setCurrency("CHF").setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE")).setOwnTaxID("4711").setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)))
|
||||
.addCharge(new Charge(new BigDecimal(0.5)).setTaxPercent(new BigDecimal(19)))
|
||||
.addAllowance(new Allowance(new BigDecimal(0.2)).setTaxPercent(new BigDecimal(19)))
|
||||
ze.setTransaction(new Invoice().setCurrency("CHF").setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815")).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)))
|
||||
.addCharge(new Charge(new BigDecimal(0.5)).setTaxPercent(new BigDecimal(19)))
|
||||
.addAllowance(new Allowance(new BigDecimal(0.2)).setTaxPercent(new BigDecimal(19)))
|
||||
|
||||
);
|
||||
String theXML = new String(ze.getProvider().getXML());
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
ze.export(TARGET_CHARGESALLOWANCESPDF);
|
||||
} catch (IOException e) {
|
||||
fail("IOException should not be raised in testEdgeExport");
|
||||
fail("IOException should not be raised");
|
||||
}
|
||||
|
||||
// now check the contents (like MustangReaderTest)
|
||||
@@ -371,29 +426,34 @@ public class ZF2PushTest extends TestCase {
|
||||
String priceStr = "1.00";
|
||||
String taxID = "9990815";
|
||||
BigDecimal price = new BigDecimal(priceStr);
|
||||
try (InputStream SOURCE_PDF = this.getClass()
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).ignorePDFAErrors()
|
||||
.load(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors()
|
||||
.load(SOURCE_PDF);
|
||||
|
||||
ze.setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("extended"));
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
try {
|
||||
|
||||
SchemedID gtin=new SchemedID("0160","2001015001325");
|
||||
SchemedID gln=new SchemedID("0088","4304171000002");
|
||||
SchemedID gtin = new SchemedID("0160", "2001015001325");
|
||||
SchemedID gln = new SchemedID("0088", "4304171000002");
|
||||
ze.setTransaction(new Invoice().setCurrency("CHF").addNote("document level 1/2").addNote("document level 2/2").setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date())
|
||||
.setSellerOrderReferencedDocumentID("9384").setBuyerOrderReferencedDocumentID("28934")
|
||||
.setDetailedDeliveryPeriod(new SimpleDateFormat("yyyyMMdd").parse(occurrenceFrom), new SimpleDateFormat("yyyyMMdd").parse(occurrenceTo))
|
||||
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID(taxID).setEmail("sender@test.org").setID("0009845"))
|
||||
.setDeliveryAddress(new TradeParty("just the other side of the street", "teststr.12a", "55232", "Entenhausen", "DE").addVATID("DE47110"))
|
||||
.setContractReferencedDocument(contractID)
|
||||
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addGlobalID(gln).setEmail("recipient@test.org").addVATID("DE4711").setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE").setFax("++49555123456")).setAdditionalAddress("Hinterhaus 3"))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(16)).addGlobalID(gtin).setSellerAssignedID("4711"), price, new BigDecimal(1.0)).addReferencedLineID("xxx").addNote("item level 1/1").addAllowance(new Allowance(new BigDecimal(0.02)).setReason("item discount").setTaxPercent(new BigDecimal(16))).setDetailedDeliveryPeriod(sdf.parse("2020-01-13"), sdf.parse("2020-01-15")))
|
||||
.addCharge(new Charge(new BigDecimal(0.5)).setReason("quick delivery charge").setTaxPercent(new BigDecimal(16)))
|
||||
.addAllowance(new Allowance(new BigDecimal(0.2)).setReason("discount").setTaxPercent(new BigDecimal(16)))
|
||||
.setDeliveryDate(sdf.parse("2020-11-02")).setOwnVATID("DE0815").setNumber(number).setVATDueDateTypeCode(EventTimeCodeTypeConstants.PAYMENT_DATE)
|
||||
.setSellerOrderReferencedDocumentID("9384").setBuyerOrderReferencedDocumentID("28934")
|
||||
.setDetailedDeliveryPeriod(new SimpleDateFormat("yyyyMMdd").parse(occurrenceFrom), new SimpleDateFormat("yyyyMMdd").parse(occurrenceTo))
|
||||
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID(taxID).setEmail("sender@test.org").setID("0009845").addVATID("DE0815"))
|
||||
.setDeliveryAddress(new TradeParty("just the other side of the street", "teststr.12a", "55232", "Entenhausen", "DE").addVATID("DE47110"))
|
||||
.setContractReferencedDocument(contractID)
|
||||
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addGlobalID(gln).setEmail("recipient@test.org").addVATID("DE4711").setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE").setFax("++49555123456")).setAdditionalAddress("Hinterhaus 3"))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(16)).addGlobalID(gtin).setSellerAssignedID("4711"), price, new BigDecimal(1.0)).addReferencedLineID("xxx").addNote("item level 1/1").addAllowance(new Allowance(new BigDecimal(0.02)).setReason("item discount").setTaxPercent(new BigDecimal(16))).setDetailedDeliveryPeriod(sdf.parse("2020-01-13"), sdf.parse("2020-01-15")))
|
||||
.addCharge(new Charge(new BigDecimal(0.5)).setReason("quick delivery charge").setTaxPercent(new BigDecimal(16)))
|
||||
.addAllowance(new Allowance(new BigDecimal(0.2)).setReason("discount").setTaxPercent(new BigDecimal(16)))
|
||||
.addCashDiscount(new CashDiscount(new BigDecimal(2), 14))
|
||||
.setDeliveryDate(sdf.parse("2020-11-02")).setNumber(number).setVATDueDateTypeCode(EventTimeCodeTypeConstants.PAYMENT_DATE)
|
||||
);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
@@ -403,7 +463,7 @@ public class ZF2PushTest extends TestCase {
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
ze.export(TARGET_PUSHEDGE);
|
||||
} catch (IOException e) {
|
||||
fail("IOException should not be raised in testEdgeExport");
|
||||
fail("IOException should not be raised");
|
||||
}
|
||||
|
||||
// now check the contents (like MustangReaderTest)
|
||||
@@ -412,9 +472,9 @@ public class ZF2PushTest extends TestCase {
|
||||
assertFalse(zi.getUTF8().contains("<ram:IBANID>")); // maybe add a direct debit mandate to the class in the future then this would fail
|
||||
assertTrue(zi.getUTF8().contains("Hinterhaus"));
|
||||
assertThat(zi.getUTF8()).valueByXPath("//*[local-name()='BuyerTradeParty']/*[local-name()='GlobalID'][@schemeID=0088]").asString()
|
||||
.isEqualTo("4304171000002");
|
||||
.isEqualTo("4304171000002");
|
||||
assertThat(zi.getUTF8()).valueByXPath("//*[local-name()='SpecifiedTradeProduct']/*[local-name()='GlobalID'][@schemeID=0160]").asString()
|
||||
.isEqualTo("2001015001325");
|
||||
.isEqualTo("2001015001325");
|
||||
assertTrue(zi.getUTF8().contains("2001015001325"));
|
||||
assertTrue(zi.getUTF8().contains("4304171000002"));
|
||||
assertTrue(zi.getUTF8().contains("0088"));
|
||||
@@ -431,9 +491,10 @@ public class ZF2PushTest extends TestCase {
|
||||
assertTrue(zi.getUTF8().contains("DE4711")); // the VAT ID should be there...
|
||||
assertFalse(zi.getUTF8().contains("DE47110")); // but not the VAT ID of the shiptotradeparty
|
||||
assertTrue(zi.getUTF8().contains("document level 2/2"));
|
||||
assertFalse(zi.getUTF8().contains("++49555123456")); // in profile EN16931 contact fax number is not allowed
|
||||
assertTrue(zi.getUTF8().contains("++49555123456"));
|
||||
assertTrue(zi.getUTF8().contains("Cash Discount")); // default description for cash discounts
|
||||
assertThat(zi.getUTF8()).valueByXPath("//*[local-name()='ApplicableTradeTax']/*[local-name()='DueDateTypeCode']").asString()
|
||||
.isEqualTo(EventTimeCodeTypeConstants.PAYMENT_DATE);
|
||||
.isEqualTo(EventTimeCodeTypeConstants.PAYMENT_DATE);
|
||||
|
||||
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(TARGET_PUSHEDGE);
|
||||
try {
|
||||
@@ -444,15 +505,14 @@ public class ZF2PushTest extends TestCase {
|
||||
|
||||
|
||||
} catch (XPathExpressionException e) {
|
||||
fail("XPathExpressionException should not be raised in testEdgeExport");
|
||||
fail("XPathExpressionException should not be raised");
|
||||
} catch (ParseException e) {
|
||||
fail("ParseException should not be raised in testEdgeExport");
|
||||
fail("ParseException should not be raised");
|
||||
/* a parseException would also be fired if the calculated grand total does not
|
||||
match the read grand total */
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testAllowancesExport() {
|
||||
@@ -460,23 +520,27 @@ public class ZF2PushTest extends TestCase {
|
||||
String orgname = "Test company";
|
||||
String number = "123";
|
||||
BigDecimal qty = new BigDecimal("20");
|
||||
try (InputStream SOURCE_PDF = this.getClass()
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("en16931")).ignorePDFAErrors()
|
||||
.load(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors().load(SOURCE_PDF);
|
||||
|
||||
ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE")).setOwnTaxID("4711").setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(500.0), qty).addAllowance(new Allowance(new BigDecimal(300)).setTaxPercent(new BigDecimal(19))))
|
||||
.addAllowance(new Allowance(new BigDecimal(600)).setTaxPercent(new BigDecimal(19)))
|
||||
ze.setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("en16931"));
|
||||
|
||||
|
||||
ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815")).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(500.0), qty).addAllowance(new Allowance(new BigDecimal(300)).setTaxPercent(new BigDecimal(19))))
|
||||
.addAllowance(new Allowance(new BigDecimal(600)).setTaxPercent(new BigDecimal(19)))
|
||||
|
||||
);
|
||||
String theXML = new String(ze.getProvider().getXML());
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
ze.export(TARGET_ALLOWANCESPDF);
|
||||
} catch (IOException e) {
|
||||
fail("IOException should not be raised in testEdgeExport");
|
||||
fail("IOException should not be raised");
|
||||
}
|
||||
|
||||
// now check the contents (like MustangReaderTest)
|
||||
@@ -503,25 +567,29 @@ public class ZF2PushTest extends TestCase {
|
||||
String number = "123";
|
||||
String priceStr = "3.00";
|
||||
BigDecimal price = new BigDecimal(priceStr);
|
||||
try (InputStream SOURCE_PDF = this.getClass()
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("extended")).ignorePDFAErrors()
|
||||
.load(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors()
|
||||
.load(SOURCE_PDF);
|
||||
|
||||
ze.setTransaction(new Invoice().setCurrency("CHF").setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE")).setOwnTaxID("4711").setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)).addCharge(new Charge().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19))))
|
||||
.addAllowance(new Allowance().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)))
|
||||
ze.setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("extended"));
|
||||
|
||||
ze.setTransaction(new Invoice().setCurrency("CHF").setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815")).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)).addCharge(new Charge().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19))))
|
||||
.addAllowance(new Allowance().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)))
|
||||
|
||||
);
|
||||
String theXML = new String(ze.getProvider().getXML());
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
ze.export(TARGET_RELATIVECHARGESALLOWANCESPDF);
|
||||
} catch (IOException e) {
|
||||
fail("IOException should not be raised in testEdgeExport");
|
||||
fail("IOException should not be raised");
|
||||
}
|
||||
|
||||
// now check the contents (like MustangReaderTest)
|
||||
@@ -555,23 +623,26 @@ public class ZF2PushTest extends TestCase {
|
||||
String priceStr = "1.00";
|
||||
BigDecimal price = new BigDecimal(priceStr);
|
||||
BigDecimal qty = new BigDecimal(-1.0);
|
||||
try (InputStream SOURCE_PDF = this.getClass()
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).ignorePDFAErrors()
|
||||
.load(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors()
|
||||
.load(SOURCE_PDF);
|
||||
ze.setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2);
|
||||
// no due date, since we are not expecting money
|
||||
Invoice i = new Invoice().setIssueDate(new Date()).setDetailedDeliveryPeriod(new Date(), new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815")).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0815")).setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty)).setCorrection("0815");
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty)).setCorrection("0815");
|
||||
ze.setTransaction(i);
|
||||
String theXML = new String(ze.getProvider().getXML());
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
ze.export(TARGET_CORRECTIONPDF);
|
||||
} catch (IOException e) {
|
||||
fail("IOException should not be raised in testEdgeExport");
|
||||
fail("IOException should not be raised");
|
||||
}
|
||||
|
||||
// now check the contents (like MustangReaderTest)
|
||||
@@ -605,22 +676,26 @@ public class ZF2PushTest extends TestCase {
|
||||
String priceStr = "1.00";
|
||||
BigDecimal price = new BigDecimal(priceStr);
|
||||
BigDecimal qty = new BigDecimal(1.0);
|
||||
try (InputStream SOURCE_PDF = this.getClass()
|
||||
try {
|
||||
InputStream SOURCE_PDF = this.getClass()
|
||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
||||
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).ignorePDFAErrors()
|
||||
.load(SOURCE_PDF)) {
|
||||
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1();
|
||||
ze.ignorePDFAErrors()
|
||||
.load(SOURCE_PDF);
|
||||
ze.
|
||||
setProducer("My Application")
|
||||
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2);
|
||||
Invoice i = new Invoice().setIssueDate(new Date()).setDueDate(new Date()).setDetailedDeliveryPeriod(new Date(), new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815").addBankDetails(new BankDetails("DE88200800000970375700", "COBADEFFXXX"))).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0815")).setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty)).setCreditNote();
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, qty)).setCreditNote();
|
||||
ze.setTransaction(i);
|
||||
String theXML = new String(ze.getProvider().getXML());
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
ze.export(TARGET_CREDITNOTEPDF);
|
||||
} catch (IOException e) {
|
||||
fail("IOException should not be raised in testEdgeExport");
|
||||
fail("IOException should not be raised");
|
||||
}
|
||||
|
||||
// now check the contents (like MustangReaderTest)
|
||||
|
||||
@@ -229,15 +229,14 @@ public class ZF2Test extends MustangReaderTestCase {
|
||||
assertEquals(zi.getSellerTradePartyAddress().getCityName(), "Stadthausen");
|
||||
|
||||
final List<org.mustangproject.Item> li = zi.getLineItemList();
|
||||
assertEquals(zi.getLineItemList().get(0).getId().toString(), "1");
|
||||
assertEquals(zi.getLineItemList().get(0).getProduct().getBuyerAssignedID(), "");
|
||||
assertEquals(zi.getLineItemList().get(0).getProduct().getSellerAssignedID(), "");
|
||||
assertEquals(zi.getLineItemList().get(0).getLineTotalAmount().toString(), "160.00");
|
||||
assertEquals(zi.getLineItemList().get(0).getQuantity().toString(), "1.0000");
|
||||
assertEquals(zi.getLineItemList().get(0).getGrossPrice().toString(), "160.0000");
|
||||
assertEquals(zi.getLineItemList().get(0).getProduct().getVATPercent().toString(), "7.00");
|
||||
assertEquals(zi.getLineItemList().get(0).getProduct().getName(), "Künstlerische Gestaltung (Stunde): Einer Beispielrechnung");
|
||||
assertEquals(zi.getLineItemList().get(0).getProduct().getDescription(), "");
|
||||
assertEquals(li.get(0).getId().toString(), "1");
|
||||
assertEquals(li.get(0).getProduct().getBuyerAssignedID(), "");
|
||||
assertEquals(li.get(0).getProduct().getSellerAssignedID(), "");
|
||||
assertEquals(li.get(0).getLineTotalAmount().toString(), "160.00");
|
||||
assertEquals(li.get(0).getQuantity().toString(), "1.0000");
|
||||
assertEquals(li.get(0).getProduct().getVATPercent().toString(), "7.00");
|
||||
assertEquals(li.get(0).getProduct().getName(), "Künstlerische Gestaltung (Stunde): Einer Beispielrechnung");
|
||||
assertEquals(li.get(0).getProduct().getDescription(), "");
|
||||
|
||||
try {
|
||||
assertEquals(zi.getVersion(), 2);
|
||||
|
||||
@@ -21,16 +21,8 @@
|
||||
*/
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
||||
import org.mustangproject.Invoice;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import java.io.*;
|
||||
import java.math.BigDecimal;
|
||||
@@ -39,7 +31,6 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Scanner;
|
||||
|
||||
|
||||
/***
|
||||
@@ -175,6 +166,7 @@ public class ZF2ZInvoiceImporterTest extends ResourceCase {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void testZF1Import() {
|
||||
|
||||
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter("./target/testout-MustangGnuaccountingBeispielRE-20171118_506zf1.pdf");
|
||||
|
||||
File diff suppressed because one or more lines are too long
175
library/src/test/resources/XRECHNUNG_Einfach.ubl.xml
Normal file
175
library/src/test/resources/XRECHNUNG_Einfach.ubl.xml
Normal file
@@ -0,0 +1,175 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cec="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
|
||||
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
|
||||
<cbc:ID>471102</cbc:ID>
|
||||
<cbc:IssueDate>2018-03-05</cbc:IssueDate>
|
||||
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||
<cbc:Note>Rechnung gemäß Bestellung vom 01.03.2018.</cbc:Note>
|
||||
<cbc:Note>#REG#Lieferant GmbH
|
||||
Lieferantenstraße 20
|
||||
80333 München
|
||||
Deutschland
|
||||
Geschäftsführer: Hans Muster
|
||||
Handelsregisternummer: H A 123
|
||||
</cbc:Note>
|
||||
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||
<cbc:BuyerReference>04011000-12345-34</cbc:BuyerReference>
|
||||
<cac:AccountingSupplierParty>
|
||||
<cac:Party>
|
||||
<cac:PartyIdentification>
|
||||
<cbc:ID schemeID="0088">4000001123452</cbc:ID>
|
||||
</cac:PartyIdentification>
|
||||
<cac:PartyName>
|
||||
<cbc:Name>Lieferant GmbH</cbc:Name>
|
||||
</cac:PartyName>
|
||||
<cac:PostalAddress>
|
||||
<cbc:StreetName>Lieferantenstraße 20</cbc:StreetName>
|
||||
<cbc:CityName>München</cbc:CityName>
|
||||
<cbc:PostalZone>80333</cbc:PostalZone>
|
||||
<cac:Country>
|
||||
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||
</cac:Country>
|
||||
</cac:PostalAddress>
|
||||
<cac:PartyTaxScheme>
|
||||
<cbc:CompanyID>201/113/40209</cbc:CompanyID>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>FC</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:PartyTaxScheme>
|
||||
<cac:PartyTaxScheme>
|
||||
<cbc:CompanyID>DE123456789</cbc:CompanyID>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:PartyTaxScheme>
|
||||
<cac:PartyLegalEntity>
|
||||
<cbc:RegistrationName>Lieferant GmbH</cbc:RegistrationName>
|
||||
</cac:PartyLegalEntity>
|
||||
<cac:Contact>
|
||||
<cbc:Name>Max Mustermann</cbc:Name>
|
||||
<cbc:Telephone>+49891234567</cbc:Telephone>
|
||||
<cbc:ElectronicMail>Max@Mustermann.de</cbc:ElectronicMail>
|
||||
</cac:Contact>
|
||||
</cac:Party>
|
||||
</cac:AccountingSupplierParty>
|
||||
<cac:AccountingCustomerParty>
|
||||
<cac:Party>
|
||||
<cac:PartyIdentification>
|
||||
<cbc:ID>GE2020211</cbc:ID>
|
||||
</cac:PartyIdentification>
|
||||
<cac:PartyName>
|
||||
<cbc:Name>Kunden AG Mitte</cbc:Name>
|
||||
</cac:PartyName>
|
||||
<cac:PostalAddress>
|
||||
<cbc:StreetName>Kundenstraße 15</cbc:StreetName>
|
||||
<cbc:CityName>Frankfurt</cbc:CityName>
|
||||
<cbc:PostalZone>69876</cbc:PostalZone>
|
||||
<cac:Country>
|
||||
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||
</cac:Country>
|
||||
</cac:PostalAddress>
|
||||
<cac:PartyLegalEntity>
|
||||
<cbc:RegistrationName>Kunden AG Mitte</cbc:RegistrationName>
|
||||
</cac:PartyLegalEntity>
|
||||
</cac:Party>
|
||||
</cac:AccountingCustomerParty>
|
||||
<cac:Delivery>
|
||||
<cbc:ActualDeliveryDate>2018-03-05</cbc:ActualDeliveryDate>
|
||||
</cac:Delivery>
|
||||
<cac:PaymentMeans>
|
||||
<cbc:PaymentMeansCode name="Zahlung per SEPA Überweisung.">58</cbc:PaymentMeansCode>
|
||||
<cac:PayeeFinancialAccount>
|
||||
<cbc:ID>DE02120300000000202051</cbc:ID>
|
||||
<cbc:Name>Kunden AG</cbc:Name>
|
||||
<cac:FinancialInstitutionBranch>
|
||||
<cbc:ID>BYLADEM1001</cbc:ID>
|
||||
</cac:FinancialInstitutionBranch>
|
||||
</cac:PayeeFinancialAccount>
|
||||
</cac:PaymentMeans>
|
||||
<cac:PaymentTerms>
|
||||
<cbc:Note>Zahlbar innerhalb 30 Tagen netto bis 04.04.2018, 3% Skonto innerhalb 10 Tagen bis 15.03.2018</cbc:Note>
|
||||
</cac:PaymentTerms>
|
||||
<cac:TaxTotal>
|
||||
<cbc:TaxAmount currencyID="EUR">56.87</cbc:TaxAmount>
|
||||
<cac:TaxSubtotal>
|
||||
<cbc:TaxableAmount currencyID="EUR">275</cbc:TaxableAmount>
|
||||
<cbc:TaxAmount currencyID="EUR">19.25</cbc:TaxAmount>
|
||||
<cac:TaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>7</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:TaxCategory>
|
||||
</cac:TaxSubtotal>
|
||||
<cac:TaxSubtotal>
|
||||
<cbc:TaxableAmount currencyID="EUR">198</cbc:TaxableAmount>
|
||||
<cbc:TaxAmount currencyID="EUR">37.62</cbc:TaxAmount>
|
||||
<cac:TaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>19</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:TaxCategory>
|
||||
</cac:TaxSubtotal>
|
||||
</cac:TaxTotal>
|
||||
<cac:LegalMonetaryTotal>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">473</cbc:LineExtensionAmount>
|
||||
<cbc:TaxExclusiveAmount currencyID="EUR">473</cbc:TaxExclusiveAmount>
|
||||
<cbc:TaxInclusiveAmount currencyID="EUR">529.87</cbc:TaxInclusiveAmount>
|
||||
<cbc:AllowanceTotalAmount currencyID="EUR">0</cbc:AllowanceTotalAmount>
|
||||
<cbc:ChargeTotalAmount currencyID="EUR">0</cbc:ChargeTotalAmount>
|
||||
<cbc:PrepaidAmount currencyID="EUR">0</cbc:PrepaidAmount>
|
||||
<cbc:PayableAmount currencyID="EUR">529.87</cbc:PayableAmount>
|
||||
</cac:LegalMonetaryTotal>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>1</cbc:ID>
|
||||
<cbc:InvoicedQuantity unitCode="H87">20</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">198</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Name>Trennblätter A4</cbc:Name>
|
||||
<cac:SellersItemIdentification>
|
||||
<cbc:ID>TB100A4</cbc:ID>
|
||||
</cac:SellersItemIdentification>
|
||||
<cac:StandardItemIdentification>
|
||||
<cbc:ID schemeID="0160">4012345001235</cbc:ID>
|
||||
</cac:StandardItemIdentification>
|
||||
<cac:ClassifiedTaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>19</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:ClassifiedTaxCategory>
|
||||
</cac:Item>
|
||||
<cac:Price>
|
||||
<cbc:PriceAmount currencyID="EUR">9.9</cbc:PriceAmount>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>2</cbc:ID>
|
||||
<cbc:InvoicedQuantity unitCode="H87">50</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">275</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Name>Joghurt Banane</cbc:Name>
|
||||
<cac:SellersItemIdentification>
|
||||
<cbc:ID>ARNR2</cbc:ID>
|
||||
</cac:SellersItemIdentification>
|
||||
<cac:StandardItemIdentification>
|
||||
<cbc:ID schemeID="0160">4000050986428</cbc:ID>
|
||||
</cac:StandardItemIdentification>
|
||||
<cac:ClassifiedTaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>7</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:ClassifiedTaxCategory>
|
||||
</cac:Item>
|
||||
<cac:Price>
|
||||
<cbc:PriceAmount currencyID="EUR">5.5</cbc:PriceAmount>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
</Invoice>
|
||||
171
library/src/test/resources/XRECHNUNG_Elektron.ubl.xml
Normal file
171
library/src/test/resources/XRECHNUNG_Elektron.ubl.xml
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
||||
<html xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xr="urn:ce.eu:en16931:2017:xoev-de:kosit:standard:xrechnung-1" xmlns:xrv="http://www.example.org/XRechnung-Viewer" lang="de">
|
||||
<!DOCTYPE HTML>
|
||||
<html xmlns:xr="urn:ce.eu:en16931:2017:xoev-de:kosit:standard:xrechnung-1" xmlns:xrv="http://www.example.org/XRechnung-Viewer" xmlns:xs="http://www.w3.org/2001/XMLSchema" lang="de">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta charset="UTF-8">
|
||||
<title>XRechnung</title>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
|
||||
<style>
|
||||
@@ -1555,7 +1555,7 @@
|
||||
<div class="boxzeile">
|
||||
<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:
|
||||
3MB. Screen 1440x900</div>
|
||||
3MB. Screen 1440x900</div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende ">Part number:</div>
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -177,7 +177,7 @@
|
||||
</ram:DueDateDateTime>
|
||||
</ram:SpecifiedTradePaymentTerms>
|
||||
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
|
||||
<ram:LineTotalAmount>496.00</ram:LineTotalAmount>
|
||||
<ram:LineTotalAmount>496.00</ram:LineTotalAmount>
|
||||
<ram:ChargeTotalAmount>0.00</ram:ChargeTotalAmount>
|
||||
<ram:AllowanceTotalAmount>0.00</ram:AllowanceTotalAmount>
|
||||
<ram:TaxBasisTotalAmount>496.00</ram:TaxBasisTotalAmount>
|
||||
|
||||
@@ -1,168 +1,174 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
||||
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
|
||||
xmlns:cec="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2">
|
||||
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
|
||||
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
|
||||
<cbc:ID>RE-20201121/508</cbc:ID>
|
||||
<cbc:IssueDate>2020-11-21</cbc:IssueDate>
|
||||
<cbc:DueDate>2020-12-12</cbc:DueDate>
|
||||
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||
<cbc:BuyerReference>AB321</cbc:BuyerReference>
|
||||
<cac:AccountingSupplierParty>
|
||||
<cac:Party>
|
||||
<cac:PartyName>
|
||||
<cbc:Name>Bei Spiel GmbH</cbc:Name>
|
||||
</cac:PartyName>
|
||||
<cac:PostalAddress>
|
||||
<cbc:StreetName>Ecke 12</cbc:StreetName>
|
||||
<cbc:CityName>Stadthausen</cbc:CityName>
|
||||
<cbc:PostalZone>12345</cbc:PostalZone>
|
||||
<cac:Country>
|
||||
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||
</cac:Country>
|
||||
</cac:PostalAddress>
|
||||
<cac:PartyTaxScheme>
|
||||
<cbc:CompanyID>DE136695976</cbc:CompanyID>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:PartyTaxScheme>
|
||||
<cac:PartyLegalEntity>
|
||||
<cbc:RegistrationName>Bei Spiel GmbH</cbc:RegistrationName>
|
||||
</cac:PartyLegalEntity>
|
||||
</cac:Party>
|
||||
</cac:AccountingSupplierParty>
|
||||
<cac:AccountingCustomerParty>
|
||||
<cac:Party>
|
||||
<cac:PartyIdentification>
|
||||
<?xml version="1.0" encoding="UTF-8"?><Invoice xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cec="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2">
|
||||
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
|
||||
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
|
||||
<cbc:ID>RE-20201121/508</cbc:ID>
|
||||
<cbc:IssueDate>2020-11-21</cbc:IssueDate>
|
||||
<cbc:DueDate>2020-12-12</cbc:DueDate>
|
||||
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||
<cbc:BuyerReference>AB321</cbc:BuyerReference>
|
||||
<cac:AccountingSupplierParty>
|
||||
<cac:Party>
|
||||
<cac:PostalAddress>
|
||||
<cbc:StreetName>Ecke 12</cbc:StreetName>
|
||||
<cbc:CityName>Stadthausen</cbc:CityName>
|
||||
<cbc:PostalZone>12345</cbc:PostalZone>
|
||||
<cac:Country>
|
||||
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||
</cac:Country>
|
||||
</cac:PostalAddress>
|
||||
<cac:PartyTaxScheme>
|
||||
<cbc:CompanyID>DE136695976</cbc:CompanyID>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:PartyTaxScheme>
|
||||
<cac:PartyLegalEntity>
|
||||
<cbc:RegistrationName>Bei Spiel GmbH</cbc:RegistrationName>
|
||||
</cac:PartyLegalEntity>
|
||||
</cac:Party>
|
||||
</cac:AccountingSupplierParty>
|
||||
<cac:AccountingCustomerParty>
|
||||
<cac:Party>
|
||||
<cac:PartyIdentification>
|
||||
<cbc:ID>2</cbc:ID>
|
||||
</cac:PartyIdentification>
|
||||
<cac:PostalAddress>
|
||||
<cbc:StreetName>Bahnstr. 42</cbc:StreetName>
|
||||
<cbc:CityName>Spielkreis</cbc:CityName>
|
||||
<cbc:PostalZone>88802</cbc:PostalZone>
|
||||
<cac:Country>
|
||||
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||
</cac:Country>
|
||||
</cac:PostalAddress>
|
||||
<cac:PartyLegalEntity>
|
||||
<cbc:RegistrationName>Theodor Est</cbc:RegistrationName>
|
||||
</cac:PartyLegalEntity>
|
||||
</cac:Party>
|
||||
</cac:AccountingCustomerParty>
|
||||
<cac:Delivery>
|
||||
<cbc:ActualDeliveryDate>2020-11-10</cbc:ActualDeliveryDate>
|
||||
</cac:Delivery>
|
||||
<cac:PaymentMeans>
|
||||
<cbc:PaymentMeansCode name="Bank transfer">42</cbc:PaymentMeansCode>
|
||||
<cbc:PaymentID>RE-20201121/508</cbc:PaymentID>
|
||||
<cac:PayeeFinancialAccount>
|
||||
<cbc:ID>DE88200800000970375700</cbc:ID>
|
||||
<cbc:Name>Max Mustermann</cbc:Name>
|
||||
<cac:FinancialInstitutionBranch>
|
||||
<cbc:ID>COBADEFFXXX</cbc:ID>
|
||||
</cac:FinancialInstitutionBranch>
|
||||
</cac:PayeeFinancialAccount>
|
||||
</cac:PaymentMeans>
|
||||
<cac:PaymentTerms>
|
||||
<cbc:Note>Zahlbar ohne Abzug bis 12.12.2020</cbc:Note>
|
||||
</cac:PaymentTerms>
|
||||
<cac:TaxTotal>
|
||||
<cbc:TaxAmount currencyID="EUR">75.04</cbc:TaxAmount>
|
||||
<cac:TaxSubtotal>
|
||||
<cbc:TaxableAmount currencyID="EUR">160</cbc:TaxableAmount>
|
||||
<cbc:TaxAmount currencyID="EUR">11.2</cbc:TaxAmount>
|
||||
<cac:TaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>7</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:TaxCategory>
|
||||
</cac:TaxSubtotal>
|
||||
<cac:TaxSubtotal>
|
||||
<cbc:TaxableAmount currencyID="EUR">336</cbc:TaxableAmount>
|
||||
<cbc:TaxAmount currencyID="EUR">63.84</cbc:TaxAmount>
|
||||
<cac:TaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>19</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:TaxCategory>
|
||||
</cac:TaxSubtotal>
|
||||
</cac:TaxTotal>
|
||||
<cac:LegalMonetaryTotal>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">496</cbc:LineExtensionAmount>
|
||||
<cbc:TaxExclusiveAmount currencyID="EUR">496</cbc:TaxExclusiveAmount>
|
||||
<cbc:TaxInclusiveAmount currencyID="EUR">571.04</cbc:TaxInclusiveAmount>
|
||||
<cbc:AllowanceTotalAmount currencyID="EUR">0</cbc:AllowanceTotalAmount>
|
||||
<cbc:ChargeTotalAmount currencyID="EUR">0</cbc:ChargeTotalAmount>
|
||||
<cbc:PrepaidAmount currencyID="EUR">0</cbc:PrepaidAmount>
|
||||
<cbc:PayableAmount currencyID="EUR">571.04</cbc:PayableAmount>
|
||||
</cac:LegalMonetaryTotal>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>1</cbc:ID>
|
||||
<cbc:InvoicedQuantity unitCode="HUR">1</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">160</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Description>Of a sample invoice</cbc:Description>
|
||||
<cbc:Name>Design (hours)</cbc:Name>
|
||||
<cac:ClassifiedTaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>7</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:ClassifiedTaxCategory>
|
||||
</cac:Item>
|
||||
<cac:Price>
|
||||
<cbc:PriceAmount currencyID="EUR">160</cbc:PriceAmount>
|
||||
<cbc:BaseQuantity unitCode="HUR">1</cbc:BaseQuantity>
|
||||
<cac:AllowanceCharge>
|
||||
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
|
||||
<cbc:Amount currencyID="EUR">0</cbc:Amount>
|
||||
<cbc:BaseAmount currencyID="EUR">160</cbc:BaseAmount>
|
||||
</cac:AllowanceCharge>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>2</cbc:ID>
|
||||
</cac:PartyIdentification>
|
||||
<cac:PartyName>
|
||||
<cbc:Name>Theodor Est</cbc:Name>
|
||||
</cac:PartyName>
|
||||
<cac:PostalAddress>
|
||||
<cbc:StreetName>Bahnstr. 42</cbc:StreetName>
|
||||
<cbc:CityName>Spielkreis</cbc:CityName>
|
||||
<cbc:PostalZone>88802</cbc:PostalZone>
|
||||
<cac:Country>
|
||||
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||
</cac:Country>
|
||||
</cac:PostalAddress>
|
||||
<cac:PartyLegalEntity>
|
||||
<cbc:RegistrationName>Theodor Est</cbc:RegistrationName>
|
||||
</cac:PartyLegalEntity>
|
||||
</cac:Party>
|
||||
</cac:AccountingCustomerParty>
|
||||
<cac:Delivery>
|
||||
<cbc:ActualDeliveryDate>2020-11-10</cbc:ActualDeliveryDate>
|
||||
</cac:Delivery>
|
||||
<cac:PaymentMeans>
|
||||
<cbc:PaymentMeansCode name="Bank transfer">42</cbc:PaymentMeansCode>
|
||||
<cbc:PaymentID>RE-20201121/508</cbc:PaymentID>
|
||||
<cac:PayeeFinancialAccount>
|
||||
<cbc:ID>DE88200800000970375700</cbc:ID>
|
||||
<cbc:Name>Max Mustermann</cbc:Name>
|
||||
<cac:FinancialInstitutionBranch>
|
||||
<cbc:ID>COBADEFFXXX</cbc:ID>
|
||||
</cac:FinancialInstitutionBranch>
|
||||
</cac:PayeeFinancialAccount>
|
||||
</cac:PaymentMeans>
|
||||
<cac:PaymentTerms>
|
||||
<cbc:Note>Zahlbar ohne Abzug bis 12.12.2020</cbc:Note>
|
||||
</cac:PaymentTerms>
|
||||
<cac:TaxTotal>
|
||||
<cbc:TaxAmount currencyID="EUR">75.04</cbc:TaxAmount>
|
||||
<cac:TaxSubtotal>
|
||||
<cbc:TaxableAmount currencyID="EUR">160</cbc:TaxableAmount>
|
||||
<cbc:TaxAmount currencyID="EUR">11.2</cbc:TaxAmount>
|
||||
<cac:TaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>7</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:TaxCategory>
|
||||
</cac:TaxSubtotal>
|
||||
<cac:TaxSubtotal>
|
||||
<cbc:TaxableAmount currencyID="EUR">336</cbc:TaxableAmount>
|
||||
<cbc:TaxAmount currencyID="EUR">63.84</cbc:TaxAmount>
|
||||
<cac:TaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>19</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:TaxCategory>
|
||||
</cac:TaxSubtotal>
|
||||
</cac:TaxTotal>
|
||||
<cac:LegalMonetaryTotal>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">496</cbc:LineExtensionAmount>
|
||||
<cbc:TaxExclusiveAmount currencyID="EUR">496</cbc:TaxExclusiveAmount>
|
||||
<cbc:TaxInclusiveAmount currencyID="EUR">571.04</cbc:TaxInclusiveAmount>
|
||||
<cbc:AllowanceTotalAmount currencyID="EUR">0</cbc:AllowanceTotalAmount>
|
||||
<cbc:ChargeTotalAmount currencyID="EUR">0</cbc:ChargeTotalAmount>
|
||||
<cbc:PrepaidAmount currencyID="EUR">0</cbc:PrepaidAmount>
|
||||
<cbc:PayableAmount currencyID="EUR">571.04</cbc:PayableAmount>
|
||||
</cac:LegalMonetaryTotal>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>1</cbc:ID>
|
||||
<cbc:InvoicedQuantity unitCode="HUR">1</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">160</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Description>Of a sample invoice</cbc:Description>
|
||||
<cbc:Name>Design (hours)</cbc:Name>
|
||||
<cac:ClassifiedTaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>7</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:ClassifiedTaxCategory>
|
||||
</cac:Item>
|
||||
<cac:Price>
|
||||
<cbc:PriceAmount currencyID="EUR">160</cbc:PriceAmount>
|
||||
<cbc:BaseQuantity unitCode="HUR">1</cbc:BaseQuantity>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>2</cbc:ID>
|
||||
<cbc:InvoicedQuantity unitCode="H87">400</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">316</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Description>various colors, ~2000ml</cbc:Description>
|
||||
<cbc:Name>Ballons</cbc:Name>
|
||||
<cac:ClassifiedTaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>19</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:ClassifiedTaxCategory>
|
||||
</cac:Item>
|
||||
<cac:Price>
|
||||
<cbc:PriceAmount currencyID="EUR">0.79</cbc:PriceAmount>
|
||||
<cbc:BaseQuantity unitCode="H87">1</cbc:BaseQuantity>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>3</cbc:ID>
|
||||
<cbc:InvoicedQuantity unitCode="LTR">800</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">20</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Name>Hot air „heiße Luft“ (litres)</cbc:Name>
|
||||
<cac:ClassifiedTaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>19</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:ClassifiedTaxCategory>
|
||||
</cac:Item>
|
||||
<cac:Price>
|
||||
<cbc:PriceAmount currencyID="EUR">0.025</cbc:PriceAmount>
|
||||
<cbc:BaseQuantity unitCode="LTR">1</cbc:BaseQuantity>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
<cbc:InvoicedQuantity unitCode="H87">400</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">316</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Description>various colors, ~2000ml</cbc:Description>
|
||||
<cbc:Name>Ballons</cbc:Name>
|
||||
<cac:ClassifiedTaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>19</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:ClassifiedTaxCategory>
|
||||
</cac:Item>
|
||||
<cac:Price>
|
||||
<cbc:PriceAmount currencyID="EUR">0.79</cbc:PriceAmount>
|
||||
<cbc:BaseQuantity unitCode="H87">1</cbc:BaseQuantity>
|
||||
<cac:AllowanceCharge>
|
||||
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
|
||||
<cbc:Amount currencyID="EUR">0</cbc:Amount>
|
||||
<cbc:BaseAmount currencyID="EUR">0.79</cbc:BaseAmount>
|
||||
</cac:AllowanceCharge>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>3</cbc:ID>
|
||||
<cbc:InvoicedQuantity unitCode="LTR">800</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">20</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Name>Hot air „heiße Luft“ (litres)</cbc:Name>
|
||||
<cac:ClassifiedTaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>19</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:ClassifiedTaxCategory>
|
||||
</cac:Item>
|
||||
<cac:Price>
|
||||
<cbc:PriceAmount currencyID="EUR">0.025</cbc:PriceAmount>
|
||||
<cbc:BaseQuantity unitCode="LTR">1</cbc:BaseQuantity>
|
||||
<cac:AllowanceCharge>
|
||||
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
|
||||
<cbc:Amount currencyID="EUR">0</cbc:Amount>
|
||||
<cbc:BaseAmount currencyID="EUR">0.025</cbc:BaseAmount>
|
||||
</cac:AllowanceCharge>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
</Invoice>
|
||||
@@ -2,7 +2,8 @@
|
||||
<ubl:Invoice xmlns:ubl="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
|
||||
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
||||
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3</cbc:CustomizationID>
|
||||
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0</cbc:CustomizationID>
|
||||
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
|
||||
<cbc:ID>123456XX</cbc:ID>
|
||||
<cbc:IssueDate>2016-04-04</cbc:IssueDate>
|
||||
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||
@@ -11,6 +12,7 @@
|
||||
<cbc:BuyerReference>04011000-12345-03</cbc:BuyerReference>
|
||||
<cac:AccountingSupplierParty>
|
||||
<cac:Party>
|
||||
<cbc:EndpointID schemeID="EM">seller@email.de</cbc:EndpointID>
|
||||
<cac:PartyName>
|
||||
<cbc:Name>[Seller trading name]</cbc:Name>
|
||||
</cac:PartyName>
|
||||
@@ -42,6 +44,7 @@
|
||||
</cac:AccountingSupplierParty>
|
||||
<cac:AccountingCustomerParty>
|
||||
<cac:Party>
|
||||
<cbc:EndpointID schemeID="EM">buyer@info.de</cbc:EndpointID>
|
||||
<cac:PartyIdentification>
|
||||
<cbc:ID>[Buyer identifier]</cbc:ID>
|
||||
</cac:PartyIdentification>
|
||||
260
library/src/test/resources/ubl/EN16931_1_Teilrechnung.ubl.xml
Normal file
260
library/src/test/resources/ubl/EN16931_1_Teilrechnung.ubl.xml
Normal file
@@ -0,0 +1,260 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cec="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
|
||||
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
|
||||
<cbc:ID>471102</cbc:ID>
|
||||
<cbc:IssueDate>2018-06-05</cbc:IssueDate>
|
||||
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
|
||||
<cbc:Note>Rechnung gemäß Bestellung Nr. 2018-471331 vom 01.03.2018.</cbc:Note>
|
||||
<cbc:Note>#AAK#Es bestehen Rabatt- und Bonusvereinbarungen.</cbc:Note>
|
||||
<cbc:Note>#REG#Lieferant GmbH
|
||||
Lieferantenstraße 20
|
||||
80333 München
|
||||
Deutschland
|
||||
Geschäftsführer: Hans Muster
|
||||
Handelsregisternummer: H A 123
|
||||
</cbc:Note>
|
||||
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
|
||||
<cac:OrderReference>
|
||||
<cbc:ID>2018-471331</cbc:ID>
|
||||
</cac:OrderReference>
|
||||
<cac:AccountingSupplierParty>
|
||||
<cac:Party>
|
||||
<cac:PartyIdentification>
|
||||
<cbc:ID schemeID="0088">4000001123452</cbc:ID>
|
||||
</cac:PartyIdentification>
|
||||
<cac:PartyName>
|
||||
<cbc:Name>Lieferant GmbH</cbc:Name>
|
||||
</cac:PartyName>
|
||||
<cac:PostalAddress>
|
||||
<cbc:StreetName>Lieferantenstraße 20</cbc:StreetName>
|
||||
<cbc:CityName>München</cbc:CityName>
|
||||
<cbc:PostalZone>80333</cbc:PostalZone>
|
||||
<cac:Country>
|
||||
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||
</cac:Country>
|
||||
</cac:PostalAddress>
|
||||
<cac:PartyTaxScheme>
|
||||
<cbc:CompanyID>201/113/40209</cbc:CompanyID>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>FC</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:PartyTaxScheme>
|
||||
<cac:PartyTaxScheme>
|
||||
<cbc:CompanyID>DE123456789</cbc:CompanyID>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:PartyTaxScheme>
|
||||
<cac:PartyLegalEntity>
|
||||
<cbc:RegistrationName>Lieferant GmbH</cbc:RegistrationName>
|
||||
</cac:PartyLegalEntity>
|
||||
</cac:Party>
|
||||
</cac:AccountingSupplierParty>
|
||||
<cac:AccountingCustomerParty>
|
||||
<cac:Party>
|
||||
<cac:PartyIdentification>
|
||||
<cbc:ID>GE2020211</cbc:ID>
|
||||
</cac:PartyIdentification>
|
||||
<cac:PartyName>
|
||||
<cbc:Name>Kunden AG Mitte</cbc:Name>
|
||||
</cac:PartyName>
|
||||
<cac:PostalAddress>
|
||||
<cbc:StreetName>Kundenstraße 15</cbc:StreetName>
|
||||
<cbc:CityName>Frankfurt</cbc:CityName>
|
||||
<cbc:PostalZone>69876</cbc:PostalZone>
|
||||
<cac:Country>
|
||||
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
|
||||
</cac:Country>
|
||||
</cac:PostalAddress>
|
||||
<cac:PartyLegalEntity>
|
||||
<cbc:RegistrationName>Kunden AG Mitte</cbc:RegistrationName>
|
||||
</cac:PartyLegalEntity>
|
||||
</cac:Party>
|
||||
</cac:AccountingCustomerParty>
|
||||
<cac:Delivery>
|
||||
<cbc:ActualDeliveryDate>2018-06-03</cbc:ActualDeliveryDate>
|
||||
</cac:Delivery>
|
||||
<cac:PaymentTerms>
|
||||
<cbc:Note>Zahlbar innerhalb 30 Tagen netto bis 04.07.2018, 3% Skonto innerhalb 10 Tagen bis 15.06.2018</cbc:Note>
|
||||
</cac:PaymentTerms>
|
||||
<cac:AllowanceCharge>
|
||||
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
|
||||
<cbc:AllowanceChargeReason>Sondernachlass</cbc:AllowanceChargeReason>
|
||||
<cbc:Amount currencyID="EUR">1</cbc:Amount>
|
||||
<cbc:BaseAmount currencyID="EUR">10</cbc:BaseAmount>
|
||||
<cac:TaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>19</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:TaxCategory>
|
||||
</cac:AllowanceCharge>
|
||||
<cac:AllowanceCharge>
|
||||
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
|
||||
<cbc:AllowanceChargeReason>Sondernachlass</cbc:AllowanceChargeReason>
|
||||
<cbc:Amount currencyID="EUR">8.07</cbc:Amount>
|
||||
<cbc:BaseAmount currencyID="EUR">115.3</cbc:BaseAmount>
|
||||
<cac:TaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>7</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:TaxCategory>
|
||||
</cac:AllowanceCharge>
|
||||
<cac:AllowanceCharge>
|
||||
<cbc:ChargeIndicator>true</cbc:ChargeIndicator>
|
||||
<cbc:AllowanceChargeReason>Versandkosten</cbc:AllowanceChargeReason>
|
||||
<cbc:Amount currencyID="EUR">5.8</cbc:Amount>
|
||||
<cbc:BaseAmount currencyID="EUR">115.3</cbc:BaseAmount>
|
||||
<cac:TaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>7</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:TaxCategory>
|
||||
</cac:AllowanceCharge>
|
||||
<cac:TaxTotal>
|
||||
<cbc:TaxAmount currencyID="EUR">20.16</cbc:TaxAmount>
|
||||
<cac:TaxSubtotal>
|
||||
<cbc:TaxableAmount currencyID="EUR">113.03</cbc:TaxableAmount>
|
||||
<cbc:TaxAmount currencyID="EUR">7.91</cbc:TaxAmount>
|
||||
<cac:TaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>7</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:TaxCategory>
|
||||
</cac:TaxSubtotal>
|
||||
<cac:TaxSubtotal>
|
||||
<cbc:TaxableAmount currencyID="EUR">64.46</cbc:TaxableAmount>
|
||||
<cbc:TaxAmount currencyID="EUR">12.25</cbc:TaxAmount>
|
||||
<cac:TaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>19</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:TaxCategory>
|
||||
</cac:TaxSubtotal>
|
||||
</cac:TaxTotal>
|
||||
<cac:LegalMonetaryTotal>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">180.76</cbc:LineExtensionAmount>
|
||||
<cbc:TaxExclusiveAmount currencyID="EUR">177.49</cbc:TaxExclusiveAmount>
|
||||
<cbc:TaxInclusiveAmount currencyID="EUR">197.65</cbc:TaxInclusiveAmount>
|
||||
<cbc:AllowanceTotalAmount currencyID="EUR">9.07</cbc:AllowanceTotalAmount>
|
||||
<cbc:ChargeTotalAmount currencyID="EUR">5.8</cbc:ChargeTotalAmount>
|
||||
<cbc:PrepaidAmount currencyID="EUR">50</cbc:PrepaidAmount>
|
||||
<cbc:PayableAmount currencyID="EUR">147.65</cbc:PayableAmount>
|
||||
</cac:LegalMonetaryTotal>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>1</cbc:ID>
|
||||
<cbc:Note>Wir erlauben uns Ihnen folgende Positionen aus der Lieferung Nr. 2018-51112 in Rechnung zu stellen:</cbc:Note>
|
||||
<cbc:InvoicedQuantity unitCode="MTK">3</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">10</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Description>300cm x 100 cm</cbc:Description>
|
||||
<cbc:Name>Kunstrasen grün 3m breit</cbc:Name>
|
||||
<cac:SellersItemIdentification>
|
||||
<cbc:ID>KR3M</cbc:ID>
|
||||
</cac:SellersItemIdentification>
|
||||
<cac:StandardItemIdentification>
|
||||
<cbc:ID schemeID="0160">4012345001235</cbc:ID>
|
||||
</cac:StandardItemIdentification>
|
||||
<cac:ClassifiedTaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>19</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:ClassifiedTaxCategory>
|
||||
</cac:Item>
|
||||
<cac:Price>
|
||||
<cbc:PriceAmount currencyID="EUR">3.3333</cbc:PriceAmount>
|
||||
<cac:AllowanceCharge>
|
||||
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
|
||||
<cbc:Amount currencyID="EUR">0.6667</cbc:Amount>
|
||||
</cac:AllowanceCharge>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>2</cbc:ID>
|
||||
<cbc:Note>Bestellt wurden 5 kg Schweinesteak. Mit dieser Rechnung werden nur die bereits gelieferten Steaks berechnet. Die noch offenen 4 kg Schweinesteak werden separat geliefert und berechnet.</cbc:Note>
|
||||
<cbc:InvoicedQuantity unitCode="KGM">1</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">5.5</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Description>Schweinesteak aus Deutschland</cbc:Description>
|
||||
<cbc:Name>Schweinesteak</cbc:Name>
|
||||
<cac:SellersItemIdentification>
|
||||
<cbc:ID>SFK5</cbc:ID>
|
||||
</cac:SellersItemIdentification>
|
||||
<cac:StandardItemIdentification>
|
||||
<cbc:ID schemeID="0160">4000050986428</cbc:ID>
|
||||
</cac:StandardItemIdentification>
|
||||
<cac:ClassifiedTaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>7</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:ClassifiedTaxCategory>
|
||||
</cac:Item>
|
||||
<cac:Price>
|
||||
<cbc:PriceAmount currencyID="EUR">5.5</cbc:PriceAmount>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>3</cbc:ID>
|
||||
<cbc:InvoicedQuantity unitCode="H87">20</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">109.8</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Name>Mineralwasser Medium
|
||||
12 x 1,0l PET
|
||||
</cbc:Name>
|
||||
<cac:SellersItemIdentification>
|
||||
<cbc:ID>GTRWA5</cbc:ID>
|
||||
</cac:SellersItemIdentification>
|
||||
<cac:StandardItemIdentification>
|
||||
<cbc:ID schemeID="0160">4000001234561</cbc:ID>
|
||||
</cac:StandardItemIdentification>
|
||||
<cac:ClassifiedTaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>7</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:ClassifiedTaxCategory>
|
||||
</cac:Item>
|
||||
<cac:Price>
|
||||
<cbc:PriceAmount currencyID="EUR">5.49</cbc:PriceAmount>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>4</cbc:ID>
|
||||
<cbc:InvoicedQuantity unitCode="C62">20</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="EUR">55.46</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Name>Pfand</cbc:Name>
|
||||
<cac:SellersItemIdentification>
|
||||
<cbc:ID>PFA5</cbc:ID>
|
||||
</cac:SellersItemIdentification>
|
||||
<cac:StandardItemIdentification>
|
||||
<cbc:ID schemeID="0160">4000001234578</cbc:ID>
|
||||
</cac:StandardItemIdentification>
|
||||
<cac:ClassifiedTaxCategory>
|
||||
<cbc:ID>S</cbc:ID>
|
||||
<cbc:Percent>19</cbc:Percent>
|
||||
<cac:TaxScheme>
|
||||
<cbc:ID>VAT</cbc:ID>
|
||||
</cac:TaxScheme>
|
||||
</cac:ClassifiedTaxCategory>
|
||||
</cac:Item>
|
||||
<cac:Price>
|
||||
<cbc:PriceAmount currencyID="EUR">2.77</cbc:PriceAmount>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
</Invoice>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user