From 597075e0dc7ace1b25a2ca47561cd49973fe2b59 Mon Sep 17 00:00:00 2001 From: Sebastian Sieber Date: Wed, 20 Jan 2021 09:32:41 +0100 Subject: [PATCH] Support SellerOrderReferencedDocumentId --- .../main/java/org/mustangproject/Invoice.java | 46 +++-- .../ZUGFeRD/IExportableTransaction.java | 8 + .../ZUGFeRD/ZUGFeRD1PullProvider.java | 64 +++---- .../ZUGFeRD/ZUGFeRD2PullProvider.java | 78 +++++---- .../ZUGFeRD/ZUGFeRDImporter.java | 160 ++++++++++-------- 5 files changed, 209 insertions(+), 147 deletions(-) diff --git a/library/src/main/java/org/mustangproject/Invoice.java b/library/src/main/java/org/mustangproject/Invoice.java index 7562f41a..6fd87275 100644 --- a/library/src/main/java/org/mustangproject/Invoice.java +++ b/library/src/main/java/org/mustangproject/Invoice.java @@ -39,6 +39,7 @@ public class Invoice implements IExportableTransaction { protected TradeParty sender = null, recipient = null, deliveryAddress = null; protected ArrayList ZFItems = null; protected ArrayList notes = null; + private String sellerOrderReferencedDocumentID; protected String contractReferencedDocument = null; protected ArrayList xmlEmbeddedFiles=null; @@ -50,7 +51,7 @@ public class Invoice implements IExportableTransaction { protected IZUGFeRDPaymentTerms paymentTerms = null; - public Invoice() { + public Invoice() { ZFItems = new ArrayList(); setCurrency("EUR"); } @@ -60,7 +61,8 @@ public class Invoice implements IExportableTransaction { return documentName; } - public String getContractReferencedDocument() { + @Override + public String getContractReferencedDocument() { return contractReferencedDocument; } @@ -81,13 +83,14 @@ public class Invoice implements IExportableTransaction { public Invoice embedFileInXML(FileAttachment fa) { if (xmlEmbeddedFiles == null) { - xmlEmbeddedFiles=new ArrayList(); + xmlEmbeddedFiles= new ArrayList<>(); } xmlEmbeddedFiles.add(fa); return this; } - public FileAttachment[] getAdditionalReferencedDocuments() { + @Override + public FileAttachment[] getAdditionalReferencedDocuments() { if (xmlEmbeddedFiles == null) { return null; } @@ -209,7 +212,16 @@ public class Invoice implements IExportableTransaction { public String getBuyerOrderReferencedDocumentID() { return buyerOrderReferencedDocumentID; } + @Override + public String getSellerOrderReferencedDocumentID() { + return sellerOrderReferencedDocumentID; + } + + public Invoice setSellerOrderReferencedDocumentID(String sellerOrderReferencedDocumentID) { + this.sellerOrderReferencedDocumentID = sellerOrderReferencedDocumentID; + return this; + } /*** * usually the order number or in case of a correction the original invoice number * @param buyerOrderReferencedDocumentID string with number @@ -310,12 +322,14 @@ public class Invoice implements IExportableTransaction { } - public String getOwnLocation() { + @Override + public String getOwnLocation() { return sender.getLocation(); } - public String getOwnCountry() { + @Override + public String getOwnCountry() { return sender.getCountry(); } @@ -405,7 +419,8 @@ public class Invoice implements IExportableTransaction { return this; } - public IZUGFeRDExportableTradeParty getRecipient() { + @Override + public IZUGFeRDExportableTradeParty getRecipient() { return recipient; } @@ -439,8 +454,9 @@ public class Invoice implements IExportableTransaction { public IZUGFeRDAllowanceCharge[] getZFAllowances() { if (Allowances.isEmpty()) { return null; - } else - return Allowances.toArray(new IZUGFeRDAllowanceCharge[0]); + } else { + return Allowances.toArray(new IZUGFeRDAllowanceCharge[0]); + } } @@ -448,8 +464,9 @@ public class Invoice implements IExportableTransaction { public IZUGFeRDAllowanceCharge[] getZFCharges() { if (Charges.isEmpty()) { return null; - } else - return Charges.toArray(new IZUGFeRDAllowanceCharge[0]); + } else { + return Charges.toArray(new IZUGFeRDAllowanceCharge[0]); + } } @@ -457,8 +474,9 @@ public class Invoice implements IExportableTransaction { public IZUGFeRDAllowanceCharge[] getZFLogisticsServiceCharges() { if (LogisticsServiceCharges.isEmpty()) { return null; - } else - return LogisticsServiceCharges.toArray(new IZUGFeRDAllowanceCharge[0]); + } else { + return LogisticsServiceCharges.toArray(new IZUGFeRDAllowanceCharge[0]); + } } @@ -599,7 +617,7 @@ public class Invoice implements IExportableTransaction { */ public Invoice addNote(String text) { if (notes == null) { - notes = new ArrayList(); + notes = new ArrayList<>(); } notes.add(text); return this; diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java index 70fa9e50..2f306ab2 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java @@ -398,6 +398,14 @@ public interface IExportableTransaction { } + /** + * get the ID of the SellerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement/ApplicableHeaderTradeAgreement + * + * @return the ID of the document + */ + default String getSellerOrderReferencedDocumentID() { + return null; + } /** * get the ID of the BuyerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement * diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java index 2a55d93b..325cc9d9 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java @@ -20,13 +20,6 @@ */ 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.XMLTools; - import java.io.IOException; import java.io.StringWriter; import java.io.UnsupportedEncodingException; @@ -37,6 +30,13 @@ 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.XMLTools; + public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLProvider { @@ -82,20 +82,20 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr byte[] res = zugferdData; - StringWriter sw = new StringWriter(); + final StringWriter sw = new StringWriter(); Document document = null; try { document = DocumentHelper.parseText(new String(zugferdData)); - } catch (DocumentException e1) { + } catch (final DocumentException e1) { Logger.getLogger(ZUGFeRD1PullProvider.class.getName()).log(Level.SEVERE, null, e1); } try { - OutputFormat format = OutputFormat.createPrettyPrint(); - XMLWriter writer = new XMLWriter(sw, format); + final OutputFormat format = OutputFormat.createPrettyPrint(); + final XMLWriter writer = new XMLWriter(sw, format); writer.write(document); res = sw.toString().getBytes("UTF-8"); - } catch (IOException e) { + } catch (final IOException e) { Logger.getLogger(ZUGFeRD1PullProvider.class.getName()).log(Level.SEVERE, null, e); } @@ -110,7 +110,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr this.calc = new TransactionCalculator(trans); boolean hasDueDate = false; - SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy"); + final SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy"); String exemptionReason = ""; if (trans.getPaymentTermDescription() != null) { @@ -199,6 +199,12 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr xml += " \n"; + if (trans.getSellerOrderReferencedDocumentID() != null) { + xml = xml + " \n" + + " " + + XMLTools.encodeXML(trans.getSellerOrderReferencedDocumentID()) + "\n" + + " \n"; + } if (trans.getBuyerOrderReferencedDocumentID() != null) { xml = xml + " \n" + " " @@ -235,7 +241,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr + " " + trans.getCurrency() + "\n"; if (trans.getTradeSettlementPayment() != null) { - for (IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) { + for (final IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) { if (payment != null) { hasDueDate = true; xml += payment.getSettlementXML(); @@ -243,7 +249,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr } } if (trans.getTradeSettlement() != null) { - for (IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { + for (final IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { if (payment != null) { if (payment instanceof IZUGFeRDTradeSettlementPayment) { hasDueDate = true; @@ -253,9 +259,9 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr } } - HashMap VATPercentAmountMap = calc.getVATPercentAmountMap(); - for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { - VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); + final HashMap VATPercentAmountMap = calc.getVATPercentAmountMap(); + for (final BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { + final VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); if (amount != null) { xml += " \n" + " " + currencyFormat(amount.getCalculated()) @@ -275,7 +281,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr + " " + paymentTermsDescription + "\n"; if (trans.getTradeSettlement() != null) { - for (IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { + for (final IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { if ((payment != null) && (payment instanceof IZUGFeRDTradeSettlementDebit)) { xml += payment.getPaymentXML(); } @@ -318,14 +324,14 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr int lineID = 0; - for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { + for (final IZUGFeRDExportableItem currentItem : trans.getZFItems()) { lineID++; if (currentItem.getProduct().getTaxExemptionReason() != null) { exemptionReason = "" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + ""; } - LineCalculator lc = new LineCalculator(currentItem); + final LineCalculator lc = new LineCalculator(currentItem); xml = xml + " \n" + " \n" + " " + lineID + "\n" //$NON-NLS-2$ @@ -404,11 +410,11 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr xml = xml + " \n" + ""; - byte[] zugferdRaw; + final byte[] zugferdRaw; try { zugferdRaw = xml.getBytes("UTF-8"); zugferdData = XMLTools.removeBOM(zugferdRaw); - } catch (UnsupportedEncodingException e) { + } catch (final UnsupportedEncodingException e) { Logger.getLogger(ZUGFeRD1PullProvider.class.getName()).log(Level.SEVERE, null, e); } } @@ -421,9 +427,9 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr private String buildPaymentTermsXml() { String paymentTermsXml = ""; - IZUGFeRDPaymentTerms paymentTerms = trans.getPaymentTerms(); - IZUGFeRDPaymentDiscountTerms discountTerms = paymentTerms.getDiscountTerms(); - Date dueDate = paymentTerms.getDueDate(); + final IZUGFeRDPaymentTerms paymentTerms = trans.getPaymentTerms(); + 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"); @@ -438,14 +444,14 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr if (discountTerms != null) { paymentTermsXml += ""; - String currency = trans.getCurrency(); - String basisAmount = currencyFormat(calc.getGrandTotal()); + final String currency = trans.getCurrency(); + final String basisAmount = currencyFormat(calc.getGrandTotal()); paymentTermsXml += "" + basisAmount + ""; paymentTermsXml += "" + discountTerms.getCalculationPercentage().toString() + ""; if (discountTerms.getBaseDate() != null) { - Date baseDate = discountTerms.getBaseDate(); + final Date baseDate = discountTerms.getBaseDate(); paymentTermsXml += ""; paymentTermsXml += "" + zugferdDateFormat.format(baseDate) + ""; paymentTermsXml += ""; diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 0e937e3d..269400ca 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -20,17 +20,18 @@ */ package org.mustangproject.ZUGFeRD; +import static org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants.CORRECTEDINVOICE; + import java.io.IOException; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; -import java.math.RoundingMode; import java.text.SimpleDateFormat; +import java.util.Base64; import java.util.Date; import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.Base64; import org.dom4j.Document; import org.dom4j.DocumentException; @@ -39,9 +40,6 @@ import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.mustangproject.FileAttachment; import org.mustangproject.XMLTools; -import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants; - -import static org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants.CORRECTEDINVOICE; public class ZUGFeRD2PullProvider implements IXMLProvider { @@ -82,20 +80,20 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { byte[] res = zugferdData; - StringWriter sw = new StringWriter(); + final StringWriter sw = new StringWriter(); Document document = null; try { document = DocumentHelper.parseText(new String(zugferdData)); - } catch (DocumentException e1) { + } catch (final DocumentException e1) { Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e1); } try { - OutputFormat format = OutputFormat.createPrettyPrint(); - XMLWriter writer = new XMLWriter(sw, format); + final OutputFormat format = OutputFormat.createPrettyPrint(); + final XMLWriter writer = new XMLWriter(sw, format); writer.write(document); res = sw.toString().getBytes("UTF-8"); - } catch (IOException e) { + } catch (final IOException e) { Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e); } @@ -210,7 +208,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { // only in extended profile reason = "" + XMLTools.encodeXML(allowance.getReason()) + ""; } - String allowanceChargeStr = "" + + final String allowanceChargeStr = "" + chargeIndicator + "" + percentage + "" + priceFormat(allowance.getTotalAmount(item)) + "" + reason + @@ -224,7 +222,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { this.calc = new TransactionCalculator(trans); boolean hasDueDate = false; - SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy"); + final SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy"); String exemptionReason = ""; @@ -265,7 +263,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { } String notes = ""; if (trans.getNotes() != null) { - for (String currentNote : trans.getNotes()) { + for (final String currentNote : trans.getNotes()) { notes = notes + "" + XMLTools.encodeXML(currentNote) + ""; } @@ -301,19 +299,19 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { + " \n" + " \n"; int lineID = 0; - for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { + for (final IZUGFeRDExportableItem currentItem : trans.getZFItems()) { lineID++; if (currentItem.getProduct().getTaxExemptionReason() != null) { exemptionReason = "" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + ""; } notes = ""; if (currentItem.getNotes() != null) { - for (String currentNote : currentItem.getNotes()) { + for (final String currentNote : currentItem.getNotes()) { notes = notes + "" + XMLTools.encodeXML(currentNote) + ""; } } - LineCalculator lc = new LineCalculator(currentItem); + final LineCalculator lc = new LineCalculator(currentItem); xml = xml + " \n" + " \n" + " " + lineID + "\n" //$NON-NLS-2$ @@ -332,12 +330,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { } String allowanceChargeStr = ""; if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) { - for (IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) { + for (final IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) { allowanceChargeStr += getAllowanceChargeStr(allowance, currentItem); } } if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) { - for (IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) { + for (final IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) { allowanceChargeStr += getAllowanceChargeStr(charge, currentItem); } @@ -423,6 +421,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { 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" + " " @@ -438,7 +442,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { // Additional Documents of XRechnung (Rechnungsbegruendende Unterlagen - BG-24 XRechnung) if (trans.getAdditionalReferencedDocuments() != null) { - for (FileAttachment f : trans.getAdditionalReferencedDocuments()) { + for (final FileAttachment f : trans.getAdditionalReferencedDocuments()) { final String documentContent = new String(Base64.getEncoder().encodeToString(f.getData())); xml = xml + " \n" + " " + f.getFilename() + "\n" @@ -480,7 +484,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { + " " + trans.getCurrency() + "\n"; if (trans.getTradeSettlementPayment() != null) { - for (IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) { + for (final IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) { if (payment != null) { hasDueDate = true; xml += payment.getSettlementXML(); @@ -488,7 +492,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { } } if (trans.getTradeSettlement() != null) { - for (IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { + for (final IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { if (payment != null) { if (payment instanceof IZUGFeRDTradeSettlementPayment) { hasDueDate = true; @@ -501,9 +505,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { hasDueDate = false; } - HashMap VATPercentAmountMap = calc.getVATPercentAmountMap(); - for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { - VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); + final HashMap VATPercentAmountMap = calc.getVATPercentAmountMap(); + for (final BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { + final VATAmount amount = VATPercentAmountMap.get(currentTaxPercent); if (amount != null) { xml += " \n" + " " + currencyFormat(amount.getCalculated()) @@ -532,7 +536,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { if ((trans.getZFCharges() != null) && (trans.getZFCharges().length > 0)) { - for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { + for (final BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { if (calc.getChargesForPercent(currentTaxPercent).compareTo(BigDecimal.ZERO) != 0) { @@ -555,7 +559,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { } if ((trans.getZFAllowances() != null) && (trans.getZFAllowances().length > 0)) { - for (BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { + for (final BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) { if (calc.getAllowancesForPercent(currentTaxPercent).compareTo(BigDecimal.ZERO) != 0) { xml = xml + " \n" + " \n" + @@ -582,7 +586,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { } if (trans.getTradeSettlement() != null) { - for (IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { + for (final IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { if ((payment != null) && (payment instanceof IZUGFeRDTradeSettlementDebit)) { xml += payment.getPaymentXML(); } @@ -601,9 +605,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { } - String allowanceTotalLine = "" + currencyFormat(calc.getAllowancesForPercent(null)) + ""; + final String allowanceTotalLine = "" + currencyFormat(calc.getAllowancesForPercent(null)) + ""; - String chargesTotalLine = "" + currencyFormat(calc.getChargesForPercent(null)) + ""; + final String chargesTotalLine = "" + currencyFormat(calc.getChargesForPercent(null)) + ""; xml = xml + " \n" + " " + currencyFormat(calc.getTotal()) + "\n" //$NON-NLS-2$ @@ -635,12 +639,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { xml = xml + " \n" + ""; - byte[] zugferdRaw; + final byte[] zugferdRaw; try { zugferdRaw = xml.getBytes("UTF-8"); zugferdData = XMLTools.removeBOM(zugferdRaw); - } catch (UnsupportedEncodingException e) { + } catch (final UnsupportedEncodingException e) { Logger.getLogger(ZUGFeRD2PullProvider.class.getName()).log(Level.SEVERE, null, e); } } @@ -652,14 +656,14 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { private String buildPaymentTermsXml() { - IZUGFeRDPaymentTerms paymentTerms = trans.getPaymentTerms(); + final IZUGFeRDPaymentTerms paymentTerms = trans.getPaymentTerms(); if (paymentTerms==null) { return ""; } String paymentTermsXml = ""; - IZUGFeRDPaymentDiscountTerms discountTerms = paymentTerms.getDiscountTerms(); - Date dueDate = paymentTerms.getDueDate(); + 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"); @@ -674,14 +678,14 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { if (discountTerms != null) { paymentTermsXml += ""; - String currency = trans.getCurrency(); - String basisAmount = currencyFormat(calc.getGrandTotal()); + final String currency = trans.getCurrency(); + final String basisAmount = currencyFormat(calc.getGrandTotal()); paymentTermsXml += "" + basisAmount + ""; paymentTermsXml += "" + discountTerms.getCalculationPercentage().toString() + ""; if (discountTerms.getBaseDate() != null) { - Date baseDate = discountTerms.getBaseDate(); + final Date baseDate = discountTerms.getBaseDate(); paymentTermsXml += ""; paymentTermsXml += "" + zugferdDateFormat.format(baseDate) + ""; paymentTermsXml += ""; diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index c66ae41b..5c546aa5 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -21,23 +21,31 @@ import java.math.BigDecimal; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Scanner; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import javax.xml.xpath.*; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; -import org.mustangproject.Item; -import org.mustangproject.Product; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary; 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.Item; +import org.mustangproject.Product; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -74,7 +82,7 @@ public class ZUGFeRDImporter { public ZUGFeRDImporter(String pdfFilename) { try (InputStream bis = Files.newInputStream(Paths.get(pdfFilename), StandardOpenOption.READ)) { extractLowLevel(bis); - } catch (IOException e) { + } catch (final IOException e) { Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); throw new ZUGFeRDExportException(e); } @@ -84,7 +92,7 @@ public class ZUGFeRDImporter { public ZUGFeRDImporter(InputStream pdfStream) { try { extractLowLevel(pdfStream); - } catch (IOException e) { + } catch (final IOException e) { Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); throw new ZUGFeRDExportException(e); } @@ -99,7 +107,7 @@ public class ZUGFeRDImporter { private void extractLowLevel(InputStream pdfStream) throws IOException { try (PDDocument doc = PDDocument.load(pdfStream)) { // PDDocumentInformation info = doc.getDocumentInformation(); - PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog()); + final PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog()); //start if (doc.getDocumentCatalog() == null || doc.getDocumentCatalog().getMetadata() == null) { @@ -107,15 +115,15 @@ public class ZUGFeRDImporter { return; } - InputStream XMP = doc.getDocumentCatalog().getMetadata().exportXMPMetadata(); + final InputStream XMP = doc.getDocumentCatalog().getMetadata().exportXMPMetadata(); xmpString = convertStreamToString(XMP); - PDEmbeddedFilesNameTreeNode etn = names.getEmbeddedFiles(); + final PDEmbeddedFilesNameTreeNode etn = names.getEmbeddedFiles(); if (etn == null) { return; } - Map efMap = etn.getNames(); + final Map efMap = etn.getNames(); // String filePath = "/tmp/"; if (efMap != null) { @@ -123,9 +131,9 @@ public class ZUGFeRDImporter { // https://memorynotfound.com/apache-pdfbox-extract-embedded-file-pdf-document/ } else { - List> kids = etn.getKids(); - for (PDNameTreeNode node : kids) { - Map namesL = node.getNames(); + final List> kids = etn.getKids(); + for (final PDNameTreeNode node : kids) { + final Map namesL = node.getNames(); extractFiles(namesL); } } @@ -134,17 +142,17 @@ public class ZUGFeRDImporter { private void extractFiles(Map names) throws IOException { - for (String alias : names.keySet()) { + for (final String alias : names.keySet()) { - PDComplexFileSpecification fileSpec = names.get(alias); - String filename = fileSpec.getFilename(); + final PDComplexFileSpecification fileSpec = names.get(alias); + final String filename = fileSpec.getFilename(); /** * 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")) || filename.equals("xrechnung.xml") || filename.equals("order-x.xml")) { containsMeta = true; - PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile(); + final PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile(); // String embeddedFilename = filePath + filename; // File file = new File(filePath + filename); // System.out.println("Writing " + embeddedFilename); @@ -158,7 +166,7 @@ public class ZUGFeRDImporter { // fos.close(); } if (filename.startsWith("additional_data")) { - PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile(); + final PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile(); additionalXMLs.put(filename, embeddedFile.toByteArray()); } } @@ -171,10 +179,10 @@ public class ZUGFeRDImporter { private void setDocument() throws ParserConfigurationException, IOException, SAXException { - DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance(); + final DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance(); xmlFact.setNamespaceAware(false); - DocumentBuilder builder = xmlFact.newDocumentBuilder(); - ByteArrayInputStream is = new ByteArrayInputStream(rawXML); + final DocumentBuilder builder = xmlFact.newDocumentBuilder(); + final ByteArrayInputStream is = new ByteArrayInputStream(rawXML); /// is.skip(guessBOMSize(is)); document = builder.parse(is); } @@ -197,13 +205,13 @@ public class ZUGFeRDImporter { if (!containsMeta) { throw new ZUGFeRDExportException("No suitable data/ZUGFeRD file could be found."); } - String result; + final String result; try { - Document document = getDocument(); - XPathFactory xpathFact = XPathFactory.newInstance(); - XPath xpath = xpathFact.newXPath(); + final Document document = getDocument(); + final XPathFactory xpathFact = XPathFactory.newInstance(); + final XPath xpath = xpathFact.newXPath(); result = xpath.evaluate(xpathStr, document); - } catch (XPathExpressionException e) { + } catch (final XPathExpressionException e) { Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); throw new ZUGFeRDExportException(e); } @@ -263,7 +271,7 @@ public class ZUGFeRDImporter { } else { return extractString("//ApplicableHeaderTradeSettlement//InvoiceCurrencyCode"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -273,13 +281,31 @@ public class ZUGFeRDImporter { * @return the IssuerAssigned ID */ public String getIssuerAssignedID() { + return extractIssuerAssignedID("BuyerOrderReferencedDocument"); + } + + /** + * @return the SellerOrderReferencedDocument IssuerAssigned ID + */ + public String getSellerOrderReferencedDocumentIssuerAssignedID() { + return extractIssuerAssignedID("SellerOrderReferencedDocument"); + } + + /** + * @return the IssuerAssigned ID + */ + public String getContractOrderReferencedDocumentIssuerAssignedID() { + return extractIssuerAssignedID("ContractReferencedDocument"); + } + + private String extractIssuerAssignedID(String propertyName) { try { if (getVersion() == 1) { return extractString("//BuyerOrderReferencedDocument//ID"); } else { return extractString("//BuyerOrderReferencedDocument//IssuerAssignedID"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -302,7 +328,7 @@ public class ZUGFeRDImporter { } else { return extractString("//ExchangedDocument//IssueDateTime//DateTimeString"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -318,7 +344,7 @@ public class ZUGFeRDImporter { } else { return extractString("//SpecifiedTradeSettlementHeaderMonetarySummation//TaxBasisTotalAmount"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -334,7 +360,7 @@ public class ZUGFeRDImporter { } else { return extractString("//SpecifiedTradeSettlementHeaderMonetarySummation//TaxTotalAmount"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -350,7 +376,7 @@ public class ZUGFeRDImporter { } else { return extractString("//SpecifiedTradeSettlementHeaderMonetarySummation//RoundingAmount"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -366,7 +392,7 @@ public class ZUGFeRDImporter { } else { return extractString("//SpecifiedTradeSettlementHeaderMonetarySummation//TotalPrepaidAmount"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -404,7 +430,7 @@ public class ZUGFeRDImporter { } else { return extractString("//ExchangedDocument//IncludedNote"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -429,7 +455,7 @@ public class ZUGFeRDImporter { } else { return extractString("//SpecifiedTradeSettlementHeaderMonetarySummation//LineTotalAmount"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -452,7 +478,7 @@ public class ZUGFeRDImporter { } else { return extractString("//ActualDeliverySupplyChainEvent//OccurrenceDateTime//DateTimeString"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -468,7 +494,7 @@ public class ZUGFeRDImporter { } else { return extractString("//ExchangedDocument//ID"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -486,7 +512,7 @@ public class ZUGFeRDImporter { } else { return extractString("//ExchangedDocument/TypeCode"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -503,7 +529,7 @@ public class ZUGFeRDImporter { } else { return extractString("//ApplicableHeaderTradeAgreement/BuyerReference"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return ""; } @@ -628,7 +654,7 @@ public class ZUGFeRDImporter { } - byte[] bomlessData; + final byte[] bomlessData; if ((rawXML[0] == (byte) 0xEF) && (rawXML[1] == (byte) 0xBB) @@ -664,7 +690,7 @@ public class ZUGFeRDImporter { // SpecifiedExchangedDocumentContext is in the schema, so a relatively good // indication if zugferd is present - better than just invoice - String meta = getMeta(); + final String meta = getMeta(); return (meta != null) && (meta.length() > 0) && ((meta.contains("SpecifiedExchangedDocumentContext") /* ZF1 */ || meta.contains("ExchangedDocumentContext") /* ZF2 */)); } @@ -673,7 +699,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, "UTF-8").useDelimiter("\\A"); + final Scanner s = new Scanner(is, "UTF-8").useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; } @@ -691,7 +717,7 @@ public class ZUGFeRDImporter { } else { nl = getNodeListByPath("//CrossIndustryInvoice//SupplyChainTradeTransaction//ApplicableHeaderTradeAgreement//BuyerTradeParty//PostalTradeAddress"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return null; } @@ -706,7 +732,7 @@ public class ZUGFeRDImporter { public PostalTradeAddress getSellerTradePartyAddress() { NodeList nl = null; - PostalTradeAddress address = new PostalTradeAddress(); + final PostalTradeAddress address = new PostalTradeAddress(); try { if (getVersion() == 1) { @@ -714,7 +740,7 @@ public class ZUGFeRDImporter { } else { nl = getNodeListByPath("//CrossIndustryInvoice//SupplyChainTradeTransaction//ApplicableHeaderTradeAgreement//SellerTradeParty//PostalTradeAddress"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return null; } @@ -723,15 +749,15 @@ public class ZUGFeRDImporter { } private PostalTradeAddress getAddressFromNodeList(NodeList nl) { - PostalTradeAddress address = new PostalTradeAddress(); + final PostalTradeAddress address = new PostalTradeAddress(); if (nl != null) { for (int i = 0; i < nl.getLength(); i++) { Node n = nl.item(i); - NodeList nodes = n.getChildNodes(); + final NodeList nodes = n.getChildNodes(); for (int j = 0; j < nodes.getLength(); j++) { n = nodes.item(j); - short nodeType = n.getNodeType(); + final short nodeType = n.getNodeType(); if (nodeType==Node.ELEMENT_NODE){ switch (n.getNodeName()) { case "ram:PostcodeCode": @@ -789,16 +815,16 @@ public class ZUGFeRDImporter { * @return a List of LineItem instances */ public List getLineItemList() { - List nodeList = getLineItemNodes(); - List lineItemList = new ArrayList<>(); + final List nodeList = getLineItemNodes(); + final List lineItemList = new ArrayList<>(); - for (Node n: nodeList) { - Item lineItem = new Item(null, null, null); + for (final Node n: nodeList) { + final Item lineItem = new Item(null, null, null); lineItem.setProduct(new Product(null,null,null,null)); - NodeList nl = n.getChildNodes(); + final NodeList nl = n.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { - Node nn = nl.item(i); + final Node nn = nl.item(i); Node node = null; switch (nn.getNodeName()) { case "ram:SpecifiedLineTradeAgreement": @@ -806,12 +832,12 @@ public class ZUGFeRDImporter { node = getNodeByName(nn.getChildNodes(), "ram:NetPriceProductTradePrice"); if (node != null) { - NodeList tradeAgreementChildren = node.getChildNodes(); + final NodeList tradeAgreementChildren = node.getChildNodes(); node = getNodeByName(tradeAgreementChildren, "ram:ChargeAmount"); lineItem.setPrice(tryBigDecimal(getNodeValue(node))); node = getNodeByName(tradeAgreementChildren, "ram:BasisQuantity"); if(node != null && node.getAttributes()!=null) { - Node unitCodeAttribute = node.getAttributes().getNamedItem("unitCode"); + final Node unitCodeAttribute = node.getAttributes().getNamedItem("unitCode"); if(unitCodeAttribute != null) { lineItem.getProduct().setUnit(unitCodeAttribute.getNodeValue()); } @@ -905,7 +931,7 @@ public class ZUGFeRDImporter { * @return a List of Node instances */ public List getLineItemNodes() { - List lineItemNodes = new ArrayList<>(); + final List lineItemNodes = new ArrayList<>(); NodeList nl = null; try { if (getVersion() == 1) { @@ -913,12 +939,12 @@ public class ZUGFeRDImporter { } else { nl = getNodeListByPath("//CrossIndustryInvoice//SupplyChainTradeTransaction//IncludedSupplyChainTradeLineItem"); } - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); } for (int i = 0; i < nl.getLength(); i++) { - Node n = nl.item(i); + final Node n = nl.item(i); lineItemNodes.add(n); } return lineItemNodes; @@ -935,7 +961,7 @@ public class ZUGFeRDImporter { if (nl.item(i).getNodeName() == name) { return nl.item(i); } else if (nl.item(i).getChildNodes().getLength() > 0) { - Node node = getNodeByName(nl.item(i).getChildNodes(), name); + final Node node = getNodeByName(nl.item(i).getChildNodes(), name); if (node != null) { return node; } @@ -951,14 +977,14 @@ public class ZUGFeRDImporter { */ public NodeList getNodeListByPath(String path) { - XPathFactory xpathFact = XPathFactory.newInstance(); - XPath xPath = xpathFact.newXPath(); - String s = path; + final XPathFactory xpathFact = XPathFactory.newInstance(); + final XPath xPath = xpathFact.newXPath(); + final String s = path; try { - XPathExpression xpr = xPath.compile(s); + final XPathExpression xpr = xPath.compile(s); return (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); return null; } @@ -986,10 +1012,10 @@ public class ZUGFeRDImporter { private BigDecimal tryBigDecimal(String nodeValue) { try { return new BigDecimal(nodeValue); - } catch (Exception e) { + } catch (final Exception e) { try { return new BigDecimal(Float.valueOf(nodeValue)); - } catch (Exception ex) { + } catch (final Exception ex) { return new BigDecimal("0.00"); } }