Merge branch 'master' into issues/458-multiple-payment-details
This commit is contained in:
@@ -134,7 +134,10 @@ public class Charge implements IZUGFeRDAllowanceCharge {
|
||||
if (totalAmount!=null) {
|
||||
return totalAmount;
|
||||
} else {
|
||||
throw new RuntimeException("totalAmount must be set");
|
||||
if (percent==null) {
|
||||
throw new RuntimeException("totalAmount must be set");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ public class FileAttachment {
|
||||
|
||||
protected String filename;
|
||||
protected String mimetype;
|
||||
protected String relation;
|
||||
protected String relation = "Unspecified";
|
||||
protected String description;
|
||||
protected byte[] data;
|
||||
|
||||
@@ -29,6 +29,13 @@ public class FileAttachment {
|
||||
this.description = "Additional file attachment";
|
||||
}
|
||||
|
||||
public FileAttachment(String filename, String mimetype, byte[] data) {
|
||||
this.filename = filename;
|
||||
this.mimetype = mimetype;
|
||||
this.data = data;
|
||||
this.description = "Additional file attachment";
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
@@ -60,6 +67,28 @@ public class FileAttachment {
|
||||
return relation;
|
||||
}
|
||||
|
||||
/***
|
||||
* only needed when embedded in PDF described
|
||||
*
|
||||
* values
|
||||
* - Source shall be used if this file specification is the original
|
||||
* source material for the associated content.
|
||||
* - Data shall be used if this file specification represents information
|
||||
* used to derive a visual presentation, such as for a table or a
|
||||
* graph.
|
||||
* - Alternative shall be used if this file specification is an alternative
|
||||
* representation of content, for example audio.
|
||||
* - Supplement shall be used if this file specification represents a
|
||||
* supplemental representation of the original source or data that
|
||||
* may be more easily consumable (e.g. A MathML version of an
|
||||
* equation).
|
||||
* - Unspecified shall be used when the relationship is not known
|
||||
* or cannot be described using one of the other values.
|
||||
* @param relation String: either : Source, Data or Alternative. Usually Data, except source if the file attachment
|
||||
* is the basis for the pdf (xrechnung2fx) or Alternative if it contains the same content (e.g. the
|
||||
* factur-x.xml file in a factur-x PDF)
|
||||
* @return fluent setter
|
||||
*/
|
||||
public FileAttachment setRelation(String relation) {
|
||||
this.relation = relation;
|
||||
return this;
|
||||
|
||||
@@ -69,6 +69,7 @@ public class Invoice implements IExportableTransaction {
|
||||
protected String vatDueDateTypeCode = null;
|
||||
protected String creditorReferenceID; // required when direct debit is used.
|
||||
private BigDecimal roundingAmount=null;
|
||||
private String paymentReference; // Remittance information / Verwendungszweck, BT-83
|
||||
|
||||
public Invoice() {
|
||||
ZFItems = new ArrayList<>();
|
||||
@@ -124,7 +125,11 @@ public class Invoice implements IExportableTransaction {
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice setAdditionalReferencedDocuments(FileAttachment[] fileArr) {
|
||||
xmlEmbeddedFiles = new ArrayList<>(Arrays.asList(fileArr));
|
||||
if (fileArr!=null) {
|
||||
xmlEmbeddedFiles = new ArrayList<>(Arrays.asList(fileArr));
|
||||
} else {
|
||||
xmlEmbeddedFiles = new ArrayList<>();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -153,7 +158,6 @@ public class Invoice implements IExportableTransaction {
|
||||
*/
|
||||
public Invoice setCorrection(String number) {
|
||||
setInvoiceReferencedDocumentID(number);
|
||||
addInvoiceReferencedDocument(new ReferencedDocument(number));
|
||||
documentCode = DocumentCodeTypeConstants.CORRECTEDINVOICE;
|
||||
return this;
|
||||
}
|
||||
@@ -679,6 +683,15 @@ public class Invoice implements IExportableTransaction {
|
||||
}
|
||||
|
||||
|
||||
public String getPaymentReference() {
|
||||
return paymentReference;
|
||||
}
|
||||
|
||||
public Invoice setPaymentReference(String paymentReference) {
|
||||
this.paymentReference = paymentReference;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeParty getDeliveryAddress() {
|
||||
return deliveryAddress;
|
||||
|
||||
@@ -42,6 +42,7 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
protected ArrayList<IZUGFeRDAllowanceCharge> Allowances = new ArrayList<>();
|
||||
protected ArrayList<IZUGFeRDAllowanceCharge> Charges = new ArrayList<>();
|
||||
protected List<IncludedNote> includedNotes = null;
|
||||
protected String accountingReference;
|
||||
//protected HashMap<String, String> attributes = new HashMap<>();
|
||||
|
||||
/***
|
||||
@@ -172,7 +173,10 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
icnm.getAsNodeMap("ApplicableTradeTax")
|
||||
.flatMap(cnm -> cnm.getAsBigDecimal("RateApplicablePercent", "ApplicablePercent"))
|
||||
.ifPresent(product::setVATPercent);
|
||||
icnm.getAsNodeMap("SpecifiedTradeAllowanceCharge").ifPresent(stac -> {
|
||||
icnm.getAsNodeMap("ApplicableTradeTax")
|
||||
.flatMap(cnm -> cnm.getAsString("ExemptionReason"))
|
||||
.ifPresent(product::setTaxExemptionReason);
|
||||
icnm.getAllNodes("SpecifiedTradeAllowanceCharge").map(NodeMap::new).forEach(stac -> {
|
||||
stac.getAsNodeMap("ChargeIndicator").ifPresent(ci -> {
|
||||
String isChargeString=ci.getAsString("Indicator").get();
|
||||
String percentString=stac.getAsStringOrNull("CalculationPercent");
|
||||
@@ -187,8 +191,12 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
if (amountString!=null) {
|
||||
izac.setTotalAmount(new BigDecimal(amountString));
|
||||
}
|
||||
if(percentString!=null) {
|
||||
izac.setPercent(new BigDecimal(percentString));
|
||||
}
|
||||
if(reason!=null) {
|
||||
izac.setReason(reason);
|
||||
}
|
||||
|
||||
if (isChargeString.equalsIgnoreCase("false")) {
|
||||
addAllowance(izac);
|
||||
@@ -206,6 +214,14 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
}
|
||||
|
||||
icnm.getAllNodes("AdditionalReferencedDocument").map(ReferencedDocument::fromNode).forEach(this::addAdditionalReference);
|
||||
|
||||
icnm.getAsString("ReceivableSpecifiedTradeAccountingAccount").ifPresent(s -> this.accountingReference = s == null ? null : s.trim());
|
||||
|
||||
icnm.getAsNodeMap("BillingSpecifiedPeriod").ifPresent(periodNode -> {
|
||||
Date start = periodNode.getAsNodeMap("StartDateTime").flatMap(dateTimeNode -> dateTimeNode.getNode("DateTimeString")).map(dts -> XMLTools.tryDate(dts)).orElse(null);
|
||||
Date end = periodNode.getAsNodeMap("EndDateTime").flatMap(dateTimeNode -> dateTimeNode.getNode("DateTimeString")).map(dts -> XMLTools.tryDate(dts)).orElse(null);
|
||||
setDetailedDeliveryPeriod(start, end);
|
||||
});
|
||||
});
|
||||
|
||||
itemMap.getAsNodeMap("AssociatedDocumentLineDocument").ifPresent(adld -> {
|
||||
@@ -353,6 +369,29 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
return Allowances.toArray(new IZUGFeRDAllowanceCharge[0]);
|
||||
}
|
||||
|
||||
/***
|
||||
* jackson convenience method
|
||||
*/
|
||||
public void setItemAllowances(ArrayList<Allowance> theAllowances) {
|
||||
if (theAllowances!=null) {
|
||||
Allowances.clear();
|
||||
for (Allowance theAllowance : theAllowances) {
|
||||
Allowances.add(theAllowance);
|
||||
}
|
||||
}
|
||||
}
|
||||
/***
|
||||
* jackson convenience method
|
||||
*/
|
||||
public void setItemCharges(ArrayList<Charge> theCharges) {
|
||||
if (theCharges!=null) {
|
||||
Charges.clear();
|
||||
for (Charge theCharge : theCharges) {
|
||||
Charges.add(theCharge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IZUGFeRDAllowanceCharge[] getItemCharges() {
|
||||
if (Charges.isEmpty()) {
|
||||
@@ -525,4 +564,9 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
public List<IncludedNote> getNotesWithSubjectCode() {
|
||||
return includedNotes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccountingReference() {
|
||||
return accountingReference;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,10 @@ public class LegalOrganisation implements IZUGFeRDLegalOrganisation {
|
||||
this.schemedID = new SchemedID(scheme, ID);
|
||||
}
|
||||
|
||||
public LegalOrganisation(String ID) {
|
||||
this.schemedID = new SchemedID(null, ID);
|
||||
}
|
||||
|
||||
public LegalOrganisation(SchemedID schemedID, String tradingBusinessName) {
|
||||
this.schemedID = schemedID;
|
||||
this.tradingBusinessName=tradingBusinessName;
|
||||
|
||||
@@ -69,7 +69,7 @@ public class Product implements IZUGFeRDExportableProduct {
|
||||
nodeMap.getAsString("Description").ifPresent(this::setDescription);
|
||||
|
||||
|
||||
nodeMap.getAsNodeMap("ApplicableProductCharacteristic").ifPresent(apcNodes -> {
|
||||
nodeMap.getAllNodes("ApplicableProductCharacteristic").map(NodeMap::new).forEach(apcNodes -> { // ApplicableProductCharacteristic is 0 .. unbounded
|
||||
String key = apcNodes.getAsStringOrNull("Description");
|
||||
String value = apcNodes.getAsStringOrNull("Value");
|
||||
if (key != null && value != null) {
|
||||
@@ -80,7 +80,6 @@ public class Product implements IZUGFeRDExportableProduct {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//UBL
|
||||
nodeMap.getAsNodeMap("AdditionalItemProperty").ifPresent(aipNodes -> {
|
||||
String name = aipNodes.getAsStringOrNull("Name");
|
||||
|
||||
@@ -129,7 +129,16 @@ public class XMLTools extends XMLWriter {
|
||||
* @return a util.Date, or null, if not parseable
|
||||
*/
|
||||
public static Date tryDate(String toParse) {
|
||||
final SimpleDateFormat formatter = ZUGFeRDDateFormat.DATE.getFormatter();
|
||||
SimpleDateFormat formatter = null;
|
||||
if (toParse==null) {
|
||||
return null;
|
||||
}
|
||||
if (toParse.contains("-")) {
|
||||
// from ubl
|
||||
formatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||
} else {
|
||||
formatter = ZUGFeRDDateFormat.DATE.getFormatter();
|
||||
}
|
||||
try {
|
||||
return formatter.parse(toParse);
|
||||
} catch (final Exception e) {
|
||||
@@ -211,7 +220,8 @@ public class XMLTools extends XMLWriter {
|
||||
}
|
||||
|
||||
public static byte[] getBytesFromStream(InputStream fileinput) throws IOException {
|
||||
return IOUtils.toByteArray (fileinput);
|
||||
// Stream closing responsibility is with the caller
|
||||
return IOUtils.toByteArray(fileinput);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -313,6 +313,10 @@ public interface IExportableTransaction {
|
||||
return null;
|
||||
}
|
||||
|
||||
default String getPaymentReference() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get payment terms for the EXTENDED profile (multiple terms are allowed)
|
||||
* @return
|
||||
|
||||
@@ -172,4 +172,8 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
|
||||
default List<IncludedNote> getNotesWithSubjectCode() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default String getAccountingReference() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.util.Map;
|
||||
|
||||
import org.mustangproject.EStandard;
|
||||
import org.mustangproject.FileAttachment;
|
||||
import org.mustangproject.ReferencedDocument;
|
||||
import org.mustangproject.XMLTools;
|
||||
|
||||
public class OXPullProvider extends ZUGFeRD2PullProvider {
|
||||
@@ -460,7 +461,7 @@ public class OXPullProvider extends ZUGFeRD2PullProvider {
|
||||
xml += "</ram:InvoiceReferencedDocument>";
|
||||
}
|
||||
if (trans.getInvoiceReferencedDocuments() != null) {
|
||||
for (var doc : trans.getInvoiceReferencedDocuments()) {
|
||||
for (ReferencedDocument doc : trans.getInvoiceReferencedDocuments()) {
|
||||
xml += "<ram:InvoiceReferencedDocument>"
|
||||
+ "<ram:IssuerAssignedID>"
|
||||
+ XMLTools.encodeXML(doc.getIssuerAssignedID()) + "</ram:IssuerAssignedID>";
|
||||
|
||||
@@ -13,14 +13,14 @@ import org.apache.pdfbox.preflight.parser.PreflightParser;
|
||||
|
||||
import jakarta.activation.DataSource;
|
||||
|
||||
// Copied from PDFBox preflight 2.0.x
|
||||
// Copied from PDFBox preflight 2.0.x
|
||||
final class ByteArrayDataSource implements DataSource
|
||||
{
|
||||
private ByteArrayOutputStream data;
|
||||
private String type = null;
|
||||
private String name = null;
|
||||
|
||||
public ByteArrayDataSource (InputStream is) throws IOException
|
||||
public ByteArrayDataSource (final InputStream is) throws IOException
|
||||
{
|
||||
data = new ByteArrayOutputStream ();
|
||||
IOUtils.copy (is, data);
|
||||
@@ -36,7 +36,7 @@ final class ByteArrayDataSource implements DataSource
|
||||
* @param type
|
||||
* the type to set
|
||||
*/
|
||||
public void setType (String type)
|
||||
public void setType (final String type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
@@ -45,7 +45,7 @@ final class ByteArrayDataSource implements DataSource
|
||||
* @param name
|
||||
* the name to set
|
||||
*/
|
||||
public void setName (String name)
|
||||
public void setName (final String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
@@ -70,12 +70,13 @@ final class ByteArrayDataSource implements DataSource
|
||||
// Try to create an API similar to the 2.x one
|
||||
final class PreflightParserHelper
|
||||
{
|
||||
private static File createTmpFile (InputStream input) throws IOException
|
||||
private static File createTmpFile (final InputStream input) throws IOException
|
||||
{
|
||||
FileOutputStream fos = null;
|
||||
try
|
||||
{
|
||||
File tmpFile = File.createTempFile ("mustang-pdf", ".pdf");
|
||||
final File tmpFile = File.createTempFile ("mustang-pdf", ".pdf");
|
||||
tmpFile.deleteOnExit ();
|
||||
fos = new FileOutputStream (tmpFile);
|
||||
IOUtils.copy (input, fos);
|
||||
return tmpFile;
|
||||
@@ -87,7 +88,7 @@ final class PreflightParserHelper
|
||||
}
|
||||
}
|
||||
|
||||
public static PreflightParser createPreflightParser (DataSource dataSource) throws IOException
|
||||
public static PreflightParser createPreflightParser (final DataSource dataSource) throws IOException
|
||||
{
|
||||
return new PreflightParser (createTmpFile (dataSource.getInputStream ()));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.StringReader;
|
||||
import org.apache.fop.apps.*;
|
||||
import org.apache.fop.apps.io.ResourceResolverFactory;
|
||||
import org.apache.fop.configuration.Configuration;
|
||||
@@ -10,11 +18,12 @@ import org.mustangproject.ClasspathResolverURIAdapter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.*;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class ValidationLogVisualizer {
|
||||
@@ -70,7 +79,7 @@ public class ValidationLogVisualizer {
|
||||
return baos.toString(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public void toPDF(String xmlLogfileContent, String pdfFilename) {
|
||||
public byte[] createPDFBytes(String xmlLogfileContent) {
|
||||
|
||||
// the writing part
|
||||
|
||||
@@ -111,13 +120,19 @@ public class ValidationLogVisualizer {
|
||||
// Step 2: Set up output stream.
|
||||
// Note: Using BufferedOutputStream for performance reasons (helpful with FileOutputStreams).
|
||||
|
||||
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(pdfFilename))) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (OutputStream out = new BufferedOutputStream(baos)) {
|
||||
|
||||
// Step 3: Construct fop with desired output format
|
||||
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent, out);
|
||||
|
||||
// Step 4: Setup JAXP using identity transformer
|
||||
TransformerFactory factory = TransformerFactory.newInstance();
|
||||
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
Transformer transformer = factory.newTransformer(); // identity transformer
|
||||
|
||||
// Step 5: Setup input and output for XSLT transformation
|
||||
@@ -133,6 +148,20 @@ public class ValidationLogVisualizer {
|
||||
} catch (FOPException | IOException | TransformerException e) {
|
||||
LOGGER.error("Failed to create PDF", e);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public byte[] toPDF(String xmlLogfileContent) {
|
||||
return createPDFBytes(xmlLogfileContent);
|
||||
}
|
||||
|
||||
public void toPDF(String xmlLogfileContent, String pdfFilename) {
|
||||
byte[] pdfData = createPDFBytes(xmlLogfileContent);
|
||||
try (FileOutputStream fos = new FileOutputStream(pdfFilename)) {
|
||||
fos.write(pdfData);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Failed to write PDF to file", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClasspathResourceURIResolver implements URIResolver {
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.mustangproject.FileAttachment;
|
||||
import org.mustangproject.IncludedNote;
|
||||
import org.mustangproject.ReferencedDocument;
|
||||
import org.mustangproject.XMLTools;
|
||||
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
|
||||
import org.slf4j.Logger;
|
||||
@@ -139,7 +140,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
xml += "<ram:GlobalID schemeID=\"" + XMLTools.encodeXML(party.getGlobalIDScheme()) + "\">"
|
||||
+ XMLTools.encodeXML(party.getGlobalID()) + "</ram:GlobalID>";
|
||||
}
|
||||
xml += "<ram:Name>" + XMLTools.encodeXML(party.getName()) + "</ram:Name>";
|
||||
if (party.getName() != null && !party.getName().isEmpty()) {
|
||||
xml += "<ram:Name>" + XMLTools.encodeXML(party.getName()) + "</ram:Name>";
|
||||
}
|
||||
if (party.getDescription() != null) {
|
||||
xml += "<ram:Description>" + XMLTools.encodeXML(party.getDescription()) + "</ram:Description>";
|
||||
}
|
||||
@@ -149,7 +152,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
if (profile == Profiles.getByName("Minimum")) {
|
||||
xml += "<ram:ID>" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getID()) + "</ram:ID>";
|
||||
} else {
|
||||
xml += "<ram:ID schemeID=\"" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getScheme()) + "\">" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getID()) + "</ram:ID>";
|
||||
String schemeAttribute="";
|
||||
if ((party.getLegalOrganisation().getSchemedID().getScheme()!=null)&&(party.getLegalOrganisation().getSchemedID().getScheme().length()>0)) {
|
||||
schemeAttribute="schemeID=\"" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getScheme())+"\"";
|
||||
|
||||
}
|
||||
xml += "<ram:ID "+schemeAttribute+">" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getID()) + "</ram:ID>";
|
||||
}
|
||||
}
|
||||
if (party.getLegalOrganisation().getTradingBusinessName() != null) {
|
||||
@@ -277,7 +285,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
}
|
||||
|
||||
String reason = "";
|
||||
if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended") || profile == Profiles.getByName("XRechnung")) || profile == Profiles.getByName("EN16931")) {
|
||||
if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended") || profile == Profiles.getByName("XRechnung") || profile == Profiles.getByName("EN16931"))) {
|
||||
reason = "<ram:Reason>" + XMLTools.encodeXML(allowance.getReason()) + "</ram:Reason>";
|
||||
}
|
||||
String reasonCode = "";
|
||||
@@ -337,8 +345,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
boolean hasDueDate = trans.getDueDate() != null;
|
||||
final SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy");
|
||||
|
||||
String exemptionReason = "";
|
||||
|
||||
if (trans.getPaymentTermDescription() != null) {
|
||||
paymentTermsDescription = XMLTools.encodeXML(trans.getPaymentTermDescription());
|
||||
}
|
||||
@@ -388,14 +394,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
+ "</ram:GuidelineSpecifiedDocumentContextParameter>"
|
||||
+ "</rsm:ExchangedDocumentContext>"
|
||||
+ "<rsm:ExchangedDocument>"
|
||||
+ "<ram:ID>" + XMLTools.encodeXML(trans.getNumber()) + "</ram:ID>"
|
||||
// + "<ram:Name>RECHNUNG</ram:Name>"
|
||||
// + "<ram:TypeCode>380</ram:TypeCode>"
|
||||
+ "<ram:TypeCode>" + typecode + "</ram:TypeCode>"
|
||||
+ "<ram:IssueDateTime>"
|
||||
+ DATE.udtFormat(trans.getIssueDate()) + "</ram:IssueDateTime>" // date
|
||||
+ "<ram:ID>" + XMLTools.encodeXML(trans.getNumber()) + "</ram:ID>";
|
||||
if (profile == Profiles.getByName("Extended") && trans.getDocumentName() != null) {
|
||||
xml += "<ram:Name>" + XMLTools.encodeXML(trans.getDocumentName()) + "</ram:Name>";
|
||||
}
|
||||
xml += "<ram:TypeCode>" + typecode + "</ram:TypeCode>"
|
||||
+ "<ram:IssueDateTime>" + DATE.udtFormat(trans.getIssueDate()) + "</ram:IssueDateTime>" // date
|
||||
+ buildNotes(trans)
|
||||
|
||||
+ "</rsm:ExchangedDocument>"
|
||||
+ "<rsm:SupplyChainTradeTransaction>";
|
||||
int lineID = 0;
|
||||
@@ -405,9 +410,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
if (currentItem.getId()!=null) {
|
||||
lineIDStr=currentItem.getId();
|
||||
}
|
||||
if (currentItem.getProduct().getTaxExemptionReason() != null) {
|
||||
exemptionReason = "<ram:ExemptionReason>" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + "</ram:ExemptionReason>";
|
||||
}
|
||||
final LineCalculator lc = new LineCalculator(currentItem);
|
||||
if ((getProfile() != Profiles.getByName("Minimum")) && (getProfile() != Profiles.getByName("BasicWL"))) {
|
||||
xml += "<ram:IncludedSupplyChainTradeLineItem>" +
|
||||
@@ -450,7 +452,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
}
|
||||
|
||||
xml += "<ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>";
|
||||
if (currentItem.getProduct().getDescription().length() > 0) {
|
||||
if (currentItem.getProduct().getDescription() != null && currentItem.getProduct().getDescription().length() > 0) {
|
||||
xml += "<ram:Description>" +
|
||||
XMLTools.encodeXML(currentItem.getProduct().getDescription()) +
|
||||
"</ram:Description>";
|
||||
@@ -458,7 +460,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
if (currentItem.getProduct().getClassifications() != null && currentItem.getProduct().getClassifications().length > 0) {
|
||||
for (IDesignatedProductClassification classification : currentItem.getProduct().getClassifications()) {
|
||||
xml += "<ram:DesignatedProductClassification>"
|
||||
+ "<ram:ClassCode listId=\"" + XMLTools.encodeXML(classification.getClassCode().getListID()) + "\"";
|
||||
+ "<ram:ClassCode listID=\"" + XMLTools.encodeXML(classification.getClassCode().getListID()) + "\"";
|
||||
if (classification.getClassCode().getListVersionID() != null) {
|
||||
xml += " listVersionID=\"" + XMLTools.encodeXML(classification.getClassCode().getListVersionID()) + "\"";
|
||||
}
|
||||
@@ -528,9 +530,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
+ "</ram:SpecifiedLineTradeDelivery>"
|
||||
+ "<ram:SpecifiedLineTradeSettlement>"
|
||||
+ "<ram:ApplicableTradeTax>"
|
||||
+ "<ram:TypeCode>VAT</ram:TypeCode>"
|
||||
+ exemptionReason
|
||||
+ "<ram:CategoryCode>" + currentItem.getProduct().getTaxCategoryCode() + "</ram:CategoryCode>"
|
||||
+ "<ram:TypeCode>VAT</ram:TypeCode>";
|
||||
|
||||
if (currentItem.getProduct().getTaxExemptionReason() != null) {
|
||||
xml += "<ram:ExemptionReason>" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + "</ram:ExemptionReason>";
|
||||
}
|
||||
|
||||
xml += "<ram:CategoryCode>" + currentItem.getProduct().getTaxCategoryCode() + "</ram:CategoryCode>"
|
||||
+ "<ram:RateApplicablePercent>"
|
||||
+ vatFormat(currentItem.getProduct().getVATPercent()) + "</ram:RateApplicablePercent>"
|
||||
+ "</ram:ApplicableTradeTax>";
|
||||
@@ -662,8 +668,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
if ((trans.getCreditorReferenceID() != null) && (getProfile() != Profiles.getByName("Minimum"))) {
|
||||
xml += "<ram:CreditorReferenceID>" + XMLTools.encodeXML(trans.getCreditorReferenceID()) + "</ram:CreditorReferenceID>";
|
||||
}
|
||||
if ((trans.getNumber() != null) && (getProfile() != Profiles.getByName("Minimum"))) {
|
||||
xml += "<ram:PaymentReference>" + XMLTools.encodeXML(trans.getNumber()) + "</ram:PaymentReference>";
|
||||
if ((trans.getPaymentReference() != null) && (getProfile() != Profiles.getByName("Minimum"))) {
|
||||
xml += "<ram:PaymentReference>" + XMLTools.encodeXML(trans.getPaymentReference()) + "</ram:PaymentReference>";
|
||||
}
|
||||
xml += "<ram:InvoiceCurrencyCode>" + trans.getCurrency() + "</ram:InvoiceCurrencyCode>";
|
||||
if (this.trans.getPayee() != null) {
|
||||
@@ -894,7 +900,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
xml += "</ram:InvoiceReferencedDocument>";
|
||||
}
|
||||
if (trans.getInvoiceReferencedDocuments() != null) {
|
||||
for (var doc : trans.getInvoiceReferencedDocuments()) {
|
||||
for (ReferencedDocument doc : trans.getInvoiceReferencedDocuments()) {
|
||||
xml += "<ram:InvoiceReferencedDocument>"
|
||||
+ "<ram:IssuerAssignedID>"
|
||||
+ XMLTools.encodeXML(doc.getIssuerAssignedID()) + "</ram:IssuerAssignedID>";
|
||||
|
||||
@@ -58,6 +58,7 @@ import org.apache.pdfbox.pdmodel.font.PDCIDFontType2;
|
||||
import org.apache.pdfbox.pdmodel.font.PDFont;
|
||||
import org.apache.pdfbox.pdmodel.font.PDFontDescriptor;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType0Font;
|
||||
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
|
||||
import org.apache.pdfbox.pdmodel.graphics.color.PDOutputIntent;
|
||||
import org.apache.xmpbox.XMPMetadata;
|
||||
import org.apache.xmpbox.schema.AdobePDFSchema;
|
||||
@@ -559,6 +560,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
// https://github.com/ZUGFeRD/mustangproject/issues/249
|
||||
|
||||
COSName cidSet = COSName.getPDFName("CIDSet");
|
||||
COSName resources = COSName.getPDFName("Resources");
|
||||
|
||||
// iterate over all pdf pages
|
||||
|
||||
@@ -567,29 +569,45 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
|
||||
PDPage page = (PDPage) object;
|
||||
PDResources res = page.getResources();
|
||||
for (COSName fontName : res.getFontNames()) {
|
||||
try {
|
||||
PDFont pdFont = res.getFont(fontName);
|
||||
if (pdFont instanceof PDType0Font) {
|
||||
PDType0Font typedFont = (PDType0Font) pdFont;
|
||||
|
||||
if (typedFont.getDescendantFont() instanceof PDCIDFontType2) {
|
||||
@SuppressWarnings("unused")
|
||||
PDCIDFontType2 f = (PDCIDFontType2) typedFont.getDescendantFont();
|
||||
PDFontDescriptor fontDescriptor = pdFont.getFontDescriptor();
|
||||
|
||||
fontDescriptor.getCOSObject().removeItem(cidSet);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
// Check for fonts in PDXObjects:
|
||||
for (COSName xObjectName : res.getXObjectNames()) {
|
||||
PDXObject xObject = res.getXObject(xObjectName);
|
||||
COSDictionary d = xObject.getCOSObject().getCOSDictionary(resources);
|
||||
if (d != null) {
|
||||
PDResources xr = new PDResources(d);
|
||||
removeCIDSetFromPDResources(cidSet, xr);
|
||||
}
|
||||
// do stuff with the font
|
||||
}
|
||||
|
||||
// Check for fonts in document-resources:
|
||||
removeCIDSetFromPDResources(cidSet, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeCIDSetFromPDResources(COSName cidSet, PDResources res) throws IOException {
|
||||
for (COSName fontName : res.getFontNames()) {
|
||||
try {
|
||||
PDFont pdFont = res.getFont(fontName);
|
||||
if (pdFont instanceof PDType0Font) {
|
||||
PDType0Font typedFont = (PDType0Font) pdFont;
|
||||
|
||||
if (typedFont.getDescendantFont() instanceof PDCIDFontType2) {
|
||||
@SuppressWarnings("unused")
|
||||
PDCIDFontType2 f = (PDCIDFontType2) typedFont.getDescendantFont();
|
||||
PDFontDescriptor fontDescriptor = pdFont.getFontDescriptor();
|
||||
|
||||
fontDescriptor.getCOSObject().removeItem(cidSet);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
}
|
||||
// do stuff with the font
|
||||
}
|
||||
}
|
||||
|
||||
protected void prepareDocument() throws IOException {
|
||||
|
||||
PDDocumentCatalog cat = doc.getDocumentCatalog();
|
||||
|
||||
@@ -90,9 +90,10 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter {
|
||||
|
||||
protected byte[] inputstreamToByteArray(InputStream fileInputStream) throws IOException {
|
||||
byte[] bytes = new byte[fileInputStream.available()];
|
||||
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
|
||||
dataInputStream.readFully(bytes);
|
||||
return bytes;
|
||||
try (DataInputStream dataInputStream = new DataInputStream(fileInputStream)) {
|
||||
dataInputStream.readFully(bytes);
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
|
||||
@@ -86,6 +86,7 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter {
|
||||
case "urn:factur-x.eu:1p0:minimum":
|
||||
return "MINIMUM";
|
||||
case "urn:ferd:CrossIndustryDocument:invoice:1p0:extended":
|
||||
case "urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended":
|
||||
case "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended":
|
||||
return "EXTENDED";
|
||||
default:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
@@ -137,9 +138,9 @@ public class ZUGFeRDInvoiceImporter {
|
||||
return;
|
||||
}
|
||||
|
||||
final InputStream XMP = doc.getDocumentCatalog().getMetadata().exportXMPMetadata();
|
||||
|
||||
xmpString = new String(XMLTools.getBytesFromStream(XMP), StandardCharsets.UTF_8);
|
||||
try (final InputStream XMP = doc.getDocumentCatalog().getMetadata().exportXMPMetadata()) {
|
||||
xmpString = new String(XMLTools.getBytesFromStream(XMP), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
final PDEmbeddedFilesNameTreeNode etn = names.getEmbeddedFiles();
|
||||
if (etn == null) {
|
||||
@@ -258,9 +259,25 @@ public class ZUGFeRDInvoiceImporter {
|
||||
}
|
||||
|
||||
private void setDocument() throws ParserConfigurationException, IOException, SAXException, ParseException {
|
||||
final DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance();
|
||||
xmlFact.setNamespaceAware(true);
|
||||
final DocumentBuilder builder = xmlFact.newDocumentBuilder();
|
||||
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
//REDHAT
|
||||
//https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf
|
||||
dbf.setAttribute(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
||||
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
|
||||
|
||||
//OWASP
|
||||
//https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
|
||||
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
// Disable external DTDs as well
|
||||
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
// and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
|
||||
dbf.setXIncludeAware(false);
|
||||
dbf.setExpandEntityReferences(false);
|
||||
dbf.setNamespaceAware(true);
|
||||
final DocumentBuilder builder = dbf.newDocumentBuilder();
|
||||
final ByteArrayInputStream is = new ByteArrayInputStream(rawXML);
|
||||
/// is.skip(guessBOMSize(is));
|
||||
document = builder.parse(is);
|
||||
@@ -288,6 +305,7 @@ public class ZUGFeRDInvoiceImporter {
|
||||
public Invoice extractInto(Invoice zpp) throws XPathExpressionException, ParseException {
|
||||
|
||||
String number = "";
|
||||
String documentName = null;
|
||||
String typeCode = null;
|
||||
String deliveryPeriodStart = null;
|
||||
String deliveryPeriodEnd = null;
|
||||
@@ -496,6 +514,9 @@ public class ZUGFeRDInvoiceImporter {
|
||||
if ((item.getLocalName() != null) && (item.getLocalName().equals("ID"))) {
|
||||
number = XMLTools.trimOrNull(item);
|
||||
}
|
||||
if ((item.getLocalName() != null) && (item.getLocalName().equals("Name"))) {
|
||||
documentName = XMLTools.trimOrNull(item);
|
||||
}
|
||||
if ((item.getLocalName() != null) && (item.getLocalName().equals("TypeCode"))) {
|
||||
typeCode = XMLTools.trimOrNull(item);
|
||||
}
|
||||
@@ -556,13 +577,13 @@ public class ZUGFeRDInvoiceImporter {
|
||||
}
|
||||
zpp.addNotes(includedNotes);
|
||||
String rootNode = extractString("local-name(/*)");
|
||||
if (rootNode.equals("Invoice")||rootNode.equals("CreditNote")) {
|
||||
if (rootNode.equals("Invoice") || rootNode.equals("CreditNote")) {
|
||||
// UBL...
|
||||
// //*[local-name()="Invoice" or local-name()="CreditNote"]
|
||||
number = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"ID\"]").trim();
|
||||
typeCode = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"InvoiceTypeCode\"]").trim();
|
||||
String issueDateStr = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"IssueDate\"]").trim();
|
||||
if (issueDateStr.length()>0) {
|
||||
if (issueDateStr.length() > 0) {
|
||||
issueDate = new SimpleDateFormat("yyyy-MM-dd").parse(issueDateStr);
|
||||
}
|
||||
String dueDt = extractString("/*[local-name()=\"Invoice\" or local-name()=\"CreditNote\"]/*[local-name()=\"DueDate\"]").trim();
|
||||
@@ -651,7 +672,7 @@ public class ZUGFeRDInvoiceImporter {
|
||||
zpp.setCurrency(currency);
|
||||
|
||||
String paymentTermsDescription = extractString("//*[local-name()=\"SpecifiedTradePaymentTerms\"]/*[local-name()=\"Description\"]|//*[local-name()=\"PaymentTerms\"]/*[local-name()=\"Note\"]");
|
||||
if ((paymentTermsDescription!=null)&&(!paymentTermsDescription.isEmpty())) {
|
||||
if ((paymentTermsDescription != null) && (!paymentTermsDescription.isEmpty())) {
|
||||
zpp.setPaymentTermDescription(paymentTermsDescription);
|
||||
}
|
||||
|
||||
@@ -661,6 +682,7 @@ public class ZUGFeRDInvoiceImporter {
|
||||
List<BankDetails> bankDetails = new ArrayList<>();
|
||||
String directDebitMandateID = null;
|
||||
String IBAN = null, BIC = null, paymentMeansCode = null, paymentMeansInformation = null;
|
||||
String accountName = null;
|
||||
|
||||
for (int i = 0; i < headerTradeSettlementNodes.getLength(); i++) {
|
||||
// XMLTools.trimOrNull(nodes.item(i)))) {
|
||||
@@ -668,6 +690,12 @@ public class ZUGFeRDInvoiceImporter {
|
||||
|
||||
NodeList headerTradeSettlementChilds = headerTradeSettlementNode.getChildNodes();
|
||||
for (int settlementChildIndex = 0; settlementChildIndex < headerTradeSettlementChilds.getLength(); settlementChildIndex++) {
|
||||
if ((headerTradeSettlementChilds.item(settlementChildIndex).getLocalName() != null)
|
||||
&& (headerTradeSettlementChilds.item(settlementChildIndex).getLocalName().equals("PaymentReference"))) {
|
||||
String paymentReference = headerTradeSettlementChilds.item(settlementChildIndex).getTextContent();
|
||||
zpp.setPaymentReference(paymentReference);
|
||||
}
|
||||
|
||||
if ((headerTradeSettlementChilds.item(settlementChildIndex).getLocalName() != null)
|
||||
&& (headerTradeSettlementChilds.item(settlementChildIndex).getLocalName().equals("SpecifiedTradePaymentTerms"))) {
|
||||
NodeList paymentTermChilds = headerTradeSettlementChilds.item(settlementChildIndex).getChildNodes();
|
||||
@@ -712,6 +740,9 @@ public class ZUGFeRDInvoiceImporter {
|
||||
if ((accountChilds.item(accountChildIndex).getLocalName() != null) && (accountChilds.item(accountChildIndex).getLocalName().equals("IBANID"))) {//CII
|
||||
IBAN = XMLTools.trimOrNull(accountChilds.item(accountChildIndex));
|
||||
}
|
||||
if ((accountChilds.item(accountChildIndex).getLocalName() != null) && (accountChilds.item(accountChildIndex).getLocalName().equals("AccountName"))) {//CII
|
||||
accountName = XMLTools.trimOrNull(accountChilds.item(accountChildIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((paymentMeansChilds.item(paymentMeansChildIndex).getLocalName() != null) && (paymentMeansChilds.item(paymentMeansChildIndex).getLocalName().equals("PayeeSpecifiedCreditorFinancialInstitution"))) {
|
||||
@@ -729,6 +760,9 @@ public class ZUGFeRDInvoiceImporter {
|
||||
if (BIC != null) {
|
||||
bd.setBIC(BIC);
|
||||
}
|
||||
if (accountName!=null) {
|
||||
bd.setAccountName(accountName);
|
||||
}
|
||||
bankDetails.add(bd);
|
||||
}
|
||||
}
|
||||
@@ -758,6 +792,21 @@ public class ZUGFeRDInvoiceImporter {
|
||||
}
|
||||
}
|
||||
|
||||
xpr = xpath.compile("/*[local-name()=\"Invoice\"]/*[local-name()=\"InvoicePeriod\"]/*"); //UBL only
|
||||
NodeList periodNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
|
||||
for (int periodChildIndex = 0; periodChildIndex < periodNodes.getLength(); periodChildIndex++) {
|
||||
String localName=periodNodes.item(periodChildIndex).getLocalName();
|
||||
if ((localName != null) && (periodNodes.item(periodChildIndex).getLocalName().equals("StartDate"))) {
|
||||
deliveryPeriodStart = XMLTools.trimOrNull(periodNodes.item(periodChildIndex));
|
||||
}
|
||||
if ((localName != null) && (periodNodes.item(periodChildIndex).getLocalName().equals("EndDate"))) {
|
||||
deliveryPeriodEnd = XMLTools.trimOrNull(periodNodes.item(periodChildIndex));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ((deliveryPeriodStart != null) && (deliveryPeriodEnd != null)) {
|
||||
zpp.setDetailedDeliveryPeriod(XMLTools.tryDate(deliveryPeriodStart), XMLTools.tryDate(deliveryPeriodEnd));
|
||||
} else if (deliveryPeriodStart != null) {
|
||||
@@ -776,12 +825,12 @@ public class ZUGFeRDInvoiceImporter {
|
||||
&& (paymentMeansChilds.item(meansChildIndex).getLocalName().equals("PayeeFinancialAccount"))) {
|
||||
NodeList paymentTermChilds = paymentMeansChilds.item(meansChildIndex).getChildNodes();
|
||||
for (int paymentTermChildIndex = 0; paymentTermChildIndex < paymentTermChilds.getLength(); paymentTermChildIndex++) {
|
||||
|
||||
if ((paymentTermChilds.item(paymentTermChildIndex).getLocalName() != null) && (paymentTermChilds.item(paymentTermChildIndex).getLocalName().equals("Name"))) {
|
||||
accountName = XMLTools.trimOrNull(paymentTermChilds.item(paymentTermChildIndex));
|
||||
}
|
||||
if ((paymentTermChilds.item(paymentTermChildIndex).getLocalName() != null) && (paymentTermChilds.item(paymentTermChildIndex).getLocalName().equals("ID"))) {
|
||||
IBAN = XMLTools.trimOrNull(paymentTermChilds.item(paymentTermChildIndex));
|
||||
if (IBAN != null) {
|
||||
BankDetails bd = new BankDetails(IBAN);
|
||||
bankDetails.add(bd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -799,10 +848,18 @@ public class ZUGFeRDInvoiceImporter {
|
||||
|
||||
}
|
||||
}
|
||||
if (IBAN != null) {
|
||||
BankDetails bd = new BankDetails(IBAN);
|
||||
if (accountName!=null) {
|
||||
bd.setAccountName(accountName);
|
||||
}
|
||||
bankDetails.add(bd);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
zpp.setIssueDate(issueDate).setDueDate(dueDate).setDeliveryDate(deliveryDate).setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number).setDocumentCode(typeCode);
|
||||
zpp.setIssueDate(issueDate).setDueDate(dueDate).setDeliveryDate(deliveryDate).setSender(new TradeParty(SellerNodes)).setRecipient(new TradeParty(BuyerNodes)).setNumber(number).setDocumentName(documentName).setDocumentCode(typeCode);
|
||||
|
||||
if ((directDebitMandateID != null) && (IBAN != null)) {
|
||||
DirectDebit d = new DirectDebit(IBAN, directDebitMandateID);
|
||||
@@ -848,15 +905,14 @@ public class ZUGFeRDInvoiceImporter {
|
||||
|
||||
Node currentItemNode = nodes.item(i);
|
||||
ReferencedDocument doc = ReferencedDocument.fromNode(currentItemNode);
|
||||
if (doc != null
|
||||
&& (!Objects.equals(zpp.getInvoiceReferencedDocumentID(), doc.getIssuerAssignedID())
|
||||
|| !Objects.equals(zpp.getInvoiceReferencedIssueDate(), doc.getFormattedIssueDateTime())))
|
||||
{
|
||||
if (doc != null
|
||||
&& (!Objects.equals(zpp.getInvoiceReferencedDocumentID(), doc.getIssuerAssignedID())
|
||||
|| !Objects.equals(zpp.getInvoiceReferencedIssueDate(), doc.getFormattedIssueDateTime()))) {
|
||||
zpp.addInvoiceReferencedDocument(doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
zpp.setOwnOrganisationName(extractString("//*[local-name()=\"SellerTradeParty\"]/*[local-name()=\"Name\"]|//*[local-name()=\"AccountingSupplierParty\"]/*[local-name()=\"Party\"]/*[local-name()=\"PartyName\"]").trim());
|
||||
|
||||
String rounding = extractString("//*[local-name()=\"SpecifiedTradeSettlementHeaderMonetarySummation\"]/*[local-name()=\"RoundingAmount\"]|//*[local-name()=\"LegalMonetaryTotal\"]/*[local-name()=\"Party\"]/*[local-name()=\"PayableRoundingAmount\"]");
|
||||
@@ -890,7 +946,7 @@ public class ZUGFeRDInvoiceImporter {
|
||||
xpr = xpath.compile("//*[local-name()=\"AttachmentBinaryObject\"]|//*[local-name()=\"EmbeddedDocumentBinaryObject\"]");
|
||||
NodeList attachmentNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
for (int i = 0; i < attachmentNodes.getLength(); i++) {
|
||||
FileAttachment fa = new FileAttachment(attachmentNodes.item(i).getAttributes().getNamedItem("filename").getNodeValue(), attachmentNodes.item(i).getAttributes().getNamedItem("mimeCode").getNodeValue(), "Data", Base64.getDecoder().decode(XMLTools.trimOrNull(attachmentNodes.item(i))));
|
||||
FileAttachment fa = new FileAttachment(attachmentNodes.item(i).getAttributes().getNamedItem("filename").getNodeValue(), attachmentNodes.item(i).getAttributes().getNamedItem("mimeCode").getNodeValue(), "Data", Base64.getMimeDecoder().decode(XMLTools.trimOrNull(attachmentNodes.item(i))));
|
||||
zpp.embedFileInXML(fa);
|
||||
// filename = "Aufmass.png" mimeCode = "image/png"
|
||||
//EmbeddedDocumentBinaryObject cbc:EmbeddedDocumentBinaryObject mimeCode="image/png" filename="Aufmass.png"
|
||||
@@ -976,6 +1032,38 @@ public class ZUGFeRDInvoiceImporter {
|
||||
}
|
||||
|
||||
}
|
||||
xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]/*[local-name()=\"SpecifiedLogisticsServiceCharge\"]");// UBL unknown
|
||||
chargeNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
for (int i = 0; i < chargeNodes.getLength(); i++) {
|
||||
NodeList chargeNodeChilds = chargeNodes.item(i).getChildNodes();
|
||||
String chargeAmount = null;
|
||||
String taxPercent = null;
|
||||
for (int chargeChildIndex = 0; chargeChildIndex < chargeNodeChilds.getLength(); chargeChildIndex++) {
|
||||
String chargeChildName = chargeNodeChilds.item(chargeChildIndex).getLocalName();
|
||||
if (chargeChildName != null) {
|
||||
if (chargeChildName.equals("AppliedAmount")) {
|
||||
chargeAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
|
||||
} else if (chargeChildName.equals("AppliedTradeTax")) {
|
||||
NodeList taxChilds = chargeNodeChilds.item(chargeChildIndex).getChildNodes();
|
||||
for (int taxChildIndex = 0; taxChildIndex < taxChilds.getLength(); taxChildIndex++) {
|
||||
String taxItemName = taxChilds.item(taxChildIndex).getLocalName();
|
||||
if ((taxItemName != null) && (taxItemName.equals("RateApplicablePercent"))) {
|
||||
taxPercent = XMLTools.trimOrNull(taxChilds.item(taxChildIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//appliedAmount
|
||||
//AppliedTradeTax
|
||||
}
|
||||
if (chargeAmount != null) {
|
||||
Charge c = new Charge(new BigDecimal(chargeAmount));
|
||||
if (taxPercent != null) {
|
||||
c.setTaxPercent(new BigDecimal(taxPercent));
|
||||
}
|
||||
zpp.addCharge(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TransactionCalculator tc = new TransactionCalculator(zpp);
|
||||
@@ -1040,7 +1128,7 @@ public class ZUGFeRDInvoiceImporter {
|
||||
} else if (rootNode.equals("Invoice")) {
|
||||
return EStandard.ubl;
|
||||
} else if (rootNode.equals("CreditNote")) {
|
||||
return EStandard.ubl;
|
||||
return EStandard.ubl_creditnote;
|
||||
} else if (rootNode.equals("CrossIndustryInvoice")) {
|
||||
return EStandard.facturx;
|
||||
} else if (rootNode.equals("SCRDMCCBDACIDAMessageStructure")) {
|
||||
@@ -1085,11 +1173,17 @@ public class ZUGFeRDInvoiceImporter {
|
||||
*
|
||||
* @return the file attachments embedded in XML (using base64) decoded as byte array,
|
||||
* for PDF embedded files in FX use getFileAttachmentsPDF()
|
||||
* may return empty array
|
||||
* @deprecated use invoice.getAdditionalReferencedDocuments
|
||||
*/
|
||||
@Deprecated
|
||||
public List<FileAttachment> getFileAttachmentsXML() {
|
||||
return new ArrayList<>(Arrays.asList(importedInvoice.getAdditionalReferencedDocuments()));
|
||||
if (importedInvoice.getAdditionalReferencedDocuments()!=null) {
|
||||
return new ArrayList<>(Arrays.asList(importedInvoice.getAdditionalReferencedDocuments()));
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/***
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import com.helger.commons.io.stream.StreamHelper;
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.fop.apps.*;
|
||||
import org.apache.fop.apps.io.ResourceResolverFactory;
|
||||
@@ -45,6 +47,9 @@ import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ZUGFeRDVisualizer {
|
||||
|
||||
@@ -87,7 +92,8 @@ public class ZUGFeRDVisualizer {
|
||||
* @param fis inputstream (will be consumed)
|
||||
* @return (facturx = cii)
|
||||
*/
|
||||
private EStandard findOutStandardFromRootNode(InputStream fis) {
|
||||
private EStandard findOutStandardFromRootNode(InputStream fis)
|
||||
throws ParserConfigurationException {
|
||||
|
||||
String zf1Signature = "CrossIndustryDocument";
|
||||
String zf2Signature = "CrossIndustryInvoice";
|
||||
@@ -96,6 +102,22 @@ public class ZUGFeRDVisualizer {
|
||||
String cioSignature = "SCRDMCCBDACIOMessageStructure";
|
||||
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
//REDHAT
|
||||
//https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf
|
||||
dbf.setAttribute(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
||||
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
|
||||
|
||||
//OWASP
|
||||
//https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
|
||||
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
// Disable external DTDs as well
|
||||
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
// and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
|
||||
dbf.setXIncludeAware(false);
|
||||
dbf.setExpandEntityReferences(false);
|
||||
dbf.setNamespaceAware(true);
|
||||
try {
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
@@ -118,12 +140,15 @@ public class ZUGFeRDVisualizer {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String visualize(String xmlFilename, Language lang) throws IOException, TransformerException {
|
||||
FileInputStream fis = new FileInputStream(xmlFilename);
|
||||
return visualize(fis, lang);
|
||||
public String visualize(String xmlFilename, Language lang)
|
||||
throws IOException, TransformerException, ParserConfigurationException {
|
||||
try (FileInputStream fis = new FileInputStream(xmlFilename)) {
|
||||
return visualize(fis, lang);
|
||||
}
|
||||
}
|
||||
|
||||
public String visualize(InputStream inputXml, Language lang) throws IOException, TransformerException {
|
||||
public String visualize(InputStream inputXml, Language lang)
|
||||
throws IOException, TransformerException, ParserConfigurationException {
|
||||
initTemplates(lang);
|
||||
|
||||
String fileContent = new String(IOUtils.toByteArray(inputXml), StandardCharsets.UTF_8);
|
||||
@@ -208,13 +233,15 @@ public class ZUGFeRDVisualizer {
|
||||
}
|
||||
|
||||
protected String toFOP(String xmlFilename)
|
||||
throws IOException, TransformerException {
|
||||
|
||||
FileInputStream fis = new FileInputStream(xmlFilename);
|
||||
EStandard theStandard = findOutStandardFromRootNode(fis);
|
||||
fis = new FileInputStream(xmlFilename);//rewind :-(
|
||||
|
||||
return toFOP(fis, theStandard);
|
||||
throws IOException, TransformerException, ParserConfigurationException {
|
||||
EStandard theStandard;
|
||||
try (FileInputStream fis = new FileInputStream(xmlFilename)) {
|
||||
theStandard = findOutStandardFromRootNode(fis);
|
||||
}
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(xmlFilename)) {
|
||||
return toFOP(fis, theStandard);
|
||||
}
|
||||
}
|
||||
|
||||
protected String toFOP(InputStream is, EStandard theStandard)
|
||||
@@ -254,16 +281,61 @@ public class ZUGFeRDVisualizer {
|
||||
// the writing part
|
||||
File XMLinputFile = new File(xmlFilename);
|
||||
|
||||
String result = null;
|
||||
String fopInput = null;
|
||||
|
||||
/* remove file endings so that tests can also pass after checking
|
||||
out from git with arbitrary options (which may include CSRF changes)
|
||||
*/
|
||||
try {
|
||||
result = this.toFOP(XMLinputFile.getAbsolutePath());
|
||||
} catch (TransformerException | IOException e) {
|
||||
fopInput = this.toFOP(XMLinputFile.getAbsolutePath());
|
||||
} catch (TransformerException | IOException | ParserConfigurationException e) {
|
||||
LOGGER.error("Failed to apply FOP", e);
|
||||
}
|
||||
|
||||
toPDFfromFOP(fopInput, () -> {
|
||||
try {
|
||||
return new FileOutputStream(pdfFilename);
|
||||
} catch (FileNotFoundException e) {
|
||||
LOGGER.error("Failed to create PDF", e);
|
||||
}
|
||||
return null;
|
||||
}, (OutputStream out) -> {});
|
||||
}
|
||||
|
||||
public byte[] toPDF(String xmlContent) {
|
||||
|
||||
String fopInput = null;
|
||||
|
||||
/* remove file endings so that tests can also pass after checking
|
||||
out from git with arbitrary options (which may include CSRF changes)
|
||||
*/
|
||||
try {
|
||||
ByteArrayInputStream fis = new ByteArrayInputStream(xmlContent.getBytes(StandardCharsets.UTF_8));
|
||||
EStandard theStandard = findOutStandardFromRootNode(fis);
|
||||
fis = new ByteArrayInputStream(xmlContent.getBytes(StandardCharsets.UTF_8));//rewind :-(
|
||||
|
||||
fopInput = toFOP(fis, theStandard);
|
||||
} catch (TransformerException | IOException | ParserConfigurationException e) {
|
||||
LOGGER.error("Failed to apply FOP", e);
|
||||
}
|
||||
|
||||
AtomicReference<byte[]> byteHolder = new AtomicReference<>();
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
toPDFfromFOP(fopInput, () -> new BufferedOutputStream(os), (OutputStream out) -> {
|
||||
|
||||
try {
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Failed to create PDF", e);
|
||||
}
|
||||
byteHolder.set(os.toByteArray());
|
||||
});
|
||||
|
||||
return byteHolder.get();
|
||||
}
|
||||
|
||||
private void toPDFfromFOP(String fopInput, Supplier<OutputStream> outputStreamDelegate, Consumer<OutputStream> consumerDelegate) {
|
||||
|
||||
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
|
||||
|
||||
Configuration cfg = null;
|
||||
@@ -291,24 +363,27 @@ public class ZUGFeRDVisualizer {
|
||||
// Step 2: Set up output stream.
|
||||
// Note: Using BufferedOutputStream for performance reasons (helpful with FileOutputStreams).
|
||||
|
||||
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(pdfFilename))) {
|
||||
try (OutputStream out = new BufferedOutputStream(outputStreamDelegate.get())) {
|
||||
|
||||
// Step 3: Construct fop with desired output format
|
||||
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent, out);
|
||||
|
||||
// Step 4: Setup JAXP using identity transformer
|
||||
TransformerFactory factory = TransformerFactory.newInstance();
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
Transformer transformer = factory.newTransformer(); // identity transformer
|
||||
|
||||
// Step 5: Setup input and output for XSLT transformation
|
||||
// Setup input stream
|
||||
Source src = new StreamSource(new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8)));
|
||||
Source src = new StreamSource(new ByteArrayInputStream(fopInput.getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
// Resulting SAX events (the generated FO) must be piped through to FOP
|
||||
Result res = new SAXResult(fop.getDefaultHandler());
|
||||
|
||||
// Step 6: Start XSLT transformation and FOP processing
|
||||
transformer.transform(src, res);
|
||||
|
||||
consumerDelegate.accept(out);
|
||||
|
||||
} catch (FOPException | IOException | TransformerException e) {
|
||||
LOGGER.error("Failed to create PDF", e);
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
<xsl:apply-templates mode="BG-11"
|
||||
select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty"/>
|
||||
<xsl:apply-templates mode="BG-13"
|
||||
select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty"/>
|
||||
select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery"/>
|
||||
<xsl:apply-templates mode="BG-14"
|
||||
select="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:BillingSpecifiedPeriod"/>
|
||||
<!--Manuell: angepasst für BG-16-->
|
||||
@@ -1146,18 +1146,18 @@
|
||||
</xr:Tax_representative_country_code>
|
||||
</xsl:template>
|
||||
<xsl:template mode="BG-13"
|
||||
match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty">
|
||||
match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery">
|
||||
<xsl:variable name="bg-contents"
|
||||
as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty der Instanz in konkreter Syntax wird auf 5 Objekte der EN 16931 abgebildet. -->
|
||||
<xsl:apply-templates mode="BT-70" select="./ram:Name"/>
|
||||
<xsl:apply-templates mode="BT-70" select="ram:ShipToTradeParty/ram:Name"/>
|
||||
<xsl:apply-templates mode="BT-71"
|
||||
select="./ram:ID[empty(following-sibling::ram:GlobalID/@schemeID)]"/>
|
||||
<xsl:apply-templates mode="BT-71" select="./ram:GlobalID[exists(@schemeID)]"/>
|
||||
select="ram:ShipToTradeParty/ram:ID[empty(following-sibling::ram:GlobalID/@schemeID)]"/>
|
||||
<xsl:apply-templates mode="BT-71" select="ram:ShipToTradeParty/ram:GlobalID[exists(@schemeID)]"/>
|
||||
<xsl:apply-templates mode="BT-72"
|
||||
select="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString[@format = '102']"/>
|
||||
select="ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString[@format='102']"/>
|
||||
<!--<xsl:apply-templates mode="BG-14"
|
||||
select="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:BillingSpecifiedPeriod"/>-->
|
||||
<xsl:apply-templates mode="BG-15" select="./ram:PostalTradeAddress"/>
|
||||
<xsl:apply-templates mode="BG-15" select="ram:ShipToTradeParty/ram:PostalTradeAddress"/>
|
||||
</xsl:variable>
|
||||
<xsl:if test="$bg-contents">
|
||||
<xr:DELIVERY_INFORMATION>
|
||||
|
||||
@@ -28,6 +28,14 @@
|
||||
<xsl:text>red</xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="xml_result_text">
|
||||
<xsl:if test="/validation/xml/summary/@status = 'valid'">
|
||||
<xsl:text>Das XML ist valide.</xsl:text>
|
||||
</xsl:if>
|
||||
<xsl:if test="/validation/xml/summary/@status = 'invalid'">
|
||||
<xsl:text>Das XML ist nicht valide.</xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="pdf_result_color">
|
||||
<xsl:if test="/validation/pdf/summary/@status = 'valid'">
|
||||
<xsl:text>green</xsl:text>
|
||||
@@ -37,18 +45,26 @@
|
||||
</xsl:if>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="pdf_result_text">
|
||||
<xsl:if test="/validation/xml/summary/@status = 'valid'">
|
||||
<xsl:if test="/validation/pdf/summary/@status = 'valid'">
|
||||
<xsl:text>Das ZUGFeRD-PDF ist valide.</xsl:text>
|
||||
</xsl:if>
|
||||
<xsl:if test="/validation/xml/summary/@status = 'invalid'">
|
||||
<xsl:if test="/validation/pdf/summary/@status = 'invalid'">
|
||||
<xsl:text>Das ZUGFeRD-PDF ist nicht valide.</xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="result_color">
|
||||
<xsl:if test="/validation/summary/@status = 'valid'">
|
||||
<xsl:text>green</xsl:text>
|
||||
</xsl:if>
|
||||
<xsl:if test="/validation/summary/@status = 'invalid'">
|
||||
<xsl:text>red</xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="result_text">
|
||||
<xsl:if test="/validation/xml/summary/@status = 'valid'">
|
||||
<xsl:if test="/validation/summary/@status = 'valid'">
|
||||
<xsl:text>Es wird empfohlen, das Dokument anzunehmen und es weiterzuverarbeiten.</xsl:text>
|
||||
</xsl:if>
|
||||
<xsl:if test="/validation/xml/summary/@status = 'invalid'">
|
||||
<xsl:if test="/validation/summary/@status = 'invalid'">
|
||||
<xsl:text>Es wird empfohlen, das Dokument zurückzuweisen.</xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:variable>
|
||||
@@ -118,6 +134,7 @@
|
||||
</fo:table-body>
|
||||
</fo:table>
|
||||
<xsl:apply-templates select="./pdf"/>
|
||||
<xsl:apply-templates select="./xml"/>
|
||||
<!--
|
||||
<xsl:call-template name="SubHeader">
|
||||
<xsl:with-param name="text"
|
||||
@@ -130,7 +147,7 @@
|
||||
<xsl:with-param name="text"
|
||||
select="concat('Bewertung: ', $result_text)"/>
|
||||
<xsl:with-param name="color"
|
||||
select="$xml_result_color"/>
|
||||
select="$result_color"/>
|
||||
</xsl:call-template>
|
||||
<fo:block>Validierungsergebnisse im Detail:</fo:block>
|
||||
<fo:table>
|
||||
@@ -165,8 +182,8 @@
|
||||
page-break-before="auto"
|
||||
page-break-inside="avoid">
|
||||
<xsl:choose>
|
||||
<xsl:when test="./xml/messages">
|
||||
<xsl:apply-templates select="./xml/messages"/>
|
||||
<xsl:when test="./pdf/messages|./xml/messages|./messages">
|
||||
<xsl:apply-templates select="./pdf/messages|./xml/messages|./messages"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<fo:table-row border-style="solid"
|
||||
@@ -185,10 +202,10 @@
|
||||
</fo:page-sequence>
|
||||
</fo:root>
|
||||
</xsl:template>
|
||||
<xsl:template match="notice|warning|error">
|
||||
<xsl:template match="notice|warning|error|exception|fatal">
|
||||
<xsl:variable name="msg_color">
|
||||
<xsl:choose>
|
||||
<xsl:when test="name() = 'error'">
|
||||
<xsl:when test="name() = 'error' or name() = 'exception' or name() = 'fatal'">
|
||||
<xsl:text>red</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="name() = 'warning'">
|
||||
@@ -201,7 +218,7 @@
|
||||
</xsl:variable>
|
||||
<xsl:variable name="msg_label">
|
||||
<xsl:choose>
|
||||
<xsl:when test="name() = 'error'">
|
||||
<xsl:when test="name() = 'error' or name() = 'exception' or name() = 'fatal'">
|
||||
<xsl:text>Fehler</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:when test="name() = 'warning'">
|
||||
@@ -291,7 +308,15 @@
|
||||
<xsl:with-param name="text"
|
||||
select="concat('ZUGFeRD-PDF: ', $pdf_result_text)"/>
|
||||
<xsl:with-param name="color"
|
||||
select="'black'"/>
|
||||
select="$pdf_result_color"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
<xsl:template match="xml">
|
||||
<xsl:call-template name="SubHeader">
|
||||
<xsl:with-param name="text"
|
||||
select="concat('E-Rechnung XML: ', $xml_result_text)"/>
|
||||
<xsl:with-param name="color"
|
||||
select="$xml_result_color"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
<xsl:template name="SubHeader">
|
||||
|
||||
@@ -789,7 +789,7 @@
|
||||
<xsl:apply-templates mode="list-entry" select="xr:DELIVERY_INFORMATION/xr:Deliver_to_location_identifier/@scheme_identifier">
|
||||
<xsl:with-param name="field-mapping-identifier" select="'xr:Deliver_to_location_identifier/@scheme_identifier'"/>
|
||||
</xsl:apply-templates>
|
||||
<xsl:apply-templates mode="list-entry" select="xr:DELIVERY_INFORMATION/xr:Actual_delivery_date">
|
||||
<xsl:apply-templates mode="list-entry" select="xr:DELIVERY_INFORMATION/xr:Actual_delivery_date">
|
||||
<xsl:with-param name="value" select="format-date(xr:DELIVERY_INFORMATION/xr:Actual_delivery_date, xrf:_('date-format'))"/>
|
||||
</xsl:apply-templates>
|
||||
<xsl:apply-templates mode="list-entry" select="xr:DELIVERY_INFORMATION/xr:Deliver_to_party_name"/>
|
||||
|
||||
@@ -398,7 +398,7 @@
|
||||
<nummer>BT-64</nummer>
|
||||
</xsl:when>
|
||||
<xsl:when test="$identifier = 'xr:Tax_representative_address_line_2'">
|
||||
<label>Postfach</label>
|
||||
<label>Adresszusatz</label>
|
||||
<nummer>BT-65</nummer>
|
||||
</xsl:when>
|
||||
<xsl:when test="$identifier = 'xr:Tax_representative_address_line_3'">
|
||||
@@ -486,7 +486,7 @@
|
||||
<nummer>BT-75</nummer>
|
||||
</xsl:when>
|
||||
<xsl:when test="$identifier = 'xr:Deliver_to_address_line_2'">
|
||||
<label>Postfach</label>
|
||||
<label>Adresszusatz</label>
|
||||
<nummer>BT-76</nummer>
|
||||
</xsl:when>
|
||||
<xsl:when test="$identifier = 'xr:Deliver_to_address_line_3'">
|
||||
|
||||
@@ -1193,7 +1193,7 @@ function downloadData (element_id) {
|
||||
<div id="BT-50" title="BT-50" class="boxdaten wert"><xsl:value-of select="xr:BUYER_POSTAL_ADDRESS/xr:Buyer_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach (BT-51):</div>
|
||||
<div class="boxdaten legende">Adresszusatz (BT-51):</div>
|
||||
<div id="BT-51" title="BT-51" class="boxdaten wert"><xsl:value-of select="xr:BUYER_POSTAL_ADDRESS/xr:Buyer_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -1258,7 +1258,7 @@ function downloadData (element_id) {
|
||||
<div id="BT-35" title="BT-35" class="boxdaten wert"><xsl:value-of select="xr:SELLER_POSTAL_ADDRESS/xr:Seller_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach (BT-36):</div>
|
||||
<div class="boxdaten legende">Adresszusatz (BT-36):</div>
|
||||
<div id="BT-36" title="BT-36" class="boxdaten wert"><xsl:value-of select="xr:SELLER_POSTAL_ADDRESS/xr:Seller_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -1998,7 +1998,7 @@ function downloadData (element_id) {
|
||||
<div id="BT-64" title="BT-64" class="boxdaten wert"><xsl:value-of select="xr:SELLER_TAX_REPRESENTATIVE_POSTAL_ADDRESS/xr:Tax_representative_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach (BT-65):</div>
|
||||
<div class="boxdaten legende">Adresszusatz (BT-65):</div>
|
||||
<div id="BT-65" title="BT-65" class="boxdaten wert"><xsl:value-of select="xr:SELLER_TAX_REPRESENTATIVE_POSTAL_ADDRESS/xr:Tax_representative_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -2111,7 +2111,7 @@ function downloadData (element_id) {
|
||||
<div id="BT-75" title="BT-75" class="boxdaten wert"><xsl:value-of select="xr:DELIVER_TO_ADDRESS/xr:Deliver_to_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach (BT-76):</div>
|
||||
<div class="boxdaten legende">Adresszusatz (BT-76):</div>
|
||||
<div id="BT-76" title="BT-76" class="boxdaten wert"><xsl:value-of select="xr:DELIVER_TO_ADDRESS/xr:Deliver_to_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<xsl:variable name="i18n.recipientInfo" select="'Informationen zum Käufer'"/>
|
||||
<xsl:variable name="i18n.dateOf" select="' vom '"/>
|
||||
<xsl:variable name="i18n.bt50" select="'Straße / Haus-Nr.'"/>
|
||||
<xsl:variable name="i18n.bt51" select="'Postfach'"/>
|
||||
<xsl:variable name="i18n.bt51" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt163" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt53" select="'PLZ'"/>
|
||||
<xsl:variable name="i18n.bt52" select="'Ort'"/>
|
||||
@@ -26,7 +26,7 @@
|
||||
<xsl:variable name="i18n.bt58" select="'E-Mail-Adresse'"/>
|
||||
<xsl:variable name="i18n.bt27" select="'Firmenname'"/>
|
||||
<xsl:variable name="i18n.bt35" select="'Straße / Haus-Nr.'"/>
|
||||
<xsl:variable name="i18n.bt36" select="'Postfach'"/>
|
||||
<xsl:variable name="i18n.bt36" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt162" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt38" select="'PLZ'"/>
|
||||
<xsl:variable name="i18n.bt37" select="'Ort'"/>
|
||||
@@ -166,7 +166,7 @@
|
||||
<xsl:variable name="i18n.bg11" select="'Steuervertreter des Verkäufers'"/>
|
||||
<xsl:variable name="i18n.bt62" select="'Name'"/>
|
||||
<xsl:variable name="i18n.bt64" select="'Straße / Hausnummer'"/>
|
||||
<xsl:variable name="i18n.bt65" select="'Postfach'"/>
|
||||
<xsl:variable name="i18n.bt65" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt164" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt67" select="'PLZ'"/>
|
||||
<xsl:variable name="i18n.bt66" select="'Ort'"/>
|
||||
@@ -189,7 +189,7 @@
|
||||
<xsl:variable name="i18n.bt72" select="'Lieferdatum'"/>
|
||||
<xsl:variable name="i18n.bt70" select="'Name des Empfängers'"/>
|
||||
<xsl:variable name="i18n.bt75" select="'Straße / Haus-Nr.'"/>
|
||||
<xsl:variable name="i18n.bt76" select="'Postfach'"/>
|
||||
<xsl:variable name="i18n.bt76" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt165" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt78" select="'PLZ'"/>
|
||||
<xsl:variable name="i18n.bt77" select="'Ort'"/>
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
<div title="BT-50" class="boxdaten wert"><xsl:value-of select="xr:BUYER_POSTAL_ADDRESS/xr:Buyer_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach:</div>
|
||||
<div class="boxdaten legende">Adresszusatz:</div>
|
||||
<div title="BT-51" class="boxdaten wert"><xsl:value-of select="xr:BUYER_POSTAL_ADDRESS/xr:Buyer_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -179,7 +179,7 @@
|
||||
<div title="BT-35" class="boxdaten wert"><xsl:value-of select="xr:SELLER_POSTAL_ADDRESS/xr:Seller_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach:</div>
|
||||
<div class="boxdaten legende">Adresszusatz:</div>
|
||||
<div title="BT-36" class="boxdaten wert"><xsl:value-of select="xr:SELLER_POSTAL_ADDRESS/xr:Seller_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -892,7 +892,7 @@
|
||||
<div title="BT-64" class="boxdaten wert"><xsl:value-of select="xr:SELLER_TAX_REPRESENTATIVE_POSTAL_ADDRESS/xr:Tax_representative_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach:</div>
|
||||
<div class="boxdaten legende">Adresszusatz:</div>
|
||||
<div title="BT-65" class="boxdaten wert"><xsl:value-of select="xr:SELLER_TAX_REPRESENTATIVE_POSTAL_ADDRESS/xr:Tax_representative_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -998,7 +998,7 @@
|
||||
<div title="BT-75" class="boxdaten wert"><xsl:value-of select="xr:DELIVER_TO_ADDRESS/xr:Deliver_to_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach:</div>
|
||||
<div class="boxdaten legende">Adresszusatz:</div>
|
||||
<div title="BT-76" class="boxdaten wert"><xsl:value-of select="xr:DELIVER_TO_ADDRESS/xr:Deliver_to_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
|
||||
Reference in New Issue
Block a user