Merge branch 'temp_for_upstream_merge_of_PR4_08_2019'
This is necessary because the automatic rebase of pull request https://github.com/seeburger-ag/PDFA3/pull/4 did not work. Merge is done via command line as suggested by GitHub.
This commit is contained in:
17
History.md
17
History.md
@@ -1,10 +1,27 @@
|
|||||||
|
1.7.3
|
||||||
|
=====
|
||||||
|
2019-08-01
|
||||||
|
|
||||||
|
- #105 does not build in windows
|
||||||
|
- #99 BOMs confuse parser
|
||||||
|
- updated javadoc
|
||||||
|
- fixed #104 nullpointerex when specifying no parameter
|
||||||
|
- PR #112 complete profile options for v1
|
||||||
|
- access to TotalPrepaidAmount in ZF v1 #118
|
||||||
|
- have unit tests for nDigitFormat #23
|
||||||
|
|
||||||
|
|
||||||
1.7.2
|
1.7.2
|
||||||
=====
|
=====
|
||||||
|
2019-07-08
|
||||||
|
|
||||||
Support BuyerReference (r+w), as well as SpecifiedLegalOrganization (w) and DefinedTradeContact (w)
|
Support BuyerReference (r+w), as well as SpecifiedLegalOrganization (w) and DefinedTradeContact (w)
|
||||||
use dom4j to format output xml document
|
use dom4j to format output xml document
|
||||||
corrected some exception logging glitches
|
corrected some exception logging glitches
|
||||||
|
upgrade PDFBox to 2.0.15+
|
||||||
|
extraction to use proper filename instead of alias #98
|
||||||
|
NullPointerException in ZUGFeRDImporter.extractLowLevel #96
|
||||||
|
Removed Bankleitzahl from ZF2
|
||||||
|
|
||||||
|
|
||||||
1.7.1
|
1.7.1
|
||||||
|
|||||||
27
pom.xml
27
pom.xml
@@ -1,10 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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"
|
<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">
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.mustangproject.ZUGFeRD</groupId>
|
<groupId>org.mustangproject.ZUGFeRD</groupId>
|
||||||
<artifactId>mustang</artifactId>
|
<artifactId>mustang</artifactId>
|
||||||
<version>1.7.2-SNAPSHOT</version>
|
<version>1.7.4-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>Mustang</name>
|
<name>Mustang</name>
|
||||||
<description>The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs
|
<description>The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs
|
||||||
@@ -14,7 +13,7 @@
|
|||||||
<connection>scm:git:https://github.com/ZUGFeRD/mustangproject.git</connection>
|
<connection>scm:git:https://github.com/ZUGFeRD/mustangproject.git</connection>
|
||||||
<developerConnection>scm:git:https://github.com/ZUGFeRD/mustangproject.git</developerConnection>
|
<developerConnection>scm:git:https://github.com/ZUGFeRD/mustangproject.git</developerConnection>
|
||||||
<url>https://github.com/ZUGFeRD/mustangproject</url>
|
<url>https://github.com/ZUGFeRD/mustangproject</url>
|
||||||
<tag>mustang-1.5.2</tag>
|
<tag>mustang-1.7.3</tag>
|
||||||
</scm>
|
</scm>
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository><!-- for jargs -->
|
<repository><!-- for jargs -->
|
||||||
@@ -66,15 +65,26 @@
|
|||||||
<artifactId>jaxb-runtime</artifactId>
|
<artifactId>jaxb-runtime</artifactId>
|
||||||
<version>2.2.11</version>
|
<version>2.2.11</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.xml.bind</groupId>
|
||||||
|
<artifactId>jaxb-api</artifactId>
|
||||||
|
<version>2.2.11</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.activation</groupId>
|
||||||
|
<artifactId>activation</artifactId>
|
||||||
|
<version>1.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.pdfbox</groupId>
|
<groupId>org.apache.pdfbox</groupId>
|
||||||
<artifactId>preflight</artifactId>
|
<artifactId>preflight</artifactId>
|
||||||
<version>2.0.12</version>
|
<version>[2.0.15,)</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.pdfbox</groupId>
|
<groupId>org.apache.pdfbox</groupId>
|
||||||
<artifactId>pdfbox</artifactId>
|
<artifactId>pdfbox</artifactId>
|
||||||
<version>2.0.12</version>
|
<version>[2.0.15,)</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dom4j</groupId>
|
<groupId>org.dom4j</groupId>
|
||||||
@@ -203,8 +213,7 @@
|
|||||||
<version>2.4.3</version>
|
<version>2.4.3</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<transformers>
|
<transformers>
|
||||||
<transformer
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
|
||||||
<mainClass>org.mustangproject.toecount.Toecount</mainClass>
|
<mainClass>org.mustangproject.toecount.Toecount</mainClass>
|
||||||
</transformer>
|
</transformer>
|
||||||
</transformers>
|
</transformers>
|
||||||
@@ -279,7 +288,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<artifactId>jaxb2-maven-plugin</artifactId>
|
<artifactId>jaxb2-maven-plugin</artifactId>
|
||||||
<version>2.3.1</version>
|
<version>2.5.0</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>xjc</id>
|
<id>xjc</id>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
*********************************************************************** */
|
*********************************************************************** */
|
||||||
package org.mustangproject.ZUGFeRD;
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
public class CustomXMLProvider implements IXMLProvider {
|
public class CustomXMLProvider implements IXMLProvider, IProfileProvider {
|
||||||
|
|
||||||
protected byte[] zugferdData;
|
protected byte[] zugferdData;
|
||||||
|
|
||||||
@@ -48,4 +48,14 @@ public class CustomXMLProvider implements IXMLProvider {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProfile() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProfile(ZUGFeRDConformanceLevel level) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,13 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public interface IExporterFactory {
|
public interface IExporterFactory {
|
||||||
|
/**
|
||||||
|
* factory: loads a PDF file and returns an appropriate exporter
|
||||||
|
*
|
||||||
|
* @param pdfFilename binary of a PDF/A1 compliant document
|
||||||
|
* @return the generated exporter
|
||||||
|
* @throws IOException if anything is wrong with filename
|
||||||
|
*/
|
||||||
public ZUGFeRDExporter load(String pdfFilename) throws IOException;
|
public ZUGFeRDExporter load(String pdfFilename) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,6 +36,8 @@ public interface IExporterFactory {
|
|||||||
* metadata level, this will not e.g. convert graphics to JPG-2000)
|
* metadata level, this will not e.g. convert graphics to JPG-2000)
|
||||||
*
|
*
|
||||||
* @param pdfBinary binary of a PDF/A1 compliant document
|
* @param pdfBinary binary of a PDF/A1 compliant document
|
||||||
|
* @return the generated exporter
|
||||||
|
* @throws IOException (should not happen at all)
|
||||||
*/
|
*/
|
||||||
public ZUGFeRDExporter load(byte[] pdfBinary) throws IOException;
|
public ZUGFeRDExporter load(byte[] pdfBinary) throws IOException;
|
||||||
|
|
||||||
@@ -37,7 +46,8 @@ public interface IExporterFactory {
|
|||||||
* metadata level, this will not e.g. convert graphics to JPG-2000)
|
* metadata level, this will not e.g. convert graphics to JPG-2000)
|
||||||
*
|
*
|
||||||
* @param pdfSource source to read a PDF/A1 compliant document from
|
* @param pdfSource source to read a PDF/A1 compliant document from
|
||||||
* @throws IOException
|
* @throws IOException if anything is wrong with inputstream
|
||||||
|
* @return the generated ZUGFeRDExporter
|
||||||
*/
|
*/
|
||||||
public ZUGFeRDExporter load(InputStream pdfSource) throws IOException;
|
public ZUGFeRDExporter load(InputStream pdfSource) throws IOException;
|
||||||
|
|
||||||
|
|||||||
@@ -21,5 +21,7 @@ package org.mustangproject.ZUGFeRD;
|
|||||||
public interface IProfileProvider {
|
public interface IProfileProvider {
|
||||||
|
|
||||||
public String getProfile();
|
public String getProfile();
|
||||||
|
|
||||||
|
public void setProfile(ZUGFeRDConformanceLevel level);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,11 @@
|
|||||||
package org.mustangproject.ZUGFeRD;
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mustangproject's ZUGFeRD implementation Neccessary interface for ZUGFeRD exporter Licensed under the APLv2
|
* Mustangproject's ZUGFeRD implementation neccessary interface for ZUGFeRD exporter Licensed under the APLv2
|
||||||
*
|
*
|
||||||
* @author jstaerk
|
* @author jstaerk
|
||||||
* @version 1.2.0
|
* @version 1.2.0
|
||||||
* @date 2014-05-10
|
* dated 2014-05-10
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -38,6 +38,24 @@ public interface IZUGFeRDExportableContact {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* customer global identification assigned by the seller
|
||||||
|
*
|
||||||
|
* @return customer identification
|
||||||
|
*/
|
||||||
|
default String getGlobalID() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* customer global identification scheme
|
||||||
|
*
|
||||||
|
* @return customer identification
|
||||||
|
*/
|
||||||
|
default String getGlobalIDScheme() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First and last name of the recipient
|
* First and last name of the recipient
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import java.math.BigDecimal;
|
|||||||
*
|
*
|
||||||
* @author jstaerk
|
* @author jstaerk
|
||||||
* @version 1.2.0
|
* @version 1.2.0
|
||||||
* @date 2014-05-10
|
* dated 2014-05-10
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface IZUGFeRDExportableProduct {
|
public interface IZUGFeRDExportableProduct {
|
||||||
|
|||||||
@@ -29,10 +29,19 @@ package org.mustangproject.ZUGFeRD;
|
|||||||
|
|
||||||
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
|
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
public interface IZUGFeRDExportableTransaction {
|
public interface IZUGFeRDExportableTransaction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* appears in /rsm:CrossIndustryDocument/rsm:HeaderExchangedDocument/ram:Name
|
||||||
|
* @return Name of document
|
||||||
|
*/
|
||||||
|
default String getDocumentName() {
|
||||||
|
return "RECHNUNG";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@@ -64,7 +73,7 @@ public interface IZUGFeRDExportableTransaction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* this should be the full sender institution name, details, manager and tax registration. It is one of the few functions which may return null. e.g.
|
* this should be the full sender institution name, details, manager and tax registration. It is one of the few functions which may return null. e.g.
|
||||||
* <p/>
|
* <p>
|
||||||
* Lieferant GmbH Lieferantenstraße 20 80333 München Deutschland Geschäftsführer: Hans Muster Handelsregisternummer: H A 123
|
* Lieferant GmbH Lieferantenstraße 20 80333 München Deutschland Geschäftsführer: Hans Muster Handelsregisternummer: H A 123
|
||||||
*
|
*
|
||||||
* @return null or full sender institution name, details, manager and tax registration
|
* @return null or full sender institution name, details, manager and tax registration
|
||||||
@@ -115,6 +124,8 @@ public interface IZUGFeRDExportableTransaction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* the creditors payment informations
|
* the creditors payment informations
|
||||||
|
*
|
||||||
|
* @return an array of IZUGFeRDTradeSettlementPayment
|
||||||
*/
|
*/
|
||||||
IZUGFeRDTradeSettlementPayment[] getTradeSettlementPayment();
|
IZUGFeRDTradeSettlementPayment[] getTradeSettlementPayment();
|
||||||
|
|
||||||
@@ -236,4 +247,23 @@ public interface IZUGFeRDExportableTransaction {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the ID of the BuyerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement
|
||||||
|
* @return the ID of the document
|
||||||
|
*/
|
||||||
|
default String getBuyerOrderReferencedDocumentID() { return null; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the issue timestamp of the BuyerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement
|
||||||
|
* @return the IssueDateTime in format CCYY-MM-DDTHH:MM:SS
|
||||||
|
*/
|
||||||
|
default String getBuyerOrderReferencedDocumentIssueDateTime() { return null; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the TotalPrepaidAmount located in SpecifiedTradeSettlementMonetarySummation (v1) or
|
||||||
|
* SpecifiedTradeSettlementHeaderMonetarySummation (v2)
|
||||||
|
* @return the total sum (incl. VAT) of prepayments, i.e. the difference between GrandTotalAmount
|
||||||
|
* and DuePayableAmount
|
||||||
|
*/
|
||||||
|
default BigDecimal getTotalPrepaidAmount() { return BigDecimal.ZERO; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,20 +27,20 @@ import java.math.BigDecimal;
|
|||||||
*
|
*
|
||||||
* @author jstaerk
|
* @author jstaerk
|
||||||
* @version 1.2.0
|
* @version 1.2.0
|
||||||
* @date 2015-10-29
|
* dated 2015-10-29
|
||||||
*/
|
*/
|
||||||
public class VATAmount {
|
public class VATAmount {
|
||||||
|
|
||||||
public VATAmount(BigDecimal basis, BigDecimal calculated, String documentCode) {
|
public VATAmount(BigDecimal basis, BigDecimal calculated, String categoryCode) {
|
||||||
super();
|
super();
|
||||||
this.basis = basis;
|
this.basis = basis;
|
||||||
this.calculated = calculated;
|
this.calculated = calculated;
|
||||||
this.documentCode = documentCode;
|
this.categoryCode = categoryCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigDecimal basis, calculated;
|
BigDecimal basis, calculated;
|
||||||
|
|
||||||
String documentCode;
|
String categoryCode;
|
||||||
|
|
||||||
public BigDecimal getBasis() {
|
public BigDecimal getBasis() {
|
||||||
return basis;
|
return basis;
|
||||||
@@ -58,20 +58,39 @@ public class VATAmount {
|
|||||||
this.calculated = calculated;
|
this.calculated = calculated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link #getCategoryCode() instead}
|
||||||
|
* @return String with category code
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public String getDocumentCode() {
|
public String getDocumentCode() {
|
||||||
return documentCode;
|
return categoryCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param documentCode as String
|
||||||
|
* @deprecated Use {@link #setCategoryCode(String)} instead
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setDocumentCode(String documentCode) {
|
public void setDocumentCode(String documentCode) {
|
||||||
this.documentCode = documentCode;
|
this.categoryCode = documentCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCategoryCode() {
|
||||||
|
return categoryCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategoryCode(String categoryCode) {
|
||||||
|
this.categoryCode = categoryCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VATAmount add(VATAmount v) {
|
public VATAmount add(VATAmount v) {
|
||||||
return new VATAmount(basis.add(v.getBasis()), calculated.add(v.getCalculated()), this.documentCode);
|
return new VATAmount(basis.add(v.getBasis()), calculated.add(v.getCalculated()), this.categoryCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public VATAmount subtract(VATAmount v) {
|
public VATAmount subtract(VATAmount v) {
|
||||||
return new VATAmount(basis.subtract(v.getBasis()), calculated.subtract(v.getCalculated()), this.documentCode);
|
return new VATAmount(basis.subtract(v.getBasis()), calculated.subtract(v.getCalculated()), this.categoryCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,13 @@ import org.apache.xmpbox.schema.XMPSchema;
|
|||||||
|
|
||||||
public class XMPSchemaZugferd extends XMPSchema {
|
public class XMPSchemaZugferd extends XMPSchema {
|
||||||
|
|
||||||
/**
|
/***
|
||||||
* This is what needs to be added to the RDF metadata - basically the name of the embedded Zugferd file
|
* This is what needs to be added to the RDF metadata - basically the name of the embedded Zugferd file
|
||||||
|
* @param metadata the xmp to be added to
|
||||||
|
* @param conformanceLevel e.g. conformanceLevel.EN16931
|
||||||
|
* @param URN the xml URI for the XMP
|
||||||
|
* @param prefix the xml namespace prefix for the XMP, zf for ZUGFeRD, fx for Factur-X
|
||||||
|
* @param filename the filename of the invoice
|
||||||
*/
|
*/
|
||||||
public XMPSchemaZugferd(XMPMetadata metadata, ZUGFeRDConformanceLevel conformanceLevel, String URN, String prefix, String filename) {
|
public XMPSchemaZugferd(XMPMetadata metadata, ZUGFeRDConformanceLevel conformanceLevel, String URN, String prefix, String filename) {
|
||||||
super(metadata, URN, prefix, "ZUGFeRD Schema");
|
super(metadata, URN, prefix, "ZUGFeRD Schema");
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
package org.mustangproject.ZUGFeRD;
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
import org.mustangproject.ZUGFeRD.model.CrossIndustryDocumentType;
|
import org.mustangproject.ZUGFeRD.model.CrossIndustryDocumentType;
|
||||||
|
import org.mustangproject.ZUGFeRD.model.DocumentContextParameterTypeConstants;
|
||||||
import org.mustangproject.ZUGFeRD.model.ZFNamespacePrefixMapper;
|
import org.mustangproject.ZUGFeRD.model.ZFNamespacePrefixMapper;
|
||||||
|
|
||||||
import javax.xml.bind.JAXBContext;
|
import javax.xml.bind.JAXBContext;
|
||||||
@@ -27,13 +28,27 @@ import javax.xml.bind.JAXBException;
|
|||||||
import javax.xml.bind.Marshaller;
|
import javax.xml.bind.Marshaller;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
public class ZUGFeRD1PullProvider implements IXMLProvider {
|
public class ZUGFeRD1PullProvider implements IXMLProvider, IProfileProvider {
|
||||||
|
|
||||||
|
|
||||||
protected byte[] zugferdData;
|
protected byte[] zugferdData;
|
||||||
private Marshaller marshaller;
|
private Marshaller marshaller;
|
||||||
|
|
||||||
private boolean isTest;
|
private boolean isTest;
|
||||||
|
private ZUGFeRDConformanceLevel level;
|
||||||
|
|
||||||
|
|
||||||
|
public void setProfile(ZUGFeRDConformanceLevel level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProfile() {
|
||||||
|
switch (level) {
|
||||||
|
case BASIC: return DocumentContextParameterTypeConstants.BASIC;
|
||||||
|
case COMFORT: return DocumentContextParameterTypeConstants.COMFORT;
|
||||||
|
default: return DocumentContextParameterTypeConstants.EXTENDED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,7 +74,7 @@ public class ZUGFeRD1PullProvider implements IXMLProvider {
|
|||||||
private String createZugferdXMLForTransaction(IZUGFeRDExportableTransaction trans) {
|
private String createZugferdXMLForTransaction(IZUGFeRDExportableTransaction trans) {
|
||||||
|
|
||||||
JAXBElement<CrossIndustryDocumentType> jaxElement =
|
JAXBElement<CrossIndustryDocumentType> jaxElement =
|
||||||
new ZUGFeRDTransactionModelConverter(trans).withTest(isTest).convertToModel();
|
new ZUGFeRDTransactionModelConverter(trans).withTest(isTest).withProfile(getProfile()).convertToModel();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return marshalJaxToXMLString(jaxElement);
|
return marshalJaxToXMLString(jaxElement);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.io.IOException;
|
|||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.DecimalFormatSymbols;
|
import java.text.DecimalFormatSymbols;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@@ -70,6 +71,11 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
|
|||||||
|
|
||||||
protected byte[] zugferdData;
|
protected byte[] zugferdData;
|
||||||
private IZUGFeRDExportableTransaction trans;
|
private IZUGFeRDExportableTransaction trans;
|
||||||
|
private ZUGFeRDConformanceLevel level;
|
||||||
|
|
||||||
|
public void setProfile(ZUGFeRDConformanceLevel level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enables the flag to indicate a test invoice in the XML structure
|
* enables the flag to indicate a test invoice in the XML structure
|
||||||
@@ -77,7 +83,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
|
|||||||
public void setTest() {
|
public void setTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String nDigitFormat(BigDecimal value, int scale) {
|
public static String nDigitFormat(BigDecimal value, int scale) {
|
||||||
/*
|
/*
|
||||||
* I needed 123,45, locale independent.I tried
|
* I needed 123,45, locale independent.I tried
|
||||||
* NumberFormat.getCurrencyInstance().format( 12345.6789 ); but that is locale
|
* NumberFormat.getCurrencyInstance().format( 12345.6789 ); but that is locale
|
||||||
@@ -92,44 +98,25 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
|
|||||||
* http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html in the
|
* http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html in the
|
||||||
* end I decided to calculate myself and take eur+sparator+cents
|
* end I decided to calculate myself and take eur+sparator+cents
|
||||||
*
|
*
|
||||||
* This function will cut off, i.e. floor() subcent values Tests:
|
|
||||||
* System.err.println(utils.currencyFormat(new BigDecimal(0),
|
|
||||||
* ".")+"\n"+utils.currencyFormat(new BigDecimal("-1.10"),
|
|
||||||
* ",")+"\n"+utils.currencyFormat(new BigDecimal("-1.1"),
|
|
||||||
* ",")+"\n"+utils.currencyFormat(new BigDecimal("-1.01"),
|
|
||||||
* ",")+"\n"+utils.currencyFormat(new BigDecimal("20000123.3489"),
|
|
||||||
* ",")+"\n"+utils.currencyFormat(new BigDecimal("20000123.3419"),
|
|
||||||
* ",")+"\n"+utils.currencyFormat(new BigDecimal("12"), ","));
|
|
||||||
*
|
|
||||||
* results 0.00 -1,10 -1,10 -1,01 20000123,34 20000123,34 12,00
|
|
||||||
*/
|
*/
|
||||||
value = value.setScale(scale, BigDecimal.ROUND_HALF_UP); // first, round so that e.g.
|
return value.setScale(scale, RoundingMode.HALF_UP).toPlainString();
|
||||||
// 1.189999999999999946709294817992486059665679931640625
|
|
||||||
// becomes 1.19
|
|
||||||
char[] repeat = new char[scale];
|
|
||||||
Arrays.fill(repeat, '0');
|
|
||||||
|
|
||||||
DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols();
|
|
||||||
otherSymbols.setDecimalSeparator('.');
|
|
||||||
DecimalFormat dec = new DecimalFormat("0." + new String(repeat), otherSymbols);
|
|
||||||
return dec.format(value);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String vatFormat(BigDecimal value) {
|
private String vatFormat(BigDecimal value) {
|
||||||
return nDigitFormat(value, 2);
|
return ZUGFeRD2PullProvider.nDigitFormat(value, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String currencyFormat(BigDecimal value) {
|
private String currencyFormat(BigDecimal value) {
|
||||||
return nDigitFormat(value, 2);
|
return ZUGFeRD2PullProvider.nDigitFormat(value, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String priceFormat(BigDecimal value) {
|
private String priceFormat(BigDecimal value) {
|
||||||
return nDigitFormat(value, 4);
|
return ZUGFeRD2PullProvider.nDigitFormat(value, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String quantityFormat(BigDecimal value) {
|
private String quantityFormat(BigDecimal value) {
|
||||||
return nDigitFormat(value, 4);
|
return ZUGFeRD2PullProvider.nDigitFormat(value, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -158,6 +145,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BigDecimal getTotalPrepaid() {
|
||||||
|
return trans.getTotalPrepaidAmount();
|
||||||
|
}
|
||||||
|
|
||||||
private BigDecimal getTotalGross() {
|
private BigDecimal getTotalGross() {
|
||||||
|
|
||||||
BigDecimal res = getTotal();
|
BigDecimal res = getTotal();
|
||||||
@@ -214,9 +205,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
|
|||||||
SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); //$NON-NLS-1$
|
SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); //$NON-NLS-1$
|
||||||
String senderReg = "";
|
String senderReg = "";
|
||||||
if (trans.getOwnOrganisationFullPlaintextInfo() != null) {
|
if (trans.getOwnOrganisationFullPlaintextInfo() != null) {
|
||||||
senderReg = "" + "<ram:IncludedCINote>\n" + " <ram:Content>\n"
|
senderReg = "" + "<ram:IncludedNote>\n" + " <ram:Content>\n"
|
||||||
+ trans.getOwnOrganisationFullPlaintextInfo() + " </ram:Content>\n"
|
+ trans.getOwnOrganisationFullPlaintextInfo() + " </ram:Content>\n"
|
||||||
+ "<ram:SubjectCode>REG</ram:SubjectCode>\n" + "</ram:IncludedCINote>\n";
|
+ "<ram:SubjectCode>REG</ram:SubjectCode>\n" + "</ram:IncludedNote>\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,11 +369,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
|
|||||||
+ " <ram:LineOne>" + trans.getRecipient().getStreet() + "</ram:LineOne>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
+ " <ram:LineOne>" + trans.getRecipient().getStreet() + "</ram:LineOne>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
+ " <ram:CityName>" + trans.getRecipient().getLocation() + "</ram:CityName>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
+ " <ram:CityName>" + trans.getRecipient().getLocation() + "</ram:CityName>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
+ " <ram:CountryID>" + trans.getRecipient().getCountry() + "</ram:CountryID>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
+ " <ram:CountryID>" + trans.getRecipient().getCountry() + "</ram:CountryID>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
+ " </ram:PostalTradeAddress>\n" //$NON-NLS-1$
|
+ " </ram:PostalTradeAddress>\n"; //$NON-NLS-1$
|
||||||
+ " <ram:SpecifiedTaxRegistration>\n" //$NON-NLS-1$
|
if (trans.getRecipient().getVATID() != null) {
|
||||||
|
xml += " <ram:SpecifiedTaxRegistration>\n" //$NON-NLS-1$
|
||||||
+ " <ram:ID schemeID=\"VA\">" + trans.getRecipient().getVATID() + "</ram:ID>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
+ " <ram:ID schemeID=\"VA\">" + trans.getRecipient().getVATID() + "</ram:ID>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
+ " </ram:SpecifiedTaxRegistration>\n" //$NON-NLS-1$
|
+ " </ram:SpecifiedTaxRegistration>\n"; //$NON-NLS-1$
|
||||||
+ " </ram:BuyerTradeParty>\n" //$NON-NLS-1$
|
}
|
||||||
|
xml += " </ram:BuyerTradeParty>\n" //$NON-NLS-1$
|
||||||
// + " <BuyerOrderReferencedDocument>\n"
|
// + " <BuyerOrderReferencedDocument>\n"
|
||||||
// + " <IssueDateTime format=\"102\">20130301</IssueDateTime>\n"
|
// + " <IssueDateTime format=\"102\">20130301</IssueDateTime>\n"
|
||||||
// + " <ID>2013-471331</ID>\n"
|
// + " <ID>2013-471331</ID>\n"
|
||||||
@@ -412,8 +405,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
|
|||||||
+ " </ram:PayeePartyCreditorFinancialAccount>\n" //$NON-NLS-1$
|
+ " </ram:PayeePartyCreditorFinancialAccount>\n" //$NON-NLS-1$
|
||||||
+ " <ram:PayeeSpecifiedCreditorFinancialInstitution>\n" //$NON-NLS-1$
|
+ " <ram:PayeeSpecifiedCreditorFinancialInstitution>\n" //$NON-NLS-1$
|
||||||
+ " <ram:BICID>" + payment.getOwnBIC() + "</ram:BICID>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
+ " <ram:BICID>" + payment.getOwnBIC() + "</ram:BICID>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
+ " <ram:GermanBankleitzahlID>" + payment.getOwnBLZ() //$NON-NLS-1$
|
|
||||||
+ "</ram:GermanBankleitzahlID>\n" //$NON-NLS-1$
|
|
||||||
// + " <ram:Name>"+trans.getOwnBankName()+"</ram:Name>\n" //$NON-NLS-1$
|
// + " <ram:Name>"+trans.getOwnBankName()+"</ram:Name>\n" //$NON-NLS-1$
|
||||||
// //$NON-NLS-2$
|
// //$NON-NLS-2$
|
||||||
+ " </ram:PayeeSpecifiedCreditorFinancialInstitution>\n" //$NON-NLS-1$
|
+ " </ram:PayeeSpecifiedCreditorFinancialInstitution>\n" //$NON-NLS-1$
|
||||||
@@ -490,8 +481,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
|
|||||||
+ " <ram:GrandTotalAmount>" + currencyFormat(getTotalGross()) + "</ram:GrandTotalAmount>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
+ " <ram:GrandTotalAmount>" + currencyFormat(getTotalGross()) + "</ram:GrandTotalAmount>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
// //
|
// //
|
||||||
// currencyID=\"EUR\"
|
// currencyID=\"EUR\"
|
||||||
// + " <TotalPrepaidAmount currencyID=\"EUR\">0.00</TotalPrepaidAmount>\n"
|
+ " <ram:TotalPrepaidAmount currencyID=\"EUR\">" + currencyFormat(getTotalPrepaid()) + "</ram:TotalPrepaidAmount>\n"
|
||||||
+ " <ram:DuePayableAmount>" + currencyFormat(getTotalGross()) + "</ram:DuePayableAmount>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
+ " <ram:DuePayableAmount>" + currencyFormat(getTotalGross().subtract(getTotalPrepaid())) + "</ram:DuePayableAmount>\n" //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
// //
|
// //
|
||||||
// currencyID=\"EUR\"
|
// currencyID=\"EUR\"
|
||||||
+ " </ram:SpecifiedTradeSettlementHeaderMonetarySummation>\n" //$NON-NLS-1$
|
+ " </ram:SpecifiedTradeSettlementHeaderMonetarySummation>\n" //$NON-NLS-1$
|
||||||
|
|||||||
@@ -195,15 +195,16 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* All files are PDF/A-3, setConformance refers to the level conformance.
|
* All files are PDF/A-3, setConformance refers to the level conformance.
|
||||||
* <p/>
|
*
|
||||||
* PDF/A-3 has three conformance levels, called "A", "U" and "B".
|
* PDF/A-3 has three conformance levels, called "A", "U" and "B".
|
||||||
* <p/>
|
* <p>
|
||||||
* PDF/A-3-B where B means only visually preservable, U -standard for Mustang-
|
* PDF/A-3-B where B means only visually preservable, U -standard for Mustang-
|
||||||
* means visually and unicode preservable and A means full compliance, i.e.
|
* means visually and unicode preservable and A means full compliance, i.e.
|
||||||
* visually, unicode and structurally preservable and tagged PDF, i.e. useful
|
* visually, unicode and structurally preservable and tagged PDF, i.e. useful
|
||||||
* metainformation for blind people.
|
* metainformation for blind people.
|
||||||
* <p/>
|
* <p>
|
||||||
* Feel free to pass "A" as new level if you know what you are doing :-)
|
* Feel free to pass "A" as new level if you know what you are doing :-)
|
||||||
|
* @param newLevel "A", "U" or "B"
|
||||||
*
|
*
|
||||||
* @deprecated Use {@link ZUGFeRDExporterFromA1Factory} instead
|
* @deprecated Use {@link ZUGFeRDExporterFromA1Factory} instead
|
||||||
*/
|
*/
|
||||||
@@ -217,16 +218,17 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* All files are PDF/A-3, setConformance refers to the level conformance.
|
* All files are PDF/A-3, setConformance refers to the level conformance.
|
||||||
* <p/>
|
* <p>
|
||||||
* PDF/A-3 has three conformance levels, called "A", "U" and "B".
|
* PDF/A-3 has three conformance levels, called "A", "U" and "B".
|
||||||
* <p/>
|
* <p>
|
||||||
* PDF/A-3-B where B means only visually preservable, U -standard for Mustang-
|
* PDF/A-3-B where B means only visually preservable, U -standard for Mustang-
|
||||||
* means visually and unicode preservable and A means full compliance, i.e.
|
* means visually and unicode preservable and A means full compliance, i.e.
|
||||||
* visually, unicode and structurally preservable and tagged PDF, i.e. useful
|
* visually, unicode and structurally preservable and tagged PDF, i.e. useful
|
||||||
* metainformation for blind people.
|
* metainformation for blind people.
|
||||||
* <p/>
|
* <p>
|
||||||
* Feel free to pass "A" as new level if you know what you are doing :-)
|
* Feel free to pass "A" as new level if you know what you are doing :-)
|
||||||
*
|
*
|
||||||
|
* @param newLevel "A", "U" or "B"
|
||||||
* @deprecated Use
|
* @deprecated Use
|
||||||
* {@link #setConformanceLevel(org.mustangproject.ZUGFeRD.PDFAConformanceLevel)}
|
* {@link #setConformanceLevel(org.mustangproject.ZUGFeRD.PDFAConformanceLevel)}
|
||||||
* instead
|
* instead
|
||||||
@@ -251,27 +253,45 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
ignoreA1Errors = true;
|
ignoreA1Errors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/***
|
||||||
|
* load from a pdf which is already A/3
|
||||||
|
* @param filename the PDF
|
||||||
|
* @throws IOException if anything is wrong with filename
|
||||||
* @deprecated Use the factory method {@link #createFromPDFA3(String)} instead
|
* @deprecated Use the factory method {@link #createFromPDFA3(String)} instead
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void loadPDFA3(String filename) throws IOException {
|
public void loadPDFA3(String filename) throws IOException {
|
||||||
doc = PDDocument.load(new File(filename));
|
doc = PDDocument.load(new File(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* factory create a ZUGFeRD exporter for a PDF/A-3 pdf file
|
||||||
|
* @param filename of the pdf
|
||||||
|
* @return the created ZUGFeRDExporter
|
||||||
|
* @throws IOException if something is wrong with filename
|
||||||
|
*/
|
||||||
public static ZUGFeRDExporter createFromPDFA3(String filename) throws IOException {
|
public static ZUGFeRDExporter createFromPDFA3(String filename) throws IOException {
|
||||||
return new ZUGFeRDExporter(PDDocument.load(new File(filename)));
|
return new ZUGFeRDExporter(PDDocument.load(new File(filename)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use the factory method {@link #createFromPDFA3(InputStream)}
|
* load from a pdf which is already A/3 from filestream
|
||||||
* instead
|
* @param file InputStream to load pdf from
|
||||||
|
* @deprecated Use the factory method {@link #createFromPDFA3(InputStream)} instead
|
||||||
|
* @throws IOException in case anything is wrong with file
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void loadPDFA3(InputStream file) throws IOException {
|
public void loadPDFA3(InputStream file) throws IOException {
|
||||||
doc = PDDocument.load(file);
|
doc = PDDocument.load(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* factory create a ZUGFeRD exporter for a PDF/A-3 inputstream
|
||||||
|
* @param pdfSource the InputStream of the pdf
|
||||||
|
* @return the created ZUGFeRDExporter
|
||||||
|
* @throws IOException (should not happen)
|
||||||
|
*/
|
||||||
public static ZUGFeRDExporter createFromPDFA3(InputStream pdfSource) throws IOException {
|
public static ZUGFeRDExporter createFromPDFA3(InputStream pdfSource) throws IOException {
|
||||||
return new ZUGFeRDExporter(PDDocument.load(pdfSource));
|
return new ZUGFeRDExporter(PDDocument.load(pdfSource));
|
||||||
}
|
}
|
||||||
@@ -279,7 +299,13 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
/**
|
/**
|
||||||
* Makes A PDF/A3a-compliant document from a PDF-A1 compliant document (on the
|
* Makes A PDF/A3a-compliant document from a PDF-A1 compliant document (on the
|
||||||
* metadata level, this will not e.g. convert graphics to JPG-2000)
|
* metadata level, this will not e.g. convert graphics to JPG-2000)
|
||||||
*
|
* @param filename the pdf
|
||||||
|
* @param producer the name of the xmp producer (app)
|
||||||
|
* @param creator the name of the xmp creator (user)
|
||||||
|
* @param attachZugferdHeaders whether to attach XMP ZUGFeRD headers
|
||||||
|
* @return the created PDFbox PDDocumentCatalog
|
||||||
|
* @throws IOException if anything is wrong with file
|
||||||
|
* @throws TransformerException in case of xml (XMP) parsing issues
|
||||||
* @deprecated use the {@link ZUGFeRDExporterFromA1Factory} instead
|
* @deprecated use the {@link ZUGFeRDExporterFromA1Factory} instead
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@@ -291,7 +317,18 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
return doc.getDocumentCatalog();
|
return doc.getDocumentCatalog();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/***
|
||||||
|
*
|
||||||
|
* Makes A PDF/A3a-compliant document from a PDF-A1 compliant document (on the
|
||||||
|
* metadata level, this will not e.g. convert graphics to JPG-2000)
|
||||||
|
|
||||||
|
* @param file the InputStream of the pdf
|
||||||
|
* @param producer the name of the xmp producer (app)
|
||||||
|
* @param creator the name of the xmp creator (user)
|
||||||
|
* @param attachZugferdHeaders whether to attach XMP ZUGFeRD headers
|
||||||
|
* @return the created PDFbox PDDocumentCatalog
|
||||||
|
* @throws IOException if anything is wrong with file
|
||||||
|
* @throws TransformerException in case of xml (XMP) parsing issues
|
||||||
* @deprecated use the {@link ZUGFeRDExporterFromA1Factory} instead
|
* @deprecated use the {@link ZUGFeRDExporterFromA1Factory} instead
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@@ -303,6 +340,7 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
return doc.getDocumentCatalog();
|
return doc.getDocumentCatalog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private IExporterFactory createPDFA1Factory() {
|
private IExporterFactory createPDFA1Factory() {
|
||||||
ZUGFeRDExporterFromA1Factory factory = new ZUGFeRDExporterFromA1Factory();
|
ZUGFeRDExporterFromA1Factory factory = new ZUGFeRDExporterFromA1Factory();
|
||||||
if (ignoreA1Errors) {
|
if (ignoreA1Errors) {
|
||||||
@@ -325,10 +363,11 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
* populate the XML. This parameter may be null, if so the XML data
|
* populate the XML. This parameter may be null, if so the XML data
|
||||||
* should hav ebeen set via
|
* should hav ebeen set via
|
||||||
* <code>setZUGFeRDXMLData(byte[] zugferdData)</code>
|
* <code>setZUGFeRDXMLData(byte[] zugferdData)</code>
|
||||||
|
* @throws IOException if anything is wrong with already loaded PDF
|
||||||
*/
|
*/
|
||||||
public void PDFattachZugferdFile(IZUGFeRDExportableTransaction trans) throws IOException {
|
public void PDFattachZugferdFile(IZUGFeRDExportableTransaction trans) throws IOException {
|
||||||
prepareDocument();
|
prepareDocument();
|
||||||
|
((IProfileProvider) xmlProvider).setProfile(profile);
|
||||||
xmlProvider.generateXML(trans);
|
xmlProvider.generateXML(trans);
|
||||||
String filename = getFilenameForVersion(ZFVersion);
|
String filename = getFilenameForVersion(ZFVersion);
|
||||||
PDFAttachGenericFile(doc, filename, "Alternative",
|
PDFAttachGenericFile(doc, filename, "Alternative",
|
||||||
@@ -339,6 +378,11 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Perform the final export to a now ZUGFeRD-enriched PDF file
|
||||||
|
* @param ZUGFeRDfilename the pdf file name
|
||||||
|
* @throws IOException if anything is wrong in the target location
|
||||||
|
*/
|
||||||
public void export(String ZUGFeRDfilename) throws IOException {
|
public void export(String ZUGFeRDfilename) throws IOException {
|
||||||
if (!documentPrepared) {
|
if (!documentPrepared) {
|
||||||
prepareDocument();
|
prepareDocument();
|
||||||
@@ -353,6 +397,12 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Perform the final export to a now ZUGFeRD-enriched PDF file as OutputStream
|
||||||
|
* @param output the OutputStream
|
||||||
|
* @throws IOException if anything is wrong in the OutputStream
|
||||||
|
*/
|
||||||
public void export(OutputStream output) throws IOException {
|
public void export(OutputStream output) throws IOException {
|
||||||
if (!documentPrepared) {
|
if (!documentPrepared) {
|
||||||
prepareDocument();
|
prepareDocument();
|
||||||
@@ -376,7 +426,7 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
* @param description Human-readable description of the file content
|
* @param description Human-readable description of the file content
|
||||||
* @param subType type of the data e.g. could be "text/xml" - mime like
|
* @param subType type of the data e.g. could be "text/xml" - mime like
|
||||||
* @param data the binary data of the file/attachment
|
* @param data the binary data of the file/attachment
|
||||||
* @throws java.io.IOException
|
* @throws java.io.IOException if anything is wrong with filename
|
||||||
*/
|
*/
|
||||||
public void PDFAttachGenericFile(PDDocument doc, String filename, String relationship, String description,
|
public void PDFAttachGenericFile(PDDocument doc, String filename, String relationship, String description,
|
||||||
String subType, byte[] data) throws IOException {
|
String subType, byte[] data) throws IOException {
|
||||||
@@ -446,6 +496,7 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
* API or component.
|
* API or component.
|
||||||
*
|
*
|
||||||
* @param zugferdData XML data to be set as a byte array (XML file in raw form).
|
* @param zugferdData XML data to be set as a byte array (XML file in raw form).
|
||||||
|
* @throws IOException (should not happen)
|
||||||
*/
|
*/
|
||||||
public void setZUGFeRDXMLData(byte[] zugferdData) throws IOException {
|
public void setZUGFeRDXMLData(byte[] zugferdData) throws IOException {
|
||||||
CustomXMLProvider cus = new CustomXMLProvider();
|
CustomXMLProvider cus = new CustomXMLProvider();
|
||||||
@@ -495,7 +546,7 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
* neccessary PDF/A schema extension description to be able to add this
|
* neccessary PDF/A schema extension description to be able to add this
|
||||||
* information to RDF
|
* information to RDF
|
||||||
*
|
*
|
||||||
* @param metadata
|
* @param metadata the PDFbox XMPMetadata object
|
||||||
*/
|
*/
|
||||||
protected void addXMP(XMPMetadata metadata) {
|
protected void addXMP(XMPMetadata metadata) {
|
||||||
|
|
||||||
@@ -607,7 +658,7 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
/**
|
/**
|
||||||
* the human author (use factory method instead)
|
* the human author (use factory method instead)
|
||||||
*
|
*
|
||||||
* @param creator
|
* @param creator the (human) name who created the PDF
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setCreator(String creator) {
|
public void setCreator(String creator) {
|
||||||
@@ -617,7 +668,7 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
/**
|
/**
|
||||||
* the CreatorTool attribute for the PDF
|
* the CreatorTool attribute for the PDF
|
||||||
*
|
*
|
||||||
* @param creator
|
* @param creatorTool the application which created the PDF
|
||||||
*/
|
*/
|
||||||
protected void setCreatorTool(String creatorTool) {
|
protected void setCreatorTool(String creatorTool) {
|
||||||
this.creatorTool = creatorTool;
|
this.creatorTool = creatorTool;
|
||||||
@@ -626,7 +677,7 @@ public class ZUGFeRDExporter implements Closeable {
|
|||||||
/**
|
/**
|
||||||
* the authoring software (use factory method instead)
|
* the authoring software (use factory method instead)
|
||||||
*
|
*
|
||||||
* @param producer
|
* @param producer the authoring software
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setProducer(String producer) {
|
public void setProducer(String producer) {
|
||||||
|
|||||||
@@ -173,14 +173,14 @@ public class ZUGFeRDExporterFromA3Factory implements IExporterFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* All files are PDF/A-3, setConformance refers to the level conformance.
|
* All files are PDF/A-3, setConformance refers to the level conformance.
|
||||||
* <p/>
|
* <p>
|
||||||
* PDF/A-3 has three coformance levels, called "A", "U" and "B".
|
* PDF/A-3 has three coformance levels, called "A", "U" and "B".
|
||||||
* <p/>
|
* <p>
|
||||||
* PDF/A-3-B where B means only visually preservable, U -standard for Mustang-
|
* PDF/A-3-B where B means only visually preservable, U -standard for Mustang-
|
||||||
* means visually and unicode preservable and A means full compliance, i.e.
|
* means visually and unicode preservable and A means full compliance, i.e.
|
||||||
* visually, unicode and structurally preservable and tagged PDF, i.e. useful
|
* visually, unicode and structurally preservable and tagged PDF, i.e. useful
|
||||||
* metainformation for blind people.
|
* metainformation for blind people.
|
||||||
* <p/>
|
* <p>
|
||||||
* Feel free to pass "A" as new level if you know what you are doing :-)
|
* Feel free to pass "A" as new level if you know what you are doing :-)
|
||||||
*/
|
*/
|
||||||
public IExporterFactory setConformanceLevel(PDFAConformanceLevel newLevel) {
|
public IExporterFactory setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ import javax.xml.xpath.XPath;
|
|||||||
import javax.xml.xpath.XPathExpressionException;
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
import javax.xml.xpath.XPathFactory;
|
import javax.xml.xpath.XPathFactory;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -65,16 +68,16 @@ public class ZUGFeRDImporter {
|
|||||||
*/
|
*/
|
||||||
private byte[] rawXML = null;
|
private byte[] rawXML = null;
|
||||||
private String xmpString = null; // XMP metadata
|
private String xmpString = null; // XMP metadata
|
||||||
|
private Document document;
|
||||||
|
|
||||||
public ZUGFeRDImporter(String pdfFilename) {
|
public ZUGFeRDImporter(String pdfFilename) {
|
||||||
try {
|
|
||||||
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pdfFilename));
|
try (InputStream bis = Files.newInputStream(Paths.get(pdfFilename), StandardOpenOption.READ)) {
|
||||||
extractLowLevel(bis);
|
extractLowLevel(bis);
|
||||||
bis.close();
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||||
throw new ZUGFeRDExportException(e);
|
throw new ZUGFeRDExportException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ZUGFeRDImporter(InputStream pdfStream) {
|
public ZUGFeRDImporter(InputStream pdfStream) {
|
||||||
@@ -125,7 +128,10 @@ public class ZUGFeRDImporter {
|
|||||||
|
|
||||||
|
|
||||||
private void extractFiles(Map<String, PDComplexFileSpecification> names) throws IOException {
|
private void extractFiles(Map<String, PDComplexFileSpecification> names) throws IOException {
|
||||||
for (String filename : names.keySet()) {
|
for (String alias : names.keySet()) {
|
||||||
|
|
||||||
|
PDComplexFileSpecification fileSpec = names.get(alias);
|
||||||
|
String filename=fileSpec.getFilename();
|
||||||
/**
|
/**
|
||||||
* currently (in the release candidate of version 1) only one attached file with
|
* currently (in the release candidate of version 1) only one attached file with
|
||||||
* the name ZUGFeRD-invoice.xml is allowed
|
* the name ZUGFeRD-invoice.xml is allowed
|
||||||
@@ -133,7 +139,6 @@ public class ZUGFeRDImporter {
|
|||||||
if ((filename.equals("ZUGFeRD-invoice.xml") || (filename.equals("zugferd-invoice.xml")) || filename.equals("factur-x.xml"))) { //$NON-NLS-1$
|
if ((filename.equals("ZUGFeRD-invoice.xml") || (filename.equals("zugferd-invoice.xml")) || filename.equals("factur-x.xml"))) { //$NON-NLS-1$
|
||||||
containsMeta = true;
|
containsMeta = true;
|
||||||
|
|
||||||
PDComplexFileSpecification fileSpec = names.get(filename);
|
|
||||||
PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile();
|
PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile();
|
||||||
// String embeddedFilename = filePath + filename;
|
// String embeddedFilename = filePath + filename;
|
||||||
// File file = new File(filePath + filename);
|
// File file = new File(filePath + filename);
|
||||||
@@ -142,15 +147,13 @@ public class ZUGFeRDImporter {
|
|||||||
// ByteArrayOutputStream();
|
// ByteArrayOutputStream();
|
||||||
// FileOutputStream fos = new FileOutputStream(file);
|
// FileOutputStream fos = new FileOutputStream(file);
|
||||||
|
|
||||||
rawXML = embeddedFile.toByteArray();
|
setRawXML(embeddedFile.toByteArray());
|
||||||
setMeta(new String(rawXML));
|
|
||||||
|
|
||||||
// fos.write(embeddedFile.getByteArray());
|
// fos.write(embeddedFile.getByteArray());
|
||||||
// fos.close();
|
// fos.close();
|
||||||
}
|
}
|
||||||
if (filename.startsWith("additional_data")) {
|
if (filename.startsWith("additional_data")) {
|
||||||
|
|
||||||
PDComplexFileSpecification fileSpec = names.get(filename);
|
|
||||||
PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile();
|
PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile();
|
||||||
additionalXMLs.put(filename, embeddedFile.toByteArray());
|
additionalXMLs.put(filename, embeddedFile.toByteArray());
|
||||||
|
|
||||||
@@ -173,13 +176,52 @@ public class ZUGFeRDImporter {
|
|||||||
System.err.println(output);
|
System.err.println(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Document getDocument() throws ParserConfigurationException, IOException, SAXException, TransformerException {
|
private Document getDocument() { return document; }
|
||||||
|
|
||||||
|
public void setRawXML(byte[] rawXML) throws IOException {
|
||||||
|
this.rawXML = rawXML;
|
||||||
|
try {
|
||||||
|
setDocument();
|
||||||
|
} catch (ParserConfigurationException | SAXException e) {
|
||||||
|
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||||
|
throw new ZUGFeRDExportException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDocument() throws ParserConfigurationException, IOException, SAXException {
|
||||||
DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance();
|
||||||
xmlFact.setNamespaceAware(false);
|
xmlFact.setNamespaceAware(false);
|
||||||
DocumentBuilder builder = xmlFact.newDocumentBuilder();
|
DocumentBuilder builder = xmlFact.newDocumentBuilder();
|
||||||
Document doc = builder.parse(new ByteArrayInputStream(rawXML));
|
ByteArrayInputStream is = new ByteArrayInputStream(rawXML);
|
||||||
//prettyPrint(doc);
|
is.skip(guessBOMSize(is));
|
||||||
return doc;
|
document = builder.parse(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skips over a BOM at the beginning of the given ByteArrayInputStream, if one exists.
|
||||||
|
* @param is the ByteArrayInputStream used
|
||||||
|
* @throws IOException
|
||||||
|
* @see <a href="https://www.w3.org/TR/xml/#sec-guessing">Autodetection of Character Encodings</a>
|
||||||
|
*/
|
||||||
|
private 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String extractString(String xpathStr) {
|
private String extractString(String xpathStr) {
|
||||||
@@ -192,10 +234,7 @@ public class ZUGFeRDImporter {
|
|||||||
XPathFactory xpathFact = XPathFactory.newInstance();
|
XPathFactory xpathFact = XPathFactory.newInstance();
|
||||||
XPath xpath = xpathFact.newXPath();
|
XPath xpath = xpathFact.newXPath();
|
||||||
result = xpath.evaluate(xpathStr, document);
|
result = xpath.evaluate(xpathStr, document);
|
||||||
} catch (ParserConfigurationException e) {
|
} catch (XPathExpressionException e) {
|
||||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
|
||||||
throw new ZUGFeRDExportException(e);
|
|
||||||
} catch (IOException | SAXException | TransformerException | XPathExpressionException e) {
|
|
||||||
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
|
||||||
throw new ZUGFeRDExportException(e);
|
throw new ZUGFeRDExportException(e);
|
||||||
}
|
}
|
||||||
@@ -300,8 +339,8 @@ public class ZUGFeRDImporter {
|
|||||||
/**
|
/**
|
||||||
* @param meta raw XML to be set
|
* @param meta raw XML to be set
|
||||||
*/
|
*/
|
||||||
public void setMeta(String meta) {
|
public void setMeta(String meta) throws IOException {
|
||||||
this.rawXML = meta.getBytes();
|
setRawXML(meta.getBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -346,6 +385,7 @@ public class ZUGFeRDImporter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the raw XML data as extracted from the ZUGFeRD PDF file.
|
* Returns the raw XML data as extracted from the ZUGFeRD PDF file.
|
||||||
|
* @return the raw ZUGFeRD XML data
|
||||||
*/
|
*/
|
||||||
public byte[] getRawXML() {
|
public byte[] getRawXML() {
|
||||||
return rawXML;
|
return rawXML;
|
||||||
@@ -369,7 +409,7 @@ public class ZUGFeRDImporter {
|
|||||||
static String convertStreamToString(java.io.InputStream is) {
|
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
|
// 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
|
// https://community.oracle.com/blogs/pat/2004/10/23/stupid-scanner-tricks
|
||||||
Scanner s = new Scanner(is).useDelimiter("\\A");
|
Scanner s = new Scanner(is, "UTF-8").useDelimiter("\\A");
|
||||||
return s.hasNext() ? s.next() : "";
|
return s.hasNext() ? s.next() : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
package org.mustangproject.ZUGFeRD;
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.DecimalFormatSymbols;
|
import java.text.DecimalFormatSymbols;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@@ -30,51 +31,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.xml.bind.JAXBElement;
|
import javax.xml.bind.JAXBElement;
|
||||||
|
|
||||||
import org.mustangproject.ZUGFeRD.model.AmountType;
|
import org.mustangproject.ZUGFeRD.model.*;
|
||||||
import org.mustangproject.ZUGFeRD.model.CodeType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.CountryIDType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.CreditorFinancialAccountType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.CreditorFinancialInstitutionType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.CrossIndustryDocumentType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.DateTimeType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.DateTimeTypeConstants;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.DocumentCodeType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.DocumentContextParameterType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.DocumentContextParameterTypeConstants;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.DocumentLineDocumentType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.ExchangedDocumentContextType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.ExchangedDocumentType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.IDType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.IndicatorType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.LogisticsServiceChargeType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.NoteType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.NoteTypeConstants;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.ObjectFactory;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.PaymentMeansCodeType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.PaymentMeansCodeTypeConstants;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.PercentType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.QuantityType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.SupplyChainEventType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.SupplyChainTradeAgreementType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.SupplyChainTradeDeliveryType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.SupplyChainTradeLineItemType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.SupplyChainTradeSettlementType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.SupplyChainTradeTransactionType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TaxRegistrationType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TaxRegistrationTypeConstants;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TaxTypeCodeType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TaxTypeCodeTypeConstants;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TextType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TradeAddressType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TradeAllowanceChargeType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TradePartyType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TradePaymentTermsType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TradePriceType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TradeProductType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TradeSettlementMonetarySummationType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TradeSettlementPaymentMeansType;
|
|
||||||
import org.mustangproject.ZUGFeRD.model.TradeTaxType;
|
|
||||||
|
|
||||||
class ZUGFeRDTransactionModelConverter {
|
class ZUGFeRDTransactionModelConverter {
|
||||||
private static final SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd");
|
private static final SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd");
|
||||||
@@ -84,6 +41,7 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
private final Totals totals;
|
private final Totals totals;
|
||||||
private boolean isTest;
|
private boolean isTest;
|
||||||
private String currency = "EUR";
|
private String currency = "EUR";
|
||||||
|
private String profile;
|
||||||
|
|
||||||
|
|
||||||
ZUGFeRDTransactionModelConverter(IZUGFeRDExportableTransaction trans) {
|
ZUGFeRDTransactionModelConverter(IZUGFeRDExportableTransaction trans) {
|
||||||
@@ -113,7 +71,7 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
DocumentContextParameterType contextParameter = xmlFactory
|
DocumentContextParameterType contextParameter = xmlFactory
|
||||||
.createDocumentContextParameterType();
|
.createDocumentContextParameterType();
|
||||||
IDType idType = xmlFactory.createIDType();
|
IDType idType = xmlFactory.createIDType();
|
||||||
idType.setValue(DocumentContextParameterTypeConstants.EXTENDED);
|
idType.setValue(profile);
|
||||||
contextParameter.setID(idType);
|
contextParameter.setID(idType);
|
||||||
context.getGuidelineSpecifiedDocumentContextParameter().add(
|
context.getGuidelineSpecifiedDocumentContextParameter().add(
|
||||||
contextParameter);
|
contextParameter);
|
||||||
@@ -149,7 +107,7 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
document.setTypeCode(documentCodeType);
|
document.setTypeCode(documentCodeType);
|
||||||
|
|
||||||
TextType name = xmlFactory.createTextType();
|
TextType name = xmlFactory.createTextType();
|
||||||
name.setValue("RECHNUNG");
|
name.setValue(trans.getDocumentName());
|
||||||
document.getName().add(name);
|
document.getName().add(name);
|
||||||
|
|
||||||
if (trans.getOwnOrganisationFullPlaintextInfo() != null) {
|
if (trans.getOwnOrganisationFullPlaintextInfo() != null) {
|
||||||
@@ -167,7 +125,7 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
if (trans.getReferenceNumber() != null && !"".equals(trans.getReferenceNumber())) {
|
if (trans.getReferenceNumber() != null && !"".equals(trans.getReferenceNumber())) {
|
||||||
NoteType referenceInfo = xmlFactory.createNoteType();
|
NoteType referenceInfo = xmlFactory.createNoteType();
|
||||||
TextType referenceInfoContent = xmlFactory.createTextType();
|
TextType referenceInfoContent = xmlFactory.createTextType();
|
||||||
referenceInfoContent.setValue("Ursprungsbeleg: " + trans.getReferenceNumber());
|
referenceInfoContent.setValue(trans.getReferenceNumber());
|
||||||
referenceInfo.getContent().add(referenceInfoContent);
|
referenceInfo.getContent().add(referenceInfoContent);
|
||||||
document.getIncludedNote().add(referenceInfo);
|
document.getIncludedNote().add(referenceInfo);
|
||||||
}
|
}
|
||||||
@@ -199,6 +157,15 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
tradeAgreement.setBuyerTradeParty(getBuyer());
|
tradeAgreement.setBuyerTradeParty(getBuyer());
|
||||||
tradeAgreement.setSellerTradeParty(getSeller());
|
tradeAgreement.setSellerTradeParty(getSeller());
|
||||||
|
|
||||||
|
if (trans.getBuyerOrderReferencedDocumentID() != null) {
|
||||||
|
ReferencedDocumentType refdoc = xmlFactory.createReferencedDocumentType();
|
||||||
|
IDType id = xmlFactory.createIDType();
|
||||||
|
id.setValue(trans.getBuyerOrderReferencedDocumentID());
|
||||||
|
refdoc.getID().add(id);
|
||||||
|
refdoc.setIssueDateTime(trans.getBuyerOrderReferencedDocumentIssueDateTime());
|
||||||
|
tradeAgreement.getBuyerOrderReferencedDocument().add(refdoc);
|
||||||
|
}
|
||||||
|
|
||||||
return tradeAgreement;
|
return tradeAgreement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,6 +179,12 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
buyerID.setValue(trans.getRecipient().getID());
|
buyerID.setValue(trans.getRecipient().getID());
|
||||||
buyerTradeParty.getID().add(buyerID);
|
buyerTradeParty.getID().add(buyerID);
|
||||||
}
|
}
|
||||||
|
if (trans.getRecipient().getGlobalID() != null) {
|
||||||
|
IDType globalID = xmlFactory.createIDType();
|
||||||
|
globalID.setValue(trans.getRecipient().getGlobalID());
|
||||||
|
globalID.setSchemeID(trans.getRecipient().getGlobalIDScheme());
|
||||||
|
buyerTradeParty.getGlobalID().add(globalID);
|
||||||
|
}
|
||||||
|
|
||||||
TextType buyerName = xmlFactory.createTextType();
|
TextType buyerName = xmlFactory.createTextType();
|
||||||
buyerName.setValue(trans.getRecipient().getName());
|
buyerName.setValue(trans.getRecipient().getName());
|
||||||
@@ -422,7 +395,7 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
|
|
||||||
TaxCategoryCodeType taxCategoryCode = xmlFactory.createTaxCategoryCodeType();
|
TaxCategoryCodeType taxCategoryCode = xmlFactory.createTaxCategoryCodeType();
|
||||||
VATAmount vatAmount = VATPercentAmountMap.get(currentTaxPercent);
|
VATAmount vatAmount = VATPercentAmountMap.get(currentTaxPercent);
|
||||||
taxCategoryCode.setValue(vatAmount.getDocumentCode());
|
taxCategoryCode.setValue(vatAmount.getCategoryCode());
|
||||||
tradeTax.setCategoryCode(taxCategoryCode);
|
tradeTax.setCategoryCode(taxCategoryCode);
|
||||||
|
|
||||||
VATAmount amount = VATPercentAmountMap.get(currentTaxPercent);
|
VATAmount amount = VATPercentAmountMap.get(currentTaxPercent);
|
||||||
@@ -686,9 +659,14 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
grandTotalAmount.setValue(currencyFormat(totals.getTotalGross()));
|
grandTotalAmount.setValue(currencyFormat(totals.getTotalGross()));
|
||||||
monetarySummation.getGrandTotalAmount().add(grandTotalAmount);
|
monetarySummation.getGrandTotalAmount().add(grandTotalAmount);
|
||||||
|
|
||||||
|
AmountType totalPrepaidAmount = xmlFactory.createAmountType();
|
||||||
|
totalPrepaidAmount.setCurrencyID(currency);
|
||||||
|
totalPrepaidAmount.setValue(currencyFormat(trans.getTotalPrepaidAmount()));
|
||||||
|
monetarySummation.getTotalPrepaidAmount().add(totalPrepaidAmount);
|
||||||
|
|
||||||
AmountType duePayableAmount = xmlFactory.createAmountType();
|
AmountType duePayableAmount = xmlFactory.createAmountType();
|
||||||
duePayableAmount.setCurrencyID(currency);
|
duePayableAmount.setCurrencyID(currency);
|
||||||
duePayableAmount.setValue(currencyFormat(totals.getTotalGross()));
|
duePayableAmount.setValue(currencyFormat(totals.getTotalGross().subtract(trans.getTotalPrepaidAmount())));
|
||||||
monetarySummation.getDuePayableAmount().add(duePayableAmount);
|
monetarySummation.getDuePayableAmount().add(duePayableAmount);
|
||||||
|
|
||||||
return monetarySummation;
|
return monetarySummation;
|
||||||
@@ -843,70 +821,26 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
|
|
||||||
|
|
||||||
private BigDecimal vatFormat(BigDecimal value) {
|
private BigDecimal vatFormat(BigDecimal value) {
|
||||||
return nDigitFormat(value, 2);
|
return value.setScale(2, RoundingMode.HALF_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private BigDecimal currencyFormat(BigDecimal value) {
|
private BigDecimal currencyFormat(BigDecimal value) {
|
||||||
return nDigitFormat(value, 2);
|
return value.setScale(2, RoundingMode.HALF_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private BigDecimal priceFormat(BigDecimal value) {
|
private BigDecimal priceFormat(BigDecimal value) {
|
||||||
return nDigitFormat(value, 4);
|
return value.setScale(4, RoundingMode.HALF_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private BigDecimal quantityFormat(BigDecimal value) {
|
private BigDecimal quantityFormat(BigDecimal value) {
|
||||||
return nDigitFormat(value, 4);
|
return value.setScale(4, RoundingMode.HALF_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private BigDecimal nDigitFormat(BigDecimal value, int scale) {
|
|
||||||
/*
|
|
||||||
* I needed 123,45, locale independent.I tried
|
|
||||||
* NumberFormat.getCurrencyInstance().format( 12345.6789 ); but that is
|
|
||||||
* locale specific.I also tried DecimalFormat df = new DecimalFormat(
|
|
||||||
* "0,00" ); df.setDecimalSeparatorAlwaysShown(true);
|
|
||||||
* df.setGroupingUsed(false); DecimalFormatSymbols symbols = new
|
|
||||||
* DecimalFormatSymbols(); symbols.setDecimalSeparator(',');
|
|
||||||
* symbols.setGroupingSeparator(' ');
|
|
||||||
* df.setDecimalFormatSymbols(symbols);
|
|
||||||
*
|
|
||||||
* but that would not switch off grouping. Although I liked very much
|
|
||||||
* the (incomplete) "BNF diagram" in
|
|
||||||
* http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html
|
|
||||||
* in the end I decided to calculate myself and take eur+sparator+cents
|
|
||||||
*
|
|
||||||
* This function will cut off, i.e. floor() subcent values Tests:
|
|
||||||
* System.err.println(utils.currencyFormat(new BigDecimal(0),
|
|
||||||
* ".")+"\n"+utils.currencyFormat(new BigDecimal("-1.10"),
|
|
||||||
* ",")+"\n"+utils.currencyFormat(new BigDecimal("-1.1"),
|
|
||||||
* ",")+"\n"+utils.currencyFormat(new BigDecimal("-1.01"),
|
|
||||||
* ",")+"\n"+utils.currencyFormat(new BigDecimal("20000123.3489"),
|
|
||||||
* ",")+"\n"+utils.currencyFormat(new BigDecimal("20000123.3419"),
|
|
||||||
* ",")+"\n"+utils.currencyFormat(new BigDecimal("12"), ","));
|
|
||||||
*
|
|
||||||
* results 0.00 -1,10 -1,10 -1,01 20000123,34 20000123,34 12,00
|
|
||||||
*/
|
|
||||||
value = value.setScale(scale, BigDecimal.ROUND_HALF_UP); // first, round
|
|
||||||
// so that
|
|
||||||
// e.g.
|
|
||||||
// 1.189999999999999946709294817992486059665679931640625
|
|
||||||
// becomes
|
|
||||||
// 1.19
|
|
||||||
char[] repeat = new char[scale];
|
|
||||||
Arrays.fill(repeat, '0');
|
|
||||||
|
|
||||||
DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols();
|
|
||||||
otherSymbols.setDecimalSeparator('.');
|
|
||||||
DecimalFormat dec = new DecimalFormat("0." + new String(repeat),
|
|
||||||
otherSymbols);
|
|
||||||
return new BigDecimal(dec.format(value));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* which taxes have been used with which amounts in this transaction, empty for no taxes, or e.g. 19=>190 and 7=>14 if 1000 Eur were applicable to 19% VAT
|
* which taxes have been used with which amounts in this transaction, empty for no taxes, or e.g. 19=>190 and 7=>14 if 1000 Eur were applicable to 19% VAT
|
||||||
* (=>190 EUR VAT) and 200 EUR were applicable to 7% (=>14 EUR VAT) 190 Eur
|
* (=>190 EUR VAT) and 200 EUR were applicable to 7% (=>14 EUR VAT) 190 Eur
|
||||||
@@ -924,7 +858,7 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) {
|
for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) {
|
||||||
BigDecimal percent = currentItem.getProduct().getVATPercent();
|
BigDecimal percent = currentItem.getProduct().getVATPercent();
|
||||||
LineCalc lc = new LineCalc(currentItem);
|
LineCalc lc = new LineCalc(currentItem);
|
||||||
VATAmount itemVATAmount = new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount(), trans.getDocumentCode());
|
VATAmount itemVATAmount = new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount(), lc.getCategoryCode());
|
||||||
VATAmount current = hm.get(percent);
|
VATAmount current = hm.get(percent);
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
hm.put(percent, itemVATAmount);
|
hm.put(percent, itemVATAmount);
|
||||||
@@ -958,7 +892,7 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
VATAmount itemVATAmount = new VATAmount(
|
VATAmount itemVATAmount = new VATAmount(
|
||||||
logisticsServiceCharge.getTotalAmount(),
|
logisticsServiceCharge.getTotalAmount(),
|
||||||
logisticsServiceCharge.getTotalAmount()
|
logisticsServiceCharge.getTotalAmount()
|
||||||
.multiply(percent).divide(new BigDecimal(100)), trans.getDocumentCode());
|
.multiply(percent).divide(new BigDecimal(100)), logisticsServiceCharge.getCategoryCode());
|
||||||
VATAmount current = hm.get(percent);
|
VATAmount current = hm.get(percent);
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
hm.put(percent, itemVATAmount);
|
hm.put(percent, itemVATAmount);
|
||||||
@@ -973,7 +907,7 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
BigDecimal percent = charge.getTaxPercent();
|
BigDecimal percent = charge.getTaxPercent();
|
||||||
VATAmount itemVATAmount = new VATAmount(
|
VATAmount itemVATAmount = new VATAmount(
|
||||||
charge.getTotalAmount(), charge.getTotalAmount()
|
charge.getTotalAmount(), charge.getTotalAmount()
|
||||||
.multiply(percent).divide(new BigDecimal(100)), trans.getDocumentCode());
|
.multiply(percent).divide(new BigDecimal(100)), charge.getCategoryCode());
|
||||||
VATAmount current = hm.get(percent);
|
VATAmount current = hm.get(percent);
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
hm.put(percent, itemVATAmount);
|
hm.put(percent, itemVATAmount);
|
||||||
@@ -992,12 +926,18 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ZUGFeRDTransactionModelConverter withProfile(String profile) {
|
||||||
|
this.profile = profile;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private class LineCalc {
|
private class LineCalc {
|
||||||
|
|
||||||
private BigDecimal totalGross;
|
private BigDecimal totalGross;
|
||||||
private BigDecimal itemTotalNetAmount;
|
private BigDecimal itemTotalNetAmount;
|
||||||
private BigDecimal itemTotalVATAmount;
|
private BigDecimal itemTotalVATAmount;
|
||||||
private BigDecimal itemNetAmount;
|
private BigDecimal itemNetAmount;
|
||||||
|
private String categoryCode;
|
||||||
|
|
||||||
|
|
||||||
public LineCalc(IZUGFeRDExportableItem currentItem) {
|
public LineCalc(IZUGFeRDExportableItem currentItem) {
|
||||||
@@ -1040,6 +980,7 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
.add(totalCharge)
|
.add(totalCharge)
|
||||||
.divide(currentItem.getQuantity(), 4,
|
.divide(currentItem.getQuantity(), 4,
|
||||||
BigDecimal.ROUND_HALF_UP);
|
BigDecimal.ROUND_HALF_UP);
|
||||||
|
categoryCode = currentItem.getCategoryCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1057,6 +998,8 @@ class ZUGFeRDTransactionModelConverter {
|
|||||||
return itemNetAmount;
|
return itemNetAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCategoryCode() { return categoryCode; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Totals {
|
private class Totals {
|
||||||
|
|||||||
165
src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java
Normal file
165
src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/** **********************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2018 Jochen Staerk
|
||||||
|
*
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*********************************************************************** */
|
||||||
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
|
import javax.xml.transform.*;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class ZUGFeRDVisualizer {
|
||||||
|
|
||||||
|
static final ClassLoader CLASS_LOADER = ZUGFeRDVisualizer.class.getClassLoader();
|
||||||
|
private static final String RESOURCE_PATH = ""; //$NON-NLS-1$
|
||||||
|
private static final Logger LOG = Logger.getLogger(ZUGFeRDVisualizer.class.getName());
|
||||||
|
// private static File createTempFileResult(final Transformer transformer, final
|
||||||
|
// StreamSource toTransform,
|
||||||
|
// final String suffix) throws TransformerException, IOException {
|
||||||
|
// File result = File.createTempFile("ZUV_", suffix); //$NON-NLS-1$
|
||||||
|
// result.deleteOnExit();
|
||||||
|
//
|
||||||
|
// try (FileOutputStream fos = new FileOutputStream(result)) {
|
||||||
|
// transformer.transform(toTransform, new StreamResult(fos));
|
||||||
|
// }
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
private TransformerFactory mFactory = null;
|
||||||
|
private Templates mXsltXRTemplate = null;
|
||||||
|
private Templates mXsltHTMLTemplate = null;
|
||||||
|
private Templates mXsltZF1HTMLTemplate = null;
|
||||||
|
|
||||||
|
public ZUGFeRDVisualizer() {
|
||||||
|
mFactory = new net.sf.saxon.TransformerFactoryImpl();
|
||||||
|
// fact = TransformerFactory.newInstance();
|
||||||
|
mFactory.setURIResolver(new ClasspathResourceURIResolver());
|
||||||
|
try {
|
||||||
|
mXsltXRTemplate = mFactory.newTemplates(
|
||||||
|
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/cii-xr.xsl")));
|
||||||
|
mXsltHTMLTemplate = mFactory.newTemplates(new StreamSource(
|
||||||
|
CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xrechnung-html.xsl")));
|
||||||
|
mXsltZF1HTMLTemplate = mFactory.newTemplates(new StreamSource(
|
||||||
|
CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt")));
|
||||||
|
} catch (TransformerConfigurationException ex) {
|
||||||
|
LOG.log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String visualize(String xmlFilename)
|
||||||
|
throws FileNotFoundException, TransformerException, UnsupportedEncodingException {
|
||||||
|
/**
|
||||||
|
* *
|
||||||
|
* http://www.unece.org/fileadmin/DAM/cefact/xml/XML-Naming-And-Design-Rules-V2_1.pdf
|
||||||
|
* http://www.ferd-net.de/upload/Dokumente/FACTUR-X_ZUGFeRD_2p0_Teil1_Profil_EN16931_1p03.pdf
|
||||||
|
* http://countwordsfree.com/xmlviewer
|
||||||
|
*/
|
||||||
|
FileInputStream fis=new FileInputStream(xmlFilename);
|
||||||
|
String fileContent="";
|
||||||
|
try {
|
||||||
|
fileContent = new String(Files.readAllBytes(Paths.get(xmlFilename)));
|
||||||
|
} catch (IOException e2) {
|
||||||
|
LOG.log(Level.SEVERE, null, e2);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArrayOutputStream iaos = new ByteArrayOutputStream();
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
String zf1Signature = "rsm:CrossIndustryDocument";
|
||||||
|
if (fileContent.contains(zf1Signature)) {
|
||||||
|
applyZF1SchematronXsl(fis, baos);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//zf2 or fx
|
||||||
|
applySchematronXsl(fis, iaos);
|
||||||
|
// take the copy of the stream and re-write it to an InputStream
|
||||||
|
PipedInputStream in = new PipedInputStream();
|
||||||
|
PipedOutputStream out;
|
||||||
|
try {
|
||||||
|
out = new PipedOutputStream(in);
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
// write the original OutputStream to the PipedOutputStream
|
||||||
|
// note that in order for the below method to work, you need
|
||||||
|
// to ensure that the data has finished writing to the
|
||||||
|
// ByteArrayOutputStream
|
||||||
|
iaos.writeTo(out);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.log(Level.SEVERE, null, 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
applySchematronXsl2(in, baos);
|
||||||
|
} catch (IOException e1) {
|
||||||
|
LOG.log(Level.SEVERE, null, e1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return baos.toString("UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applySchematronXsl(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
||||||
|
throws TransformerException {
|
||||||
|
Transformer transformer = mXsltXRTemplate.newTransformer();
|
||||||
|
|
||||||
|
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyZF1SchematronXsl(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
||||||
|
throws TransformerException {
|
||||||
|
Transformer transformer = mXsltZF1HTMLTemplate.newTransformer();
|
||||||
|
|
||||||
|
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applySchematronXsl2(final InputStream xmlFile, final OutputStream HTMLOutstream)
|
||||||
|
throws TransformerException {
|
||||||
|
Transformer transformer = mXsltHTMLTemplate.newTransformer();
|
||||||
|
|
||||||
|
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ClasspathResourceURIResolver implements URIResolver {
|
||||||
|
ClasspathResourceURIResolver() {
|
||||||
|
// Do nothing, just prevents synthetic access warning.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Source resolve(String href, String base) throws TransformerException {
|
||||||
|
return new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + href));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
package org.mustangproject.ZUGFeRD.model;
|
package org.mustangproject.ZUGFeRD.model;
|
||||||
|
|
||||||
public class DocumentContextParameterTypeConstants {
|
public class DocumentContextParameterTypeConstants {
|
||||||
|
public static final String BASIC = "urn:ferd:CrossIndustryDocument:invoice:1p0:basic";
|
||||||
public static final String COMFORT = "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort";
|
public static final String COMFORT = "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort";
|
||||||
public static final String EXTENDED = "urn:ferd:CrossIndustryDocument:invoice:1p0:extended";
|
public static final String EXTENDED = "urn:ferd:CrossIndustryDocument:invoice:1p0:extended";
|
||||||
// this does not look complete :-/
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,14 @@ import org.mustangproject.ZUGFeRD.*;
|
|||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.transform.TransformerException;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@@ -104,8 +110,7 @@ public class Toecount {
|
|||||||
+ "\t\t[--source-xml <filename>]: set input XML file\r\n"
|
+ "\t\t[--source-xml <filename>]: set input XML file\r\n"
|
||||||
+ "\t\t[--out <filename>]: set output PDF file\r\n"
|
+ "\t\t[--out <filename>]: set output PDF file\r\n"
|
||||||
+ "\t\t[--format <fx|zf>]: enable factur-x or ZUGFeRD\r\n"
|
+ "\t\t[--format <fx|zf>]: enable factur-x or ZUGFeRD\r\n"
|
||||||
+ "\t\t[--version <1|2>]: set ZUGFeRD version\r\n"
|
+ "\t\t[--version <1|2>]: set ZUGFeRD version\r\n" + "\t\t[--profile <...>]: set ZUGFeRD profile\r\n"
|
||||||
+ "\t\t[--profile <...>]: set ZUGFeRD profile\r\n"
|
|
||||||
+ "\t\t\tFor ZUGFeRD v1: <B>ASIC, <C>OMFORT or <E>XTENDED\r\n"
|
+ "\t\t\tFor ZUGFeRD v1: <B>ASIC, <C>OMFORT or <E>XTENDED\r\n"
|
||||||
+ "\t\t\tFor ZUGFeRD v2: <M>INIMUM, BASIC <W>L, <B>ASIC, <C>IUS, <E>N16931, E<X>TENDED\r\n");
|
+ "\t\t\tFor ZUGFeRD v2: <M>INIMUM, BASIC <W>L, <B>ASIC, <C>IUS, <E>N16931, E<X>TENDED\r\n");
|
||||||
}
|
}
|
||||||
@@ -114,11 +119,15 @@ public class Toecount {
|
|||||||
* Asks the user (repeatedly, if neccessary) on the command line for a String
|
* Asks the user (repeatedly, if neccessary) on the command line for a String
|
||||||
* (offering a defaultValue) conforming to a Regex pattern
|
* (offering a defaultValue) conforming to a Regex pattern
|
||||||
*
|
*
|
||||||
* @param prompt the question to be asked to the user
|
* @param prompt
|
||||||
* @param defaultValue the default return value if user hits enter
|
* the question to be asked to the user
|
||||||
* @param pattern a regex of acceptable values
|
* @param defaultValue
|
||||||
|
* the default return value if user hits enter
|
||||||
|
* @param pattern
|
||||||
|
* a regex of acceptable values
|
||||||
* @return the user answer conforming to pattern
|
* @return the user answer conforming to pattern
|
||||||
* @throws Exception if pattern not compielable or IOexception on input
|
* @throws Exception
|
||||||
|
* if pattern not compielable or IOexception on input
|
||||||
*/
|
*/
|
||||||
protected static String getStringFromUser(String prompt, String defaultValue, String pattern) throws Exception {
|
protected static String getStringFromUser(String prompt, String defaultValue, String pattern) throws Exception {
|
||||||
String input = "";
|
String input = "";
|
||||||
@@ -157,15 +166,15 @@ public class Toecount {
|
|||||||
/**
|
/**
|
||||||
* Prompts the user for a input or output filename
|
* Prompts the user for a input or output filename
|
||||||
*
|
*
|
||||||
* @param the text the user is asked
|
* @param prompt the text the user is asked
|
||||||
* @param a default Filename
|
* @param defaultFilename a default Filename
|
||||||
* @param expectedExtension will warn if filename does not match expected file extension
|
* @param expectedExtension will warn if filename does not match expected file extension
|
||||||
* @param ensureFileExists will warn if file does NOT exist (for input files)
|
* @param ensureFileExists will warn if file does NOT exist (for input files)
|
||||||
* @param ensureFileNotExists will warn if file DOES exist (for output files)
|
* @param ensureFileNotExists will warn if file DOES exist (for output files)
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
protected static String getFilenameFromUser(String prompt, String defaultFilename, String expectedExtension,
|
protected static String getFilenameFromUser(String prompt, String defaultFilename, String expectedExtension,
|
||||||
boolean ensureFileExists, boolean ensureFileNotExists) {
|
boolean ensureFileExists, boolean ensureFileNotExists) {
|
||||||
boolean fileExistenceOK = false;
|
boolean fileExistenceOK = false;
|
||||||
String selectedName = "";
|
String selectedName = "";
|
||||||
do {
|
do {
|
||||||
@@ -235,6 +244,8 @@ public class Toecount {
|
|||||||
|
|
||||||
// Option: Help
|
// Option: Help
|
||||||
Option<Boolean> helpOption = parser.addBooleanOption('h', "help");
|
Option<Boolean> helpOption = parser.addBooleanOption('h', "help");
|
||||||
|
// Option: Action
|
||||||
|
Option<String> actionOption = parser.addStringOption('a', "action");
|
||||||
|
|
||||||
// Generic options available for multiple command
|
// Generic options available for multiple command
|
||||||
// --source: input file
|
// --source: input file
|
||||||
@@ -292,14 +303,15 @@ public class Toecount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve all options
|
// Retrieve all options
|
||||||
|
String action = parser.getOptionValue(actionOption);
|
||||||
String directoryName = parser.getOptionValue(dirnameOption);
|
String directoryName = parser.getOptionValue(dirnameOption);
|
||||||
Boolean filesFromStdIn = parser.getOptionValue(filesFromStdInOption, Boolean.FALSE);
|
Boolean filesFromStdIn = parser.getOptionValue(filesFromStdInOption, Boolean.FALSE);
|
||||||
Boolean combineRequested = parser.getOptionValue(combineOption, Boolean.FALSE);
|
Boolean combineRequested = parser.getOptionValue(combineOption, Boolean.FALSE) || ((action!=null)&&(action.equals("combine")));
|
||||||
Boolean extractRequested = parser.getOptionValue(extractOption, Boolean.FALSE);
|
Boolean extractRequested = parser.getOptionValue(extractOption, Boolean.FALSE) || ((action!=null)&&(action.equals("extract")));
|
||||||
Boolean helpRequested = parser.getOptionValue(helpOption, Boolean.FALSE);
|
Boolean helpRequested = parser.getOptionValue(helpOption, Boolean.FALSE) || ((action!=null)&&(action.equals("help")));
|
||||||
Boolean upgradeRequested = parser.getOptionValue(upgradeOption, Boolean.FALSE);
|
Boolean upgradeRequested = parser.getOptionValue(upgradeOption, Boolean.FALSE) || ((action!=null)&&(action.equals("upgrade")));
|
||||||
Boolean ignoreFileExt = parser.getOptionValue(ignoreFileExtOption, Boolean.FALSE);
|
Boolean ignoreFileExt = parser.getOptionValue(ignoreFileExtOption, Boolean.FALSE);
|
||||||
Boolean a3only = parser.getOptionValue(a3onlyOption, Boolean.FALSE);
|
Boolean a3only = parser.getOptionValue(a3onlyOption, Boolean.FALSE) || ((action!=null)&&(action.equals("a3")));
|
||||||
String sourceName = parser.getOptionValue(sourceOption);
|
String sourceName = parser.getOptionValue(sourceOption);
|
||||||
String sourceXMLName = parser.getOptionValue(sourceXmlOption);
|
String sourceXMLName = parser.getOptionValue(sourceXmlOption);
|
||||||
String outName = parser.getOptionValue(outOption);
|
String outName = parser.getOptionValue(outOption);
|
||||||
@@ -325,7 +337,7 @@ public class Toecount {
|
|||||||
System.exit(2);
|
System.exit(2);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
||||||
Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e);
|
Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e);
|
||||||
System.exit(-1);
|
System.exit(-1);
|
||||||
}
|
}
|
||||||
@@ -341,7 +353,7 @@ public class Toecount {
|
|||||||
System.out.println("ZUGFeRD 1.0 XML source set to " + xmlName);
|
System.out.println("ZUGFeRD 1.0 XML source set to " + xmlName);
|
||||||
}
|
}
|
||||||
if (outName == null) {
|
if (outName == null) {
|
||||||
outName = getFilenameFromUser("ZUGFeRD 2.0 XML target", "factur-x.xml", "xml", false, true);
|
outName = getFilenameFromUser("ZUGFeRD 2.0 XML target", "zugferd-invoice.xml", "xml", false, true);
|
||||||
} else {
|
} else {
|
||||||
System.out.println("ZUGFeRD 1.0 XML source set to " + outName);
|
System.out.println("ZUGFeRD 1.0 XML source set to " + outName);
|
||||||
}
|
}
|
||||||
@@ -421,7 +433,7 @@ public class Toecount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void performCombine(String pdfName, String xmlName, String outName, String format, String zfVersion,
|
private static void performCombine(String pdfName, String xmlName, String outName, String format, String zfVersion,
|
||||||
String zfProfile) throws Exception {
|
String zfProfile) throws Exception {
|
||||||
/*
|
/*
|
||||||
* ZUGFeRDExporter ze= new ZUGFeRDExporterFromA1Factory()
|
* ZUGFeRDExporter ze= new ZUGFeRDExporterFromA1Factory()
|
||||||
* .setProducer("toecount") .setCreator(System.getProperty("user.name"))
|
* .setProducer("toecount") .setCreator(System.getProperty("user.name"))
|
||||||
@@ -459,7 +471,6 @@ public class Toecount {
|
|||||||
System.out.println("Format set to " + format);
|
System.out.println("Format set to " + format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (zfVersion == null) {
|
if (zfVersion == null) {
|
||||||
try {
|
try {
|
||||||
zfVersion = getStringFromUser("Version (1 or 2)", "1", "1|2");
|
zfVersion = getStringFromUser("Version (1 or 2)", "1", "1|2");
|
||||||
@@ -473,13 +484,12 @@ public class Toecount {
|
|||||||
|
|
||||||
if (zfProfile == null) {
|
if (zfProfile == null) {
|
||||||
try {
|
try {
|
||||||
if (format.equals("zf")&&(zfIntVersion == 1)) {
|
if (format.equals("zf") && (zfIntVersion == 1)) {
|
||||||
zfProfile = getStringFromUser("Profile b)asic, c)omfort or e)xtended", "e",
|
zfProfile = getStringFromUser("Profile b)asic, c)omfort or e)xtended", "e", "B|b|C|c|E|e");
|
||||||
"B|b|C|c|E|e");
|
|
||||||
} else {
|
} else {
|
||||||
zfProfile = getStringFromUser(
|
zfProfile = getStringFromUser(
|
||||||
"Profile [M]INIMUM, BASIC [W]L, [B]ASIC,\n" + "[C]IUS, [E]N16931, E[X]TENDED",
|
"Profile [M]INIMUM, BASIC [W]L, [B]ASIC,\n" + "[C]IUS, [E]N16931, E[X]TENDED", "E",
|
||||||
"E", "M|m|W|w|B|b|C|c|E|e|X|x|");
|
"M|m|W|w|B|b|C|c|E|e|X|x|");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e);
|
Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e);
|
||||||
@@ -494,12 +504,12 @@ public class Toecount {
|
|||||||
ensureFileExists(pdfName);
|
ensureFileExists(pdfName);
|
||||||
ensureFileExists(xmlName);
|
ensureFileExists(xmlName);
|
||||||
ensureFileNotExists(outName);
|
ensureFileNotExists(outName);
|
||||||
|
|
||||||
if ((format.equals("fx"))&&(zfIntVersion>1)) {
|
if ((format.equals("fx")) && (zfIntVersion > 1)) {
|
||||||
throw new Exception("Factur-X is only available in version 1 (roughly corresponding to ZF2)");
|
throw new Exception("Factur-X is only available in version 1 (roughly corresponding to ZF2)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((format.equals("zf"))&&(zfIntVersion == 1)) {
|
if ((format.equals("zf")) && (zfIntVersion == 1)) {
|
||||||
if (zfProfile.equals("b")) {
|
if (zfProfile.equals("b")) {
|
||||||
zfConformanceLevelProfile = ZUGFeRDConformanceLevel.BASIC;
|
zfConformanceLevelProfile = ZUGFeRDConformanceLevel.BASIC;
|
||||||
} else if (zfProfile.equals("c")) {
|
} else if (zfProfile.equals("c")) {
|
||||||
@@ -509,7 +519,7 @@ public class Toecount {
|
|||||||
} else {
|
} else {
|
||||||
throw new Exception(String.format("Unknown ZUGFeRD profile '%s'", zfProfile));
|
throw new Exception(String.format("Unknown ZUGFeRD profile '%s'", zfProfile));
|
||||||
}
|
}
|
||||||
} else if (((format.equals("zf"))&&(zfIntVersion == 2))||(format.equals("fx"))) {
|
} else if (((format.equals("zf")) && (zfIntVersion == 2)) || (format.equals("fx"))) {
|
||||||
if (zfProfile.equals("m")) {
|
if (zfProfile.equals("m")) {
|
||||||
zfConformanceLevelProfile = ZUGFeRDConformanceLevel.MINIMUM;
|
zfConformanceLevelProfile = ZUGFeRDConformanceLevel.MINIMUM;
|
||||||
} else if (zfProfile.equals("w")) {
|
} else if (zfProfile.equals("w")) {
|
||||||
@@ -538,7 +548,6 @@ public class Toecount {
|
|||||||
if (format.equals("fx")) {
|
if (format.equals("fx")) {
|
||||||
ze.setFacturX();
|
ze.setFacturX();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ze.setZUGFeRDXMLData(Files.readAllBytes(Paths.get(xmlName)));
|
ze.setZUGFeRDXMLData(Files.readAllBytes(Paths.get(xmlName)));
|
||||||
|
|
||||||
|
|||||||
3008
src/main/resources/stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt
Normal file
3008
src/main/resources/stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt
Normal file
File diff suppressed because it is too large
Load Diff
65
src/test/java/org/mustangproject/ZUGFeRD/BaseTest.java
Normal file
65
src/test/java/org/mustangproject/ZUGFeRD/BaseTest.java
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/** **********************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2019 Jochen Staerk
|
||||||
|
*
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*********************************************************************** */
|
||||||
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class BaseTest extends TestCase {
|
||||||
|
/**
|
||||||
|
* Create the test case
|
||||||
|
*
|
||||||
|
* @param testName name of the test case
|
||||||
|
*/
|
||||||
|
public BaseTest(String testName) {
|
||||||
|
super(testName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the suite of tests being tested
|
||||||
|
*/
|
||||||
|
public static Test suite() {
|
||||||
|
return new TestSuite(BaseTest.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCorrectDigits() {
|
||||||
|
assertEquals("0.00", ZUGFeRD2PullProvider.nDigitFormat(new BigDecimal(0),2));
|
||||||
|
assertEquals("-1.10", ZUGFeRD2PullProvider.nDigitFormat(new BigDecimal("-1.10"),2));
|
||||||
|
assertEquals("-1.10", ZUGFeRD2PullProvider.nDigitFormat(new BigDecimal("-1.1"),2));
|
||||||
|
assertEquals("-1.01", ZUGFeRD2PullProvider.nDigitFormat(new BigDecimal("-1.01"),2));
|
||||||
|
assertEquals("20000123.35", ZUGFeRD2PullProvider.nDigitFormat(new BigDecimal("20000123.3489"),2));
|
||||||
|
assertEquals("20000123.34", ZUGFeRD2PullProvider.nDigitFormat(new BigDecimal("20000123.3419"),2));
|
||||||
|
assertEquals("12.00", ZUGFeRD2PullProvider.nDigitFormat(new BigDecimal("12"),2));
|
||||||
|
assertEquals("12", ZUGFeRD2PullProvider.nDigitFormat(new BigDecimal("12"),0));
|
||||||
|
assertEquals("20000123.342", ZUGFeRD2PullProvider.nDigitFormat(new BigDecimal("20000123.3419"),3));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ import org.junit.runners.MethodSorters;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
public class MustangReaderWriterCustomXMLTest extends TestCase {
|
public class MustangReaderWriterCustomXMLTest extends TestCase {
|
||||||
@@ -49,7 +50,7 @@ public class MustangReaderWriterCustomXMLTest extends TestCase {
|
|||||||
|
|
||||||
// //////// TESTS
|
// //////// TESTS
|
||||||
// //////////////////////////////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////////////////////////////
|
||||||
public void testCustomZF2Export() throws Exception {
|
public void testCustomZF2Export() {
|
||||||
|
|
||||||
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20171118_506custom.pdf";
|
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20171118_506custom.pdf";
|
||||||
// the writing part
|
// the writing part
|
||||||
@@ -61,8 +62,10 @@ public class MustangReaderWriterCustomXMLTest extends TestCase {
|
|||||||
.load(SOURCE_PDF);
|
.load(SOURCE_PDF);
|
||||||
|
|
||||||
final byte[] UTF8ByteOrderMark = new byte[]{(byte) 0xef, (byte) 0xbb, (byte) 0xbf};
|
final byte[] UTF8ByteOrderMark = new byte[]{(byte) 0xef, (byte) 0xbb, (byte) 0xbf};
|
||||||
/* we have much more information than just in the basic profile (comfort or extended) but it's perfectly valid to provide more information, just not less. */
|
/* we have much more information than just in the basic profile (comfort or extended) but it's perfectly valid to provide more information, just not less.
|
||||||
String ownZUGFeRDXML = new String(UTF8ByteOrderMark) + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
* test the export with bom (which is valid) because this will also test the import (which also needs to work and needs to be tested)
|
||||||
|
* */
|
||||||
|
String ownZUGFeRDXML = new String(UTF8ByteOrderMark, StandardCharsets.UTF_8) + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||||
"<rsm:CrossIndustryInvoice xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:rsm=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100\" xmlns:ram=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100\" xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100\">\n" +
|
"<rsm:CrossIndustryInvoice xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:rsm=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100\" xmlns:ram=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100\" xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100\">\n" +
|
||||||
" <rsm:ExchangedDocumentContext>\n" +
|
" <rsm:ExchangedDocumentContext>\n" +
|
||||||
" <ram:TestIndicator><udt:Indicator>false</udt:Indicator></ram:TestIndicator>\n" +
|
" <ram:TestIndicator><udt:Indicator>false</udt:Indicator></ram:TestIndicator>\n" +
|
||||||
@@ -286,10 +289,10 @@ public class MustangReaderWriterCustomXMLTest extends TestCase {
|
|||||||
* ./src/test/MustangGnuaccountingBeispielRE-20140703_502blanko.pdf}, adds
|
* ./src/test/MustangGnuaccountingBeispielRE-20140703_502blanko.pdf}, adds
|
||||||
* metadata, writes to @{code ./target/testout-*} and then imports to check the
|
* metadata, writes to @{code ./target/testout-*} and then imports to check the
|
||||||
* values. It would not make sense to have it run before the less complex
|
* values. It would not make sense to have it run before the less complex
|
||||||
* importer test (which is probably redundant) --> as only Name Ascending is
|
* importer test (which is probably redundant). As only Name Ascending is
|
||||||
* supported for Test Unit sequence, I renamed the Exporter Test test-Z-Export
|
* supported for Test Unit sequence, I renamed the Exporter Test test-Z-Export
|
||||||
*/
|
*/
|
||||||
public void testCustomZF1Export() throws Exception {
|
public void testCustomZF1Export() {
|
||||||
|
|
||||||
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505custom.pdf";
|
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505custom.pdf";
|
||||||
// the writing part
|
// the writing part
|
||||||
|
|||||||
@@ -170,13 +170,11 @@ public class MustangReaderWriterEdgeTest extends MustangReaderTestCase {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The importer test imports from ./src/test/MustangGnuaccountingBeispielRE-20170509_505.pdf to check the values.
|
* The importer test imports from ./src/test/MustangGnuaccountingBeispielRE-20170509_505.pdf to check the values.
|
||||||
* --> as only Name Ascending is supported for Test Unit sequence, I renamed the this test-A-Export to run before
|
* As only Name Ascending is supported for Test Unit sequence, I renamed the this test-A-Import to run before
|
||||||
* testZExport
|
* testZExport
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void testAImport() throws IOException {
|
public void testAImport() {
|
||||||
InputStream inputStream = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505.pdf");
|
InputStream inputStream = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505.pdf");
|
||||||
ZUGFeRDImporter zi = new ZUGFeRDImporter(inputStream);
|
ZUGFeRDImporter zi = new ZUGFeRDImporter(inputStream);
|
||||||
|
|
||||||
@@ -195,12 +193,11 @@ public class MustangReaderWriterEdgeTest extends MustangReaderTestCase {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The exporter test bases on @{code ./src/test/MustangGnuaccountingBeispielRE-20140703_502blanko.pdf}, adds metadata,
|
* The exporter test bases on @{code ./src/test/MustangGnuaccountingBeispielRE-20140703_502blanko.pdf}, adds metadata,
|
||||||
* writes
|
* writes to @{code ./target/testout-*} and then imports to check the values.
|
||||||
* to @{code ./target/testout-*} and then imports to check the values.
|
* It would not make sense to have it run before the less complex importer test (which is probably redundant).
|
||||||
* It would not make sense to have it run before the less complex importer test (which is probably redundant)
|
* As only Name Ascending is supported for Test Unit sequence, I renamed the Exporter Test test-Z-Export
|
||||||
* --> as only Name Ascending is supported for Test Unit sequence, I renamed the Exporter Test test-Z-Export
|
|
||||||
*/
|
*/
|
||||||
public void testEdgeExport() throws Exception {
|
public void testEdgeExport() {
|
||||||
|
|
||||||
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505newEdge.pdf";
|
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505newEdge.pdf";
|
||||||
// the writing part
|
// the writing part
|
||||||
@@ -218,6 +215,8 @@ public class MustangReaderWriterEdgeTest extends MustangReaderTestCase {
|
|||||||
String theXML = new String(ze.getProvider().getXML());
|
String theXML = new String(ze.getProvider().getXML());
|
||||||
assertTrue(theXML.contains("<rsm:CrossIndustryDocument"));
|
assertTrue(theXML.contains("<rsm:CrossIndustryDocument"));
|
||||||
ze.export(TARGET_PDF);
|
ze.export(TARGET_PDF);
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("IOException should not happen in testEdgeExport");
|
||||||
}
|
}
|
||||||
|
|
||||||
// now check the contents (like MustangReaderTest)
|
// now check the contents (like MustangReaderTest)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.apache.xmpbox.xml.DomXmpParser;
|
|||||||
import org.apache.xmpbox.xml.XmpParsingException;
|
import org.apache.xmpbox.xml.XmpParsingException;
|
||||||
import org.junit.FixMethodOrder;
|
import org.junit.FixMethodOrder;
|
||||||
import org.junit.runners.MethodSorters;
|
import org.junit.runners.MethodSorters;
|
||||||
|
import org.mustangproject.ZUGFeRD.model.DocumentContextParameterTypeConstants;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -184,15 +185,12 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
|||||||
// //////////////////////////////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The importer test imports from
|
* The importer test imports from ./src/test/MustangGnuaccountingBeispielRE-20170509_505.pdf to check the
|
||||||
* ./src/test/MustangGnuaccountingBeispielRE-20170509_505.pdf to check the
|
* values. As only Name Ascending is supported for Test Unit sequence, I renamed the this testAImport
|
||||||
* values. --> as only Name Ascending is supported for Test Unit sequence, I
|
* to run before testZExport
|
||||||
* renamed the this test-A-Export to run before testZExport
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void testAImport() throws IOException {
|
public void testAImport() {
|
||||||
InputStream inputStream = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505.pdf");
|
InputStream inputStream = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505.pdf");
|
||||||
ZUGFeRDImporter zi = new ZUGFeRDImporter(inputStream);
|
ZUGFeRDImporter zi = new ZUGFeRDImporter(inputStream);
|
||||||
|
|
||||||
@@ -206,7 +204,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
|||||||
assertEquals(zi.getForeignReference(), "RE-20170509/505");
|
assertEquals(zi.getForeignReference(), "RE-20170509/505");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testForeignImport() throws IOException {
|
public void testForeignImport() {
|
||||||
InputStream inputStream = this.getClass().getResourceAsStream("/zugferd_invoice.pdf");
|
InputStream inputStream = this.getClass().getResourceAsStream("/zugferd_invoice.pdf");
|
||||||
ZUGFeRDImporter zi = new ZUGFeRDImporter(inputStream);
|
ZUGFeRDImporter zi = new ZUGFeRDImporter(inputStream);
|
||||||
|
|
||||||
@@ -343,16 +341,16 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
|||||||
* ./src/test/MustangGnuaccountingBeispielRE-20140703_502blanko.pdf}, adds
|
* ./src/test/MustangGnuaccountingBeispielRE-20140703_502blanko.pdf}, adds
|
||||||
* metadata, writes to @{code ./target/testout-*} and then imports to check the
|
* metadata, writes to @{code ./target/testout-*} and then imports to check the
|
||||||
* values. It would not make sense to have it run before the less complex
|
* values. It would not make sense to have it run before the less complex
|
||||||
* importer test (which is probably redundant) --> as only Name Ascending is
|
* importer test (which is probably redundant). As only Name Ascending is
|
||||||
* supported for Test Unit sequence, I renamed the Exporter Test test-Z-Export
|
* supported for Test Unit sequence, I renamed the Exporter Test test-Z-Export
|
||||||
*/
|
*/
|
||||||
public void testZExport() throws Exception {
|
public void testZExport() {
|
||||||
|
|
||||||
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20171118_506new.pdf";
|
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20171118_506new.pdf";
|
||||||
|
|
||||||
// the writing part
|
// the writing part
|
||||||
try (InputStream SOURCE_PDF = this.getClass()
|
try (InputStream SOURCE_PDF = this.getClass()
|
||||||
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf");
|
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf");
|
||||||
|
|
||||||
ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setZUGFeRDVersion(2).setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.EN16931).load(SOURCE_PDF)) {
|
ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setZUGFeRDVersion(2).setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.EN16931).load(SOURCE_PDF)) {
|
||||||
|
|
||||||
@@ -369,7 +367,9 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
|||||||
// assertFalse(pdfContent.indexOf("<zf:ConformanceLevel>EN 16931</zf:ConformanceLevel>") == -1);
|
// assertFalse(pdfContent.indexOf("<zf:ConformanceLevel>EN 16931</zf:ConformanceLevel>") == -1);
|
||||||
// assertFalse(pdfContent.indexOf("<pdfaSchema:prefix>zf</pdfaSchema:prefix>") == -1);
|
// assertFalse(pdfContent.indexOf("<pdfaSchema:prefix>zf</pdfaSchema:prefix>") == -1);
|
||||||
// assertFalse(pdfContent.indexOf("urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#") == -1);
|
// assertFalse(pdfContent.indexOf("urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#") == -1);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("IOException should not happen in testZExport");
|
||||||
}
|
}
|
||||||
|
|
||||||
// now check the contents (like MustangReaderTest)
|
// now check the contents (like MustangReaderTest)
|
||||||
@@ -385,6 +385,37 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
|||||||
assertEquals(zi.getForeignReference(), getNumber());
|
assertEquals(zi.getForeignReference(), getNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quick and dirty copy of testZExport to check if v1 files contain
|
||||||
|
* the correct profile string when the comfort profile is selected.
|
||||||
|
*/
|
||||||
|
public void testZExportv1Profile() {
|
||||||
|
|
||||||
|
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20171118_506new.pdf";
|
||||||
|
|
||||||
|
// the writing part
|
||||||
|
try (InputStream SOURCE_PDF = this.getClass()
|
||||||
|
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf");
|
||||||
|
|
||||||
|
ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setZUGFeRDVersion(1).setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.COMFORT).load(SOURCE_PDF)) {
|
||||||
|
|
||||||
|
ze.PDFattachZugferdFile(this);
|
||||||
|
ze.disableAutoClose(true);
|
||||||
|
ze.export(TARGET_PDF);
|
||||||
|
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
ze.export(baos);
|
||||||
|
ze.close();
|
||||||
|
String pdfContent = baos.toString("UTF-8");
|
||||||
|
assertFalse(pdfContent.indexOf(DocumentContextParameterTypeConstants.BASIC) >= 0);
|
||||||
|
assertFalse(pdfContent.indexOf(DocumentContextParameterTypeConstants.EXTENDED) >= 0);
|
||||||
|
assertTrue(pdfContent.indexOf(DocumentContextParameterTypeConstants.COMFORT) >= 0);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("IOException should not happen in testZExport");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testFXExport() throws Exception {
|
public void testFXExport() throws Exception {
|
||||||
|
|
||||||
@@ -423,11 +454,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
|||||||
assertEquals(zi.getForeignReference(), getNumber());
|
assertEquals(zi.getForeignReference(), getNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void testExceptionOnPDF14() {
|
||||||
* @throws Exception
|
|
||||||
* @Test(expected = IndexOutOfBoundsException.class)
|
|
||||||
*/
|
|
||||||
public void testExceptionOnPDF14() throws Exception {
|
|
||||||
|
|
||||||
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505new.pdf";
|
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505new.pdf";
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ public class ResourceUtilities {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Loading a File into a String using a certain encoding and file path
|
* Loading a File into a String using a certain encoding and file path
|
||||||
|
* @param encoding the charset used in the file
|
||||||
|
* @param path the path to the file
|
||||||
|
* @return the file contents as a String
|
||||||
|
* @throws IOException if the file cannot be read
|
||||||
*/
|
*/
|
||||||
public static String readFile(Charset encoding, String path) throws IOException {
|
public static String readFile(Charset encoding, String path) throws IOException {
|
||||||
byte[] content = Files.readAllBytes(Paths.get(path));
|
byte[] content = Files.readAllBytes(Paths.get(path));
|
||||||
@@ -42,6 +46,10 @@ public class ResourceUtilities {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Saving a String as a file to a certain file path
|
* Saving a String as a file to a certain file path
|
||||||
|
* @param encoding the charset used in the file
|
||||||
|
* @param path the path to the file
|
||||||
|
* @param content the contents of the file
|
||||||
|
* @throws FileNotFoundException if the file cannot be found
|
||||||
*/
|
*/
|
||||||
public static void saveFile(Charset encoding, String path, String content) throws FileNotFoundException {
|
public static void saveFile(Charset encoding, String path, String content) throws FileNotFoundException {
|
||||||
|
|
||||||
@@ -147,7 +155,7 @@ public class ResourceUtilities {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* To fix the 3 slashes bug for File URI: For example:
|
* To fix the 3 slashes bug for File URI: For example:
|
||||||
* file:/C:/work/test.txt -> file:///C:/work/test.txt
|
* file:/C:/work/test.txt gives file:///C:/work/test.txt
|
||||||
*
|
*
|
||||||
* @param u - the File URI
|
* @param u - the File URI
|
||||||
* @return the String of the URI
|
* @return the String of the URI
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import static org.junit.Assert.assertFalse;
|
|||||||
* will be migrated to <code>src/test/resources/migration/output</code>.
|
* will be migrated to <code>src/test/resources/migration/output</code>.
|
||||||
* If there is a similar named file as test reference <code>src/test/resources/migration/reference</code> a test
|
* If there is a similar named file as test reference <code>src/test/resources/migration/reference</code> a test
|
||||||
* will be triggered for every single file.
|
* will be triggered for every single file.
|
||||||
* <p/>
|
*
|
||||||
* Note: Any 'ZUGFeRD1' will be exchanged to 'ZUGFeRD2' during migration and adequate reference will be searched for.
|
* Note: Any 'ZUGFeRD1' will be exchanged to 'ZUGFeRD2' during migration and adequate reference will be searched for.
|
||||||
*/
|
*/
|
||||||
@RunWith(Parameterized.class)
|
@RunWith(Parameterized.class)
|
||||||
|
|||||||
211
src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java
Normal file
211
src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
/** **********************************************************************
|
||||||
|
*
|
||||||
|
* Copyright 2019 Jochen Staerk
|
||||||
|
*
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*********************************************************************** */
|
||||||
|
package org.mustangproject.ZUGFeRD;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
public class ZF2EdgeTest extends MustangReaderTestCase {
|
||||||
|
final String TARGET_PDF = "./target/testout-ZF2newEdge.pdf";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getDeliveryDate() {
|
||||||
|
return new GregorianCalendar(2017, Calendar.MAY, 7).getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getDueDate() {
|
||||||
|
return new GregorianCalendar(2017, Calendar.MAY, 30).getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getIssueDate() {
|
||||||
|
return new GregorianCalendar(2017, Calendar.MAY, 9).getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNumber() {
|
||||||
|
return "RE-20170509/505";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwnCountry() {
|
||||||
|
return "DE";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwnLocation() {
|
||||||
|
return "Stadthausen";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwnOrganisationName() {
|
||||||
|
return "Bei Spiel GmbH";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwnStreet() {
|
||||||
|
return "Ecke 12";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IZUGFeRDExportableContact getOwnContact() {
|
||||||
|
return new SenderContact();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwnTaxID() {
|
||||||
|
return "22/815/0815/4";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwnVATID() {
|
||||||
|
return "DE136695976";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwnZIP() {
|
||||||
|
return "12345";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IZUGFeRDExportableContact getRecipient() {
|
||||||
|
return new RecipientContact();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwnOrganisationFullPlaintextInfo() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCurrency() {
|
||||||
|
return "EUR";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IZUGFeRDExportableItem[] getZFItems() {
|
||||||
|
Item[] allItems = new Item[3];
|
||||||
|
Product designProduct = new Product("", "Künstlerische Gestaltung (Stunde): Einer Beispielrechnung", "HUR", new BigDecimal("7.000000"));
|
||||||
|
Product balloonProduct = new Product("", "Bestellerweiterung für E&F Umbau", "C62", new BigDecimal("19.000000"));
|
||||||
|
Product airProduct = new Product("", "Heiße Luft pro Liter", "LTR", new BigDecimal("19.000000"));
|
||||||
|
|
||||||
|
allItems[0] = new Item(new BigDecimal("160"), new BigDecimal("1"), designProduct);
|
||||||
|
allItems[1] = new Item(new BigDecimal("0.79"), new BigDecimal("400"), balloonProduct);
|
||||||
|
allItems[2] = new Item(new BigDecimal("0.10"), new BigDecimal("200"), airProduct);
|
||||||
|
return allItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPaymentTermDescription() {
|
||||||
|
SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy");
|
||||||
|
return "Zahlbar ohne Abzug bis zum " + germanDateFormat.format(getDueDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IZUGFeRDAllowanceCharge[] getZFAllowances() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IZUGFeRDAllowanceCharge[] getZFCharges() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IZUGFeRDAllowanceCharge[] getZFLogisticsServiceCharges() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getReferenceNumber() {
|
||||||
|
return "AB321";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the test case
|
||||||
|
*
|
||||||
|
* @param testName name of the test case
|
||||||
|
*/
|
||||||
|
public ZF2EdgeTest(String testName) {
|
||||||
|
super(testName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the suite of tests being tested
|
||||||
|
*/
|
||||||
|
public static Test suite() {
|
||||||
|
return new TestSuite(ZF2EdgeTest.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// //////// TESTS //////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The exporter test bases on @{code ./src/test/MustangGnuaccountingBeispielRE-20170509_505PDFA3.pdf}, adds metadata,
|
||||||
|
* writes to @{code ./target/testout-*} and then imports to check the values.
|
||||||
|
*/
|
||||||
|
public void testEdgeExport() {
|
||||||
|
|
||||||
|
// the writing part
|
||||||
|
|
||||||
|
try (InputStream SOURCE_PDF =
|
||||||
|
this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505PDFA3.pdf");
|
||||||
|
|
||||||
|
ZUGFeRDExporter ze = new ZUGFeRDExporterFromA3Factory()
|
||||||
|
.setProducer("My Application")
|
||||||
|
.setCreator(System.getProperty("user.name"))
|
||||||
|
.setZUGFeRDVersion(2)
|
||||||
|
.ignorePDFAErrors()
|
||||||
|
.load(SOURCE_PDF)) {
|
||||||
|
ze.setZUGFeRDVersion(1);
|
||||||
|
ze.PDFattachZugferdFile(this);
|
||||||
|
String theXML = new String(ze.getProvider().getXML());
|
||||||
|
assertTrue(theXML.contains("<rsm:CrossIndustryDocument"));
|
||||||
|
ze.export(TARGET_PDF);
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("IOException should not be raised in testEdgeExport");
|
||||||
|
}
|
||||||
|
|
||||||
|
// now check the contents (like MustangReaderTest)
|
||||||
|
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF);
|
||||||
|
|
||||||
|
// Reading ZUGFeRD
|
||||||
|
assertEquals(zi.getAmount(), "571.04");
|
||||||
|
assertEquals(zi.getBIC(), getTradeSettlementPayment()[0].getOwnBIC());
|
||||||
|
assertEquals(zi.getBLZ(), getTradeSettlementPayment()[0].getOwnBLZ());
|
||||||
|
assertEquals(zi.getIBAN(), getTradeSettlementPayment()[0].getOwnIBAN());
|
||||||
|
assertEquals(zi.getKTO(), getTradeSettlementPayment()[0].getOwnKto());
|
||||||
|
assertEquals(zi.getHolder(), getOwnOrganisationName());
|
||||||
|
assertEquals(zi.getForeignReference(), getNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Binary file not shown.
Reference in New Issue
Block a user