From ffeb4a6463564eca0bb75212a7253bf9972d6696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Thu, 11 Apr 2019 17:03:44 +0200 Subject: [PATCH 01/82] no message --- .../org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index f827bc06..a4d9b936 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -551,7 +551,7 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta assertEquals(ref, getNumber()); } - /* + public void testFXExport() throws Exception { final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20171118_506fx.pdf"; @@ -606,7 +606,7 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta assertEquals(ref, getNumber()); } -*/ + /** * @throws Exception * @Test(expected = IndexOutOfBoundsException.class) From f53ff3546299b9b01c1bd064a3ad83eebfe51af7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Thu, 11 Apr 2019 17:07:54 +0200 Subject: [PATCH 02/82] corrected new zF2 filename CaPiTaliZatIon --- .../java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java index e5504667..3256ca25 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java @@ -158,7 +158,11 @@ public class ZUGFeRDExporter implements Closeable { if (isFacturX) { return "factur-x.xml"; } else { - return "ZUGFeRD-invoice.xml"; + if (ver==1) { + return "ZUGFeRD-invoice.xml"; + } else { + return "zugferd-invoice.xml"; + } } } From 00a7d4be2cfbf70f6c485eb2955387b822990d8b Mon Sep 17 00:00:00 2001 From: Andre Kemper Date: Sat, 13 Apr 2019 14:20:45 +0200 Subject: [PATCH 03/82] change to multiple bank accounts --- .../IZUGFeRDExportableTransaction.java | 58 +---- .../IZUGFeRDTradeSettlementPayment.java | 81 +++++++ .../ZUGFeRD/ZUGFeRD2PullProvider.java | 45 ++-- .../ZUGFeRDTransactionModelConverter.java | 84 ++++---- .../IZUGFeRDExportableTransactionImpl.java | 72 +------ .../IZUGFeRDTradeSettlementPaymentImpl.java | 90 ++++++++ .../ZUGFeRD/MustangReaderTestCase.java | 204 ++++++++++++++++++ .../ZUGFeRD/MustangReaderWriterEdgeTest.java | 183 +--------------- .../ZUGFeRD/MustangReaderWriterTest.java | 196 ++--------------- .../ZUGFeRDTransactionModelConverterTest.java | 2 +- 10 files changed, 472 insertions(+), 543 deletions(-) create mode 100644 src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDTradeSettlementPayment.java create mode 100644 src/test/java/org/mustangproject/ZUGFeRD/IZUGFeRDTradeSettlementPaymentImpl.java create mode 100644 src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java index 21b55190..112080ec 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java @@ -105,53 +105,9 @@ public interface IZUGFeRDExportableTransaction { /** - * BIC of the sender - * - * @return the BIC code of the recipient sender's bank + * the creditors payment informations */ - default String getOwnBIC() { - return null; - } - - - /** - * BLZ of the sender - * - * @return the BLZ code of the recipient sender's bank - */ - default String getOwnBLZ() { - return null; - } - - - /** - * Bank name of the sender - * - * @return the name of the sender's bank - */ - default String getOwnBankName() { - return null; - } - - - /** - * IBAN of the sender - * - * @return the IBAN of the invoice sender's bank account - */ - default String getOwnIBAN() { - return null; - } - - - /** - * IBAN of the sender - * - * @return the Account Number of the invoice sender's bank account - */ - default String getOwnKto() { - return null; - } + IZUGFeRDTradeSettlementPayment[] getTradeSettlementPayment(); /** @@ -252,16 +208,6 @@ public interface IZUGFeRDExportableTransaction { } - /** - * get payment information text. e.g. Bank transfer - * - * @return payment information text - */ - default String getOwnPaymentInfoText() { - return null; - } - - /** * get payment term descriptional text e.g. Bis zum 22.10.2015 ohne Abzug * diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDTradeSettlementPayment.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDTradeSettlementPayment.java new file mode 100644 index 00000000..3b45b9c8 --- /dev/null +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDTradeSettlementPayment.java @@ -0,0 +1,81 @@ +/** ********************************************************************** + * + * Copyright 2019 by ak on 12.04.19. + * + * 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; + +public interface IZUGFeRDTradeSettlementPayment { + + /** + * get payment information text. e.g. Bank transfer + * + * @return payment information text + */ + default String getOwnPaymentInfoText() { + return null; + } + + /** + * BIC of the sender + * + * @return the BIC code of the recipient sender's bank + */ + default String getOwnBIC() { + return null; + } + + + /** + * BLZ of the sender + * + * @return the BLZ code of the recipient sender's bank + */ + default String getOwnBLZ() { + return null; + } + + + /** + * Bank name of the sender + * + * @return the name of the sender's bank + */ + default String getOwnBankName() { + return null; + } + + + /** + * IBAN of the sender + * + * @return the IBAN of the invoice sender's bank account + */ + default String getOwnIBAN() { + return null; + } + + + /** + * IBAN of the sender + * + * @return the Account Number of the invoice sender's bank account + */ + default String getOwnKto() { + return null; + } + +} diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 52a77fe5..cb0b8c69 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -29,13 +29,11 @@ import java.util.HashMap; public class ZUGFeRD2PullProvider implements IXMLProvider { private class LineCalc { - private IZUGFeRDExportableItem currentItem = null; private BigDecimal totalGross; private BigDecimal itemTotalNetAmount; private BigDecimal itemTotalVATAmount; public LineCalc(IZUGFeRDExportableItem currentItem) { - this.currentItem = currentItem; BigDecimal multiplicator = currentItem.getProduct().getVATPercent().divide(new BigDecimal(100)).add(new BigDecimal(1)); // priceGross=currentItem.getPrice().multiply(multiplicator); totalGross = currentItem.getPrice().multiply(multiplicator).multiply(currentItem.getQuantity()); @@ -58,14 +56,11 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { protected byte[] zugferdData; private IZUGFeRDExportableTransaction trans; - private boolean isTest; /** * enables the flag to indicate a test invoice in the XML structure */ - public void setTest() { - isTest = true; - } + public void setTest() {} private String nDigitFormat(BigDecimal value, int scale) { /* @@ -155,7 +150,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { * @return which taxes have been used with which amounts in this invoice */ private HashMap getVATPercentAmountMap() { - HashMap hm = new HashMap(); + HashMap hm = new HashMap<>(); for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { BigDecimal percent = currentItem.getProduct().getVATPercent(); @@ -174,15 +169,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { @Override public void generateXML(IZUGFeRDExportableTransaction trans) { - this.trans = trans; SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy"); //$NON-NLS-1$ SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); //$NON-NLS-1$ - String testBooleanStr = "false"; - if (isTest) { - testBooleanStr = "true"; - - } String senderReg = ""; if (trans.getOwnOrganisationFullPlaintextInfo() != null) { senderReg = "" @@ -331,21 +320,23 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { + " \n" + " \n" //$NON-NLS-1$ + " " + trans.getNumber() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " EUR\n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " 42\n" //$NON-NLS-1$ - + " Überweisung\n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " " + trans.getOwnIBAN() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " " + trans.getOwnKto() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " " + trans.getOwnBIC() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " " + trans.getOwnBLZ() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ -// + " "+trans.getOwnBankName()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n"; //$NON-NLS-1$ + + " EUR\n"; //$NON-NLS-1$ + for(IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) { + xml += " \n" //$NON-NLS-1$ + + " 42\n" //$NON-NLS-1$ + + " Überweisung\n" //$NON-NLS-1$ + + " \n" //$NON-NLS-1$ + + " " + payment.getOwnIBAN() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + payment.getOwnKto() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " \n" //$NON-NLS-1$ + + " \n" //$NON-NLS-1$ + + " " + payment.getOwnBIC() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + payment.getOwnBLZ() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ +// + " "+trans.getOwnBankName()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " \n" //$NON-NLS-1$ + + " \n"; //$NON-NLS-1$ + } HashMap VATPercentAmountMap = getVATPercentAmountMap(); for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java index d7434eee..11b8b45c 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java @@ -39,7 +39,6 @@ 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.DocumentCodeTypeConstants; import org.mustangproject.ZUGFeRD.model.DocumentContextParameterType; import org.mustangproject.ZUGFeRD.model.DocumentContextParameterTypeConstants; import org.mustangproject.ZUGFeRD.model.DocumentLineDocumentType; @@ -62,7 +61,6 @@ 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.TaxCategoryCodeTypeConstants; import org.mustangproject.ZUGFeRD.model.TaxRegistrationType; import org.mustangproject.ZUGFeRD.model.TaxRegistrationTypeConstants; import org.mustangproject.ZUGFeRD.model.TaxTypeCodeType; @@ -340,7 +338,7 @@ class ZUGFeRDTransactionModelConverter { currencyCode.setValue(currency); tradeSettlement.setInvoiceCurrencyCode(currencyCode); - tradeSettlement.getSpecifiedTradeSettlementPaymentMeans().add( + tradeSettlement.getSpecifiedTradeSettlementPaymentMeans().addAll( getPaymentData()); tradeSettlement.getApplicableTradeTax().addAll(getTradeTax()); tradeSettlement.getSpecifiedTradePaymentTerms().addAll( @@ -364,46 +362,50 @@ class ZUGFeRDTransactionModelConverter { } - private TradeSettlementPaymentMeansType getPaymentData() { - TradeSettlementPaymentMeansType paymentData = xmlFactory - .createTradeSettlementPaymentMeansType(); - PaymentMeansCodeType paymentDataType = xmlFactory - .createPaymentMeansCodeType(); - paymentDataType.setValue(PaymentMeansCodeTypeConstants.BANKACCOUNT); - paymentData.setTypeCode(paymentDataType); + private List getPaymentData() { + List result = new ArrayList<>(); + for (IZUGFeRDTradeSettlementPayment settlementPayment : trans.getTradeSettlementPayment()) { + TradeSettlementPaymentMeansType paymentData = xmlFactory + .createTradeSettlementPaymentMeansType(); + PaymentMeansCodeType paymentDataType = xmlFactory + .createPaymentMeansCodeType(); + paymentDataType.setValue(PaymentMeansCodeTypeConstants.BANKACCOUNT); + paymentData.setTypeCode(paymentDataType); - TextType paymentInfo = xmlFactory.createTextType(); - String paymentInfoText = trans.getOwnPaymentInfoText(); - if (paymentInfoText == null) { - paymentInfoText = ""; + TextType paymentInfo = xmlFactory.createTextType(); + String paymentInfoText = settlementPayment.getOwnPaymentInfoText(); + if (paymentInfoText == null) { + paymentInfoText = ""; + } + paymentInfo.setValue(paymentInfoText); + paymentData.getInformation().add(paymentInfo); + + CreditorFinancialAccountType bankAccount = xmlFactory + .createCreditorFinancialAccountType(); + IDType iban = xmlFactory.createIDType(); + iban.setValue(settlementPayment.getOwnIBAN()); + bankAccount.setIBANID(iban); + IDType kto = xmlFactory.createIDType(); + kto.setValue(settlementPayment.getOwnKto()); + bankAccount.setProprietaryID(kto); + paymentData.setPayeePartyCreditorFinancialAccount(bankAccount); + + CreditorFinancialInstitutionType bankData = xmlFactory + .createCreditorFinancialInstitutionType(); + IDType bicId = xmlFactory.createIDType(); + bicId.setValue(settlementPayment.getOwnBIC()); + bankData.setBICID(bicId); + TextType bankName = xmlFactory.createTextType(); + bankName.setValue(settlementPayment.getOwnBankName()); + bankData.setName(bankName); + IDType blz = xmlFactory.createIDType(); + blz.setValue(settlementPayment.getOwnBLZ()); + bankData.setGermanBankleitzahlID(blz); + + paymentData.setPayeeSpecifiedCreditorFinancialInstitution(bankData); + result.add(paymentData); } - paymentInfo.setValue(paymentInfoText); - paymentData.getInformation().add(paymentInfo); - - CreditorFinancialAccountType bankAccount = xmlFactory - .createCreditorFinancialAccountType(); - IDType iban = xmlFactory.createIDType(); - iban.setValue(trans.getOwnIBAN()); - bankAccount.setIBANID(iban); - IDType kto = xmlFactory.createIDType(); - kto.setValue(trans.getOwnKto()); - bankAccount.setProprietaryID(kto); - paymentData.setPayeePartyCreditorFinancialAccount(bankAccount); - - CreditorFinancialInstitutionType bankData = xmlFactory - .createCreditorFinancialInstitutionType(); - IDType bicId = xmlFactory.createIDType(); - bicId.setValue(trans.getOwnBIC()); - bankData.setBICID(bicId); - TextType bankName = xmlFactory.createTextType(); - bankName.setValue(trans.getOwnBankName()); - bankData.setName(bankName); - IDType blz = xmlFactory.createIDType(); - blz.setValue(trans.getOwnBLZ()); - bankData.setGermanBankleitzahlID(blz); - - paymentData.setPayeeSpecifiedCreditorFinancialInstitution(bankData); - return paymentData; + return result; } diff --git a/src/test/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransactionImpl.java b/src/test/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransactionImpl.java index 1aefd3a8..f1d5d001 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransactionImpl.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransactionImpl.java @@ -21,6 +21,7 @@ package org.mustangproject.ZUGFeRD; import java.util.Date; public class IZUGFeRDExportableTransactionImpl implements IZUGFeRDExportableTransaction { + private String number; private Date issueDate; private String ownOrganisationFullPlaintextInfo; @@ -30,11 +31,7 @@ public class IZUGFeRDExportableTransactionImpl implements IZUGFeRDExportableTran private IZUGFeRDAllowanceCharge[] zFLogisticsServiceCharges; private IZUGFeRDExportableItem[] zFItems; private IZUGFeRDExportableContact recipient; - private String ownKto; - private String ownBLZ; - private String ownBIC; - private String ownBankName; - private String ownIBAN; + private IZUGFeRDTradeSettlementPayment[] settlementPayments; private String ownTaxID; private String ownVATID; private String ownOrganisationName; @@ -44,7 +41,6 @@ public class IZUGFeRDExportableTransactionImpl implements IZUGFeRDExportableTran private String ownCountry; private Date deliveryDate; private String currency; - private String ownPaymentInfoText; private String paymentTermDescription; private String referenceNumber; @@ -94,28 +90,8 @@ public class IZUGFeRDExportableTransactionImpl implements IZUGFeRDExportableTran } @Override - public String getOwnKto() { - return ownKto; - } - - @Override - public String getOwnBLZ() { - return ownBLZ; - } - - @Override - public String getOwnBIC() { - return ownBIC; - } - - @Override - public String getOwnBankName() { - return ownBankName; - } - - @Override - public String getOwnIBAN() { - return ownIBAN; + public IZUGFeRDTradeSettlementPayment[] getTradeSettlementPayment() { + return settlementPayments; } @Override @@ -163,11 +139,6 @@ public class IZUGFeRDExportableTransactionImpl implements IZUGFeRDExportableTran return currency; } - @Override - public String getOwnPaymentInfoText() { - return ownPaymentInfoText; - } - @Override public String getPaymentTermDescription() { return paymentTermDescription; @@ -223,31 +194,6 @@ public class IZUGFeRDExportableTransactionImpl implements IZUGFeRDExportableTran return this; } - public IZUGFeRDExportableTransactionImpl setOwnBLZ(String ownBLZ) { - this.ownBLZ = ownBLZ; - return this; - } - - public IZUGFeRDExportableTransactionImpl setOwnBIC(String ownBIC) { - this.ownBIC = ownBIC; - return this; - } - - public IZUGFeRDExportableTransactionImpl setOwnBankName(String ownBankName) { - this.ownBankName = ownBankName; - return this; - } - - public IZUGFeRDExportableTransactionImpl setOwnKto(String ownKto) { - this.ownKto = ownKto; - return this; - } - - public IZUGFeRDExportableTransactionImpl setOwnIBAN(String ownIBAN) { - this.ownIBAN = ownIBAN; - return this; - } - public IZUGFeRDExportableTransactionImpl setOwnTaxID(String ownTaxID) { this.ownTaxID = ownTaxID; return this; @@ -293,11 +239,6 @@ public class IZUGFeRDExportableTransactionImpl implements IZUGFeRDExportableTran return this; } - public IZUGFeRDExportableTransactionImpl setOwnPaymentInfoText(String ownPaymentInfoText) { - this.ownPaymentInfoText = ownPaymentInfoText; - return this; - } - public IZUGFeRDExportableTransactionImpl setPaymentTermDescription(String paymentTermDescription) { this.paymentTermDescription = paymentTermDescription; return this; @@ -307,4 +248,9 @@ public class IZUGFeRDExportableTransactionImpl implements IZUGFeRDExportableTran this.referenceNumber = referenceNumber; return this; } + + public IZUGFeRDExportableTransactionImpl setTradeSettlementPayment(IZUGFeRDTradeSettlementPayment... settlementPayments) { + this.settlementPayments = settlementPayments; + return this; + } } diff --git a/src/test/java/org/mustangproject/ZUGFeRD/IZUGFeRDTradeSettlementPaymentImpl.java b/src/test/java/org/mustangproject/ZUGFeRD/IZUGFeRDTradeSettlementPaymentImpl.java new file mode 100644 index 00000000..8ad9839a --- /dev/null +++ b/src/test/java/org/mustangproject/ZUGFeRD/IZUGFeRDTradeSettlementPaymentImpl.java @@ -0,0 +1,90 @@ +/** ********************************************************************** + * + * Copyright 2019 by ak on 12.04.19. + * + * 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; + +public class IZUGFeRDTradeSettlementPaymentImpl implements IZUGFeRDTradeSettlementPayment { + + private String ownKto; + private String ownBLZ; + private String ownBIC; + private String ownBankName; + private String ownIBAN; + private String ownPaymentInfoText; + + @Override + public String getOwnKto() { + return ownKto; + } + + @Override + public String getOwnBLZ() { + return ownBLZ; + } + + @Override + public String getOwnBIC() { + return ownBIC; + } + + @Override + public String getOwnBankName() { + return ownBankName; + } + + @Override + public String getOwnIBAN() { + return ownIBAN; + } + + @Override + public String getOwnPaymentInfoText() { + return ownPaymentInfoText; + } + + public IZUGFeRDTradeSettlementPaymentImpl setOwnBLZ(String ownBLZ) { + this.ownBLZ = ownBLZ; + return this; + } + + public IZUGFeRDTradeSettlementPaymentImpl setOwnBIC(String ownBIC) { + this.ownBIC = ownBIC; + return this; + } + + public IZUGFeRDTradeSettlementPaymentImpl setOwnBankName(String ownBankName) { + this.ownBankName = ownBankName; + return this; + } + + public IZUGFeRDTradeSettlementPaymentImpl setOwnKto(String ownKto) { + this.ownKto = ownKto; + return this; + } + + public IZUGFeRDTradeSettlementPaymentImpl setOwnIBAN(String ownIBAN) { + this.ownIBAN = ownIBAN; + return this; + } + + public IZUGFeRDTradeSettlementPaymentImpl setOwnPaymentInfoText(String ownPaymentInfoText) { + this.ownPaymentInfoText = ownPaymentInfoText; + return this; + } + +} diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java new file mode 100644 index 00000000..57043b05 --- /dev/null +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java @@ -0,0 +1,204 @@ +/** ********************************************************************** + * + * Copyright 2019 by ak on 12.04.19. + * + * 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.TestCase; + +import java.math.BigDecimal; + +public abstract class MustangReaderTestCase extends TestCase implements IZUGFeRDExportableTransaction { + + public MustangReaderTestCase(String testName) { + super(testName); + } + + @Override + public IZUGFeRDTradeSettlementPayment[] getTradeSettlementPayment() { + Payment[] payments = new Payment[1]; + payments[0] = new Payment(); + return payments; + } + + protected class Payment implements IZUGFeRDTradeSettlementPayment { + + @Override + public String getOwnKto() { + return "44421800"; + } + + @Override + public String getOwnBLZ() { + return "41441604"; + } + + @Override + public String getOwnBIC() { + return "COBADEFFXXX"; + } + + @Override + public String getOwnBankName() { + return "Commerzbank"; + } + + @Override + public String getOwnPaymentInfoText() { + return "Überweisung"; + } + + @Override + public String getOwnIBAN() { + return "DE88 2008 0000 0970 3757 00"; + } + } + + protected class Contact implements IZUGFeRDExportableContact { + + @Override + public String getCountry() { + return "DE"; + } + + @Override + public String getLocation() { + return "Spielkreis"; + } + + @Override + public String getName() { + return "Theodor Est"; + } + + @Override + public String getStreet() { + return "Bahnstr. 42"; + } + + @Override + public String getVATID() { + return "DE999999999"; + } + + @Override + public String getZIP() { + return "88802"; + } + } + + protected class Item implements IZUGFeRDExportableItem { + + public Item(BigDecimal price, BigDecimal quantity, Product product) { + super(); + this.price = price; + this.quantity = quantity; + this.product = product; + } + + private BigDecimal price, quantity; + private Product product; + + @Override + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + @Override + public BigDecimal getQuantity() { + return quantity; + } + + public void setQuantity(BigDecimal quantity) { + this.quantity = quantity; + } + + @Override + public Product getProduct() { + return product; + } + + public void setProduct(Product product) { + this.product = product; + } + + @Override + public IZUGFeRDAllowanceCharge[] getItemAllowances() { + return null; + } + + @Override + public IZUGFeRDAllowanceCharge[] getItemCharges() { + return null; + } + + } + + protected class Product implements IZUGFeRDExportableProduct { + private String description, name, unit; + private BigDecimal VATPercent; + + public Product(String description, String name, String unit, BigDecimal VATPercent) { + super(); + this.description = description; + this.name = name; + this.unit = unit; + this.VATPercent = VATPercent; + } + + @Override + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String getUnit() { + return unit; + } + + public void setUnit(String unit) { + this.unit = unit; + } + + @Override + public BigDecimal getVATPercent() { + return VATPercent; + } + + public void setVATPercent(BigDecimal VATPercent) { + this.VATPercent = VATPercent; + } + } + +} diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java index 84fd2fa3..1bb90beb 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java @@ -33,7 +33,7 @@ import java.util.Date; import java.util.GregorianCalendar; @FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class MustangReaderWriterEdgeTest extends TestCase implements IZUGFeRDExportableTransaction { +public class MustangReaderWriterEdgeTest extends MustangReaderTestCase { @Override public Date getDeliveryDate() { @@ -55,36 +55,11 @@ public class MustangReaderWriterEdgeTest extends TestCase implements IZUGFeRDExp return "RE-20170509/505"; } - @Override - public String getOwnKto() { - return "44421800"; - } - - @Override - public String getOwnBLZ() { - return "41441604"; - } - - @Override - public String getOwnBIC() { - return "COBADEFFXXX"; - } - - @Override - public String getOwnBankName() { - return "Commerzbank"; - } - @Override public String getOwnCountry() { return "DE"; } - @Override - public String getOwnIBAN() { - return "DE88 2008 0000 0970 3757 00"; - } - @Override public String getOwnLocation() { return "Stadthausen"; @@ -120,7 +95,6 @@ public class MustangReaderWriterEdgeTest extends TestCase implements IZUGFeRDExp return new Contact(); } - @Override public String getOwnOrganisationFullPlaintextInfo() { return null; @@ -144,11 +118,6 @@ public class MustangReaderWriterEdgeTest extends TestCase implements IZUGFeRDExp return allItems; } - @Override - public String getOwnPaymentInfoText() { - return "Überweisung"; - } - @Override public String getPaymentTermDescription() { SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy"); @@ -175,140 +144,6 @@ public class MustangReaderWriterEdgeTest extends TestCase implements IZUGFeRDExp return null; } - class Contact implements IZUGFeRDExportableContact { - - @Override - public String getCountry() { - return "DE"; - } - - @Override - public String getLocation() { - return "Spielkreis"; - } - - @Override - public String getName() { - return "Theodor Est"; - } - - @Override - public String getStreet() { - return "Bahnstr. 42"; - } - - @Override - public String getVATID() { - return "DE999999999"; - } - - @Override - public String getZIP() { - return "88802"; - } - } - - class Item implements IZUGFeRDExportableItem { - - public Item(BigDecimal price, BigDecimal quantity, Product product) { - super(); - this.price = price; - this.quantity = quantity; - this.product = product; - } - - private BigDecimal price, quantity; - private Product product; - - @Override - public BigDecimal getPrice() { - return price; - } - - public void setPrice(BigDecimal price) { - this.price = price; - } - - @Override - public BigDecimal getQuantity() { - return quantity; - } - - public void setQuantity(BigDecimal quantity) { - this.quantity = quantity; - } - - @Override - public Product getProduct() { - return product; - } - - public void setProduct(Product product) { - this.product = product; - } - - @Override - public IZUGFeRDAllowanceCharge[] getItemAllowances() { - return null; - } - - @Override - public IZUGFeRDAllowanceCharge[] getItemCharges() { - return null; - } - - } - - class Product implements IZUGFeRDExportableProduct { - private String description, name, unit; - private BigDecimal VATPercent; - - public Product(String description, String name, String unit, BigDecimal VATPercent) { - super(); - this.description = description; - this.name = name; - this.unit = unit; - this.VATPercent = VATPercent; - } - - @Override - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String getUnit() { - return unit; - } - - public void setUnit(String unit) { - this.unit = unit; - } - - @Override - public BigDecimal getVATPercent() { - return VATPercent; - } - - public void setVATPercent(BigDecimal vATPercent) { - VATPercent = vATPercent; - } - - } - /** * Create the test case * @@ -341,10 +176,10 @@ public class MustangReaderWriterEdgeTest extends TestCase implements IZUGFeRDExp // Reading ZUGFeRD assertEquals(zi.getAmount(), "571.04"); - assertEquals(zi.getBIC(), getOwnBIC()); - assertEquals(zi.getBLZ(), getOwnBLZ()); - assertEquals(zi.getIBAN(), getOwnIBAN()); - assertEquals(zi.getKTO(), getOwnKto()); + 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.getDueDate(), "20170530"); assertEquals(zi.getForeignReference(), getNumber()); @@ -384,10 +219,10 @@ public class MustangReaderWriterEdgeTest extends TestCase implements IZUGFeRDExp // Reading ZUGFeRD assertEquals(zi.getAmount(), "571.04"); - assertEquals(zi.getBIC(), getOwnBIC()); - assertEquals(zi.getBLZ(), getOwnBLZ()); - assertEquals(zi.getIBAN(), getOwnIBAN()); - assertEquals(zi.getKTO(), getOwnKto()); + 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()); } diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index 45cc0b2e..58f49c44 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -30,12 +30,10 @@ import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; +import java.util.*; @FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExportableTransaction { +public class MustangReaderWriterTest extends MustangReaderTestCase { @Override public Date getDeliveryDate() { @@ -57,36 +55,11 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta return "RE-20171118/506"; } - @Override - public String getOwnKto() { - return "44421800"; - } - - @Override - public String getOwnBLZ() { - return "41441604"; - } - - @Override - public String getOwnBIC() { - return "COBADEFFXXX"; - } - - @Override - public String getOwnBankName() { - return "Commerzbank"; - } - @Override public String getOwnCountry() { return "DE"; } - @Override - public String getOwnIBAN() { - return "DE88 2008 0000 0970 3757 00"; - } - @Override public String getOwnLocation() { return "Stadthausen"; @@ -146,11 +119,6 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta return allItems; } - @Override - public String getOwnPaymentInfoText() { - return "Überweisung"; - } - @Override public String getPaymentTermDescription() { SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy"); @@ -183,140 +151,6 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta return null; } - class Contact implements IZUGFeRDExportableContact { - - @Override - public String getCountry() { - return "DE"; - } - - @Override - public String getLocation() { - return "Spielkreis"; - } - - @Override - public String getName() { - return "Theodor Est"; - } - - @Override - public String getStreet() { - return "Bahnstr. 42"; - } - - @Override - public String getVATID() { - return "DE999999999"; - } - - @Override - public String getZIP() { - return "88802"; - } - } - - class Item implements IZUGFeRDExportableItem { - - public Item(BigDecimal price, BigDecimal quantity, Product product) { - super(); - this.price = price; - this.quantity = quantity; - this.product = product; - } - - private BigDecimal price, quantity; - private Product product; - - @Override - public BigDecimal getPrice() { - return price; - } - - public void setPrice(BigDecimal price) { - this.price = price; - } - - @Override - public BigDecimal getQuantity() { - return quantity; - } - - public void setQuantity(BigDecimal quantity) { - this.quantity = quantity; - } - - @Override - public Product getProduct() { - return product; - } - - public void setProduct(Product product) { - this.product = product; - } - - @Override - public IZUGFeRDAllowanceCharge[] getItemAllowances() { - return null; - } - - @Override - public IZUGFeRDAllowanceCharge[] getItemCharges() { - return null; - } - - } - - class Product implements IZUGFeRDExportableProduct { - private String description, name, unit; - private BigDecimal VATPercent; - - public Product(String description, String name, String unit, BigDecimal VATPercent) { - super(); - this.description = description; - this.name = name; - this.unit = unit; - this.VATPercent = VATPercent; - } - - @Override - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String getUnit() { - return unit; - } - - public void setUnit(String unit) { - this.unit = unit; - } - - @Override - public BigDecimal getVATPercent() { - return VATPercent; - } - - public void setVATPercent(BigDecimal VATPercent) { - this.VATPercent = VATPercent; - } - - } - /** * Create the test case * @@ -351,10 +185,10 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta // Reading ZUGFeRD assertEquals(zi.getAmount(), "571.04"); - assertEquals(zi.getBLZ(), getOwnBLZ()); - assertEquals(zi.getBIC(), getOwnBIC()); - assertEquals(zi.getIBAN(), getOwnIBAN()); - assertEquals(zi.getKTO(), getOwnKto()); + assertEquals(zi.getBLZ(), getTradeSettlementPayment()[0].getOwnBLZ()); + assertEquals(zi.getBIC(), getTradeSettlementPayment()[0].getOwnBIC()); + assertEquals(zi.getIBAN(),getTradeSettlementPayment()[0].getOwnIBAN()); + assertEquals(zi.getKTO(), getTradeSettlementPayment()[0].getOwnKto()); assertEquals(zi.getHolder(), getOwnOrganisationName()); assertEquals(zi.getForeignReference(), "RE-20170509/505"); } @@ -488,9 +322,9 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta String pdfContent = baos.toString("UTF-8"); assertFalse(pdfContent.indexOf("(via mustangproject.org") == -1); // check for pdf-a schema extension - assertFalse(pdfContent.indexOf("EN 16931") == -1); - assertFalse(pdfContent.indexOf("zf") == -1); - assertFalse(pdfContent.indexOf("urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#") == -1); +// assertFalse(pdfContent.indexOf("EN 16931") == -1); +// assertFalse(pdfContent.indexOf("zf") == -1); +// assertFalse(pdfContent.indexOf("urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#") == -1); } @@ -499,9 +333,9 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta // Reading ZUGFeRD assertEquals(zi.getAmount(), "571.04"); - assertEquals(zi.getBIC(), getOwnBIC()); - assertEquals(zi.getIBAN(), getOwnIBAN()); - assertEquals(zi.getKTO(), getOwnKto()); + assertEquals(zi.getBIC(), getTradeSettlementPayment()[0].getOwnBIC()); + assertEquals(zi.getIBAN(), getTradeSettlementPayment()[0].getOwnIBAN()); + assertEquals(zi.getKTO(), getTradeSettlementPayment()[0].getOwnKto()); assertEquals(zi.getHolder(), getOwnOrganisationName()); assertEquals(zi.getForeignReference(), getNumber()); } @@ -536,9 +370,9 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta // Reading ZUGFeRD assertEquals(zi.getAmount(), "571.04"); - assertEquals(zi.getBIC(), getOwnBIC()); - assertEquals(zi.getIBAN(), getOwnIBAN()); - assertEquals(zi.getKTO(), getOwnKto()); + assertEquals(zi.getBIC(), getTradeSettlementPayment()[0].getOwnBIC()); + assertEquals(zi.getIBAN(), getTradeSettlementPayment()[0].getOwnIBAN()); + assertEquals(zi.getKTO(), getTradeSettlementPayment()[0].getOwnKto()); assertEquals(zi.getHolder(), getOwnOrganisationName()); assertEquals(zi.getForeignReference(), getNumber()); } diff --git a/src/test/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverterTest.java index 2e284fdd..5497d282 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverterTest.java @@ -45,7 +45,7 @@ public class ZUGFeRDTransactionModelConverterTest { .setOwnStreet("own street") .setOwnCountry("own country") .setOwnLocation("own city") - .setOwnBankName("own bank") + .setTradeSettlementPayment(new IZUGFeRDTradeSettlementPaymentImpl().setOwnBankName("own bank")) .setZFItems( new IZUGFeRDExportableItemImpl() .setProduct(new IZUGFeRDExportableProductImpl() From 9a3a32a91c1376069179c3e8dc3d1c71a041a18a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 21 Apr 2019 09:30:19 +0200 Subject: [PATCH 04/82] zf2 importer correction --- src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index 6b2a1acb..11cb05c9 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -127,7 +127,7 @@ public class ZUGFeRDImporter { * currently (in the release candidate of version 1) only one attached file with * the name ZUGFeRD-invoice.xml is allowed */ - if ((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; PDComplexFileSpecification fileSpec = names.get(filename); From 015a5302221bafe93d0d3b6e46cb096326bd6b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 21 Apr 2019 18:09:15 +0200 Subject: [PATCH 05/82] reactivated a test --- .../ZUGFeRD/XMPSchemaPDFAExtensions.java | 12 ++++++++---- .../mustangproject/ZUGFeRD/ZUGFeRDExporter.java | 14 +++++++------- .../ZUGFeRD/MustangReaderWriterTest.java | 3 ++- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaPDFAExtensions.java b/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaPDFAExtensions.java index 131638db..3e0dca57 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaPDFAExtensions.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaPDFAExtensions.java @@ -52,11 +52,13 @@ public class XMPSchemaPDFAExtensions extends PDFAExtensionSchema { public final String prefix_pdfaProperty = "pdfaProperty"; public String namespace = null; public String prefix = null; + + protected ZUGFeRDExporter exporter; protected void setZUGFeRDVersion(int ver) { - namespace = ZUGFeRDExporter.getNamespaceForVersion(ver); - prefix = ZUGFeRDExporter.getPrefixForVersion(ver); + namespace = exporter.getNamespaceForVersion(ver); + prefix = exporter.getPrefixForVersion(ver); } @@ -87,14 +89,16 @@ public class XMPSchemaPDFAExtensions extends PDFAExtensionSchema { return li; } - public XMPSchemaPDFAExtensions(XMPMetadata metadata, int ZFVersion) { + public XMPSchemaPDFAExtensions(ZUGFeRDExporter ze, XMPMetadata metadata, int ZFVersion) { super(metadata); + exporter=ze; setZUGFeRDVersion(ZFVersion); attachExtensions(metadata, true); } - public XMPSchemaPDFAExtensions(XMPMetadata metadata, int ZFVersion, boolean withZF) { + public XMPSchemaPDFAExtensions(ZUGFeRDExporter ze, XMPMetadata metadata, int ZFVersion, boolean withZF) { super(metadata); + exporter=ze; setZUGFeRDVersion(ZFVersion); attachExtensions(metadata, withZF); } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java index 3256ca25..1efeb8d2 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java @@ -55,7 +55,7 @@ public class ZUGFeRDExporter implements Closeable { public static final int DefaultZUGFeRDVersion = 1; - private static boolean isFacturX = false; + private boolean isFacturX = false; /** * To use the ZUGFeRD exporter, implement IZUGFeRDExportableTransaction in @@ -133,7 +133,7 @@ public class ZUGFeRDExporter implements Closeable { additionalXMLs.put(filename, xml); } - public static String getNamespaceForVersion(int ver) { + public String getNamespaceForVersion(int ver) { if (isFacturX) { return "urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#"; } else if (ver == 1) { @@ -146,7 +146,7 @@ public class ZUGFeRDExporter implements Closeable { } } - public static String getPrefixForVersion(int ver) { + public String getPrefixForVersion(int ver) { if (isFacturX) { return "fx"; } else { @@ -154,7 +154,7 @@ public class ZUGFeRDExporter implements Closeable { } } - public static String getFilenameForVersion(int ver) { + public String getFilenameForVersion(int ver) { if (isFacturX) { return "factur-x.xml"; } else { @@ -498,13 +498,13 @@ public class ZUGFeRDExporter implements Closeable { if (attachZUGFeRDHeaders) { XMPSchemaZugferd zf = new XMPSchemaZugferd(metadata, profile, - ZUGFeRDExporter.getNamespaceForVersion(ZFVersion), ZUGFeRDExporter.getPrefixForVersion(ZFVersion), - ZUGFeRDExporter.getFilenameForVersion(ZFVersion)); + getNamespaceForVersion(ZFVersion), getPrefixForVersion(ZFVersion), + getFilenameForVersion(ZFVersion)); metadata.addSchema(zf); } - XMPSchemaPDFAExtensions pdfaex = new XMPSchemaPDFAExtensions(metadata, ZFVersion, attachZUGFeRDHeaders); + XMPSchemaPDFAExtensions pdfaex = new XMPSchemaPDFAExtensions(this, metadata, ZFVersion, attachZUGFeRDHeaders); pdfaex.setZUGFeRDVersion(ZFVersion); metadata.addSchema(pdfaex); diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index 45cc0b2e..05fd034a 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -506,6 +506,7 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta assertEquals(zi.getForeignReference(), getNumber()); } + public void testFXExport() throws Exception { final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20171118_506fx.pdf"; @@ -514,7 +515,7 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta try (InputStream SOURCE_PDF = this.getClass() .getResourceAsStream("/MustangGnuaccountingBeispielRE-20171118_506blanko.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)) { ze.setFacturX(); ze.PDFattachZugferdFile(this); ze.disableAutoClose(true); From 9b5c106f1c6b1038392822cf47304e0cdb6abeed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Wed, 24 Apr 2019 20:51:44 +0200 Subject: [PATCH 06/82] new command line option / prompt for format (fx or zf) --- ZUGFeRD-invoice.xml | 0 pom.xml | 2 +- .../ZUGFeRD/ZUGFeRDMigrator.java | 8 + .../org/mustangproject/toecount/Toecount.java | 65 ++- .../input/ZUGFeRD1_COMFORT_Einfach.xml | 216 +++++++ .../input/ZUGFeRD1_EXTENDED_Warenrechnung.xml | 520 +++++++++++++++++ .../reference/ZUGFeRD2-invoice-adjusted.xml | 219 +++++++ .../migration/reference/ZUGFeRD2-invoice.xml | 4 +- .../reference/ZUGFeRD2_COMFORT_Einfach.xml | 229 ++++++++ .../ZUGFeRD2_EXTENDED_Warenrechnung.xml | 546 ++++++++++++++++++ 10 files changed, 1785 insertions(+), 24 deletions(-) delete mode 100644 ZUGFeRD-invoice.xml create mode 100644 src/test/resources/migration/input/ZUGFeRD1_COMFORT_Einfach.xml create mode 100644 src/test/resources/migration/input/ZUGFeRD1_EXTENDED_Warenrechnung.xml create mode 100644 src/test/resources/migration/reference/ZUGFeRD2-invoice-adjusted.xml create mode 100644 src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml create mode 100644 src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml diff --git a/ZUGFeRD-invoice.xml b/ZUGFeRD-invoice.xml deleted file mode 100644 index e69de29b..00000000 diff --git a/pom.xml b/pom.xml index 650c1728..8f16a2dc 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.6.1-SNAPSHOT + 1.6.2-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDMigrator.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDMigrator.java index 3b232c17..bdc78ea3 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDMigrator.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDMigrator.java @@ -63,8 +63,16 @@ public class ZUGFeRDMigrator { */ ByteArrayOutputStream baos = new ByteArrayOutputStream(); applySchematronXsl(new FileInputStream(xmlFilename), baos); + String res = null; res = baos.toString("UTF-8"); + + //somehow the XML parser seems to insert erreneous XML namespaces, depending on which one it is, saxon seems to be cleaner. + //nevertheless, remove them manually + res=res.replace("", ""); + res=res.replace("", ""); + + return res; } diff --git a/src/main/java/org/mustangproject/toecount/Toecount.java b/src/main/java/org/mustangproject/toecount/Toecount.java index 2cf1c3b3..c1143fc2 100755 --- a/src/main/java/org/mustangproject/toecount/Toecount.java +++ b/src/main/java/org/mustangproject/toecount/Toecount.java @@ -69,8 +69,9 @@ public class Toecount { + " [--source ]: set input PDF file\n" + " [--source-xml ]: set input XML file\n" + " [--out ]: set output PDF file\n" - + " [--zugferd-version <1|2>]: set ZUGFeRD version\n" - + " [--zugferd-profile <...>]: set ZUGFeRD profile\n" + + " [--format ]: set ZUGFeRD or FacturX\n" + + " [--version <1|2>]: set ZUGFeRD version\n" + + " [--profile <...>]: set ZUGFeRD profile\n" + " For ZUGFeRD v1: ASIC, OMFORT or XTENDED\n" + " For ZUGFeRD v2: INIMUM, BASIC L, ASIC, IUS, N16931, ETENDED "; } @@ -102,8 +103,9 @@ public class Toecount { + "\t\t[--source ]: set input PDF file\r\n" + "\t\t[--source-xml ]: set input XML file\r\n" + "\t\t[--out ]: set output PDF file\r\n" - + "\t\t[--zugferd-version <1|2>]: set ZUGFeRD version\r\n" - + "\t\t[--zugferd-profile <...>]: set ZUGFeRD profile\r\n" + + "\t\t[--format ]: enable factur-x or ZUGFeRD\r\n" + + "\t\t[--version <1|2>]: set ZUGFeRD version\r\n" + + "\t\t[--profile <...>]: set ZUGFeRD profile\r\n" + "\t\t\tFor ZUGFeRD v1: ASIC, OMFORT or XTENDED\r\n" + "\t\t\tFor ZUGFeRD v2: INIMUM, BASIC L, ASIC, IUS, N16931, ETENDED\r\n"); } @@ -264,12 +266,13 @@ public class Toecount { // (--source: input PDF file) // (--source-xml: input XML file) // (--out: output PDF file) - // (--zugferd-version: ZUGFeRD version) - // (--zugferd-profile: ZUGFeRD profile) + // (--version: ZUGFeRD version) + // (--profile: ZUGFeRD profile) Option combineOption = parser.addBooleanOption('c', "combine"); Option sourceXmlOption = parser.addStringOption("source-xml"); - Option zugferdVersionOption = parser.addStringOption("zugferd-version"); - Option zugferdProfileOption = parser.addStringOption("zugferd-profile"); + Option formatOption = parser.addStringOption('f', "format"); + Option zugferdVersionOption = parser.addStringOption("version"); + Option zugferdProfileOption = parser.addStringOption("profile"); // Command: Show metrics in dir // --directory @@ -301,6 +304,7 @@ public class Toecount { String sourceName = parser.getOptionValue(sourceOption); String sourceXMLName = parser.getOptionValue(sourceXmlOption); String outName = parser.getOptionValue(outOption); + String format = parser.getOptionValue(formatOption); String zugferdVersion = parser.getOptionValue(zugferdVersionOption); String zugferdProfile = parser.getOptionValue(zugferdProfileOption); @@ -309,7 +313,7 @@ public class Toecount { } else if (((directoryName != null) && (directoryName.length() > 0)) || filesFromStdIn.booleanValue()) { performMetrics(directoryName, filesFromStdIn, ignoreFileExt); } else if (combineRequested) { - performCombine(sourceName, sourceXMLName, outName, zugferdVersion, zugferdProfile); + performCombine(sourceName, sourceXMLName, outName, format, zugferdVersion, zugferdProfile); } else if (extractRequested) { performExtract(sourceName, outName); } else if (a3only) { @@ -417,7 +421,7 @@ public class Toecount { } } - private static void performCombine(String pdfName, String xmlName, String outName, String zfVersion, + private static void performCombine(String pdfName, String xmlName, String outName, String format, String zfVersion, String zfProfile) throws Exception { /* * ZUGFeRDExporter ze= new ZUGFeRDExporterFromA1Factory() @@ -425,7 +429,7 @@ public class Toecount { * .loadFromPDFA1("invoice.pdf"); */ try { - int zfIntVersion = 1; + int zfIntVersion = ZUGFeRDExporter.DefaultZUGFeRDVersion; ZUGFeRDConformanceLevel zfConformanceLevelProfile = ZUGFeRDConformanceLevel.EXTENDED; if (pdfName == null) { @@ -446,27 +450,38 @@ public class Toecount { System.out.println("Ouput PDF set to " + outName); } - if (zfVersion == null) { + if (format == null) { try { - zfVersion = getStringFromUser("ZUGFeRD version (1 or 2)", "1", "1|2"); + format = getStringFromUser("Format (fx=Factur-X, zf=ZUGFeRD,)", "zf", "fx|zf"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { - System.out.println("ZUGFeRD version set to " + zfVersion); + System.out.println("Format set to " + format); } + + if (zfVersion == null) { + try { + zfVersion = getStringFromUser("Version (1 or 2)", "1", "1|2"); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } else { + System.out.println("Version set to " + zfVersion); + } zfIntVersion = Integer.valueOf(zfVersion); if (zfProfile == null) { try { - if (zfIntVersion == 1) { - zfProfile = getStringFromUser("ZUGFeRD profile b)asic, c)omfort or e)xtended", "e", + if (format.equals("zf")&&(zfIntVersion == 1)) { + zfProfile = getStringFromUser("Profile b)asic, c)omfort or e)xtended", "e", "B|b|C|c|E|e"); } else { zfProfile = getStringFromUser( - "ZUGFeRD 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", "M|m|W|w|B|b|C|c|E|e|X|x|"); } } catch (Exception e) { @@ -474,7 +489,7 @@ public class Toecount { e.printStackTrace(); } } else { - System.out.println("ZUGFeRD profile set to " + zfProfile); + System.out.println("Profile set to " + zfProfile); } zfProfile = zfProfile.toLowerCase(); @@ -482,8 +497,12 @@ public class Toecount { ensureFileExists(pdfName); ensureFileExists(xmlName); ensureFileNotExists(outName); + + if ((format.equals("fx"))&&(zfIntVersion>1)) { + throw new Exception("Factur-X is only available in version 1 (roughly corresponding to ZF2)"); + } - if (zfIntVersion == 1) { + if ((format.equals("zf"))&&(zfIntVersion == 1)) { if (zfProfile.equals("b")) { zfConformanceLevelProfile = ZUGFeRDConformanceLevel.BASIC; } else if (zfProfile.equals("c")) { @@ -493,7 +512,7 @@ public class Toecount { } else { throw new Exception(String.format("Unknown ZUGFeRD profile '%s'", zfProfile)); } - } else if (zfIntVersion == 2) { + } else if (((format.equals("zf"))&&(zfIntVersion == 2))||(format.equals("fx"))) { if (zfProfile.equals("m")) { zfConformanceLevelProfile = ZUGFeRDConformanceLevel.MINIMUM; } else if (zfProfile.equals("w")) { @@ -510,7 +529,7 @@ public class Toecount { throw new Exception(String.format("Unknown ZUGFeRD profile '%s'", zfProfile)); } } else { - throw new Exception(String.format("Unknown ZUGFeRD version '%i'", zfIntVersion)); + throw new Exception(String.format("Unknown version '%i'", zfIntVersion)); } // All params are good! continue... @@ -519,6 +538,10 @@ public class Toecount { .load(pdfName); ze.setZUGFeRDVersion(zfIntVersion); + if (format.equals("fx")) { + ze.setFacturX(); + } + ze.setZUGFeRDXMLData(Files.readAllBytes(Paths.get(xmlName))); diff --git a/src/test/resources/migration/input/ZUGFeRD1_COMFORT_Einfach.xml b/src/test/resources/migration/input/ZUGFeRD1_COMFORT_Einfach.xml new file mode 100644 index 00000000..db6672dd --- /dev/null +++ b/src/test/resources/migration/input/ZUGFeRD1_COMFORT_Einfach.xml @@ -0,0 +1,216 @@ + + + + + true + + urn:ferd:CrossIndustryDocument:invoice:1p0:comfort + + + + 471102 + RECHNUNG + 380 + 20130305 + + Rechnung gemäß Bestellung vom 01.03.2013. + + + Lieferant GmbH +Lieferantenstraße 20 +80333 München +Deutschland +Geschäftsführer: Hans Muster +Handelsregisternummer: H A 123 + +REG + + + + + + 4000001123452 + Lieferant GmbH + + 80333 + Lieferantenstraße 20 + München + DE + + + 201/113/40209 + + + DE123456789 + + + + GE2020211 + 4000001987658 + Kunden AG Mitte + + Hans Muster + + + 69876 + Kundenstraße 15 + Frankfurt + DE + + + + + + 20130305 + + + + 2013-471102 + EUR + + 31 + Überweisung + + DE08700901001234567890 + + + GENODEF1M04 + + + + 19.25 + VAT + 275.00 + S + 7.00 + + + 37.62 + VAT + 198.00 + S + 19.00 + + + Zahlbar innerhalb 30 Tagen netto bis 04.04.2013, 3% Skonto innerhalb 10 Tagen bis 15.03.2013 + 20130404 + + + 473.00 + 0.00 + 0.00 + 473.00 + 56.87 + 529.87 + 0.00 + 529.87 + + + + + 1 + + + + 9.9000 + + + 9.9000 + + + + 20.0000 + + + + VAT + S + 19.00 + + + 198.00 + + + + 4012345001235 + TB100A4 + Trennblätter A4 + + + + + 2 + + + + 5.5000 + + + 5.5000 + + + + 50.0000 + + + + VAT + S + 7.00 + + + 275.00 + + + + 4000050986428 + ARNR2 + Joghurt Banane + + + + \ No newline at end of file diff --git a/src/test/resources/migration/input/ZUGFeRD1_EXTENDED_Warenrechnung.xml b/src/test/resources/migration/input/ZUGFeRD1_EXTENDED_Warenrechnung.xml new file mode 100644 index 00000000..0f26d3ea --- /dev/null +++ b/src/test/resources/migration/input/ZUGFeRD1_EXTENDED_Warenrechnung.xml @@ -0,0 +1,520 @@ + + + + + + true + + urn:ferd:CrossIndustryDocument:invoice:1p0:extended + + + + R87654321012345 + WARENRECHNUNG + 380 + + 20130806 + + + ST3 + Es bestehen Rabatt- oder Bonusvereinbarungen. + AAK + + + EEV + Der Verkäufer bleibt Eigentümer der Waren bis zu vollständigen Erfüllung der Kaufpreisforderung. + AAJ + + + MUSTERLIEFERANT GMBH +BAHNHOFSTRASSE 99 +99199 MUSTERHAUSEN +Geschäftsführung: +Max Mustermann +USt-IdNr: DE123456789 +Telefon: +49 932 431 0 +www.musterlieferant.de +HRB Nr. 372876 +Amtsgericht Musterstadt +GLN 4304171000002 +WEEE-Reg-Nr.: DE87654321 + REG + + + Leergutwert: 46,50 + + + + + + 549910 + 4333741000005 + MUSTERLIEFERANT GMBH + + + +49 932 431 500 + + + max.mustermann@musterlieferant.de + + + + 99199 + BAHNHOFSTRASSE 99 + MUSTERHAUSEN + DE + + + DE123456789 + + + + 009420 + 4304171000002 + MUSTER-KUNDE GMBH + + 40235 + KUNDENWEG 88 + DUESSELDORF + DE + + + + 2013-08-01T00:00:00 + B123456789 + + + 2013-08-02T00:00:00 + VN + A456123 + + + + + 4304171088093 + MUSTER-MARKT + + 8211 + + + 31157 + HAUPTSTRASSE 44 + SARSTEDT + DE + + + + + 20130805 + + + + 2013-08-05T00:00:00 + L87654321012345 + + + + EUR + + 009420 + 4304171000002 + MUSTER-KUNDE GMBH + + 40235 + KUNDENWEG 88 + DUESSELDORF + DE + + + + 61.07 + VAT + 321.40 + 326.50 + -5.10 + S + 19.00 + + + 8.93 + VAT + 127.59 + 130.70 + -3.11 + S + 7.00 + + + false + 2.00 + 280.00 + 5.60 + Rechnungsrabatt 1 + + VAT + S + 19.00 + + + + false + 2.00 + 130.70 + 2.61 + Rechnungsrabatt 1 + + VAT + S + 7.00 + + + + false + 280.00 + 2.50 + Rechnungsrabatt 2 + + VAT + S + 19.00 + + + + false + 130.70 + 0.50 + Rechnungsrabatt 2 + + VAT + S + 7.00 + + + + Transportkosten + 3.00 + + VAT + S + 19.00 + + + + Bei Zahlung innerhalb 14 Tagen gewähren wir 2,0% Skonto. + + 14 + 2.00 + + + + 457.20 + 3.00 + 11.21 + 448.99 + 70.00 + 518.99 + 0.00 + 518.99 + + + + + + Wichtige Information: Bei Bestellungen bis zum 19.12. ist die Auslieferung bis spätestens 23.12. garantiert. + + + + + + + + + 1.0000 + + + 1.0000 + + + + 100.0000 + 4.0000 + + + + VAT + S + 19.00 + + + 100.00 + + + + 4123456000014 + ZS997 + Zitronensäure 100ml + + PACKAGING_TYPE + Verpackungsart + BO + + + + + + + + 1.5000 + + false + 2.00 + 1.5000 + 0.0300 + Artikelrabatt 1 + + + false + 1 + 0.0200 + Artikelrabatt 2 + + + + 1.4500 + + + + 50.0000 + 1.0000 + + + + VAT + S + 7.00 + + + 72.50 + + + + 4123456000021 + GZ250 + Gelierzucker Extra 250g + + + + + + + 0.0000 + + + 0.0000 + + + + 10.0000 + 1.0000 + + + + VAT + S + 7.00 + + + 0.00 + + + + 4123456000021 + GZ250 + Gelierzucker Extra 250g + Artikel wie vereinbart ohne Berechnung + + + + + + Öko-Kontroll-Nr.: DE-BW-006-987654321054 + AAY + + + + + 12.0000 + + + 12.0000 + + + + 15.0000 + 20.0000 + + + + VAT + S + 19.00 + + + 180.00 + + + + 4100130013294 + 2031 + K4321 + Bierbrau Pils 20/0500 + EAN-VKE: 4100130913297 + + PACKAGING_MATERIAL + Verpackung + Kiste + + + + + + + + 3.1000 + + + 3.1000 + + + + 15.0000 + 1.0000 + + + + VAT + S + 19.00 + + + 46.50 + + + + 2001015001325 + 1805 + K4322 + Leergutpfand 20 x 0,5l + + PACKAGING_MATERIAL + Verpackung + unverpackt + + + + + + + + 30.0000 + + false + 3.00 + 30.0000 + 0.9000 + Artikelrabatt 1 + + + + 29.1000 + + + + 2.0000 + 1.0000 + + + + VAT + S + 7.00 + + + 58.20 + + + + 4123456000038 + MP107 + Mischpalette Joghurt Karton 3 x 20 + + PACKAGING_MATERIAL + Verpackung + Karton + + + 4123456001035 + JOG103 + Erdbeer 20 x 150g Becher + 20.0000 + + + 4123456002032 + JOG203 + Banane 20 x 150g Becher + 20.0000 + + + 4123456003039 + JOG303 + Schoko 20 x 150g Becher + 20.0000 + + + + + diff --git a/src/test/resources/migration/reference/ZUGFeRD2-invoice-adjusted.xml b/src/test/resources/migration/reference/ZUGFeRD2-invoice-adjusted.xml new file mode 100644 index 00000000..bb9ba7a4 --- /dev/null +++ b/src/test/resources/migration/reference/ZUGFeRD2-invoice-adjusted.xml @@ -0,0 +1,219 @@ + + + + + false + + + urn:ferd:CrossIndustryDocument:invoice:1p0:extended + + + + RE-20170509/506 + RECHNUNG2 + 380 + + 20170510 + + + + + + 1 + + + Künstlerische Gestaltung (Stunde): Einer weiteren Beispielrechnung + + + + + 160.0000 + 1.0000 + + + 160.0000 + 1.0000 + + + + 1.0000 + + + + VAT + S + 7.00 + + + 160.00 + + + + + + 2 + + + Luftballon: Bunt, ca. 500ml + + + + + 0.7900 + 1.0000 + + + 0.7900 + 1.0000 + + + + 400.0000 + + + + VAT + S + 19.00 + + + 316.00 + + + + + + 3 + + + Heiße Luft pro Liter + + + + + 0.1000 + 1.0000 + + + 0.1000 + 1.0000 + + + + 200.0000 + + + + VAT + S + 19.00 + + + 20.00 + + + + + + Bei Spiel GmbH + + 12345 + Ecke 12 + Stadthausen + DE + + + 22/815/0815/4 + + + DE136695976 + + + + Theodor Est + + 88802 + Bahnstr. 42 + Spielkreis + DE + + + DE999999999 + + + + + + + 20170507 + + + + + RE-20170509/505 + EUR + + 42 + Überweisung + + DE88 2008 0000 0970 3757 00 + 44421800 + + + COBADEFFXXX + 41441604 + Commerzbank + + + + 11.20 + VAT + 160.00 + S + 7.00 + + + 63.84 + VAT + 336.00 + S + 19.00 + + + Zahlbar ohne Abzug bis zum 30.05.2017 + + 20170530 + + + + 496.00 + 0.00 + 0.00 + 496.00 + 75.04 + 571.04 + 571.04 + + + + diff --git a/src/test/resources/migration/reference/ZUGFeRD2-invoice.xml b/src/test/resources/migration/reference/ZUGFeRD2-invoice.xml index b0a390e8..cbaf1829 100644 --- a/src/test/resources/migration/reference/ZUGFeRD2-invoice.xml +++ b/src/test/resources/migration/reference/ZUGFeRD2-invoice.xml @@ -28,7 +28,7 @@ urn:ferd:CrossIndustryDocument:invoice:1p0:extended - + RE-20170509/505 RECHNUNG 380 @@ -36,7 +36,7 @@ 20170509 - + 1 diff --git a/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml b/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml new file mode 100644 index 00000000..250b7565 --- /dev/null +++ b/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml @@ -0,0 +1,229 @@ + + + + + true + + + + urn:ferd:CrossIndustryDocument:invoice:1p0:comfort + + + + 471102 + RECHNUNG + 380 + + 20130305 + + + Rechnung gemäß Bestellung vom 01.03.2013. + + + Lieferant GmbH +Lieferantenstraße 20 +80333 München +Deutschland +Geschäftsführer: Hans Muster +Handelsregisternummer: H A 123 + + REG + + + + + + 1 + + + 4012345001235 + TB100A4 + Trennblätter A4 + + + + 9.9000 + + + 9.9000 + + + + 20.0000 + + + + VAT + S + 19.00 + + + 198.00 + + + + + + 2 + + + 4000050986428 + ARNR2 + Joghurt Banane + + + + 5.5000 + + + 5.5000 + + + + 50.0000 + + + + VAT + S + 7.00 + + + 275.00 + + + + + + 4000001123452 + Lieferant GmbH + + 80333 + Lieferantenstraße 20 + München + DE + + + 201/113/40209 + + + DE123456789 + + + + GE2020211 + 4000001987658 + Kunden AG Mitte + + Hans Muster + + + 69876 + Kundenstraße 15 + Frankfurt + DE + + + + + + + 20130305 + + + + + 2013-471102 + EUR + + 31 + Überweisung + + DE08700901001234567890 + + + GENODEF1M04 + + + + 19.25 + VAT + 275.00 + S + 7.00 + + + 37.62 + VAT + 198.00 + S + 19.00 + + + Zahlbar innerhalb 30 Tagen netto bis 04.04.2013, 3% Skonto innerhalb 10 Tagen bis 15.03.2013 + + 20130404 + + + + 473.00 + 0.00 + 0.00 + 473.00 + 56.87 + 529.87 + 0.00 + 529.87 + + + + diff --git a/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml b/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml new file mode 100644 index 00000000..44468bdd --- /dev/null +++ b/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml @@ -0,0 +1,546 @@ + + + + + true + + + + urn:ferd:CrossIndustryDocument:invoice:1p0:extended + + + + R87654321012345 + WARENRECHNUNG + 380 + + 20130806 + + + ST3 + Es bestehen Rabatt- oder Bonusvereinbarungen. + AAK + + + EEV + Der Verkäufer bleibt Eigentümer der Waren bis zu vollständigen Erfüllung der Kaufpreisforderung. + AAJ + + + MUSTERLIEFERANT GMBH +BAHNHOFSTRASSE 99 +99199 MUSTERHAUSEN +Geschäftsführung: +Max Mustermann +USt-IdNr: DE123456789 +Telefon: +49 932 431 0 +www.musterlieferant.de +HRB Nr. 372876 +Amtsgericht Musterstadt +GLN 4304171000002 +WEEE-Reg-Nr.: DE87654321 + REG + + + Leergutwert: 46,50 + + + + + + + Wichtige Information: Bei Bestellungen bis zum 19.12. ist die Auslieferung bis spätestens 23.12. garantiert. + + + + + + + + 4123456000014 + ZS997 + Zitronensäure 100ml + + PACKAGING_TYPE + Verpackungsart + BO + + + + + 1.0000 + + + 1.0000 + + + + 100.0000 + 4.0000 + + + + VAT + S + 19.00 + + + 100.00 + + + + + + + 4123456000021 + GZ250 + Gelierzucker Extra 250g + + + + 1.5000 + + + false + + 2.00 + 1.5000 + 0.0300 + Artikelrabatt 1 + + + + false + + 1 + 0.0200 + Artikelrabatt 2 + + + + 1.4500 + + + + 50.0000 + 1.0000 + + + + VAT + S + 7.00 + + + 72.50 + + + + + + + 4123456000021 + GZ250 + Gelierzucker Extra 250g + Artikel wie vereinbart ohne Berechnung + + + + 0.0000 + + + 0.0000 + + + + 10.0000 + 1.0000 + + + + VAT + S + 7.00 + + + 0.00 + + + + + + + Öko-Kontroll-Nr.: DE-BW-006-987654321054 + AAY + + + + 4100130013294 + 2031 + K4321 + Bierbrau Pils 20/0500 + EAN-VKE: 4100130913297 + + PACKAGING_MATERIAL + Verpackung + Kiste + + + + + 12.0000 + + + 12.0000 + + + + 15.0000 + 20.0000 + + + + VAT + S + 19.00 + + + 180.00 + + + + + + + 2001015001325 + 1805 + K4322 + Leergutpfand 20 x 0,5l + + PACKAGING_MATERIAL + Verpackung + unverpackt + + + + + 3.1000 + + + 3.1000 + + + + 15.0000 + 1.0000 + + + + VAT + S + 19.00 + + + 46.50 + + + + + + + 4123456000038 + MP107 + Mischpalette Joghurt Karton 3 x 20 + + PACKAGING_MATERIAL + Verpackung + Karton + + + 4123456001035 + JOG103 + Erdbeer 20 x 150g Becher + 20.0000 + + + 4123456002032 + JOG203 + Banane 20 x 150g Becher + 20.0000 + + + 4123456003039 + JOG303 + Schoko 20 x 150g Becher + 20.0000 + + + + + 30.0000 + + + false + + 3.00 + 30.0000 + 0.9000 + Artikelrabatt 1 + + + + 29.1000 + + + + 2.0000 + 1.0000 + + + + VAT + S + 7.00 + + + 58.20 + + + + + + 549910 + 4333741000005 + MUSTERLIEFERANT GMBH + + + +49 932 431 500 + + + max.mustermann@musterlieferant.de + + + + 99199 + BAHNHOFSTRASSE 99 + MUSTERHAUSEN + DE + + + DE123456789 + + + + 009420 + 4304171000002 + MUSTER-KUNDE GMBH + + 40235 + KUNDENWEG 88 + DUESSELDORF + DE + + + + B123456789 + + 2013-08-01T00:00:00 + + + + A456123 + VN + + 2013-08-02T00:00:00 + + + + + + 4304171088093 + MUSTER-MARKT + + 8211 + + + 31157 + HAUPTSTRASSE 44 + SARSTEDT + DE + + + + + 20130805 + + + + L87654321012345 + + 2013-08-05T00:00:00 + + + + + EUR + + 009420 + 4304171000002 + MUSTER-KUNDE GMBH + + 40235 + KUNDENWEG 88 + DUESSELDORF + DE + + + + 61.07 + VAT + 321.40 + 326.50 + -5.10 + S + 19.00 + + + 8.93 + VAT + 127.59 + 130.70 + -3.11 + S + 7.00 + + + + false + + 2.00 + 280.00 + 5.60 + Rechnungsrabatt 1 + + VAT + S + 19.00 + + + + + false + + 2.00 + 130.70 + 2.61 + Rechnungsrabatt 1 + + VAT + S + 7.00 + + + + + false + + 280.00 + 2.50 + Rechnungsrabatt 2 + + VAT + S + 19.00 + + + + + false + + 130.70 + 0.50 + Rechnungsrabatt 2 + + VAT + S + 7.00 + + + + Transportkosten + 3.00 + + VAT + S + 19.00 + + + + Bei Zahlung innerhalb 14 Tagen gewähren wir 2,0% Skonto. + + 14 + 2.00 + + + + 457.20 + 3.00 + 11.21 + 448.99 + 70.00 + 518.99 + 0.00 + 518.99 + + + + From b203d427a60433257315b29bf1c1b915df7875b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Wed, 1 May 2019 08:14:12 +0200 Subject: [PATCH 07/82] also migrate profiles --- History.md | 10 ++++++++++ .../org/mustangproject/ZUGFeRD/ZUGFeRDMigrator.java | 6 ++++++ .../migration/reference/ZUGFeRD2-invoice-adjusted.xml | 2 +- .../resources/migration/reference/ZUGFeRD2-invoice.xml | 2 +- .../migration/reference/ZUGFeRD2_COMFORT_Einfach.xml | 2 +- .../reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml | 2 +- 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/History.md b/History.md index 42272163..02233be3 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,13 @@ +signatur mustangproject wird nicht erkannt +fx option in kommandozeile fehlt + +java -jar ZUV-0.7.0c-SNAPSHOT.jar --action validate -x /Users/jstaerk/workspace/mustangproject/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml +errors + + +java -jar ZUV-0.7.0c-SNAPSHOT.jar --action validate -x /Users/jstaerk/workspace/mustangproject/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml +nullpointerex + 1.6.0 ===== 2019-02-03 diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDMigrator.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDMigrator.java index bdc78ea3..83d67468 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDMigrator.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDMigrator.java @@ -67,6 +67,12 @@ public class ZUGFeRDMigrator { String res = null; res = baos.toString("UTF-8"); + //migrate the profiles + + res=res.replace("urn:ferd:CrossIndustryDocument:invoice:1p0:basic", "urn:cen.eu:en16931:2017#compliant#urn:zugferd.de:2p0:basic"); + res=res.replace("urn:ferd:CrossIndustryDocument:invoice:1p0:comfort", "urn:cen.eu:en16931:2017"); + res=res.replace("urn:ferd:CrossIndustryDocument:invoice:1p0:extended", "urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended"); + //somehow the XML parser seems to insert erreneous XML namespaces, depending on which one it is, saxon seems to be cleaner. //nevertheless, remove them manually res=res.replace("", ""); diff --git a/src/test/resources/migration/reference/ZUGFeRD2-invoice-adjusted.xml b/src/test/resources/migration/reference/ZUGFeRD2-invoice-adjusted.xml index bb9ba7a4..d0c2bf92 100644 --- a/src/test/resources/migration/reference/ZUGFeRD2-invoice-adjusted.xml +++ b/src/test/resources/migration/reference/ZUGFeRD2-invoice-adjusted.xml @@ -25,7 +25,7 @@ Migrated by Mustangproject XSLT false - urn:ferd:CrossIndustryDocument:invoice:1p0:extended + urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended diff --git a/src/test/resources/migration/reference/ZUGFeRD2-invoice.xml b/src/test/resources/migration/reference/ZUGFeRD2-invoice.xml index cbaf1829..9502a57d 100644 --- a/src/test/resources/migration/reference/ZUGFeRD2-invoice.xml +++ b/src/test/resources/migration/reference/ZUGFeRD2-invoice.xml @@ -25,7 +25,7 @@ false - urn:ferd:CrossIndustryDocument:invoice:1p0:extended + urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended diff --git a/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml b/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml index 250b7565..86566c1b 100644 --- a/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml +++ b/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml @@ -55,7 +55,7 @@ Migrated by Mustangproject XSLT - urn:ferd:CrossIndustryDocument:invoice:1p0:comfort + urn:cen.eu:en16931:2017 diff --git a/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml b/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml index 44468bdd..ad6d4ca5 100644 --- a/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml +++ b/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml @@ -55,7 +55,7 @@ Migrated by Mustangproject XSLT - urn:ferd:CrossIndustryDocument:invoice:1p0:extended + urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended From 6fb5e4c532fac8e0e8b996452bb8e7cf65ed724c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 5 May 2019 14:30:36 +0200 Subject: [PATCH 08/82] preparing release --- History.md | 14 ++++++++------ pom.xml | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/History.md b/History.md index 02233be3..d47dd4d5 100644 --- a/History.md +++ b/History.md @@ -1,12 +1,14 @@ -signatur mustangproject wird nicht erkannt -fx option in kommandozeile fehlt -java -jar ZUV-0.7.0c-SNAPSHOT.jar --action validate -x /Users/jstaerk/workspace/mustangproject/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml -errors +1.7.0 +===== +2019-05-05 +Export ZF2 final now seems halfway valid (new filename, new namespace prefixa) +Migrates profile names in ZF1 to ZF2 migration +Nullpointerex solved with certain invalid profiles +Be able to access additional files ("additional data") +Known bugs: src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml is invalid -java -jar ZUV-0.7.0c-SNAPSHOT.jar --action validate -x /Users/jstaerk/workspace/mustangproject/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml -nullpointerex 1.6.0 ===== diff --git a/pom.xml b/pom.xml index 8f16a2dc..6fc91321 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.6.2-SNAPSHOT + 1.7.0-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs From 3c5d4525281f077d8e78f76762ea327b5beb55cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 5 May 2019 14:31:21 +0200 Subject: [PATCH 09/82] [maven-release-plugin] prepare release mustang-1.7.0 --- pom.xml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 6fc91321..e488390a 100644 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,9 @@ - + 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.0-SNAPSHOT + 1.7.0 jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -14,7 +13,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - mustang-1.5.2 + mustang-1.7.0 @@ -198,8 +197,7 @@ 2.4.3 - + org.mustangproject.toecount.Toecount From 8af62febb1dff03f100c29b1a442b0d465515545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 5 May 2019 14:31:28 +0200 Subject: [PATCH 10/82] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e488390a..a738b8e1 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.0 + 1.7.1-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -13,7 +13,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - mustang-1.7.0 + mustang-1.5.2 From d2e54824a6add4c60a7ac4b1b2fd694f4e0d66fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 12 May 2019 07:26:43 +0200 Subject: [PATCH 11/82] no message --- .../java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java | 2 +- .../org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index cb0b8c69..f898ad0f 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -194,7 +194,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { + " \n" //$NON-NLS-1$ // + " "+testBooleanStr+"\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " urn:cen.eu:en16931:2017:compliant:factur-x.eu:1p0:en16931\n" //$NON-NLS-1$ + + " urn:cen.eu:en16931:2017\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index 73b8a2c8..fef3a66a 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -363,7 +363,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { // check for pdf-a schema extension assertFalse(pdfContent.indexOf("EN 16931") == -1); assertFalse(pdfContent.indexOf("fx") == -1); - assertFalse(pdfContent.indexOf("urn:cen.eu:en16931:2017:compliant:factur-x.eu:1p0:en16931") == -1); + assertFalse(pdfContent.indexOf("urn:cen.eu:en16931:2017") == -1); } // now check the contents (like MustangReaderTest) From b5905e0ea06af2d67dc5f5f5c65b8d5e78dc932c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 26 May 2019 13:26:33 +0200 Subject: [PATCH 12/82] no message --- History.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/History.md b/History.md index d47dd4d5..960ca8cc 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,10 @@ +1.7.1 +===== +2019-05-26 + +Corrected EN16931 ZF2 profile name + 1.7.0 ===== 2019-05-05 From 813e1af4c02cbdb16f34ba067638ff3fb16e4632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 26 May 2019 13:29:20 +0200 Subject: [PATCH 13/82] [maven-release-plugin] prepare release mustang-1.7.1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a738b8e1..398535c9 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.1-SNAPSHOT + 1.7.1 jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -13,7 +13,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - mustang-1.5.2 + mustang-1.7.1 From f5cabc5eae4cc7629a21e05825c6654253f4ac40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 26 May 2019 13:29:27 +0200 Subject: [PATCH 14/82] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 398535c9..2cd5f02c 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.1 + 1.7.2-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -13,7 +13,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - mustang-1.7.1 + mustang-1.5.2 From 71e9e73ba65c639468b10d371a5033f85f3f3633 Mon Sep 17 00:00:00 2001 From: Jochen Staerk Date: Sat, 1 Jun 2019 09:40:35 +0200 Subject: [PATCH 15/82] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d38d0088..bc41c36f 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ As dependency use this org.mustangproject.ZUGFeRD mustang - 1.5.4 + 1.7.1 From d5122364dc6e844560407ab2954cd60870f9cde9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 9 Jun 2019 15:51:51 +0200 Subject: [PATCH 16/82] support reference, seller DefinedTradeContact attributes --- .../ZUGFeRD/IProfileProvider.java | 25 ++ .../ZUGFeRD/IZUGFeRDExportableContact.java | 28 +- .../IZUGFeRDExportableTransaction.java | 9 + .../ZUGFeRD/ZUGFeRD2PullProvider.java | 380 ++++++++++-------- .../ZUGFeRD/ZUGFeRDImporter.java | 7 + .../ZUGFeRD/MustangReaderTestCase.java | 23 +- .../ZUGFeRD/MustangReaderWriterEdgeTest.java | 12 +- .../ZUGFeRD/MustangReaderWriterTest.java | 11 +- 8 files changed, 318 insertions(+), 177 deletions(-) create mode 100644 src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java new file mode 100644 index 00000000..adc695df --- /dev/null +++ b/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java @@ -0,0 +1,25 @@ +/** ********************************************************************** + * + * 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; + +public interface IProfileProvider { + + public String getProfile(); + +} diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableContact.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableContact.java index 125852c8..7b7e1c89 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableContact.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableContact.java @@ -46,13 +46,23 @@ public interface IZUGFeRDExportableContact { */ String getName(); + default String getPhone() { + return null; + } + + default String getEMail() { + return null; + } + /** * Postal code of the recipient * * @return Postal code of the recipient */ - String getZIP(); + default String getZIP() { + return null; + } /** @@ -60,7 +70,9 @@ public interface IZUGFeRDExportableContact { * * @return VAT ID (Umsatzsteueridentifikationsnummer) of the contact */ - String getVATID(); + default String getVATID() { + return null; + } /** @@ -68,7 +80,9 @@ public interface IZUGFeRDExportableContact { * * @return two-letter iso country code of the contact */ - String getCountry(); + default String getCountry() { + return null; + } /** @@ -76,7 +90,9 @@ public interface IZUGFeRDExportableContact { * * @return Returns the city of the recipient */ - String getLocation(); + default String getLocation() { + return null; + } /** @@ -84,6 +100,8 @@ public interface IZUGFeRDExportableContact { * * @return street address (street+number) of the contact */ - String getStreet(); + default String getStreet() { + return null; + } } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java index 112080ec..6addf89f 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java @@ -83,6 +83,15 @@ public interface IZUGFeRDExportableTransaction { return null; } + /** + * who processed the order + * + * @return the contact person at the supplier side + */ + default IZUGFeRDExportableContact getOwnContact() { + return null; + } + IZUGFeRDAllowanceCharge[] getZFAllowances(); diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index f898ad0f..a1d4a842 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -26,7 +26,7 @@ import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.HashMap; -public class ZUGFeRD2PullProvider implements IXMLProvider { +public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { private class LineCalc { private BigDecimal totalGross; @@ -34,10 +34,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { private BigDecimal itemTotalVATAmount; public LineCalc(IZUGFeRDExportableItem currentItem) { - BigDecimal multiplicator = currentItem.getProduct().getVATPercent().divide(new BigDecimal(100)).add(new BigDecimal(1)); -// priceGross=currentItem.getPrice().multiply(multiplicator); + BigDecimal multiplicator = currentItem.getProduct().getVATPercent().divide(new BigDecimal(100)) + .add(new BigDecimal(1)); + // priceGross=currentItem.getPrice().multiply(multiplicator); totalGross = currentItem.getPrice().multiply(multiplicator).multiply(currentItem.getQuantity()); - itemTotalNetAmount = currentItem.getQuantity().multiply(currentItem.getPrice()).setScale(2, BigDecimal.ROUND_HALF_UP); + itemTotalNetAmount = currentItem.getQuantity().multiply(currentItem.getPrice()).setScale(2, + BigDecimal.ROUND_HALF_UP); itemTotalVATAmount = totalGross.subtract(itemTotalNetAmount); } @@ -51,7 +53,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { } - //// MAIN CLASS protected byte[] zugferdData; @@ -60,23 +61,23 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { /** * enables the flag to indicate a test invoice in the XML structure */ - public void setTest() {} + public void setTest() { + } private String 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(' '); + * 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 + * 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), @@ -89,7 +90,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { * * 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 + 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'); @@ -142,10 +145,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { } /** - * 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 + * 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 * * @return which taxes have been used with which amounts in this invoice */ @@ -155,7 +157,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { BigDecimal percent = currentItem.getProduct().getVATPercent(); LineCalc lc = new LineCalc(currentItem); - VATAmount itemVATAmount = new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount(), trans.getDocumentCode()); + VATAmount itemVATAmount = new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount(), + trans.getDocumentCode()); VATAmount current = hm.get(percent); if (current == null) { hm.put(percent, itemVATAmount); @@ -166,6 +169,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { return hm; } + public String getProfile() { + return "urn:cen.eu:en16931:2017"; + } @Override public void generateXML(IZUGFeRDExportableTransaction trans) { @@ -174,47 +180,50 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); //$NON-NLS-1$ String senderReg = ""; if (trans.getOwnOrganisationFullPlaintextInfo() != null) { - senderReg = "" - + "\n" - + " \n" - + trans.getOwnOrganisationFullPlaintextInfo() - + " \n" - + "REG\n" - + "\n"; + senderReg = "" + "\n" + " \n" + + trans.getOwnOrganisationFullPlaintextInfo() + " \n" + + "REG\n" + "\n"; } - String xml = "\n" //$NON-NLS-1$ + "\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ -// + " "+testBooleanStr+"\n" //$NON-NLS-1$ + // + " + // "+testBooleanStr+"\n" + // //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " urn:cen.eu:en16931:2017\n" //$NON-NLS-1$ + + " " + getProfile() + "\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " " + trans.getNumber() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ -// + " RECHNUNG\n" //$NON-NLS-1$ + // + " RECHNUNG\n" //$NON-NLS-1$ + " 380\n" //$NON-NLS-1$ - + " " + zugferdDateFormat.format(trans.getIssueDate()) + "\n" //date format was 20130605 //$NON-NLS-1$ //$NON-NLS-2$ + + " " //$NON-NLS-1$ + + zugferdDateFormat.format(trans.getIssueDate()) + "\n" // date //$NON-NLS-1$ + // format + // was + // 20130605 + senderReg -// + " \n" -// + " \n" -// + "Rechnung gemäß Bestellung Nr. 2013-471331 vom 01.03.2013.\n" -// + "\n" -// + " \n" -// + " \n" -// + " \n" -// + " \n" -// + "Es bestehen Rabatt- und Bonusvereinbarungen.\n" -// + " \n" -// + " AAK\n" -// + " \n" + // + " \n" + // + " \n" + // + "Rechnung gemäß Bestellung Nr. 2013-471331 vom 01.03.2013.\n" + // + "\n" + // + " \n" + // + " \n" + // + " \n" + // + " \n" + // + "Es bestehen Rabatt- und Bonusvereinbarungen.\n" + // + " \n" + // + " AAK\n" + // + " \n" + " \n" //$NON-NLS-1$ + " \n"; //$NON-NLS-1$ int lineID = 0; @@ -227,58 +236,86 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { + " " + lineID + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ -// + " 4012345001235\n" -// + " KR3M\n" -// + " 55T01\n" + // + " 4012345001235\n" + // + " KR3M\n" + // + " 55T01\n" + " " + currentItem.getProduct().getName() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " " + currentItem.getProduct().getDescription() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + currentItem.getProduct().getDescription() //$NON-NLS-1$ + + "\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " " + priceFormat(currentItem.getPrice()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ //currencyID=\"EUR\" - + " 1.0000\n" //$NON-NLS-1$ //$NON-NLS-2$ -// + " \n" -// + " false\n" -// + " 0.6667\n" -// + " Rabatt\n" -// + " \n" + + " " + priceFormat(currentItem.getPrice()) //$NON-NLS-1$ + + "\n" //$NON-NLS-1$ //currencyID=\"EUR\" + + " 1.0000\n" //$NON-NLS-1$ + // + " \n" + // + " false\n" + // + " 0.6667\n" + // + " Rabatt\n" + // + " \n" + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " " + priceFormat(currentItem.getPrice()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // currencyID=\"EUR\" - + " 1.0000\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + priceFormat(currentItem.getPrice()) //$NON-NLS-1$ + + "\n" //$NON-NLS-1$ // currencyID=\"EUR\" + + " 1.0000\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " " + quantityFormat(currentItem.getQuantity()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + " " //$NON-NLS-1$ //$NON-NLS-2$ + + quantityFormat(currentItem.getQuantity()) + "\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " VAT\n" //$NON-NLS-1$ + " S\n" //$NON-NLS-1$ - + " " + vatFormat(currentItem.getProduct().getVATPercent()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " //$NON-NLS-1$ + + vatFormat(currentItem.getProduct().getVATPercent()) + "\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " " + currencyFormat(lc.getItemTotalNetAmount()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // currencyID=\"EUR\" + + " " + currencyFormat(lc.getItemTotalNetAmount()) //$NON-NLS-1$ + + "\n" //$NON-NLS-1$ // currencyID=\"EUR\" + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n"; //$NON-NLS-1$ + } + + xml = xml + " \n"; //$NON-NLS-1$ + if (trans.getReferenceNumber() != null) { + xml = xml + " " + trans.getReferenceNumber() + "\n"; + + } + xml = xml + " \n" //$NON-NLS-1$ + // + " 4000001123452\n" + + " " + trans.getOwnOrganisationName() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ + if (trans.getOwnContact() != null) { + xml = xml + "\n" + " " + trans.getOwnContact().getName() + + "\n"; + if (trans.getOwnContact().getPhone() != null) { + + xml = xml + " \n" + " " + + trans.getOwnContact().getPhone() + "\n" + + " \n"; + } + if (trans.getOwnContact().getEMail() != null) { + + xml = xml + " \n" + " " + + trans.getOwnContact().getEMail() + "\n" + + " \n"; + } + xml = xml + " "; } - xml = xml + " \n" //$NON-NLS-1$ -// + " AB-312\n" - + " \n" //$NON-NLS-1$ -// + " 4000001123452\n" - + " " + trans.getOwnOrganisationName() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" - + " " + trans.getOwnZIP() + "\n" - + " " + trans.getOwnStreet() + "\n" - + " " + trans.getOwnLocation() + "\n" - + " " + trans.getOwnCountry() + "\n" - + " \n" + xml = xml + " \n" + " " + + trans.getOwnZIP() + "\n" + " " + + trans.getOwnStreet() + "\n" + " " + trans.getOwnLocation() + + "\n" + " " + trans.getOwnCountry() + + "\n" + " \n" + " \n" //$NON-NLS-1$ + " " + trans.getOwnTaxID() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " \n" //$NON-NLS-1$ @@ -287,12 +324,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ -// + " GE2020211\n" -// + " 4000001987658\n" + // + " GE2020211\n" + // + " 4000001987658\n" + " " + trans.getRecipient().getName() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ -// + " \n" -// + " xxx\n" -// + " \n" + // + " \n" + // + " xxx\n" + // + " \n" + " \n" //$NON-NLS-1$ + " " + trans.getRecipient().getZIP() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " " + trans.getRecipient().getStreet() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ @@ -303,114 +340,127 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { + " " + trans.getRecipient().getVATID() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ -// + " \n" -// + " 20130301\n" -// + " 2013-471331\n" -// + " \n" + // + " \n" + // + " 20130301\n" + // + " 2013-471331\n" + // + " \n" + " \n" //$NON-NLS-1$ - + " \n" - + " \n" - + " " + zugferdDateFormat.format(trans.getDeliveryDate()) + "\n" + + " \n" + " \n" + + " " + + zugferdDateFormat.format(trans.getDeliveryDate()) + "\n" + " \n" - /* - + " \n" - + " 20130603\n" - + " 2013-51112\n" - + " \n" */ - + " \n" - + " \n" //$NON-NLS-1$ + /* + * + " \n" + + * " 20130603\n" + + * " 2013-51112\n" + + * " \n" + */ + + " \n" + " \n" //$NON-NLS-2$ + " " + trans.getNumber() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " EUR\n"; //$NON-NLS-1$ - for(IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) { - xml += " \n" //$NON-NLS-1$ - + " 42\n" //$NON-NLS-1$ - + " Überweisung\n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " " + payment.getOwnIBAN() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " " + payment.getOwnKto() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ - + " " + payment.getOwnBIC() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " " + payment.getOwnBLZ() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ -// + " "+trans.getOwnBankName()+"\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n"; //$NON-NLS-1$ - } + for (IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) { + xml += " \n" //$NON-NLS-1$ + + " 42\n" //$NON-NLS-1$ + + " Überweisung\n" //$NON-NLS-1$ + + " \n" //$NON-NLS-1$ + + " " + payment.getOwnIBAN() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + payment.getOwnKto() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " \n" //$NON-NLS-1$ + + " \n" //$NON-NLS-1$ + + " " + payment.getOwnBIC() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + payment.getOwnBLZ() //$NON-NLS-1$ + + "\n" //$NON-NLS-1$ + // + " "+trans.getOwnBankName()+"\n" //$NON-NLS-1$ + // //$NON-NLS-2$ + + " \n" //$NON-NLS-1$ + + " \n"; //$NON-NLS-1$ + } HashMap VATPercentAmountMap = getVATPercentAmountMap(); for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); if (amount != null) { xml += " \n" //$NON-NLS-1$ - + " " + currencyFormat(amount.getCalculated()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ //currencyID=\"EUR\" + + " " + currencyFormat(amount.getCalculated()) //$NON-NLS-1$ + + "\n" //$NON-NLS-1$ //currencyID=\"EUR\" + " VAT\n" //$NON-NLS-1$ + " " + currencyFormat(amount.getBasis()) + "\n" // currencyID=\"EUR\" + " S\n" //$NON-NLS-1$ - + " " + vatFormat(currentTaxPercent) + "\n" //$NON-NLS-1$ - + " \n"; //$NON-NLS-1$ - + + " " + vatFormat(currentTaxPercent) //$NON-NLS-1$ + + "\n" + " \n"; //$NON-NLS-2$ } } - /* xml+= " - + " \n" - + " false\n" - + " 10\n" - + " 1.00\n" - + " Sondernachlass\n" - + " \n" - + " VAT\n" - + " S\n" - + " 19\n" - + " \n" - + " \n" - + " \n" - + " false\n" - + " 137.30\n" - + " 13.73\n" - + " Sondernachlass\n" - + " \n" - + " VAT\n" - + " S\n" - + " 7\n" - + " \n" - + " \n" - + " \n" - + " Versandkosten\n" - + " 5.80\n" - + " \n" - + " VAT\n" - + " S\n" - + " 7\n" - + " \n" - + " \n"*/ + /* + * xml+= " + " \n" + + * " false\n" + + * " 10\n" + + * " 1.00\n" + + * " Sondernachlass\n" + + * " \n" + + * " VAT\n" + + * " S\n" + + * " 19\n" + + * " \n" + + * " \n" + + * " \n" + + * " false\n" + + * " 137.30\n" + + * " 13.73\n" + + * " Sondernachlass\n" + + * " \n" + + * " VAT\n" + + * " S\n" + + * " 7\n" + + * " \n" + + * " \n" + + * " \n" + + * " Versandkosten\n" + + * " 5.80\n" + + * " \n" + + * " VAT\n" + + * " S\n" + + * " 7\n" + + * " \n" + + * " \n" + */ xml = xml + " \n" //$NON-NLS-1$ - + " Zahlbar ohne Abzug bis " + germanDateFormat.format(trans.getDueDate()) + "\n" - + " " + zugferdDateFormat.format(trans.getDueDate()) + "\n"//20130704 //$NON-NLS-1$ //$NON-NLS-2$ + + " Zahlbar ohne Abzug bis " + germanDateFormat.format(trans.getDueDate()) + + "\n" + " " //$NON-NLS-2$ + + zugferdDateFormat.format(trans.getDueDate()) + "\n"// 20130704 //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " " + currencyFormat(getTotal()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ currencyID=\"EUR\" - + " 0.00\n" //$NON-NLS-1$ currencyID=\"EUR\" - + " 0.00\n" //$NON-NLS-1$ // currencyID=\"EUR\" -// + " 5.80\n" -// + " 14.73\n" - + " " + currencyFormat(getTotal()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // currencyID=\"EUR\" - + " " + currencyFormat(getTotalGross().subtract(getTotal())) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " " + currencyFormat(getTotalGross()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // currencyID=\"EUR\" -// + " 0.00\n" - + " " + currencyFormat(getTotalGross()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // currencyID=\"EUR\" + + " " + currencyFormat(getTotal()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + // currencyID=\"EUR\" + + " 0.00\n" //$NON-NLS-1$ currencyID=\"EUR\" + + " 0.00\n" //$NON-NLS-1$ // + // currencyID=\"EUR\" + // + " 5.80\n" + // + " 14.73\n" + + " " + currencyFormat(getTotal()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + // // + // currencyID=\"EUR\" + + " " //$NON-NLS-1$ + + currencyFormat(getTotalGross().subtract(getTotal())) + "\n" //$NON-NLS-1$ + + " " + currencyFormat(getTotalGross()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + // // + // currencyID=\"EUR\" + // + " 0.00\n" + + " " + currencyFormat(getTotalGross()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + // // + // currencyID=\"EUR\" + " \n" //$NON-NLS-1$ + " \n"; //$NON-NLS-1$ -// + " \n" -// + " \n" -// + " \n" -// + " Wir erlauben uns Ihnen folgende Positionen aus der Lieferung Nr. 2013-51112 in Rechnung zu stellen:\n" -// + " \n" -// + " \n" -// + " \n"; - + // + " \n" + // + " \n" + // + " \n" + // + " Wir erlauben uns Ihnen folgende Positionen aus der Lieferung Nr. + // 2013-51112 in Rechnung zu stellen:\n" + // + " \n" + // + " \n" + // + " \n"; xml = xml + " \n" //$NON-NLS-1$ + ""; //$NON-NLS-1$ @@ -429,7 +479,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); - } //$NON-NLS-1$ + } // $NON-NLS-1$ } } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index 11cb05c9..b437067a 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -216,6 +216,13 @@ public class ZUGFeRDImporter { return extractString("//HeaderExchangedDocument/TypeCode"); } + /** + * @return the referred document + */ + public String getReference() { + return extractString("//ApplicableHeaderTradeAgreement/BuyerReference"); + } + /** * @return the sender's bank's BLZ code */ diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java index 57043b05..bf9877f0 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java @@ -68,7 +68,7 @@ public abstract class MustangReaderTestCase extends TestCase implements IZUGFeRD } } - protected class Contact implements IZUGFeRDExportableContact { + protected class RecipientContact implements IZUGFeRDExportableContact { @Override public String getCountry() { @@ -101,6 +101,27 @@ public abstract class MustangReaderTestCase extends TestCase implements IZUGFeRD } } + protected class SenderContact implements IZUGFeRDExportableContact { + + + + @Override + public String getName() { + return "Dieter Mara"; + } + + @Override + public String getPhone() { + return "++49(0)1771234567"; + } + + @Override + public String getEMail() { + return "Dieter@Mara.de"; + } + + } + protected class Item implements IZUGFeRDExportableItem { public Item(BigDecimal price, BigDecimal quantity, Product product) { diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java index 1bb90beb..74dee7e6 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java @@ -19,7 +19,6 @@ package org.mustangproject.ZUGFeRD; import junit.framework.Test; -import junit.framework.TestCase; import junit.framework.TestSuite; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; @@ -75,6 +74,13 @@ public class MustangReaderWriterEdgeTest extends MustangReaderTestCase { return "Ecke 12"; } + + @Override + public IZUGFeRDExportableContact getOwnContact() { + return new SenderContact(); + + } + @Override public String getOwnTaxID() { return "22/815/0815/4"; @@ -92,7 +98,7 @@ public class MustangReaderWriterEdgeTest extends MustangReaderTestCase { @Override public IZUGFeRDExportableContact getRecipient() { - return new Contact(); + return new RecipientContact(); } @Override @@ -141,7 +147,7 @@ public class MustangReaderWriterEdgeTest extends MustangReaderTestCase { @Override public String getReferenceNumber() { - return null; + return "AB321"; } /** diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index fef3a66a..f58c444b 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -19,7 +19,6 @@ package org.mustangproject.ZUGFeRD; import junit.framework.Test; -import junit.framework.TestCase; import junit.framework.TestSuite; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; @@ -92,7 +91,12 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { @Override public IZUGFeRDExportableContact getRecipient() { - return new Contact(); + return new RecipientContact(); + } + + @Override + public IZUGFeRDExportableContact getOwnContact() { + return new SenderContact(); } @Override @@ -148,7 +152,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { @Override public String getReferenceNumber() { - return null; + return "AB32"; } /** @@ -334,6 +338,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { // Reading ZUGFeRD assertEquals(zi.getAmount(), "571.04"); assertEquals(zi.getBIC(), getTradeSettlementPayment()[0].getOwnBIC()); + assertEquals(zi.getReference(), getReferenceNumber()); assertEquals(zi.getIBAN(), getTradeSettlementPayment()[0].getOwnIBAN()); assertEquals(zi.getKTO(), getTradeSettlementPayment()[0].getOwnKto()); assertEquals(zi.getHolder(), getOwnOrganisationName()); From 513040558c39457a381fb3c326965137853b3b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 9 Jun 2019 16:07:04 +0200 Subject: [PATCH 17/82] support specifiedlegalorganization --- .../IZUGFeRDExportableOrganization.java | 26 +++++++++++++++++++ .../IZUGFeRDExportableTransaction.java | 4 +++ .../ZUGFeRD/ZUGFeRD2PullProvider.java | 8 ++++++ .../ZUGFeRD/MustangReaderTestCase.java | 19 ++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableOrganization.java diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableOrganization.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableOrganization.java new file mode 100644 index 00000000..312b4666 --- /dev/null +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableOrganization.java @@ -0,0 +1,26 @@ + +/** ********************************************************************** + * + * 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; + +public interface IZUGFeRDExportableOrganization { + public String getID(); + + public String getName(); +} diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java index 6addf89f..31847027 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java @@ -83,6 +83,10 @@ public interface IZUGFeRDExportableTransaction { return null; } + default IZUGFeRDExportableOrganization getOwnOrganization() { + return null; + } + /** * who processed the order * diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index a1d4a842..f8d01465 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -292,6 +292,14 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { xml = xml + " \n" //$NON-NLS-1$ // + " 4000001123452\n" + " " + trans.getOwnOrganisationName() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ + if (trans.getOwnOrganization()!=null) { + + xml = xml + " \n" + + " "+trans.getOwnOrganization().getID()+"\n" + + " "+trans.getOwnOrganization().getName()+"\n" + + " "; + + } if (trans.getOwnContact() != null) { xml = xml + "\n" + " " + trans.getOwnContact().getName() + "\n"; diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java index bf9877f0..8ae406a5 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java @@ -27,6 +27,10 @@ public abstract class MustangReaderTestCase extends TestCase implements IZUGFeRD public MustangReaderTestCase(String testName) { super(testName); } + + @Override public IZUGFeRDExportableOrganization getOwnOrganization() { + return new SenderOrganization(); + } @Override public IZUGFeRDTradeSettlementPayment[] getTradeSettlementPayment() { @@ -100,6 +104,21 @@ public abstract class MustangReaderTestCase extends TestCase implements IZUGFeRD return "88802"; } } + + protected class SenderOrganization implements IZUGFeRDExportableOrganization { + + @Override + public String getID() { + + return "HRA-555123456"; + } + + @Override + public String getName() { + return "Bei Spiel GmbH"; + } + + } protected class SenderContact implements IZUGFeRDExportableContact { From 6662f987f6faaa62dafd27dfd0172f4c99c3ebc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Mon, 10 Jun 2019 11:57:20 +0200 Subject: [PATCH 18/82] format output, some exception logging corrections --- History.md | 8 + doc/MustangWriter.java | 6 +- pom.xml | 635 +++++++++--------- .../ZUGFeRD/ZUGFeRD2PullProvider.java | 55 +- .../ZUGFeRD/ZUGFeRDImporter.java | 13 +- .../org/mustangproject/toecount/Toecount.java | 28 +- 6 files changed, 397 insertions(+), 348 deletions(-) diff --git a/History.md b/History.md index 960ca8cc..615a200c 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,12 @@ +1.7.2 +===== + +Support BuyerReference (r+w), as well as SpecifiedLegalOrganization (w) and DefinedTradeContact (w) +use dom4j to format output xml document +corrected some exception logging glitches + + 1.7.1 ===== 2019-05-26 diff --git a/doc/MustangWriter.java b/doc/MustangWriter.java index 91c2cfe1..500923dc 100644 --- a/doc/MustangWriter.java +++ b/doc/MustangWriter.java @@ -5,12 +5,15 @@ import java.math.BigDecimal; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.logging.Level; +import java.util.logging.Logger; import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge; import org.mustangproject.ZUGFeRD.IZUGFeRDExportableContact; import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem; import org.mustangproject.ZUGFeRD.IZUGFeRDExportableProduct; import org.mustangproject.ZUGFeRD.IZUGFeRDExportableTransaction; +import org.mustangproject.ZUGFeRD.ZUGFeRD2PullProvider; import org.mustangproject.ZUGFeRD.ZUGFeRDExporter; import org.mustangproject.ZUGFeRD.ZUGFeRDExporterFromA1Factory; @@ -32,8 +35,7 @@ public class MustangWriter implements IZUGFeRDExportableTransaction { ze.export("./MustangGnuaccountingBeispielRE-20171118_506new.pdf"); System.out.println("Done."); } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Logger.getLogger(MustangWriter.class.getName()).log(Level.SEVERE, null, e1); } } diff --git a/pom.xml b/pom.xml index 2cd5f02c..e8b226d1 100644 --- a/pom.xml +++ b/pom.xml @@ -1,325 +1,332 @@ - - 4.0.0 - org.mustangproject.ZUGFeRD - mustang - 1.7.2-SNAPSHOT - jar - Mustang - The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs + + 4.0.0 + org.mustangproject.ZUGFeRD + mustang + 1.7.2-SNAPSHOT + jar + Mustang + The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs - http://www.mustangproject.org/ - - scm:git:https://github.com/ZUGFeRD/mustangproject.git - scm:git:https://github.com/ZUGFeRD/mustangproject.git - https://github.com/ZUGFeRD/mustangproject - mustang-1.5.2 - - - - sonatype-oss-public - https://oss.sonatype.org/content/groups/public/ - - true - - - true - - - - - - internal.repo - Temporary Staging Repository - file://${project.build.directory}/mvn-repo - - - - UTF-8 - github - -Xdoclint:none - - 1.8 - 1.8 - 1.8 - - - - - net.sf.saxon - Saxon-HE - 9.8.0-11 - - - com.sun.xml.bind - jaxb-impl - 2.2.11 - - - com.sun.xml.bind - jaxb-core - 2.2.11 - - - org.glassfish.jaxb - jaxb-runtime - 2.2.11 - - - org.apache.pdfbox - preflight - 2.0.12 - - - org.apache.pdfbox - pdfbox - 2.0.12 - - - junit - junit - 4.12 - test - - - com.helger - ph-schematron - 5.0.4 - test - - - org.xmlunit - xmlunit-core - 2.6.2 - test - - - - com.sanityinc - jargs - 2.0-SNAPSHOT - + http://www.mustangproject.org/ + + scm:git:https://github.com/ZUGFeRD/mustangproject.git + scm:git:https://github.com/ZUGFeRD/mustangproject.git + https://github.com/ZUGFeRD/mustangproject + mustang-1.5.2 + + + + sonatype-oss-public + https://oss.sonatype.org/content/groups/public/ + + true + + + true + + + + + + internal.repo + Temporary Staging Repository + file://${project.build.directory}/mvn-repo + + + + UTF-8 + github + -Xdoclint:none + + 1.8 + 1.8 + 1.8 + + + + + net.sf.saxon + Saxon-HE + 9.8.0-11 + + + com.sun.xml.bind + jaxb-impl + 2.2.11 + + + com.sun.xml.bind + jaxb-core + 2.2.11 + + + org.glassfish.jaxb + jaxb-runtime + 2.2.11 + + + org.apache.pdfbox + preflight + 2.0.12 + + + org.apache.pdfbox + pdfbox + 2.0.12 + + + org.dom4j + dom4j + 2.1.1 + + + junit + junit + 4.12 + test + + + com.helger + ph-schematron + 5.0.4 + test + + + org.xmlunit + xmlunit-core + 2.6.2 + test + + + + com.sanityinc + jargs + 2.0-SNAPSHOT + - - - - - - org.apache.maven.plugins - maven-release-plugin - 2.5.3 - - - - + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + + + - - - org.apache.maven.plugins - maven-compiler-plugin - 3.6.1 - - - - true - org.mustangproject.toecount.Toecount - - - - jar-with-dependencies - - - - 1.8 - 1.8 - - + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + + + true + org.mustangproject.toecount.Toecount + + + + jar-with-dependencies + + + + 1.8 + 1.8 + + - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.0.1 - + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.1 + - org.mustangproject.ZUGFeRD.model.* + org.mustangproject.ZUGFeRD.model.* - - - - maven-deploy-plugin - 2.8.2 - - internal.repo::default::file://${project.build.directory}/mvn-repo - - - - - com.github.github - site-maven-plugin - 0.12 - - Maven artifacts for ${project.version} - - true - - ${project.build.directory}/mvn-repo - - refs/heads/mvn-repo - - - **/* - - true - mustangproject - - ZUGFeRD - - - - - - - site - - deploy - - - - - org.apache.maven.plugins - maven-shade-plugin - 2.4.3 - - - - org.mustangproject.toecount.Toecount - - - true - + + + + maven-deploy-plugin + 2.8.2 + + internal.repo::default::file://${project.build.directory}/mvn-repo + + + + + com.github.github + site-maven-plugin + 0.12 + + Maven artifacts for ${project.version} + + true + + ${project.build.directory}/mvn-repo + + refs/heads/mvn-repo + + + **/* + + true + mustangproject + + ZUGFeRD + + + + + + + site + + deploy + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.4.3 + + + + org.mustangproject.toecount.Toecount + + + true + - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - log4j:log4j - - ** - - - - commons-logging:commons-logging - - ** - - - - com.sun.xml.bind:jaxb-impl - - ** - - - - com.sun.xml.bind:jaxb-core - - ** - - - - - - - package - - shade - - - - - - - - - - - - - org.codehaus.mojo - templating-maven-plugin - 1.0.0 - - - filtering-java-templates - - filter-sources - - - - - - org.codehaus.mojo - jaxb2-maven-plugin - 2.3.1 - - - xjc - - xjc - - - - - 2.1 - org.mustangproject.ZUGFeRD.model - - src/main/resources/schema/ZUGFeRD1p0.xsd - - - - - - - - User List - https://groups.google.com/forum/?hl=de#!forum/mustangproject - - - - - Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - A business-friendly OSS license - - - - - Jochen Stärk - jstaerk@usegroup.de - - architect - developer - - - - Alexander Schmidt - schmidt.alexander@mail.de - - developer - - - + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + log4j:log4j + + ** + + + + commons-logging:commons-logging + + ** + + + + com.sun.xml.bind:jaxb-impl + + ** + + + + com.sun.xml.bind:jaxb-core + + ** + + + + + + + package + + shade + + + + + + + + + + + + + org.codehaus.mojo + templating-maven-plugin + 1.0.0 + + + filtering-java-templates + + filter-sources + + + + + + org.codehaus.mojo + jaxb2-maven-plugin + 2.3.1 + + + xjc + + xjc + + + + + 2.1 + org.mustangproject.ZUGFeRD.model + + src/main/resources/schema/ZUGFeRD1p0.xsd + + + + + + + + User List + https://groups.google.com/forum/?hl=de#!forum/mustangproject + + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + A business-friendly OSS license + + + + + Jochen Stärk + jstaerk@usegroup.de + + architect + developer + + + + Alexander Schmidt + schmidt.alexander@mail.de + + developer + + + diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index f8d01465..1516f3fb 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -18,6 +18,10 @@ *********************************************************************** */ package org.mustangproject.ZUGFeRD; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.text.DecimalFormat; @@ -25,6 +29,15 @@ import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.HashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; +import org.mustangproject.toecount.Toecount; public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { @@ -121,7 +134,28 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { @Override public byte[] getXML() { - return zugferdData; + + byte[] res = zugferdData; + + StringWriter sw = new StringWriter(); + Document document=null; + try { + document = DocumentHelper.parseText(new String(zugferdData)); + } catch (DocumentException e1) { + Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e1); + } + try { + OutputFormat format = OutputFormat.createPrettyPrint(); + XMLWriter writer = new XMLWriter(sw, format); + writer.write(document); + res = sw.toString().getBytes("UTF-8"); + + } catch (IOException e) { + Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e); + } + + return res; + } private BigDecimal getTotalGross() { @@ -292,13 +326,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { xml = xml + " \n" //$NON-NLS-1$ // + " 4000001123452\n" + " " + trans.getOwnOrganisationName() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ - if (trans.getOwnOrganization()!=null) { - - xml = xml + " \n" + - " "+trans.getOwnOrganization().getID()+"\n" + - " "+trans.getOwnOrganization().getName()+"\n" + - " "; - + if (trans.getOwnOrganization() != null) { + + xml = xml + " \n" + " " + + trans.getOwnOrganization().getID() + "\n" + " " + + trans.getOwnOrganization().getName() + "\n" + + " "; + } if (trans.getOwnContact() != null) { xml = xml + "\n" + " " + trans.getOwnContact().getName() @@ -401,7 +435,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { } } /* - * xml+= " + " \n" + + * xml+= " + " \n" + * " false\n" + * " 10\n" + * " 1.00\n" + @@ -485,8 +519,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { zugferdData = zugferdRaw; } } catch (UnsupportedEncodingException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); } // $NON-NLS-1$ } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index b437067a..9b24ef11 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -32,6 +32,7 @@ import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode; import org.apache.pdfbox.pdmodel.common.PDNameTreeNode; import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification; import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile; +import org.mustangproject.toecount.Toecount; import org.w3c.dom.Document; import org.xml.sax.SAXException; @@ -46,6 +47,8 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.io.*; import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; public class ZUGFeRDImporter { @@ -69,7 +72,7 @@ public class ZUGFeRDImporter { extractLowLevel(bis); bis.close(); } catch (IOException e) { - e.printStackTrace(); + Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); throw new ZUGFeRDExportException(e); } } @@ -78,7 +81,7 @@ public class ZUGFeRDImporter { try { extractLowLevel(pdfStream); } catch (IOException e) { - e.printStackTrace(); + Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); throw new ZUGFeRDExportException(e); } } @@ -161,7 +164,7 @@ public class ZUGFeRDImporter { try { transformer = tf.newTransformer(); } catch (TransformerConfigurationException e) { - e.printStackTrace(); + Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); } transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); StringWriter writer = new StringWriter(); @@ -190,10 +193,10 @@ public class ZUGFeRDImporter { XPath xpath = xpathFact.newXPath(); result = xpath.evaluate(xpathStr, document); } catch (ParserConfigurationException e) { - e.printStackTrace(); + Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); throw new ZUGFeRDExportException(e); } catch (IOException | SAXException | TransformerException | XPathExpressionException e) { - e.printStackTrace(); + Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); throw new ZUGFeRDExportException(e); } return result; diff --git a/src/main/java/org/mustangproject/toecount/Toecount.java b/src/main/java/org/mustangproject/toecount/Toecount.java index c1143fc2..d45a26ce 100755 --- a/src/main/java/org/mustangproject/toecount/Toecount.java +++ b/src/main/java/org/mustangproject/toecount/Toecount.java @@ -139,8 +139,8 @@ public class Toecount { try { input = buffer.readLine(); } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); + } if (input.isEmpty()) { @@ -176,8 +176,8 @@ public class Toecount { try { selectedName = buffer.readLine(); } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); + } if (selectedName.isEmpty()) { @@ -193,8 +193,7 @@ public class Toecount { try { selectedAnswer = buffer.readLine(); } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); } if (!selectedAnswer.equals("Y") && !selectedAnswer.equals("y")) { System.err.println("Aborted by user"); @@ -326,7 +325,7 @@ public class Toecount { System.exit(2); } } catch (Exception e) { - e.printStackTrace(); + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); System.exit(-1); } @@ -454,8 +453,7 @@ public class Toecount { try { format = getStringFromUser("Format (fx=Factur-X, zf=ZUGFeRD,)", "zf", "fx|zf"); } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); } } else { System.out.println("Format set to " + format); @@ -466,8 +464,7 @@ public class Toecount { try { zfVersion = getStringFromUser("Version (1 or 2)", "1", "1|2"); } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); } } else { System.out.println("Version set to " + zfVersion); @@ -485,8 +482,8 @@ public class Toecount { "E", "M|m|W|w|B|b|C|c|E|e|X|x|"); } } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); + } } else { System.out.println("Profile set to " + zfProfile); @@ -550,9 +547,8 @@ public class Toecount { System.out.println("Written to " + outName); } catch (IOException e) { - e.printStackTrace(); - // } catch (JAXBException e) { - // e.printStackTrace(); + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); + } } From 35fc56cb5362c573dae4dd0bbdab892391e7ddd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Mon, 17 Jun 2019 21:17:04 +0200 Subject: [PATCH 19/82] no message --- .../IZUGFeRDExportableOrganization.java | 26 ------------------- .../IZUGFeRDExportableTransaction.java | 4 --- .../ZUGFeRD/ZUGFeRD2PullProvider.java | 11 ++++---- .../ZUGFeRD/MustangReaderTestCase.java | 24 +++-------------- .../ZUGFeRD/MustangReaderWriterTest.java | 24 ++++++++--------- 5 files changed, 21 insertions(+), 68 deletions(-) delete mode 100644 src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableOrganization.java diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableOrganization.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableOrganization.java deleted file mode 100644 index 312b4666..00000000 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableOrganization.java +++ /dev/null @@ -1,26 +0,0 @@ - -/** ********************************************************************** - * - * 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; - -public interface IZUGFeRDExportableOrganization { - public String getID(); - - public String getName(); -} diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java index 31847027..6addf89f 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java @@ -83,10 +83,6 @@ public interface IZUGFeRDExportableTransaction { return null; } - default IZUGFeRDExportableOrganization getOwnOrganization() { - return null; - } - /** * who processed the order * diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 1516f3fb..bbfc8ae1 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -326,14 +326,15 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { xml = xml + " \n" //$NON-NLS-1$ // + " 4000001123452\n" + " " + trans.getOwnOrganisationName() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ - if (trans.getOwnOrganization() != null) { - xml = xml + " \n" + " " - + trans.getOwnOrganization().getID() + "\n" + " " - + trans.getOwnOrganization().getName() + "\n" + if ((trans.getOwnVATID()!=null)&&(trans.getOwnOrganisationName()!=null)) { + + xml = xml + " \n" + " " + + trans.getOwnVATID() + "\n" + " " + + trans.getOwnOrganisationName() + "\n" + " "; - } + if (trans.getOwnContact() != null) { xml = xml + "\n" + " " + trans.getOwnContact().getName() + "\n"; diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java index 8ae406a5..9b74f570 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java @@ -28,9 +28,6 @@ public abstract class MustangReaderTestCase extends TestCase implements IZUGFeRD super(testName); } - @Override public IZUGFeRDExportableOrganization getOwnOrganization() { - return new SenderOrganization(); - } @Override public IZUGFeRDTradeSettlementPayment[] getTradeSettlementPayment() { @@ -105,38 +102,23 @@ public abstract class MustangReaderTestCase extends TestCase implements IZUGFeRD } } - protected class SenderOrganization implements IZUGFeRDExportableOrganization { - - @Override - public String getID() { - - return "HRA-555123456"; - } - - @Override - public String getName() { - return "Bei Spiel GmbH"; - } - - } - protected class SenderContact implements IZUGFeRDExportableContact { @Override public String getName() { - return "Dieter Mara"; + return "Ingmar N. Fo"; } @Override public String getPhone() { - return "++49(0)1771234567"; + return "++49(0)237823"; } @Override public String getEMail() { - return "Dieter@Mara.de"; + return "info@localhost.local"; } } diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index f58c444b..bc620665 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -36,22 +36,22 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { @Override public Date getDeliveryDate() { - return new GregorianCalendar(2017, Calendar.NOVEMBER, 17).getTime(); + return new GregorianCalendar(2019, Calendar.JUNE, 10).getTime(); } @Override public Date getDueDate() { - return new GregorianCalendar(2017, Calendar.DECEMBER, 9).getTime(); + return new GregorianCalendar(2019, Calendar.JULY, 1).getTime(); } @Override public Date getIssueDate() { - return new GregorianCalendar(2017, Calendar.NOVEMBER, 18).getTime(); + return new GregorianCalendar(2019, Calendar.JUNE, 10).getTime(); } @Override public String getNumber() { - return "RE-20171118/506"; + return "RE-20190610/507"; } @Override @@ -112,21 +112,21 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { @Override public IZUGFeRDExportableItem[] getZFItems() { Item[] allItems = new Item[3]; - Product designProduct = new Product("", "Künstlerische Gestaltung (Stunde): Einer Beispielrechnung", "HUR", + Product designProduct = new Product("", "Design (hours): Of a sample invoice", "HUR", new BigDecimal("7.000000")); - Product balloonProduct = new Product("", "Luftballon: Bunt, ca. 500ml", "C62", new BigDecimal("19.000000")); - Product airProduct = new Product("", "Heiße Luft pro Liter", "LTR", new BigDecimal("19.000000")); + Product balloonProduct = new Product("", "Ballons: various colors, ~2000ml", "C62", new BigDecimal("19.000000")); + Product airProduct = new Product("", "Hot air „heiße Luft“ (litres)", "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); + allItems[2] = new Item(new BigDecimal("0.025"), new BigDecimal("800"), airProduct); return allItems; } @Override public String getPaymentTermDescription() { - SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy"); - return "Zahlbar ohne Abzug bis zum " + germanDateFormat.format(getDueDate()); + SimpleDateFormat isoDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + return "Remit until " + isoDateFormat.format(getDueDate()); } @Override @@ -152,7 +152,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { @Override public String getReferenceNumber() { - return "AB32"; + return "AB321"; } /** @@ -312,7 +312,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { // the writing part try (InputStream SOURCE_PDF = this.getClass() - .getResourceAsStream("/MustangGnuaccountingBeispielRE-20171118_506blanko.pdf"); + .getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf"); ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setZUGFeRDVersion(2).setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.EN16931).load(SOURCE_PDF)) { From 0aee3cbdd98046bfc32501b550bc3c09cea4e2a9 Mon Sep 17 00:00:00 2001 From: Jochen Staerk Date: Tue, 18 Jun 2019 11:08:44 +0200 Subject: [PATCH 20/82] added namespace prefix --- .../java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index bbfc8ae1..331e2a96 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -320,7 +320,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { xml = xml + " \n"; //$NON-NLS-1$ if (trans.getReferenceNumber() != null) { - xml = xml + " " + trans.getReferenceNumber() + "\n"; + xml = xml + " " + trans.getReferenceNumber() + "\n"; } xml = xml + " \n" //$NON-NLS-1$ From 896866dbbfc6db237404d09a69c5f09250bfc595 Mon Sep 17 00:00:00 2001 From: Tarik Osman Date: Tue, 18 Jun 2019 14:04:40 +0200 Subject: [PATCH 21/82] Fix Issue #90: PDF/A-3 conversion missing in ZUGFeRDExporter.export(OutputStream output) --- .../ZUGFeRD/ZUGFeRDExporter.java | 5 ++- .../ZUGFeRD/MustangReaderWriterTest.java | 42 ++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java index 1efeb8d2..211a8397 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java @@ -354,7 +354,10 @@ public class ZUGFeRDExporter implements Closeable { } public void export(OutputStream output) throws IOException { - if (!fileAttached) { + if (!documentPrepared) { + prepareDocument(); + } + if ((!fileAttached) && (attachZUGFeRDHeaders)) { throw new IOException( "File must be attached (usually with PDFattachZugferdFile) before perfoming this operation"); } diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index bc620665..f955e6bd 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -20,11 +20,20 @@ package org.mustangproject.ZUGFeRD; import junit.framework.Test; import junit.framework.TestSuite; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.common.PDMetadata; +import org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException; +import org.apache.xmpbox.XMPMetadata; +import org.apache.xmpbox.schema.PDFAIdentificationSchema; +import org.apache.xmpbox.xml.DomXmpParser; +import org.apache.xmpbox.xml.XmpParsingException; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; @@ -294,8 +303,39 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setAttachZUGFeRDHeaders(false).load(SOURCE_PDF); File tempFile = File.createTempFile("ZUGFeRD-", "-test"); - ze.export(tempFile.getName()); + ze.export(tempFile.getAbsolutePath()); tempFile.deleteOnExit(); + checkPdfA3B(tempFile); + } + + public void testMigratePDFA1ToA3Stream() throws IOException { + // just make sure there is no Exception + InputStream SOURCE_PDF = this.getClass() + .getResourceAsStream("/MustangGnuaccountingBeispielRE-20171118_506blanko.pdf"); + + ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setAttachZUGFeRDHeaders(false).load(SOURCE_PDF); + + File tempFile = File.createTempFile("ZUGFeRD-", "-test"); + tempFile.deleteOnExit(); + try (FileOutputStream fos = new FileOutputStream(tempFile)) { + ze.export(fos); + } + checkPdfA3B(tempFile); + } + + private void checkPdfA3B(File tempFile) throws IOException, InvalidPasswordException { + try (PDDocument doc = PDDocument.load(tempFile)) { + PDMetadata metadata = doc.getDocumentCatalog().getMetadata(); + InputStream exportXMPMetadata = metadata.exportXMPMetadata(); + byte[] xmpBytes = new byte[exportXMPMetadata.available()]; + exportXMPMetadata.read(xmpBytes); + final XMPMetadata xmp = new DomXmpParser().parse(xmpBytes); + PDFAIdentificationSchema pdfaid = xmp.getPDFIdentificationSchema(); + assertEquals(pdfaid.getPart().intValue(), 3); + assertEquals(pdfaid.getConformance(), "U"); + } catch (XmpParsingException e) { + throw new IllegalStateException("Failed to read PDF", e); + } } /** From 80a9a74c5c313b926835f5caa867c20abc143647 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Sat, 22 Jun 2019 19:30:56 +0200 Subject: [PATCH 22/82] Remove byte order marks, which cause tests to fail with Java 1.8 --- src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java | 2 +- .../ZUGFeRD/MustangReaderWriterCustomXMLTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index 9b24ef11..35ce8717 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -369,7 +369,7 @@ public class ZUGFeRDImporter { static String convertStreamToString(java.io.InputStream is) { // source https://stackoverflow.com/questions/309424/how-do-i-read-convert-an-inputstream-into-a-string-in-java referring to // https://community.oracle.com/blogs/pat/2004/10/23/stupid-scanner-tricks - Scanner s = new Scanner(is).useDelimiter("\\A"); + Scanner s = new Scanner(is, "UTF-8").useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; } diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java index 07b03609..b52d8d97 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java @@ -62,7 +62,7 @@ public class MustangReaderWriterCustomXMLTest extends TestCase { 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. */ - String ownZUGFeRDXML = new String(UTF8ByteOrderMark) + "\n" + + String ownZUGFeRDXML = "\n" + "\n" + " \n" + " false\n" + From e8e7c4b623caa1316746bbaa3770d7cc1cfcdf0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Tue, 25 Jun 2019 20:10:10 +0200 Subject: [PATCH 23/82] test nom in export so that it is also tested in import --- .../ZUGFeRD/MustangReaderWriterCustomXMLTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java index b52d8d97..42277aba 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java @@ -61,8 +61,10 @@ public class MustangReaderWriterCustomXMLTest extends TestCase { .load(SOURCE_PDF); 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. */ - String ownZUGFeRDXML = "\n" + + /* 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. + * 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) + "\n" + "\n" + " \n" + " false\n" + From 86027e9462825fcfae54f90e7595d400b94b67f0 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Mon, 1 Jul 2019 18:55:39 +0200 Subject: [PATCH 24/82] Remove hardcoded prefix "Ursprungsbeleg: " from reference info --- .../ZUGFeRD/ZUGFeRDTransactionModelConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java index 11b8b45c..cf01b3c1 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java @@ -167,7 +167,7 @@ class ZUGFeRDTransactionModelConverter { if (trans.getReferenceNumber() != null && !"".equals(trans.getReferenceNumber())) { NoteType referenceInfo = xmlFactory.createNoteType(); TextType referenceInfoContent = xmlFactory.createTextType(); - referenceInfoContent.setValue("Ursprungsbeleg: " + trans.getReferenceNumber()); + referenceInfoContent.setValue(trans.getReferenceNumber()); referenceInfo.getContent().add(referenceInfoContent); document.getIncludedNote().add(referenceInfo); } From 00af1dcf0807e7fc4200e0c43f727e781ef69ff0 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Wed, 3 Jul 2019 14:03:23 +0200 Subject: [PATCH 25/82] deprecate misleading documentCode in favour of categoryCode --- .../org/mustangproject/ZUGFeRD/VATAmount.java | 32 +++++++++++++++---- .../ZUGFeRDTransactionModelConverter.java | 12 ++++--- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/VATAmount.java b/src/main/java/org/mustangproject/ZUGFeRD/VATAmount.java index 408ea69f..817595f6 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/VATAmount.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/VATAmount.java @@ -31,16 +31,16 @@ import java.math.BigDecimal; */ public class VATAmount { - public VATAmount(BigDecimal basis, BigDecimal calculated, String documentCode) { + public VATAmount(BigDecimal basis, BigDecimal calculated, String categoryCode) { super(); this.basis = basis; this.calculated = calculated; - this.documentCode = documentCode; + this.categoryCode = categoryCode; } BigDecimal basis, calculated; - String documentCode; + String categoryCode; public BigDecimal getBasis() { return basis; @@ -58,20 +58,38 @@ public class VATAmount { this.calculated = calculated; } + /** + * + * @deprecated Use {@link #getCategoryCode() instead} + */ + @Deprecated public String getDocumentCode() { - return documentCode; + return categoryCode; } + /** + * + * @deprecated Use {@link #setCategoryCode(String)} instead + */ + @Deprecated 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) { - 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) { - 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); } } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java index cf01b3c1..206b5a2e 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java @@ -422,7 +422,7 @@ class ZUGFeRDTransactionModelConverter { TaxCategoryCodeType taxCategoryCode = xmlFactory.createTaxCategoryCodeType(); VATAmount vatAmount = VATPercentAmountMap.get(currentTaxPercent); - taxCategoryCode.setValue(vatAmount.getDocumentCode()); + taxCategoryCode.setValue(vatAmount.getCategoryCode()); tradeTax.setCategoryCode(taxCategoryCode); VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); @@ -924,7 +924,7 @@ class ZUGFeRDTransactionModelConverter { for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { BigDecimal percent = currentItem.getProduct().getVATPercent(); 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); if (current == null) { hm.put(percent, itemVATAmount); @@ -958,7 +958,7 @@ class ZUGFeRDTransactionModelConverter { VATAmount itemVATAmount = new VATAmount( 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); if (current == null) { hm.put(percent, itemVATAmount); @@ -973,7 +973,7 @@ class ZUGFeRDTransactionModelConverter { BigDecimal percent = charge.getTaxPercent(); VATAmount itemVATAmount = new VATAmount( 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); if (current == null) { hm.put(percent, itemVATAmount); @@ -998,6 +998,7 @@ class ZUGFeRDTransactionModelConverter { private BigDecimal itemTotalNetAmount; private BigDecimal itemTotalVATAmount; private BigDecimal itemNetAmount; + private String categoryCode; public LineCalc(IZUGFeRDExportableItem currentItem) { @@ -1040,6 +1041,7 @@ class ZUGFeRDTransactionModelConverter { .add(totalCharge) .divide(currentItem.getQuantity(), 4, BigDecimal.ROUND_HALF_UP); + categoryCode = currentItem.getCategoryCode(); } @@ -1057,6 +1059,8 @@ class ZUGFeRDTransactionModelConverter { return itemNetAmount; } + public String getCategoryCode() { return categoryCode; } + } private class Totals { From 5ace39936534e311dc279e3ec279e55a2ac1b126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sat, 6 Jul 2019 13:42:24 +0200 Subject: [PATCH 26/82] no message --- History.md | 3 + pom.xml | 4 +- .../ZUGFeRD/ZUGFeRDImporter.java | 14 +- .../ZUGFeRD/ZUGFeRDVisualizer.java | 134 + .../org/mustangproject/toecount/Toecount.java | 51 +- .../stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt | 3008 +++++++++++++++++ src/main/resources/stylesheets/cii-xr.xsl | 2202 ++++++++++++ .../resources/stylesheets/xrechnung-html.xsl | 1188 +++++++ ...ccountingBeispielRE-20190610_507blanko.pdf | Bin 0 -> 87968 bytes 9 files changed, 6596 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java create mode 100644 src/main/resources/stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt create mode 100644 src/main/resources/stylesheets/cii-xr.xsl create mode 100644 src/main/resources/stylesheets/xrechnung-html.xsl create mode 100644 src/test/resources/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf diff --git a/History.md b/History.md index 615a200c..f24355a2 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,9 @@ Support BuyerReference (r+w), as well as SpecifiedLegalOrganization (w) and DefinedTradeContact (w) use dom4j to format output xml document 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 1.7.1 diff --git a/pom.xml b/pom.xml index e8b226d1..67a0bb2a 100644 --- a/pom.xml +++ b/pom.xml @@ -69,12 +69,12 @@ org.apache.pdfbox preflight - 2.0.12 + [2.0.15,) org.apache.pdfbox pdfbox - 2.0.12 + [2.0.15,) org.dom4j diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index 35ce8717..c9004873 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -46,6 +46,9 @@ import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; @@ -67,14 +70,13 @@ public class ZUGFeRDImporter { private String xmpString = null; // XMP metadata public ZUGFeRDImporter(String pdfFilename) { - try { - BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pdfFilename)); + + try (InputStream bis = Files.newInputStream(Paths.get(pdfFilename), StandardOpenOption.READ)) { extractLowLevel(bis); - bis.close(); } catch (IOException e) { Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); throw new ZUGFeRDExportException(e); - } + } } public ZUGFeRDImporter(InputStream pdfStream) { @@ -125,7 +127,9 @@ public class ZUGFeRDImporter { private void extractFiles(Map names) throws IOException { - for (String filename : names.keySet()) { + for (String alias : names.keySet()) { + String filename=names.get(alias).getFilename(); + /** * currently (in the release candidate of version 1) only one attached file with * the name ZUGFeRD-invoice.xml is allowed diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java new file mode 100644 index 00000000..03b820b3 --- /dev/null +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java @@ -0,0 +1,134 @@ +/** ********************************************************************** + * + * 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.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; + + 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"))); + } 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 + */ + ByteArrayOutputStream iaos = new ByteArrayOutputStream(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + applySchematronXsl(new FileInputStream(xmlFilename), 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) { + // logging and exception handling should go here + } + 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 + e.printStackTrace(); + } + } + } + } + }).start(); + applySchematronXsl2(in, baos); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + 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 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)); + } + } +} diff --git a/src/main/java/org/mustangproject/toecount/Toecount.java b/src/main/java/org/mustangproject/toecount/Toecount.java index d45a26ce..06843a4c 100755 --- a/src/main/java/org/mustangproject/toecount/Toecount.java +++ b/src/main/java/org/mustangproject/toecount/Toecount.java @@ -30,8 +30,10 @@ import org.mustangproject.ZUGFeRD.*; import javax.xml.transform.TransformerException; import java.io.BufferedReader; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -235,6 +237,8 @@ public class Toecount { // Option: Help Option helpOption = parser.addBooleanOption('h', "help"); + // Option: Action + Option actionOption = parser.addStringOption('a', "action"); // Generic options available for multiple command // --source: input file @@ -304,6 +308,7 @@ public class Toecount { String sourceXMLName = parser.getOptionValue(sourceXmlOption); String outName = parser.getOptionValue(outOption); String format = parser.getOptionValue(formatOption); + String action = parser.getOptionValue(actionOption); String zugferdVersion = parser.getOptionValue(zugferdVersionOption); String zugferdProfile = parser.getOptionValue(zugferdProfileOption); @@ -319,6 +324,8 @@ public class Toecount { performConvert(sourceName, outName); } else if (upgradeRequested) { performUpgrade(sourceName, outName); + } else if (action.equals("convertToHTML")) { + performVisualization(sourceName, outName); } else { // no argument or argument unknown printUsage(); @@ -332,6 +339,48 @@ public class Toecount { } + private static void performVisualization(String sourceName, String outName) { + // Get params from user if not already defined + if (sourceName == null) { + sourceName = getFilenameFromUser("ZUGFeRD XML source", "zugferd-invoice.xml", "xml", true, false); + } else { + System.out.println("ZUGFeRD XML source set to " + sourceName); + } + if (outName == null) { + outName = getFilenameFromUser("ZUGFeRD 2.0 XML target", "factur-x.html", "html", false, true); + } else { + System.out.println("ZUGFeRD 1.0 XML source set to " + outName); + } + + // Verify params + try { + ensureFileExists(sourceName); + ensureFileNotExists(outName); + + //stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt + } catch (IOException e) { + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); + } + + ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer(); + String xml = null; + try { + xml = zvi.visualize(sourceName); + Files.write(Paths.get(outName), xml.getBytes()); + } catch (FileNotFoundException e) { + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); + } catch (UnsupportedEncodingException e) { + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); + } catch (TransformerException e) { + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); + } catch (IOException e) { + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); + } + System.out.println("Written to " + outName); + + + } + private static void performUpgrade(String xmlName, String outName) throws IOException, TransformerException { // Get params from user if not already defined @@ -341,7 +390,7 @@ public class Toecount { System.out.println("ZUGFeRD 1.0 XML source set to " + xmlName); } 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 { System.out.println("ZUGFeRD 1.0 XML source set to " + outName); } diff --git a/src/main/resources/stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt b/src/main/resources/stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt new file mode 100644 index 00000000..97f444fe --- /dev/null +++ b/src/main/resources/stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt @@ -0,0 +1,3008 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + <meta http-equiv="X-UA-Compatible" content="IE=9"/> + <xsl:comment>[if IE]><STYLE type="text/css">.altova-rotate-left-textbox{filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3)} .altova-rotate-right-textbox{filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1)} </STYLE><![endif]</xsl:comment> + <xsl:comment>[if !IE]><!</xsl:comment> + <style type="text/css">.altova-rotate-left-textbox{-webkit-transform: rotate(-90deg) translate(-100%, 0%); -webkit-transform-origin: 0% 0%;-moz-transform: rotate(-90deg) translate(-100%, 0%); -moz-transform-origin: 0% 0%;-ms-transform: rotate(-90deg) translate(-100%, 0%); -ms-transform-origin: 0% 0%;}.altova-rotate-right-textbox{-webkit-transform: rotate(90deg) translate(0%, -100%); -webkit-transform-origin: 0% 0%;-moz-transform: rotate(90deg) translate(0%, -100%); -moz-transform-origin: 0% 0%;-ms-transform: rotate(90deg) translate(0%, -100%); -ms-transform-origin: 0% 0%;}</style> + <xsl:comment><![endif]</xsl:comment> + <style type="text/css">@page { margin-left:0.60in; margin-right:0.60in; margin-top:0.79in; margin-bottom:0.79in } @media print { br.altova-page-break { page-break-before: always; } }</style> + </head> + <body style="font-family:Courier; font-size:small; "> + <xsl:for-each select="$XML"> + <xsl:for-each select="rsm:CrossIndustryDocument"> + <span> + <xsl:text>Stylesheet Lesbarmachung der XML-Daten von ZUGFeRD-Rechnungen</xsl:text> + </span> + <br/> + <span> + <xsl:text>ZUGFeRD-Version   : 1.0 vom 25.06.2014 </xsl:text> + </span> + <br/> + <span> + <xsl:text>Stylesheet-Version: 1.0 vom 25.06.2014</xsl:text> + </span> + <br/> + <span> + <xsl:text>Codelisten-Version: 1.0 vom 25.06.2014</xsl:text> + </span> + <br/> + <span> + <xsl:text>(c) AWV e.V. 2014</xsl:text> + </span> + <xsl:variable name="altova:table"> + <table style="border-collapse:collapse; " border="1" width="100%"> + <xsl:variable name="altova:CurrContextGrid_0" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <tr> + <td> + <br/> + <h2> + <xsl:for-each select="rsm:HeaderExchangedDocument"> + <xsl:for-each select="ram:Name"> + <span style="font-weight:bold; "> + <xsl:apply-templates/> + </span> + </xsl:for-each> + <span style="empty-cells:hide; font-weight:bold; "> + <xsl:text>(</xsl:text> + </span> + <xsl:for-each select="ram:TypeCode"> + <xsl:apply-templates/> + </xsl:for-each> + <span style="empty-cells:hide; font-weight:bold; "> + <xsl:text>) Nr. </xsl:text> + </span> + <xsl:for-each select="ram:ID"> + <span style="font-weight:bold; "> + <xsl:apply-templates/> + </span> + </xsl:for-each> + <span style="empty-cells:hide; font-weight:bold; "> + <xsl:text> vom </xsl:text> + </span> + <xsl:for-each select="ram:IssueDateTime"> + <xsl:for-each select="udt:DateTimeString"> + <xsl:call-template name="ram:Datum"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </h2> + <xsl:for-each select="rsm:SpecifiedExchangedDocumentContext"> + <br/> + <xsl:for-each select="ram:TestIndicator"> + <xsl:for-each select="udt:Indicator"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Testkennzeichen      : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:BusinessProcessSpecifiedDocumentContextParameter"> + <xsl:for-each select="ram:ID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Geschäftsprozess     : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedExchangedDocumentContext"> + <xsl:for-each select="ram:GuidelineSpecifiedDocumentContextParameter"> + <xsl:for-each select="ram:ID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Anwendungsempfehlung : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:HeaderExchangedDocument"> + <xsl:for-each select="ram:CopyIndicator"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Kopie                : </xsl:text> + </span> + <xsl:for-each select="udt:Indicator"> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:HeaderExchangedDocument"> + <xsl:for-each select="ram:LanguageID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Sprache              : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeSettlement"> + <xsl:for-each select="ram:InvoiceCurrencyCode"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Währung              : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <br/> + </td> + </tr> + <tr> + <td> + <xsl:for-each select="rsm:HeaderExchangedDocument"> + <xsl:for-each select="ram:EffectiveSpecifiedPeriod"> + <xsl:for-each select="ram:CompleteDateTime"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Vertragliches Fälligkeitsdatum: </xsl:text> + </span> + <xsl:for-each select="udt:DateTimeString"> + <xsl:call-template name="ram:Datum"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeDelivery"> + <xsl:for-each select="ram:ActualDeliverySupplyChainEvent"> + <xsl:for-each select="ram:OccurrenceDateTime"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Liefer- und Leistungsdatum    : </xsl:text> + </span> + <xsl:for-each select="udt:DateTimeString"> + <xsl:call-template name="ram:Datum"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeSettlement"> + <xsl:for-each select="ram:BillingSpecifiedPeriod"> + <xsl:for-each select="ram:StartDateTime"> + <br/> + <span> + <xsl:text>Abrechnungszeitraum           : </xsl:text> + </span> + <xsl:for-each select="udt:DateTimeString"> + <xsl:call-template name="ram:Datum"/> + </xsl:for-each> + </xsl:for-each> + <span> + <xsl:text> bis </xsl:text> + </span> + <xsl:for-each select="ram:EndDateTime"> + <xsl:for-each select="udt:DateTimeString"> + <xsl:call-template name="ram:Datum"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <br/> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeAgreement"> + <xsl:for-each select="ram:BuyerReference"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Referenz des Käufers          : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeSettlement"> + <xsl:for-each select="ram:PaymentReference"> + <br/> + <span style="empty-cells:hide; font-weight:bold; "> + <xsl:text>Zahlungsreferenz              : </xsl:text> + </span> + <span style="font-weight:bold; "> + <xsl:apply-templates/> + </span> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeSettlement"> + <xsl:for-each select="ram:ReceivableSpecifiedTradeAccountingAccount"> + <xsl:for-each select="ram:ID"> + <br/> + <span> + <xsl:text>Buchungsreferenz              : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeAgreement"> + <xsl:for-each select="ram:ApplicableTradeDeliveryTerms"> + <xsl:for-each select="ram:DeliveryTypeCode"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Lieferbedingung (codiert)     : </xsl:text> + </span> + <xsl:call-template name="DeliveryTypeCode"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeDelivery"> + <xsl:for-each select="ram:RelatedSupplyChainConsignment"> + <xsl:for-each select="ram:SpecifiedLogisticsTransportMovement"> + <xsl:for-each select="ram:ModeCode"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Versandart (codiert)          : </xsl:text> + </span> + <xsl:call-template name="ram:VersandMode"/> + </xsl:for-each> + <xsl:for-each select="ram:ID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Versand-ID                    : </xsl:text> + </span> + <xsl:apply-templates/> + <xsl:for-each select="@schemeID"> + <span style="empty-cells:hide; "> + <xsl:text>, Art: </xsl:text> + </span> + <xsl:call-template name="ram:Versand_Identifer"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <br/> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeAgreement"> + <xsl:for-each select="ram:BuyerOrderReferencedDocument"> + <xsl:for-each select="ram:ID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Bestellung                    : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <span style="empty-cells:hide; "> + <xsl:text> vom </xsl:text> + </span> + <xsl:for-each select="ram:IssueDateTime"> + <span> + <xsl:variable name="altova:seqContentStrings_1"> + <xsl:value-of select="format-number(number(substring(string(string(.)), 9, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(.)), 6, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(string(.))), 1, 4)), '0000', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_1" select="string($altova:seqContentStrings_1)"/> + <xsl:value-of select="$altova:sContent_1"/> + </span> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeDelivery"> + <xsl:for-each select="ram:DespatchAdviceReferencedDocument"> + <xsl:for-each select="ram:ID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Lieferavis                    : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <span style="empty-cells:hide; "> + <xsl:text> vom </xsl:text> + </span> + <xsl:for-each select="ram:IssueDateTime"> + <span> + <xsl:variable name="altova:seqContentStrings_2"> + <xsl:value-of select="format-number(number(substring(string(string(.)), 9, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(.)), 6, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(string(.))), 1, 4)), '0000', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_2" select="string($altova:seqContentStrings_2)"/> + <xsl:value-of select="$altova:sContent_2"/> + </span> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeDelivery"> + <xsl:for-each select="ram:DeliveryNoteReferencedDocument"> + <xsl:for-each select="ram:ID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Lieferschein                  : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <span style="empty-cells:hide; "> + <xsl:text> vom </xsl:text> + </span> + <xsl:for-each select="ram:IssueDateTime"> + <span> + <xsl:variable name="altova:seqContentStrings_3"> + <xsl:value-of select="format-number(number(substring(string(string(.)), 9, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(.)), 6, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(string(.))), 1, 4)), '0000', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_3" select="string($altova:seqContentStrings_3)"/> + <xsl:value-of select="$altova:sContent_3"/> + </span> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeAgreement"> + <xsl:for-each select="ram:ContractReferencedDocument"> + <xsl:for-each select="ram:ID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Vertrag                       : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <span style="empty-cells:hide; "> + <xsl:text> vom </xsl:text> + </span> + <xsl:for-each select="ram:IssueDateTime"> + <span> + <xsl:variable name="altova:seqContentStrings_4"> + <xsl:value-of select="format-number(number(substring(string(string(.)), 9, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(.)), 6, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(string(.))), 1, 4)), '0000', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_4" select="string($altova:seqContentStrings_4)"/> + <xsl:value-of select="$altova:sContent_4"/> + </span> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeAgreement"> + <xsl:for-each select="ram:CustomerOrderReferencedDocument"> + <xsl:for-each select="ram:ID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Kundenbestellung              : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <span style="empty-cells:hide; "> + <xsl:text> vom </xsl:text> + </span> + <xsl:for-each select="ram:IssueDateTime"> + <span> + <xsl:variable name="altova:seqContentStrings_5"> + <xsl:value-of select="format-number(number(substring(string(string(.)), 9, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(.)), 6, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(string(.))), 1, 4)), '0000', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_5" select="string($altova:seqContentStrings_5)"/> + <xsl:value-of select="$altova:sContent_5"/> + </span> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeAgreement"> + <xsl:for-each select="ram:AdditionalReferencedDocument"> + <xsl:for-each select="ram:ID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Weitere Referenz              : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <span style="empty-cells:hide; "> + <xsl:text> vom </xsl:text> + </span> + <xsl:for-each select="ram:IssueDateTime"> + <span> + <xsl:variable name="altova:seqContentStrings_6"> + <xsl:value-of select="format-number(number(substring(string(string(.)), 9, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(.)), 6, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(string(.))), 1, 4)), '0000', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_6" select="string($altova:seqContentStrings_6)"/> + <xsl:value-of select="$altova:sContent_6"/> + </span> + </xsl:for-each> + <xsl:for-each select="ram:TypeCode"> + <span style="empty-cells:hide; "> + <xsl:text>, Art der Referenz: </xsl:text> + </span> + <xsl:call-template name="ram:Referenz"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <br/> + <span style="empty-cells:hide; "> + <xsl:text> </xsl:text> + </span> + </td> + </tr> + <tr> + <td> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeAgreement"> + <xsl:for-each select="ram:SellerTradeParty"> + <br/> + <span style="empty-cells:hide; font-weight:bold; text-decoration:underline; "> + <xsl:text>Verkäufer:</xsl:text> + </span> + <br/> + <xsl:call-template name="ram:Party"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeAgreement"> + <xsl:for-each select="ram:BuyerTradeParty"> + <br/> + <span style="empty-cells:hide; font-weight:bold; text-decoration:underline; "> + <xsl:text>Käufer:</xsl:text> + </span> + <br/> + <xsl:call-template name="ram:Party"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeAgreement"> + <xsl:for-each select="ram:ProductEndUserTradeParty"> + <br/> + <span style="empty-cells:hide; font-weight:bold; text-decoration:underline; "> + <xsl:text>Endverbraucher:</xsl:text> + </span> + <br/> + <xsl:call-template name="ram:Party"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeDelivery"> + <xsl:for-each select="ram:ShipToTradeParty"> + <br/> + <span style="empty-cells:hide; font-weight:bold; text-decoration:underline; "> + <xsl:text>Abweichender Warenempfänger:</xsl:text> + </span> + <br/> + <xsl:call-template name="ram:Party"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeDelivery"> + <xsl:for-each select="ram:UltimateShipToTradeParty"> + <br/> + <span style="empty-cells:hide; font-weight:bold; text-decoration:underline; "> + <xsl:text>Abweichender Endempfänger:</xsl:text> + </span> + <br/> + <xsl:call-template name="ram:Party"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeDelivery"> + <xsl:for-each select="ram:ShipFromTradeParty"> + <br/> + <span style="empty-cells:hide; font-weight:bold; text-decoration:underline; "> + <xsl:text>Abweichender Versender:</xsl:text> + </span> + <br/> + <xsl:call-template name="ram:Party"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeSettlement"> + <xsl:for-each select="ram:InvoiceeTradeParty"> + <br/> + <span style="empty-cells:hide; font-weight:bold; text-decoration:underline; "> + <xsl:text>Abweichender Rechnungsempfänger:</xsl:text> + </span> + <br/> + <xsl:call-template name="ram:Party"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeSettlement"> + <xsl:for-each select="ram:PayeeTradeParty"> + <br/> + <span style="empty-cells:hide; font-weight:bold; text-decoration:underline; "> + <xsl:text>Abweichender Zahlungsempfänger:</xsl:text> + </span> + <br/> + <xsl:call-template name="ram:Party"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </td> + </tr> + <tr> + <td> + <xsl:for-each select="rsm:HeaderExchangedDocument"> + <br/> + <xsl:for-each select="ram:IncludedNote"> + <xsl:for-each select="ram:SubjectCode"> + <span style="color:gray; empty-cells:hide; "> + <xsl:text>Qualifizierung der Textart: </xsl:text> + </span> + <span style="font-weight:bold; "> + <xsl:apply-templates/> + </span> + </xsl:for-each> + <xsl:for-each select="ram:ContentCode"> + <span style="color:gray; empty-cells:hide; "> + <xsl:text>, Qualifizierung des Textes: </xsl:text> + </span> + <span style="font-weight:bold; "> + <xsl:apply-templates/> + </span> + </xsl:for-each> + <xsl:for-each select="ram:Content"> + <br/> + <span style="font-weight:bold; white-space:pre-wrap; "> + <xsl:apply-templates/> + </span> + <br/> + <br/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </td> + </tr> + <tr> + <td style="border-bottom-style:none; "> + <xsl:variable name="altova:table"> + <table style="border:0px; border-collapse:collapse; border-spacing:0px; padding:0px; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_7" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <tr style="text-align:center; vertical-align:middle; "> + <td style="border-bottom-style:solid; border-collapse:collapse; border-left-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:center; width:30px; "> + <span style="font-weight:bold; "> + <xsl:text>Pos</xsl:text> + </span> + </td> + <td style="border-bottom-style:solid; border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:left; width:110px; "> + <span style="font-weight:bold; "> + <xsl:text>Art-Nr-Kunde</xsl:text> + </span> + <br/> + <span style="font-weight:bold; "> + <xsl:text>Art-Nr-Lief.</xsl:text> + </span> + <br/> + <span style="font-weight:bold; "> + <xsl:text>Art-Nr</xsl:text> + </span> + <br/> + <span style="font-weight:bold; "> + <xsl:text>(Art)</xsl:text> + </span> + </td> + <td style="border-bottom-style:solid; border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; "> + <span style="font-weight:bold; "> + <xsl:text>Beschreibung</xsl:text> + </span> + </td> + <td style="border-bottom-style:solid; border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; width:110px; "> + <span style="font-weight:bold; "> + <xsl:text>E-Preis</xsl:text> + </span> + </td> + <td style="border-bottom-style:solid; border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; width:120px; "> + <span style="font-weight:bold; "> + <xsl:text>Menge</xsl:text> + </span> + </td> + <td style="border-bottom-style:solid; border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; width:110px; "> + <span style="font-weight:bold; "> + <xsl:text>Steuer</xsl:text> + </span> + </td> + <td style="border-bottom-style:solid; border-collapse:collapse; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; width:110px; "> + <span style="font-weight:bold; "> + <xsl:text>Entgelt</xsl:text> + </span> + </td> + </tr> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:IncludedSupplyChainTradeLineItem"> + <xsl:if test="fn:not( fn:empty(ram:SpecifiedTradeProduct))"> + <xsl:variable name="altova:table"> + <table style="border:0px; border-collapse:collapse; border-spacing:0px; padding:0px; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_8" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <tr style="vertical-align:top; "> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:center; width:30px; "> + <xsl:for-each select="ram:AssociatedDocumentLineDocument"> + <xsl:if test="fn:empty(ram:IncludedNote)"> + <xsl:for-each select="ram:LineID"> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:if> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; width:110px; "> + <xsl:for-each select="ram:SpecifiedTradeProduct"> + <xsl:for-each select="ram:BuyerAssignedID"> + <xsl:apply-templates/> + </xsl:for-each> + <br/> + <xsl:for-each select="ram:SellerAssignedID"> + <xsl:apply-templates/> + </xsl:for-each> + <br/> + <xsl:for-each select="ram:GlobalID"> + <xsl:apply-templates/> + <br/> + <xsl:for-each select="@schemeID"> + <xsl:call-template name="ram:Global_Identifier"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; "> + <xsl:for-each select="ram:SpecifiedTradeProduct"> + <xsl:for-each select="ram:Name"> + <span style="white-space:pre-wrap; "> + <xsl:apply-templates/> + </span> + <br/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeAgreement"> + <xsl:if test="fn:exists(ram:GrossPriceProductTradePrice)"> + <xsl:for-each select="ram:GrossPriceProductTradePrice"> + <xsl:for-each select="ram:BasisQuantity"> + <span> + <xsl:text>Preisbasismenge: </xsl:text> + </span> + <xsl:call-template name="ram:Menge"/> + </xsl:for-each> + </xsl:for-each> + </xsl:if> + <xsl:if test="fn:not(fn:exists(ram:GrossPriceProductTradePrice))"> + <xsl:for-each select="ram:NetPriceProductTradePrice"> + <xsl:for-each select="ram:BasisQuantity"> + <br/> + <span> + <xsl:text>Preisbasismenge: </xsl:text> + </span> + <xsl:call-template name="ram:Menge"/> + </xsl:for-each> + </xsl:for-each> + </xsl:if> + </xsl:for-each> + </td> + <td style="border-bottom-style:solid; border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; width:110px; "> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeAgreement"> + <xsl:if test="fn:exists(ram:GrossPriceProductTradePrice)"> + <xsl:for-each select="ram:GrossPriceProductTradePrice"> + <xsl:for-each select="ram:ChargeAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_9"> + <xsl:value-of select="format-number(number(string(.)), '##0,0000', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_9" select="string($altova:seqContentStrings_9)"/> + <xsl:value-of select="$altova:sContent_9"/> + </span> + </xsl:for-each> + </xsl:for-each> + </xsl:if> + <xsl:if test="not(fn:exists(ram:GrossPriceProductTradePrice))"> + <xsl:for-each select="ram:NetPriceProductTradePrice"> + <xsl:for-each select="ram:ChargeAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_10"> + <xsl:value-of select="format-number(number(string(.)), '###.##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_10" select="string($altova:seqContentStrings_10)"/> + <xsl:value-of select="$altova:sContent_10"/> + </span> + </xsl:for-each> + </xsl:for-each> + </xsl:if> + </xsl:for-each> + </td> + <td style="border-bottom-style:solid; border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; width:120px; "> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeDelivery"> + <xsl:for-each select="ram:BilledQuantity"> + <xsl:call-template name="ram:Menge"/> + </xsl:for-each> + <xsl:for-each select="ram:ChargeFreeQuantity"> + <br/> + <span> + <xsl:text>kostenfrei:</xsl:text> + </span> + <br/> + <xsl:call-template name="ram:Menge"/> + </xsl:for-each> + </xsl:for-each> + </td> + <td style="border-bottom-style:solid; border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; width:110px; "> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeSettlement"> + <xsl:for-each select="ram:ApplicableTradeTax"> + <xsl:call-template name="ram:TradeTax"/> + </xsl:for-each> + </xsl:for-each> + </td> + <td style="border-bottom-style:solid; border-collapse:collapse; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; width:110px; "> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeSettlement"> + <xsl:for-each select="ram:SpecifiedTradeSettlementMonetarySummation"> + <xsl:for-each select="ram:LineTotalAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_11"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_11" select="string($altova:seqContentStrings_11)"/> + <xsl:value-of select="$altova:sContent_11"/> + </span> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </td> + </tr> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:if> + <xsl:for-each select="ram:AssociatedDocumentLineDocument"> + <xsl:if test="fn:not( fn:empty(ram:IncludedNote))"> + <xsl:variable name="altova:table"> + <table style="border:0px; border-collapse:collapse; border-spacing:0px; border-top-style:none; padding:0px; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_12" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <tr style="empty-cells:hide; vertical-align:top; "> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:center; width:30px; "> + <xsl:for-each select="ram:LineID"> + <xsl:apply-templates/> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; width:110px; "/> + <td style="border-bottom-style:none; border-collapse:collapse; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; "> + <xsl:for-each select="ram:IncludedNote"> + <xsl:for-each select="ram:Content"> + <span style="white-space:pre-wrap; "> + <xsl:apply-templates/> + </span> + </xsl:for-each> + <xsl:for-each select="ram:SubjectCode"> + <br/> + <span style="color:gray; empty-cells:hide; "> + <xsl:text>Qualifizierung der Textart: </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:ContentCode"> + <span style="color:gray; empty-cells:hide; "> + <xsl:text>, Qualifizierung des Textes: </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <br/> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; width:110px; "/> + </tr> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:if> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeAgreement"> + <xsl:for-each select="ram:GrossPriceProductTradePrice"> + <xsl:if test="fn:not( fn:empty(ram:AppliedTradeAllowanceCharge))"> + <xsl:variable name="altova:table"> + <table style="border:0px; border-collapse:collapse; border-spacing:0px; padding:0px; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_13" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <tr style="empty-cells:hide; vertical-align:top; "> + <td style="border-bottom-style:none; border-left-style:none; border-top-style:none; width:30px; "/> + <td style="border-bottom-style:none; border-top-style:none; width:110px; "/> + <td style="border-bottom-style:none; border-right-style:none; border-top-style:none; "> + <xsl:variable name="altova:table"> + <table style="border:0px; border-style:none; padding:0px; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_14" select="."/> + <xsl:variable name="altova:ColumnData"/> + <thead> + <tr> + <th style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; font-weight:normal; text-align:left; width:70px; "> + <span style="font-style:italic; "> + <xsl:text>Art</xsl:text> + </span> + </th> + <th style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; font-weight:normal; text-align:left; "> + <span style="font-style:italic; "> + <xsl:text>Grund</xsl:text> + </span> + </th> + <th style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; font-weight:normal; text-align:right; width:70px; "> + <span style="font-style:italic; "> + <xsl:text>%</xsl:text> + </span> + </th> + <th style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; font-weight:normal; text-align:right; width:110px; "> + <span style="font-style:italic; "> + <xsl:text>Basisbetrag</xsl:text> + </span> + </th> + <th style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; font-weight:normal; text-align:right; width:120px; "> + <span style="font-style:italic; "> + <xsl:text>Basismenge</xsl:text> + </span> + </th> + <th style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; font-weight:normal; text-align:right; width:110px; "> + <span style="font-style:italic; "> + <xsl:text>Betrag</xsl:text> + </span> + </th> + <th style="border-bottom-style:none; border-left-style:none; border-right-style:none; border-top-style:none; width:112px; "/> + </tr> + </thead> + <tbody> + <xsl:for-each select="ram:AppliedTradeAllowanceCharge"> + <xsl:sort select="ram:SequenceNumeric" data-type="text" order="ascending"/> + <tr> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; vertical-align:top; width:70px; "> + <xsl:for-each select="ram:ChargeIndicator"> + <xsl:for-each select="udt:Indicator"> + <span> + <xsl:value-of select="if (. eq fn:true())then 'Zuschlag' else 'Abschlag'"/> + </span> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SequenceNumeric"> + <span> + <xsl:text> Nr. </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; vertical-align:top; "> + <xsl:for-each select="ram:Reason"> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:ReasonCode"> + <span> + <xsl:text> </xsl:text> + </span> + <xsl:call-template name="AllowanceChargeReasonCode"/> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; vertical-align:top; width:70px; "> + <xsl:for-each select="ram:CalculationPercent"> + <span> + <xsl:variable name="altova:seqContentStrings_15"> + <xsl:value-of select="format-number(number(string(.)), '###.##0,####', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_15" select="string($altova:seqContentStrings_15)"/> + <xsl:value-of select="$altova:sContent_15"/> + </span> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; vertical-align:top; width:110px; "> + <xsl:for-each select="ram:BasisAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_16"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_16" select="string($altova:seqContentStrings_16)"/> + <xsl:value-of select="$altova:sContent_16"/> + </span> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; vertical-align:top; width:120px; "> + <xsl:for-each select="ram:BasisQuantity"> + <xsl:call-template name="ram:Menge"/> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; vertical-align:top; width:110px; "> + <xsl:for-each select="ram:ActualAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_17"> + <xsl:value-of select="format-number(number(if(../ram:ChargeIndicator/udt:Indicator = fn:false()) then -1*. else .), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_17" select="string($altova:seqContentStrings_17)"/> + <xsl:value-of select="$altova:sContent_17"/> + </span> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; width:108px; "/> + </tr> + </xsl:for-each> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </td> + </tr> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:if> + <xsl:if test="fn:exists(../../ram:SpecifiedSupplyChainTradeSettlement/ram:SpecifiedTradeSettlementMonetarySummation/ram:TotalAllowanceChargeAmount)"> + <xsl:variable name="altova:table"> + <table style="border:0px; border-collapse:collapse; border-spacing:0px; padding:0px; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_18" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <tr style="empty-cells:hide; vertical-align:top; "> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; width:30px; "/> + <td style="border-bottom-style:none; border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; width:110px; "/> + <td style="border-bottom-style:none; border-collapse:collapse; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; "> + <br/> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; width:110px; "> + <span> + <xsl:text>Summe:</xsl:text> + </span> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-right-style:none; border-spacing:0px; border-top-style:double; empty-cells:hide; text-align:right; width:110px; "> + <xsl:for-each select="$XML"> + <xsl:for-each select="rsm:CrossIndustryDocument"> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:IncludedSupplyChainTradeLineItem"> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeSettlement"> + <xsl:for-each select="ram:SpecifiedTradeSettlementMonetarySummation"> + <xsl:for-each select="ram:TotalAllowanceChargeAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_19"> + <xsl:value-of select="format-number(number(-1*.), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_19" select="string($altova:seqContentStrings_19)"/> + <xsl:value-of select="$altova:sContent_19"/> + </span> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-collapse:collapse; border-left-style:none; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; text-align:right; width:110px; "/> + </tr> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:if> + </xsl:for-each> + </xsl:for-each> + <xsl:variable name="altova:table"> + <table style="border:0px; border-collapse:collapse; border-spacing:0px; border-top-style:none; padding:0px; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_20" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <tr style="empty-cells:hide; vertical-align:top; "> + <td style="border-collapse:collapse; border-left-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; width:30px; "/> + <td style="border-collapse:collapse; border-spacing:0px; border-top-style:none; empty-cells:hide; width:110px; "/> + <td style="border-collapse:collapse; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; "> + <xsl:for-each select="ram:SpecifiedTradeProduct"> + <xsl:for-each select="ram:Description"> + <br/> + <span style="white-space:pre-wrap; "> + <xsl:apply-templates/> + </span> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeDelivery"> + <xsl:for-each select="ram:ActualDeliverySupplyChainEvent"> + <xsl:for-each select="ram:OccurrenceDateTime"> + <br/> + <span> + <xsl:text>* Leistungsdatum: </xsl:text> + </span> + <xsl:for-each select="udt:DateTimeString"> + <xsl:call-template name="ram:Datum"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeSettlement"> + <xsl:for-each select="ram:BillingSpecifiedPeriod"> + <br/> + <span> + <xsl:text>* Berechnungszeitraum: </xsl:text> + </span> + <xsl:for-each select="ram:StartDateTime"> + <xsl:for-each select="udt:DateTimeString"> + <xsl:call-template name="ram:Datum"/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:EndDateTime"> + <span> + <xsl:text> bis </xsl:text> + </span> + <xsl:for-each select="udt:DateTimeString"> + <xsl:call-template name="ram:Datum"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedTradeProduct"> + <xsl:for-each select="ram:OriginTradeCountry"> + <xsl:for-each select="ram:ID"> + <br/> + <span> + <xsl:text>* Herkunftsland: </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeDelivery"> + <xsl:for-each select="ram:PackageQuantity"> + <br/> + <span> + <xsl:text>* Anzahl Packstücke: </xsl:text> + </span> + <span> + <xsl:variable name="altova:seqContentStrings_21"> + <xsl:value-of select="format-number(number(string(.)), '##0', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_21" select="string($altova:seqContentStrings_21)"/> + <xsl:value-of select="$altova:sContent_21"/> + </span> + </xsl:for-each> + <xsl:call-template name="PackageQuantity"/> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeAgreement"> + <xsl:for-each select="ram:BuyerOrderReferencedDocument"> + <br/> + <span> + <xsl:text>* Bestellung</xsl:text> + </span> + <xsl:call-template name="ram:Positionsreferenz"/> + </xsl:for-each> + <xsl:for-each select="ram:ContractReferencedDocument"> + <br/> + <span> + <xsl:text>* Vertrag</xsl:text> + </span> + <xsl:call-template name="ram:Positionsreferenz"/> + </xsl:for-each> + <xsl:for-each select="ram:AdditionalReferencedDocument"> + <br/> + <span> + <xsl:text>* Dokument (</xsl:text> + </span> + <xsl:for-each select="ram:ReferenceTypeCode"> + <xsl:call-template name="ram:Referenz"/> + </xsl:for-each> + <span> + <xsl:text>)</xsl:text> + </span> + <xsl:call-template name="ram:Positionsreferenz"/> + </xsl:for-each> + <xsl:for-each select="ram:CustomerOrderReferencedDocument"> + <br/> + <span> + <xsl:text>* Kundenbestellung</xsl:text> + </span> + <xsl:call-template name="ram:Positionsreferenz"/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeDelivery"> + <xsl:for-each select="ram:DespatchAdviceReferencedDocument"> + <br/> + <span> + <xsl:text>* Lieferavis</xsl:text> + </span> + <xsl:call-template name="ram:Positionsreferenz"/> + </xsl:for-each> + <xsl:for-each select="ram:ReceivingAdviceReferencedDocument"> + <br/> + <span> + <xsl:text>* Wareneingang </xsl:text> + </span> + <xsl:call-template name="ram:Positionsreferenz"/> + </xsl:for-each> + <xsl:for-each select="ram:DeliveryNoteReferencedDocument"> + <br/> + <span> + <xsl:text>* Lieferschein</xsl:text> + </span> + <xsl:call-template name="ram:Positionsreferenz"/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeSettlement"> + <xsl:for-each select="ram:SpecifiedTradeAccountingAccount"> + <xsl:for-each select="ram:ID"> + <br/> + <span> + <xsl:text>* Buchungsreferenz: </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedTradeProduct"> + <xsl:for-each select="ram:DesignatedProductClassification"> + <br/> + <span> + <xsl:text>* Klassifikation: </xsl:text> + </span> + <xsl:for-each select="ram:ClassCode"> + <span> + <xsl:text>[</xsl:text> + </span> + <xsl:apply-templates/> + <span> + <xsl:text>] </xsl:text> + </span> + </xsl:for-each> + <xsl:for-each select="ram:ClassName"> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:ClassCode"> + <xsl:call-template name="Klassifikationsart"/> + <xsl:for-each select="@listVersionID"> + <span> + <xsl:text>, Version: </xsl:text> + </span> + <span> + <xsl:value-of select="string(.)"/> + </span> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedSupplyChainTradeDelivery"> + <xsl:for-each select="ram:ShipToTradeParty"> + <br/> + <span style="text-decoration:underline; "> + <xsl:text>Abweichender Warenempfänger:</xsl:text> + </span> + <br/> + <xsl:call-template name="ram:Party"/> + </xsl:for-each> + <xsl:for-each select="ram:UltimateShipToTradeParty"> + <br/> + <span style="text-decoration:underline; "> + <xsl:text>Abweichender Endempfänger:</xsl:text> + </span> + <br/> + <xsl:call-template name="ram:Party"/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedTradeProduct"> + <xsl:if test="fn:exists(ram:ApplicableProductCharacteristic)"> + <br/> + <br/> + <span style="text-decoration:underline; "> + <xsl:text>Weitere Eigenschaften:</xsl:text> + </span> + <br/> + </xsl:if> + <xsl:for-each select="ram:ApplicableProductCharacteristic"> + <xsl:for-each select="ram:Description"> + <br/> + <xsl:apply-templates/> + </xsl:for-each> + <span> + <xsl:text>: </xsl:text> + </span> + <xsl:for-each select="ram:TypeCode"> + <xsl:apply-templates/> + </xsl:for-each> + <span> + <xsl:text> = </xsl:text> + </span> + <xsl:for-each select="ram:Value"> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:ValueMeasure"> + <xsl:call-template name="ram:Menge"/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:if test="fn:exists(ram:SpecifiedTradeProduct/ram:IncludedReferencedProduct)"> + <br/> + <br/> + <span style="text-decoration:underline; "> + <xsl:text>Basisartikel:</xsl:text> + </span> + <br/> + </xsl:if> + <xsl:for-each select="ram:SpecifiedTradeProduct"> + <xsl:if test="fn:exists(ram:IncludedReferencedProduct)"> + <xsl:variable name="altova:table"> + <table style="border:0px; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_22" select="."/> + <xsl:variable name="altova:ColumnData"/> + <thead> + <tr> + <th style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; text-align:left; width:110px; "> + <span style="font-weight:bold; "> + <xsl:text>Art-Nr-Kunde</xsl:text> + </span> + <br/> + </th> + <th style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; width:110px; "> + <span style="font-weight:bold; "> + <xsl:text>Art-Nr-Lief.</xsl:text> + </span> + </th> + <th style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; width:110px; "> + <span> + <xsl:text>Art-Nr. (Art)</xsl:text> + </span> + </th> + <th style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; "> + <span> + <xsl:text>Beschreibung</xsl:text> + </span> + </th> + <th style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; text-align:right; width:120px; "> + <span> + <xsl:text>Menge</xsl:text> + </span> + </th> + </tr> + </thead> + <tbody> + <xsl:for-each select="ram:IncludedReferencedProduct"> + <tr> + <td style="border-bottom-style:none; border-left-style:none; border-right-style:none; border-top-style:none; text-align:left; vertical-align:top; width:110px; "> + <xsl:for-each select="ram:BuyerAssignedID"> + <xsl:apply-templates/> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-left-style:none; border-right-style:none; border-top-style:none; vertical-align:top; width:110px; "> + <xsl:for-each select="ram:SellerAssignedID"> + <xsl:apply-templates/> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-left-style:none; border-right-style:none; border-top-style:none; vertical-align:top; width:110px; "> + <xsl:for-each select="ram:GlobalID"> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:GlobalID"> + <xsl:for-each select="@schemeID"> + <xsl:call-template name="ram:Global_Identifier"/> + </xsl:for-each> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-left-style:none; border-right-style:none; border-top-style:none; vertical-align:top; "> + <xsl:for-each select="ram:Name"> + <xsl:apply-templates/> + </xsl:for-each> + <br/> + <xsl:for-each select="ram:Description"> + <xsl:apply-templates/> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-left-style:none; border-right-style:none; border-top-style:none; text-align:right; vertical-align:top; width:120px; "> + <xsl:for-each select="ram:UnitQuantity"> + <xsl:call-template name="ram:Menge"/> + </xsl:for-each> + </td> + </tr> + </xsl:for-each> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:if> + </xsl:for-each> + </td> + <td style="border-collapse:collapse; border-left-style:none; border-right-style:none; border-spacing:0px; border-top-style:none; empty-cells:hide; width:110px; "/> + </tr> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:for-each> + </xsl:for-each> + <br/> + </td> + </tr> + <tr> + <td style="border-bottom-style:none; border-top-style:none; "> + <xsl:if test="fn:exists(rsm:SpecifiedSupplyChainTradeTransaction/ram:ApplicableSupplyChainTradeSettlement/ram:SpecifiedTradePaymentTerms)"> + <br/> + <span style="empty-cells:hide; font-weight:bold; text-decoration:underline; "> + <xsl:text>Zahlungsbedingungen:</xsl:text> + </span> + <br/> + <br/> + <xsl:variable name="altova:table"> + <table style="border:0px; border-collapse:collapse; border-right-style:none; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_23" select="."/> + <xsl:variable name="altova:ColumnData"/> + <thead> + <tr> + <th style="border-left-style:none; "> + <span> + <xsl:text>Beschreibung</xsl:text> + </span> + </th> + <th style="width:110px; "> + <span> + <xsl:text>Fälligkeit</xsl:text> + </span> + </th> + <th style="border-right-style:none; width:110px; "> + <span> + <xsl:text>Teilzahlung</xsl:text> + </span> + </th> + </tr> + </thead> + <tbody> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeSettlement"> + <xsl:for-each select="ram:SpecifiedTradePaymentTerms"> + <tr> + <td style="border-bottom-style:none; border-left-style:none; "> + <xsl:for-each select="ram:Description"> + <span style="white-space:pre-wrap; "> + <xsl:apply-templates/> + </span> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; text-align:center; width:110px; "> + <xsl:for-each select="ram:DueDateDateTime"> + <xsl:for-each select="udt:DateTimeString"> + <xsl:call-template name="ram:Datum"/> + </xsl:for-each> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-right-style:none; text-align:right; width:110px; "> + <xsl:for-each select="ram:PartialPaymentAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_24"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_24" select="string($altova:seqContentStrings_24)"/> + <xsl:value-of select="$altova:sContent_24"/> + </span> + </xsl:for-each> + </td> + </tr> + <tr> + <td colspan="3" style="border-left-style:none; border-right-style:none; border-top-style:none; min-height:0px; "> + <xsl:if test="fn:exists(ram:ApplicableTradePaymentPenaltyTerms) or fn:exists(ram:ApplicableTradePaymentDiscountTerms)"> + <xsl:variable name="altova:table"> + <table style="border:0px; border-collapse:collapse; border-left-style:none; border-top-style:none; margin:0px; padding:0px; " border="1" width="100%"> + <xsl:variable name="altova:CurrContextGrid_25" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <tr style="border-bottom-style:none; border-top-style:none; "> + <td style="border-bottom-style:none; border-left-style:none; border-top-style:none; min-height:0px; "/> + <td style="border-bottom-style:none; min-height:0px; text-align:center; width:110px; "> + <span style="font-weight:bold; "> + <xsl:text>Bezug</xsl:text> + </span> + </td> + <td style="border-bottom-style:none; min-height:0px; text-align:center; width:110px; "> + <span style="font-weight:bold; "> + <xsl:text>Innerhalb</xsl:text> + </span> + </td> + <td style="border-bottom-style:none; min-height:0px; text-align:center; width:110px; "> + <span style="font-weight:bold; "> + <xsl:text>Basisbetrag</xsl:text> + </span> + </td> + <td style="border-bottom-style:none; min-height:0px; text-align:center; width:110px; "> + <span style="font-weight:bold; "> + <xsl:text>%</xsl:text> + </span> + </td> + <td style="border-bottom-style:none; border-right-style:none; min-height:0px; text-align:center; width:108px; "> + <span style="font-weight:bold; "> + <xsl:text>Betrag</xsl:text> + </span> + </td> + </tr> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:if> + <xsl:if test="fn:exists(ram:ApplicableTradePaymentPenaltyTerms)"> + <xsl:variable name="altova:table"> + <table style="border:0px; border-bottom-style:none; border-collapse:collapse; margin:0px; padding:0px; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_26" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <xsl:for-each select="ram:ApplicableTradePaymentPenaltyTerms"> + <tr> + <td style="border-bottom-style:none; border-left-style:none; min-height:0px; text-align:right; "> + <span> + <xsl:text>Zuschlag  </xsl:text> + </span> + </td> + <td style="border-bottom-style:none; min-height:0px; text-align:center; width:110px; "> + <xsl:for-each select="ram:BasisDateTime"> + <xsl:for-each select="udt:DateTimeString"> + <xsl:call-template name="ram:Datum"/> + </xsl:for-each> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; min-height:0px; text-align:right; width:110px; "> + <xsl:for-each select="ram:BasisPeriodMeasure"> + <xsl:call-template name="ram:Menge"/> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; min-height:0px; text-align:right; width:110px; "> + <xsl:for-each select="ram:BasisAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_27"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_27" select="string($altova:seqContentStrings_27)"/> + <xsl:value-of select="$altova:sContent_27"/> + </span> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; min-height:0px; text-align:right; width:110px; "> + <xsl:for-each select="ram:CalculationPercent"> + <span> + <xsl:variable name="altova:seqContentStrings_28"> + <xsl:value-of select="format-number(number(string(.)), '###.##0,####', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_28" select="string($altova:seqContentStrings_28)"/> + <xsl:value-of select="$altova:sContent_28"/> + </span> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-right-style:none; min-height:0px; text-align:right; width:108px; "> + <xsl:for-each select="ram:ActualPenaltyAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_29"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_29" select="string($altova:seqContentStrings_29)"/> + <xsl:value-of select="$altova:sContent_29"/> + </span> + </xsl:for-each> + </td> + </tr> + </xsl:for-each> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:if> + <xsl:if test="fn:exists(ram:ApplicableTradePaymentDiscountTerms)"> + <xsl:variable name="altova:table"> + <table style="border:0px; border-collapse:collapse; margin:0px; padding:0px; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_30" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <xsl:for-each select="ram:ApplicableTradePaymentDiscountTerms"> + <tr> + <td style="border-bottom-style:none; border-left-style:none; min-height:0px; text-align:right; "> + <span> + <xsl:text>Skonto  </xsl:text> + </span> + </td> + <td style="border-bottom-style:none; min-height:0px; text-align:center; width:110px; "> + <xsl:for-each select="ram:BasisDateTime"> + <xsl:for-each select="udt:DateTimeString"> + <xsl:call-template name="ram:Datum"/> + </xsl:for-each> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; min-height:0px; text-align:right; width:110px; "> + <xsl:for-each select="ram:BasisPeriodMeasure"> + <xsl:call-template name="ram:Menge"/> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; min-height:0px; text-align:right; width:110px; "> + <xsl:for-each select="ram:BasisAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_31"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_31" select="string($altova:seqContentStrings_31)"/> + <xsl:value-of select="$altova:sContent_31"/> + </span> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; min-height:0px; text-align:right; width:110px; "> + <xsl:for-each select="ram:CalculationPercent"> + <span> + <xsl:variable name="altova:seqContentStrings_32"> + <xsl:value-of select="format-number(number(string(.)), '###.##0,####', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_32" select="string($altova:seqContentStrings_32)"/> + <xsl:value-of select="$altova:sContent_32"/> + </span> + </xsl:for-each> + </td> + <td style="border-bottom-style:none; border-right-style:none; min-height:0px; text-align:right; width:108px; "> + <xsl:for-each select="ram:ActualDiscountAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_33"> + <xsl:value-of select="format-number(number(-1 * .), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_33" select="string($altova:seqContentStrings_33)"/> + <xsl:value-of select="$altova:sContent_33"/> + </span> + </xsl:for-each> + </td> + </tr> + </xsl:for-each> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:if> + </td> + </tr> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:if> + <xsl:if test="fn:exists(rsm:SpecifiedSupplyChainTradeTransaction/ram:ApplicableSupplyChainTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans)"> + <br/> + <span style="font-weight:bold; text-decoration:underline; "> + <xsl:text>Zahlungsart:</xsl:text> + </span> + <br/> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeSettlement"> + <xsl:for-each select="ram:SpecifiedTradeSettlementPaymentMeans"> + <xsl:for-each select="ram:Information"> + <br/> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:TypeCode"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Zahlungstyp (codiert): </xsl:text> + </span> + <xsl:call-template name="ram:PaymentType"/> + </xsl:for-each> + <xsl:for-each select="ram:ID"> + <xsl:for-each select="@schemeAgencyID"> + <br/> + <span> + <xsl:text>Gläubiger-ID         : </xsl:text> + </span> + <span> + <xsl:value-of select="string(.)"/> + </span> + </xsl:for-each> + <br/> + <span> + <xsl:text>Mandatsreferenz      : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:PayerPartyDebtorFinancialAccount"> + <xsl:for-each select="ram:IBANID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Käufer-IBAN          : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:ProprietaryID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Käufer-Kontonummer   : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:PayerSpecifiedDebtorFinancialInstitution"> + <xsl:for-each select="ram:BICID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Käufer-BIC           : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:GermanBankleitzahlID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Käufer-Bankleitzahl  : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:Name"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Käufer-Kreditinstitut: </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + <br/> + <xsl:for-each select="ram:PayeePartyCreditorFinancialAccount"> + <xsl:for-each select="ram:AccountName"> + <br/> + <span> + <xsl:text>Verkäufer-Kontoname  : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:IBANID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Verkäufer-IBAN       : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:ProprietaryID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Verkäufer-Kontonummer: </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:PayeeSpecifiedCreditorFinancialInstitution"> + <xsl:for-each select="ram:BICID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Verkäufer-BIC        : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:GermanBankleitzahlID"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Verkäufer-BLZ        : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:Name"> + <br/> + <span style="empty-cells:hide; "> + <xsl:text>Verkäufer-Kreditinst.: </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:if> + </td> + </tr> + <tr> + <td style="border-bottom-style:none; border-right-style:none; border-top-style:none; "> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeSettlement"> + <br/> + <xsl:if test="fn:exists(ram:SpecifiedTradeAllowanceCharge) or fn:exists(ram:SpecifiedLogisticsServiceCharge)"> + <span style="font-weight:bold; text-decoration:underline; "> + <xsl:text>Zu- und Abschläge:</xsl:text> + </span> + <br/> + <br/> + <xsl:variable name="altova:table"> + <table style="border:0px; border-collapse:collapse; empty-cells:hide; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_34" select="."/> + <xsl:variable name="altova:ColumnData"/> + <thead> + <tr> + <th colspan="2" style="border-left-style:none; "> + <span> + <xsl:text>Art</xsl:text> + </span> + </th> + <th> + <span> + <xsl:text>%</xsl:text> + </span> + </th> + <th> + <span> + <xsl:text>Basisbetrag</xsl:text> + </span> + </th> + <th style="width:110px; "> + <span> + <xsl:text>Basismenge</xsl:text> + </span> + </th> + <th style="width:110px; "> + <span> + <xsl:text>Steuer</xsl:text> + </span> + </th> + <th style="border-right-style:none; width:110px; "> + <span> + <xsl:text>Betrag</xsl:text> + </span> + </th> + </tr> + </thead> + <tbody> + <xsl:for-each select="ram:SpecifiedTradeAllowanceCharge"> + <xsl:sort select="ram:SequenceNumeric" data-type="text" order="ascending"/> + <tr> + <td style="border-left-style:none; "> + <xsl:for-each select="ram:ChargeIndicator"> + <xsl:for-each select="udt:Indicator"> + <span> + <xsl:value-of select="if (. eq fn:true())then 'Zuschlag' else 'Abschlag'"/> + </span> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SequenceNumeric"> + <span> + <xsl:text> Nr. </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </td> + <td> + <xsl:for-each select="ram:Reason"> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:ReasonCode"> + <span> + <xsl:text> </xsl:text> + </span> + <xsl:call-template name="AllowanceChargeReasonCode"/> + </xsl:for-each> + </td> + <td style="text-align:right; "> + <xsl:for-each select="ram:CalculationPercent"> + <span> + <xsl:variable name="altova:seqContentStrings_35"> + <xsl:value-of select="format-number(number(string(.)), '###.##0,####', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_35" select="string($altova:seqContentStrings_35)"/> + <xsl:value-of select="$altova:sContent_35"/> + </span> + </xsl:for-each> + </td> + <td style="text-align:right; "> + <xsl:for-each select="ram:BasisAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_36"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_36" select="string($altova:seqContentStrings_36)"/> + <xsl:value-of select="$altova:sContent_36"/> + </span> + </xsl:for-each> + </td> + <td style="text-align:right; width:110px; "> + <xsl:for-each select="ram:BasisQuantity"> + <xsl:call-template name="ram:Menge"/> + </xsl:for-each> + </td> + <td style="text-align:right; width:110px; "> + <xsl:for-each select="ram:CategoryTradeTax"> + <xsl:call-template name="ram:TradeTax"/> + </xsl:for-each> + </td> + <td style="border-right-style:none; text-align:right; width:110px; "> + <xsl:for-each select="ram:ActualAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_37"> + <xsl:value-of select="format-number(number(if (../ram:ChargeIndicator/udt:Indicator eq fn:true()) then . else -1 * .), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_37" select="string($altova:seqContentStrings_37)"/> + <xsl:value-of select="$altova:sContent_37"/> + </span> + </xsl:for-each> + </td> + </tr> + </xsl:for-each> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + <xsl:if test="fn:exists(ram:SpecifiedLogisticsServiceCharge)"> + <xsl:if test="fn:not(fn:exists(ram:SpecifiedTradeAllowanceCharge))"> + <xsl:variable name="altova:table"> + <table style="border:0px; border-top-style:none; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_38" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <xsl:for-each select="ram:SpecifiedLogisticsServiceCharge"> + <tr> + <td style="border-left-style:none; border-top-style:solid; text-align:center; "> + <span style="font-weight:bold; "> + <xsl:text>Art</xsl:text> + </span> + </td> + <td style="border-top-style:solid; text-align:center; width:110px; "> + <span style="font-weight:bold; "> + <xsl:text>Steuer</xsl:text> + </span> + </td> + <td style="border-right-style:none; border-top-style:solid; text-align:center; width:110px; "> + <span style="font-weight:bold; "> + <xsl:text>Betrag</xsl:text> + </span> + </td> + </tr> + </xsl:for-each> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:if> + <xsl:variable name="altova:table"> + <table style="border:0px; border-top-style:none; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_39" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <xsl:for-each select="ram:SpecifiedLogisticsServiceCharge"> + <tr> + <td style="border-left-style:none; border-top-style:none; "> + <xsl:for-each select="ram:Description"> + <span style="white-space:pre-wrap; "> + <xsl:apply-templates/> + </span> + </xsl:for-each> + </td> + <td style="border-top-style:none; text-align:right; width:110px; "> + <xsl:for-each select="ram:AppliedTradeTax"> + <xsl:call-template name="ram:TradeTax"/> + </xsl:for-each> + </td> + <td style="border-right-style:none; border-top-style:none; text-align:right; width:110px; "> + <xsl:for-each select="ram:AppliedAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_40"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_40" select="string($altova:seqContentStrings_40)"/> + <xsl:value-of select="$altova:sContent_40"/> + </span> + </xsl:for-each> + </td> + </tr> + </xsl:for-each> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:if> + </xsl:if> + <br/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeSettlement"/> + </xsl:for-each> + </td> + </tr> + <tr> + <td style="border-bottom-style:none; border-top-style:none; "> + <xsl:if test="fn:exists(rsm:SpecifiedSupplyChainTradeTransaction/ram:ApplicableSupplyChainTradeSettlement/ram:ApplicableTradeTax)"> + <br/> + <span style="font-weight:bold; text-decoration:underline; "> + <xsl:text>Steuern:</xsl:text> + </span> + <br/> + <br/> + <xsl:variable name="altova:table"> + <table style="border:0px; border-collapse:collapse; border-right-style:none; width:100%; " border="1"> + <xsl:variable name="altova:CurrContextGrid_41" select="."/> + <xsl:variable name="altova:ColumnData"/> + <thead> + <tr> + <th style="border-left-style:none; "> + <span> + <xsl:text>Art (Kategorie)</xsl:text> + </span> + </th> + <th> + <span> + <xsl:text>Warenwert</xsl:text> + </span> + </th> + <th> + <span> + <xsl:text>Zu-/Abschlag</xsl:text> + </span> + </th> + <th style="width:110px; "> + <span> + <xsl:text>Nettobetrag</xsl:text> + </span> + </th> + <th style="width:110px; "> + <span> + <xsl:text>USt. %</xsl:text> + </span> + </th> + <th style="border-right-style:none; width:110px; "> + <span> + <xsl:text>USt.-Betrag</xsl:text> + </span> + </th> + </tr> + </thead> + <tbody> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeSettlement"> + <xsl:for-each select="ram:ApplicableTradeTax"> + <tr> + <td style="border-left-style:none; "> + <xsl:for-each select="ram:TypeCode"> + <xsl:apply-templates/> + </xsl:for-each> + <span> + <xsl:text> </xsl:text> + </span> + <xsl:for-each select="ram:CategoryCode"> + <span> + <xsl:text>(</xsl:text> + </span> + <xsl:apply-templates/> + <span> + <xsl:text>)</xsl:text> + </span> + </xsl:for-each> + <xsl:for-each select="ram:ExemptionReason"> + <br/> + <xsl:apply-templates/> + </xsl:for-each> + </td> + <td style="text-align:right; "> + <xsl:for-each select="ram:LineTotalBasisAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_42"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_42" select="string($altova:seqContentStrings_42)"/> + <xsl:value-of select="$altova:sContent_42"/> + </span> + </xsl:for-each> + </td> + <td style="text-align:right; "> + <xsl:for-each select="ram:AllowanceChargeBasisAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_43"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_43" select="string($altova:seqContentStrings_43)"/> + <xsl:value-of select="$altova:sContent_43"/> + </span> + </xsl:for-each> + </td> + <td style="text-align:right; width:110px; "> + <xsl:for-each select="ram:BasisAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_44"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_44" select="string($altova:seqContentStrings_44)"/> + <xsl:value-of select="$altova:sContent_44"/> + </span> + </xsl:for-each> + </td> + <td style="text-align:right; width:110px; "> + <xsl:for-each select="ram:ApplicablePercent"> + <span> + <xsl:variable name="altova:seqContentStrings_45"> + <xsl:value-of select="format-number(number(string(.)), '###.##0,####', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_45" select="string($altova:seqContentStrings_45)"/> + <xsl:value-of select="$altova:sContent_45"/> + </span> + </xsl:for-each> + </td> + <td style="border-right-style:none; text-align:right; width:110px; "> + <xsl:for-each select="ram:CalculatedAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_46"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_46" select="string($altova:seqContentStrings_46)"/> + <xsl:value-of select="$altova:sContent_46"/> + </span> + </xsl:for-each> + </td> + </tr> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:if> + </td> + </tr> + <tr> + <td style="border-bottom-style:none; text-align:left; "> + <br/> + <span style="font-weight:bold; text-decoration:underline; "> + <xsl:text>Belegsummen:</xsl:text> + </span> + <br/> + <xsl:for-each select="rsm:SpecifiedSupplyChainTradeTransaction"> + <xsl:for-each select="ram:ApplicableSupplyChainTradeSettlement"> + <xsl:for-each select="ram:SpecifiedTradeSettlementMonetarySummation"> + <xsl:variable name="altova:table"> + <table style="border:0px; " border="1" width="100%"> + <xsl:variable name="altova:CurrContextGrid_47" select="."/> + <xsl:variable name="altova:ColumnData"/> + <tbody> + <tr> + <td style="border-style:none; "/> + <td style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; padding:1px; text-align:left; width:220px; "> + <span style="font-weight:bold; "> + <xsl:text>Positionssumme</xsl:text> + </span> + </td> + <td style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; padding:1px; text-align:right; width:110px; "> + <xsl:for-each select="ram:LineTotalAmount"> + <span style="font-weight:bold; "> + <xsl:variable name="altova:seqContentStrings_48"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_48" select="string($altova:seqContentStrings_48)"/> + <xsl:value-of select="$altova:sContent_48"/> + </span> + </xsl:for-each> + </td> + </tr> + <tr> + <td style="border-style:none; "/> + <td style="border:0px; border-top-style:double; padding:1px; text-align:left; width:220px; "> + <span> + <xsl:text>Gesamtbetrag der Zuschläge</xsl:text> + </span> + </td> + <td style="border:0px; border-top-style:double; padding:1px; text-align:right; width:110px; "> + <xsl:for-each select="ram:ChargeTotalAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_49"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_49" select="string($altova:seqContentStrings_49)"/> + <xsl:value-of select="$altova:sContent_49"/> + </span> + </xsl:for-each> + </td> + </tr> + <tr> + <td style="border-style:none; "/> + <td style="border:0px; border-top-style:double; padding:1px; text-align:left; width:220px; "> + <span> + <xsl:text>Gesamtbetrag der Abschläge</xsl:text> + </span> + </td> + <td style="border:0px; border-top-style:double; padding:1px; text-align:right; width:110px; "> + <xsl:for-each select="ram:AllowanceTotalAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_50"> + <xsl:value-of select="format-number(number(-1*.), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_50" select="string($altova:seqContentStrings_50)"/> + <xsl:value-of select="$altova:sContent_50"/> + </span> + </xsl:for-each> + </td> + </tr> + <tr> + <td style="border-style:none; "/> + <td style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; padding:1px; text-align:left; width:220px; "> + <span style="font-weight:bold; "> + <xsl:text>Rechnungssumme ohne USt.</xsl:text> + </span> + </td> + <td style="border-bottom-style:solid; border-left-style:none; border-right-style:none; border-top-style:none; padding:1px; text-align:right; width:110px; "> + <xsl:for-each select="ram:TaxBasisTotalAmount"> + <span style="font-weight:bold; "> + <xsl:variable name="altova:seqContentStrings_51"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_51" select="string($altova:seqContentStrings_51)"/> + <xsl:value-of select="$altova:sContent_51"/> + </span> + </xsl:for-each> + </td> + </tr> + <tr> + <td style="border-style:none; "/> + <td style="border:0px; border-top-style:double; padding:1px; text-align:left; width:220px; "> + <span> + <xsl:text>Steuerbetrag</xsl:text> + </span> + </td> + <td style="border:0px; border-top-style:double; padding:1px; text-align:right; width:110px; "> + <xsl:for-each select="ram:TaxTotalAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_52"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_52" select="string($altova:seqContentStrings_52)"/> + <xsl:value-of select="$altova:sContent_52"/> + </span> + </xsl:for-each> + </td> + </tr> + <tr> + <td style="border-style:none; "/> + <td style="border-bottom-style:double; border-bottom-width:medium; border-left-style:none; border-right-style:none; border-top-style:none; padding:1px; text-align:left; width:220px; "> + <span style="font-weight:bold; "> + <xsl:text>Bruttosumme</xsl:text> + </span> + </td> + <td style="border-bottom-style:double; border-bottom-width:medium; border-left-style:none; border-right-style:none; border-top-style:none; padding:1px; text-align:right; width:110px; "> + <xsl:for-each select="ram:GrandTotalAmount"> + <span style="font-weight:bold; "> + <xsl:variable name="altova:seqContentStrings_53"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_53" select="string($altova:seqContentStrings_53)"/> + <xsl:value-of select="$altova:sContent_53"/> + </span> + </xsl:for-each> + </td> + </tr> + <tr> + <td style="border-style:none; "/> + <td style="border:0px; border-top-style:double; padding:1px; text-align:left; width:220px; "> + <xsl:if test="(ram:TotalPrepaidAmount>=0 and fn:exists(ram:TotalPrepaidAmount)) or(fn:not(fn:exists(ram:TotalPrepaidAmount)) and fn:not(ends-with( ../../../rsm:SpecifiedExchangedDocumentContext/ram:GuidelineSpecifiedDocumentContextParameter/ram:ID , 'basic' )))"> + <span> + <xsl:text>Erhaltene Anzahlungen</xsl:text> + </span> + <br/> + </xsl:if> + <xsl:if test="ram:TotalPrepaidAmount<0 and fn:exists(ram:TotalPrepaidAmount)"> + <span> + <xsl:text>Offene Zahlungen</xsl:text> + </span> + <br/> + </xsl:if> + </td> + <td style="border:0px; border-top-style:double; padding:1px; text-align:right; width:110px; "> + <xsl:if test="fn:exists(TotalPrepaidAmount) or fn:not(ends-with( ../../../rsm:SpecifiedExchangedDocumentContext/ram:GuidelineSpecifiedDocumentContextParameter/ram:ID , 'basic' ))"> + <xsl:for-each select="ram:TotalPrepaidAmount"> + <span> + <xsl:variable name="altova:seqContentStrings_54"> + <xsl:value-of select="format-number(number(-1*.), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_54" select="string($altova:seqContentStrings_54)"/> + <xsl:value-of select="$altova:sContent_54"/> + </span> + </xsl:for-each> + </xsl:if> + </td> + </tr> + <tr> + <td style="border-style:none; "/> + <td style="border:0px; border-top-style:double; padding:1px; text-align:left; width:220px; "> + <xsl:if test="fn:exists(ram:DuePayableAmount) or fn:not(ends-with( ../../../rsm:SpecifiedExchangedDocumentContext/GuidelineSpecifiedDocumentContextParameter/ID , 'basic' ))"> + <span style="font-weight:bold; "> + <xsl:text>Zahlbetrag</xsl:text> + </span> + </xsl:if> + </td> + <td style="border:0px; border-top-style:double; padding:1px; text-align:right; width:110px; "> + <xsl:if test="fn:exists(ram:DuePayableAmount) or fn:not(ends-with( ../../../rsm:SpecifiedExchangedDocumentContext/GuidelineSpecifiedDocumentContextParameter/ID , 'basic' ))"> + <xsl:for-each select="ram:DuePayableAmount"> + <span style="font-weight:bold; "> + <xsl:variable name="altova:seqContentStrings_55"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_55" select="string($altova:seqContentStrings_55)"/> + <xsl:value-of select="$altova:sContent_55"/> + </span> + </xsl:for-each> + </xsl:if> + </td> + </tr> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </td> + </tr> + </tbody> + </table> + </xsl:variable> + <xsl:variable name="altova:col-count" select="sum( for $altova:cell in $altova:table/table/(thead | tbody | tfoot)[ 1 ]/tr[ 1 ]/(th | td) return altova:col-span( $altova:cell ) )"/> + <xsl:variable name="altova:generate-cols" as="xs:boolean*" select="for $altova:pos in 1 to $altova:col-count return true()"/> + <xsl:apply-templates select="$altova:table" mode="altova:generate-table"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + <br/> + </xsl:for-each> + </xsl:for-each> + <br/> + <br/> + </body> + </html> + </xsl:template> + <xsl:template name="ram:Party"> + <xsl:for-each select="ram:ID"> + <span> + <xsl:text>Nummer        : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="@schemeID"> + <xsl:call-template name="local_Identifier"/> + </xsl:for-each> + <xsl:for-each select="ram:GlobalID"> + <br/> + <span> + <xsl:text>Globale Nummer: </xsl:text> + </span> + <xsl:apply-templates/> + <xsl:for-each select="@schemeID"> + <span> + <xsl:text> </xsl:text> + </span> + <xsl:call-template name="ram:Global_Identifier"/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:Name"> + <br/> + <span style="font-weight:bold; white-space:pre-wrap; "> + <xsl:apply-templates/> + </span> + </xsl:for-each> + <xsl:for-each select="ram:DefinedTradeContact"> + <xsl:for-each select="ram:PersonName"> + <br/> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:DepartmentName"> + <br/> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:PostalTradeAddress"> + <xsl:for-each select="ram:LineOne"> + <br/> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:LineTwo"> + <br/> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:CountryID"> + <br/> + <xsl:apply-templates/> + <span> + <xsl:text> </xsl:text> + </span> + </xsl:for-each> + <xsl:for-each select="ram:PostcodeCode"> + <xsl:apply-templates/> + <span> + <xsl:text> </xsl:text> + </span> + </xsl:for-each> + <xsl:for-each select="ram:CityName"> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + <br/> + <xsl:for-each select="ram:DefinedTradeContact"> + <xsl:for-each select="ram:TelephoneUniversalCommunication"> + <xsl:for-each select="ram:CompleteNumber"> + <br/> + <span> + <xsl:text>Telefon      : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:FaxUniversalCommunication"> + <xsl:for-each select="ram:CompleteNumber"> + <br/> + <span> + <xsl:text>Fax          : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:EmailURIUniversalCommunication"> + <xsl:for-each select="ram:URIID"> + <br/> + <span> + <xsl:text>E-Mail       : </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + <xsl:for-each select="ram:SpecifiedTaxRegistration"> + <xsl:for-each select="ram:ID"> + <br/> + <xsl:call-template name="ram:TaxRegistration"/> + </xsl:for-each> + </xsl:for-each> + <br/> + </xsl:template> + <xsl:template name="ram:TradeTax"> + <xsl:for-each select="ram:ApplicablePercent"> + <span> + <xsl:variable name="altova:seqContentStrings_56"> + <xsl:value-of select="format-number(number(string(.)), '###.##0,####', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_56" select="string($altova:seqContentStrings_56)"/> + <xsl:value-of select="$altova:sContent_56"/> + </span> + <span> + <xsl:text> %</xsl:text> + </span> + </xsl:for-each> + <xsl:for-each select="ram:TypeCode"> + <span> + <xsl:text> </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:CategoryCode"> + <span> + <xsl:text> (</xsl:text> + </span> + <xsl:apply-templates/> + <span> + <xsl:text>)</xsl:text> + </span> + </xsl:for-each> + <xsl:for-each select="ram:CalculatedAmount"> + <span> + <xsl:text> entspricht </xsl:text> + </span> + <span> + <xsl:variable name="altova:seqContentStrings_57"> + <xsl:value-of select="format-number(number(string(.)), '##0,00', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_57" select="string($altova:seqContentStrings_57)"/> + <xsl:value-of select="$altova:sContent_57"/> + </span> + </xsl:for-each> + <xsl:for-each select="ram:ExemptionReason"> + <br/> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:template> + <xsl:template name="ram:Positionsreferenz"> + <xsl:for-each select="ram:ID"> + <span> + <xsl:text> Nr. </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + <xsl:for-each select="ram:IssueDateTime"> + <span> + <xsl:text> vom </xsl:text> + </span> + <span> + <xsl:variable name="altova:seqContentStrings_58"> + <xsl:value-of select="format-number(number(substring(string(string(.)), 9, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(.)), 6, 2)), '00', 'format1')"/> + <xsl:variable name="sText" as="xs:string?"> + <xsl:text>. </xsl:text> + </xsl:variable> + <xsl:value-of select="$sText"/> + <xsl:value-of select="format-number(number(substring(string(string(string(.))), 1, 4)), '0000', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_58" select="string($altova:seqContentStrings_58)"/> + <xsl:value-of select="$altova:sContent_58"/> + </span> + </xsl:for-each> + <xsl:for-each select="ram:LineID"> + <span> + <xsl:text> Zeile </xsl:text> + </span> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:template> + <xsl:template name="ram:Datum"> + <span> + <xsl:value-of select="if ( @format = '102') then concat(substring(.,7,2),'.',substring(.,5,2),'.',substring(.,1,4)) else +if ( @format = '610') then concat(substring(.,5,2),'-',substring(.,1,4)) else +if ( @format = '616') then concat('KW ',substring(.,5,2),' ',substring(.,1,4)) else +concat('Ungültiges Datumsformat für: ', .)"/> + </span> + </xsl:template> + <xsl:template name="ram:Versand_Identifer"> + <span> + <xsl:value-of select="if(. eq 'GSIN') then . else +if(. eq 'GINC') then . else +if(. eq 'SSCC') then 'Nummer der Versandeinheit' else +if(. eq 'FLIGHT_NO') then 'Flugnummer' else +if(. eq 'NUMBER_PLATE') then 'Nummernschild' else +if(. eq 'SHIPMENT_REFERENCE') then 'Sendungs-/Ladungsbezugsnummer' else +."/> + </span> + </xsl:template> + <xsl:template name="ram:Global_Identifier"> + <span> + <xsl:text>(</xsl:text> + </span> + <span> + <xsl:value-of select="if (. eq '0021') then 'BIC' else +if (. eq '0060') then 'DUNS' else +if (. eq '0088') then 'GTIN' else +if (. eq '0160') then 'GLN' else +if (. eq '0177') then 'OSCAR' else +."/> + </span> + <span> + <xsl:text>)</xsl:text> + </span> + </xsl:template> + <xsl:template name="ram:Menge"> + <span> + <xsl:variable name="altova:seqContentStrings_59"> + <xsl:value-of select="format-number(number(string(.)), '##0', 'format1')"/> + </xsl:variable> + <xsl:variable name="altova:sContent_59" select="string($altova:seqContentStrings_59)"/> + <xsl:value-of select="$altova:sContent_59"/> + </span> + <xsl:for-each select="@unitCode"> + <span> + <xsl:text> </xsl:text> + </span> + <span> + <xsl:value-of select="if (. eq 'C62') then 'Stk' else +if (. eq 'DAY') then 'Tag(e)' else +if (. eq 'HAR') then 'ha' else +if (. eq 'HUR') then 'Std' else +if (. eq 'KGM') then 'kg' else +if (. eq 'KTM') then 'km' else +if (. eq 'LS') then 'pausch' else +if (. eq 'LTR') then 'l' else +if (. eq 'MIN') then 'min' else +if (. eq 'MMK') then 'mm²' else +if (. eq 'MMT') then 'mm' else +if (. eq 'MTK') then 'm²' else +if (. eq 'MTQ') then 'm³' else +if (. eq 'MTR') then 'm' else +if (. eq 'NAR') then 'Anz' else +if (. eq 'NPR') then 'Paar' else +if (. eq 'P1') then '%' else +if (. eq 'SET') then 'Set' else +if (. eq 'TNE') then 't' else +if (. eq 'WEE') then 'Woche(n)' else +."/> + </span> + </xsl:for-each> + </xsl:template> + <xsl:template name="ram:TaxRegistration"> + <span> + <xsl:value-of select="if ( @schemeID = 'FC') then concat('Steuernummer : ', .) else +if ( @schemeID = 'VA') then concat('USt.-Id.-Nr. : ', .) else +concat('Unbekannte Steuernummer (', @schemeID , '): ', .)"/> + </span> + </xsl:template> + <xsl:template name="ram:VersandMode"> + <span> + <xsl:value-of select="if (. eq '0')then '0 - Nicht spezifiziert' else +if (. eq '1')then '1 - Seefracht' else +if (. eq '2')then '2 - Schiene' else +if (. eq '3')then '3 - Straße' else +if (. eq '4')then '4 - Luftfracht' else +if (. eq '5')then '5 - Post/Paketversand' else +if (. eq '6')then '6 - Multimodaler Transport/kombinierter Verkehr' else +if (. eq '7')then '7 - Feste Transportinstallation' else +if (. eq '8')then '8 - Transport auf Binnengewässern' else +if (. eq '9')then '9 - Nicht anwendbar' else +fn:concat(.,' - unbekannte Transportart')"/> + </span> + </xsl:template> + <xsl:template name="ram:PaymentType"> + <span> + <xsl:value-of select="if(. eq '1') then concat(.,' - nicht definiert') else +if(. eq '3') then concat(.,' - Belastung durch automatisierte Clearingstelle') else +if(. eq '10') then concat(.,' - Barzahlung') else +if(. eq '20') then concat(.,' - per Scheck') else +if(. eq '31') then concat(.,' - per Überweisung (SEPA)') else +if(. eq '42') then concat(.,' - per Überweisung (nicht SEPA)') else +if(. eq '48') then concat(.,' - per Kreditkarte') else +if(. eq '49') then concat(.,' - per Lastschrift') else +if(. eq '97') then concat(.,' - per Ausgleich zwischen Partnern') else +."/> + </span> + </xsl:template> + <xsl:template name="ram:Referenz"> + <span> + <xsl:value-of select="if (. eq 'AAA')then 'Auftragsbestätigung' else +if (. eq 'AAB')then 'Proforma-Rechnung' else +if (. eq 'AAG') then 'Angebot' else +if (. eq 'AAJ') then 'Lieferauftrag' else +if (. eq 'AAL') then 'Zeichnung' else +if (. eq 'AAM') then 'Frachtbrief' else +if (. eq 'AAS') then 'Transportdokument' else +if (. eq 'ABT') then 'Zollerklärung' else +if (. eq 'AER') then 'Projektspezifikation' else +if (. eq 'AGG') then 'Reklamation' else +if (. eq 'AJS') then 'Vereinbarung' else +if (. eq 'ALO') then 'Wareneingang' else +if (. eq 'ALQ') then 'Rücksendungsanzeige' else +if (. eq 'API') then 'Bestandsbericht' else +if (. eq 'ASI') then 'Abliefernachweis' else +if (. eq 'AUD') then 'Inkasso-Referenz' else +if (. eq 'AWR') then 'Ursprungsbeleg' else +if (. eq 'BO') then 'Rahmenauftrag' else +if (. eq 'BC') then 'Vertrag (Käufer)' else +if (. eq 'CD') then 'Gutschrift' else +if (. eq 'DL') then 'Belastungsanzeige' else +if (. eq 'MG') then 'Zählernummer' else +if (. eq 'OI') then 'Vorherige Rechnung' else +if (. eq 'PK') then 'Packliste' else +if (. eq 'PL') then 'Preisliste' else +if (. eq 'POR') then 'Bestellantwort' else +if (. eq 'PP') then 'Bestelländerung' else +if (. eq 'TIN') then 'Transportauftrag' else +if (. eq 'VN') then 'Auftragsnummer (Lieferant)' else +."/> + </span> + </xsl:template> + <xsl:template name="PackageQuantity"> + <xsl:for-each select="ram:PackageQuantity"> + <xsl:for-each select="@unitCode"> + <span> + <xsl:text> </xsl:text> + </span> + <span> + <xsl:value-of select="if (. eq 'BA') then 'Tonne' else +if (. eq 'BC') then 'Getränkekiste' else +if (. eq 'BG') then 'Tüte, Beutel' else +if (. eq 'BO') then 'Flasche' else +if (. eq 'BX') then 'Schachtel' else +if (. eq 'CS') then 'Kiste' else +if (. eq 'CT') then 'Karton' else +if (. eq 'CX') then 'Dose' else +if (. eq 'NE') then 'Unverpackt oder ausgepackt' else +if (. eq 'PX') then 'Palette' else +if (. eq 'RO') then 'Rolle' else +if (. eq 'SA') then 'Sack' +else ."/> + </span> + </xsl:for-each> + </xsl:for-each> + </xsl:template> + <xsl:template name="local_Identifier"> + <span> + <xsl:text>(</xsl:text> + </span> + <xsl:choose> + <xsl:when test=". instance of element()"> + <xsl:apply-templates/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="."/> + </xsl:otherwise> + </xsl:choose> + <span> + <xsl:text>)</xsl:text> + </span> + </xsl:template> + <xsl:template name="Klassifikationsart"> + <xsl:for-each select="@listID"> + <span> + <xsl:text>, Art: </xsl:text> + </span> + <span> + <xsl:value-of select="if (. eq 'GPC') then 'Global Product Classification (GS1)' else +if (. eq 'ECL') then 'eCl@ass' else +if (. eq 'UNSPSC') then 'United Nations Standard Products and Services Code® (UNSPSC®)' else +if (. eq 'HS') then 'Zolltarifnummer (Harmonised System)' else +if (. eq 'CBV') then 'Gemeinsames Vokabular für öffentliche Aufträge (Common Procurement Vocabulary - CPV)' else +if (. eq 'SELLER_ASSIGNED') then 'vom Verkäufer vergeben' else +if (. eq 'BUYER_ASSIGNED') then 'vom Käufer vergeben' else +."/> + </span> + </xsl:for-each> + </xsl:template> + <xsl:template name="DeliveryTypeCode"> + <span> + <xsl:value-of select="if (. eq 'XW') then 'ab Werk' else +if (. eq 'FCA') then 'frei Frachtführer' else +if (. eq 'FAS') then 'frei längsseits Schiff' else +if (. eq 'FOB') then 'frei an Bord' else +if (. eq 'CFR') then 'Kosten und Fracht' else +if (. eq 'CIF') then 'Kosten, Versicherung und Fracht bis zum Bestimmungshafen' else +if (. eq 'DAT') then 'geliefert Terminal' else +if (. eq 'DAP') then 'geliefert benannter Ort' else +if (. eq 'CPT') then 'Fracht bezahlt bis' else +if (. eq 'CIP') then 'Fracht und Versicherung bezahlt' else +if (. eq 'DDP') then 'geliefert Zoll bezahlt' else +."/> + </span> + </xsl:template> + <xsl:template name="AllowanceChargeReasonCode"> + <span> + <xsl:text>(</xsl:text> + </span> + <span> + <xsl:value-of select="if (. eq 'AA') then 'Werbekostenzuschuß' else +if (. eq 'ADR') then 'Andere Dienste' else +if (. eq 'AEO') then 'Sammel- und Recyclingservice' else +if (. eq 'DI') then 'Abzug (Rabatt)' else +if (. eq 'EAB') then 'Skonto' else +if (. eq 'FC') then 'Frachtgebühren' else +if (. eq 'IN') then 'Versicherung' else +if (. eq 'MAC') then 'Mindermengenzuschlag' else +if (. eq 'NAA') then 'Einwegbehälter' else +if (. eq 'PC') then 'Verpacken' else +if (. eq 'RAA') then 'Rückvergütung' else +if (. eq 'SH') then 'Spezielle Handhabungsdienstleistungen' else +."/> + </span> + <span> + <xsl:text>)</xsl:text> + </span> + </xsl:template> + <xsl:function name="altova:is-cell-empty" as="xs:boolean"> + <xsl:param name="altova:cell" as="element()"/> + <xsl:sequence select="altova:is-node-empty( $altova:cell )"/> + </xsl:function> + <xsl:function name="altova:is-node-empty" as="xs:boolean"> + <xsl:param name="altova:node" as="element()"/> + <xsl:sequence select="every $altova:child in $altova:node/child::node() satisfies ( ( boolean( $altova:child/self::text() ) and string-length( $altova:child ) = 0 ) or ( ( boolean( $altova:child/self::div ) or boolean( $altova:child/self::span ) or boolean( $altova:child/self::a ) ) and altova:is-node-empty( $altova:child ) ) )"/> + </xsl:function> + <xsl:function name="altova:col-span" as="xs:integer"> + <xsl:param name="altova:cell" as="element()"/> + <xsl:sequence select="if ( exists( $altova:cell/@colspan ) ) then xs:integer( $altova:cell/@colspan ) else 1"/> + </xsl:function> + <xsl:template match="@* | node()" mode="altova:generate-table"> + <xsl:param name="altova:generate-cols"/> + <xsl:copy> + <xsl:apply-templates select="@* | node()" mode="#current"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:copy> + </xsl:template> + <xsl:template match="tbody" mode="altova:generate-table"> + <xsl:param name="altova:generate-cols"/> + <xsl:choose> + <xsl:when test="empty(tr)"> + <xsl:copy> + <tr> + <td/> + </tr> + </xsl:copy> + </xsl:when> + <xsl:otherwise> + <xsl:copy> + <xsl:apply-templates select="@* | node()" mode="#current"> + <xsl:with-param name="altova:generate-cols" select="$altova:generate-cols"/> + </xsl:apply-templates> + </xsl:copy> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + <xsl:template match="th | td" mode="altova:generate-table"> + <xsl:choose> + <xsl:when test="altova:is-cell-empty( . )"> + <xsl:copy> + <xsl:apply-templates select="@*" mode="#current"/> + <xsl:text> </xsl:text> + </xsl:copy> + </xsl:when> + <xsl:otherwise> + <xsl:copy> + <xsl:apply-templates select="@* | node()" mode="#current"/> + </xsl:copy> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + <xsl:function name="altova:GetChartYValuesForSingleSeries"> + <xsl:param name="seqCategoryLeafPos" as="node()*"/> + <xsl:param name="nodeSeriesLeafPos" as="node()"/> + <xsl:param name="bValuesInCategory" as="xs:boolean"/> + <xsl:for-each select="$seqCategoryLeafPos"> + <xsl:element name="altova:Value"> + <xsl:value-of select="altova:GetChartYValueForSingleSeriesPos($nodeSeriesLeafPos, ., $bValuesInCategory)"/> + </xsl:element> + </xsl:for-each> + </xsl:function> + <xsl:function name="altova:GetChartYValueForSingleSeriesPos"> + <xsl:param name="nodeSeriesLeafPos" as="node()"/> + <xsl:param name="nodeCategoryLeafPos" as="node()"/> + <xsl:param name="bValuesInCategory" as="xs:boolean"/> + <xsl:variable name="altova:seqCategoryContextIds" select="$nodeCategoryLeafPos/altova:Context/@altova:ContextId" as="xs:string*"/> + <xsl:variable name="altova:seqSeriesContextIds" select="$nodeSeriesLeafPos/altova:Context/@altova:ContextId" as="xs:string*"/> + <xsl:variable name="altova:sCommonContextId" select="for $i in $altova:seqCategoryContextIds return if (some $j in $altova:seqSeriesContextIds satisfies $i eq $j) then $i else ()" as="xs:string*"/> + <xsl:choose> + <xsl:when test="count($altova:sCommonContextId) gt 1"> + <xsl:message select="concat('Es wurden mehrere Werte anstatt eines einzigen gefunden (Contexts: ', string-join($altova:sCommonContextId, ', '), ').')" terminate="yes"/> + </xsl:when> + <xsl:when test="count($altova:sCommonContextId) lt 1"> + <xsl:message select="concat('XBRL Chart: Info: No value found for position labeled "', $nodeCategoryLeafPos/@altova:sLabel, '"')" terminate="no"/> + <xsl:sequence select="'altova:no-value'"/> + </xsl:when> + <xsl:when test="$bValuesInCategory"> + <xsl:sequence select="xs:string($nodeCategoryLeafPos/altova:Context[@altova:ContextId eq $altova:sCommonContextId]/@altova:Value)"/> + </xsl:when> + <xsl:otherwise> + <xsl:sequence select="xs:string($nodeSeriesLeafPos/altova:Context[@altova:ContextId eq $altova:sCommonContextId]/@altova:Value)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:function> + <xsl:function name="altova:GetChartLabelForPos" as="xs:string"> + <xsl:param name="nodeParam" as="node()"/> + <xsl:value-of select="string-join($nodeParam/ancestor-or-self::altova:Pos/@altova:sLabel, ' ')"/> + </xsl:function> + <xsl:function name="altova:convert-length-to-pixel" as="xs:decimal"> + <xsl:param name="altova:length"/> + <xsl:variable name="normLength" select="normalize-space($altova:length)"/> + <xsl:choose> + <xsl:when test="ends-with($normLength, 'px')"> + <xsl:value-of select="substring-before($normLength, 'px')"/> + </xsl:when> + <xsl:when test="ends-with($normLength, 'in')"> + <xsl:value-of select="xs:decimal(substring-before($normLength, 'in')) * $altova:nPxPerIn"/> + </xsl:when> + <xsl:when test="ends-with($normLength, 'cm')"> + <xsl:value-of select="xs:decimal(substring-before($normLength, 'cm')) * $altova:nPxPerIn div 2.54"/> + </xsl:when> + <xsl:when test="ends-with($normLength, 'mm')"> + <xsl:value-of select="xs:decimal(substring-before($normLength, 'mm')) * $altova:nPxPerIn div 25.4"/> + </xsl:when> + <xsl:when test="ends-with($normLength, 'pt')"> + <xsl:value-of select="xs:decimal(substring-before($normLength, 'pt')) * $altova:nPxPerIn div 72.0"/> + </xsl:when> + <xsl:when test="ends-with($normLength, 'pc')"> + <xsl:value-of select="xs:decimal(substring-before($normLength, 'pc')) * $altova:nPxPerIn div 6.0"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$normLength"/> + </xsl:otherwise> + </xsl:choose> + </xsl:function> + <xsl:function name="altova:convert-length-to-mm" as="xs:decimal"> + <xsl:param name="altova:length"/> + <xsl:variable name="normLength" select="normalize-space($altova:length)"/> + <xsl:choose> + <xsl:when test="ends-with($normLength, 'px')"> + <xsl:value-of select="xs:decimal(substring-before($normLength, 'px')) div $altova:nPxPerIn * 25.4"/> + </xsl:when> + <xsl:when test="ends-with($normLength, 'in')"> + <xsl:value-of select="xs:decimal(substring-before($normLength, 'in')) * 25.4"/> + </xsl:when> + <xsl:when test="ends-with($normLength, 'cm')"> + <xsl:value-of select="xs:decimal(substring-before($normLength, 'cm')) * 10"/> + </xsl:when> + <xsl:when test="ends-with($normLength, 'mm')"> + <xsl:value-of select="substring-before($normLength, 'mm') "/> + </xsl:when> + <xsl:when test="ends-with($normLength, 'pt')"> + <xsl:value-of select="xs:decimal(substring-before($normLength, 'pt')) * 25.4 div 72.0"/> + </xsl:when> + <xsl:when test="ends-with($normLength, 'pc')"> + <xsl:value-of select="xs:decimal(substring-before($normLength, 'pc')) * 25.4 div 6.0"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="number($normLength) div $altova:nPxPerIn * 25.4"/> + </xsl:otherwise> + </xsl:choose> + </xsl:function> +</xsl:stylesheet> diff --git a/src/main/resources/stylesheets/cii-xr.xsl b/src/main/resources/stylesheets/cii-xr.xsl new file mode 100644 index 00000000..5fca7b9d --- /dev/null +++ b/src/main/resources/stylesheets/cii-xr.xsl @@ -0,0 +1,2202 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xr="urn:ce.eu:en16931:2017:xoev-de:kosit:standard:xrechnung-1" + xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" + xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" + xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" + xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100" + xmlns:saxon="http://saxon.sf.net/" + exclude-result-prefixes="#all" + version="2.0"> + <xd:doc scope="stylesheet"> + <xd:desc> + <xd:p> + <xd:b>Author:</xd:b> KoSIT Bremen (kosit@finanzen.bremen.de)</xd:p> + <xd:b>Fassung vom: 2019-03-18+01:00</xd:b> + <xd:p>Überführt eine zur EN 16931 konforme elektronische Rechnung in der konkreten Syntax UNCEFACT.CII.D16B in eine Instanz gemäß des Schemas für den Namensraum urn:ce.eu:en16931:2017:xoev-de:kosit:standard:xrechnung-1.</xd:p> + <xd:p>Das Skript setzt voraus, dass das zu verarbeitende Dokument valide bzgl. des XML Schemas und der Schematron-Regeln der Quelle ist. Für nicht valide Dokumente ist das Ergebnis nicht definiert.</xd:p> + </xd:desc> + </xd:doc> + + <xsl:output method="xml" indent="yes"/> + + <xsl:template match="/rsm:CrossIndustryInvoice"> + <xr:invoice> + <xsl:variable name="current-bg" as="element()" select="."/> + <xsl:apply-templates mode="BT-1" select="./rsm:ExchangedDocument/ram:ID"/> + <xsl:apply-templates mode="BT-2" + select="./rsm:ExchangedDocument/ram:IssueDateTime/udt:DateTimeString[@format = '102']"/> + <xsl:apply-templates mode="BT-3" select="./rsm:ExchangedDocument/ram:TypeCode"/> + <xsl:apply-templates mode="BT-5" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:InvoiceCurrencyCode"/> + <xsl:apply-templates mode="BT-6" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:TaxCurrencyCode"/> + <xsl:apply-templates mode="BT-7" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax/ram:TaxPointDate/udt:DateString[@format = '102']"/> + <xsl:apply-templates mode="BT-8" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax/ram:DueDateTypeCode"/> + <xsl:apply-templates mode="BT-9" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms/ram:DueDateDateTime/udt:DateTimeString[@format = '102']"/> + <xsl:apply-templates mode="BT-10" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerReference"/> + <xsl:apply-templates mode="BT-11" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SpecifiedProcuringProject/ram:ID"/> + <xsl:apply-templates mode="BT-12" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:ContractReferencedDocument/ram:IssuerAssignedID"/> + <xsl:apply-templates mode="BT-13" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerOrderReferencedDocument/ram:IssuerAssignedID"/> + <xsl:apply-templates mode="BT-14" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerOrderReferencedDocument/ram:IssuerAssignedID"/> + <xsl:apply-templates mode="BT-15" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ReceivingAdviceReferencedDocument/ram:IssuerAssignedID"/> + <xsl:apply-templates mode="BT-16" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:DespatchAdviceReferencedDocument/ram:IssuerAssignedID"/> + <xsl:apply-templates mode="BT-17" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument/ram:IssuerAssignedID[following-sibling::ram:TypeCode='50']"/> + <xsl:apply-templates mode="BT-18" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument/ram:IssuerAssignedID[following-sibling::ram:TypeCode='130']"/> + <xsl:apply-templates mode="BT-19" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ReceivableSpecifiedTradeAccountingAccount/ram:ID"/> + <xsl:apply-templates mode="BT-20" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms/ram:Description"/> + <xsl:apply-templates mode="BG-1" select="./rsm:ExchangedDocument/ram:IncludedNote"/> + <xsl:apply-templates mode="BG-2" select="./rsm:ExchangedDocumentContext"/> + <xsl:apply-templates mode="BG-3" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument"/> + <xsl:apply-templates mode="BG-4" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty"/> + <xsl:apply-templates mode="BG-7" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty"/> + <xsl:apply-templates mode="BG-10" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:PayeeTradeParty"/> + <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"/> + <!--Manuell: angepasst für BG-16--> + <xsl:for-each-group select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans" + group-by="ram:TypeCode"> + <xr:PAYMENT_INSTRUCTIONS> + <xsl:attribute name="xr:id" select="'BG-16'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:apply-templates mode="BT-81" select="current-group()[1]/ram:TypeCode"/> + <xsl:apply-templates mode="BT-82" select="./ram:Information"/> + <xsl:apply-templates mode="BT-83" + select="current-group()[1]/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:PaymentReference"/> + <xsl:apply-templates mode="BG-17" + select="current-group()/ram:PayeePartyCreditorFinancialAccount"/> + <xsl:apply-templates mode="BG-18" + select="current-group()/ram:ApplicableTradeSettlementFinancialCard"/> + <xsl:apply-templates mode="BG-19" + select="current-group()/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement"/> + </xr:PAYMENT_INSTRUCTIONS> + </xsl:for-each-group> + <xsl:apply-templates mode="BG-20" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='false']"/> + <xsl:apply-templates mode="BG-21" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='true']"/> + <xsl:apply-templates mode="BG-22" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation"/> + <xsl:apply-templates mode="BG-23" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax"/> + <xsl:apply-templates mode="BG-24" + select="./rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument"/> + <xsl:apply-templates mode="BG-25" + select="./rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem"/> + </xr:invoice> + </xsl:template> + <xsl:template mode="BT-1" + match="/rsm:CrossIndustryInvoice/rsm:ExchangedDocument/ram:ID"> + <xr:Invoice_number> + <xsl:attribute name="xr:id" select="'BT-1'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Invoice_number> + </xsl:template> + <xsl:template mode="BT-2" + match="/rsm:CrossIndustryInvoice/rsm:ExchangedDocument/ram:IssueDateTime/udt:DateTimeString[@format = '102']"> + <xr:Invoice_issue_date> + <xsl:attribute name="xr:id" select="'BT-2'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="date"/> + </xr:Invoice_issue_date> + </xsl:template> + <xsl:template mode="BT-3" + match="/rsm:CrossIndustryInvoice/rsm:ExchangedDocument/ram:TypeCode"> + <xr:Invoice_type_code> + <xsl:attribute name="xr:id" select="'BT-3'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Invoice_type_code> + </xsl:template> + <xsl:template mode="BT-5" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:InvoiceCurrencyCode"> + <xr:Invoice_currency_code> + <xsl:attribute name="xr:id" select="'BT-5'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Invoice_currency_code> + </xsl:template> + <xsl:template mode="BT-6" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:TaxCurrencyCode"> + <xr:VAT_accounting_currency_code> + <xsl:attribute name="xr:id" select="'BT-6'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:VAT_accounting_currency_code> + </xsl:template> + <xsl:template mode="BT-7" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax/ram:TaxPointDate/udt:DateString[@format = '102']"> + <xr:Value_added_tax_point_date> + <xsl:attribute name="xr:id" select="'BT-7'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="date"/> + </xr:Value_added_tax_point_date> + </xsl:template> + <xsl:template mode="BT-8" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax/ram:DueDateTypeCode"> + <xr:Value_added_tax_point_date_code> + <xsl:attribute name="xr:id" select="'BT-8'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Value_added_tax_point_date_code> + </xsl:template> + <xsl:template mode="BT-9" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms/ram:DueDateDateTime/udt:DateTimeString[@format = '102']"> + <xr:Payment_due_date> + <xsl:attribute name="xr:id" select="'BT-9'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="date"/> + </xr:Payment_due_date> + </xsl:template> + <xsl:template mode="BT-10" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerReference"> + <xr:Buyer_reference> + <xsl:attribute name="xr:id" select="'BT-10'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_reference> + </xsl:template> + <xsl:template mode="BT-11" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SpecifiedProcuringProject/ram:ID"> + <xr:Project_reference> + <xsl:attribute name="xr:id" select="'BT-11'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="document_reference"/> + </xr:Project_reference> + </xsl:template> + <xsl:template mode="BT-12" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:ContractReferencedDocument/ram:IssuerAssignedID"> + <xr:Contract_reference> + <xsl:attribute name="xr:id" select="'BT-12'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="document_reference"/> + </xr:Contract_reference> + </xsl:template> + <xsl:template mode="BT-13" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerOrderReferencedDocument/ram:IssuerAssignedID"> + <xr:Purchase_order_reference> + <xsl:attribute name="xr:id" select="'BT-13'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="document_reference"/> + </xr:Purchase_order_reference> + </xsl:template> + <xsl:template mode="BT-14" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerOrderReferencedDocument/ram:IssuerAssignedID"> + <xr:Sales_order_reference> + <xsl:attribute name="xr:id" select="'BT-14'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="document_reference"/> + </xr:Sales_order_reference> + </xsl:template> + <xsl:template mode="BT-15" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ReceivingAdviceReferencedDocument/ram:IssuerAssignedID"> + <xr:Receiving_advice_reference> + <xsl:attribute name="xr:id" select="'BT-15'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="document_reference"/> + </xr:Receiving_advice_reference> + </xsl:template> + <xsl:template mode="BT-16" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:DespatchAdviceReferencedDocument/ram:IssuerAssignedID"> + <xr:Despatch_advice_reference> + <xsl:attribute name="xr:id" select="'BT-16'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="document_reference"/> + </xr:Despatch_advice_reference> + </xsl:template> + <xsl:template mode="BT-17" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument/ram:IssuerAssignedID[following-sibling::ram:TypeCode='50']"> + <xr:Tender_or_lot_reference> + <xsl:attribute name="xr:id" select="'BT-17'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="document_reference"/> + </xr:Tender_or_lot_reference> + </xsl:template> + <xsl:template mode="BT-18" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument/ram:IssuerAssignedID[following-sibling::ram:TypeCode='130']"> + <xr:Invoiced_object_identifier> + <xsl:attribute name="xr:id" select="'BT-18'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"> + <xsl:with-param name="schemeID" select="following-sibling::ram:ReferenceTypeCode"/> + </xsl:call-template> + </xr:Invoiced_object_identifier> + </xsl:template> + <xsl:template mode="BT-19" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ReceivableSpecifiedTradeAccountingAccount/ram:ID"> + <xr:Buyer_accounting_reference> + <xsl:attribute name="xr:id" select="'BT-19'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_accounting_reference> + </xsl:template> + <xsl:template mode="BT-20" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms/ram:Description"> + <xr:Payment_terms> + <xsl:attribute name="xr:id" select="'BT-20'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Payment_terms> + </xsl:template> + <xsl:template mode="BG-1" + match="/rsm:CrossIndustryInvoice/rsm:ExchangedDocument/ram:IncludedNote"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:ExchangedDocument/ram:IncludedNote der Instanz in konkreter Syntax wird auf 2 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-21" select="./ram:SubjectCode"/> + <xsl:apply-templates mode="BT-22" select="./ram:Content"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:INVOICE_NOTE> + <xsl:attribute name="xr:id" select="'BG-1'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:INVOICE_NOTE> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-21" + match="/rsm:CrossIndustryInvoice/rsm:ExchangedDocument/ram:IncludedNote/ram:SubjectCode"> + <xr:Invoice_note_subject_code> + <xsl:attribute name="xr:id" select="'BT-21'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Invoice_note_subject_code> + </xsl:template> + <xsl:template mode="BT-22" + match="/rsm:CrossIndustryInvoice/rsm:ExchangedDocument/ram:IncludedNote/ram:Content"> + <xr:Invoice_note> + <xsl:attribute name="xr:id" select="'BT-22'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Invoice_note> + </xsl:template> + <xsl:template mode="BG-2" + match="/rsm:CrossIndustryInvoice/rsm:ExchangedDocumentContext"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:ExchangedDocumentContext der Instanz in konkreter Syntax wird auf 2 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-23" + select="./ram:BusinessProcessSpecifiedDocumentContextParameter/ram:ID"/> + <xsl:apply-templates mode="BT-24" + select="./ram:GuidelineSpecifiedDocumentContextParameter/ram:ID"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:PROCESS_CONTROL> + <xsl:attribute name="xr:id" select="'BG-2'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:PROCESS_CONTROL> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-23" + match="/rsm:CrossIndustryInvoice/rsm:ExchangedDocumentContext/ram:BusinessProcessSpecifiedDocumentContextParameter/ram:ID"> + <xr:Business_process_type> + <xsl:attribute name="xr:id" select="'BT-23'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Business_process_type> + </xsl:template> + <xsl:template mode="BT-24" + match="/rsm:CrossIndustryInvoice/rsm:ExchangedDocumentContext/ram:GuidelineSpecifiedDocumentContextParameter/ram:ID"> + <xr:Specification_identifier> + <xsl:attribute name="xr:id" select="'BT-24'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Specification_identifier> + </xsl:template> + <xsl:template mode="BG-3" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument der Instanz in konkreter Syntax wird auf 2 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-25" select="./ram:IssuerAssignedID"/> + <xsl:apply-templates mode="BT-26" + select="./ram:FormattedIssueDateTime/qdt:DateTimeString[@format = '102']"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:PRECEDING_INVOICE_REFERENCE> + <xsl:attribute name="xr:id" select="'BG-3'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:PRECEDING_INVOICE_REFERENCE> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-25" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument/ram:IssuerAssignedID"> + <xr:Preceding_Invoice_reference> + <xsl:attribute name="xr:id" select="'BT-25'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="document_reference"/> + </xr:Preceding_Invoice_reference> + </xsl:template> + <xsl:template mode="BT-26" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString[@format = '102']"> + <xr:Preceding_Invoice_issue_date> + <xsl:attribute name="xr:id" select="'BT-26'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="date"/> + </xr:Preceding_Invoice_issue_date> + </xsl:template> + <xsl:template mode="BG-4" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty der Instanz in konkreter Syntax wird auf 10 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-27" select="./ram:Name"/> + <xsl:apply-templates mode="BT-28" + select="./ram:SpecifiedLegalOrganization/ram:TradingBusinessName"/> + <xsl:apply-templates mode="BT-29" select="./ram:GlobalID[exists(@schemeID)]"/> + <xsl:apply-templates mode="BT-29" + select="./ram:ID[empty(following-sibling::ram:GlobalID/@schemeID)]"/> + <xsl:apply-templates mode="BT-30" select="./ram:SpecifiedLegalOrganization/ram:ID"/> + <xsl:apply-templates mode="BT-31" + select="./ram:SpecifiedTaxRegistration/ram:ID[@schemeID=('VA', 'VAT')]"/> + <xsl:apply-templates mode="BT-32" + select="./ram:SpecifiedTaxRegistration/ram:ID[@schemeID='FC']"/> + <xsl:apply-templates mode="BT-33" select="./ram:Description"/> + <xsl:apply-templates mode="BT-34" select="./ram:URIUniversalCommunication/ram:URIID"/> + <xsl:apply-templates mode="BG-5" select="./ram:PostalTradeAddress"/> + <xsl:apply-templates mode="BG-6" select="./ram:DefinedTradeContact"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:SELLER> + <xsl:attribute name="xr:id" select="'BG-4'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:SELLER> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-27" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:Name"> + <xr:Seller_name> + <xsl:attribute name="xr:id" select="'BT-27'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_name> + </xsl:template> + <xsl:template mode="BT-28" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:SpecifiedLegalOrganization/ram:TradingBusinessName"> + <xr:Seller_trading_name> + <xsl:attribute name="xr:id" select="'BT-28'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_trading_name> + </xsl:template> + <xsl:template mode="BT-29" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:GlobalID[exists(@schemeID)]"> + <xr:Seller_identifier> + <xsl:attribute name="xr:id" select="'BT-29'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Seller_identifier> + </xsl:template> + <xsl:template mode="BT-29" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID[empty(following-sibling::ram:GlobalID/@schemeID)]"> + <xr:Seller_identifier> + <xsl:attribute name="xr:id" select="'BT-29'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Seller_identifier> + </xsl:template> + <xsl:template mode="BT-30" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:SpecifiedLegalOrganization/ram:ID"> + <xr:Seller_legal_registration_identifier> + <xsl:attribute name="xr:id" select="'BT-30'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Seller_legal_registration_identifier> + </xsl:template> + <xsl:template mode="BT-31" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID=('VA', 'VAT')]"> + <xr:Seller_VAT_identifier> + <xsl:attribute name="xr:id" select="'BT-31'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Seller_VAT_identifier> + </xsl:template> + <xsl:template mode="BT-32" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID='FC']"> + <xr:Seller_tax_registration_identifier> + <xsl:attribute name="xr:id" select="'BT-32'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Seller_tax_registration_identifier> + </xsl:template> + <xsl:template mode="BT-33" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:Description"> + <xr:Seller_additional_legal_information> + <xsl:attribute name="xr:id" select="'BT-33'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_additional_legal_information> + </xsl:template> + <xsl:template mode="BT-34" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:URIUniversalCommunication/ram:URIID"> + <xr:Seller_electronic_address> + <xsl:attribute name="xr:id" select="'BT-34'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Seller_electronic_address> + </xsl:template> + <xsl:template mode="BG-5" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:PostalTradeAddress"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:PostalTradeAddress der Instanz in konkreter Syntax wird auf 7 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-35" select="./ram:LineOne"/> + <xsl:apply-templates mode="BT-36" select="./ram:LineTwo"/> + <xsl:apply-templates mode="BT-162" select="./ram:LineThree"/> + <xsl:apply-templates mode="BT-37" select="./ram:CityName"/> + <xsl:apply-templates mode="BT-38" select="./ram:PostcodeCode"/> + <xsl:apply-templates mode="BT-39" select="./ram:CountrySubDivisionName"/> + <xsl:apply-templates mode="BT-40" select="./ram:CountryID"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:SELLER_POSTAL_ADDRESS> + <xsl:attribute name="xr:id" select="'BG-5'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:SELLER_POSTAL_ADDRESS> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-35" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:PostalTradeAddress/ram:LineOne"> + <xr:Seller_address_line_1> + <xsl:attribute name="xr:id" select="'BT-35'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_address_line_1> + </xsl:template> + <xsl:template mode="BT-36" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:PostalTradeAddress/ram:LineTwo"> + <xr:Seller_address_line_2> + <xsl:attribute name="xr:id" select="'BT-36'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_address_line_2> + </xsl:template> + <xsl:template mode="BT-162" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:PostalTradeAddress/ram:LineThree"> + <xr:Seller_address_line_3> + <xsl:attribute name="xr:id" select="'BT-162'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_address_line_3> + </xsl:template> + <xsl:template mode="BT-37" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:PostalTradeAddress/ram:CityName"> + <xr:Seller_city> + <xsl:attribute name="xr:id" select="'BT-37'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_city> + </xsl:template> + <xsl:template mode="BT-38" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:PostalTradeAddress/ram:PostcodeCode"> + <xr:Seller_post_code> + <xsl:attribute name="xr:id" select="'BT-38'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_post_code> + </xsl:template> + <xsl:template mode="BT-39" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:PostalTradeAddress/ram:CountrySubDivisionName"> + <xr:Seller_country_subdivision> + <xsl:attribute name="xr:id" select="'BT-39'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_country_subdivision> + </xsl:template> + <xsl:template mode="BT-40" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:PostalTradeAddress/ram:CountryID"> + <xr:Seller_country_code> + <xsl:attribute name="xr:id" select="'BT-40'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Seller_country_code> + </xsl:template> + <xsl:template mode="BG-6" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:DefinedTradeContact"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:DefinedTradeContact der Instanz in konkreter Syntax wird auf 3 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-41" select="./ram:DepartmentName"/> + <xsl:apply-templates mode="BT-41" select="./ram:PersonName"/> + <xsl:apply-templates mode="BT-42" + select="./ram:TelephoneUniversalCommunication/ram:CompleteNumber"/> + <xsl:apply-templates mode="BT-43" select="./ram:EmailURIUniversalCommunication/ram:URIID"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:SELLER_CONTACT> + <xsl:attribute name="xr:id" select="'BG-6'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:SELLER_CONTACT> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-41" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:DefinedTradeContact/ram:DepartmentName"> + <xr:Seller_contact_point> + <xsl:attribute name="xr:id" select="'BT-41'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_contact_point> + </xsl:template> + <xsl:template mode="BT-41" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:DefinedTradeContact/ram:PersonName"> + <xr:Seller_contact_point> + <xsl:attribute name="xr:id" select="'BT-41'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_contact_point> + </xsl:template> + <xsl:template mode="BT-42" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:DefinedTradeContact/ram:TelephoneUniversalCommunication/ram:CompleteNumber"> + <xr:Seller_contact_telephone_number> + <xsl:attribute name="xr:id" select="'BT-42'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_contact_telephone_number> + </xsl:template> + <xsl:template mode="BT-43" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:DefinedTradeContact/ram:EmailURIUniversalCommunication/ram:URIID"> + <xr:Seller_contact_email_address> + <xsl:attribute name="xr:id" select="'BT-43'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_contact_email_address> + </xsl:template> + <xsl:template mode="BG-7" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty der Instanz in konkreter Syntax wird auf 8 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-44" select="./ram:Name"/> + <xsl:apply-templates mode="BT-45" + select="./ram:SpecifiedLegalOrganization/ram:TradingBusinessName"/> + <xsl:apply-templates mode="BT-46" + select="./ram:ID[empty(following-sibling::ram:GlobalID/@schemeID)]"/> + <xsl:apply-templates mode="BT-46" select="./ram:GlobalID[exists(@schemeID)]"/> + <xsl:apply-templates mode="BT-47" select="./ram:SpecifiedLegalOrganization/ram:ID"/> + <xsl:apply-templates mode="BT-48" + select="./ram:SpecifiedTaxRegistration/ram:ID[@schemeID=('VA', 'VAT')]"/> + <xsl:apply-templates mode="BT-49" select="./ram:URIUniversalCommunication/ram:URIID"/> + <xsl:apply-templates mode="BG-8" select="./ram:PostalTradeAddress"/> + <xsl:apply-templates mode="BG-9" select="./ram:DefinedTradeContact"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:BUYER> + <xsl:attribute name="xr:id" select="'BG-7'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:BUYER> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-44" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:Name"> + <xr:Buyer_name> + <xsl:attribute name="xr:id" select="'BT-44'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_name> + </xsl:template> + <xsl:template mode="BT-45" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:SpecifiedLegalOrganization/ram:TradingBusinessName"> + <xr:Buyer_trading_name> + <xsl:attribute name="xr:id" select="'BT-45'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_trading_name> + </xsl:template> + <xsl:template mode="BT-46" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID[empty(following-sibling::ram:GlobalID/@schemeID)]"> + <xr:Buyer_identifier> + <xsl:attribute name="xr:id" select="'BT-46'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Buyer_identifier> + </xsl:template> + <xsl:template mode="BT-46" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:GlobalID[exists(@schemeID)]"> + <xr:Buyer_identifier> + <xsl:attribute name="xr:id" select="'BT-46'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Buyer_identifier> + </xsl:template> + <xsl:template mode="BT-47" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:SpecifiedLegalOrganization/ram:ID"> + <xr:Buyer_legal_registration_identifier> + <xsl:attribute name="xr:id" select="'BT-47'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Buyer_legal_registration_identifier> + </xsl:template> + <xsl:template mode="BT-48" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID=('VA', 'VAT')]"> + <xr:Buyer_VAT_identifier> + <xsl:attribute name="xr:id" select="'BT-48'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Buyer_VAT_identifier> + </xsl:template> + <xsl:template mode="BT-49" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:URIUniversalCommunication/ram:URIID"> + <xr:Buyer_electronic_address> + <xsl:attribute name="xr:id" select="'BT-49'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Buyer_electronic_address> + </xsl:template> + <xsl:template mode="BG-8" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:PostalTradeAddress"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:PostalTradeAddress der Instanz in konkreter Syntax wird auf 7 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-50" select="./ram:LineOne"/> + <xsl:apply-templates mode="BT-51" select="./ram:LineTwo"/> + <xsl:apply-templates mode="BT-163" select="./ram:LineThree"/> + <xsl:apply-templates mode="BT-52" select="./ram:CityName"/> + <xsl:apply-templates mode="BT-53" select="./ram:PostcodeCode"/> + <xsl:apply-templates mode="BT-54" select="./ram:CountrySubDivisionName"/> + <xsl:apply-templates mode="BT-55" select="./ram:CountryID"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:BUYER_POSTAL_ADDRESS> + <xsl:attribute name="xr:id" select="'BG-8'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:BUYER_POSTAL_ADDRESS> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-50" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:PostalTradeAddress/ram:LineOne"> + <xr:Buyer_address_line_1> + <xsl:attribute name="xr:id" select="'BT-50'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_address_line_1> + </xsl:template> + <xsl:template mode="BT-51" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:PostalTradeAddress/ram:LineTwo"> + <xr:Buyer_address_line_2> + <xsl:attribute name="xr:id" select="'BT-51'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_address_line_2> + </xsl:template> + <xsl:template mode="BT-163" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:PostalTradeAddress/ram:LineThree"> + <xr:Buyer_address_line_3> + <xsl:attribute name="xr:id" select="'BT-163'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_address_line_3> + </xsl:template> + <xsl:template mode="BT-52" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:PostalTradeAddress/ram:CityName"> + <xr:Buyer_city> + <xsl:attribute name="xr:id" select="'BT-52'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_city> + </xsl:template> + <xsl:template mode="BT-53" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:PostalTradeAddress/ram:PostcodeCode"> + <xr:Buyer_post_code> + <xsl:attribute name="xr:id" select="'BT-53'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_post_code> + </xsl:template> + <xsl:template mode="BT-54" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:PostalTradeAddress/ram:CountrySubDivisionName"> + <xr:Buyer_country_subdivision> + <xsl:attribute name="xr:id" select="'BT-54'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_country_subdivision> + </xsl:template> + <xsl:template mode="BT-55" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:PostalTradeAddress/ram:CountryID"> + <xr:Buyer_country_code> + <xsl:attribute name="xr:id" select="'BT-55'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Buyer_country_code> + </xsl:template> + <xsl:template mode="BG-9" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:DefinedTradeContact"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:DefinedTradeContact der Instanz in konkreter Syntax wird auf 3 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-56" select="./ram:DepartmentName"/> + <xsl:apply-templates mode="BT-56" select="./ram:PersonName"/> + <xsl:apply-templates mode="BT-57" + select="./ram:TelephoneUniversalCommunication/ram:CompleteNumber"/> + <xsl:apply-templates mode="BT-58" select="./ram:EmailURIUniversalCommunication/ram:URIID"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:BUYER_CONTACT> + <xsl:attribute name="xr:id" select="'BG-9'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:BUYER_CONTACT> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-56" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:DefinedTradeContact/ram:DepartmentName"> + <xr:Buyer_contact_point> + <xsl:attribute name="xr:id" select="'BT-56'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_contact_point> + </xsl:template> + <xsl:template mode="BT-56" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:DefinedTradeContact/ram:PersonName"> + <xr:Buyer_contact_point> + <xsl:attribute name="xr:id" select="'BT-56'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_contact_point> + </xsl:template> + <xsl:template mode="BT-57" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:DefinedTradeContact/ram:TelephoneUniversalCommunication/ram:CompleteNumber"> + <xr:Buyer_contact_telephone_number> + <xsl:attribute name="xr:id" select="'BT-57'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_contact_telephone_number> + </xsl:template> + <xsl:template mode="BT-58" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:DefinedTradeContact/ram:EmailURIUniversalCommunication/ram:URIID"> + <xr:Buyer_contact_email_address> + <xsl:attribute name="xr:id" select="'BT-58'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Buyer_contact_email_address> + </xsl:template> + <xsl:template mode="BG-10" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:PayeeTradeParty"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:PayeeTradeParty der Instanz in konkreter Syntax wird auf 3 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-59" select="./ram:Name"/> + <xsl:apply-templates mode="BT-60" select="./ram:GlobalID[exists(@schemeID)]"/> + <xsl:apply-templates mode="BT-60" + select="./ram:ID[empty(following-sibling::ram:GlobalID/@schemeID)]"/> + <xsl:apply-templates mode="BT-61" select="./ram:SpecifiedLegalOrganization/ram:ID/@schemeID"/> + <xsl:apply-templates mode="BT-61" select="./ram:SpecifiedLegalOrganization/ram:ID"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:PAYEE> + <xsl:attribute name="xr:id" select="'BG-10'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:PAYEE> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-59" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:PayeeTradeParty/ram:Name"> + <xr:Payee_name> + <xsl:attribute name="xr:id" select="'BT-59'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Payee_name> + </xsl:template> + <xsl:template mode="BT-60" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:PayeeTradeParty/ram:GlobalID[exists(@schemeID)]"> + <xr:Payee_identifier> + <xsl:attribute name="xr:id" select="'BT-60'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Payee_identifier> + </xsl:template> + <xsl:template mode="BT-60" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:PayeeTradeParty/ram:ID[empty(following-sibling::ram:GlobalID/@schemeID)]"> + <xr:Payee_identifier> + <xsl:attribute name="xr:id" select="'BT-60'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Payee_identifier> + </xsl:template> + <xsl:template mode="BT-61" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:PayeeTradeParty/ram:SpecifiedLegalOrganization/ram:ID/@schemeID"> + <xr:Payee_legal_registration_identifier> + <xsl:attribute name="xr:id" select="'BT-61'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Payee_legal_registration_identifier> + </xsl:template> + <xsl:template mode="BT-61" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:PayeeTradeParty/ram:SpecifiedLegalOrganization/ram:ID"> + <xr:Payee_legal_registration_identifier> + <xsl:attribute name="xr:id" select="'BT-61'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Payee_legal_registration_identifier> + </xsl:template> + <xsl:template mode="BG-11" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty der Instanz in konkreter Syntax wird auf 3 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-62" select="./ram:Name"/> + <xsl:apply-templates mode="BT-63" select="./ram:SpecifiedTaxRegistration/ram:ID"/> + <xsl:apply-templates mode="BG-12" select="./ram:PostalTradeAddress"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:SELLER_TAX_REPRESENTATIVE_PARTY> + <xsl:attribute name="xr:id" select="'BG-11'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:SELLER_TAX_REPRESENTATIVE_PARTY> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-62" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:Name"> + <xr:Seller_tax_representative_name> + <xsl:attribute name="xr:id" select="'BT-62'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Seller_tax_representative_name> + </xsl:template> + <xsl:template mode="BT-63" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:SpecifiedTaxRegistration/ram:ID"> + <xr:Seller_tax_representative_VAT_identifier> + <xsl:attribute name="xr:id" select="'BT-63'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Seller_tax_representative_VAT_identifier> + </xsl:template> + <xsl:template mode="BG-12" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:PostalTradeAddress"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:PostalTradeAddress der Instanz in konkreter Syntax wird auf 7 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-64" select="./ram:LineOne"/> + <xsl:apply-templates mode="BT-65" select="./ram:LineTwo"/> + <xsl:apply-templates mode="BT-164" select="./ram:LineThree"/> + <xsl:apply-templates mode="BT-66" select="./ram:CityName"/> + <xsl:apply-templates mode="BT-67" select="./ram:PostcodeCode"/> + <xsl:apply-templates mode="BT-68" select="./ram:CountrySubDivisionName"/> + <xsl:apply-templates mode="BT-69" select="./ram:CountryID"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:SELLER_TAX_REPRESENTATIVE_POSTAL_ADDRESS> + <xsl:attribute name="xr:id" select="'BG-12'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:SELLER_TAX_REPRESENTATIVE_POSTAL_ADDRESS> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-64" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:PostalTradeAddress/ram:LineOne"> + <xr:Tax_representative_address_line_1> + <xsl:attribute name="xr:id" select="'BT-64'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Tax_representative_address_line_1> + </xsl:template> + <xsl:template mode="BT-65" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:PostalTradeAddress/ram:LineTwo"> + <xr:Tax_representative_address_line_2> + <xsl:attribute name="xr:id" select="'BT-65'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Tax_representative_address_line_2> + </xsl:template> + <xsl:template mode="BT-164" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:PostalTradeAddress/ram:LineThree"> + <xr:Tax_representative_address_line_3> + <xsl:attribute name="xr:id" select="'BT-164'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Tax_representative_address_line_3> + </xsl:template> + <xsl:template mode="BT-66" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:PostalTradeAddress/ram:CityName"> + <xr:Tax_representative_city> + <xsl:attribute name="xr:id" select="'BT-66'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Tax_representative_city> + </xsl:template> + <xsl:template mode="BT-67" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:PostalTradeAddress/ram:PostcodeCode"> + <xr:Tax_representative_post_code> + <xsl:attribute name="xr:id" select="'BT-67'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Tax_representative_post_code> + </xsl:template> + <xsl:template mode="BT-68" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:PostalTradeAddress/ram:CountrySubDivisionName"> + <xr:Tax_representative_country_subdivision> + <xsl:attribute name="xr:id" select="'BT-68'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Tax_representative_country_subdivision> + </xsl:template> + <xsl:template mode="BT-69" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:PostalTradeAddress/ram:CountryID"> + <xr:Tax_representative_country_code> + <xsl:attribute name="xr:id" select="'BT-69'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Tax_representative_country_code> + </xsl:template> + <xsl:template mode="BG-13" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty"> + <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-71" select="./ram:GlobalID[exists(@schemeID)]"/> + <xsl:apply-templates mode="BT-71" + select="./ram:ID[empty(following-sibling::ram:GlobalID/@schemeID)]"/> + <xsl:apply-templates mode="BT-72" + select="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/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:variable> + <xsl:if test="$bg-contents"> + <xr:DELIVERY_INFORMATION> + <xsl:attribute name="xr:id" select="'BG-13'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:DELIVERY_INFORMATION> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-70" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:Name"> + <xr:Deliver_to_party_name> + <xsl:attribute name="xr:id" select="'BT-70'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Deliver_to_party_name> + </xsl:template> + <xsl:template mode="BT-71" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:GlobalID[exists(@schemeID)]"> + <xr:Deliver_to_location_identifier> + <xsl:attribute name="xr:id" select="'BT-71'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Deliver_to_location_identifier> + </xsl:template> + <xsl:template mode="BT-71" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:ID[empty(following-sibling::ram:GlobalID/@schemeID)]"> + <xr:Deliver_to_location_identifier> + <xsl:attribute name="xr:id" select="'BT-71'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Deliver_to_location_identifier> + </xsl:template> + <xsl:template mode="BT-72" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString[@format = '102']"> + <xr:Actual_delivery_date> + <xsl:attribute name="xr:id" select="'BT-72'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="date"/> + </xr:Actual_delivery_date> + </xsl:template> + <xsl:template mode="BG-14" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:BillingSpecifiedPeriod"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:BillingSpecifiedPeriod der Instanz in konkreter Syntax wird auf 2 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-73" + select="./ram:StartDateTime/udt:DateTimeString[@format = '102']"/> + <xsl:apply-templates mode="BT-74" + select="./ram:EndDateTime/udt:DateTimeString[@format = '102']"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:INVOICING_PERIOD> + <xsl:attribute name="xr:id" select="'BG-14'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:INVOICING_PERIOD> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-73" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:BillingSpecifiedPeriod/ram:StartDateTime/udt:DateTimeString[@format = '102']"> + <xr:Invoicing_period_start_date> + <xsl:attribute name="xr:id" select="'BT-73'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="date"/> + </xr:Invoicing_period_start_date> + </xsl:template> + <xsl:template mode="BT-74" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:BillingSpecifiedPeriod/ram:EndDateTime/udt:DateTimeString[@format = '102']"> + <xr:Invoicing_period_end_date> + <xsl:attribute name="xr:id" select="'BT-74'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="date"/> + </xr:Invoicing_period_end_date> + </xsl:template> + <xsl:template mode="BG-15" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:PostalTradeAddress"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:PostalTradeAddress der Instanz in konkreter Syntax wird auf 7 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-75" select="./ram:LineOne"/> + <xsl:apply-templates mode="BT-76" select="./ram:LineTwo"/> + <xsl:apply-templates mode="BT-165" select="./ram:LineThree"/> + <xsl:apply-templates mode="BT-77" select="./ram:CityName"/> + <xsl:apply-templates mode="BT-78" select="./ram:PostcodeCode"/> + <xsl:apply-templates mode="BT-79" select="./ram:CountrySubDivisionName"/> + <xsl:apply-templates mode="BT-80" select="./ram:CountryID"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:DELIVER_TO_ADDRESS> + <xsl:attribute name="xr:id" select="'BG-15'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:DELIVER_TO_ADDRESS> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-75" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:PostalTradeAddress/ram:LineOne"> + <xr:Deliver_to_address_line_1> + <xsl:attribute name="xr:id" select="'BT-75'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Deliver_to_address_line_1> + </xsl:template> + <xsl:template mode="BT-76" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:PostalTradeAddress/ram:LineTwo"> + <xr:Deliver_to_address_line_2> + <xsl:attribute name="xr:id" select="'BT-76'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Deliver_to_address_line_2> + </xsl:template> + <xsl:template mode="BT-165" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:PostalTradeAddress/ram:LineThree"> + <xr:Deliver_to_address_line_3> + <xsl:attribute name="xr:id" select="'BT-165'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Deliver_to_address_line_3> + </xsl:template> + <xsl:template mode="BT-77" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:PostalTradeAddress/ram:CityName"> + <xr:Deliver_to_city> + <xsl:attribute name="xr:id" select="'BT-77'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Deliver_to_city> + </xsl:template> + <xsl:template mode="BT-78" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:PostalTradeAddress/ram:PostcodeCode"> + <xr:Deliver_to_post_code> + <xsl:attribute name="xr:id" select="'BT-78'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Deliver_to_post_code> + </xsl:template> + <xsl:template mode="BT-79" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:PostalTradeAddress/ram:CountrySubDivisionName"> + <xr:Deliver_to_country_subdivision> + <xsl:attribute name="xr:id" select="'BT-79'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Deliver_to_country_subdivision> + </xsl:template> + <xsl:template mode="BT-80" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:PostalTradeAddress/ram:CountryID"> + <xr:Deliver_to_country_code> + <xsl:attribute name="xr:id" select="'BT-80'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Deliver_to_country_code> + </xsl:template> + <xsl:template mode="BG-16" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans der Instanz in konkreter Syntax wird auf 6 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-81" select="./ram:TypeCode"/> + <xsl:apply-templates mode="BT-82" select="./ram:Information"/> + <xsl:apply-templates mode="BT-83" + select="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:PaymentReference"/> + <xsl:apply-templates mode="BG-17" select="./ram:PayeePartyCreditorFinancialAccount"/> + <xsl:apply-templates mode="BG-18" select="./ram:ApplicableTradeSettlementFinancialCard"/> + <xsl:apply-templates mode="BG-19" + select="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:PAYMENT_INSTRUCTIONS> + <xsl:attribute name="xr:id" select="'BG-16'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:PAYMENT_INSTRUCTIONS> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-81" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:TypeCode"> + <xr:Payment_means_type_code> + <xsl:attribute name="xr:id" select="'BT-81'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Payment_means_type_code> + </xsl:template> + <xsl:template mode="BT-82" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:Information"> + <xr:Payment_means_text> + <xsl:attribute name="xr:id" select="'BT-82'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Payment_means_text> + </xsl:template> + <xsl:template mode="BT-83" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:PaymentReference"> + <xr:Remittance_information> + <xsl:attribute name="xr:id" select="'BT-83'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Remittance_information> + </xsl:template> + <xsl:template mode="BG-17" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeePartyCreditorFinancialAccount"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeePartyCreditorFinancialAccount der Instanz in konkreter Syntax wird auf 3 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-84" select="./ram:ProprietaryID"/> + <xsl:apply-templates mode="BT-84" select="./ram:IBANID"/> + <xsl:apply-templates mode="BT-85" select="./ram:AccountName"/> + <xsl:apply-templates mode="BT-86" + select="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeeSpecifiedCreditorFinancialInstitution/ram:BICID"/> + <xsl:apply-templates mode="BT-86" + select="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeeSpecifiedCreditorFinancialInstitution/ram:BICID"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:CREDIT_TRANSFER> + <xsl:attribute name="xr:id" select="'BG-17'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:CREDIT_TRANSFER> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-84" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeePartyCreditorFinancialAccount/ram:ProprietaryID"> + <xr:Payment_account_identifier> + <xsl:attribute name="xr:id" select="'BT-84'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Payment_account_identifier> + </xsl:template> + <xsl:template mode="BT-84" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeePartyCreditorFinancialAccount/ram:IBANID"> + <xr:Payment_account_identifier> + <xsl:attribute name="xr:id" select="'BT-84'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Payment_account_identifier> + </xsl:template> + <xsl:template mode="BT-85" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeePartyCreditorFinancialAccount/ram:AccountName"> + <xr:Payment_account_name> + <xsl:attribute name="xr:id" select="'BT-85'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Payment_account_name> + </xsl:template> + <xsl:template mode="BT-86" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeeSpecifiedCreditorFinancialInstitution/ram:BICID"> + <xr:Payment_service_provider_identifier> + <xsl:attribute name="xr:id" select="'BT-86'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Payment_service_provider_identifier> + </xsl:template> + <xsl:template mode="BT-86" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeeSpecifiedCreditorFinancialInstitution/ram:BICID"> + <xr:Payment_service_provider_identifier> + <xsl:attribute name="xr:id" select="'BT-86'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Payment_service_provider_identifier> + </xsl:template> + <xsl:template mode="BG-18" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:ApplicableTradeSettlementFinancialCard"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:ApplicableTradeSettlementFinancialCard der Instanz in konkreter Syntax wird auf 2 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-87" select="./ram:ID"/> + <xsl:apply-templates mode="BT-88" select="./ram:CardholderName"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:PAYMENT_CARD_INFORMATION> + <xsl:attribute name="xr:id" select="'BG-18'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:PAYMENT_CARD_INFORMATION> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-87" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:ApplicableTradeSettlementFinancialCard/ram:ID"> + <xr:Payment_card_primary_account_number> + <xsl:attribute name="xr:id" select="'BT-87'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Payment_card_primary_account_number> + </xsl:template> + <xsl:template mode="BT-88" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:ApplicableTradeSettlementFinancialCard/ram:CardholderName"> + <xr:Payment_card_holder_name> + <xsl:attribute name="xr:id" select="'BT-88'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Payment_card_holder_name> + </xsl:template> + <xsl:template mode="BG-19" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement der Instanz in konkreter Syntax wird auf 3 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-89" + select="./ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID"/> + <xsl:apply-templates mode="BT-90" select="./ram:CreditorReferenceID"/> + <xsl:apply-templates mode="BT-91" + select="./ram:SpecifiedTradeSettlementPaymentMeans/ram:PayerPartyDebtorFinancialAccount/ram:IBANID"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:DIRECT_DEBIT> + <xsl:attribute name="xr:id" select="'BG-19'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:DIRECT_DEBIT> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-89" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID"> + <xr:Mandate_reference_identifier> + <xsl:attribute name="xr:id" select="'BT-89'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Mandate_reference_identifier> + </xsl:template> + <xsl:template mode="BT-90" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:CreditorReferenceID"> + <xr:Bank_assigned_creditor_identifier> + <xsl:attribute name="xr:id" select="'BT-90'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Bank_assigned_creditor_identifier> + </xsl:template> + <xsl:template mode="BT-91" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayerPartyDebtorFinancialAccount/ram:IBANID"> + <xr:Debited_account_identifier> + <xsl:attribute name="xr:id" select="'BT-91'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Debited_account_identifier> + </xsl:template> + <xsl:template mode="BG-20" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='false']"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='false'] der Instanz in konkreter Syntax wird auf 7 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-92" select="./ram:ActualAmount"/> + <xsl:apply-templates mode="BT-93" select="./ram:BasisAmount"/> + <xsl:apply-templates mode="BT-94" select="./ram:CalculationPercent"/> + <xsl:apply-templates mode="BT-95" select="./ram:CategoryTradeTax/ram:CategoryCode"/> + <xsl:apply-templates mode="BT-96" select="./ram:CategoryTradeTax/ram:RateApplicablePercent"/> + <xsl:apply-templates mode="BT-97" select="./ram:Reason"/> + <xsl:apply-templates mode="BT-98" select="./ram:ReasonCode"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:DOCUMENT_LEVEL_ALLOWANCES> + <xsl:attribute name="xr:id" select="'BG-20'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:DOCUMENT_LEVEL_ALLOWANCES> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-92" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ActualAmount"> + <xr:Document_level_allowance_amount> + <xsl:attribute name="xr:id" select="'BT-92'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Document_level_allowance_amount> + </xsl:template> + <xsl:template mode="BT-93" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:BasisAmount"> + <xr:Document_level_allowance_base_amount> + <xsl:attribute name="xr:id" select="'BT-93'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Document_level_allowance_base_amount> + </xsl:template> + <xsl:template mode="BT-94" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CalculationPercent"> + <xr:Document_level_allowance_percentage> + <xsl:attribute name="xr:id" select="'BT-94'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="percentage"/> + </xr:Document_level_allowance_percentage> + </xsl:template> + <xsl:template mode="BT-95" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:CategoryCode"> + <xr:Document_level_allowance_VAT_category_code> + <xsl:attribute name="xr:id" select="'BT-95'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Document_level_allowance_VAT_category_code> + </xsl:template> + <xsl:template mode="BT-96" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:RateApplicablePercent"> + <xr:Document_level_allowance_VAT_rate> + <xsl:attribute name="xr:id" select="'BT-96'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="percentage"/> + </xr:Document_level_allowance_VAT_rate> + </xsl:template> + <xsl:template mode="BT-97" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:Reason"> + <xr:Document_level_allowance_reason> + <xsl:attribute name="xr:id" select="'BT-97'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Document_level_allowance_reason> + </xsl:template> + <xsl:template mode="BT-98" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ReasonCode"> + <xr:Document_level_allowance_reason_code> + <xsl:attribute name="xr:id" select="'BT-98'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Document_level_allowance_reason_code> + </xsl:template> + <xsl:template mode="BG-21" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='true']"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='true'] der Instanz in konkreter Syntax wird auf 7 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-99" select="./ram:ActualAmount"/> + <xsl:apply-templates mode="BT-100" select="./ram:BasisAmount"/> + <xsl:apply-templates mode="BT-101" select="./ram:CalculationPercent"/> + <xsl:apply-templates mode="BT-102" select="./ram:CategoryTradeTax/ram:CategoryCode"/> + <xsl:apply-templates mode="BT-103" select="./ram:CategoryTradeTax/ram:RateApplicablePercent"/> + <xsl:apply-templates mode="BT-104" select="./ram:Reason"/> + <xsl:apply-templates mode="BT-105" select="./ram:ReasonCode"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:DOCUMENT_LEVEL_CHARGES> + <xsl:attribute name="xr:id" select="'BG-21'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:DOCUMENT_LEVEL_CHARGES> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-99" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ActualAmount"> + <xr:Document_level_charge_amount> + <xsl:attribute name="xr:id" select="'BT-99'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Document_level_charge_amount> + </xsl:template> + <xsl:template mode="BT-100" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:BasisAmount"> + <xr:Document_level_charge_base_amount> + <xsl:attribute name="xr:id" select="'BT-100'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Document_level_charge_base_amount> + </xsl:template> + <xsl:template mode="BT-101" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CalculationPercent"> + <xr:Document_level_charge_percentage> + <xsl:attribute name="xr:id" select="'BT-101'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="percentage"/> + </xr:Document_level_charge_percentage> + </xsl:template> + <xsl:template mode="BT-102" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:CategoryCode"> + <xr:Document_level_charge_VAT_category_code> + <xsl:attribute name="xr:id" select="'BT-102'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Document_level_charge_VAT_category_code> + </xsl:template> + <xsl:template mode="BT-103" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CategoryTradeTax/ram:RateApplicablePercent"> + <xr:Document_level_charge_VAT_rate> + <xsl:attribute name="xr:id" select="'BT-103'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="percentage"/> + </xr:Document_level_charge_VAT_rate> + </xsl:template> + <xsl:template mode="BT-104" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:Reason"> + <xr:Document_level_charge_reason> + <xsl:attribute name="xr:id" select="'BT-104'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Document_level_charge_reason> + </xsl:template> + <xsl:template mode="BT-105" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ReasonCode"> + <xr:Document_level_charge_reason_code> + <xsl:attribute name="xr:id" select="'BT-105'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Document_level_charge_reason_code> + </xsl:template> + <xsl:template mode="BG-22" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation der Instanz in konkreter Syntax wird auf 10 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-106" select="./ram:LineTotalAmount"/> + <xsl:apply-templates mode="BT-107" select="./ram:AllowanceTotalAmount"/> + <xsl:apply-templates mode="BT-108" select="./ram:ChargeTotalAmount"/> + <xsl:apply-templates mode="BT-109" select="./ram:TaxBasisTotalAmount"/> + <xsl:apply-templates mode="BT-110" + select="./ram:TaxTotalAmount[@currencyID = parent::ram:SpecifiedTradeSettlementHeaderMonetarySummation/preceding-sibling::ram:TaxCurrencyCode]"/> + <xsl:apply-templates mode="BT-111" + select="./ram:TaxTotalAmount[@currencyID = parent::ram:SpecifiedTradeSettlementHeaderMonetarySummation/preceding-sibling::ram:InvoiceCurrencyCode]"/> + <xsl:apply-templates mode="BT-112" select="./ram:GrandTotalAmount"/> + <xsl:apply-templates mode="BT-113" select="./ram:TotalPrepaidAmount"/> + <xsl:apply-templates mode="BT-114" select="./ram:RoundingAmount"/> + <xsl:apply-templates mode="BT-115" select="./ram:DuePayableAmount"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:DOCUMENT_TOTALS> + <xsl:attribute name="xr:id" select="'BG-22'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:DOCUMENT_TOTALS> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-106" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:LineTotalAmount"> + <xr:Sum_of_Invoice_line_net_amount> + <xsl:attribute name="xr:id" select="'BT-106'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Sum_of_Invoice_line_net_amount> + </xsl:template> + <xsl:template mode="BT-107" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:AllowanceTotalAmount"> + <xr:Sum_of_allowances_on_document_level> + <xsl:attribute name="xr:id" select="'BT-107'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Sum_of_allowances_on_document_level> + </xsl:template> + <xsl:template mode="BT-108" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:ChargeTotalAmount"> + <xr:Sum_of_charges_on_document_level> + <xsl:attribute name="xr:id" select="'BT-108'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Sum_of_charges_on_document_level> + </xsl:template> + <xsl:template mode="BT-109" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TaxBasisTotalAmount"> + <xr:Invoice_total_amount_without_VAT> + <xsl:attribute name="xr:id" select="'BT-109'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Invoice_total_amount_without_VAT> + </xsl:template> + <xsl:template mode="BT-110" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TaxTotalAmount[@currencyID = parent::ram:SpecifiedTradeSettlementHeaderMonetarySummation/preceding-sibling::ram:TaxCurrencyCode]"> + <xr:Invoice_total_VAT_amount> + <xsl:attribute name="xr:id" select="'BT-110'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Invoice_total_VAT_amount> + </xsl:template> + <xsl:template mode="BT-111" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TaxTotalAmount[@currencyID = parent::ram:SpecifiedTradeSettlementHeaderMonetarySummation/preceding-sibling::ram:InvoiceCurrencyCode]"> + <xr:Invoice_total_VAT_amount_in_accounting_currency> + <xsl:attribute name="xr:id" select="'BT-111'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Invoice_total_VAT_amount_in_accounting_currency> + </xsl:template> + <xsl:template mode="BT-112" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:GrandTotalAmount"> + <xr:Invoice_total_amount_with_VAT> + <xsl:attribute name="xr:id" select="'BT-112'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Invoice_total_amount_with_VAT> + </xsl:template> + <xsl:template mode="BT-113" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TotalPrepaidAmount"> + <xr:Paid_amount> + <xsl:attribute name="xr:id" select="'BT-113'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Paid_amount> + </xsl:template> + <xsl:template mode="BT-114" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:RoundingAmount"> + <xr:Rounding_amount> + <xsl:attribute name="xr:id" select="'BT-114'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Rounding_amount> + </xsl:template> + <xsl:template mode="BT-115" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:DuePayableAmount"> + <xr:Amount_due_for_payment> + <xsl:attribute name="xr:id" select="'BT-115'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Amount_due_for_payment> + </xsl:template> + <xsl:template mode="BG-23" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax der Instanz in konkreter Syntax wird auf 6 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-116" select="./ram:BasisAmount"/> + <xsl:apply-templates mode="BT-117" select="./ram:CalculatedAmount"/> + <xsl:apply-templates mode="BT-118" select="./ram:CategoryCode"/> + <xsl:apply-templates mode="BT-119" select="./ram:RateApplicablePercent"/> + <xsl:apply-templates mode="BT-120" select="./ram:ExemptionReason"/> + <xsl:apply-templates mode="BT-121" select="./ram:ExemptionReasonCode"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:VAT_BREAKDOWN> + <xsl:attribute name="xr:id" select="'BG-23'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:VAT_BREAKDOWN> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-116" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax/ram:BasisAmount"> + <xr:VAT_category_taxable_amount> + <xsl:attribute name="xr:id" select="'BT-116'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:VAT_category_taxable_amount> + </xsl:template> + <xsl:template mode="BT-117" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax/ram:CalculatedAmount"> + <xr:VAT_category_tax_amount> + <xsl:attribute name="xr:id" select="'BT-117'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:VAT_category_tax_amount> + </xsl:template> + <xsl:template mode="BT-118" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax/ram:CategoryCode"> + <xr:VAT_category_code> + <xsl:attribute name="xr:id" select="'BT-118'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:VAT_category_code> + </xsl:template> + <xsl:template mode="BT-119" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax/ram:RateApplicablePercent"> + <xr:VAT_category_rate> + <xsl:attribute name="xr:id" select="'BT-119'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="percentage"/> + </xr:VAT_category_rate> + </xsl:template> + <xsl:template mode="BT-120" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax/ram:ExemptionReason"> + <xr:VAT_exemption_reason_text> + <xsl:attribute name="xr:id" select="'BT-120'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:VAT_exemption_reason_text> + </xsl:template> + <xsl:template mode="BT-121" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax/ram:ExemptionReasonCode"> + <xr:VAT_exemption_reason_code> + <xsl:attribute name="xr:id" select="'BT-121'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:VAT_exemption_reason_code> + </xsl:template> + <xsl:template mode="BG-24" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument der Instanz in konkreter Syntax wird auf 4 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-122" + select="./ram:IssuerAssignedID[following-sibling::ram:TypeCode='916']"/> + <xsl:apply-templates mode="BT-123" select="./ram:Name"/> + <xsl:apply-templates mode="BT-124" select="./ram:URIID"/> + <xsl:apply-templates mode="BT-125" select="./ram:AttachmentBinaryObject"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:ADDITIONAL_SUPPORTING_DOCUMENTS> + <xsl:attribute name="xr:id" select="'BG-24'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:ADDITIONAL_SUPPORTING_DOCUMENTS> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-122" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument/ram:IssuerAssignedID[following-sibling::ram:TypeCode='916']"> + <xr:Supporting_document_reference> + <xsl:attribute name="xr:id" select="'BT-122'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="document_reference"/> + </xr:Supporting_document_reference> + </xsl:template> + <xsl:template mode="BT-123" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument/ram:Name"> + <xr:Supporting_document_description> + <xsl:attribute name="xr:id" select="'BT-123'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Supporting_document_description> + </xsl:template> + <xsl:template mode="BT-124" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument/ram:URIID"> + <xr:External_document_location> + <xsl:attribute name="xr:id" select="'BT-124'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:External_document_location> + </xsl:template> + <xsl:template mode="BT-125" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument/ram:AttachmentBinaryObject"> + <xr:Attached_document> + <xsl:attribute name="xr:id" select="'BT-125'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="binary_object"/> + </xr:Attached_document> + </xsl:template> + <xsl:template mode="BG-25" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem der Instanz in konkreter Syntax wird auf 14 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-126" select="./ram:AssociatedDocumentLineDocument/ram:LineID"/> + <xsl:apply-templates mode="BT-127" + select="./ram:AssociatedDocumentLineDocument/ram:IncludedNote/ram:Content"/> + <xsl:apply-templates mode="BT-128" + select="./ram:SpecifiedLineTradeSettlement/ram:AdditionalReferencedDocument/ram:IssuerAssignedID[following-sibling::ram:TypeCode='130']"/> + <xsl:apply-templates mode="BT-129" + select="./ram:SpecifiedLineTradeDelivery/ram:BilledQuantity"/> + <xsl:apply-templates mode="BT-130" + select="./ram:SpecifiedLineTradeDelivery/ram:BilledQuantity/@unitCode"/> + <xsl:apply-templates mode="BT-131" + select="./ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeSettlementLineMonetarySummation/ram:LineTotalAmount"/> + <xsl:apply-templates mode="BT-132" + select="./ram:SpecifiedLineTradeAgreement/ram:BuyerOrderReferencedDocument/ram:LineID"/> + <xsl:apply-templates mode="BT-133" + select="./ram:SpecifiedLineTradeSettlement/ram:ReceivableSpecifiedTradeAccountingAccount/ram:ID"/> + <xsl:apply-templates mode="BG-26" + select="./ram:SpecifiedLineTradeSettlement/ram:BillingSpecifiedPeriod"/> + <xsl:apply-templates mode="BG-27" + select="./ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='false']"/> + <xsl:apply-templates mode="BG-28" + select="./ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='true']"/> + <xsl:apply-templates mode="BG-29" select="./ram:SpecifiedLineTradeAgreement"/> + <xsl:apply-templates mode="BG-30" + select="./ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax"/> + <xsl:apply-templates mode="BG-31" select="./ram:SpecifiedTradeProduct"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:INVOICE_LINE> + <xsl:attribute name="xr:id" select="'BG-25'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:INVOICE_LINE> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-126" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:AssociatedDocumentLineDocument/ram:LineID"> + <xr:Invoice_line_identifier> + <xsl:attribute name="xr:id" select="'BT-126'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Invoice_line_identifier> + </xsl:template> + <xsl:template mode="BT-127" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:AssociatedDocumentLineDocument/ram:IncludedNote/ram:Content"> + <xr:Invoice_line_note> + <xsl:attribute name="xr:id" select="'BT-127'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Invoice_line_note> + </xsl:template> + <xsl:template mode="BT-128" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:AdditionalReferencedDocument/ram:IssuerAssignedID[following-sibling::ram:TypeCode='130']"> + <xr:Invoice_line_object_identifier> + <xsl:attribute name="xr:id" select="'BT-128'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"> + <xsl:with-param name="schemeID" select="following-sibling::ram:ReferenceTypeCode"/> + </xsl:call-template> + </xr:Invoice_line_object_identifier> + </xsl:template> + <xsl:template mode="BT-129" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeDelivery/ram:BilledQuantity"> + <xr:Invoiced_quantity> + <xsl:attribute name="xr:id" select="'BT-129'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="quantity"/> + </xr:Invoiced_quantity> + </xsl:template> + <xsl:template mode="BT-130" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeDelivery/ram:BilledQuantity/@unitCode"> + <xr:Invoiced_quantity_unit_of_measure_code> + <xsl:attribute name="xr:id" select="'BT-130'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Invoiced_quantity_unit_of_measure_code> + </xsl:template> + <xsl:template mode="BT-131" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeSettlementLineMonetarySummation/ram:LineTotalAmount"> + <xr:Invoice_line_net_amount> + <xsl:attribute name="xr:id" select="'BT-131'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Invoice_line_net_amount> + </xsl:template> + <xsl:template mode="BT-132" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeAgreement/ram:BuyerOrderReferencedDocument/ram:LineID"> + <xr:Referenced_purchase_order_line_reference> + <xsl:attribute name="xr:id" select="'BT-132'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="document_reference"/> + </xr:Referenced_purchase_order_line_reference> + </xsl:template> + <xsl:template mode="BT-133" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ReceivableSpecifiedTradeAccountingAccount/ram:ID"> + <xr:Invoice_line_Buyer_accounting_reference> + <xsl:attribute name="xr:id" select="'BT-133'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Invoice_line_Buyer_accounting_reference> + </xsl:template> + <xsl:template mode="BG-26" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:BillingSpecifiedPeriod"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:BillingSpecifiedPeriod der Instanz in konkreter Syntax wird auf 2 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-134" + select="./ram:StartDateTime/udt:DateTimeString[@format='102']"/> + <xsl:apply-templates mode="BT-135" + select="./ram:EndDateTime/udt:DateTimeString[@format='102']"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:INVOICE_LINE_PERIOD> + <xsl:attribute name="xr:id" select="'BG-26'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:INVOICE_LINE_PERIOD> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-134" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:BillingSpecifiedPeriod/ram:StartDateTime/udt:DateTimeString[@format='102']"> + <xr:Invoice_line_period_start_date> + <xsl:attribute name="xr:id" select="'BT-134'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="date"/> + </xr:Invoice_line_period_start_date> + </xsl:template> + <xsl:template mode="BT-135" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:BillingSpecifiedPeriod/ram:EndDateTime/udt:DateTimeString[@format='102']"> + <xr:Invoice_line_period_end_date> + <xsl:attribute name="xr:id" select="'BT-135'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="date"/> + </xr:Invoice_line_period_end_date> + </xsl:template> + <xsl:template mode="BG-27" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='false']"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='false'] der Instanz in konkreter Syntax wird auf 5 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-136" select="./ram:ActualAmount"/> + <xsl:apply-templates mode="BT-137" select="./ram:BasisAmount"/> + <xsl:apply-templates mode="BT-138" select="./ram:CalculationPercent"/> + <xsl:apply-templates mode="BT-139" select="./ram:Reason"/> + <xsl:apply-templates mode="BT-140" select="./ram:ReasonCode"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:INVOICE_LINE_ALLOWANCES> + <xsl:attribute name="xr:id" select="'BG-27'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:INVOICE_LINE_ALLOWANCES> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-136" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ActualAmount"> + <xr:Invoice_line_allowance_amount> + <xsl:attribute name="xr:id" select="'BT-136'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Invoice_line_allowance_amount> + </xsl:template> + <xsl:template mode="BT-137" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:BasisAmount"> + <xr:Invoice_line_allowance_base_amount> + <xsl:attribute name="xr:id" select="'BT-137'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Invoice_line_allowance_base_amount> + </xsl:template> + <xsl:template mode="BT-138" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CalculationPercent"> + <xr:Invoice_line_allowance_percentage> + <xsl:attribute name="xr:id" select="'BT-138'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="percentage"/> + </xr:Invoice_line_allowance_percentage> + </xsl:template> + <xsl:template mode="BT-139" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:Reason"> + <xr:Invoice_line_allowance_reason> + <xsl:attribute name="xr:id" select="'BT-139'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Invoice_line_allowance_reason> + </xsl:template> + <xsl:template mode="BT-140" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ReasonCode"> + <xr:Invoice_line_allowance_reason_code> + <xsl:attribute name="xr:id" select="'BT-140'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Invoice_line_allowance_reason_code> + </xsl:template> + <xsl:template mode="BG-28" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='true']"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge[ram:ChargeIndicator='true'] der Instanz in konkreter Syntax wird auf 5 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-141" select="./ram:ActualAmount"/> + <xsl:apply-templates mode="BT-142" select="./ram:BasisAmount"/> + <xsl:apply-templates mode="BT-143" select="./ram:CalculationPercent"/> + <xsl:apply-templates mode="BT-144" select="./ram:Reason"/> + <xsl:apply-templates mode="BT-145" select="./ram:ReasonCode"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:INVOICE_LINE_CHARGES> + <xsl:attribute name="xr:id" select="'BG-28'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:INVOICE_LINE_CHARGES> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-141" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ActualAmount"> + <xr:Invoice_line_charge_amount> + <xsl:attribute name="xr:id" select="'BT-141'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Invoice_line_charge_amount> + </xsl:template> + <xsl:template mode="BT-142" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:BasisAmount"> + <xr:Invoice_line_charge_base_amount> + <xsl:attribute name="xr:id" select="'BT-142'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="amount"/> + </xr:Invoice_line_charge_base_amount> + </xsl:template> + <xsl:template mode="BT-143" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:CalculationPercent"> + <xr:Invoice_line_charge_percentage> + <xsl:attribute name="xr:id" select="'BT-143'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="percentage"/> + </xr:Invoice_line_charge_percentage> + </xsl:template> + <xsl:template mode="BT-144" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:Reason"> + <xr:Invoice_line_charge_reason> + <xsl:attribute name="xr:id" select="'BT-144'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Invoice_line_charge_reason> + </xsl:template> + <xsl:template mode="BT-145" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeAllowanceCharge/ram:ReasonCode"> + <xr:Invoice_line_charge_reason_code> + <xsl:attribute name="xr:id" select="'BT-145'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Invoice_line_charge_reason_code> + </xsl:template> + <xsl:template mode="BG-29" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeAgreement"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeAgreement der Instanz in konkreter Syntax wird auf 5 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-146" select="./ram:NetPriceProductTradePrice/ram:ChargeAmount"/> + <xsl:apply-templates mode="BT-147" + select="./ram:GrossPriceProductTradePrice/ram:AppliedTradeAllowanceCharge/ram:ActualAmount"/> + <xsl:apply-templates mode="BT-148" + select="./ram:GrossPriceProductTradePrice/ram:ChargeAmount"/> + <xsl:apply-templates mode="BT-149" + select="./ram:NetPriceProductTradePrice/ram:BasisQuantity"/> + <xsl:apply-templates mode="BT-149" + select="./ram:GrossPriceProductTradePrice/ram:BasisQuantity"/> + <xsl:apply-templates mode="BT-150" + select="./ram:GrossPriceProductTradePrice/ram:BasisQuantity/@unitCode"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:PRICE_DETAILS> + <xsl:attribute name="xr:id" select="'BG-29'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:PRICE_DETAILS> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-146" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeAgreement/ram:NetPriceProductTradePrice/ram:ChargeAmount"> + <xr:Item_net_price> + <xsl:attribute name="xr:id" select="'BT-146'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="unit_price_amount"/> + </xr:Item_net_price> + </xsl:template> + <xsl:template mode="BT-147" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeAgreement/ram:GrossPriceProductTradePrice/ram:AppliedTradeAllowanceCharge/ram:ActualAmount"> + <xr:Item_price_discount> + <xsl:attribute name="xr:id" select="'BT-147'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="unit_price_amount"/> + </xr:Item_price_discount> + </xsl:template> + <xsl:template mode="BT-148" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeAgreement/ram:GrossPriceProductTradePrice/ram:ChargeAmount"> + <xr:Item_gross_price> + <xsl:attribute name="xr:id" select="'BT-148'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="unit_price_amount"/> + </xr:Item_gross_price> + </xsl:template> + <xsl:template mode="BT-149" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeAgreement/ram:NetPriceProductTradePrice/ram:BasisQuantity"> + <xr:Item_price_base_quantity> + <xsl:attribute name="xr:id" select="'BT-149'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="quantity"/> + </xr:Item_price_base_quantity> + </xsl:template> + <xsl:template mode="BT-149" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeAgreement/ram:GrossPriceProductTradePrice/ram:BasisQuantity"> + <xr:Item_price_base_quantity> + <xsl:attribute name="xr:id" select="'BT-149'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="quantity"/> + </xr:Item_price_base_quantity> + </xsl:template> + <xsl:template mode="BT-150" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeAgreement/ram:GrossPriceProductTradePrice/ram:BasisQuantity/@unitCode"> + <xr:Item_price_base_quantity_unit_of_measure> + <xsl:attribute name="xr:id" select="'BT-150'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Item_price_base_quantity_unit_of_measure> + </xsl:template> + <xsl:template mode="BG-30" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax der Instanz in konkreter Syntax wird auf 2 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-151" select="./ram:CategoryCode"/> + <xsl:apply-templates mode="BT-152" select="./ram:RateApplicablePercent"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:LINE_VAT_INFORMATION> + <xsl:attribute name="xr:id" select="'BG-30'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:LINE_VAT_INFORMATION> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-151" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:CategoryCode"> + <xr:Invoiced_item_VAT_category_code> + <xsl:attribute name="xr:id" select="'BT-151'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Invoiced_item_VAT_category_code> + </xsl:template> + <xsl:template mode="BT-152" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:RateApplicablePercent"> + <xr:Invoiced_item_VAT_rate> + <xsl:attribute name="xr:id" select="'BT-152'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="percentage"/> + </xr:Invoiced_item_VAT_rate> + </xsl:template> + <xsl:template mode="BG-31" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct der Instanz in konkreter Syntax wird auf 8 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-153" select="./ram:Name"/> + <xsl:apply-templates mode="BT-154" select="./ram:Description"/> + <xsl:apply-templates mode="BT-155" select="./ram:SellerAssignedID"/> + <xsl:apply-templates mode="BT-156" select="./ram:BuyerAssignedID"/> + <xsl:apply-templates mode="BT-157" select="./ram:GlobalID"/> + <xsl:apply-templates mode="BT-158" + select="./ram:DesignatedProductClassification/ram:ClassCode"/> + <xsl:apply-templates mode="BT-159" select="./ram:OriginTradeCountry/ram:ID"/> + <xsl:apply-templates mode="BG-32" select="./ram:ApplicableProductCharacteristic"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:ITEM_INFORMATION> + <xsl:attribute name="xr:id" select="'BG-31'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:ITEM_INFORMATION> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-153" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct/ram:Name"> + <xr:Item_name> + <xsl:attribute name="xr:id" select="'BT-153'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Item_name> + </xsl:template> + <xsl:template mode="BT-154" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct/ram:Description"> + <xr:Item_description> + <xsl:attribute name="xr:id" select="'BT-154'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Item_description> + </xsl:template> + <xsl:template mode="BT-155" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct/ram:SellerAssignedID"> + <xr:Item_Sellers_identifier> + <xsl:attribute name="xr:id" select="'BT-155'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Item_Sellers_identifier> + </xsl:template> + <xsl:template mode="BT-156" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct/ram:BuyerAssignedID"> + <xr:Item_Buyers_identifier> + <xsl:attribute name="xr:id" select="'BT-156'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier"/> + </xr:Item_Buyers_identifier> + </xsl:template> + <xsl:template mode="BT-157" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct/ram:GlobalID"> + <xr:Item_standard_identifier> + <xsl:attribute name="xr:id" select="'BT-157'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme"/> + </xr:Item_standard_identifier> + </xsl:template> + <xsl:template mode="BT-158" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct/ram:DesignatedProductClassification/ram:ClassCode"> + <xr:Item_classification_identifier> + <xsl:attribute name="xr:id" select="'BT-158'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="identifier-with-scheme-and-version"/> + </xr:Item_classification_identifier> + </xsl:template> + <xsl:template mode="BT-159" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct/ram:OriginTradeCountry/ram:ID"> + <xr:Item_country_of_origin> + <xsl:attribute name="xr:id" select="'BT-159'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="code"/> + </xr:Item_country_of_origin> + </xsl:template> + <xsl:template mode="BG-32" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct/ram:ApplicableProductCharacteristic"> + <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct/ram:ApplicableProductCharacteristic der Instanz in konkreter Syntax wird auf 2 Objekte der EN 16931 abgebildet. --> + <xsl:apply-templates mode="BT-160" select="./ram:Description"/> + <xsl:apply-templates mode="BT-161" select="./ram:Value"/> + </xsl:variable> + <xsl:if test="$bg-contents"> + <xr:ITEM_ATTRIBUTES> + <xsl:attribute name="xr:id" select="'BG-32'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:sequence select="$bg-contents"/> + </xr:ITEM_ATTRIBUTES> + </xsl:if> + </xsl:template> + <xsl:template mode="BT-160" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct/ram:ApplicableProductCharacteristic/ram:Description"> + <xr:Item_attribute_name> + <xsl:attribute name="xr:id" select="'BT-160'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Item_attribute_name> + </xsl:template> + <xsl:template mode="BT-161" + match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem/ram:SpecifiedTradeProduct/ram:ApplicableProductCharacteristic/ram:Value"> + <xr:Item_attribute_value> + <xsl:attribute name="xr:id" select="'BT-161'"/> + <xsl:attribute name="xr:src" select="xr:src-path(.)"/> + <xsl:call-template name="text"/> + </xr:Item_attribute_value> + </xsl:template> + <xsl:template name="text"> + <xsl:value-of select="."/> + </xsl:template> + <xsl:template name="date"> + <xsl:choose> + <xsl:when test="matches(normalize-space(.), '^[0-9]{8}$')"> + <xsl:value-of select="xs:date( concat(substring(.,1,4), '-', substring(.,5,2), '-', substring(.,7,2) ) )"/> + </xsl:when> + <xsl:otherwise>ILLEGAL DATE FORMAT: <para>Mit diesem Datentyp wird ein kalendarisches Datum abgebildet, wie es in der ISO 8601 Spezifikation <quote>Calendar date complete representation</quote> beschrieben ist (siehe ISO 8601:2004, Abschnitt 5.2.1.1). Das Datum beinhaltet keine Zeitangabe. Das konkret zu verwendende Format ist abhängig von der genutzten Syntax.</para> +<para>Der Datentyp basiert auf dem Typ <quote>Date Time. Type</quote>, wie in ISO 15000-5:2014 Anhang B definiert.</para></xsl:otherwise> + </xsl:choose> + </xsl:template> + <xsl:template name="identifier-with-scheme-and-version"> + <xsl:param name="schemeID" as="element()?"/> + <xsl:if test="@listID | @schemeID"> + <xsl:attribute name="scheme_identifier" select="($schemeID, @listID, @schemeID)[1]"/> + </xsl:if> + <xsl:if test="@schemeVersionID | @listVersionID"> + <xsl:attribute name="scheme_version_identifier" + select="(@listVersionID, @schemeVersionID)[1]"/> + </xsl:if> + <xsl:value-of select="."/> + </xsl:template> + <xsl:template name="identifier-with-scheme"> + <xsl:param name="schemeID" as="element()?"/> + <xsl:if test="@schemeID"> + <xsl:attribute name="scheme_identifier" select="($schemeID, @listID, @schemeID)[1]"/> + </xsl:if> + <xsl:value-of select="."/> + </xsl:template> + <xsl:template name="identifier"> + <xsl:value-of select="."/> + </xsl:template> + <xsl:template name="code"> + <xsl:value-of select="."/> + </xsl:template> + <xsl:template name="amount"> + <xsl:value-of select="."/> + </xsl:template> + <xsl:template name="percentage"> + <xsl:value-of select="."/> + </xsl:template> + <xsl:template name="binary_object"> + <xsl:if test="@mimeCode"> + <xsl:attribute name="mime_code"> + <xsl:value-of select="@mimeCode"/> + </xsl:attribute> + </xsl:if> + <xsl:if test="@filename"> + <xsl:attribute name="filename"> + <xsl:value-of select="@filename"/> + </xsl:attribute> + </xsl:if> + <xsl:value-of select="."/> + </xsl:template> + <xsl:template name="unit_price_amount"> + <xsl:value-of select="."/> + </xsl:template> + <xsl:template name="quantity"> + <xsl:value-of select="."/> + </xsl:template> + <xsl:template name="document_reference"> + <xsl:value-of select="."/> + </xsl:template> + <xd:doc> + <xd:desc> Liefert einen XPath-Pfad, welches $n eindeutig identifiziert. </xd:desc> + <xd:param name="n"/> + </xd:doc> + <xsl:function name="xr:src-path" as="xs:string"> + <xsl:param name="n" as="node()"/> + <xsl:variable name="segments" as="xs:string*"> + <xsl:apply-templates select="$n" mode="xr:src-path"/> + </xsl:variable> + <xsl:sequence select="string-join($segments, '')"/> + </xsl:function> + <xd:doc> + <xd:desc> Liefert einen XPath-Pfad, welches $n eindeutig identifiziert. </xd:desc> + <xd:param name="n"/> + </xd:doc> + <xsl:template match="node() | @*" mode="xr:src-path"> + <xsl:for-each select="ancestor-or-self::*"> + <xsl:text>/</xsl:text> + <xsl:value-of select="name(.)"/> + <xsl:if test="preceding-sibling::*[name(.) = name(current())] or following-sibling::*[name(.) = name(current())]"> + <xsl:text>[</xsl:text> + <xsl:value-of select="count(preceding-sibling::*[name(.) = name(current())]) + 1"/> + <xsl:text>]</xsl:text> + </xsl:if> + </xsl:for-each> + <xsl:if test="not(self::*)"> + <xsl:text/>/@<xsl:value-of select="name(.)"/> + </xsl:if> + </xsl:template> +</xsl:stylesheet> diff --git a/src/main/resources/stylesheets/xrechnung-html.xsl b/src/main/resources/stylesheets/xrechnung-html.xsl new file mode 100644 index 00000000..5e15f314 --- /dev/null +++ b/src/main/resources/stylesheets/xrechnung-html.xsl @@ -0,0 +1,1188 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet version="2.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns:xr="urn:ce.eu:en16931:2017:xoev-de:kosit:standard:xrechnung-1" + xmlns:xrv="http://www.example.org/XRechnung-Viewer"> + + <xsl:output indent="yes" method="html" encoding="UTF-8" /> + + <xsl:decimal-format name="decimal" decimal-separator="," grouping-separator="." NaN="" /> + + + <!-- MAIN HTML --> + <xsl:template match="/xr:invoice"> + + <html lang="de"> + <head> + <meta charset="UTF-8"/> + <title>XRechnung + + + + +
+ +
+
+
+ + + + + +
+
+ + + +
+ + + +
+
Wir übernehmen keine Haftung für die Richtigkeit der Daten.
+
+
+ + + +
+ + + +
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+
+ + + +
+
Informationen zum Käufer
+
+
+
Leitweg-ID:
+
+
+
+
Name:
+
+
+
+
Straße / Hausnummer:
+
+
+
+
Postfach:
+
+
+
+
Adresszusatz:
+
+
+
+
PLZ:
+
+
+
+
Ort:
+
+
+
+
Land:
+
+
+
+
Kennung:
+
+
+
+
Schema der Kennung:
+
+
+
+
Name:
+
+
+
+
Telefon:
+
+
+
+
E-Mail-Adresse:
+
+
+
+
+
+ + + +
+
Informationen zum Verkäufer
+
+
+
Firmenname:
+
+
+
+
Straße / Hausnummer:
+
+
+
+
Postfach:
+
+
+
+
Adresszusatz:
+
+
+
+
PLZ:
+
+
+
+
Ort:
+
+
+
+
Bundesland:
+
+
+
+
Ländercode:
+
+
+
+
Kennung:
+
+
+
+
Schema der Kennung:
+
+
+
+
Name:
+
+
+
+
Telefon:
+
+
+
+
E-Mail-Adresse:
+
+
+
+
+
+ + + +
+
+
Rechnungsdaten
+
+
+
+
+
Rechnungsnummer:
+
+
+
+
Rechnungsdatum:
+
+
+
+
Rechnungsart:
+
+
+
+
Währung:
+
+
+
+

Abrechnungszeitraum:

+
+
+
von:
+
+
+
+
bis:
+
+
+
+
+
+
+
+
+
Projektnummer:
+
+
+
+
Vertragsnummer:
+
+
+
+
Bestellnummer:
+
+
+
+
Auftragsnummer:
+
+
+
+

Vorausgegangene Rechnungen:

+ +
+
+
+
+
+ + +
+
+
Rechnungsnummer:
+
+
+
+
Rechnungsdatum:
+
+
+
+
+ + + +
+
+
Gesamtbeträge der Rechnung
+
+
+
Summe aller Positionen
+
netto
+
+
+
+
Summe Nachlässe
+
netto
+
+
+
+
Summe Zuschläge
+
netto
+
+
+
+
Gesamtsumme
+
netto
+
+
+
+
Summe Umsatzsteuer
+
+
+
+
+
Summe Umsatzsteuer in Abrechnungswährung
+
+
+
+
+
Gesamtsumme
+
brutto
+
+
+
+
Gezahlter Betrag
+
brutto
+
+
+
+
Rundungsbetrag
+
brutto
+
+
+
+
Fälliger Betrag
+
brutto
+
+
+
+
+
+
+ + + +
+
+
Aufschlüsselung der Umsatzsteuer auf Ebene der Rechnung
+
+
+
Umsatzsteuerkategorie:
+
+
+
+
+
Gesamtsumme
+
netto
+
+
+
+
Umsatzsteuersatz
+
+
%
+
+
+
Umsatzsteuerbetrag
+
+
+
+
+ +
+
Befreiungsgrund:
+
Kennung für den Befreiungsgrund:
+
+
+
+
+ + + +
+
+
Nachlass auf Ebene der Rechnung
+
+
+
Umsatzsteuerkategorie des Nachlasses:
+
+
+
+
+
Grundbetrag
+
netto
+
+
+
+
Prozentsatz
+
+
%
+
+
+
Nachlass
+
netto
+
+
+
+
Umsatzsteuersatz des Nachlasses
+
+
+
+
+
+
Grund für den Nachlass:
+
Document level allowance reason code:
+
+
+
+
+
+ + + +
+
+
Zuschlag auf Ebene der Rechnung
+
+
+
Umsatzsteuerkategorie des Zuschlages:
+
+
+
+
+
Grundbetrag
+
netto
+
+
+
+
Prozentsatz
+
+
%
+
+
+
Zuschlag
+
netto
+
+
+
+
Umsatzsteuersatz des Zuschlages
+
+
+
+
+
+
Grund für den Zuschlag:
+
Document level charge reason code:
+
+
+
+
+
+ + + +
+
Zahlungsdaten
+
+
+
Skonto; weitere Zahlungsbedingungen:
+
+
+
+
Fälligkeitsdatum:
+
+
+
+
Code für das Zahlungsmittel:
+
+
+
+
Zahlungsmittel:
+
+
+
+
Verwendungszweck:
+
+
+
+
+
+ + + +
+
Karteninformation
+
+
+
Kartennummer:
+
+
+
+
Karteninhaber:
+
+
+
+
+
+ + + +
+
Lastschrift
+
+
+
Mandatsreferenznr.:
+
+
+
+
IBAN:
+
+
+
+
Gläubiger-ID:
+
+
+
+
+
+ + + +
+
Überweisung
+
+
+
Kontoinhaber:
+
+
+
+
IBAN:
+
+
+
+
BIC:
+
+
+
+
+
+ + + +
+
Bemerkung zur Rechnung
+
+
+
Betreff:
+
+
+
+
Bemerkung:
+
+
+
+
+
+ + + +
+
Wir übernehmen keine Haftung für die Richtigkeit der Daten.
+ +
+
+ + + +
+
+
+
Position
+
+
+
Freitext:
+
+
+
+
Objektkennung:
+
+
+
+
Schema der Objektkennung:
+
+
+
+
Nummer der Auftragsposition:
+
+
+
+
Kontierungshinweis:
+
+
+

Abrechnungszeitraum:

+
+
von:
+
+
+
+
bis:
+
+
+
+
+
+
Preiseinzelheiten
+
+
+
Menge
+
+
+
+
Einheit
+
+
+
+
Preis pro Einheit (netto)
+
+
+
+
Gesamtpreis (netto)
+
+
+
+
+
+
Rabatt (netto):
+
+
+
+
Listenpreis (netto):
+
+
+
+
Anzahl der Einheit:
+
+
+
+
Code der Maßeinheit:
+
+
+
+
Umsatzsteuer:
+
+
+
+
Umsatzsteuersatz in Prozent:
+
%
+
+
+
+
+
+
+
+
+
Nachlässe auf Ebene der Rechnungsposition
+
+
+
Grundbetrag (netto)
+
+
+
+
Prozentsatz
+
%
+
+
+
Nachlass (netto)
+
+
+
+
+
Grund des Nachlasses:
+
Code für den Nachlassgrund:
+
+
+
+
Zuschläge auf Ebene der Rechnungsposition
+
+
+
Grundbetrag (netto)
+
+
+
+
Prozentsatz
+
%
+
+
+
Zuschlag (netto)
+
+
+
+
+
Grund des Zuschlags:
+
Code für den Zuschlagsgrund:
+
+
+
+
+
+
+
+
Artikelinformationen
+
+
+
+
+
+
Bezeichnung:
+
+
+
+
Beschreibung:
+
+
+
+
Artikelnummer:
+
+
+
+
Artikelkennung des Käufers:
+
+
+

Eigenschaften des Artikels:

+ +
+
+
+
+
+
+
Artikelkennung:
+
+
+
+
Schema der Artikelkennung:
+
+
+
+
Code der Artikelklassifizierung:
+
+
+
+
Kennung zur Bildung des Schemas:
+
+
+
+
Version zur Bildung des Schemas:
+
+
+
+
Code des Herkunftslandes:
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+ + + +
+
Wir übernehmen keine Haftung für die Richtigkeit der Daten.
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+ + + +
+
Informationen zum Verkäufer
+
+
+
Abweichender Handelsname:
+
+
+
+
Bundesland:
+
+
+
+
Elektronische Adresse:
+
+
+
+
Schema der elektronischen Adresse:
+
+
+
+
Register-/Registriernummer:
+
+
+
+
Umsatzsteuer-ID:
+
+
+
+
Steuernummer:
+
+
+
+
Schema der Steuernummer:
+
+
+
+
Weitere rechtliche Informationen:
+
+
+
+
Code der Umsatzsteuerwährung:
+
+
+
+
+
+ + + +
+
Steuervertreter des Verkäufers
+
+
+
Name:
+
+
+
+
Straße / Hausnummer:
+
+
+
+
Postfach:
+
+
+
+
Adresszusatz:
+
+
+
+
PLZ:
+
+
+
+
Ort:
+
+
+
+
Bundesland:
+
+
+
+
Ländercode:
+
+
+
+
Umsatzsteuer-ID:
+
+
+
+
+
+ + + +
+
Informationen zum Käufer
+
+
+
Abweichender Handelsname:
+
+
+
+
Bundesland:
+
+
+
+
Elektronische Adresse:
+
+
+
+
Schema der elektronischen Adresse:
+
+
+
+
Register-/Registriernummer:
+
+
+
+
Schema der Register-/Registriernummer:
+
+
+
+
Umsatzsteuer-ID:
+
+
+
+
Abrechnungsdatum der Umsatzsteuer:
+
+
+
+
Code des Umsatzsteuer-Abrechnungsdatums:
+
+
+
+
Kontierungsinformation:
+
+
+
+
+
+ + + +
+
Lieferinformationen
+
+
+
Kennung des Lieferorts:
+
+
+
+
Schema der Kennung:
+
+
+
+
Lieferdatum:
+
+
+
+
Name des Empfängers:
+
+
+
+
Straße / Hausnummer:
+
+
+
+
Postfach:
+
+
+
+
Adresszusatz:
+
+
+
+
PLZ:
+
+
+
+
Ort:
+
+
+
+
Bundesland:
+
+
+
+
Land:
+
+
+
+
+
+ + + +
+
Informationen zum Vertrag
+
+
+
Vergabenummer:
+
+
+
+
Kennung der Empfangsbestätigung:
+
+
+
+
Kennung der Versandanzeige:
+
+
+
+
Prozesskennung:
+
+
+
+
Spezifikationskennung:
+
+
+
+
Objektkennung:
+
+
+
+
Schema der Objektkennung:
+
+
+
+
+
+ + + +
+
Vom Verkäufer abweichender Zahlungsempfänger
+
+
+
Name:
+
+
+
+
Kennung:
+
+
+
+
Schema der Kennung:
+
+
+
+
Register-/Registriernummer:
+
+
+
+
Schema der Register-/Registriernummer:
+
+
+
+
+
+ + + +
+
Wir übernehmen keine Haftung für die Richtigkeit der Daten.
+
+
+
+
Rechnungsbegründende Unterlagen
+ +
+
+
+
+
+ + + +
+
+
Kennung:
+
+
+
+
Beschreibung:
+
+
+
+
Verweis (z.B. Internetadresse):
+
+
+
+
Anhangsdokument:
+
+ Öffnen +
+ + +
+
+
Format des Anhangdokuments:
+
+
+
+
Name des Anhangsdokuments:
+
+
+
+
+ + + +
+
+
+
+
Bearbeitungshistorie
+ +
+
+
+
+
+ + + +
+
+
Datum/Uhrzeit:
+
+
+
+
Betreff:
+
+
+
+
Text:
+
+
+
+
Details:
+
+
+
+
+ +
diff --git a/src/test/resources/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf b/src/test/resources/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9c4ae5582f811026979dfb671f1f830045eede1f GIT binary patch literal 87968 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 literal 0 HcmV?d00001 From ca05dbc0dcde2378a879b4887f5ba552c2bbe70a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sat, 6 Jul 2019 13:45:04 +0200 Subject: [PATCH 27/82] no message --- xrechnung-viewer.css | 917 +++++++++++++++++++++++++++++++++++++++++++ xrechnung-viewer.js | 145 +++++++ 2 files changed, 1062 insertions(+) create mode 100644 xrechnung-viewer.css create mode 100644 xrechnung-viewer.js diff --git a/xrechnung-viewer.css b/xrechnung-viewer.css new file mode 100644 index 00000000..adea4c9b --- /dev/null +++ b/xrechnung-viewer.css @@ -0,0 +1,917 @@ +/* Grundformatierung ********************************************/ + +*, +*:after, +*:before +{ + box-sizing: border-box; + -moz-box-sizing: border-box; +} + +.clear:after +{ + content: "."; + clear: both; + display: block; + visibility: hidden; + height: 0; +} + +html, +body +{ + height: 100%; + min-width: 320px; + margin: 0; + padding: 0; + color: #000; + font-size: 14px; +} + +body +{ + overflow-y: scroll; + background-color: rgba(4, 101, 161, 0.08); +} + +h4 +{ + color: inherit; + font-size: inherit; + margin-bottom: 0.5rem; +} + + +/* Grundaufbau *************************************************/ + +.menue +{ + position: relative; + z-index: 2000; + background-color: #000; + margin-bottom: 30px; +} + +.innen +{ + max-width: 1080px; + margin: 0 auto; + padding: 0 2%; +} + + + +/* Formatierungen *************************************************/ + +.color2 +{ + color: rgba(0, 0, 0, 0.6); +} + +.schwarz +{ + color: #555 !important; +} + +.normal +{ + font-weight: normal; +} + +.bold +{ + font-weight: bold; +} + +.abstandUnten +{ + margin-bottom: 5px; +} + +.abstandUntenKlein +{ + margin-bottom: 10px; +} + +.noPaddingTop +{ + padding-top: 0 !important; +} + +.ausrichtungRechts +{ + text-align: right; +} + + + + +/* Menü ********************************************************/ + +button +{ + position: relative; + font-family: serif; + padding-top: 15px; + padding-left: 0; + padding-right: 0; + margin-right: 2%; +} + +.btnAktiv +{ + font-size: 22px; + color: #ffb619; + height: 50px; + outline: none; + border: none; + background: none; +} + +.btnAktiv:after +{ + content: ""; + display: block; + position: absolute; + top: 50px; + left: 50%; + z-index: 10; + font-size: 0; + line-height: 0; + height: 0; + padding: 0; + margin: 0; + transform: translateX(-50%); + border: 15px solid #000; + border-right-color: transparent; + border-bottom-color: transparent; + border-left-color: transparent; +} + +.btnInaktiv, +.tab +{ + font-size: 22px; + color: #fff; + height: 50px; + z-index: 0; + outline: none; + border: none; + background: none; + transition: color 0.3s ease; +} + +.btnInaktiv:hover, +.tab:hover +{ + color: #ffb619; + cursor: pointer; +} + +.divHide +{ + display: none; +} + +/* Content *********************************************************************/ + +.inhalt +{ + font-family: sans-serif; + margin-bottom: 30px; +} + +.haftungausschluss +{ + color: #000; + text-align: center; + padding: 7px; + margin-bottom: 30px; + width: 100%; + border: 1px solid #ffb619; + background-color: #fff; +} + +.box +{ + position: relative; + display: table-cell; + padding: 0; + border: 1px solid rgba(4, 101, 161, 0.2); + background-color: #fff; +} + +.subBox +{ + border-top: none; + width: 50%; +} + +.subBox:last-child +{ + border-left: none; +} + +.first > .boxzeile > .subBox +{ + border-top: 1px solid rgba(4, 101, 161, 0.2) !important; +} + +.boxtitel +{ + display: inline-block; + background-color: #0465A1; + padding: 7px 10px; + color: #fff; + font-weight: bold; +} + +.boxBorderTop +{ + border-top: none; +} + +.boxBorderLeft +{ + border-left: none; +} + +.boxtitelSub +{ + color: #000; + background-color: rgba(4, 101, 161, 0.1); + border-right: 1px solid rgba(4, 101, 161, 0.2); + border-bottom: 1px solid rgba(4, 101, 161, 0.2); +} + +.boxinhalt +{ + padding: 15px 20px; +} + +.boxtabelle +{ + display: table; + width: 100%; +} + +.borderSpacing +{ + border-spacing: 0 5px; +} + +.boxabstandtop +{ + margin-top: 30px; +} + +.boxzeile +{ + display: table-row; +} + +.boxzeile .box:last-child +{ + margin-bottom: 0; +} + +.boxdaten +{ + display: table-cell; + padding: 5px 0; + vertical-align: middle; + height: 38px; + /* + -ms-word-break: break-all; + word-break: break-all; + word-break: break-word; + -webkit-hyphens: auto; + -moz-hyphens: auto; + hyphens: auto; +*/ +} + +.boxdaten.wert +{ + padding: 5px 10px; +} + +.boxcell +{ + display: table-cell; +} + +.boxdatenBlock +{ + display: block; + padding: 3px 0; + /* + -ms-word-break: break-all; + word-break: break-all; + word-break: break-word; + -webkit-hyphens: auto; + -moz-hyphens: auto; + hyphens: auto; +*/ +} + +.noBreak +{ + -ms-word-break: keep-all; + word-break: keep-all; + word-break: keep-all; + -webkit-hyphens: none; + -moz-hyphens: none; + hyphens: none; +} + +.boxabstand +{ + display: table-cell; + width: 30px; +} + +.legende +{ + color: rgba(0, 0, 0, 0.6); + width: 170px; + font-size: 13px; + line-height: 16px; + padding-right: 5px; +} + +.wert +{ + background-color: rgba(4, 101, 161, 0.03); +} + +.boxtabelleEinspaltig +{ + width: 49%; +} + +.boxtabelleZweispaltig, +.boxtabelleDreispaltig +{ + width: 100%; +} + +.box5050 +{ + width: 50%; +} + +.boxEinspaltig +{ + width: 100%; +} + +.boxZweispaltig +{ + width: 48.5%; +} + +.boxSpalte1 { + width: 50%; +} + +.boxSpalte2 { + width: 50%; + padding-left: 20px; +} + +.paddingLeft { + padding-left: 0.1em; +} + +.noPadding { + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.rechnungsZeile +{ + display: table-row; +} + +.rechnungsZeile .boxdaten +{ + height: auto; +} + +.rechnungSp1 +{ + width: 65%; + font-size: 16px; +} + +.rechnungSp2 +{ + width: 10%; +} + +.rechnungSp3 +{ + width: 25%; + font-size: 16px; + text-align: right; +} + +.detailSp1, +.detailSp2 +{ + width: 50%; +} + +.detailSp2 +{ + text-align: right; +} + +.line1Bottom +{ + border-bottom: 1px solid #000; +} + +.line1BottomLight +{ + padding-bottom: 5px; + border-bottom: 1px solid #f0f0f0; + margin-bottom: 5px; +} + +.line2Bottom +{ + border-bottom: 2px solid #000; +} + +.paddingTop +{ + padding-top: 10px; +} + +.paddingBottom +{ + padding-bottom: 10px; +} + +.grund +{ + font-size: 16px; + display: block; + width: 100%; + padding: 0 20px 15px 20px; +} + +.grundDetail +{ + display: block; + width: 100%; + padding: 0 20px 15px 20px; +} + +/* Übersichtformatierungen */ +#uebersichtLastschrift.box, +#uebersichtUeberweisung.box +{ + border-top: none; +} + +#uebersichtUeberweisung.box +{ + border-left: none; +} + + +/* Formatierungen Detailseite */ + +.detailsSpalte1, +.detailsSpalte2 +{ + width: 30%; + float: left; + font-size: 90%; + line-height: 115%; + margin-right: 5%; +} + +.detailsSpalte3 +{ + width: 30%; + float: left; + font-size: 90%; + line-height: 115%; +} + +.detailsSpalte1 .legende, +.detailsSpalte2 .legende, +.detailsSpalte3 .legende +{ + width: 145px; +} + +.titelPosition +{ + font-size: 17px; + font-weight: bold; +} + + +/* Laufzettelformatierungen */ +#laufzettelHistorie .boxtabelle:not(:nth-child(2)) +{ + border-top: 1px solid rgba(4, 101, 161, 0.2); + padding-top: 10px; + margin-top: 10px; +} + + + + + +/* 1023px und kleiner ************************************************/ + +@media screen and (max-width : 1023px) { + + .box + { + display: block; + width: 100%; + margin-bottom: 20px; + } + + .boxabstandtop + { + margin-top: 15px; + } + + .subBox:first-child + { + margin-bottom: 0 !important; + } + + .subBox:last-child + { + border-left: 1px solid rgba(4, 101, 161, 0.2); + } + + .first > .boxzeile > .subBox + { + border-top: none !important; + } + + .first > .boxzeile > .subBox:first-child + { + border-top: 1px solid rgba(4, 101, 161, 0.2) !important; + } + + .first > .boxzeile + { + margin-bottom: 0; + } + + #uebersichtUeberweisung.box + { + border-left: 1px solid rgba(4, 101, 161, 0.2); + } + + #uebersichtLastschrift.box + { + margin-bottom: 0; + } + + .boxzeile + { + display: block; + margin-bottom: 5px; + } + + .boxzeile:after + { + visibility: hidden; + display: block; + font-size: 0; + content: " "; + clear: both; + height: 0; + } + + #details > .boxtabelle > .boxzeile + { + margin-bottom: 0px; + } + + .boxcell + { + display: block; + } + + .boxcell:last-child + { + margin-top: 20px; + } + + .boxZweispaltig + { + width: 100%; + } + + .legende + { + display: block; + float: left; + width: 170px; + padding: 5px 0; + height: auto; + } + + .wert + { + display: block; + float: left; + width: calc(100% - 170px); + padding: 11px 10px !important; + line-height: 1.3; + min-height: 38px; + height: auto; + } + + .boxdaten .legende + { + height: auto; + } + + .rechnungsZeile .boxdaten + { + padding: 5px 0; + } + + .boxabstand + { + display: none; + } + + .boxtabelleEinspaltig { + width: 100%; + } + + .boxSpalte1 { + display: block; + width: auto; + } + + .boxSpalte2 { + display: block; + width: auto; + padding-left: 0px; + margin-top: 1.2rem; + } + + .detailsSpalte1, + .detailsSpalte2, + .detailsSpalte3 + { + width: 100%; + float: none; + padding-right: 0px; + } + + .detailsSpalte2, + .detailsSpalte3 + { + margin-top: 15px; + } + + .detailsSpalte2, + .detailsSpalte3 + { + margin-top: 10px; + } + + .tableNumberAlignRight + { + display: block; + width: 130px; + text-align: right; + } +} + + + +/* 800px und kleiner ************************************************/ + +@media screen and (max-width : 800px) { + + button + { + padding-top: 10px; + } + + .btnAktiv, + .btnInaktiv, + .tab + { + font-size: 20px; + height: 40px; + } + + .btnAktiv:after + { + top: 40px; + } + + .rechnungSp1 + { + width: 55%; + font-size: 15px; + } + + .rechnungSp2 + { + width: 10%; + } + + .rechnungSp3 + { + width: 35%; + text-align: right; + font-size: 15px; + } + + .grund + { + font-size: 15px; + } +} + +/* 450px und kleiner ************************************************/ + +@media screen and (max-width : 450px) +{ + + html, + body + { + font-size: 12px; + } + + .menue + { + margin-bottom: 20px; + } + + button + { + padding-top: 5px; + } + + .btnAktiv, + .btnInaktiv, + .tab + { + font-size: 17px; + height: 35px; + } + + .btnAktiv:after + { + top: 35px; + } + + .legende + { + font-size: 12px; + width: 100%; + } + + .wert + { + font-size: 12px; + line-height: 1.3; + width: 100%; + margin-bottom: 10px + } + + .boxzeile + { + margin-bottom: 0px + } + + .boxdaten + { + height: auto; + } + + .haftungausschluss + { + margin-bottom: 20px; + } + + .boxinhalt + { + margin-top: 0px; + } + + .boxabstandtop + { + margin-top: 20px; + } + + .boxtitel + { + padding: 7px 8px; + } + + .box + { + margin-bottom: 10px; + padding: 0; + } + + .boxabstandtop + { + margin-top: 10px; + } + + .boxdaten, + .boxdatenBlock + { + padding: 2px 0; + } + + .rechnungSp1 + { + width: 50%; + font-size: inherit; + } + + .rechnungSp2 + { + width: 15%; + } + + .rechnungSp3 + { + width: 35%; + font-size: inherit; + text-align: right; + } + + .grund + { + font-size: inherit; + } + + .titelPosition + { + font-size: 15px; + } + + .abstandUnten + { + margin-bottom: 5px; + } + + .detailsSpalte1, + .detailsSpalte2, + .detailsSpalte3 + { + font-size: inherit; + line-height: inherit; + } +} + +/* 380px und kleiner ************************************************/ + +@media screen and (max-width : 380px) { + + html, + body + { + font-size: 11px; + line-height: 100%; + } + + .btnAktiv, + .btnInaktiv, + .tab + { + font-size: 15px; + } + + .boxdaten +.boxdatenBlock + { + padding: 2px 0; + } + + .boxinhalt + { + margin-top: 0px; + } + + .boxtitel + { + padding: 5px 7px; + } +} diff --git a/xrechnung-viewer.js b/xrechnung-viewer.js new file mode 100644 index 00000000..2d547b86 --- /dev/null +++ b/xrechnung-viewer.js @@ -0,0 +1,145 @@ + +/* Tab-Container aufbauen **************************************************/ + +var a = new Array("uebersicht", "details", "zusaetze", "anlagen", "laufzettel"); +var b = new Array("menueUebersicht", "menueDetails", "menueZusaetze", "menueAnlagen", "menueLaufzettel"); + +function show(e) { + var i = 0; + var j = 1; + for (var t = 0; t < b.length; t++) { + if (b[t] === e.id) { + i = t; + if (i > 0) { + j = 0; + } else { + j = i + 1; + } + break; + } + } + e.setAttribute("class", "btnAktiv"); + for (var k = 0; k < b.length; k++) { + if (k === i && (document.getElementById(a[k]) != null)) { + document.getElementById(a[k]).style.display = "block"; + if (i === j) + j = i + 1; + } else { + if (document.getElementById(a[k]) != null) { + document.getElementById(a[j]).style.display = "none"; + document.getElementById(b[j]).setAttribute("class", "btnInaktiv"); + j += 1; + } + } + } +} +window.onload = function () { + document.getElementById(b[0]).setAttribute("class", "btnAktiv"); +} + +/* Eingebettete Binaerdaten runterladen ************************************/ + + +function base64_to_binary (data) { + var chars = atob(data); + var bytes = new Array(chars.length); + for (var i = 0; i < chars.length; i++) { + bytes[i] = chars.charCodeAt(i); + } + return new Uint8Array(bytes); +} + +function downloadData (element_id) { + var data_element = document.getElementById(element_id); + var mimetype = data_element.getAttribute('mimeType'); + var filename = data_element.getAttribute('filename'); + var text = data_element.innerHTML; + var binary = base64_to_binary(text); + var blob = new Blob([binary], { + type: mimetype, size: binary.length + }); + + if (window.navigator && window.navigator.msSaveOrOpenBlob) { + // IE + window.navigator.msSaveOrOpenBlob(blob, filename); + } else { + // Non-IE + var url = window.URL.createObjectURL(blob); + window.open(url); + } +} + + +/* Polyfill IE atob/btoa ************************************/ + +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], function () { + factory(root); + }); + } else factory(root); + // node.js has always supported base64 conversions, while browsers that support + // web workers support base64 too, but you may never know. +})(typeof exports !== "undefined" ? exports: this, function (root) { + if (root.atob) { + // Some browsers' implementation of atob doesn't support whitespaces + // in the encoded string (notably, IE). This wraps the native atob + // in a function that strips the whitespaces. + // The original function can be retrieved in atob.original + try { + root.atob(" "); + } + catch (e) { + root.atob = (function (atob) { + var func = function (string) { + return atob(String(string).replace(/[\t\n\f\r ]+/g, "")); + }; + func.original = atob; + return func; + })(root.atob); + } + return; + } + + // base64 character set, plus padding character (=) + var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", + // Regular expression to check formal correctness of base64 encoded strings + b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/; + + root.btoa = function (string) { + string = String(string); + var bitmap, a, b, c, + result = "", i = 0, + rest = string.length % 3; // To determine the final padding + + for (; i < string.length;) { + if ((a = string.charCodeAt(i++)) > 255 || (b = string.charCodeAt(i++)) > 255 || (c = string.charCodeAt(i++)) > 255) + throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range."); + + bitmap = (a << 16) | (b << 8) | c; + result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) + b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63); + } + + // If there's need of padding, replace the last 'A's with equal signs + return rest ? result.slice(0, rest - 3) + "===".substring(rest): result; + }; + + root.atob = function (string) { + // atob can work with strings with whitespaces, even inside the encoded part, + // but only \t, \n, \f, \r and ' ', which can be stripped. + string = String(string).replace(/[\t\n\f\r ]+/g, ""); + if (! b64re.test(string)) + throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded."); + + // Adding the padding if missing, for semplicity + string += "==".slice(2 - (string.length & 3)); + var bitmap, result = "", r1, r2, i = 0; + for (; i < string.length;) { + bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12 | (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++))); + + result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255): r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255): String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255); + } + return result; + }; +}); \ No newline at end of file From afb6ae9a8db9e41d61bb5dff914d62005d16343a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sat, 6 Jul 2019 13:51:36 +0200 Subject: [PATCH 28/82] no message --- History.md | 1 + .../ZUGFeRD/ZUGFeRDVisualizer.java | 134 - .../org/mustangproject/toecount/Toecount.java | 44 - src/main/resources/stylesheets/cii-xr.xsl | 2202 ----------------- .../resources/stylesheets/xrechnung-html.xsl | 1188 --------- 5 files changed, 1 insertion(+), 3568 deletions(-) delete mode 100644 src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java delete mode 100644 src/main/resources/stylesheets/cii-xr.xsl delete mode 100644 src/main/resources/stylesheets/xrechnung-html.xsl diff --git a/History.md b/History.md index f24355a2..704cc024 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ 1.7.2 ===== +2019-07-06 Support BuyerReference (r+w), as well as SpecifiedLegalOrganization (w) and DefinedTradeContact (w) use dom4j to format output xml document diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java deleted file mode 100644 index 03b820b3..00000000 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java +++ /dev/null @@ -1,134 +0,0 @@ -/** ********************************************************************** - * - * 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.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; - - 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"))); - } 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 - */ - ByteArrayOutputStream iaos = new ByteArrayOutputStream(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - applySchematronXsl(new FileInputStream(xmlFilename), 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) { - // logging and exception handling should go here - } - 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 - e.printStackTrace(); - } - } - } - } - }).start(); - applySchematronXsl2(in, baos); - } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - 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 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)); - } - } -} diff --git a/src/main/java/org/mustangproject/toecount/Toecount.java b/src/main/java/org/mustangproject/toecount/Toecount.java index 06843a4c..34b58526 100755 --- a/src/main/java/org/mustangproject/toecount/Toecount.java +++ b/src/main/java/org/mustangproject/toecount/Toecount.java @@ -324,8 +324,6 @@ public class Toecount { performConvert(sourceName, outName); } else if (upgradeRequested) { performUpgrade(sourceName, outName); - } else if (action.equals("convertToHTML")) { - performVisualization(sourceName, outName); } else { // no argument or argument unknown printUsage(); @@ -339,48 +337,6 @@ public class Toecount { } - private static void performVisualization(String sourceName, String outName) { - // Get params from user if not already defined - if (sourceName == null) { - sourceName = getFilenameFromUser("ZUGFeRD XML source", "zugferd-invoice.xml", "xml", true, false); - } else { - System.out.println("ZUGFeRD XML source set to " + sourceName); - } - if (outName == null) { - outName = getFilenameFromUser("ZUGFeRD 2.0 XML target", "factur-x.html", "html", false, true); - } else { - System.out.println("ZUGFeRD 1.0 XML source set to " + outName); - } - - // Verify params - try { - ensureFileExists(sourceName); - ensureFileNotExists(outName); - - //stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt - } catch (IOException e) { - Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); - } - - ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer(); - String xml = null; - try { - xml = zvi.visualize(sourceName); - Files.write(Paths.get(outName), xml.getBytes()); - } catch (FileNotFoundException e) { - Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); - } catch (UnsupportedEncodingException e) { - Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); - } catch (TransformerException e) { - Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); - } catch (IOException e) { - Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); - } - System.out.println("Written to " + outName); - - - } - private static void performUpgrade(String xmlName, String outName) throws IOException, TransformerException { // Get params from user if not already defined diff --git a/src/main/resources/stylesheets/cii-xr.xsl b/src/main/resources/stylesheets/cii-xr.xsl deleted file mode 100644 index 5fca7b9d..00000000 --- a/src/main/resources/stylesheets/cii-xr.xsl +++ /dev/null @@ -1,2202 +0,0 @@ - - - - - - Author: KoSIT Bremen (kosit@finanzen.bremen.de) - Fassung vom: 2019-03-18+01:00 - Überführt eine zur EN 16931 konforme elektronische Rechnung in der konkreten Syntax UNCEFACT.CII.D16B in eine Instanz gemäß des Schemas für den Namensraum urn:ce.eu:en16931:2017:xoev-de:kosit:standard:xrechnung-1. - Das Skript setzt voraus, dass das zu verarbeitende Dokument valide bzgl. des XML Schemas und der Schematron-Regeln der Quelle ist. Für nicht valide Dokumente ist das Ergebnis nicht definiert. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ILLEGAL DATE FORMAT: <para>Mit diesem Datentyp wird ein kalendarisches Datum abgebildet, wie es in der ISO 8601 Spezifikation <quote>Calendar date complete representation</quote> beschrieben ist (siehe ISO 8601:2004, Abschnitt 5.2.1.1). Das Datum beinhaltet keine Zeitangabe. Das konkret zu verwendende Format ist abhängig von der genutzten Syntax.</para> -<para>Der Datentyp basiert auf dem Typ <quote>Date Time. Type</quote>, wie in ISO 15000-5:2014 Anhang B definiert.</para> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Liefert einen XPath-Pfad, welches $n eindeutig identifiziert. - - - - - - - - - - - Liefert einen XPath-Pfad, welches $n eindeutig identifiziert. - - - - - / - - - [ - - ] - - - - /@ - - - diff --git a/src/main/resources/stylesheets/xrechnung-html.xsl b/src/main/resources/stylesheets/xrechnung-html.xsl deleted file mode 100644 index 5e15f314..00000000 --- a/src/main/resources/stylesheets/xrechnung-html.xsl +++ /dev/null @@ -1,1188 +0,0 @@ - - - - - - - - - - - - - - - XRechnung - - - - -
- -
-
-
- - - - - -
-
- - - -
- - - -
-
Wir übernehmen keine Haftung für die Richtigkeit der Daten.
-
-
- - - -
- - - -
-
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
-
- - -
-
- -
-
- - -
-
- -
-
- -
-
-
-
- - - -
-
Informationen zum Käufer
-
-
-
Leitweg-ID:
-
-
-
-
Name:
-
-
-
-
Straße / Hausnummer:
-
-
-
-
Postfach:
-
-
-
-
Adresszusatz:
-
-
-
-
PLZ:
-
-
-
-
Ort:
-
-
-
-
Land:
-
-
-
-
Kennung:
-
-
-
-
Schema der Kennung:
-
-
-
-
Name:
-
-
-
-
Telefon:
-
-
-
-
E-Mail-Adresse:
-
-
-
-
-
- - - -
-
Informationen zum Verkäufer
-
-
-
Firmenname:
-
-
-
-
Straße / Hausnummer:
-
-
-
-
Postfach:
-
-
-
-
Adresszusatz:
-
-
-
-
PLZ:
-
-
-
-
Ort:
-
-
-
-
Bundesland:
-
-
-
-
Ländercode:
-
-
-
-
Kennung:
-
-
-
-
Schema der Kennung:
-
-
-
-
Name:
-
-
-
-
Telefon:
-
-
-
-
E-Mail-Adresse:
-
-
-
-
-
- - - -
-
-
Rechnungsdaten
-
-
-
-
-
Rechnungsnummer:
-
-
-
-
Rechnungsdatum:
-
-
-
-
Rechnungsart:
-
-
-
-
Währung:
-
-
-
-

Abrechnungszeitraum:

-
-
-
von:
-
-
-
-
bis:
-
-
-
-
-
-
-
-
-
Projektnummer:
-
-
-
-
Vertragsnummer:
-
-
-
-
Bestellnummer:
-
-
-
-
Auftragsnummer:
-
-
-
-

Vorausgegangene Rechnungen:

- -
-
-
-
-
- - -
-
-
Rechnungsnummer:
-
-
-
-
Rechnungsdatum:
-
-
-
-
- - - -
-
-
Gesamtbeträge der Rechnung
-
-
-
Summe aller Positionen
-
netto
-
-
-
-
Summe Nachlässe
-
netto
-
-
-
-
Summe Zuschläge
-
netto
-
-
-
-
Gesamtsumme
-
netto
-
-
-
-
Summe Umsatzsteuer
-
-
-
-
-
Summe Umsatzsteuer in Abrechnungswährung
-
-
-
-
-
Gesamtsumme
-
brutto
-
-
-
-
Gezahlter Betrag
-
brutto
-
-
-
-
Rundungsbetrag
-
brutto
-
-
-
-
Fälliger Betrag
-
brutto
-
-
-
-
-
-
- - - -
-
-
Aufschlüsselung der Umsatzsteuer auf Ebene der Rechnung
-
-
-
Umsatzsteuerkategorie:
-
-
-
-
-
Gesamtsumme
-
netto
-
-
-
-
Umsatzsteuersatz
-
-
%
-
-
-
Umsatzsteuerbetrag
-
-
-
-
- -
-
Befreiungsgrund:
-
Kennung für den Befreiungsgrund:
-
-
-
-
- - - -
-
-
Nachlass auf Ebene der Rechnung
-
-
-
Umsatzsteuerkategorie des Nachlasses:
-
-
-
-
-
Grundbetrag
-
netto
-
-
-
-
Prozentsatz
-
-
%
-
-
-
Nachlass
-
netto
-
-
-
-
Umsatzsteuersatz des Nachlasses
-
-
-
-
-
-
Grund für den Nachlass:
-
Document level allowance reason code:
-
-
-
-
-
- - - -
-
-
Zuschlag auf Ebene der Rechnung
-
-
-
Umsatzsteuerkategorie des Zuschlages:
-
-
-
-
-
Grundbetrag
-
netto
-
-
-
-
Prozentsatz
-
-
%
-
-
-
Zuschlag
-
netto
-
-
-
-
Umsatzsteuersatz des Zuschlages
-
-
-
-
-
-
Grund für den Zuschlag:
-
Document level charge reason code:
-
-
-
-
-
- - - -
-
Zahlungsdaten
-
-
-
Skonto; weitere Zahlungsbedingungen:
-
-
-
-
Fälligkeitsdatum:
-
-
-
-
Code für das Zahlungsmittel:
-
-
-
-
Zahlungsmittel:
-
-
-
-
Verwendungszweck:
-
-
-
-
-
- - - -
-
Karteninformation
-
-
-
Kartennummer:
-
-
-
-
Karteninhaber:
-
-
-
-
-
- - - -
-
Lastschrift
-
-
-
Mandatsreferenznr.:
-
-
-
-
IBAN:
-
-
-
-
Gläubiger-ID:
-
-
-
-
-
- - - -
-
Überweisung
-
-
-
Kontoinhaber:
-
-
-
-
IBAN:
-
-
-
-
BIC:
-
-
-
-
-
- - - -
-
Bemerkung zur Rechnung
-
-
-
Betreff:
-
-
-
-
Bemerkung:
-
-
-
-
-
- - - -
-
Wir übernehmen keine Haftung für die Richtigkeit der Daten.
- -
-
- - - -
-
-
-
Position
-
-
-
Freitext:
-
-
-
-
Objektkennung:
-
-
-
-
Schema der Objektkennung:
-
-
-
-
Nummer der Auftragsposition:
-
-
-
-
Kontierungshinweis:
-
-
-

Abrechnungszeitraum:

-
-
von:
-
-
-
-
bis:
-
-
-
-
-
-
Preiseinzelheiten
-
-
-
Menge
-
-
-
-
Einheit
-
-
-
-
Preis pro Einheit (netto)
-
-
-
-
Gesamtpreis (netto)
-
-
-
-
-
-
Rabatt (netto):
-
-
-
-
Listenpreis (netto):
-
-
-
-
Anzahl der Einheit:
-
-
-
-
Code der Maßeinheit:
-
-
-
-
Umsatzsteuer:
-
-
-
-
Umsatzsteuersatz in Prozent:
-
%
-
-
-
-
-
-
-
-
-
Nachlässe auf Ebene der Rechnungsposition
-
-
-
Grundbetrag (netto)
-
-
-
-
Prozentsatz
-
%
-
-
-
Nachlass (netto)
-
-
-
-
-
Grund des Nachlasses:
-
Code für den Nachlassgrund:
-
-
-
-
Zuschläge auf Ebene der Rechnungsposition
-
-
-
Grundbetrag (netto)
-
-
-
-
Prozentsatz
-
%
-
-
-
Zuschlag (netto)
-
-
-
-
-
Grund des Zuschlags:
-
Code für den Zuschlagsgrund:
-
-
-
-
-
-
-
-
Artikelinformationen
-
-
-
-
-
-
Bezeichnung:
-
-
-
-
Beschreibung:
-
-
-
-
Artikelnummer:
-
-
-
-
Artikelkennung des Käufers:
-
-
-

Eigenschaften des Artikels:

- -
-
-
-
-
-
-
Artikelkennung:
-
-
-
-
Schema der Artikelkennung:
-
-
-
-
Code der Artikelklassifizierung:
-
-
-
-
Kennung zur Bildung des Schemas:
-
-
-
-
Version zur Bildung des Schemas:
-
-
-
-
Code des Herkunftslandes:
-
-
-
-
-
-
-
-
-
-
- - - -
-
-
-
-
- - - -
-
Wir übernehmen keine Haftung für die Richtigkeit der Daten.
-
-
- -
- -
-
-
-
- -
- -
-
-
-
- -
- -
-
-
-
- - - -
-
Informationen zum Verkäufer
-
-
-
Abweichender Handelsname:
-
-
-
-
Bundesland:
-
-
-
-
Elektronische Adresse:
-
-
-
-
Schema der elektronischen Adresse:
-
-
-
-
Register-/Registriernummer:
-
-
-
-
Umsatzsteuer-ID:
-
-
-
-
Steuernummer:
-
-
-
-
Schema der Steuernummer:
-
-
-
-
Weitere rechtliche Informationen:
-
-
-
-
Code der Umsatzsteuerwährung:
-
-
-
-
-
- - - -
-
Steuervertreter des Verkäufers
-
-
-
Name:
-
-
-
-
Straße / Hausnummer:
-
-
-
-
Postfach:
-
-
-
-
Adresszusatz:
-
-
-
-
PLZ:
-
-
-
-
Ort:
-
-
-
-
Bundesland:
-
-
-
-
Ländercode:
-
-
-
-
Umsatzsteuer-ID:
-
-
-
-
-
- - - -
-
Informationen zum Käufer
-
-
-
Abweichender Handelsname:
-
-
-
-
Bundesland:
-
-
-
-
Elektronische Adresse:
-
-
-
-
Schema der elektronischen Adresse:
-
-
-
-
Register-/Registriernummer:
-
-
-
-
Schema der Register-/Registriernummer:
-
-
-
-
Umsatzsteuer-ID:
-
-
-
-
Abrechnungsdatum der Umsatzsteuer:
-
-
-
-
Code des Umsatzsteuer-Abrechnungsdatums:
-
-
-
-
Kontierungsinformation:
-
-
-
-
-
- - - -
-
Lieferinformationen
-
-
-
Kennung des Lieferorts:
-
-
-
-
Schema der Kennung:
-
-
-
-
Lieferdatum:
-
-
-
-
Name des Empfängers:
-
-
-
-
Straße / Hausnummer:
-
-
-
-
Postfach:
-
-
-
-
Adresszusatz:
-
-
-
-
PLZ:
-
-
-
-
Ort:
-
-
-
-
Bundesland:
-
-
-
-
Land:
-
-
-
-
-
- - - -
-
Informationen zum Vertrag
-
-
-
Vergabenummer:
-
-
-
-
Kennung der Empfangsbestätigung:
-
-
-
-
Kennung der Versandanzeige:
-
-
-
-
Prozesskennung:
-
-
-
-
Spezifikationskennung:
-
-
-
-
Objektkennung:
-
-
-
-
Schema der Objektkennung:
-
-
-
-
-
- - - -
-
Vom Verkäufer abweichender Zahlungsempfänger
-
-
-
Name:
-
-
-
-
Kennung:
-
-
-
-
Schema der Kennung:
-
-
-
-
Register-/Registriernummer:
-
-
-
-
Schema der Register-/Registriernummer:
-
-
-
-
-
- - - -
-
Wir übernehmen keine Haftung für die Richtigkeit der Daten.
-
-
-
-
Rechnungsbegründende Unterlagen
- -
-
-
-
-
- - - -
-
-
Kennung:
-
-
-
-
Beschreibung:
-
-
-
-
Verweis (z.B. Internetadresse):
-
-
-
-
Anhangsdokument:
-
- Öffnen -
- - -
-
-
Format des Anhangdokuments:
-
-
-
-
Name des Anhangsdokuments:
-
-
-
-
- - - -
-
-
-
-
Bearbeitungshistorie
- -
-
-
-
-
- - - -
-
-
Datum/Uhrzeit:
-
-
-
-
Betreff:
-
-
-
-
Text:
-
-
-
-
Details:
-
-
-
-
- -
From 560556fbd4f7a425ecdf5f89887e5c1f3fca204f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sat, 6 Jul 2019 13:52:32 +0200 Subject: [PATCH 29/82] [maven-release-plugin] prepare release mustang-1.7.2 --- pom.xml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 67a0bb2a..4c6a7b8e 100644 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,9 @@ - + 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.2-SNAPSHOT + 1.7.2 jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -14,7 +13,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - mustang-1.5.2 + mustang-1.7.2 @@ -203,8 +202,7 @@ 2.4.3 - + org.mustangproject.toecount.Toecount From a08a5ec344c7273590e69b5503a7c6a3d270d154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sat, 6 Jul 2019 13:52:39 +0200 Subject: [PATCH 30/82] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4c6a7b8e..ad1bfc0b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.2 + 1.7.3-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -13,7 +13,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - mustang-1.7.2 + mustang-1.5.2 From 97766c749463131ce26d3f6c41460ddaa7f61645 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sat, 6 Jul 2019 21:39:37 +0200 Subject: [PATCH 31/82] no message --- pom.xml | 2 +- .../java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index ad1bfc0b..ed9d55d5 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.3-SNAPSHOT + 1.7.2-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index c9004873..a33ea2e3 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -128,8 +128,9 @@ public class ZUGFeRDImporter { private void extractFiles(Map names) throws IOException { for (String alias : names.keySet()) { - String filename=names.get(alias).getFilename(); - + + PDComplexFileSpecification fileSpec = names.get(alias); + String filename=fileSpec.getFilename(); /** * currently (in the release candidate of version 1) only one attached file with * the name ZUGFeRD-invoice.xml is allowed @@ -137,7 +138,6 @@ public class ZUGFeRDImporter { if ((filename.equals("ZUGFeRD-invoice.xml") || (filename.equals("zugferd-invoice.xml")) || filename.equals("factur-x.xml"))) { //$NON-NLS-1$ containsMeta = true; - PDComplexFileSpecification fileSpec = names.get(filename); PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile(); // String embeddedFilename = filePath + filename; // File file = new File(filePath + filename); @@ -154,7 +154,6 @@ public class ZUGFeRDImporter { } if (filename.startsWith("additional_data")) { - PDComplexFileSpecification fileSpec = names.get(filename); PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile(); additionalXMLs.put(filename, embeddedFile.toByteArray()); From a7b26247d2796886779f247be416a23b61aedbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sat, 6 Jul 2019 21:40:21 +0200 Subject: [PATCH 32/82] [maven-release-plugin] prepare release mustang-1.7.2 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ed9d55d5..4c6a7b8e 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.2-SNAPSHOT + 1.7.2 jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -13,7 +13,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - mustang-1.5.2 + mustang-1.7.2 From 976d3813a3b55f814433dcf7ae225b55e786678d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sat, 6 Jul 2019 21:40:29 +0200 Subject: [PATCH 33/82] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4c6a7b8e..ad1bfc0b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.2 + 1.7.3-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -13,7 +13,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - mustang-1.7.2 + mustang-1.5.2 From 636829aed34c2aad0ca7b631946015c49d4087d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Mon, 8 Jul 2019 19:03:33 +0200 Subject: [PATCH 34/82] Bankleitzahl (german bank code) is invalid in the schema file and in the spec of ZF2 --- .../java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 331e2a96..40ccc6eb 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -412,8 +412,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " " + payment.getOwnBIC() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " " + payment.getOwnBLZ() //$NON-NLS-1$ - + "\n" //$NON-NLS-1$ // + " "+trans.getOwnBankName()+"\n" //$NON-NLS-1$ // //$NON-NLS-2$ + " \n" //$NON-NLS-1$ From 96522d3af42d9f3a8796154db6cecb61636f9102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Mon, 8 Jul 2019 19:11:43 +0200 Subject: [PATCH 35/82] release without german national bank code in zf2 --- History.md | 3 ++- pom.xml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/History.md b/History.md index 704cc024..1a50736f 100644 --- a/History.md +++ b/History.md @@ -1,7 +1,7 @@ 1.7.2 ===== -2019-07-06 +2019-07-08 Support BuyerReference (r+w), as well as SpecifiedLegalOrganization (w) and DefinedTradeContact (w) use dom4j to format output xml document @@ -9,6 +9,7 @@ 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 diff --git a/pom.xml b/pom.xml index ad1bfc0b..ed9d55d5 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.3-SNAPSHOT + 1.7.2-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs From d6c45c65eea7c63ffedcb0e003d8203f0ec4071c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Mon, 8 Jul 2019 19:12:29 +0200 Subject: [PATCH 36/82] [maven-release-plugin] prepare release mustang-1.7.2 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ed9d55d5..4c6a7b8e 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.2-SNAPSHOT + 1.7.2 jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -13,7 +13,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - mustang-1.5.2 + mustang-1.7.2 From b8163a407fcf08118850ffd501120dcc69c46e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Mon, 8 Jul 2019 19:14:20 +0200 Subject: [PATCH 37/82] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4c6a7b8e..ad1bfc0b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.2 + 1.7.3-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -13,7 +13,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - mustang-1.7.2 + mustang-1.5.2 From 94453bbd031d04a3c8777dfc6dcbbeafd84bfe48 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Mon, 8 Jul 2019 22:25:48 +0200 Subject: [PATCH 38/82] skip over BOM in XML input --- .../ZUGFeRD/ZUGFeRDImporter.java | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index a33ea2e3..be95f293 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -180,11 +180,40 @@ public class ZUGFeRDImporter { DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance(); xmlFact.setNamespaceAware(false); DocumentBuilder builder = xmlFact.newDocumentBuilder(); - Document doc = builder.parse(new ByteArrayInputStream(rawXML)); + ByteArrayInputStream is = new ByteArrayInputStream(rawXML); + is.skip(guessBOMSize(is)); + Document doc = builder.parse(is); //prettyPrint(doc); return doc; } + /** + * Skips over a BOM at the beginning of the given ByteArrayInputStream, if one exists. + * @param is the ByteArrayInputStream used + * @throws IOException + * @see Autodetection of Character Encodings + */ + 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) { if (!containsMeta) { throw new ZUGFeRDExportException("No suitable data/ZUGFeRD file could be found."); From 7e74739023f18590580e3ca56266075c3db679db Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Tue, 9 Jul 2019 21:29:08 +0200 Subject: [PATCH 39/82] updates for 2.0 compatibility (IncludedNote, SpecifiedTaxRegistration) --- .../ZUGFeRD/ZUGFeRD2PullProvider.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 40ccc6eb..e2f7f09d 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -214,9 +214,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); //$NON-NLS-1$ String senderReg = ""; if (trans.getOwnOrganisationFullPlaintextInfo() != null) { - senderReg = "" + "\n" + " \n" + senderReg = "" + "\n" + " \n" + trans.getOwnOrganisationFullPlaintextInfo() + " \n" - + "REG\n" + "\n"; + + "REG\n" + "\n"; } @@ -378,11 +378,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { + " " + trans.getRecipient().getStreet() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " " + trans.getRecipient().getLocation() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " " + trans.getRecipient().getCountry() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ + + " \n"; //$NON-NLS-1$ + if (trans.getRecipient().getVATID() != null) { + xml += " \n" //$NON-NLS-1$ + " " + trans.getRecipient().getVATID() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ + + " \n"; //$NON-NLS-1$ + } + xml += " \n" //$NON-NLS-1$ // + " \n" // + " 20130301\n" // + " 2013-471331\n" From d045073c78466b7a971003ec93977c8082515922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Wed, 10 Jul 2019 17:53:13 +0200 Subject: [PATCH 40/82] refer to (external) css and js file instead of embedding them --- src/main/resources/stylesheets/xrechnung-html.xsl | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/resources/stylesheets/xrechnung-html.xsl b/src/main/resources/stylesheets/xrechnung-html.xsl index 5e15f314..54a0de84 100644 --- a/src/main/resources/stylesheets/xrechnung-html.xsl +++ b/src/main/resources/stylesheets/xrechnung-html.xsl @@ -18,9 +18,7 @@ XRechnung - +
@@ -44,9 +42,7 @@ - + From fb53501c61d7873d43c2eea0df97dc6601d5cb0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Wed, 10 Jul 2019 18:41:06 +0200 Subject: [PATCH 41/82] zf1 visualization, recognition if file is zf1 or zf2 --- .../ZUGFeRD/ZUGFeRDVisualizer.java | 141 +++++++++++------- .../stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt | 2 +- 2 files changed, 87 insertions(+), 56 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java index 03b820b3..eb75f9dd 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDVisualizer.java @@ -21,7 +21,11 @@ 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; @@ -30,94 +34,121 @@ 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 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(); + // 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"))); + 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 { + 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(); - applySchematronXsl(new FileInputStream(xmlFilename), 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) { - // logging and exception handling should go here - } - 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(); + + 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) { - // TODO Auto-generated catch block - e.printStackTrace(); + 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) { - // TODO Auto-generated catch block - e1.printStackTrace(); + } + }).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 { + 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 applySchematronXsl2(final InputStream xmlFile, - final OutputStream HTMLOutstream) throws TransformerException { + 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)); } diff --git a/src/main/resources/stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt b/src/main/resources/stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt index 97f444fe..bf0b71e4 100644 --- a/src/main/resources/stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt +++ b/src/main/resources/stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt @@ -57,7 +57,7 @@ Kosten, Verluste bzw. Schäden hätte normalerweise vorhergesehen werden können - + From 020ca043b60295feaff5540cb2753d54168f742a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 14 Jul 2019 10:53:20 +0200 Subject: [PATCH 42/82] updated javadoc --- History.md | 3 + .../ZUGFeRD/IExporterFactory.java | 12 ++- .../ZUGFeRD/IZUGFeRDExportableContact.java | 4 +- .../ZUGFeRD/IZUGFeRDExportableProduct.java | 2 +- .../IZUGFeRDExportableTransaction.java | 4 +- .../org/mustangproject/ZUGFeRD/VATAmount.java | 5 +- .../ZUGFeRD/XMPSchemaZugferd.java | 7 +- .../ZUGFeRD/ZUGFeRDExporter.java | 85 +++++++++++++++---- .../ZUGFeRD/ZUGFeRDExporterFromA3Factory.java | 6 +- .../ZUGFeRD/ZUGFeRDImporter.java | 1 + .../org/mustangproject/toecount/Toecount.java | 15 ++-- 11 files changed, 106 insertions(+), 38 deletions(-) diff --git a/History.md b/History.md index 1a50736f..0a274709 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,6 @@ +- migration: testIndicator entfernen +- in ram:ExchangedDocument: ram:name entfernen +- updated javadoc 1.7.2 ===== diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IExporterFactory.java b/src/main/java/org/mustangproject/ZUGFeRD/IExporterFactory.java index 47c22cc6..6822d744 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IExporterFactory.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IExporterFactory.java @@ -22,6 +22,13 @@ import java.io.IOException; import java.io.InputStream; 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; /** @@ -29,6 +36,8 @@ public interface IExporterFactory { * metadata level, this will not e.g. convert graphics to JPG-2000) * * @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; @@ -37,7 +46,8 @@ public interface IExporterFactory { * metadata level, this will not e.g. convert graphics to JPG-2000) * * @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; diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableContact.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableContact.java index 7b7e1c89..6b154b67 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableContact.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableContact.java @@ -19,11 +19,11 @@ 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 * @version 1.2.0 - * @date 2014-05-10 + * dated 2014-05-10 */ diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java index d58a2588..ea41877f 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableProduct.java @@ -27,7 +27,7 @@ import java.math.BigDecimal; * * @author jstaerk * @version 1.2.0 - * @date 2014-05-10 + * dated 2014-05-10 */ public interface IZUGFeRDExportableProduct { diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java index 6addf89f..0de986c1 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java @@ -64,7 +64,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. - *

+ *

* 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 @@ -115,6 +115,8 @@ public interface IZUGFeRDExportableTransaction { /** * the creditors payment informations + * + * @return an array of IZUGFeRDTradeSettlementPayment */ IZUGFeRDTradeSettlementPayment[] getTradeSettlementPayment(); diff --git a/src/main/java/org/mustangproject/ZUGFeRD/VATAmount.java b/src/main/java/org/mustangproject/ZUGFeRD/VATAmount.java index 817595f6..3ba0acc1 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/VATAmount.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/VATAmount.java @@ -27,7 +27,7 @@ import java.math.BigDecimal; * * @author jstaerk * @version 1.2.0 - * @date 2015-10-29 + * dated 2015-10-29 */ public class VATAmount { @@ -61,6 +61,7 @@ public class VATAmount { /** * * @deprecated Use {@link #getCategoryCode() instead} + * @return String with category code */ @Deprecated public String getDocumentCode() { @@ -68,7 +69,7 @@ public class VATAmount { } /** - * + * @param documentCode as String * @deprecated Use {@link #setCategoryCode(String)} instead */ @Deprecated diff --git a/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaZugferd.java b/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaZugferd.java index 57cc5197..c2a4bde5 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaZugferd.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaZugferd.java @@ -31,8 +31,13 @@ import org.apache.xmpbox.schema.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 + * @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) { super(metadata, URN, prefix, "ZUGFeRD Schema"); diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java index 211a8397..af5dd4cc 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java @@ -195,15 +195,16 @@ public class ZUGFeRDExporter implements Closeable { /** * All files are PDF/A-3, setConformance refers to the level conformance. - *

+ * * PDF/A-3 has three conformance levels, called "A", "U" and "B". - *

+ *

* 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. * visually, unicode and structurally preservable and tagged PDF, i.e. useful * metainformation for blind people. - *

+ *

* 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 */ @@ -217,16 +218,17 @@ public class ZUGFeRDExporter implements Closeable { /** * All files are PDF/A-3, setConformance refers to the level conformance. - *

+ *

* PDF/A-3 has three conformance levels, called "A", "U" and "B". - *

+ *

* 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. * visually, unicode and structurally preservable and tagged PDF, i.e. useful * metainformation for blind people. - *

+ *

* Feel free to pass "A" as new level if you know what you are doing :-) * + * @param newLevel "A", "U" or "B" * @deprecated Use * {@link #setConformanceLevel(org.mustangproject.ZUGFeRD.PDFAConformanceLevel)} * instead @@ -251,27 +253,45 @@ public class ZUGFeRDExporter implements Closeable { 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 public void loadPDFA3(String filename) throws IOException { 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 { return new ZUGFeRDExporter(PDDocument.load(new File(filename))); } /** - * @deprecated Use the factory method {@link #createFromPDFA3(InputStream)} - * instead + * load from a pdf which is already A/3 from filestream + * @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 public void loadPDFA3(InputStream file) throws IOException { 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 { 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 * 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 @@ -291,7 +317,18 @@ public class ZUGFeRDExporter implements Closeable { 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 @@ -303,6 +340,7 @@ public class ZUGFeRDExporter implements Closeable { return doc.getDocumentCatalog(); } + private IExporterFactory createPDFA1Factory() { ZUGFeRDExporterFromA1Factory factory = new ZUGFeRDExporterFromA1Factory(); if (ignoreA1Errors) { @@ -325,6 +363,7 @@ public class ZUGFeRDExporter implements Closeable { * populate the XML. This parameter may be null, if so the XML data * should hav ebeen set via * setZUGFeRDXMLData(byte[] zugferdData) + * @throws IOException if anything is wrong with already loaded PDF */ public void PDFattachZugferdFile(IZUGFeRDExportableTransaction trans) throws IOException { prepareDocument(); @@ -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 { if (!documentPrepared) { 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 { if (!documentPrepared) { prepareDocument(); @@ -376,7 +426,7 @@ public class ZUGFeRDExporter implements Closeable { * @param description Human-readable description of the file content * @param subType type of the data e.g. could be "text/xml" - mime like * @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, String subType, byte[] data) throws IOException { @@ -446,6 +496,7 @@ public class ZUGFeRDExporter implements Closeable { * API or component. * * @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 { 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 * information to RDF * - * @param metadata + * @param metadata the PDFbox XMPMetadata object */ protected void addXMP(XMPMetadata metadata) { @@ -607,7 +658,7 @@ public class ZUGFeRDExporter implements Closeable { /** * the human author (use factory method instead) * - * @param creator + * @param creator the (human) name who created the PDF */ @Deprecated public void setCreator(String creator) { @@ -617,7 +668,7 @@ public class ZUGFeRDExporter implements Closeable { /** * the CreatorTool attribute for the PDF * - * @param creator + * @param creatorTool the application which created the PDF */ protected void setCreatorTool(String creatorTool) { this.creatorTool = creatorTool; @@ -626,7 +677,7 @@ public class ZUGFeRDExporter implements Closeable { /** * the authoring software (use factory method instead) * - * @param producer + * @param producer the authoring software */ @Deprecated public void setProducer(String producer) { diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3Factory.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3Factory.java index a0a5cb20..ffed7bb7 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3Factory.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3Factory.java @@ -173,14 +173,14 @@ public class ZUGFeRDExporterFromA3Factory implements IExporterFactory { /** * All files are PDF/A-3, setConformance refers to the level conformance. - *

+ *

* PDF/A-3 has three coformance levels, called "A", "U" and "B". - *

+ *

* 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. * visually, unicode and structurally preservable and tagged PDF, i.e. useful * metainformation for blind people. - *

+ *

* Feel free to pass "A" as new level if you know what you are doing :-) */ public IExporterFactory setConformanceLevel(PDFAConformanceLevel newLevel) { diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index be95f293..a9f1c9c2 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -378,6 +378,7 @@ public class ZUGFeRDImporter { /** * Returns the raw XML data as extracted from the ZUGFeRD PDF file. + * @return the raw ZUGFeRD XML data */ public byte[] getRawXML() { return rawXML; diff --git a/src/main/java/org/mustangproject/toecount/Toecount.java b/src/main/java/org/mustangproject/toecount/Toecount.java index f6f235a0..1cb1c7ce 100755 --- a/src/main/java/org/mustangproject/toecount/Toecount.java +++ b/src/main/java/org/mustangproject/toecount/Toecount.java @@ -162,16 +162,11 @@ public class Toecount { /** * Prompts the user for a input or output filename * - * @param the - * text the user is asked - * @param a - * default Filename - * @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 ensureFileNotExists - * will warn if file DOES exist (for output files) + * @param prompt the text the user is asked + * @param defaultFilename a default Filename + * @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 ensureFileNotExists will warn if file DOES exist (for output files) * @return String */ protected static String getFilenameFromUser(String prompt, String defaultFilename, String expectedExtension, From 24b27a9b516df3bf753119a31f0788c23b990396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Thu, 18 Jul 2019 11:08:57 +0200 Subject: [PATCH 43/82] added unit test for problematic cases also for zf2 --- .../mustangproject/ZUGFeRD/ZF2EdgeTest.java | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java diff --git a/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java b/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java new file mode 100644 index 00000000..21f9131f --- /dev/null +++ b/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java @@ -0,0 +1,212 @@ +/** ********************************************************************** + * + * 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-20140703_502blanko.pdf}, adds 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 importer test (which is probably redundant) + * --> as only Name Ascending is supported for Test Unit sequence, I renamed the Exporter Test test-Z-Export + */ + public void testEdgeExport() throws Exception { + + // 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(" Date: Sun, 21 Jul 2019 17:55:41 +0200 Subject: [PATCH 44/82] closes #104 --- History.md | 1 + .../java/org/mustangproject/toecount/Toecount.java | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/History.md b/History.md index 0a274709..9f3087f8 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ - migration: testIndicator entfernen - in ram:ExchangedDocument: ram:name entfernen - updated javadoc +- fixed #104 nullpointerex when specifying no parameter 1.7.2 ===== diff --git a/src/main/java/org/mustangproject/toecount/Toecount.java b/src/main/java/org/mustangproject/toecount/Toecount.java index 1cb1c7ce..dd3bea00 100755 --- a/src/main/java/org/mustangproject/toecount/Toecount.java +++ b/src/main/java/org/mustangproject/toecount/Toecount.java @@ -299,19 +299,19 @@ public class Toecount { } // Retrieve all options + String action = parser.getOptionValue(actionOption); String directoryName = parser.getOptionValue(dirnameOption); Boolean filesFromStdIn = parser.getOptionValue(filesFromStdInOption, Boolean.FALSE); - Boolean combineRequested = parser.getOptionValue(combineOption, Boolean.FALSE); - Boolean extractRequested = parser.getOptionValue(extractOption, Boolean.FALSE); - Boolean helpRequested = parser.getOptionValue(helpOption, Boolean.FALSE); - Boolean upgradeRequested = parser.getOptionValue(upgradeOption, Boolean.FALSE); + Boolean combineRequested = parser.getOptionValue(combineOption, Boolean.FALSE) || ((action!=null)&&(action.equals("combine"))); + Boolean extractRequested = parser.getOptionValue(extractOption, Boolean.FALSE) || ((action!=null)&&(action.equals("extract"))); + Boolean helpRequested = parser.getOptionValue(helpOption, Boolean.FALSE) || ((action!=null)&&(action.equals("help"))); + Boolean upgradeRequested = parser.getOptionValue(upgradeOption, Boolean.FALSE) || ((action!=null)&&(action.equals("upgrade"))); 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 sourceXMLName = parser.getOptionValue(sourceXmlOption); String outName = parser.getOptionValue(outOption); String format = parser.getOptionValue(formatOption); - String action = parser.getOptionValue(actionOption); String zugferdVersion = parser.getOptionValue(zugferdVersionOption); String zugferdProfile = parser.getOptionValue(zugferdProfileOption); @@ -327,7 +327,7 @@ public class Toecount { performConvert(sourceName, outName); } else if (upgradeRequested) { performUpgrade(sourceName, outName); - } else if (action.equals("visualize")) { + } else if ((action!=null)&&(action.equals("visualize"))) { performVisualization(sourceName, outName); } else { // no argument or argument unknown From df3b54bef2f75bc21ec28896f990d2a63a4e61f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 21 Jul 2019 20:13:23 +0200 Subject: [PATCH 45/82] work on #105 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ad1bfc0b..01a48584 100644 --- a/pom.xml +++ b/pom.xml @@ -277,7 +277,7 @@ org.codehaus.mojo jaxb2-maven-plugin - 2.3.1 + 2.5.0 xjc From 780d92575b70a762912deba1d52dd2e40c7e85ae Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Mon, 22 Jul 2019 10:42:38 +0200 Subject: [PATCH 46/82] iron out javadoc errors and warnings IntelliJ now succeeds in building javadoc --- .../MustangReaderWriterCustomXMLTest.java | 6 ++--- .../ZUGFeRD/MustangReaderWriterEdgeTest.java | 17 ++++++------- .../ZUGFeRD/MustangReaderWriterTest.java | 25 ++++++++----------- .../ZUGFeRD/ResourceUtilities.java | 10 +++++++- .../ZUGFeRD/VersionMigrationTest.java | 2 +- .../mustangproject/ZUGFeRD/ZF2EdgeTest.java | 11 ++++---- 6 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java index 42277aba..72f9285b 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java @@ -49,7 +49,7 @@ public class MustangReaderWriterCustomXMLTest extends TestCase { // //////// TESTS // ////////////////////////////////////////////////////////////////////////////////////////// - public void testCustomZF2Export() throws Exception { + public void testCustomZF2Export() { final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20171118_506custom.pdf"; // the writing part @@ -288,10 +288,10 @@ public class MustangReaderWriterCustomXMLTest extends TestCase { * ./src/test/MustangGnuaccountingBeispielRE-20140703_502blanko.pdf}, adds * 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 - * 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 */ - public void testCustomZF1Export() throws Exception { + public void testCustomZF1Export() { final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505custom.pdf"; // the writing part diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java index 74dee7e6..db00461a 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java @@ -170,13 +170,11 @@ public class MustangReaderWriterEdgeTest extends MustangReaderTestCase { /** * 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 - * - * @throws IOException */ - public void testAImport() throws IOException { + public void testAImport() { InputStream inputStream = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505.pdf"); 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, - * 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 importer test (which is probably redundant) - * --> as only Name Ascending is supported for Test Unit sequence, I renamed the Exporter Test test-Z-Export + * 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 importer test (which is probably redundant). + * 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"; // the writing part @@ -218,6 +215,8 @@ public class MustangReaderWriterEdgeTest extends MustangReaderTestCase { String theXML = new String(ze.getProvider().getXML()); assertTrue(theXML.contains(" as only Name Ascending is supported for Test Unit sequence, I - * renamed the this test-A-Export to run before testZExport - * - * @throws IOException + * 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 testAImport + * to run before testZExport */ - public void testAImport() throws IOException { + public void testAImport() { InputStream inputStream = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505.pdf"); ZUGFeRDImporter zi = new ZUGFeRDImporter(inputStream); @@ -206,7 +203,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { assertEquals(zi.getForeignReference(), "RE-20170509/505"); } - public void testForeignImport() throws IOException { + public void testForeignImport() { InputStream inputStream = this.getClass().getResourceAsStream("/zugferd_invoice.pdf"); ZUGFeRDImporter zi = new ZUGFeRDImporter(inputStream); @@ -343,10 +340,10 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { * ./src/test/MustangGnuaccountingBeispielRE-20140703_502blanko.pdf}, adds * 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 - * 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 */ - public void testZExport() throws Exception { + public void testZExport() { final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20171118_506new.pdf"; @@ -370,6 +367,8 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { // assertFalse(pdfContent.indexOf("zf") == -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) @@ -423,11 +422,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { assertEquals(zi.getForeignReference(), getNumber()); } - /** - * @throws Exception - * @Test(expected = IndexOutOfBoundsException.class) - */ - public void testExceptionOnPDF14() throws Exception { + public void testExceptionOnPDF14() { final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505new.pdf"; diff --git a/src/test/java/org/mustangproject/ZUGFeRD/ResourceUtilities.java b/src/test/java/org/mustangproject/ZUGFeRD/ResourceUtilities.java index 2a36e4ef..cf908e72 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/ResourceUtilities.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/ResourceUtilities.java @@ -34,6 +34,10 @@ public class ResourceUtilities { /** * 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 { 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 + * @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 { @@ -147,7 +155,7 @@ public class ResourceUtilities { /** * 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 * @return the String of the URI diff --git a/src/test/java/org/mustangproject/ZUGFeRD/VersionMigrationTest.java b/src/test/java/org/mustangproject/ZUGFeRD/VersionMigrationTest.java index ab628dcd..62e83b67 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/VersionMigrationTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/VersionMigrationTest.java @@ -41,7 +41,7 @@ import static org.junit.Assert.assertFalse; * will be migrated to src/test/resources/migration/output. * If there is a similar named file as test reference src/test/resources/migration/reference a test * will be triggered for every single file. - *

+ * * Note: Any 'ZUGFeRD1' will be exchanged to 'ZUGFeRD2' during migration and adequate reference will be searched for. */ @RunWith(Parameterized.class) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java b/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java index 21f9131f..c0c56af4 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java @@ -170,13 +170,10 @@ public class ZF2EdgeTest extends MustangReaderTestCase { // //////// TESTS ////////////////////////////////////////////////////////////////////////////////////////// /** - * The exporter test bases on @{code ./src/test/MustangGnuaccountingBeispielRE-20140703_502blanko.pdf}, adds 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 importer test (which is probably redundant) - * --> as only Name Ascending is supported for Test Unit sequence, I renamed the Exporter Test test-Z-Export + * 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() throws Exception { + public void testEdgeExport() { // the writing part @@ -194,6 +191,8 @@ public class ZF2EdgeTest extends MustangReaderTestCase { String theXML = new String(ze.getProvider().getXML()); assertTrue(theXML.contains(" Date: Mon, 22 Jul 2019 18:50:35 +0200 Subject: [PATCH 47/82] added dependencies for coretto 11 (windows build) --- pom.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pom.xml b/pom.xml index 01a48584..4ca4bb50 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,17 @@ jaxb-runtime 2.2.11 + + javax.xml.bind + jaxb-api + 2.2.11 + + + javax.activation + activation + 1.1 + + org.apache.pdfbox preflight From 04da31d37c4ecb3f1337f455d773cadaa1c846c0 Mon Sep 17 00:00:00 2001 From: Jochen Staerk Date: Mon, 22 Jul 2019 20:00:01 +0200 Subject: [PATCH 48/82] closes #23 --- History.md | 1 + .../ZUGFeRD/ZUGFeRD2PullProvider.java | 26 +++----- .../org/mustangproject/ZUGFeRD/BaseTest.java | 65 +++++++++++++++++++ 3 files changed, 76 insertions(+), 16 deletions(-) create mode 100644 src/test/java/org/mustangproject/ZUGFeRD/BaseTest.java diff --git a/History.md b/History.md index 9f3087f8..dc797fd2 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ - in ram:ExchangedDocument: ram:name entfernen - updated javadoc - fixed #104 nullpointerex when specifying no parameter +- closed #23 1.7.2 ===== diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index e2f7f09d..12b17673 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -77,7 +77,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { 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 * NumberFormat.getCurrencyInstance().format( 12345.6789 ); but that is locale @@ -92,16 +92,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { * 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 @@ -111,25 +101,29 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols(); otherSymbols.setDecimalSeparator('.'); - DecimalFormat dec = new DecimalFormat("0." + new String(repeat), otherSymbols); + String baseFormat="0"; + if (scale>0) { + baseFormat+="."; + } + DecimalFormat dec = new DecimalFormat(baseFormat + new String(repeat), otherSymbols); return dec.format(value); } private String vatFormat(BigDecimal value) { - return nDigitFormat(value, 2); + return ZUGFeRD2PullProvider.nDigitFormat(value, 2); } private String currencyFormat(BigDecimal value) { - return nDigitFormat(value, 2); + return ZUGFeRD2PullProvider.nDigitFormat(value, 2); } private String priceFormat(BigDecimal value) { - return nDigitFormat(value, 4); + return ZUGFeRD2PullProvider.nDigitFormat(value, 4); } private String quantityFormat(BigDecimal value) { - return nDigitFormat(value, 4); + return ZUGFeRD2PullProvider.nDigitFormat(value, 4); } @Override diff --git a/src/test/java/org/mustangproject/ZUGFeRD/BaseTest.java b/src/test/java/org/mustangproject/ZUGFeRD/BaseTest.java new file mode 100644 index 00000000..8d3152b6 --- /dev/null +++ b/src/test/java/org/mustangproject/ZUGFeRD/BaseTest.java @@ -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)); + } + +} From a10d9bdf3fa6cc91b5dafa6903f8d9fc1f063fb6 Mon Sep 17 00:00:00 2001 From: Jochen Staerk Date: Mon, 22 Jul 2019 20:10:06 +0200 Subject: [PATCH 49/82] ndigitformat was ment to return string --- .../ZUGFeRDTransactionModelConverter.java | 62 +++---------------- 1 file changed, 9 insertions(+), 53 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java index 206b5a2e..8e63ec71 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java @@ -843,70 +843,26 @@ class ZUGFeRDTransactionModelConverter { private BigDecimal vatFormat(BigDecimal value) { - return nDigitFormat(value, 2); - } + return value.setScale(2, BigDecimal.ROUND_HALF_UP); + } private BigDecimal currencyFormat(BigDecimal value) { - return nDigitFormat(value, 2); - } + return value.setScale(2, BigDecimal.ROUND_HALF_UP); + } private BigDecimal priceFormat(BigDecimal value) { - return nDigitFormat(value, 4); - } + return value.setScale(4, BigDecimal.ROUND_HALF_UP); + } private BigDecimal quantityFormat(BigDecimal value) { - return nDigitFormat(value, 4); - } - - - 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)); - - } + return value.setScale(4, BigDecimal.ROUND_HALF_UP); + } + /** * 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 From 2e5818f8e79bf1a9ac796263747b6ccad57c5c2e Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Mon, 22 Jul 2019 21:17:12 +0200 Subject: [PATCH 50/82] specify charset to avoid platform specific defaults --- .../ZUGFeRD/MustangReaderWriterCustomXMLTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java index 72f9285b..42c1a118 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java @@ -27,6 +27,7 @@ import org.junit.runners.MethodSorters; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class MustangReaderWriterCustomXMLTest extends TestCase { @@ -64,7 +65,7 @@ public class MustangReaderWriterCustomXMLTest extends TestCase { /* 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. * 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) + "\n" + + String ownZUGFeRDXML = new String(UTF8ByteOrderMark, StandardCharsets.UTF_8) + "\n" + "\n" + " \n" + " false\n" + From deac979877456dfc4422d20374f05b43de65c4f3 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Mon, 22 Jul 2019 21:27:47 +0200 Subject: [PATCH 51/82] use RoundingMode enumeration and locale-safe BigDecimal.toPlainString --- .../ZUGFeRD/ZUGFeRD2PullProvider.java | 16 ++-------------- .../ZUGFeRDTransactionModelConverter.java | 9 +++++---- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 12b17673..03db8e0c 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; +import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; @@ -93,20 +94,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { * end I decided to calculate myself and take eur+sparator+cents * */ - 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('.'); - String baseFormat="0"; - if (scale>0) { - baseFormat+="."; - } - DecimalFormat dec = new DecimalFormat(baseFormat + new String(repeat), otherSymbols); - return dec.format(value); + return value.setScale(scale, RoundingMode.HALF_UP).toPlainString(); } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java index 8e63ec71..456e38df 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java @@ -19,6 +19,7 @@ package org.mustangproject.ZUGFeRD; import java.math.BigDecimal; +import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; @@ -843,22 +844,22 @@ class ZUGFeRDTransactionModelConverter { private BigDecimal vatFormat(BigDecimal value) { - return value.setScale(2, BigDecimal.ROUND_HALF_UP); + return value.setScale(2, RoundingMode.HALF_UP); } private BigDecimal currencyFormat(BigDecimal value) { - return value.setScale(2, BigDecimal.ROUND_HALF_UP); + return value.setScale(2, RoundingMode.HALF_UP); } private BigDecimal priceFormat(BigDecimal value) { - return value.setScale(4, BigDecimal.ROUND_HALF_UP); + return value.setScale(4, RoundingMode.HALF_UP); } private BigDecimal quantityFormat(BigDecimal value) { - return value.setScale(4, BigDecimal.ROUND_HALF_UP); + return value.setScale(4, RoundingMode.HALF_UP); } From 5816929617cda65d656976bbbf8943326aaf423c Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Wed, 24 Jul 2019 15:24:35 +0200 Subject: [PATCH 52/82] make document name and globalID configurable by implementers --- .../ZUGFeRD/IZUGFeRDExportableContact.java | 18 ++++++++++++++++++ .../ZUGFeRD/IZUGFeRDExportableTransaction.java | 8 ++++++++ .../ZUGFeRDTransactionModelConverter.java | 8 +++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableContact.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableContact.java index 6b154b67..4704ab4f 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableContact.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableContact.java @@ -38,6 +38,24 @@ public interface IZUGFeRDExportableContact { 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 diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java index 0de986c1..03a93e7d 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java @@ -33,6 +33,14 @@ import java.util.Date; public interface IZUGFeRDExportableTransaction { + /** + * appears in /rsm:CrossIndustryDocument/rsm:HeaderExchangedDocument/ram:Name + * @return Name of document + */ + default String getDocumentName() { + return "RECHNUNG"; + } + /** * * diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java index 8e63ec71..ef65035c 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java @@ -149,7 +149,7 @@ class ZUGFeRDTransactionModelConverter { document.setTypeCode(documentCodeType); TextType name = xmlFactory.createTextType(); - name.setValue("RECHNUNG"); + name.setValue(trans.getDocumentName()); document.getName().add(name); if (trans.getOwnOrganisationFullPlaintextInfo() != null) { @@ -212,6 +212,12 @@ class ZUGFeRDTransactionModelConverter { buyerID.setValue(trans.getRecipient().getID()); 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(); buyerName.setValue(trans.getRecipient().getName()); From ce5af7b012ca2182c3d51ac6f54d136265bc5324 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Thu, 25 Jul 2019 16:55:28 +0200 Subject: [PATCH 53/82] complete profile options for v1 see "Das ZUGFeRD-Format_1p0", p. 98, lines 1982 ff. --- .../ZUGFeRD/model/DocumentContextParameterTypeConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/model/DocumentContextParameterTypeConstants.java b/src/main/java/org/mustangproject/ZUGFeRD/model/DocumentContextParameterTypeConstants.java index 57033f6d..d90eabd1 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/model/DocumentContextParameterTypeConstants.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/model/DocumentContextParameterTypeConstants.java @@ -19,7 +19,7 @@ package org.mustangproject.ZUGFeRD.model; 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 EXTENDED = "urn:ferd:CrossIndustryDocument:invoice:1p0:extended"; - // this does not look complete :-/ } From 0720751d350c3de96d438fb23ed8f30e0ca28f0f Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Thu, 25 Jul 2019 17:42:03 +0200 Subject: [PATCH 54/82] failing test case to check for correct v1 profile string --- .../ZUGFeRD/MustangReaderWriterTest.java | 47 ++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index 9b1f1f42..72d0f9b0 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -30,6 +30,7 @@ import org.apache.xmpbox.xml.DomXmpParser; import org.apache.xmpbox.xml.XmpParsingException; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; +import org.mustangproject.ZUGFeRD.model.DocumentContextParameterTypeConstants; import java.io.ByteArrayOutputStream; import java.io.File; @@ -349,7 +350,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { // the writing part 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)) { @@ -366,7 +367,49 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { // assertFalse(pdfContent.indexOf("EN 16931") == -1); // assertFalse(pdfContent.indexOf("zf") == -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) + ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_PDF); + + // Reading ZUGFeRD + assertEquals(zi.getAmount(), "571.04"); + assertEquals(zi.getBIC(), getTradeSettlementPayment()[0].getOwnBIC()); + assertEquals(zi.getReference(), getReferenceNumber()); + assertEquals(zi.getIBAN(), getTradeSettlementPayment()[0].getOwnIBAN()); + assertEquals(zi.getKTO(), getTradeSettlementPayment()[0].getOwnKto()); + assertEquals(zi.getHolder(), getOwnOrganisationName()); + 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.EXTENDED) >= 0); + assertTrue(pdfContent.indexOf(DocumentContextParameterTypeConstants.COMFORT) >= 0); + } catch (IOException e) { fail("IOException should not happen in testZExport"); } From b701bf25c8ca928be5e2fe77074c5c500e869463 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Thu, 25 Jul 2019 17:59:18 +0200 Subject: [PATCH 55/82] failing test case to check for correct v1 profile string --- .../ZUGFeRD/MustangReaderWriterTest.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index 72d0f9b0..94c9fa4f 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -407,24 +407,13 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { 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"); } - - // 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.getReference(), getReferenceNumber()); - assertEquals(zi.getIBAN(), getTradeSettlementPayment()[0].getOwnIBAN()); - assertEquals(zi.getKTO(), getTradeSettlementPayment()[0].getOwnKto()); - assertEquals(zi.getHolder(), getOwnOrganisationName()); - assertEquals(zi.getForeignReference(), getNumber()); } From 9681b4fa6d087efd88df5cd07b00fbea7dd1c6a3 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Thu, 25 Jul 2019 18:33:14 +0200 Subject: [PATCH 56/82] extend IProfileProvider to allow modification of profile --- .../ZUGFeRD/CustomXMLProvider.java | 12 +++++++++++- .../ZUGFeRD/IProfileProvider.java | 2 ++ .../ZUGFeRD/ZUGFeRD1PullProvider.java | 19 +++++++++++++++++-- .../ZUGFeRD/ZUGFeRD2PullProvider.java | 5 +++++ .../ZUGFeRD/ZUGFeRDExporter.java | 2 +- .../ZUGFeRDTransactionModelConverter.java | 8 +++++++- 6 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/CustomXMLProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/CustomXMLProvider.java index dfd8be88..6ac2c275 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/CustomXMLProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/CustomXMLProvider.java @@ -18,7 +18,7 @@ *********************************************************************** */ package org.mustangproject.ZUGFeRD; -public class CustomXMLProvider implements IXMLProvider { +public class CustomXMLProvider implements IXMLProvider, IProfileProvider { 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 + } } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java index adc695df..d4469edb 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java @@ -21,5 +21,7 @@ package org.mustangproject.ZUGFeRD; public interface IProfileProvider { public String getProfile(); + + public void setProfile(ZUGFeRDConformanceLevel level); } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java index 3c782866..f8278a32 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java @@ -19,6 +19,7 @@ package org.mustangproject.ZUGFeRD; import org.mustangproject.ZUGFeRD.model.CrossIndustryDocumentType; +import org.mustangproject.ZUGFeRD.model.DocumentContextParameterTypeConstants; import org.mustangproject.ZUGFeRD.model.ZFNamespacePrefixMapper; import javax.xml.bind.JAXBContext; @@ -27,13 +28,27 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import java.io.ByteArrayOutputStream; -public class ZUGFeRD1PullProvider implements IXMLProvider { +public class ZUGFeRD1PullProvider implements IXMLProvider, IProfileProvider { protected byte[] zugferdData; private Marshaller marshaller; 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) { JAXBElement jaxElement = - new ZUGFeRDTransactionModelConverter(trans).withTest(isTest).convertToModel(); + new ZUGFeRDTransactionModelConverter(trans).withTest(isTest).withProfile(getProfile()).convertToModel(); try { return marshalJaxToXMLString(jaxElement); diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 03db8e0c..7e12cdfe 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -71,6 +71,11 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { protected byte[] zugferdData; 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 diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java index af5dd4cc..f6796991 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java @@ -367,7 +367,7 @@ public class ZUGFeRDExporter implements Closeable { */ public void PDFattachZugferdFile(IZUGFeRDExportableTransaction trans) throws IOException { prepareDocument(); - + ((IProfileProvider) xmlProvider).setProfile(profile); xmlProvider.generateXML(trans); String filename = getFilenameForVersion(ZFVersion); PDFAttachGenericFile(doc, filename, "Alternative", diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java index 330619ee..6896dd2a 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java @@ -85,6 +85,7 @@ class ZUGFeRDTransactionModelConverter { private final Totals totals; private boolean isTest; private String currency = "EUR"; + private String profile; ZUGFeRDTransactionModelConverter(IZUGFeRDExportableTransaction trans) { @@ -114,7 +115,7 @@ class ZUGFeRDTransactionModelConverter { DocumentContextParameterType contextParameter = xmlFactory .createDocumentContextParameterType(); IDType idType = xmlFactory.createIDType(); - idType.setValue(DocumentContextParameterTypeConstants.EXTENDED); + idType.setValue(profile); contextParameter.setID(idType); context.getGuidelineSpecifiedDocumentContextParameter().add( contextParameter); @@ -955,6 +956,11 @@ class ZUGFeRDTransactionModelConverter { return this; } + public ZUGFeRDTransactionModelConverter withProfile(String profile) { + this.profile = profile; + return this; + } + private class LineCalc { private BigDecimal totalGross; From a7e9d72d3a3b0556a4bfc4977921ea9e2a0fee59 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Thu, 25 Jul 2019 20:35:11 +0200 Subject: [PATCH 57/82] make BuyerOrderReferencedDocument accessible --- .../IZUGFeRDExportableTransaction.java | 11 ++++ .../ZUGFeRDTransactionModelConverter.java | 55 ++++--------------- 2 files changed, 21 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java index 03a93e7d..3be30215 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java @@ -246,4 +246,15 @@ public interface IZUGFeRDExportableTransaction { 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; } } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java index 330619ee..fc20245c 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java @@ -31,51 +31,7 @@ import java.util.List; import javax.xml.bind.JAXBElement; -import org.mustangproject.ZUGFeRD.model.AmountType; -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; +import org.mustangproject.ZUGFeRD.model.*; class ZUGFeRDTransactionModelConverter { private static final SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); @@ -200,6 +156,15 @@ class ZUGFeRDTransactionModelConverter { tradeAgreement.setBuyerTradeParty(getBuyer()); 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; } From da01149a4126c35d3cb2cbe753008e556a3cbcc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Thu, 25 Jul 2019 22:29:25 +0200 Subject: [PATCH 58/82] have css and js file in resources and write to working dir on visualization --- History.md | 2 + pom.xml | 2 +- .../org/mustangproject/toecount/Toecount.java | 49 + src/main/resources/xrechnung-viewer.css | 917 ++++++++++++++++++ src/main/resources/xrechnung-viewer.js | 145 +++ 5 files changed, 1114 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/xrechnung-viewer.css create mode 100644 src/main/resources/xrechnung-viewer.js diff --git a/History.md b/History.md index dc797fd2..6fbb57bd 100644 --- a/History.md +++ b/History.md @@ -1,8 +1,10 @@ +- 1.8.0 feature: --action=visualize convert zugferd xml to html - migration: testIndicator entfernen - in ram:ExchangedDocument: ram:name entfernen - updated javadoc - fixed #104 nullpointerex when specifying no parameter - closed #23 +- #112 1.7.2 ===== diff --git a/pom.xml b/pom.xml index 4ca4bb50..c8783537 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.3-SNAPSHOT + 1.8.0-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs diff --git a/src/main/java/org/mustangproject/toecount/Toecount.java b/src/main/java/org/mustangproject/toecount/Toecount.java index dd3bea00..3d1ff415 100755 --- a/src/main/java/org/mustangproject/toecount/Toecount.java +++ b/src/main/java/org/mustangproject/toecount/Toecount.java @@ -31,9 +31,13 @@ import javax.xml.transform.TransformerException; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; 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.Path; import java.nio.file.Paths; @@ -82,6 +86,7 @@ public class Toecount { System.out.println("Mustangproject.org " + org.mustangproject.ZUGFeRD.Version.VERSION + " \r\n" + "A Apache Public License library and command line tool for statistics on PDF invoices with\r\n" + "ZUGFeRD Metadata (http://www.zugferd.org)\r\n" + "\r\n" + getUsage() + "\r\n" + + "* --action=visualize to convert XML to HTML or \\r\\n" + "* Count operations\r\n" + "\t-d, --directory\tcount ZUGFeRD files in directory to be scanned\r\n" + "\t\tIf it is a directory, it will recurse.\r\n" + "\t-l, --listfromstdin\tcount ZUGFeRD files from a list of linefeed separated files on runtime.\r\n" @@ -381,7 +386,51 @@ public class Toecount { } System.out.println("Written to " + outName); + try { + ExportResource("/xrechnung-viewer.css"); + ExportResource("/xrechnung-viewer.js"); + + System.out.println("xrechnung-viewer.css and xrechnung-viewer.js written as well (to local working dir)"); + } catch (Exception e) { + Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); + } + + } + + /** + * Export a resource embedded into a Jar file to the local file path. + * + * @param resourceName ie.: "/SmartLibrary.dll" + * @return The path to the exported resource + * @throws Exception + */ + static public String ExportResource(String resourceName) throws Exception { + InputStream stream = null; + OutputStream resStreamOut = null; + String jarFolder; + try { + stream = Toecount.class.getResourceAsStream(resourceName);//note that each / is a directory down in the "jar tree" been the jar the root of the tree + if(stream == null) { + throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file."); + } + + int readBytes; + byte[] buffer = new byte[4096]; + jarFolder = System.getProperty("user.dir"); + resStreamOut = new FileOutputStream(jarFolder + resourceName); + while ((readBytes = stream.read(buffer)) > 0) { + resStreamOut.write(buffer, 0, readBytes); + } + } catch (Exception ex) { + throw ex; + } finally { + stream.close(); + resStreamOut.close(); + } + + return jarFolder + resourceName; + } private static void performUpgrade(String xmlName, String outName) throws IOException, TransformerException { diff --git a/src/main/resources/xrechnung-viewer.css b/src/main/resources/xrechnung-viewer.css new file mode 100644 index 00000000..adea4c9b --- /dev/null +++ b/src/main/resources/xrechnung-viewer.css @@ -0,0 +1,917 @@ +/* Grundformatierung ********************************************/ + +*, +*:after, +*:before +{ + box-sizing: border-box; + -moz-box-sizing: border-box; +} + +.clear:after +{ + content: "."; + clear: both; + display: block; + visibility: hidden; + height: 0; +} + +html, +body +{ + height: 100%; + min-width: 320px; + margin: 0; + padding: 0; + color: #000; + font-size: 14px; +} + +body +{ + overflow-y: scroll; + background-color: rgba(4, 101, 161, 0.08); +} + +h4 +{ + color: inherit; + font-size: inherit; + margin-bottom: 0.5rem; +} + + +/* Grundaufbau *************************************************/ + +.menue +{ + position: relative; + z-index: 2000; + background-color: #000; + margin-bottom: 30px; +} + +.innen +{ + max-width: 1080px; + margin: 0 auto; + padding: 0 2%; +} + + + +/* Formatierungen *************************************************/ + +.color2 +{ + color: rgba(0, 0, 0, 0.6); +} + +.schwarz +{ + color: #555 !important; +} + +.normal +{ + font-weight: normal; +} + +.bold +{ + font-weight: bold; +} + +.abstandUnten +{ + margin-bottom: 5px; +} + +.abstandUntenKlein +{ + margin-bottom: 10px; +} + +.noPaddingTop +{ + padding-top: 0 !important; +} + +.ausrichtungRechts +{ + text-align: right; +} + + + + +/* Menü ********************************************************/ + +button +{ + position: relative; + font-family: serif; + padding-top: 15px; + padding-left: 0; + padding-right: 0; + margin-right: 2%; +} + +.btnAktiv +{ + font-size: 22px; + color: #ffb619; + height: 50px; + outline: none; + border: none; + background: none; +} + +.btnAktiv:after +{ + content: ""; + display: block; + position: absolute; + top: 50px; + left: 50%; + z-index: 10; + font-size: 0; + line-height: 0; + height: 0; + padding: 0; + margin: 0; + transform: translateX(-50%); + border: 15px solid #000; + border-right-color: transparent; + border-bottom-color: transparent; + border-left-color: transparent; +} + +.btnInaktiv, +.tab +{ + font-size: 22px; + color: #fff; + height: 50px; + z-index: 0; + outline: none; + border: none; + background: none; + transition: color 0.3s ease; +} + +.btnInaktiv:hover, +.tab:hover +{ + color: #ffb619; + cursor: pointer; +} + +.divHide +{ + display: none; +} + +/* Content *********************************************************************/ + +.inhalt +{ + font-family: sans-serif; + margin-bottom: 30px; +} + +.haftungausschluss +{ + color: #000; + text-align: center; + padding: 7px; + margin-bottom: 30px; + width: 100%; + border: 1px solid #ffb619; + background-color: #fff; +} + +.box +{ + position: relative; + display: table-cell; + padding: 0; + border: 1px solid rgba(4, 101, 161, 0.2); + background-color: #fff; +} + +.subBox +{ + border-top: none; + width: 50%; +} + +.subBox:last-child +{ + border-left: none; +} + +.first > .boxzeile > .subBox +{ + border-top: 1px solid rgba(4, 101, 161, 0.2) !important; +} + +.boxtitel +{ + display: inline-block; + background-color: #0465A1; + padding: 7px 10px; + color: #fff; + font-weight: bold; +} + +.boxBorderTop +{ + border-top: none; +} + +.boxBorderLeft +{ + border-left: none; +} + +.boxtitelSub +{ + color: #000; + background-color: rgba(4, 101, 161, 0.1); + border-right: 1px solid rgba(4, 101, 161, 0.2); + border-bottom: 1px solid rgba(4, 101, 161, 0.2); +} + +.boxinhalt +{ + padding: 15px 20px; +} + +.boxtabelle +{ + display: table; + width: 100%; +} + +.borderSpacing +{ + border-spacing: 0 5px; +} + +.boxabstandtop +{ + margin-top: 30px; +} + +.boxzeile +{ + display: table-row; +} + +.boxzeile .box:last-child +{ + margin-bottom: 0; +} + +.boxdaten +{ + display: table-cell; + padding: 5px 0; + vertical-align: middle; + height: 38px; + /* + -ms-word-break: break-all; + word-break: break-all; + word-break: break-word; + -webkit-hyphens: auto; + -moz-hyphens: auto; + hyphens: auto; +*/ +} + +.boxdaten.wert +{ + padding: 5px 10px; +} + +.boxcell +{ + display: table-cell; +} + +.boxdatenBlock +{ + display: block; + padding: 3px 0; + /* + -ms-word-break: break-all; + word-break: break-all; + word-break: break-word; + -webkit-hyphens: auto; + -moz-hyphens: auto; + hyphens: auto; +*/ +} + +.noBreak +{ + -ms-word-break: keep-all; + word-break: keep-all; + word-break: keep-all; + -webkit-hyphens: none; + -moz-hyphens: none; + hyphens: none; +} + +.boxabstand +{ + display: table-cell; + width: 30px; +} + +.legende +{ + color: rgba(0, 0, 0, 0.6); + width: 170px; + font-size: 13px; + line-height: 16px; + padding-right: 5px; +} + +.wert +{ + background-color: rgba(4, 101, 161, 0.03); +} + +.boxtabelleEinspaltig +{ + width: 49%; +} + +.boxtabelleZweispaltig, +.boxtabelleDreispaltig +{ + width: 100%; +} + +.box5050 +{ + width: 50%; +} + +.boxEinspaltig +{ + width: 100%; +} + +.boxZweispaltig +{ + width: 48.5%; +} + +.boxSpalte1 { + width: 50%; +} + +.boxSpalte2 { + width: 50%; + padding-left: 20px; +} + +.paddingLeft { + padding-left: 0.1em; +} + +.noPadding { + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.rechnungsZeile +{ + display: table-row; +} + +.rechnungsZeile .boxdaten +{ + height: auto; +} + +.rechnungSp1 +{ + width: 65%; + font-size: 16px; +} + +.rechnungSp2 +{ + width: 10%; +} + +.rechnungSp3 +{ + width: 25%; + font-size: 16px; + text-align: right; +} + +.detailSp1, +.detailSp2 +{ + width: 50%; +} + +.detailSp2 +{ + text-align: right; +} + +.line1Bottom +{ + border-bottom: 1px solid #000; +} + +.line1BottomLight +{ + padding-bottom: 5px; + border-bottom: 1px solid #f0f0f0; + margin-bottom: 5px; +} + +.line2Bottom +{ + border-bottom: 2px solid #000; +} + +.paddingTop +{ + padding-top: 10px; +} + +.paddingBottom +{ + padding-bottom: 10px; +} + +.grund +{ + font-size: 16px; + display: block; + width: 100%; + padding: 0 20px 15px 20px; +} + +.grundDetail +{ + display: block; + width: 100%; + padding: 0 20px 15px 20px; +} + +/* Übersichtformatierungen */ +#uebersichtLastschrift.box, +#uebersichtUeberweisung.box +{ + border-top: none; +} + +#uebersichtUeberweisung.box +{ + border-left: none; +} + + +/* Formatierungen Detailseite */ + +.detailsSpalte1, +.detailsSpalte2 +{ + width: 30%; + float: left; + font-size: 90%; + line-height: 115%; + margin-right: 5%; +} + +.detailsSpalte3 +{ + width: 30%; + float: left; + font-size: 90%; + line-height: 115%; +} + +.detailsSpalte1 .legende, +.detailsSpalte2 .legende, +.detailsSpalte3 .legende +{ + width: 145px; +} + +.titelPosition +{ + font-size: 17px; + font-weight: bold; +} + + +/* Laufzettelformatierungen */ +#laufzettelHistorie .boxtabelle:not(:nth-child(2)) +{ + border-top: 1px solid rgba(4, 101, 161, 0.2); + padding-top: 10px; + margin-top: 10px; +} + + + + + +/* 1023px und kleiner ************************************************/ + +@media screen and (max-width : 1023px) { + + .box + { + display: block; + width: 100%; + margin-bottom: 20px; + } + + .boxabstandtop + { + margin-top: 15px; + } + + .subBox:first-child + { + margin-bottom: 0 !important; + } + + .subBox:last-child + { + border-left: 1px solid rgba(4, 101, 161, 0.2); + } + + .first > .boxzeile > .subBox + { + border-top: none !important; + } + + .first > .boxzeile > .subBox:first-child + { + border-top: 1px solid rgba(4, 101, 161, 0.2) !important; + } + + .first > .boxzeile + { + margin-bottom: 0; + } + + #uebersichtUeberweisung.box + { + border-left: 1px solid rgba(4, 101, 161, 0.2); + } + + #uebersichtLastschrift.box + { + margin-bottom: 0; + } + + .boxzeile + { + display: block; + margin-bottom: 5px; + } + + .boxzeile:after + { + visibility: hidden; + display: block; + font-size: 0; + content: " "; + clear: both; + height: 0; + } + + #details > .boxtabelle > .boxzeile + { + margin-bottom: 0px; + } + + .boxcell + { + display: block; + } + + .boxcell:last-child + { + margin-top: 20px; + } + + .boxZweispaltig + { + width: 100%; + } + + .legende + { + display: block; + float: left; + width: 170px; + padding: 5px 0; + height: auto; + } + + .wert + { + display: block; + float: left; + width: calc(100% - 170px); + padding: 11px 10px !important; + line-height: 1.3; + min-height: 38px; + height: auto; + } + + .boxdaten .legende + { + height: auto; + } + + .rechnungsZeile .boxdaten + { + padding: 5px 0; + } + + .boxabstand + { + display: none; + } + + .boxtabelleEinspaltig { + width: 100%; + } + + .boxSpalte1 { + display: block; + width: auto; + } + + .boxSpalte2 { + display: block; + width: auto; + padding-left: 0px; + margin-top: 1.2rem; + } + + .detailsSpalte1, + .detailsSpalte2, + .detailsSpalte3 + { + width: 100%; + float: none; + padding-right: 0px; + } + + .detailsSpalte2, + .detailsSpalte3 + { + margin-top: 15px; + } + + .detailsSpalte2, + .detailsSpalte3 + { + margin-top: 10px; + } + + .tableNumberAlignRight + { + display: block; + width: 130px; + text-align: right; + } +} + + + +/* 800px und kleiner ************************************************/ + +@media screen and (max-width : 800px) { + + button + { + padding-top: 10px; + } + + .btnAktiv, + .btnInaktiv, + .tab + { + font-size: 20px; + height: 40px; + } + + .btnAktiv:after + { + top: 40px; + } + + .rechnungSp1 + { + width: 55%; + font-size: 15px; + } + + .rechnungSp2 + { + width: 10%; + } + + .rechnungSp3 + { + width: 35%; + text-align: right; + font-size: 15px; + } + + .grund + { + font-size: 15px; + } +} + +/* 450px und kleiner ************************************************/ + +@media screen and (max-width : 450px) +{ + + html, + body + { + font-size: 12px; + } + + .menue + { + margin-bottom: 20px; + } + + button + { + padding-top: 5px; + } + + .btnAktiv, + .btnInaktiv, + .tab + { + font-size: 17px; + height: 35px; + } + + .btnAktiv:after + { + top: 35px; + } + + .legende + { + font-size: 12px; + width: 100%; + } + + .wert + { + font-size: 12px; + line-height: 1.3; + width: 100%; + margin-bottom: 10px + } + + .boxzeile + { + margin-bottom: 0px + } + + .boxdaten + { + height: auto; + } + + .haftungausschluss + { + margin-bottom: 20px; + } + + .boxinhalt + { + margin-top: 0px; + } + + .boxabstandtop + { + margin-top: 20px; + } + + .boxtitel + { + padding: 7px 8px; + } + + .box + { + margin-bottom: 10px; + padding: 0; + } + + .boxabstandtop + { + margin-top: 10px; + } + + .boxdaten, + .boxdatenBlock + { + padding: 2px 0; + } + + .rechnungSp1 + { + width: 50%; + font-size: inherit; + } + + .rechnungSp2 + { + width: 15%; + } + + .rechnungSp3 + { + width: 35%; + font-size: inherit; + text-align: right; + } + + .grund + { + font-size: inherit; + } + + .titelPosition + { + font-size: 15px; + } + + .abstandUnten + { + margin-bottom: 5px; + } + + .detailsSpalte1, + .detailsSpalte2, + .detailsSpalte3 + { + font-size: inherit; + line-height: inherit; + } +} + +/* 380px und kleiner ************************************************/ + +@media screen and (max-width : 380px) { + + html, + body + { + font-size: 11px; + line-height: 100%; + } + + .btnAktiv, + .btnInaktiv, + .tab + { + font-size: 15px; + } + + .boxdaten +.boxdatenBlock + { + padding: 2px 0; + } + + .boxinhalt + { + margin-top: 0px; + } + + .boxtitel + { + padding: 5px 7px; + } +} diff --git a/src/main/resources/xrechnung-viewer.js b/src/main/resources/xrechnung-viewer.js new file mode 100644 index 00000000..2d547b86 --- /dev/null +++ b/src/main/resources/xrechnung-viewer.js @@ -0,0 +1,145 @@ + +/* Tab-Container aufbauen **************************************************/ + +var a = new Array("uebersicht", "details", "zusaetze", "anlagen", "laufzettel"); +var b = new Array("menueUebersicht", "menueDetails", "menueZusaetze", "menueAnlagen", "menueLaufzettel"); + +function show(e) { + var i = 0; + var j = 1; + for (var t = 0; t < b.length; t++) { + if (b[t] === e.id) { + i = t; + if (i > 0) { + j = 0; + } else { + j = i + 1; + } + break; + } + } + e.setAttribute("class", "btnAktiv"); + for (var k = 0; k < b.length; k++) { + if (k === i && (document.getElementById(a[k]) != null)) { + document.getElementById(a[k]).style.display = "block"; + if (i === j) + j = i + 1; + } else { + if (document.getElementById(a[k]) != null) { + document.getElementById(a[j]).style.display = "none"; + document.getElementById(b[j]).setAttribute("class", "btnInaktiv"); + j += 1; + } + } + } +} +window.onload = function () { + document.getElementById(b[0]).setAttribute("class", "btnAktiv"); +} + +/* Eingebettete Binaerdaten runterladen ************************************/ + + +function base64_to_binary (data) { + var chars = atob(data); + var bytes = new Array(chars.length); + for (var i = 0; i < chars.length; i++) { + bytes[i] = chars.charCodeAt(i); + } + return new Uint8Array(bytes); +} + +function downloadData (element_id) { + var data_element = document.getElementById(element_id); + var mimetype = data_element.getAttribute('mimeType'); + var filename = data_element.getAttribute('filename'); + var text = data_element.innerHTML; + var binary = base64_to_binary(text); + var blob = new Blob([binary], { + type: mimetype, size: binary.length + }); + + if (window.navigator && window.navigator.msSaveOrOpenBlob) { + // IE + window.navigator.msSaveOrOpenBlob(blob, filename); + } else { + // Non-IE + var url = window.URL.createObjectURL(blob); + window.open(url); + } +} + + +/* Polyfill IE atob/btoa ************************************/ + +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], function () { + factory(root); + }); + } else factory(root); + // node.js has always supported base64 conversions, while browsers that support + // web workers support base64 too, but you may never know. +})(typeof exports !== "undefined" ? exports: this, function (root) { + if (root.atob) { + // Some browsers' implementation of atob doesn't support whitespaces + // in the encoded string (notably, IE). This wraps the native atob + // in a function that strips the whitespaces. + // The original function can be retrieved in atob.original + try { + root.atob(" "); + } + catch (e) { + root.atob = (function (atob) { + var func = function (string) { + return atob(String(string).replace(/[\t\n\f\r ]+/g, "")); + }; + func.original = atob; + return func; + })(root.atob); + } + return; + } + + // base64 character set, plus padding character (=) + var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", + // Regular expression to check formal correctness of base64 encoded strings + b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/; + + root.btoa = function (string) { + string = String(string); + var bitmap, a, b, c, + result = "", i = 0, + rest = string.length % 3; // To determine the final padding + + for (; i < string.length;) { + if ((a = string.charCodeAt(i++)) > 255 || (b = string.charCodeAt(i++)) > 255 || (c = string.charCodeAt(i++)) > 255) + throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range."); + + bitmap = (a << 16) | (b << 8) | c; + result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) + b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63); + } + + // If there's need of padding, replace the last 'A's with equal signs + return rest ? result.slice(0, rest - 3) + "===".substring(rest): result; + }; + + root.atob = function (string) { + // atob can work with strings with whitespaces, even inside the encoded part, + // but only \t, \n, \f, \r and ' ', which can be stripped. + string = String(string).replace(/[\t\n\f\r ]+/g, ""); + if (! b64re.test(string)) + throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded."); + + // Adding the padding if missing, for semplicity + string += "==".slice(2 - (string.length & 3)); + var bitmap, result = "", r1, r2, i = 0; + for (; i < string.length;) { + bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12 | (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++))); + + result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255): r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255): String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255); + } + return result; + }; +}); \ No newline at end of file From f9f018e895dedd9e805e0049fa33463900a879de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Thu, 25 Jul 2019 22:49:49 +0200 Subject: [PATCH 59/82] removed visualization, it remains in v1.8.0 branch but master aims at 1.7.3 since I might want to try to add unit tests and some documentation for the new feature --- History.md | 3 +- pom.xml | 2 +- .../org/mustangproject/toecount/Toecount.java | 88 - src/main/resources/stylesheets/cii-xr.xsl | 2202 ----------------- .../resources/stylesheets/xrechnung-html.xsl | 1184 --------- src/main/resources/xrechnung-viewer.css | 917 ------- src/main/resources/xrechnung-viewer.js | 145 -- xrechnung-viewer.css | 917 ------- xrechnung-viewer.js | 145 -- 9 files changed, 3 insertions(+), 5600 deletions(-) delete mode 100644 src/main/resources/stylesheets/cii-xr.xsl delete mode 100644 src/main/resources/stylesheets/xrechnung-html.xsl delete mode 100644 src/main/resources/xrechnung-viewer.css delete mode 100644 src/main/resources/xrechnung-viewer.js delete mode 100644 xrechnung-viewer.css delete mode 100644 xrechnung-viewer.js diff --git a/History.md b/History.md index 6fbb57bd..f4b57df7 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,7 @@ -- 1.8.0 feature: --action=visualize convert zugferd xml to html +todo - migration: testIndicator entfernen - in ram:ExchangedDocument: ram:name entfernen +done - updated javadoc - fixed #104 nullpointerex when specifying no parameter - closed #23 diff --git a/pom.xml b/pom.xml index c8783537..4ca4bb50 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.8.0-SNAPSHOT + 1.7.3-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs diff --git a/src/main/java/org/mustangproject/toecount/Toecount.java b/src/main/java/org/mustangproject/toecount/Toecount.java index 3d1ff415..84edf28b 100755 --- a/src/main/java/org/mustangproject/toecount/Toecount.java +++ b/src/main/java/org/mustangproject/toecount/Toecount.java @@ -86,7 +86,6 @@ public class Toecount { System.out.println("Mustangproject.org " + org.mustangproject.ZUGFeRD.Version.VERSION + " \r\n" + "A Apache Public License library and command line tool for statistics on PDF invoices with\r\n" + "ZUGFeRD Metadata (http://www.zugferd.org)\r\n" + "\r\n" + getUsage() + "\r\n" - + "* --action=visualize to convert XML to HTML or \\r\\n" + "* Count operations\r\n" + "\t-d, --directory\tcount ZUGFeRD files in directory to be scanned\r\n" + "\t\tIf it is a directory, it will recurse.\r\n" + "\t-l, --listfromstdin\tcount ZUGFeRD files from a list of linefeed separated files on runtime.\r\n" @@ -332,8 +331,6 @@ public class Toecount { performConvert(sourceName, outName); } else if (upgradeRequested) { performUpgrade(sourceName, outName); - } else if ((action!=null)&&(action.equals("visualize"))) { - performVisualization(sourceName, outName); } else { // no argument or argument unknown printUsage(); @@ -347,91 +344,6 @@ public class Toecount { } - private static void performVisualization(String sourceName, String outName) { - // Get params from user if not already defined - if (sourceName == null) { - sourceName = getFilenameFromUser("ZUGFeRD XML source", "zugferd-invoice.xml", "xml", true, false); - } else { - System.out.println("ZUGFeRD XML source set to " + sourceName); - } - if (outName == null) { - outName = getFilenameFromUser("ZUGFeRD 2.0 XML target", "factur-x.html", "html", false, true); - } else { - System.out.println("ZUGFeRD 1.0 XML source set to " + outName); - } - - // Verify params - try { - ensureFileExists(sourceName); - ensureFileNotExists(outName); - - // stylesheets/ZUGFeRD_1p0_c1p0_s1p0.xslt - } catch (IOException e) { - Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); - } - - ZUGFeRDVisualizer zvi = new ZUGFeRDVisualizer(); - String xml = null; - try { - xml = zvi.visualize(sourceName); - Files.write(Paths.get(outName), xml.getBytes()); - } catch (FileNotFoundException e) { - Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); - } catch (UnsupportedEncodingException e) { - Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); - } catch (TransformerException e) { - Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); - } catch (IOException e) { - Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); - } - System.out.println("Written to " + outName); - - try { - ExportResource("/xrechnung-viewer.css"); - ExportResource("/xrechnung-viewer.js"); - - System.out.println("xrechnung-viewer.css and xrechnung-viewer.js written as well (to local working dir)"); - } catch (Exception e) { - Logger.getLogger(Toecount.class.getName()).log(Level.SEVERE, null, e); - } - - - } - - /** - * Export a resource embedded into a Jar file to the local file path. - * - * @param resourceName ie.: "/SmartLibrary.dll" - * @return The path to the exported resource - * @throws Exception - */ - static public String ExportResource(String resourceName) throws Exception { - InputStream stream = null; - OutputStream resStreamOut = null; - String jarFolder; - try { - stream = Toecount.class.getResourceAsStream(resourceName);//note that each / is a directory down in the "jar tree" been the jar the root of the tree - if(stream == null) { - throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file."); - } - - int readBytes; - byte[] buffer = new byte[4096]; - jarFolder = System.getProperty("user.dir"); - resStreamOut = new FileOutputStream(jarFolder + resourceName); - while ((readBytes = stream.read(buffer)) > 0) { - resStreamOut.write(buffer, 0, readBytes); - } - } catch (Exception ex) { - throw ex; - } finally { - stream.close(); - resStreamOut.close(); - } - - return jarFolder + resourceName; - } - private static void performUpgrade(String xmlName, String outName) throws IOException, TransformerException { // Get params from user if not already defined diff --git a/src/main/resources/stylesheets/cii-xr.xsl b/src/main/resources/stylesheets/cii-xr.xsl deleted file mode 100644 index 5fca7b9d..00000000 --- a/src/main/resources/stylesheets/cii-xr.xsl +++ /dev/null @@ -1,2202 +0,0 @@ - - - - - - Author: KoSIT Bremen (kosit@finanzen.bremen.de) - Fassung vom: 2019-03-18+01:00 - Überführt eine zur EN 16931 konforme elektronische Rechnung in der konkreten Syntax UNCEFACT.CII.D16B in eine Instanz gemäß des Schemas für den Namensraum urn:ce.eu:en16931:2017:xoev-de:kosit:standard:xrechnung-1. - Das Skript setzt voraus, dass das zu verarbeitende Dokument valide bzgl. des XML Schemas und der Schematron-Regeln der Quelle ist. Für nicht valide Dokumente ist das Ergebnis nicht definiert. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ILLEGAL DATE FORMAT: <para>Mit diesem Datentyp wird ein kalendarisches Datum abgebildet, wie es in der ISO 8601 Spezifikation <quote>Calendar date complete representation</quote> beschrieben ist (siehe ISO 8601:2004, Abschnitt 5.2.1.1). Das Datum beinhaltet keine Zeitangabe. Das konkret zu verwendende Format ist abhängig von der genutzten Syntax.</para> -<para>Der Datentyp basiert auf dem Typ <quote>Date Time. Type</quote>, wie in ISO 15000-5:2014 Anhang B definiert.</para> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Liefert einen XPath-Pfad, welches $n eindeutig identifiziert. - - - - - - - - - - - Liefert einen XPath-Pfad, welches $n eindeutig identifiziert. - - - - - / - - - [ - - ] - - - - /@ - - - diff --git a/src/main/resources/stylesheets/xrechnung-html.xsl b/src/main/resources/stylesheets/xrechnung-html.xsl deleted file mode 100644 index 54a0de84..00000000 --- a/src/main/resources/stylesheets/xrechnung-html.xsl +++ /dev/null @@ -1,1184 +0,0 @@ - - - - - - - - - - - - - - - XRechnung - - - - - -

- -
-
- - - - - -
-
- - - -
- - - -
-
Wir übernehmen keine Haftung für die Richtigkeit der Daten.
-
-
- - - -
- - - -
-
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
-
- - -
-
- -
-
- - -
-
- -
-
- -
-
-
-
- - - -
-
Informationen zum Käufer
-
-
-
Leitweg-ID:
-
-
-
-
Name:
-
-
-
-
Straße / Hausnummer:
-
-
-
-
Postfach:
-
-
-
-
Adresszusatz:
-
-
-
-
PLZ:
-
-
-
-
Ort:
-
-
-
-
Land:
-
-
-
-
Kennung:
-
-
-
-
Schema der Kennung:
-
-
-
-
Name:
-
-
-
-
Telefon:
-
-
-
-
E-Mail-Adresse:
-
-
-
-
-
- - - -
-
Informationen zum Verkäufer
-
-
-
Firmenname:
-
-
-
-
Straße / Hausnummer:
-
-
-
-
Postfach:
-
-
-
-
Adresszusatz:
-
-
-
-
PLZ:
-
-
-
-
Ort:
-
-
-
-
Bundesland:
-
-
-
-
Ländercode:
-
-
-
-
Kennung:
-
-
-
-
Schema der Kennung:
-
-
-
-
Name:
-
-
-
-
Telefon:
-
-
-
-
E-Mail-Adresse:
-
-
-
-
-
- - - -
-
-
Rechnungsdaten
-
-
-
-
-
Rechnungsnummer:
-
-
-
-
Rechnungsdatum:
-
-
-
-
Rechnungsart:
-
-
-
-
Währung:
-
-
-
-

Abrechnungszeitraum:

-
-
-
von:
-
-
-
-
bis:
-
-
-
-
-
-
-
-
-
Projektnummer:
-
-
-
-
Vertragsnummer:
-
-
-
-
Bestellnummer:
-
-
-
-
Auftragsnummer:
-
-
-
-

Vorausgegangene Rechnungen:

- -
-
-
-
-
- - -
-
-
Rechnungsnummer:
-
-
-
-
Rechnungsdatum:
-
-
-
-
- - - -
-
-
Gesamtbeträge der Rechnung
-
-
-
Summe aller Positionen
-
netto
-
-
-
-
Summe Nachlässe
-
netto
-
-
-
-
Summe Zuschläge
-
netto
-
-
-
-
Gesamtsumme
-
netto
-
-
-
-
Summe Umsatzsteuer
-
-
-
-
-
Summe Umsatzsteuer in Abrechnungswährung
-
-
-
-
-
Gesamtsumme
-
brutto
-
-
-
-
Gezahlter Betrag
-
brutto
-
-
-
-
Rundungsbetrag
-
brutto
-
-
-
-
Fälliger Betrag
-
brutto
-
-
-
-
-
-
- - - -
-
-
Aufschlüsselung der Umsatzsteuer auf Ebene der Rechnung
-
-
-
Umsatzsteuerkategorie:
-
-
-
-
-
Gesamtsumme
-
netto
-
-
-
-
Umsatzsteuersatz
-
-
%
-
-
-
Umsatzsteuerbetrag
-
-
-
-
- -
-
Befreiungsgrund:
-
Kennung für den Befreiungsgrund:
-
-
-
-
- - - -
-
-
Nachlass auf Ebene der Rechnung
-
-
-
Umsatzsteuerkategorie des Nachlasses:
-
-
-
-
-
Grundbetrag
-
netto
-
-
-
-
Prozentsatz
-
-
%
-
-
-
Nachlass
-
netto
-
-
-
-
Umsatzsteuersatz des Nachlasses
-
-
-
-
-
-
Grund für den Nachlass:
-
Document level allowance reason code:
-
-
-
-
-
- - - -
-
-
Zuschlag auf Ebene der Rechnung
-
-
-
Umsatzsteuerkategorie des Zuschlages:
-
-
-
-
-
Grundbetrag
-
netto
-
-
-
-
Prozentsatz
-
-
%
-
-
-
Zuschlag
-
netto
-
-
-
-
Umsatzsteuersatz des Zuschlages
-
-
-
-
-
-
Grund für den Zuschlag:
-
Document level charge reason code:
-
-
-
-
-
- - - -
-
Zahlungsdaten
-
-
-
Skonto; weitere Zahlungsbedingungen:
-
-
-
-
Fälligkeitsdatum:
-
-
-
-
Code für das Zahlungsmittel:
-
-
-
-
Zahlungsmittel:
-
-
-
-
Verwendungszweck:
-
-
-
-
-
- - - -
-
Karteninformation
-
-
-
Kartennummer:
-
-
-
-
Karteninhaber:
-
-
-
-
-
- - - -
-
Lastschrift
-
-
-
Mandatsreferenznr.:
-
-
-
-
IBAN:
-
-
-
-
Gläubiger-ID:
-
-
-
-
-
- - - -
-
Überweisung
-
-
-
Kontoinhaber:
-
-
-
-
IBAN:
-
-
-
-
BIC:
-
-
-
-
-
- - - -
-
Bemerkung zur Rechnung
-
-
-
Betreff:
-
-
-
-
Bemerkung:
-
-
-
-
-
- - - -
-
Wir übernehmen keine Haftung für die Richtigkeit der Daten.
- -
-
- - - -
-
-
-
Position
-
-
-
Freitext:
-
-
-
-
Objektkennung:
-
-
-
-
Schema der Objektkennung:
-
-
-
-
Nummer der Auftragsposition:
-
-
-
-
Kontierungshinweis:
-
-
-

Abrechnungszeitraum:

-
-
von:
-
-
-
-
bis:
-
-
-
-
-
-
Preiseinzelheiten
-
-
-
Menge
-
-
-
-
Einheit
-
-
-
-
Preis pro Einheit (netto)
-
-
-
-
Gesamtpreis (netto)
-
-
-
-
-
-
Rabatt (netto):
-
-
-
-
Listenpreis (netto):
-
-
-
-
Anzahl der Einheit:
-
-
-
-
Code der Maßeinheit:
-
-
-
-
Umsatzsteuer:
-
-
-
-
Umsatzsteuersatz in Prozent:
-
%
-
-
-
-
-
-
-
-
-
Nachlässe auf Ebene der Rechnungsposition
-
-
-
Grundbetrag (netto)
-
-
-
-
Prozentsatz
-
%
-
-
-
Nachlass (netto)
-
-
-
-
-
Grund des Nachlasses:
-
Code für den Nachlassgrund:
-
-
-
-
Zuschläge auf Ebene der Rechnungsposition
-
-
-
Grundbetrag (netto)
-
-
-
-
Prozentsatz
-
%
-
-
-
Zuschlag (netto)
-
-
-
-
-
Grund des Zuschlags:
-
Code für den Zuschlagsgrund:
-
-
-
-
-
-
-
-
Artikelinformationen
-
-
-
-
-
-
Bezeichnung:
-
-
-
-
Beschreibung:
-
-
-
-
Artikelnummer:
-
-
-
-
Artikelkennung des Käufers:
-
-
-

Eigenschaften des Artikels:

- -
-
-
-
-
-
-
Artikelkennung:
-
-
-
-
Schema der Artikelkennung:
-
-
-
-
Code der Artikelklassifizierung:
-
-
-
-
Kennung zur Bildung des Schemas:
-
-
-
-
Version zur Bildung des Schemas:
-
-
-
-
Code des Herkunftslandes:
-
-
-
-
-
-
-
-
-
-
- - - -
-
-
-
-
- - - -
-
Wir übernehmen keine Haftung für die Richtigkeit der Daten.
-
-
- -
- -
-
-
-
- -
- -
-
-
-
- -
- -
-
-
-
- - - -
-
Informationen zum Verkäufer
-
-
-
Abweichender Handelsname:
-
-
-
-
Bundesland:
-
-
-
-
Elektronische Adresse:
-
-
-
-
Schema der elektronischen Adresse:
-
-
-
-
Register-/Registriernummer:
-
-
-
-
Umsatzsteuer-ID:
-
-
-
-
Steuernummer:
-
-
-
-
Schema der Steuernummer:
-
-
-
-
Weitere rechtliche Informationen:
-
-
-
-
Code der Umsatzsteuerwährung:
-
-
-
-
-
- - - -
-
Steuervertreter des Verkäufers
-
-
-
Name:
-
-
-
-
Straße / Hausnummer:
-
-
-
-
Postfach:
-
-
-
-
Adresszusatz:
-
-
-
-
PLZ:
-
-
-
-
Ort:
-
-
-
-
Bundesland:
-
-
-
-
Ländercode:
-
-
-
-
Umsatzsteuer-ID:
-
-
-
-
-
- - - -
-
Informationen zum Käufer
-
-
-
Abweichender Handelsname:
-
-
-
-
Bundesland:
-
-
-
-
Elektronische Adresse:
-
-
-
-
Schema der elektronischen Adresse:
-
-
-
-
Register-/Registriernummer:
-
-
-
-
Schema der Register-/Registriernummer:
-
-
-
-
Umsatzsteuer-ID:
-
-
-
-
Abrechnungsdatum der Umsatzsteuer:
-
-
-
-
Code des Umsatzsteuer-Abrechnungsdatums:
-
-
-
-
Kontierungsinformation:
-
-
-
-
-
- - - -
-
Lieferinformationen
-
-
-
Kennung des Lieferorts:
-
-
-
-
Schema der Kennung:
-
-
-
-
Lieferdatum:
-
-
-
-
Name des Empfängers:
-
-
-
-
Straße / Hausnummer:
-
-
-
-
Postfach:
-
-
-
-
Adresszusatz:
-
-
-
-
PLZ:
-
-
-
-
Ort:
-
-
-
-
Bundesland:
-
-
-
-
Land:
-
-
-
-
-
- - - -
-
Informationen zum Vertrag
-
-
-
Vergabenummer:
-
-
-
-
Kennung der Empfangsbestätigung:
-
-
-
-
Kennung der Versandanzeige:
-
-
-
-
Prozesskennung:
-
-
-
-
Spezifikationskennung:
-
-
-
-
Objektkennung:
-
-
-
-
Schema der Objektkennung:
-
-
-
-
-
- - - -
-
Vom Verkäufer abweichender Zahlungsempfänger
-
-
-
Name:
-
-
-
-
Kennung:
-
-
-
-
Schema der Kennung:
-
-
-
-
Register-/Registriernummer:
-
-
-
-
Schema der Register-/Registriernummer:
-
-
-
-
-
- - - -
-
Wir übernehmen keine Haftung für die Richtigkeit der Daten.
-
-
-
-
Rechnungsbegründende Unterlagen
- -
-
-
-
-
- - - -
-
-
Kennung:
-
-
-
-
Beschreibung:
-
-
-
-
Verweis (z.B. Internetadresse):
-
-
-
-
Anhangsdokument:
-
- Öffnen -
- - -
-
-
Format des Anhangdokuments:
-
-
-
-
Name des Anhangsdokuments:
-
-
-
-
- - - -
-
-
-
-
Bearbeitungshistorie
- -
-
-
-
-
- - - -
-
-
Datum/Uhrzeit:
-
-
-
-
Betreff:
-
-
-
-
Text:
-
-
-
-
Details:
-
-
-
-
- - diff --git a/src/main/resources/xrechnung-viewer.css b/src/main/resources/xrechnung-viewer.css deleted file mode 100644 index adea4c9b..00000000 --- a/src/main/resources/xrechnung-viewer.css +++ /dev/null @@ -1,917 +0,0 @@ -/* Grundformatierung ********************************************/ - -*, -*:after, -*:before -{ - box-sizing: border-box; - -moz-box-sizing: border-box; -} - -.clear:after -{ - content: "."; - clear: both; - display: block; - visibility: hidden; - height: 0; -} - -html, -body -{ - height: 100%; - min-width: 320px; - margin: 0; - padding: 0; - color: #000; - font-size: 14px; -} - -body -{ - overflow-y: scroll; - background-color: rgba(4, 101, 161, 0.08); -} - -h4 -{ - color: inherit; - font-size: inherit; - margin-bottom: 0.5rem; -} - - -/* Grundaufbau *************************************************/ - -.menue -{ - position: relative; - z-index: 2000; - background-color: #000; - margin-bottom: 30px; -} - -.innen -{ - max-width: 1080px; - margin: 0 auto; - padding: 0 2%; -} - - - -/* Formatierungen *************************************************/ - -.color2 -{ - color: rgba(0, 0, 0, 0.6); -} - -.schwarz -{ - color: #555 !important; -} - -.normal -{ - font-weight: normal; -} - -.bold -{ - font-weight: bold; -} - -.abstandUnten -{ - margin-bottom: 5px; -} - -.abstandUntenKlein -{ - margin-bottom: 10px; -} - -.noPaddingTop -{ - padding-top: 0 !important; -} - -.ausrichtungRechts -{ - text-align: right; -} - - - - -/* Menü ********************************************************/ - -button -{ - position: relative; - font-family: serif; - padding-top: 15px; - padding-left: 0; - padding-right: 0; - margin-right: 2%; -} - -.btnAktiv -{ - font-size: 22px; - color: #ffb619; - height: 50px; - outline: none; - border: none; - background: none; -} - -.btnAktiv:after -{ - content: ""; - display: block; - position: absolute; - top: 50px; - left: 50%; - z-index: 10; - font-size: 0; - line-height: 0; - height: 0; - padding: 0; - margin: 0; - transform: translateX(-50%); - border: 15px solid #000; - border-right-color: transparent; - border-bottom-color: transparent; - border-left-color: transparent; -} - -.btnInaktiv, -.tab -{ - font-size: 22px; - color: #fff; - height: 50px; - z-index: 0; - outline: none; - border: none; - background: none; - transition: color 0.3s ease; -} - -.btnInaktiv:hover, -.tab:hover -{ - color: #ffb619; - cursor: pointer; -} - -.divHide -{ - display: none; -} - -/* Content *********************************************************************/ - -.inhalt -{ - font-family: sans-serif; - margin-bottom: 30px; -} - -.haftungausschluss -{ - color: #000; - text-align: center; - padding: 7px; - margin-bottom: 30px; - width: 100%; - border: 1px solid #ffb619; - background-color: #fff; -} - -.box -{ - position: relative; - display: table-cell; - padding: 0; - border: 1px solid rgba(4, 101, 161, 0.2); - background-color: #fff; -} - -.subBox -{ - border-top: none; - width: 50%; -} - -.subBox:last-child -{ - border-left: none; -} - -.first > .boxzeile > .subBox -{ - border-top: 1px solid rgba(4, 101, 161, 0.2) !important; -} - -.boxtitel -{ - display: inline-block; - background-color: #0465A1; - padding: 7px 10px; - color: #fff; - font-weight: bold; -} - -.boxBorderTop -{ - border-top: none; -} - -.boxBorderLeft -{ - border-left: none; -} - -.boxtitelSub -{ - color: #000; - background-color: rgba(4, 101, 161, 0.1); - border-right: 1px solid rgba(4, 101, 161, 0.2); - border-bottom: 1px solid rgba(4, 101, 161, 0.2); -} - -.boxinhalt -{ - padding: 15px 20px; -} - -.boxtabelle -{ - display: table; - width: 100%; -} - -.borderSpacing -{ - border-spacing: 0 5px; -} - -.boxabstandtop -{ - margin-top: 30px; -} - -.boxzeile -{ - display: table-row; -} - -.boxzeile .box:last-child -{ - margin-bottom: 0; -} - -.boxdaten -{ - display: table-cell; - padding: 5px 0; - vertical-align: middle; - height: 38px; - /* - -ms-word-break: break-all; - word-break: break-all; - word-break: break-word; - -webkit-hyphens: auto; - -moz-hyphens: auto; - hyphens: auto; -*/ -} - -.boxdaten.wert -{ - padding: 5px 10px; -} - -.boxcell -{ - display: table-cell; -} - -.boxdatenBlock -{ - display: block; - padding: 3px 0; - /* - -ms-word-break: break-all; - word-break: break-all; - word-break: break-word; - -webkit-hyphens: auto; - -moz-hyphens: auto; - hyphens: auto; -*/ -} - -.noBreak -{ - -ms-word-break: keep-all; - word-break: keep-all; - word-break: keep-all; - -webkit-hyphens: none; - -moz-hyphens: none; - hyphens: none; -} - -.boxabstand -{ - display: table-cell; - width: 30px; -} - -.legende -{ - color: rgba(0, 0, 0, 0.6); - width: 170px; - font-size: 13px; - line-height: 16px; - padding-right: 5px; -} - -.wert -{ - background-color: rgba(4, 101, 161, 0.03); -} - -.boxtabelleEinspaltig -{ - width: 49%; -} - -.boxtabelleZweispaltig, -.boxtabelleDreispaltig -{ - width: 100%; -} - -.box5050 -{ - width: 50%; -} - -.boxEinspaltig -{ - width: 100%; -} - -.boxZweispaltig -{ - width: 48.5%; -} - -.boxSpalte1 { - width: 50%; -} - -.boxSpalte2 { - width: 50%; - padding-left: 20px; -} - -.paddingLeft { - padding-left: 0.1em; -} - -.noPadding { - padding-top: 0 !important; - padding-bottom: 0 !important; -} - -.rechnungsZeile -{ - display: table-row; -} - -.rechnungsZeile .boxdaten -{ - height: auto; -} - -.rechnungSp1 -{ - width: 65%; - font-size: 16px; -} - -.rechnungSp2 -{ - width: 10%; -} - -.rechnungSp3 -{ - width: 25%; - font-size: 16px; - text-align: right; -} - -.detailSp1, -.detailSp2 -{ - width: 50%; -} - -.detailSp2 -{ - text-align: right; -} - -.line1Bottom -{ - border-bottom: 1px solid #000; -} - -.line1BottomLight -{ - padding-bottom: 5px; - border-bottom: 1px solid #f0f0f0; - margin-bottom: 5px; -} - -.line2Bottom -{ - border-bottom: 2px solid #000; -} - -.paddingTop -{ - padding-top: 10px; -} - -.paddingBottom -{ - padding-bottom: 10px; -} - -.grund -{ - font-size: 16px; - display: block; - width: 100%; - padding: 0 20px 15px 20px; -} - -.grundDetail -{ - display: block; - width: 100%; - padding: 0 20px 15px 20px; -} - -/* Übersichtformatierungen */ -#uebersichtLastschrift.box, -#uebersichtUeberweisung.box -{ - border-top: none; -} - -#uebersichtUeberweisung.box -{ - border-left: none; -} - - -/* Formatierungen Detailseite */ - -.detailsSpalte1, -.detailsSpalte2 -{ - width: 30%; - float: left; - font-size: 90%; - line-height: 115%; - margin-right: 5%; -} - -.detailsSpalte3 -{ - width: 30%; - float: left; - font-size: 90%; - line-height: 115%; -} - -.detailsSpalte1 .legende, -.detailsSpalte2 .legende, -.detailsSpalte3 .legende -{ - width: 145px; -} - -.titelPosition -{ - font-size: 17px; - font-weight: bold; -} - - -/* Laufzettelformatierungen */ -#laufzettelHistorie .boxtabelle:not(:nth-child(2)) -{ - border-top: 1px solid rgba(4, 101, 161, 0.2); - padding-top: 10px; - margin-top: 10px; -} - - - - - -/* 1023px und kleiner ************************************************/ - -@media screen and (max-width : 1023px) { - - .box - { - display: block; - width: 100%; - margin-bottom: 20px; - } - - .boxabstandtop - { - margin-top: 15px; - } - - .subBox:first-child - { - margin-bottom: 0 !important; - } - - .subBox:last-child - { - border-left: 1px solid rgba(4, 101, 161, 0.2); - } - - .first > .boxzeile > .subBox - { - border-top: none !important; - } - - .first > .boxzeile > .subBox:first-child - { - border-top: 1px solid rgba(4, 101, 161, 0.2) !important; - } - - .first > .boxzeile - { - margin-bottom: 0; - } - - #uebersichtUeberweisung.box - { - border-left: 1px solid rgba(4, 101, 161, 0.2); - } - - #uebersichtLastschrift.box - { - margin-bottom: 0; - } - - .boxzeile - { - display: block; - margin-bottom: 5px; - } - - .boxzeile:after - { - visibility: hidden; - display: block; - font-size: 0; - content: " "; - clear: both; - height: 0; - } - - #details > .boxtabelle > .boxzeile - { - margin-bottom: 0px; - } - - .boxcell - { - display: block; - } - - .boxcell:last-child - { - margin-top: 20px; - } - - .boxZweispaltig - { - width: 100%; - } - - .legende - { - display: block; - float: left; - width: 170px; - padding: 5px 0; - height: auto; - } - - .wert - { - display: block; - float: left; - width: calc(100% - 170px); - padding: 11px 10px !important; - line-height: 1.3; - min-height: 38px; - height: auto; - } - - .boxdaten .legende - { - height: auto; - } - - .rechnungsZeile .boxdaten - { - padding: 5px 0; - } - - .boxabstand - { - display: none; - } - - .boxtabelleEinspaltig { - width: 100%; - } - - .boxSpalte1 { - display: block; - width: auto; - } - - .boxSpalte2 { - display: block; - width: auto; - padding-left: 0px; - margin-top: 1.2rem; - } - - .detailsSpalte1, - .detailsSpalte2, - .detailsSpalte3 - { - width: 100%; - float: none; - padding-right: 0px; - } - - .detailsSpalte2, - .detailsSpalte3 - { - margin-top: 15px; - } - - .detailsSpalte2, - .detailsSpalte3 - { - margin-top: 10px; - } - - .tableNumberAlignRight - { - display: block; - width: 130px; - text-align: right; - } -} - - - -/* 800px und kleiner ************************************************/ - -@media screen and (max-width : 800px) { - - button - { - padding-top: 10px; - } - - .btnAktiv, - .btnInaktiv, - .tab - { - font-size: 20px; - height: 40px; - } - - .btnAktiv:after - { - top: 40px; - } - - .rechnungSp1 - { - width: 55%; - font-size: 15px; - } - - .rechnungSp2 - { - width: 10%; - } - - .rechnungSp3 - { - width: 35%; - text-align: right; - font-size: 15px; - } - - .grund - { - font-size: 15px; - } -} - -/* 450px und kleiner ************************************************/ - -@media screen and (max-width : 450px) -{ - - html, - body - { - font-size: 12px; - } - - .menue - { - margin-bottom: 20px; - } - - button - { - padding-top: 5px; - } - - .btnAktiv, - .btnInaktiv, - .tab - { - font-size: 17px; - height: 35px; - } - - .btnAktiv:after - { - top: 35px; - } - - .legende - { - font-size: 12px; - width: 100%; - } - - .wert - { - font-size: 12px; - line-height: 1.3; - width: 100%; - margin-bottom: 10px - } - - .boxzeile - { - margin-bottom: 0px - } - - .boxdaten - { - height: auto; - } - - .haftungausschluss - { - margin-bottom: 20px; - } - - .boxinhalt - { - margin-top: 0px; - } - - .boxabstandtop - { - margin-top: 20px; - } - - .boxtitel - { - padding: 7px 8px; - } - - .box - { - margin-bottom: 10px; - padding: 0; - } - - .boxabstandtop - { - margin-top: 10px; - } - - .boxdaten, - .boxdatenBlock - { - padding: 2px 0; - } - - .rechnungSp1 - { - width: 50%; - font-size: inherit; - } - - .rechnungSp2 - { - width: 15%; - } - - .rechnungSp3 - { - width: 35%; - font-size: inherit; - text-align: right; - } - - .grund - { - font-size: inherit; - } - - .titelPosition - { - font-size: 15px; - } - - .abstandUnten - { - margin-bottom: 5px; - } - - .detailsSpalte1, - .detailsSpalte2, - .detailsSpalte3 - { - font-size: inherit; - line-height: inherit; - } -} - -/* 380px und kleiner ************************************************/ - -@media screen and (max-width : 380px) { - - html, - body - { - font-size: 11px; - line-height: 100%; - } - - .btnAktiv, - .btnInaktiv, - .tab - { - font-size: 15px; - } - - .boxdaten -.boxdatenBlock - { - padding: 2px 0; - } - - .boxinhalt - { - margin-top: 0px; - } - - .boxtitel - { - padding: 5px 7px; - } -} diff --git a/src/main/resources/xrechnung-viewer.js b/src/main/resources/xrechnung-viewer.js deleted file mode 100644 index 2d547b86..00000000 --- a/src/main/resources/xrechnung-viewer.js +++ /dev/null @@ -1,145 +0,0 @@ - -/* Tab-Container aufbauen **************************************************/ - -var a = new Array("uebersicht", "details", "zusaetze", "anlagen", "laufzettel"); -var b = new Array("menueUebersicht", "menueDetails", "menueZusaetze", "menueAnlagen", "menueLaufzettel"); - -function show(e) { - var i = 0; - var j = 1; - for (var t = 0; t < b.length; t++) { - if (b[t] === e.id) { - i = t; - if (i > 0) { - j = 0; - } else { - j = i + 1; - } - break; - } - } - e.setAttribute("class", "btnAktiv"); - for (var k = 0; k < b.length; k++) { - if (k === i && (document.getElementById(a[k]) != null)) { - document.getElementById(a[k]).style.display = "block"; - if (i === j) - j = i + 1; - } else { - if (document.getElementById(a[k]) != null) { - document.getElementById(a[j]).style.display = "none"; - document.getElementById(b[j]).setAttribute("class", "btnInaktiv"); - j += 1; - } - } - } -} -window.onload = function () { - document.getElementById(b[0]).setAttribute("class", "btnAktiv"); -} - -/* Eingebettete Binaerdaten runterladen ************************************/ - - -function base64_to_binary (data) { - var chars = atob(data); - var bytes = new Array(chars.length); - for (var i = 0; i < chars.length; i++) { - bytes[i] = chars.charCodeAt(i); - } - return new Uint8Array(bytes); -} - -function downloadData (element_id) { - var data_element = document.getElementById(element_id); - var mimetype = data_element.getAttribute('mimeType'); - var filename = data_element.getAttribute('filename'); - var text = data_element.innerHTML; - var binary = base64_to_binary(text); - var blob = new Blob([binary], { - type: mimetype, size: binary.length - }); - - if (window.navigator && window.navigator.msSaveOrOpenBlob) { - // IE - window.navigator.msSaveOrOpenBlob(blob, filename); - } else { - // Non-IE - var url = window.URL.createObjectURL(blob); - window.open(url); - } -} - - -/* Polyfill IE atob/btoa ************************************/ - -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define([], function () { - factory(root); - }); - } else factory(root); - // node.js has always supported base64 conversions, while browsers that support - // web workers support base64 too, but you may never know. -})(typeof exports !== "undefined" ? exports: this, function (root) { - if (root.atob) { - // Some browsers' implementation of atob doesn't support whitespaces - // in the encoded string (notably, IE). This wraps the native atob - // in a function that strips the whitespaces. - // The original function can be retrieved in atob.original - try { - root.atob(" "); - } - catch (e) { - root.atob = (function (atob) { - var func = function (string) { - return atob(String(string).replace(/[\t\n\f\r ]+/g, "")); - }; - func.original = atob; - return func; - })(root.atob); - } - return; - } - - // base64 character set, plus padding character (=) - var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", - // Regular expression to check formal correctness of base64 encoded strings - b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/; - - root.btoa = function (string) { - string = String(string); - var bitmap, a, b, c, - result = "", i = 0, - rest = string.length % 3; // To determine the final padding - - for (; i < string.length;) { - if ((a = string.charCodeAt(i++)) > 255 || (b = string.charCodeAt(i++)) > 255 || (c = string.charCodeAt(i++)) > 255) - throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range."); - - bitmap = (a << 16) | (b << 8) | c; - result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) + b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63); - } - - // If there's need of padding, replace the last 'A's with equal signs - return rest ? result.slice(0, rest - 3) + "===".substring(rest): result; - }; - - root.atob = function (string) { - // atob can work with strings with whitespaces, even inside the encoded part, - // but only \t, \n, \f, \r and ' ', which can be stripped. - string = String(string).replace(/[\t\n\f\r ]+/g, ""); - if (! b64re.test(string)) - throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded."); - - // Adding the padding if missing, for semplicity - string += "==".slice(2 - (string.length & 3)); - var bitmap, result = "", r1, r2, i = 0; - for (; i < string.length;) { - bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12 | (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++))); - - result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255): r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255): String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255); - } - return result; - }; -}); \ No newline at end of file diff --git a/xrechnung-viewer.css b/xrechnung-viewer.css deleted file mode 100644 index adea4c9b..00000000 --- a/xrechnung-viewer.css +++ /dev/null @@ -1,917 +0,0 @@ -/* Grundformatierung ********************************************/ - -*, -*:after, -*:before -{ - box-sizing: border-box; - -moz-box-sizing: border-box; -} - -.clear:after -{ - content: "."; - clear: both; - display: block; - visibility: hidden; - height: 0; -} - -html, -body -{ - height: 100%; - min-width: 320px; - margin: 0; - padding: 0; - color: #000; - font-size: 14px; -} - -body -{ - overflow-y: scroll; - background-color: rgba(4, 101, 161, 0.08); -} - -h4 -{ - color: inherit; - font-size: inherit; - margin-bottom: 0.5rem; -} - - -/* Grundaufbau *************************************************/ - -.menue -{ - position: relative; - z-index: 2000; - background-color: #000; - margin-bottom: 30px; -} - -.innen -{ - max-width: 1080px; - margin: 0 auto; - padding: 0 2%; -} - - - -/* Formatierungen *************************************************/ - -.color2 -{ - color: rgba(0, 0, 0, 0.6); -} - -.schwarz -{ - color: #555 !important; -} - -.normal -{ - font-weight: normal; -} - -.bold -{ - font-weight: bold; -} - -.abstandUnten -{ - margin-bottom: 5px; -} - -.abstandUntenKlein -{ - margin-bottom: 10px; -} - -.noPaddingTop -{ - padding-top: 0 !important; -} - -.ausrichtungRechts -{ - text-align: right; -} - - - - -/* Menü ********************************************************/ - -button -{ - position: relative; - font-family: serif; - padding-top: 15px; - padding-left: 0; - padding-right: 0; - margin-right: 2%; -} - -.btnAktiv -{ - font-size: 22px; - color: #ffb619; - height: 50px; - outline: none; - border: none; - background: none; -} - -.btnAktiv:after -{ - content: ""; - display: block; - position: absolute; - top: 50px; - left: 50%; - z-index: 10; - font-size: 0; - line-height: 0; - height: 0; - padding: 0; - margin: 0; - transform: translateX(-50%); - border: 15px solid #000; - border-right-color: transparent; - border-bottom-color: transparent; - border-left-color: transparent; -} - -.btnInaktiv, -.tab -{ - font-size: 22px; - color: #fff; - height: 50px; - z-index: 0; - outline: none; - border: none; - background: none; - transition: color 0.3s ease; -} - -.btnInaktiv:hover, -.tab:hover -{ - color: #ffb619; - cursor: pointer; -} - -.divHide -{ - display: none; -} - -/* Content *********************************************************************/ - -.inhalt -{ - font-family: sans-serif; - margin-bottom: 30px; -} - -.haftungausschluss -{ - color: #000; - text-align: center; - padding: 7px; - margin-bottom: 30px; - width: 100%; - border: 1px solid #ffb619; - background-color: #fff; -} - -.box -{ - position: relative; - display: table-cell; - padding: 0; - border: 1px solid rgba(4, 101, 161, 0.2); - background-color: #fff; -} - -.subBox -{ - border-top: none; - width: 50%; -} - -.subBox:last-child -{ - border-left: none; -} - -.first > .boxzeile > .subBox -{ - border-top: 1px solid rgba(4, 101, 161, 0.2) !important; -} - -.boxtitel -{ - display: inline-block; - background-color: #0465A1; - padding: 7px 10px; - color: #fff; - font-weight: bold; -} - -.boxBorderTop -{ - border-top: none; -} - -.boxBorderLeft -{ - border-left: none; -} - -.boxtitelSub -{ - color: #000; - background-color: rgba(4, 101, 161, 0.1); - border-right: 1px solid rgba(4, 101, 161, 0.2); - border-bottom: 1px solid rgba(4, 101, 161, 0.2); -} - -.boxinhalt -{ - padding: 15px 20px; -} - -.boxtabelle -{ - display: table; - width: 100%; -} - -.borderSpacing -{ - border-spacing: 0 5px; -} - -.boxabstandtop -{ - margin-top: 30px; -} - -.boxzeile -{ - display: table-row; -} - -.boxzeile .box:last-child -{ - margin-bottom: 0; -} - -.boxdaten -{ - display: table-cell; - padding: 5px 0; - vertical-align: middle; - height: 38px; - /* - -ms-word-break: break-all; - word-break: break-all; - word-break: break-word; - -webkit-hyphens: auto; - -moz-hyphens: auto; - hyphens: auto; -*/ -} - -.boxdaten.wert -{ - padding: 5px 10px; -} - -.boxcell -{ - display: table-cell; -} - -.boxdatenBlock -{ - display: block; - padding: 3px 0; - /* - -ms-word-break: break-all; - word-break: break-all; - word-break: break-word; - -webkit-hyphens: auto; - -moz-hyphens: auto; - hyphens: auto; -*/ -} - -.noBreak -{ - -ms-word-break: keep-all; - word-break: keep-all; - word-break: keep-all; - -webkit-hyphens: none; - -moz-hyphens: none; - hyphens: none; -} - -.boxabstand -{ - display: table-cell; - width: 30px; -} - -.legende -{ - color: rgba(0, 0, 0, 0.6); - width: 170px; - font-size: 13px; - line-height: 16px; - padding-right: 5px; -} - -.wert -{ - background-color: rgba(4, 101, 161, 0.03); -} - -.boxtabelleEinspaltig -{ - width: 49%; -} - -.boxtabelleZweispaltig, -.boxtabelleDreispaltig -{ - width: 100%; -} - -.box5050 -{ - width: 50%; -} - -.boxEinspaltig -{ - width: 100%; -} - -.boxZweispaltig -{ - width: 48.5%; -} - -.boxSpalte1 { - width: 50%; -} - -.boxSpalte2 { - width: 50%; - padding-left: 20px; -} - -.paddingLeft { - padding-left: 0.1em; -} - -.noPadding { - padding-top: 0 !important; - padding-bottom: 0 !important; -} - -.rechnungsZeile -{ - display: table-row; -} - -.rechnungsZeile .boxdaten -{ - height: auto; -} - -.rechnungSp1 -{ - width: 65%; - font-size: 16px; -} - -.rechnungSp2 -{ - width: 10%; -} - -.rechnungSp3 -{ - width: 25%; - font-size: 16px; - text-align: right; -} - -.detailSp1, -.detailSp2 -{ - width: 50%; -} - -.detailSp2 -{ - text-align: right; -} - -.line1Bottom -{ - border-bottom: 1px solid #000; -} - -.line1BottomLight -{ - padding-bottom: 5px; - border-bottom: 1px solid #f0f0f0; - margin-bottom: 5px; -} - -.line2Bottom -{ - border-bottom: 2px solid #000; -} - -.paddingTop -{ - padding-top: 10px; -} - -.paddingBottom -{ - padding-bottom: 10px; -} - -.grund -{ - font-size: 16px; - display: block; - width: 100%; - padding: 0 20px 15px 20px; -} - -.grundDetail -{ - display: block; - width: 100%; - padding: 0 20px 15px 20px; -} - -/* Übersichtformatierungen */ -#uebersichtLastschrift.box, -#uebersichtUeberweisung.box -{ - border-top: none; -} - -#uebersichtUeberweisung.box -{ - border-left: none; -} - - -/* Formatierungen Detailseite */ - -.detailsSpalte1, -.detailsSpalte2 -{ - width: 30%; - float: left; - font-size: 90%; - line-height: 115%; - margin-right: 5%; -} - -.detailsSpalte3 -{ - width: 30%; - float: left; - font-size: 90%; - line-height: 115%; -} - -.detailsSpalte1 .legende, -.detailsSpalte2 .legende, -.detailsSpalte3 .legende -{ - width: 145px; -} - -.titelPosition -{ - font-size: 17px; - font-weight: bold; -} - - -/* Laufzettelformatierungen */ -#laufzettelHistorie .boxtabelle:not(:nth-child(2)) -{ - border-top: 1px solid rgba(4, 101, 161, 0.2); - padding-top: 10px; - margin-top: 10px; -} - - - - - -/* 1023px und kleiner ************************************************/ - -@media screen and (max-width : 1023px) { - - .box - { - display: block; - width: 100%; - margin-bottom: 20px; - } - - .boxabstandtop - { - margin-top: 15px; - } - - .subBox:first-child - { - margin-bottom: 0 !important; - } - - .subBox:last-child - { - border-left: 1px solid rgba(4, 101, 161, 0.2); - } - - .first > .boxzeile > .subBox - { - border-top: none !important; - } - - .first > .boxzeile > .subBox:first-child - { - border-top: 1px solid rgba(4, 101, 161, 0.2) !important; - } - - .first > .boxzeile - { - margin-bottom: 0; - } - - #uebersichtUeberweisung.box - { - border-left: 1px solid rgba(4, 101, 161, 0.2); - } - - #uebersichtLastschrift.box - { - margin-bottom: 0; - } - - .boxzeile - { - display: block; - margin-bottom: 5px; - } - - .boxzeile:after - { - visibility: hidden; - display: block; - font-size: 0; - content: " "; - clear: both; - height: 0; - } - - #details > .boxtabelle > .boxzeile - { - margin-bottom: 0px; - } - - .boxcell - { - display: block; - } - - .boxcell:last-child - { - margin-top: 20px; - } - - .boxZweispaltig - { - width: 100%; - } - - .legende - { - display: block; - float: left; - width: 170px; - padding: 5px 0; - height: auto; - } - - .wert - { - display: block; - float: left; - width: calc(100% - 170px); - padding: 11px 10px !important; - line-height: 1.3; - min-height: 38px; - height: auto; - } - - .boxdaten .legende - { - height: auto; - } - - .rechnungsZeile .boxdaten - { - padding: 5px 0; - } - - .boxabstand - { - display: none; - } - - .boxtabelleEinspaltig { - width: 100%; - } - - .boxSpalte1 { - display: block; - width: auto; - } - - .boxSpalte2 { - display: block; - width: auto; - padding-left: 0px; - margin-top: 1.2rem; - } - - .detailsSpalte1, - .detailsSpalte2, - .detailsSpalte3 - { - width: 100%; - float: none; - padding-right: 0px; - } - - .detailsSpalte2, - .detailsSpalte3 - { - margin-top: 15px; - } - - .detailsSpalte2, - .detailsSpalte3 - { - margin-top: 10px; - } - - .tableNumberAlignRight - { - display: block; - width: 130px; - text-align: right; - } -} - - - -/* 800px und kleiner ************************************************/ - -@media screen and (max-width : 800px) { - - button - { - padding-top: 10px; - } - - .btnAktiv, - .btnInaktiv, - .tab - { - font-size: 20px; - height: 40px; - } - - .btnAktiv:after - { - top: 40px; - } - - .rechnungSp1 - { - width: 55%; - font-size: 15px; - } - - .rechnungSp2 - { - width: 10%; - } - - .rechnungSp3 - { - width: 35%; - text-align: right; - font-size: 15px; - } - - .grund - { - font-size: 15px; - } -} - -/* 450px und kleiner ************************************************/ - -@media screen and (max-width : 450px) -{ - - html, - body - { - font-size: 12px; - } - - .menue - { - margin-bottom: 20px; - } - - button - { - padding-top: 5px; - } - - .btnAktiv, - .btnInaktiv, - .tab - { - font-size: 17px; - height: 35px; - } - - .btnAktiv:after - { - top: 35px; - } - - .legende - { - font-size: 12px; - width: 100%; - } - - .wert - { - font-size: 12px; - line-height: 1.3; - width: 100%; - margin-bottom: 10px - } - - .boxzeile - { - margin-bottom: 0px - } - - .boxdaten - { - height: auto; - } - - .haftungausschluss - { - margin-bottom: 20px; - } - - .boxinhalt - { - margin-top: 0px; - } - - .boxabstandtop - { - margin-top: 20px; - } - - .boxtitel - { - padding: 7px 8px; - } - - .box - { - margin-bottom: 10px; - padding: 0; - } - - .boxabstandtop - { - margin-top: 10px; - } - - .boxdaten, - .boxdatenBlock - { - padding: 2px 0; - } - - .rechnungSp1 - { - width: 50%; - font-size: inherit; - } - - .rechnungSp2 - { - width: 15%; - } - - .rechnungSp3 - { - width: 35%; - font-size: inherit; - text-align: right; - } - - .grund - { - font-size: inherit; - } - - .titelPosition - { - font-size: 15px; - } - - .abstandUnten - { - margin-bottom: 5px; - } - - .detailsSpalte1, - .detailsSpalte2, - .detailsSpalte3 - { - font-size: inherit; - line-height: inherit; - } -} - -/* 380px und kleiner ************************************************/ - -@media screen and (max-width : 380px) { - - html, - body - { - font-size: 11px; - line-height: 100%; - } - - .btnAktiv, - .btnInaktiv, - .tab - { - font-size: 15px; - } - - .boxdaten -.boxdatenBlock - { - padding: 2px 0; - } - - .boxinhalt - { - margin-top: 0px; - } - - .boxtitel - { - padding: 5px 7px; - } -} diff --git a/xrechnung-viewer.js b/xrechnung-viewer.js deleted file mode 100644 index 2d547b86..00000000 --- a/xrechnung-viewer.js +++ /dev/null @@ -1,145 +0,0 @@ - -/* Tab-Container aufbauen **************************************************/ - -var a = new Array("uebersicht", "details", "zusaetze", "anlagen", "laufzettel"); -var b = new Array("menueUebersicht", "menueDetails", "menueZusaetze", "menueAnlagen", "menueLaufzettel"); - -function show(e) { - var i = 0; - var j = 1; - for (var t = 0; t < b.length; t++) { - if (b[t] === e.id) { - i = t; - if (i > 0) { - j = 0; - } else { - j = i + 1; - } - break; - } - } - e.setAttribute("class", "btnAktiv"); - for (var k = 0; k < b.length; k++) { - if (k === i && (document.getElementById(a[k]) != null)) { - document.getElementById(a[k]).style.display = "block"; - if (i === j) - j = i + 1; - } else { - if (document.getElementById(a[k]) != null) { - document.getElementById(a[j]).style.display = "none"; - document.getElementById(b[j]).setAttribute("class", "btnInaktiv"); - j += 1; - } - } - } -} -window.onload = function () { - document.getElementById(b[0]).setAttribute("class", "btnAktiv"); -} - -/* Eingebettete Binaerdaten runterladen ************************************/ - - -function base64_to_binary (data) { - var chars = atob(data); - var bytes = new Array(chars.length); - for (var i = 0; i < chars.length; i++) { - bytes[i] = chars.charCodeAt(i); - } - return new Uint8Array(bytes); -} - -function downloadData (element_id) { - var data_element = document.getElementById(element_id); - var mimetype = data_element.getAttribute('mimeType'); - var filename = data_element.getAttribute('filename'); - var text = data_element.innerHTML; - var binary = base64_to_binary(text); - var blob = new Blob([binary], { - type: mimetype, size: binary.length - }); - - if (window.navigator && window.navigator.msSaveOrOpenBlob) { - // IE - window.navigator.msSaveOrOpenBlob(blob, filename); - } else { - // Non-IE - var url = window.URL.createObjectURL(blob); - window.open(url); - } -} - - -/* Polyfill IE atob/btoa ************************************/ - -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define([], function () { - factory(root); - }); - } else factory(root); - // node.js has always supported base64 conversions, while browsers that support - // web workers support base64 too, but you may never know. -})(typeof exports !== "undefined" ? exports: this, function (root) { - if (root.atob) { - // Some browsers' implementation of atob doesn't support whitespaces - // in the encoded string (notably, IE). This wraps the native atob - // in a function that strips the whitespaces. - // The original function can be retrieved in atob.original - try { - root.atob(" "); - } - catch (e) { - root.atob = (function (atob) { - var func = function (string) { - return atob(String(string).replace(/[\t\n\f\r ]+/g, "")); - }; - func.original = atob; - return func; - })(root.atob); - } - return; - } - - // base64 character set, plus padding character (=) - var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", - // Regular expression to check formal correctness of base64 encoded strings - b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/; - - root.btoa = function (string) { - string = String(string); - var bitmap, a, b, c, - result = "", i = 0, - rest = string.length % 3; // To determine the final padding - - for (; i < string.length;) { - if ((a = string.charCodeAt(i++)) > 255 || (b = string.charCodeAt(i++)) > 255 || (c = string.charCodeAt(i++)) > 255) - throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range."); - - bitmap = (a << 16) | (b << 8) | c; - result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) + b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63); - } - - // If there's need of padding, replace the last 'A's with equal signs - return rest ? result.slice(0, rest - 3) + "===".substring(rest): result; - }; - - root.atob = function (string) { - // atob can work with strings with whitespaces, even inside the encoded part, - // but only \t, \n, \f, \r and ' ', which can be stripped. - string = String(string).replace(/[\t\n\f\r ]+/g, ""); - if (! b64re.test(string)) - throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded."); - - // Adding the padding if missing, for semplicity - string += "==".slice(2 - (string.length & 3)); - var bitmap, result = "", r1, r2, i = 0; - for (; i < string.length;) { - bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12 | (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++))); - - result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255): r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255): String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255); - } - return result; - }; -}); \ No newline at end of file From 8f34fa90103a44310190cb86898a65292d55c5d5 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Wed, 31 Jul 2019 21:49:24 +0200 Subject: [PATCH 60/82] add getter for TotalPrepaidAmount to IZUGFeRDExportableTransaction interface --- .../ZUGFeRD/IZUGFeRDExportableTransaction.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java index 3be30215..9d3306aa 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java @@ -29,6 +29,7 @@ package org.mustangproject.ZUGFeRD; import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants; +import java.math.BigDecimal; import java.util.Date; public interface IZUGFeRDExportableTransaction { @@ -257,4 +258,12 @@ public interface IZUGFeRDExportableTransaction { * @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; } } From e668a460fb9b64e4392755e888a22a4d3be85688 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Wed, 31 Jul 2019 21:54:00 +0200 Subject: [PATCH 61/82] add totalPrepaidAmount to monetarySummation and use value to calculate duePayableAmount --- .../ZUGFeRD/ZUGFeRDTransactionModelConverter.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java index 6610f0f2..e8ca6841 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java @@ -659,9 +659,14 @@ class ZUGFeRDTransactionModelConverter { grandTotalAmount.setValue(currencyFormat(totals.getTotalGross())); monetarySummation.getGrandTotalAmount().add(grandTotalAmount); + AmountType totalPrepaidAmount = xmlFactory.createAmountType(); + totalPrepaidAmount.setCurrencyID(currency); + totalPrepaidAmount.setValue(currencyFormat(trans.getTotalPrepaidAmount())); + monetarySummation.getTotalPrepaidAmount().add(totalPrepaidAmount); + AmountType duePayableAmount = xmlFactory.createAmountType(); duePayableAmount.setCurrencyID(currency); - duePayableAmount.setValue(currencyFormat(totals.getTotalGross())); + duePayableAmount.setValue(currencyFormat(totals.getTotalGross().subtract(trans.getTotalPrepaidAmount()))); monetarySummation.getDuePayableAmount().add(duePayableAmount); return monetarySummation; From 70643a3ff7a303161a5b7d57094dc25a442951ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Thu, 1 Aug 2019 19:49:19 +0200 Subject: [PATCH 62/82] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4ca4bb50..8e7763ad 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.3-SNAPSHOT + 1.7.4-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -113,7 +113,7 @@ com.sanityinc jargs - 2.0-SNAPSHOT + 2.0 From 91cb384d9ff6c8008031b9c0e4e96d7499534528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Thu, 1 Aug 2019 19:52:24 +0200 Subject: [PATCH 63/82] corrected for release --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8e7763ad..3fa41d78 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.4-SNAPSHOT + 1.7.3-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -13,7 +13,7 @@ scm:git:https://github.com/ZUGFeRD/mustangproject.git scm:git:https://github.com/ZUGFeRD/mustangproject.git https://github.com/ZUGFeRD/mustangproject - mustang-1.5.2 + mustang-1.7.3 From de5241769cadeb338de6af54f6749de5e96c75a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Thu, 1 Aug 2019 19:53:53 +0200 Subject: [PATCH 64/82] [maven-release-plugin] prepare release mustang-1.7.3 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3fa41d78..3b7f7798 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.3-SNAPSHOT + 1.7.3 jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs @@ -113,7 +113,7 @@ com.sanityinc jargs - 2.0 + 2.0-SNAPSHOT From 60868a3914b7000f60caac7856d16adbe37f50d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Thu, 1 Aug 2019 19:56:43 +0200 Subject: [PATCH 65/82] updated history for 1.7.3 --- History.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/History.md b/History.md index f4b57df7..fdfa3e44 100644 --- a/History.md +++ b/History.md @@ -1,11 +1,15 @@ -todo -- migration: testIndicator entfernen -- in ram:ExchangedDocument: ram:name entfernen -done +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 -- closed #23 -- #112 +- PR #112 complete profile options for v1 +- access to TotalPrepaidAmount in ZF v1 #118 +- have unit tests for nDigitFormat #23 + 1.7.2 ===== From 4fff136fa5010e6e0855b3ca2ed9e5fa6338c466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Thu, 1 Aug 2019 19:57:21 +0200 Subject: [PATCH 66/82] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3b7f7798..77463aa8 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.mustangproject.ZUGFeRD mustang - 1.7.3 + 1.7.4-SNAPSHOT jar Mustang The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs From 81635bb0952fc466b65e9a19ed3d6b328b0d2177 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Thu, 1 Aug 2019 20:16:54 +0200 Subject: [PATCH 67/82] use totalPrepaidAmount to calculate duePayableAmount (for v2) --- .../org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 7e12cdfe..58818aaa 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -145,6 +145,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { } + private BigDecimal getTotalPrepaid() { + return trans.getTotalPrepaidAmount(); + } + private BigDecimal getTotalGross() { BigDecimal res = getTotal(); @@ -477,8 +481,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { + " " + currencyFormat(getTotalGross()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // // // currencyID=\"EUR\" - // + " 0.00\n" - + " " + currencyFormat(getTotalGross()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + currencyFormat(getTotalPrepaid()) + "\n" + + " " + currencyFormat(getTotalGross().subtract(getTotalPrepaid())) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // // // currencyID=\"EUR\" + " \n" //$NON-NLS-1$ From c74e21ca87664f4110f4351c1cdc0608097dc075 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Mon, 5 Aug 2019 14:53:42 +0200 Subject: [PATCH 68/82] add missing ram: to closing tag --- .../java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 58818aaa..4b5f00d2 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -481,7 +481,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { + " " + currencyFormat(getTotalGross()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // // // currencyID=\"EUR\" - + " " + currencyFormat(getTotalPrepaid()) + "\n" + + " " + currencyFormat(getTotalPrepaid()) + "\n" + " " + currencyFormat(getTotalGross().subtract(getTotalPrepaid())) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // // // currencyID=\"EUR\" From bbd22852d4708c6f8dedd10b4896ae4ece978031 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Mon, 5 Aug 2019 15:04:51 +0200 Subject: [PATCH 69/82] parse rawXML into document only once --- .../ZUGFeRD/ZUGFeRDImporter.java | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index a9f1c9c2..639230ed 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -68,6 +68,7 @@ public class ZUGFeRDImporter { */ private byte[] rawXML = null; private String xmpString = null; // XMP metadata + private Document document; public ZUGFeRDImporter(String pdfFilename) { @@ -146,8 +147,7 @@ public class ZUGFeRDImporter { // ByteArrayOutputStream(); // FileOutputStream fos = new FileOutputStream(file); - rawXML = embeddedFile.toByteArray(); - setMeta(new String(rawXML)); + setRawXML(embeddedFile.toByteArray()); // fos.write(embeddedFile.getByteArray()); // fos.close(); @@ -176,15 +176,25 @@ public class ZUGFeRDImporter { 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(); xmlFact.setNamespaceAware(false); DocumentBuilder builder = xmlFact.newDocumentBuilder(); ByteArrayInputStream is = new ByteArrayInputStream(rawXML); is.skip(guessBOMSize(is)); - Document doc = builder.parse(is); - //prettyPrint(doc); - return doc; + document = builder.parse(is); } /** @@ -224,10 +234,7 @@ public class ZUGFeRDImporter { XPathFactory xpathFact = XPathFactory.newInstance(); XPath xpath = xpathFact.newXPath(); result = xpath.evaluate(xpathStr, document); - } catch (ParserConfigurationException e) { - Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); - throw new ZUGFeRDExportException(e); - } catch (IOException | SAXException | TransformerException | XPathExpressionException e) { + } catch (XPathExpressionException e) { Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); throw new ZUGFeRDExportException(e); } @@ -332,8 +339,8 @@ public class ZUGFeRDImporter { /** * @param meta raw XML to be set */ - public void setMeta(String meta) { - this.rawXML = meta.getBytes(); + public void setMeta(String meta) throws IOException { + setRawXML(meta.getBytes()); } /** From a264538d857f8a1684ddc9ba316d99ec4158e257 Mon Sep 17 00:00:00 2001 From: Ivan Vaklinov Date: Tue, 6 Aug 2019 14:26:34 +0300 Subject: [PATCH 70/82] Changes: 1. Minor improvement to exception handling 2. Changes to adding a file to the document catalog if the AF item is not directly a COSArray. --- .../ZUGFeRD/ZUGFeRDExporter.java | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java index f6796991..5dd999eb 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java @@ -33,6 +33,7 @@ import org.apache.pdfbox.cos.COSArray; import org.apache.pdfbox.cos.COSBase; import org.apache.pdfbox.cos.COSDictionary; import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.cos.COSObject; import org.apache.pdfbox.pdmodel.*; import org.apache.pdfbox.pdmodel.common.PDMetadata; import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification; @@ -478,17 +479,27 @@ public class ZUGFeRDExporter implements Closeable { doc.getDocumentCatalog().setNames(names); // AF entry (Array) in catalog with the FileSpec - COSArray cosArray = (COSArray) doc.getDocumentCatalog().getCOSObject().getItem("AF"); - if (cosArray == null) { - cosArray = new COSArray(); - } - cosArray.add(fs); - COSDictionary dict2 = doc.getDocumentCatalog().getCOSObject(); - COSArray array = new COSArray(); - array.add(fs.getCOSObject()); // see below - dict2.setItem("AF", array); - doc.getDocumentCatalog().getCOSObject().setItem("AF", cosArray); - } + COSBase AFEntry = (COSBase)doc.getDocumentCatalog().getCOSObject().getItem("AF"); + if ((AFEntry == null)) + { + COSArray cosArray = new COSArray(); + cosArray.add(fs); + doc.getDocumentCatalog().getCOSObject().setItem("AF", cosArray); + } else if (AFEntry instanceof COSArray) + { + COSArray cosArray = (COSArray)AFEntry; + cosArray.add(fs); + doc.getDocumentCatalog().getCOSObject().setItem("AF", cosArray); + } else if ((AFEntry instanceof COSObject) && + ((COSObject)AFEntry).getObject() instanceof COSArray) + { + COSArray cosArray = (COSArray)((COSObject)AFEntry).getObject(); + cosArray.add(fs); + } else + { + throw new IOException("Unexpected object type for PDFDocument/Catalog/COSDictionary/Item(AF)"); + } + } /** * Sets the ZUGFeRD XML data to be attached as a single byte array. This is @@ -575,12 +586,12 @@ public class ZUGFeRDExporter implements Closeable { buffer.write(prefix.getBytes("UTF-8")); // see https://github.com/ZUGFeRD/mustangproject/issues/44 serializer.serialize(xmpMetadata, buffer, false); buffer.write(suffix.getBytes("UTF-8")); - } catch (UnsupportedEncodingException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + } catch (UnsupportedEncodingException e) + { + throw new TransformerException(e); + } catch (IOException e) + { + throw new TransformerException(e); } return buffer.toByteArray(); } From 3492ed770a3ac581f3c50c063cb9e48dd3c1211c Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Wed, 7 Aug 2019 11:18:32 +0200 Subject: [PATCH 71/82] add test for ZUGFeRDImporter.getBankName ... and make it work --- src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java | 2 +- .../org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index 639230ed..3ae9bc24 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -283,7 +283,7 @@ public class ZUGFeRDImporter { * @return the sender's bankname */ public String getBankName() { - return extractString("/CrossIndustryInvoice/SupplyChainTradeTransaction/ApplicableHeaderTradeSettlement/SpecifiedTradeSettlementPaymentMeans/PayeeSpecifiedCreditorFinancialInstitution/Name"); + return extractString("//PayeeSpecifiedCreditorFinancialInstitution/Name"); } public String getIBAN() { diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index 94c9fa4f..38f9a552 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -202,6 +202,7 @@ public class MustangReaderWriterTest extends MustangReaderTestCase { assertEquals(zi.getKTO(), getTradeSettlementPayment()[0].getOwnKto()); assertEquals(zi.getHolder(), getOwnOrganisationName()); assertEquals(zi.getForeignReference(), "RE-20170509/505"); + assertEquals(zi.getBankName(), "Commerzbank"); } public void testForeignImport() { From 6e1ea1a3f3d8d8de04d1bbee8fa5dd13da8945e0 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Wed, 7 Aug 2019 11:33:51 +0200 Subject: [PATCH 72/82] deprecate German BLZ and Kontonummer --- .../ZUGFeRD/ZUGFeRDImporter.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index 639230ed..9b4e9c4f 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -267,11 +267,22 @@ public class ZUGFeRDImporter { /** * @return the sender's bank's BLZ code + * @deprecated use BIC and IBAN instead of BLZ and KTO */ + @Deprecated public String getBLZ() { return extractString("//PayeeSpecifiedCreditorFinancialInstitution/GermanBankleitzahlID"); } + /** + * @return the sender's account number + * @deprecated use BIC and IBAN instead of BLZ and KTO + */ + @Deprecated + public String getKTO() { + return extractString("//PayeePartyCreditorFinancialAccount/ProprietaryID"); + } + /** * @return the sender's bank's BIC code */ @@ -280,18 +291,17 @@ public class ZUGFeRDImporter { } /** - * @return the sender's bankname + * @return the sender's account IBAN code */ - public String getBankName() { - return extractString("/CrossIndustryInvoice/SupplyChainTradeTransaction/ApplicableHeaderTradeSettlement/SpecifiedTradeSettlementPaymentMeans/PayeeSpecifiedCreditorFinancialInstitution/Name"); - } - public String getIBAN() { return extractString("//PayeePartyCreditorFinancialAccount/IBANID"); } - public String getKTO() { - return extractString("//PayeePartyCreditorFinancialAccount/ProprietaryID"); + /** + * @return the sender's bankname + */ + public String getBankName() { + return extractString("/CrossIndustryInvoice/SupplyChainTradeTransaction/ApplicableHeaderTradeSettlement/SpecifiedTradeSettlementPaymentMeans/PayeeSpecifiedCreditorFinancialInstitution/Name"); } public String getHolder() { From c1d0bbfbf9a5e8a6233c438a3be084b06daa4257 Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Wed, 7 Aug 2019 11:41:35 +0200 Subject: [PATCH 73/82] comment editing and cosmetic improvements --- .../ZUGFeRD/ZUGFeRDImporter.java | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index 639230ed..1a49296c 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -56,28 +56,33 @@ import java.util.logging.Logger; public class ZUGFeRDImporter { /** - * @var if metadata has been found + * if metadata has been found */ private boolean containsMeta = false; /** - * @var the reference (i.e. invoice number) of the sender + * map filenames of additional XML files to their contents */ private HashMap additionalXMLs = new HashMap<>(); /** * Raw XML form of the extracted data - may be directly obtained. */ private byte[] rawXML = null; + /** + * XMP metadata + */ private String xmpString = null; // XMP metadata + /** + * parsed Document + */ private Document document; public ZUGFeRDImporter(String pdfFilename) { - try (InputStream bis = Files.newInputStream(Paths.get(pdfFilename), StandardOpenOption.READ)) { extractLowLevel(bis); } catch (IOException e) { Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); throw new ZUGFeRDExportException(e); - } + } } public ZUGFeRDImporter(InputStream pdfStream) { @@ -133,8 +138,7 @@ public class ZUGFeRDImporter { PDComplexFileSpecification fileSpec = names.get(alias); String filename=fileSpec.getFilename(); /** - * currently (in the release candidate of version 1) only one attached file with - * the name ZUGFeRD-invoice.xml is allowed + * filenames for invoice data (ZUGFeRD v1 and v2, Factur-X) */ if ((filename.equals("ZUGFeRD-invoice.xml") || (filename.equals("zugferd-invoice.xml")) || filename.equals("factur-x.xml"))) { //$NON-NLS-1$ containsMeta = true; @@ -153,10 +157,8 @@ public class ZUGFeRDImporter { // fos.close(); } if (filename.startsWith("additional_data")) { - PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile(); additionalXMLs.put(filename, embeddedFile.toByteArray()); - } } } @@ -176,7 +178,16 @@ public class ZUGFeRDImporter { System.err.println(output); } - private Document getDocument() { return document; } + private Document getDocument() { return document; } + + private void setDocument() throws ParserConfigurationException, IOException, SAXException { + DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance(); + xmlFact.setNamespaceAware(false); + DocumentBuilder builder = xmlFact.newDocumentBuilder(); + ByteArrayInputStream is = new ByteArrayInputStream(rawXML); + is.skip(guessBOMSize(is)); + document = builder.parse(is); + } public void setRawXML(byte[] rawXML) throws IOException { this.rawXML = rawXML; @@ -188,15 +199,6 @@ public class ZUGFeRDImporter { } } - private void setDocument() throws ParserConfigurationException, IOException, SAXException { - DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance(); - xmlFact.setNamespaceAware(false); - DocumentBuilder builder = xmlFact.newDocumentBuilder(); - ByteArrayInputStream is = new ByteArrayInputStream(rawXML); - is.skip(guessBOMSize(is)); - document = builder.parse(is); - } - /** * Skips over a BOM at the beginning of the given ByteArrayInputStream, if one exists. * @param is the ByteArrayInputStream used From 0e57a2bcb7e9aa394f2d47b87b46b894fdc6d62b Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Wed, 7 Aug 2019 13:43:23 +0200 Subject: [PATCH 74/82] remove zombie definition of getBankName --- .../java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index 7b0051f8..e748332c 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -294,7 +294,7 @@ public class ZUGFeRDImporter { /** - * @return the sender's bank name code + * @return the sender's bank name */ public String getBankName() { return extractString("//PayeeSpecifiedCreditorFinancialInstitution/Name"); @@ -307,13 +307,6 @@ public class ZUGFeRDImporter { return extractString("//PayeePartyCreditorFinancialAccount/IBANID"); } - /** - * @return the sender's bankname - */ - public String getBankName() { - return extractString("/CrossIndustryInvoice/SupplyChainTradeTransaction/ApplicableHeaderTradeSettlement/SpecifiedTradeSettlementPaymentMeans/PayeeSpecifiedCreditorFinancialInstitution/Name"); - } - public String getHolder() { return extractString("//SellerTradeParty/Name"); } From eaaf97eb6e1b5327fa6346829cbce0515489106d Mon Sep 17 00:00:00 2001 From: Stefan Schmiedl Date: Wed, 7 Aug 2019 14:53:39 +0200 Subject: [PATCH 75/82] avoid deprecated ZUGFeRDExporter methods In most cases this is achieved by using the corresponding factory methods. Since they have to be set _somehow_, I introduced a new public method `ZUGFeRDExporter.configure` to keep these calls local to the class. This is called once in A3Factory.load(byte[]). The deprecated Exporter setters could now be made private but that could break existing code. --- .../ZUGFeRD/ZUGFeRDExporter.java | 15 ++++++++++- .../ZUGFeRD/ZUGFeRDExporterFromA3Factory.java | 25 ++++--------------- .../org/mustangproject/toecount/Toecount.java | 2 +- .../MustangReaderWriterCustomXMLTest.java | 5 +++- .../ZUGFeRD/MustangReaderWriterEdgeTest.java | 2 +- .../mustangproject/ZUGFeRD/ZF2EdgeTest.java | 3 +-- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java index 5dd999eb..0330c4e4 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java @@ -97,7 +97,7 @@ public class ZUGFeRDExporter implements Closeable { */ protected String producer = "mustangproject"; /** - * Author/Creator attribute for PDF for PDF + * Author/Creator attribute for PDF */ protected String creator = "mustangproject"; /** @@ -709,4 +709,17 @@ public class ZUGFeRDExporter implements Closeable { this.attachZUGFeRDHeaders = attachZUGFeRDHeaders; } + /** + * encapsulate the deprecated setters + * @param zfVersion 1 or 2 + * @param zugferdConformanceLevel BASIC, COMFORT, EN16931, etc. + * @param creator PDF creator + * @param producer PDF producer + */ + public void configure(int zfVersion, ZUGFeRDConformanceLevel zugferdConformanceLevel, String creator, String producer) { + setZUGFeRDVersion(zfVersion); + setZUGFeRDConformanceLevel(zugferdConformanceLevel); + setCreator(creator); + setProducer(producer); + } } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3Factory.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3Factory.java index ffed7bb7..483f174f 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3Factory.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3Factory.java @@ -63,20 +63,9 @@ public class ZUGFeRDExporterFromA3Factory implements IExporterFactory { public ZUGFeRDExporter load(String pdfFilename) throws IOException { ensurePDFIsValidPDFA(new FileDataSource(pdfFilename)); - ZUGFeRDExporter zugFeRDExporter; - PDDocument doc = PDDocument.load(new File(pdfFilename)); - zugFeRDExporter = new ZUGFeRDExporter(doc); - zugFeRDExporter.setZUGFeRDVersion(ZFVersion); - zugFeRDExporter.setZUGFeRDConformanceLevel(zugferdConformanceLevel); - zugFeRDExporter.setCreator(creator); - // Use creator as default for compatibility - zugFeRDExporter.setCreatorTool(creatorTool != null ? creatorTool : creator); - zugFeRDExporter.setProducer(producer); - zugFeRDExporter.setAttachZUGFeRDHeaders(attachZUGFeRDHeaders); - zugFeRDExporter.setPDFA3(ensurePDFisUpgraded); - - return zugFeRDExporter; - + try (FileInputStream pdf = new FileInputStream(pdfFilename)) { + return load(readAllBytes(pdf)); + } } @@ -88,13 +77,9 @@ public class ZUGFeRDExporterFromA3Factory implements IExporterFactory { */ public ZUGFeRDExporter load(byte[] pdfBinary) throws IOException { ensurePDFIsValidPDFA(new ByteArrayDataSource(new ByteArrayInputStream(pdfBinary))); - ZUGFeRDExporter zugFeRDExporter; PDDocument doc = PDDocument.load(pdfBinary); - zugFeRDExporter = new ZUGFeRDExporter(doc); - zugFeRDExporter.setZUGFeRDVersion(ZFVersion); - zugFeRDExporter.setZUGFeRDConformanceLevel(zugferdConformanceLevel); - zugFeRDExporter.setCreator(creator); - zugFeRDExporter.setProducer(producer); + ZUGFeRDExporter zugFeRDExporter = new ZUGFeRDExporter(doc); + zugFeRDExporter.configure(ZFVersion, zugferdConformanceLevel, creator, producer); zugFeRDExporter.setAttachZUGFeRDHeaders(attachZUGFeRDHeaders); zugFeRDExporter.setPDFA3(ensurePDFisUpgraded); diff --git a/src/main/java/org/mustangproject/toecount/Toecount.java b/src/main/java/org/mustangproject/toecount/Toecount.java index 84edf28b..688dcda2 100755 --- a/src/main/java/org/mustangproject/toecount/Toecount.java +++ b/src/main/java/org/mustangproject/toecount/Toecount.java @@ -541,10 +541,10 @@ public class Toecount { // All params are good! continue... ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setProducer("Toecount") + .setZUGFeRDVersion(zfIntVersion) .setCreator(System.getProperty("user.name")).setZUGFeRDConformanceLevel(zfConformanceLevelProfile) .load(pdfName); - ze.setZUGFeRDVersion(zfIntVersion); if (format.equals("fx")) { ze.setFacturX(); } diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java index 42c1a118..e1908c7b 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java @@ -300,7 +300,10 @@ public class MustangReaderWriterCustomXMLTest extends TestCase { try { InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); - ZUGFeRDExporter zea1 = new ZUGFeRDExporterFromA1Factory().setProducer("My Application").setCreator("Test").setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.BASIC) + ZUGFeRDExporter zea1 = new ZUGFeRDExporterFromA1Factory() + .setProducer("My Application") + .setCreator("Test") + .setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.BASIC) .load(SOURCE_PDF); /* 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 = "\n" diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java index db00461a..a104fccf 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java @@ -208,9 +208,9 @@ public class MustangReaderWriterEdgeTest extends MustangReaderTestCase { ZUGFeRDExporter ze = new ZUGFeRDExporterFromA3Factory() .setProducer("My Application") .setCreator(System.getProperty("user.name")) + .setZUGFeRDVersion(1) .ignorePDFAErrors() .load(SOURCE_PDF)) { - ze.setZUGFeRDVersion(1); ze.PDFattachZugferdFile(this); String theXML = new String(ze.getProvider().getXML()); assertTrue(theXML.contains(" Date: Thu, 8 Aug 2019 18:38:54 +0200 Subject: [PATCH 76/82] Update ZF2EdgeTest.java I would not want ZF1 in the test for critical cases zugferd v2 cases --- src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java b/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java index 52425c6b..f4a69812 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java @@ -183,7 +183,7 @@ public class ZF2EdgeTest extends MustangReaderTestCase { ZUGFeRDExporter ze = new ZUGFeRDExporterFromA3Factory() .setProducer("My Application") .setCreator(System.getProperty("user.name")) - .setZUGFeRDVersion(1) + .setZUGFeRDVersion(2) .ignorePDFAErrors() .load(SOURCE_PDF)) { ze.PDFattachZugferdFile(this); From 6cb647cd47ec7aa7ac887457a132610fd9d23b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Fri, 9 Aug 2019 18:44:43 +0200 Subject: [PATCH 77/82] removed testIndicator in migration from v1 to v2 --- .../mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java | 10 +++++++--- src/main/resources/COMFORTtoEN16931.xsl | 7 ++++++- .../migration/reference/ZUGFeRD2-invoice-adjusted.xml | 3 --- .../resources/migration/reference/ZUGFeRD2-invoice.xml | 3 --- .../migration/reference/ZUGFeRD2_COMFORT_Einfach.xml | 4 ---- .../reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml | 3 --- 6 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 4b5f00d2..90d1cf58 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -124,7 +124,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { byte[] res = zugferdData; - StringWriter sw = new StringWriter(); + /*StringWriter sw = new StringWriter(); Document document=null; try { document = DocumentHelper.parseText(new String(zugferdData)); @@ -140,13 +140,17 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { } catch (IOException e) { Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e); } - + */ return res; } private BigDecimal getTotalPrepaid() { - return trans.getTotalPrepaidAmount(); + if (trans.getTotalPrepaidAmount()==null) { + return new BigDecimal(0); + } else { + return trans.getTotalPrepaidAmount(); + } } private BigDecimal getTotalGross() { diff --git a/src/main/resources/COMFORTtoEN16931.xsl b/src/main/resources/COMFORTtoEN16931.xsl index d6eb2e03..c4f974a9 100644 --- a/src/main/resources/COMFORTtoEN16931.xsl +++ b/src/main/resources/COMFORTtoEN16931.xsl @@ -63,7 +63,12 @@ Migrated by Mustangproject XSLT - + + + + + + diff --git a/src/test/resources/migration/reference/ZUGFeRD2-invoice-adjusted.xml b/src/test/resources/migration/reference/ZUGFeRD2-invoice-adjusted.xml index d0c2bf92..770e7dc9 100644 --- a/src/test/resources/migration/reference/ZUGFeRD2-invoice-adjusted.xml +++ b/src/test/resources/migration/reference/ZUGFeRD2-invoice-adjusted.xml @@ -21,9 +21,6 @@ xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"> - - false - urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended diff --git a/src/test/resources/migration/reference/ZUGFeRD2-invoice.xml b/src/test/resources/migration/reference/ZUGFeRD2-invoice.xml index 9502a57d..a1ebb2b3 100644 --- a/src/test/resources/migration/reference/ZUGFeRD2-invoice.xml +++ b/src/test/resources/migration/reference/ZUGFeRD2-invoice.xml @@ -21,9 +21,6 @@ xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"> - - false - urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended diff --git a/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml b/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml index 86566c1b..81432621 100644 --- a/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml +++ b/src/test/resources/migration/reference/ZUGFeRD2_COMFORT_Einfach.xml @@ -50,10 +50,6 @@ Kosten, Verluste bzw. Schäden hätte normalerweise vorhergesehen werden können xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"> - - true - - urn:cen.eu:en16931:2017 diff --git a/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml b/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml index ad6d4ca5..2ee1b6ea 100644 --- a/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml +++ b/src/test/resources/migration/reference/ZUGFeRD2_EXTENDED_Warenrechnung.xml @@ -50,9 +50,6 @@ Kosten, Verluste bzw. Schäden hätte normalerweise vorhergesehen werden können xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"> - - true - urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended From 0708bcf91e92d7457c8d7b1b3240a5316d3d87e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Fri, 9 Aug 2019 18:46:00 +0200 Subject: [PATCH 78/82] re-enable pretty print --- .../java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 90d1cf58..ed19e23f 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -124,7 +124,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { byte[] res = zugferdData; - /*StringWriter sw = new StringWriter(); + StringWriter sw = new StringWriter(); Document document=null; try { document = DocumentHelper.parseText(new String(zugferdData)); @@ -140,7 +140,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { } catch (IOException e) { Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e); } - */ + return res; } From 33a11ad9a1a88bbe121716ac9622621261cb00ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 11 Aug 2019 11:51:52 +0200 Subject: [PATCH 79/82] migrated development documentation to markdown --- doc/development_documentation.md | 91 ++++++++++++++++++ ...cumentation_screenshot_github_settings.png | Bin 0 -> 62318 bytes ...ment_documentation_screenshot_release.png} | Bin 181164 -> 100720 bytes 3 files changed, 91 insertions(+) create mode 100644 doc/development_documentation.md create mode 100644 doc/development_documentation_screenshot_github_settings.png rename doc/{MustangDev.en.odt => development_documentation_screenshot_release.png} (55%) diff --git a/doc/development_documentation.md b/doc/development_documentation.md new file mode 100644 index 00000000..b46f7fe2 --- /dev/null +++ b/doc/development_documentation.md @@ -0,0 +1,91 @@ +##New build + +Target platform is java 1.7 +##Build + +Toecount is now part of the package which can be build with +``` +mvn clean package +``` + +##Test + +`package -Dmaven.surefire.debug="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -Xnoagent -Djava.compiler=NONE"` +can be used as debug configuration goal in eclipse + + +##Deployment +A section in Maven's settings.xml is needed, in Linux (and MacOS) that's at ~/.m2/settings.xml + +As „servers“, enter the following +```xml +   +    +      github +      GITHUB-TOKEN +    +   +``` +The whole settings.xml then looks e.g. like this +```xml + + + + + + + + +      github +      TOKEN +     + + + + + + +``` + +The password is generated on github. +See the following screenshot: + + +Sign in in GitHub and click on the profile picture -> Settings. Now just generate a new token and set the checkboxes from the screenshot. +![screenshot](development_documentation_screenshot_github_settings.png "Screenshot Github Settings") + The Token-ID is the password. + + +##Release + +You will need a git client on the console, if that's available can e.g. be checked with "git --version" . +Change to the root of the repo. + +Change to the project directory and run + * "/usr/local/Cellar/maven/3.5.2/bin/mvn clean install" . If that works you can + * clean the release with „/usr/local/Cellar/maven/3.5.2/bin/mvn release:clean“ and prepare the release with + * "/usr/local/Cellar/maven/3.5.2/bin/mvn release:prepare -DignoreSnapshots=true" and enter the version numbers. + * After that is through you can create a new release via "/usr/local/Cellar/maven/3.5.2/bin/mvn release:perform -Darguments="-Dmaven.javadoc.skip=true".This will also update the maven repo. + + ![screenshot](development_documentation_screenshot_release.png "Screenshot Release") + + +Afterwards you can access the release page and update the documentation, e.g. upload the jar, the jar javadoc and ZugferdDev. You can also enter a changelog and a better title. + + +##Release process + * Update documentation + * write/translate announcement + * release via/for mvn + * Publish a github release + * update mustangproject.org RE + * version number and release date + * sample file? + * Deployment jar + * put announcement on usegroup + * email the mailing list + * freshcode.club + \ No newline at end of file diff --git a/doc/development_documentation_screenshot_github_settings.png b/doc/development_documentation_screenshot_github_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..ff1ba41eedef715ef275e91996ec36ac1e915cd1 GIT binary patch literal 62318 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 T-rY3)u0uga1zIj``u=|a3$jbl literal 0 HcmV?d00001 diff --git a/doc/MustangDev.en.odt b/doc/development_documentation_screenshot_release.png similarity index 55% rename from doc/MustangDev.en.odt rename to doc/development_documentation_screenshot_release.png index b9b50a219763d8478a8299628d0df671f22d8a45..a7ea70740f134496a04cb3b6462737811608ad98 100644 GIT binary patch delta 15 WcmZ3}&i!E$Tk`_p?F)n%3pxQe7zSYg delta 81089 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�`4{+QZN=4eV2$}jmPZO{U`s>tNa5Vg3VFjQ2j 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 From 0cfde40dbd4795608bce8a3c8a9014860d4c6c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 11 Aug 2019 11:53:12 +0200 Subject: [PATCH 80/82] corrected headlines --- doc/development_documentation.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/doc/development_documentation.md b/doc/development_documentation.md index b46f7fe2..5d8dc9e6 100644 --- a/doc/development_documentation.md +++ b/doc/development_documentation.md @@ -1,20 +1,22 @@ -##New build +## New build Target platform is java 1.7 -##Build + +## Build Toecount is now part of the package which can be build with ``` mvn clean package ``` -##Test +## Test `package -Dmaven.surefire.debug="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -Xnoagent -Djava.compiler=NONE"` can be used as debug configuration goal in eclipse -##Deployment +## Deployment + A section in Maven's settings.xml is needed, in Linux (and MacOS) that's at ~/.m2/settings.xml As „servers“, enter the following @@ -59,7 +61,7 @@ Sign in in GitHub and click on the profile picture -> Settings. Now just generat The Token-ID is the password. -##Release +## Release You will need a git client on the console, if that's available can e.g. be checked with "git --version" . Change to the root of the repo. @@ -76,7 +78,8 @@ Change to the project directory and run Afterwards you can access the release page and update the documentation, e.g. upload the jar, the jar javadoc and ZugferdDev. You can also enter a changelog and a better title. -##Release process +## Release process + * Update documentation * write/translate announcement * release via/for mvn From 75151402aefa7aaa1ef88b8bd0cd199965062480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sta=CC=88rk?= Date: Sun, 11 Aug 2019 12:10:02 +0200 Subject: [PATCH 81/82] corrected tests for ZF2 export: the one for issue #102 fails, which is correct until it is solved. --- src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java b/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java index f4a69812..830e657d 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java @@ -116,7 +116,7 @@ public class ZF2EdgeTest extends MustangReaderTestCase { 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 balloonProduct = new Product("", "Bestellerweiterung für E&F Umbau", "C62", new BigDecimal("19.000000"));// test for issue 102 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); @@ -188,7 +188,7 @@ public class ZF2EdgeTest extends MustangReaderTestCase { .load(SOURCE_PDF)) { ze.PDFattachZugferdFile(this); String theXML = new String(ze.getProvider().getXML()); - assertTrue(theXML.contains(" Date: Sun, 11 Aug 2019 18:47:36 +0200 Subject: [PATCH 82/82] closes #102 --- History.md | 6 + doc/development_documentation.md | 7 +- .../ZUGFeRD/ZUGFeRD2PullProvider.java | 103 +++++++++++++----- .../mustangproject/ZUGFeRD/ZF2EdgeTest.java | 3 +- 4 files changed, 86 insertions(+), 33 deletions(-) diff --git a/History.md b/History.md index fdfa3e44..81ce7e8c 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +1.7.4 +===== + +- #102 XML entities for ZF2 export + + 1.7.3 ===== 2019-08-01 diff --git a/doc/development_documentation.md b/doc/development_documentation.md index 5d8dc9e6..f9439a5e 100644 --- a/doc/development_documentation.md +++ b/doc/development_documentation.md @@ -11,9 +11,12 @@ mvn clean package ## Test -`package -Dmaven.surefire.debug="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -Xnoagent -Djava.compiler=NONE"` -can be used as debug configuration goal in eclipse +`package -Dmaven.surefire.debug="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8001 -Xnoagent -Djava.compiler=NONE"` +can be used as debug configuration goal in Eclipse. In that case you can set breakpoints in tests. +## Validate + +[ZUV](https://github.com/ZUGFeRD/ZUV/) can be used to validate generated files. ## Deployment diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index ed19e23f..bd8a70ff 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -201,6 +201,46 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { public String getProfile() { return "urn:cen.eu:en16931:2017"; } + + public static String encodeXML(CharSequence s) { + StringBuilder sb = new StringBuilder(); + int len = s.length(); + for (int i=0;i= 0xd800 && c <= 0xdbff && i + 1 < len) { + c = ((c-0xd7c0)<<10) | (s.charAt(++i)&0x3ff); // UTF16 decode + } + if (c < 0x80) { // ASCII range: test most common case first + if (c < 0x20 && (c != '\t' && c != '\r' && c != '\n')) { + // Illegal XML character, even encoded. Skip or substitute + sb.append("�"); // Unicode replacement character + } else { + switch(c) { + case '&': sb.append("&"); break; + case '>': sb.append(">"); break; + case '<': sb.append("<"); break; + // Uncomment next two if encoding for an XML attribute +// case '\'' sb.append("'"); break; +// case '\"' sb.append("""); break; + // Uncomment next three if you prefer, but not required +// case '\n' sb.append(" "); break; +// case '\r' sb.append(" "); break; +// case '\t' sb.append(" "); break; + + default: sb.append((char)c); + } + } + } else if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) { + // Illegal XML character, even encoded. Skip or substitute + sb.append("�"); // Unicode replacement character + } else { + sb.append("&#x"); + sb.append(Integer.toHexString(c)); + sb.append(';'); + } + } + return sb.toString(); + } @Override public void generateXML(IZUGFeRDExportableTransaction trans) { @@ -210,7 +250,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { String senderReg = ""; if (trans.getOwnOrganisationFullPlaintextInfo() != null) { senderReg = "" + "\n" + " \n" - + trans.getOwnOrganisationFullPlaintextInfo() + " \n" + + encodeXML(trans.getOwnOrganisationFullPlaintextInfo()) + " \n" + "REG\n" + "\n"; } @@ -232,7 +272,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " " + trans.getNumber() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(trans.getNumber()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // + " RECHNUNG\n" //$NON-NLS-1$ + " 380\n" //$NON-NLS-1$ + " " //$NON-NLS-1$ @@ -268,8 +308,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { // + " 4012345001235\n" // + " KR3M\n" // + " 55T01\n" - + " " + currentItem.getProduct().getName() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " " + currentItem.getProduct().getDescription() //$NON-NLS-1$ + + " " + encodeXML(currentItem.getProduct().getName()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(currentItem.getProduct().getDescription()) //$NON-NLS-1$ + "\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ @@ -277,7 +317,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { + " \n" //$NON-NLS-1$ + " " + priceFormat(currentItem.getPrice()) //$NON-NLS-1$ + "\n" //$NON-NLS-1$ //currencyID=\"EUR\" - + " 1.0000\n" //$NON-NLS-1$ // + " \n" // + " false\n" @@ -288,13 +328,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { + " \n" //$NON-NLS-1$ + " " + priceFormat(currentItem.getPrice()) //$NON-NLS-1$ + "\n" //$NON-NLS-1$ // currencyID=\"EUR\" - + " 1.0000\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " " //$NON-NLS-1$ //$NON-NLS-2$ + + " " //$NON-NLS-1$ //$NON-NLS-2$ + quantityFormat(currentItem.getQuantity()) + "\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ @@ -315,34 +355,34 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { xml = xml + " \n"; //$NON-NLS-1$ if (trans.getReferenceNumber() != null) { - xml = xml + " " + trans.getReferenceNumber() + "\n"; + xml = xml + " " + encodeXML(trans.getReferenceNumber()) + "\n"; } xml = xml + " \n" //$NON-NLS-1$ // + " 4000001123452\n" - + " " + trans.getOwnOrganisationName() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(trans.getOwnOrganisationName()) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ if ((trans.getOwnVATID()!=null)&&(trans.getOwnOrganisationName()!=null)) { xml = xml + " \n" + " " - + trans.getOwnVATID() + "\n" + " " - + trans.getOwnOrganisationName() + "\n" + + encodeXML(trans.getOwnVATID()) + "\n" + " " + + encodeXML(trans.getOwnOrganisationName()) + "\n" + " "; } if (trans.getOwnContact() != null) { - xml = xml + "\n" + " " + trans.getOwnContact().getName() + xml = xml + "\n" + " " + encodeXML(trans.getOwnContact().getName()) + "\n"; if (trans.getOwnContact().getPhone() != null) { xml = xml + " \n" + " " - + trans.getOwnContact().getPhone() + "\n" + + encodeXML(trans.getOwnContact().getPhone()) + "\n" + " \n"; } if (trans.getOwnContact().getEMail() != null) { xml = xml + " \n" + " " - + trans.getOwnContact().getEMail() + "\n" + + encodeXML(trans.getOwnContact().getEMail()) + "\n" + " \n"; } xml = xml + " "; @@ -350,33 +390,33 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { } xml = xml + " \n" + " " - + trans.getOwnZIP() + "\n" + " " - + trans.getOwnStreet() + "\n" + " " + trans.getOwnLocation() - + "\n" + " " + trans.getOwnCountry() + + encodeXML(trans.getOwnZIP()) + "\n" + " " + + encodeXML(trans.getOwnStreet()) + "\n" + " " + encodeXML(trans.getOwnLocation()) + + "\n" + " " + encodeXML(trans.getOwnCountry()) + "\n" + " \n" + " \n" //$NON-NLS-1$ - + " " + trans.getOwnTaxID() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(trans.getOwnTaxID()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " " + trans.getOwnVATID() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(trans.getOwnVATID()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ // + " GE2020211\n" // + " 4000001987658\n" - + " " + trans.getRecipient().getName() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(trans.getRecipient().getName()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // + " \n" // + " xxx\n" // + " \n" + " \n" //$NON-NLS-1$ - + " " + trans.getRecipient().getZIP() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " " + trans.getRecipient().getStreet() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " " + trans.getRecipient().getLocation() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " " + trans.getRecipient().getCountry() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(trans.getRecipient().getZIP()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(trans.getRecipient().getStreet()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(trans.getRecipient().getLocation()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(trans.getRecipient().getCountry()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " \n"; //$NON-NLS-1$ if (trans.getRecipient().getVATID() != null) { xml += " \n" //$NON-NLS-1$ - + " " + trans.getRecipient().getVATID() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(trans.getRecipient().getVATID()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " \n"; //$NON-NLS-1$ } xml += " \n" //$NON-NLS-1$ @@ -396,7 +436,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { * " \n" */ + " \n" + " \n" //$NON-NLS-2$ - + " " + trans.getNumber() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(trans.getNumber()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " EUR\n"; //$NON-NLS-1$ for (IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) { @@ -404,11 +444,14 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { + " 42\n" //$NON-NLS-1$ + " Überweisung\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " " + payment.getOwnIBAN() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " " + payment.getOwnKto() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ - + " \n" //$NON-NLS-1$ + + " " + encodeXML(payment.getOwnIBAN()) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ + if (payment.getOwnKto()!=null) { + xml+= " " + encodeXML(payment.getOwnKto()) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ + + } + xml+= " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " " + payment.getOwnBIC() + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " " + encodeXML(payment.getOwnBIC()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // + " "+trans.getOwnBankName()+"\n" //$NON-NLS-1$ // //$NON-NLS-2$ + " \n" //$NON-NLS-1$ diff --git a/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java b/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java index 830e657d..a4f4dc13 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java @@ -116,7 +116,7 @@ public class ZF2EdgeTest extends MustangReaderTestCase { 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"));// test for issue 102 + Product balloonProduct = new Product("", "Bestellerweiterung für E&F Umbau", "C62", new BigDecimal("19.000000"));// test for issue 103 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); @@ -167,6 +167,7 @@ public class ZF2EdgeTest extends MustangReaderTestCase { return new TestSuite(ZF2EdgeTest.class); } + // //////// TESTS ////////////////////////////////////////////////////////////////////////////////////////// /**