From 8bec54c4f1da71cb5dba942346597fc470aef07e Mon Sep 17 00:00:00 2001 From: j-dimension Date: Wed, 11 Sep 2024 16:38:28 +0200 Subject: [PATCH] implemented ZUGFerd XML creation and embedding upon PDF creation. issue #2165 --- .../documents/SaveDocumentsLocallyDialog.java | 2 +- .../editors/files/ArchiveFilePanel.java | 4 +- .../client/editors/files/SendPDFAction.java | 2 +- .../jlawyer/client/utils/FileConverter.java | 87 +++++++++++++++---- .../services/ArchiveFileServiceRemote.java | 2 + .../jlawyer/services/ArchiveFileService.java | 10 +++ 6 files changed, 85 insertions(+), 22 deletions(-) diff --git a/j-lawyer-client/src/com/jdimension/jlawyer/client/editors/documents/SaveDocumentsLocallyDialog.java b/j-lawyer-client/src/com/jdimension/jlawyer/client/editors/documents/SaveDocumentsLocallyDialog.java index 65f344aa0..2700ab168 100644 --- a/j-lawyer-client/src/com/jdimension/jlawyer/client/editors/documents/SaveDocumentsLocallyDialog.java +++ b/j-lawyer-client/src/com/jdimension/jlawyer/client/editors/documents/SaveDocumentsLocallyDialog.java @@ -870,7 +870,7 @@ private void cmdSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST byte[] content=CachingDocumentLoader.getInstance().getDocument(doc.getId()); if (this.convertToPdf && conv.supportsInputFormat(doc.getName())) { String tempPath = FileUtils.createTempFile(doc.getName(), content); - String tempPdfPath = conv.convertToPDF(tempPath); + String tempPdfPath = conv.convertToPDF(tempPath, doc); byte[] fileContent = FileUtils.readFile(new File(tempPdfPath)); FileUtils.cleanupTempFile(tempPdfPath); FileUtils.cleanupTempFile(tempPath); diff --git a/j-lawyer-client/src/com/jdimension/jlawyer/client/editors/files/ArchiveFilePanel.java b/j-lawyer-client/src/com/jdimension/jlawyer/client/editors/files/ArchiveFilePanel.java index 83bdb8fd8..52f0c16ce 100755 --- a/j-lawyer-client/src/com/jdimension/jlawyer/client/editors/files/ArchiveFilePanel.java +++ b/j-lawyer-client/src/com/jdimension/jlawyer/client/editors/files/ArchiveFilePanel.java @@ -5598,7 +5598,7 @@ public void convertDocumentToPdf(ArchiveFileDocumentsBean doc) throws Exception FileConverter conv = FileConverter.getInstance(); String tempPath = FileUtils.createTempFile(doc.getName(), content); - String tempPdfPath = conv.convertToPDF(tempPath); + String tempPdfPath = conv.convertToPDF(tempPath, doc); byte[] pdfContent = FileUtils.readFile(new File(tempPdfPath)); FileUtils.cleanupTempFile(tempPath); FileUtils.cleanupTempFile(tempPdfPath); @@ -6029,7 +6029,7 @@ private void mnuSaveDocumentEncryptedActionPerformed(java.awt.event.ActionEvent if (!(tmpUrl.toLowerCase().endsWith(".pdf"))) { FileConverter conv = FileConverter.getInstance(); - tmpUrl = conv.convertToPDF(tmpUrl); + tmpUrl = conv.convertToPDF(tmpUrl, doc); } PDFEncryptionDialog encDlg = new PDFEncryptionDialog(EditorsRegistry.getInstance().getMainWindow(), true, tmpUrl); diff --git a/j-lawyer-client/src/com/jdimension/jlawyer/client/editors/files/SendPDFAction.java b/j-lawyer-client/src/com/jdimension/jlawyer/client/editors/files/SendPDFAction.java index f8c2a3709..0e68cf0c0 100755 --- a/j-lawyer-client/src/com/jdimension/jlawyer/client/editors/files/SendPDFAction.java +++ b/j-lawyer-client/src/com/jdimension/jlawyer/client/editors/files/SendPDFAction.java @@ -723,7 +723,7 @@ public boolean execute() throws Exception { if (doc.getName().toLowerCase().endsWith(".pdf") || !(conv.supportsInputFormat(doc.getName().toLowerCase()))) { dlg.addAttachment(tmpUrl, doc.getDictateSign()); } else { - String pdfUrl = conv.convertToPDF(tmpUrl); + String pdfUrl = conv.convertToPDF(tmpUrl, doc); try { // give some more time to LibreOffice to shut down Thread.sleep(2500); diff --git a/j-lawyer-client/src/com/jdimension/jlawyer/client/utils/FileConverter.java b/j-lawyer-client/src/com/jdimension/jlawyer/client/utils/FileConverter.java index d08ab4392..c723143bb 100755 --- a/j-lawyer-client/src/com/jdimension/jlawyer/client/utils/FileConverter.java +++ b/j-lawyer-client/src/com/jdimension/jlawyer/client/utils/FileConverter.java @@ -665,6 +665,12 @@ import com.jdimension.jlawyer.client.bea.BeaAccess; import com.jdimension.jlawyer.client.settings.ClientSettings; +import com.jdimension.jlawyer.client.settings.UserSettings; +import com.jdimension.jlawyer.client.utils.einvoice.EInvoiceUtils; +import com.jdimension.jlawyer.persistence.AppUserBean; +import com.jdimension.jlawyer.persistence.ArchiveFileDocumentsBean; +import com.jdimension.jlawyer.persistence.Invoice; +import com.jdimension.jlawyer.services.JLawyerServiceLocator; import java.io.File; import java.util.ArrayList; import java.util.Arrays; @@ -675,6 +681,8 @@ import org.jlawyer.bea.model.Attachment; import org.jlawyer.bea.model.Message; import org.jlawyer.bea.model.MessageExport; +import org.mustangproject.ZUGFeRD.IZUGFeRDExporter; +import org.mustangproject.ZUGFeRD.ZUGFeRDExporterFromPDFA; /** * @@ -708,6 +716,49 @@ public String convertToPDF(String file) throws Exception { return null; } + /** + * This method will check if the document is related to an invoice and + * generate a ZUGFerd electronic invoice. + * + * @param file + * @param doc + * @return + * @throws Exception + */ + public String convertToPDF(String file, ArchiveFileDocumentsBean doc) throws Exception { + + String pdfTempFile = convertToPDF(file); + + ClientSettings settings = ClientSettings.getInstance(); + FileConverter conv = FileConverter.getInstance(); + JLawyerServiceLocator locator = JLawyerServiceLocator.getInstance(settings.getLookupProperties()); + List invoices = locator.lookupArchiveFileServiceRemote().getInvoicesForDocument(doc.getId()); + if (invoices.size() > 1) { + throw new Exception("Diesem Dokument ist mit mehreren Rechnungen verknüpft, elektronische Rechnung kann nicht erstellt werden."); + } + if (invoices.size() == 1) { + // generate electronic invoice + Invoice sourceInvoice = invoices.get(0); + if (StringUtils.isEmpty(sourceInvoice.getSender())) { + throw new Exception("Die dem Dokument zugeordnete Rechnung hat keinen Absender, elektronische Rechnung kann nicht erstellt werden."); + } + + AppUserBean sender = locator.lookupSystemManagementRemote().getUser(sourceInvoice.getSender()); + if (sender == null) { + throw new Exception("Die dem Dokument zugeordnete Rechnung hat den unbekannten Absender '" + sourceInvoice.getSender() + "', elektronische Rechnung kann nicht erstellt werden."); + } + + org.mustangproject.Invoice i = EInvoiceUtils.getEInvoice(sourceInvoice, sender); + + + IZUGFeRDExporter ze = new ZUGFeRDExporterFromPDFA().load(pdfTempFile).setProducer("j-lawyer.org " + VersionUtils.getFullClientVersion()).setCreator(UserSettings.getInstance().getCurrentUser().getDisplayName()); + ze.setTransaction(i); + ze.export(pdfTempFile); + } + + return pdfTempFile; + } + public String convertTo(String file, String targetFileExtension) throws Exception { return null; } @@ -738,7 +789,7 @@ protected static String pdf2pdf(String url) throws Exception { } return url; } - + protected String bea2pdf(String url) throws Exception { if (url.toLowerCase().endsWith(".bea")) { @@ -747,24 +798,24 @@ protected String bea2pdf(String url) throws Exception { MessageExport export = new MessageExport(); export.setContent(data); Message msg = BeaAccess.getMessageFromExport(export); - - byte[] pdf=msg.toPdf("j-lawyer.org " + VersionUtils.getFullClientVersion()); - String beaPdf=FileUtils.createTempFile(inputFile.getName() + ".pdf", pdf); - - ArrayList attachments=msg.getAttachments(); + + byte[] pdf = msg.toPdf("j-lawyer.org " + VersionUtils.getFullClientVersion()); + String beaPdf = FileUtils.createTempFile(inputFile.getName() + ".pdf", pdf); + + ArrayList attachments = msg.getAttachments(); if (!attachments.isEmpty()) { PDFMergerUtility merger = new PDFMergerUtility(); merger.addSource(new File(beaPdf)); - + for (Attachment att : attachments) { - + try { - String attFile=FileUtils.createTempFile(att.getFileName(), att.getContent()); - String attFilePdf=convertToPDF(attFile); - + String attFile = FileUtils.createTempFile(att.getFileName(), att.getContent()); + String attFilePdf = convertToPDF(attFile); + merger.addSource(new File(attFilePdf)); - + } catch (Throwable t) { log.error("unable to convert attachment " + att.getFileName() + " of beA message " + url + " to PDF - skipping!", t); } @@ -879,7 +930,7 @@ public String convertTo(String url, String targetFileExtension) throws Exception @Override public String convertToPDF(String url) throws Exception { - + if (url.toLowerCase().endsWith(".pdf")) { return pdf2pdf(url); } @@ -887,11 +938,11 @@ public String convertToPDF(String url) throws Exception { if (url.toLowerCase().endsWith(".eml")) { return eml2pdf(url); } - + if (url.toLowerCase().endsWith(".bea")) { return bea2pdf(url); } - + ClientSettings set = ClientSettings.getInstance(); String wordProcessor = set.getConfiguration(ClientSettings.CONF_APPS_WORDPROCESSOR_KEY, ClientSettings.CONF_APPS_WORDPROCESSOR_VALUE_LO); boolean wordProcessorMicrosoft = ClientSettings.CONF_APPS_WORDPROCESSOR_VALUE_MSO.equalsIgnoreCase(wordProcessor); @@ -1045,7 +1096,7 @@ public String convertToPDF(String url) throws Exception { if (url.toLowerCase().endsWith(".eml")) { return eml2pdf(url); } - + if (url.toLowerCase().endsWith(".bea")) { return bea2pdf(url); } @@ -1131,11 +1182,11 @@ public String convertToPDF(String url) throws Exception { if (url.toLowerCase().endsWith(".eml")) { return eml2pdf(url); } - + if (url.toLowerCase().endsWith(".bea")) { return bea2pdf(url); } - + if (!this.supportsInputFormat(url)) { throw new Exception("Format nicht unterstützt: " + new File(url).getName()); } diff --git a/j-lawyer-server-api/src/com/jdimension/jlawyer/services/ArchiveFileServiceRemote.java b/j-lawyer-server-api/src/com/jdimension/jlawyer/services/ArchiveFileServiceRemote.java index b39724e82..5c7060125 100644 --- a/j-lawyer-server-api/src/com/jdimension/jlawyer/services/ArchiveFileServiceRemote.java +++ b/j-lawyer-server-api/src/com/jdimension/jlawyer/services/ArchiveFileServiceRemote.java @@ -865,6 +865,8 @@ public interface ArchiveFileServiceRemote { List getInvoicePositions(String invoiceId) throws Exception; ArchiveFileDocumentsBean getInvoiceDocument(String invoiceId) throws Exception; + + List getInvoicesForDocument(String docId) throws Exception; InvoicePosition updateInvoicePosition(String invoiceId, InvoicePosition position) throws Exception; diff --git a/j-lawyer-server/j-lawyer-server-ejb/src/java/com/jdimension/jlawyer/services/ArchiveFileService.java b/j-lawyer-server/j-lawyer-server-ejb/src/java/com/jdimension/jlawyer/services/ArchiveFileService.java index ac1944974..3df98dd1c 100644 --- a/j-lawyer-server/j-lawyer-server-ejb/src/java/com/jdimension/jlawyer/services/ArchiveFileService.java +++ b/j-lawyer-server/j-lawyer-server-ejb/src/java/com/jdimension/jlawyer/services/ArchiveFileService.java @@ -5106,6 +5106,16 @@ public List getInvoicePositions(String invoiceId) throws Except } } + @Override + @RolesAllowed({"readArchiveFileRole"}) + public List getInvoicesForDocument(String docId) throws Exception { + // this call will also check if caller is allowed for this case + ArchiveFileDocumentsBean doc=this.getDocument(docId); + + return this.invoicesFacade.findByInvoiceDocument(doc); + + } + @Override @RolesAllowed({"readArchiveFileRole"}) public ArchiveFileDocumentsBean getInvoiceDocument(String invoiceId) throws Exception {