diff --git a/library/src/main/java/org/mustangproject/EStandard.java b/library/src/main/java/org/mustangproject/EStandard.java new file mode 100644 index 00000000..69c43648 --- /dev/null +++ b/library/src/main/java/org/mustangproject/EStandard.java @@ -0,0 +1,6 @@ +package org.mustangproject; + +public enum EStandard { + facturx, orderx, zugferd, cii, ubl + +} diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/OXPullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/OXPullProvider.java new file mode 100644 index 00000000..95035e8c --- /dev/null +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/OXPullProvider.java @@ -0,0 +1,592 @@ +/** + * ********************************************************************* + *

+ * 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 org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; +import org.mustangproject.EStandard; +import org.mustangproject.FileAttachment; +import org.mustangproject.XMLTools; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.Base64; +import java.util.Date; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static org.mustangproject.ZUGFeRD.ZUGFeRDDateFormat.DATE; +import static org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants.CORRECTEDINVOICE; +import static org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants.CATEGORY_CODES_WITH_EXEMPTION_REASON; + +public class OXPullProvider extends ZUGFeRD2PullProvider implements IXMLProvider { + + protected IExportableTransaction trans; + protected TransactionCalculator calc; + private String paymentTermsDescription; + protected Profile profile = Profiles.getByName(EStandard.orderx,"basic", 1); + + + @Override + public void generateXML(IExportableTransaction trans) { + this.trans = trans; + this.calc = new TransactionCalculator(trans); + + boolean hasDueDate = false; + final SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy"); + + String exemptionReason = ""; + + if (trans.getPaymentTermDescription() != null) { + paymentTermsDescription = trans.getPaymentTermDescription(); + } + + if ((paymentTermsDescription == null) && (trans.getDocumentCode() != CORRECTEDINVOICE)/* && (trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE)*/) { + paymentTermsDescription = "Zahlbar ohne Abzug bis " + germanDateFormat.format(trans.getDueDate()); + + } + + String senderReg = ""; + if (trans.getOwnOrganisationFullPlaintextInfo() != null) { + senderReg = "" + "\n" + " \n" + + XMLTools.encodeXML(trans.getOwnOrganisationFullPlaintextInfo()) + " \n" + + "REG\n" + "\n"; + + } + + String rebateAgreement = ""; + if (trans.rebateAgreementExists()) { + rebateAgreement = "\n" + " " + + "Es bestehen Rabatt- und Bonusvereinbarungen.\n" + + "AAK\n" + "\n"; + } + + String subjectNote = ""; + if (trans.getSubjectNote() != null) { + subjectNote = "\n" + " " + + XMLTools.encodeXML(trans.getSubjectNote()) + "\n" + + "\n"; + } + + String typecode = "220"; + /*if (trans.getDocumentCode() != null) { + typecode = trans.getDocumentCode(); + }*/ + String notes = ""; + if (trans.getNotes() != null) { + for (final String currentNote : trans.getNotes()) { + notes = notes + "" + XMLTools.encodeXML(currentNote) + ""; + + } + } + String xml = "\n" + + + "\n" + // + " + // xsi:schemaLocation=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100 + // ../Schema/ZUGFeRD1p0.xsd\"" + + " \n" + // + " + // "+testBooleanStr+"\n" + // + + "\n" + + "A1\n" + + "\n" + + " \n" + + " " + getProfile().getID() + "\n" + + " \n" + + " \n" + + " \n" + + " " + XMLTools.encodeXML(trans.getNumber()) + "\n" + // + " RECHNUNG\n" + // + " 380\n" + + " " + typecode + "\n" + + " " + + DATE.udtFormat(trans.getIssueDate()) + "\n" // date + + notes + + subjectNote + + rebateAgreement + + senderReg + + + " \n" + + " \n"; + int lineID = 0; + for (final IZUGFeRDExportableItem currentItem : trans.getZFItems()) { + lineID++; + if (currentItem.getProduct().getTaxExemptionReason() != null) { + // exemptionReason = "" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + ""; + } + notes = ""; + if (currentItem.getNotes() != null) { + for (final String currentNote : currentItem.getNotes()) { + notes = notes + "" + XMLTools.encodeXML(currentNote) + ""; + + } + } + final LineCalculator lc = new LineCalculator(currentItem); + xml = xml + " \n" + + " \n" + + " " + lineID + "\n" + + notes + + " \n" + + + " \n"; + // + " 4012345001235\n" + if (currentItem.getProduct().getSellerAssignedID() != null) { + xml = xml + " " + + XMLTools.encodeXML(currentItem.getProduct().getSellerAssignedID()) + "\n"; + } + if (currentItem.getProduct().getBuyerAssignedID() != null) { + xml = xml + " " + + XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "\n"; + } + String allowanceChargeStr = ""; + if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) { + for (final IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) { + allowanceChargeStr += getAllowanceChargeStr(allowance, currentItem); + } + } + if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) { + for (final IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) { + allowanceChargeStr += getAllowanceChargeStr(charge, currentItem); + + } + } + + + xml = xml + " " + XMLTools.encodeXML(currentItem.getProduct().getName()) + "\n" + + " " + XMLTools.encodeXML(currentItem.getProduct().getDescription()) + + "\n" + + " \n" + + + " \n"; + /* if (currentItem.getReferencedDocuments() != null) { + for (IReferencedDocument currentReferencedDocument : currentItem.getReferencedDocuments()) { + xml = xml + "\n" + + "" + XMLTools.encodeXML(currentReferencedDocument.getIssuerAssignedID()) + "\n" + + "" + XMLTools.encodeXML(currentReferencedDocument.getTypeCode()) + "\n" + + "" + XMLTools.encodeXML(currentReferencedDocument.getReferenceTypeCode()) + "\n" + + "\n"; + + + } + + }*/ + if (currentItem.getBuyerOrderReferencedDocumentLineID() != null) { + xml = xml + " \n" + + " " + XMLTools.encodeXML(currentItem.getBuyerOrderReferencedDocumentLineID()) + "\n" + + " \n"; + + } + xml = xml + " \n" + + " " + priceFormat(lc.getPriceGross()) + + "\n" //currencyID=\"EUR\" + + "" + quantityFormat(currentItem.getBasisQuantity()) + "\n" + + allowanceChargeStr + // + " \n" + // + " false\n" + // + " 0.6667\n" + // + " Rabatt\n" + // + " \n" + + " \n" + + " \n" + + " " + priceFormat(lc.getPrice()) + + "\n" // currencyID=\"EUR\" + + " " + quantityFormat(currentItem.getBasisQuantity()) + "\n" + + " \n" + + " \n" + + + " \n" + + " " + + quantityFormat(currentItem.getQuantity()) + "\n" + + " \n" + + " \n" + + " \n" + + " VAT\n" + + exemptionReason + + " " + currentItem.getProduct().getTaxCategoryCode() + "\n" + + + " " + + vatFormat(currentItem.getProduct().getVATPercent()) + "\n" + + " \n"; + if ((currentItem.getDetailedDeliveryPeriodFrom() != null) || (currentItem.getDetailedDeliveryPeriodTo() != null)) { + xml = xml + ""; + if (currentItem.getDetailedDeliveryPeriodFrom() != null) { + xml = xml + "" + DATE.udtFormat(currentItem.getDetailedDeliveryPeriodFrom()) + ""; + } + if (currentItem.getDetailedDeliveryPeriodTo() != null) { + xml = xml + "" + DATE.udtFormat(currentItem.getDetailedDeliveryPeriodTo()) + ""; + } + xml = xml + ""; + + } + + xml = xml + " \n" + + " " + currencyFormat(lc.getItemTotalNetAmount()) + + "\n" // currencyID=\"EUR\" + + " \n"; + /* if (currentItem.getAdditionalReferencedDocumentID() != null) { + xml = xml + " " + currentItem.getAdditionalReferencedDocumentID() + "130\n"; + + }*/ + xml = xml + " \n" + + " \n"; + + } + + xml = xml + " \n"; + if (trans.getReferenceNumber() != null) { + xml = xml + " " + XMLTools.encodeXML(trans.getReferenceNumber()) + "\n"; + + } + xml = xml + " \n" + + getTradePartyAsXML(trans.getSender(), true, false) + + " \n" + + " \n"; + // + " GE2020211\n" + // + " 4000001987658\n" + + xml += getTradePartyAsXML(trans.getRecipient(), false, false); + xml += " \n"; + + if (trans.getSellerOrderReferencedDocumentID() != null) { + xml = xml + " \n" + + " " + + XMLTools.encodeXML(trans.getSellerOrderReferencedDocumentID()) + "\n" + + " \n"; + } + if (trans.getBuyerOrderReferencedDocumentID() != null) { + xml = xml + " \n" + + " " + + XMLTools.encodeXML(trans.getBuyerOrderReferencedDocumentID()) + "\n" + + " \n"; + } + if (trans.getContractReferencedDocument() != null) { + xml = xml + " \n" + + " " + + XMLTools.encodeXML(trans.getContractReferencedDocument()) + "\n" + + " \n"; + } + + // Additional Documents of XRechnung (Rechnungsbegruendende Unterlagen - BG-24 XRechnung) + if (trans.getAdditionalReferencedDocuments() != null) { + for (final FileAttachment f : trans.getAdditionalReferencedDocuments()) { + final String documentContent = new String(Base64.getEncoder().encodeToString(f.getData())); + xml = xml + " \n" + + " " + f.getFilename() + "\n" + + " 916\n" + + " " + f.getDescription() + "\n" + + " " + documentContent + "\n" + + " \n"; + } + } + + if (trans.getSpecifiedProcuringProjectID() != null) { + xml = xml + " \n" + + " " + + XMLTools.encodeXML(trans.getSpecifiedProcuringProjectID()) + "\n"; + if (trans.getSpecifiedProcuringProjectName() != null) { + xml += " " + XMLTools.encodeXML(trans.getSpecifiedProcuringProjectName()) + "\n"; + } + xml += " \n"; + } + xml = xml + " \n" + + " \n"; + if (this.trans.getDeliveryAddress() != null) { + xml += "" + + getTradePartyAsXML(this.trans.getDeliveryAddress(), false, true) + + ""; + } +/* + xml += " \n" + + " "; + + if (trans.getDeliveryDate() != null) { + xml += DATE.udtFormat(trans.getDeliveryDate()); + } else { + throw new IllegalStateException("No delivery date provided"); + } + xml += "\n"; + xml += " \n" + + */ + /* + * + " \n" + + * " 20130603\n" + + * " 2013-51112\n" + + * " \n" + */ + xml+= " \n" + " \n" + // + " " + XMLTools.encodeXML(trans.getNumber()) + "\n" + + " " + trans.getCurrency() + "\n"; + + if (trans.getTradeSettlementPayment() != null) { + for (final IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) { + if (payment != null) { + hasDueDate = true; + // xml += payment.getSettlementXML(); + } + } + } + if (trans.getTradeSettlement() != null) { + for (final IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { + if (payment != null) { + if (payment instanceof IZUGFeRDTradeSettlementPayment) { + hasDueDate = true; + } + // xml += payment.getSettlementXML(); + } + } + } + if ((trans.getDocumentCode() == CORRECTEDINVOICE)/*||(trans.getDocumentCode() == DocumentCodeTypeConstants.CREDITNOTE)*/) { + hasDueDate = false; + } + + final Map VATPercentAmountMap = calc.getVATPercentAmountMap(); + for (final BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { + final VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); + if (amount != null) { + final String amountCategoryCode = amount.getCategoryCode(); + final boolean displayExemptionReason = CATEGORY_CODES_WITH_EXEMPTION_REASON.contains(amountCategoryCode); + /* xml += " \n" + + " " + currencyFormat(amount.getCalculated()) + + "\n" //currencyID=\"EUR\" + + " VAT\n" + + (displayExemptionReason ? exemptionReason : "") + + " " + currencyFormat(amount.getBasis()) + "\n" // currencyID=\"EUR\" + + " " + amountCategoryCode + "\n" + + " " + + vatFormat(currentTaxPercent) + "\n" + " \n"; + + */ + } + } + if ((trans.getDetailedDeliveryPeriodFrom() != null) || (trans.getDetailedDeliveryPeriodTo() != null)) { + xml = xml + ""; + if (trans.getDetailedDeliveryPeriodFrom() != null) { + xml = xml + "" + DATE.udtFormat(trans.getDetailedDeliveryPeriodFrom()) + ""; + } + if (trans.getDetailedDeliveryPeriodTo() != null) { + xml = xml + "" + DATE.udtFormat(trans.getDetailedDeliveryPeriodTo()) + ""; + } + xml = xml + ""; + + + } + + if ((trans.getZFCharges() != null) && (trans.getZFCharges().length > 0)) { + + for (final BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { + if (calc.getChargesForPercent(currentTaxPercent).compareTo(BigDecimal.ZERO) != 0) { + + + xml = xml + " \n" + + " \n" + + " true\n" + + " \n" + + " " + currencyFormat(calc.getChargesForPercent(currentTaxPercent)) + "\n" + + " " + XMLTools.encodeXML(calc.getChargeReasonForPercent(currentTaxPercent)) + "\n" + + " \n" + + " VAT\n" + + " " + VATPercentAmountMap.get(currentTaxPercent).getCategoryCode() + "\n" + + " " + vatFormat(currentTaxPercent) + "\n" + + " \n" + + " \n"; + + } + } + + } + + if ((trans.getZFAllowances() != null) && (trans.getZFAllowances().length > 0)) { + for (final BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { + if (calc.getAllowancesForPercent(currentTaxPercent).compareTo(BigDecimal.ZERO) != 0) { + xml = xml + " \n" + + " \n" + + " false\n" + + " \n" + + " " + currencyFormat(calc.getAllowancesForPercent(currentTaxPercent)) + "\n" + + " " + XMLTools.encodeXML(calc.getAllowanceReasonForPercent(currentTaxPercent)) + "\n" + + " \n" + + " VAT\n" + + " " + VATPercentAmountMap.get(currentTaxPercent).getCategoryCode() + "\n" + + " " + vatFormat(currentTaxPercent) + "\n" + + " \n" + + " \n"; + } + } + } + + + if ((trans.getPaymentTerms() == null) && ((paymentTermsDescription != null) || (trans.getTradeSettlement() != null) || (hasDueDate))) { + xml = xml + "\n"; + + if (paymentTermsDescription != null) { + xml = xml + "" + paymentTermsDescription + "\n"; + } + + if (trans.getTradeSettlement() != null) { + for (final IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { + if ((payment != null) && (payment instanceof IZUGFeRDTradeSettlementDebit)) { + // xml += payment.getPaymentXML(); + } + } + } + + if (hasDueDate && (trans.getDueDate() != null)) { + xml = xml + " " // $NON-NLS-2$ + + DATE.udtFormat(trans.getDueDate()) + + "\n";// 20130704 + + } + xml = xml + " \n"; + } else { + xml = xml + buildPaymentTermsXml(); + } + + + final String allowanceTotalLine = "" + currencyFormat(calc.getAllowancesForPercent(null)) + ""; + + final String chargesTotalLine = "" + currencyFormat(calc.getChargesForPercent(null)) + ""; + + xml = xml + " \n" + + " " + currencyFormat(calc.getTotal()) + "\n" + + chargesTotalLine + + allowanceTotalLine + + " " + currencyFormat(calc.getTaxBasis()) + "\n" + // // + // currencyID=\"EUR\" + + " " + + currencyFormat(calc.getGrandTotal().subtract(calc.getTaxBasis())) + "\n" + + " " + currencyFormat(calc.getGrandTotal()) + "\n" + // // + // currencyID=\"EUR\" + //+ " " + currencyFormat(calc.getTotalPrepaid()) + "\n" + //+ " " + currencyFormat(calc.getGrandTotal().subtract(calc.getTotalPrepaid())) + "\n" + + " \n"; + if (trans.getInvoiceReferencedDocumentID() != null) { + xml = xml + " \n" + + " " + + XMLTools.encodeXML(trans.getInvoiceReferencedDocumentID()) + "\n"; + if (trans.getInvoiceReferencedIssueDate() != null) { + xml += "" + + DATE.qdtFormat(trans.getInvoiceReferencedIssueDate()) + + "\n"; + } + xml += " \n"; + } + + xml = xml + " \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" + + ""; + + final byte[] zugferdRaw; + try { + zugferdRaw = xml.getBytes("UTF-8"); + + zugferdData = XMLTools.removeBOM(zugferdRaw); + } catch (final UnsupportedEncodingException e) { + Logger.getLogger(OXPullProvider.class.getName()).log(Level.SEVERE, null, e); + } + } + + + @Override + public void setProfile(Profile p) { + profile = p; + } + + @Override + public Profile getProfile() { + return profile; + } + + private String buildPaymentTermsXml() { + + final IZUGFeRDPaymentTerms paymentTerms = trans.getPaymentTerms(); + if (paymentTerms == null) { + return ""; + } + String paymentTermsXml = ""; + + final IZUGFeRDPaymentDiscountTerms discountTerms = paymentTerms.getDiscountTerms(); + final Date dueDate = paymentTerms.getDueDate(); + if (dueDate != null && discountTerms != null && discountTerms.getBaseDate() != null) { + throw new IllegalStateException( + "if paymentTerms.dueDate is specified, paymentTerms.discountTerms.baseDate has not to be specified"); + } + paymentTermsXml += "" + paymentTerms.getDescription() + ""; + if (dueDate != null) { + paymentTermsXml += ""; + paymentTermsXml += DATE.udtFormat(dueDate); + paymentTermsXml += ""; + } + + if (discountTerms != null) { + paymentTermsXml += ""; + final String currency = trans.getCurrency(); + final String basisAmount = currencyFormat(calc.getGrandTotal()); + paymentTermsXml += "" + basisAmount + ""; + paymentTermsXml += "" + discountTerms.getCalculationPercentage().toString() + + ""; + + if (discountTerms.getBaseDate() != null) { + final Date baseDate = discountTerms.getBaseDate(); + paymentTermsXml += ""; + paymentTermsXml += DATE.udtFormat(baseDate); + paymentTermsXml += ""; + + paymentTermsXml += "" + + discountTerms.getBasePeriodMeasure() + ""; + } + + paymentTermsXml += ""; + } + + paymentTermsXml += ""; + return paymentTermsXml; + } + +} diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java b/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java index f91a6979..721500b3 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java @@ -20,6 +20,8 @@ */ package org.mustangproject.ZUGFeRD; +import org.mustangproject.EStandard; + import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -41,18 +43,41 @@ public class Profiles { }).collect(Collectors.toMap(data -> (String) data[0], data -> (Profile) data[1])); + static Map ox1Map = Stream.of(new Object[][]{ + {"BASIC", new Profile("BASIC", "urn:order-x.eu:1p0:basic")}, + {"COMFORT", new Profile("COMFORT", "urn:order-x.eu:1p0:comfort")}, + {"EXTENDED", new Profile("EXTENDED", "urn:order-x.eu:1p0:extended")}, + }).collect(Collectors.toMap(data -> (String) data[0], data -> (Profile) data[1])); + + + public static Profile getByName(EStandard standard, String name, int version) { + if (standard != EStandard.orderx) { + return getByName(name, version); + } else { + Profile result = null; + result = ox1Map.get(name.toUpperCase()); + if (result == null) { + throw new RuntimeException("Profile not found"); + } + return result; + } + } + public static Profile getByName(String name, int version) { - Profile result=null; - if (version==1) { - result=zf1Map.get(name.toUpperCase()); + Profile result = null; + if (version == 1) { + result = zf1Map.get(name.toUpperCase()); } else { - result=zf2Map.get(name.toUpperCase()); + result = zf2Map.get(name.toUpperCase()); + } + if (result == null) { + throw new RuntimeException("Profile not found"); } - if (result==null) { throw new RuntimeException("Profile not found"); } return result; } + public static Profile getByName(String name) { return getByName(name, ZUGFeRDExporterFromA3.DefaultZUGFeRDVersion); } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/OXTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/OXTest.java new file mode 100644 index 00000000..a1ff5aee --- /dev/null +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/OXTest.java @@ -0,0 +1,299 @@ + +/** ********************************************************************** + * + * 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.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class OXTest extends MustangReaderTestCase implements IExportableTransaction { + final String TARGET_PDF = "./target/testout-OX.pdf"; + final String TARGET_XML = "./target/testout-OX.xml"; + + protected class EdgeProduct implements IZUGFeRDExportableProduct { + private String description, name, unit; + + public EdgeProduct(String description, String name, String unit) { + super(); + this.description = description; + this.name = name; + this.unit = unit; + } + + @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 BigDecimal.ZERO; + } + + @Override + public boolean isIntraCommunitySupply() { + return true; // simulate intra community supply + } + } + + protected class DebitPayment implements IZUGFeRDTradeSettlementDebit { + + @Override + public String getIBAN() { + return "DE540815"; + } + + @Override + public String getMandate() { + return "DE99XX12345"; + } + + } + + @Override + public IZUGFeRDTradeSettlement[] getTradeSettlement() { + IZUGFeRDTradeSettlement[] payments = new DebitPayment[1]; + payments[0] = new DebitPayment(); + return payments; + } + + @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 IZUGFeRDExportableTradeParty getSender() { + return new SenderTradeParty(); + } + + @Override + public String getOwnTaxID() { + return "22/815/0815/4"; + } + + @Override + public String getOwnVATID() { + return "DE136695976"; + } + + @Override + public String getOwnZIP() { + return "12345"; + } + + @Override + public IZUGFeRDExportableTradeParty getRecipient() { + return new RecipientTradeParty(); + } + + @Override + public IZUGFeRDExportableTradeParty getDeliveryAddress() { + return new RecipientTradeParty(); + } + + @Override + public String getOwnOrganisationFullPlaintextInfo() { + return null; + } + + @Override + public String getCurrency() { + return "USD"; + } + + @Override + public IZUGFeRDExportableItem[] getZFItems() { + Item[] allItems = new Item[3]; + EdgeProduct designProduct = new EdgeProduct("", "Künstlerische Gestaltung (Stunde): Einer Beispielrechnung", + "HUR"); + EdgeProduct balloonProduct = new EdgeProduct("", "Bestellerweiterung für E&F Umbau", "C62");// test for issue + // 103 + EdgeProduct airProduct = new EdgeProduct("", "Heiße Luft pro Liter", "LTR"); + + Item design=new Item(new BigDecimal("160"), new BigDecimal("1"), designProduct); + design.setAddReference("1825"); + allItems[0] = design; + 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 OXTest(String testName) { + super(testName); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() { + return new TestSuite(OXTest.class); + } + + // //////// TESTS + // ////////////////////////////////////////////////////////////////////////////////////////// + + /** + * The exporter test bases on @{code + * ./src/test/MustangGnuaccountingBeispielRE-20170509_505PDFA3.pdf}, adds + * metadata, writes to @{code ./target/testout-*} and then imports to check the + * values. + */ + public void testOXExport() { + + // the writing part + + try (InputStream SOURCE_PDF = this.getClass() + .getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); + + OXExporterFromA1 oe = new OXExporterFromA1().setProducer("My Application") + .setCreator(System.getProperty("user.name")).setZUGFeRDVersion(1).ignorePDFAErrors() + .load(SOURCE_PDF)) { + oe.setTransaction(this); + String theXML = new String(oe.getProvider().getXML(), StandardCharsets.UTF_8); + assertTrue(theXML.contains("59")); + assertTrue(zi.getUTF8().contains("")); + assertTrue(zi.getUTF8().contains("DE540815")); + assertTrue(zi.getUTF8().contains("DE99XX12345")); + assertFalse(zi.getUTF8().contains("")); + assertFalse(zi.getUTF8().contains("EUR")); + assertTrue(zi.getUTF8().contains("USD"));//currency should be USD, test for #150 + + // Reading ZUGFeRD + assertEquals("496.00", zi.getAmount()); + assertEquals(zi.getHolder(), getOwnOrganisationName()); + assertEquals(zi.getForeignReference(), getNumber()); + + + } + +}