From 3d4bbb03e05167d6792a7d101e91613257ead9ae Mon Sep 17 00:00:00 2001 From: Ralph Soika Date: Sun, 28 Jul 2024 16:24:06 +0200 Subject: [PATCH] sepa export DWC --- .../dwc/SEPAExportAdapterNBD.java | 227 ++++++++++++++++-- templates/sepa/sepa-dwc.xlsx | Bin 0 -> 5558 bytes workflow/sepa-export-manual-dwc-3.0.0.bpmn | 43 ++-- 3 files changed, 233 insertions(+), 37 deletions(-) create mode 100644 templates/sepa/sepa-dwc.xlsx diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/dwc/SEPAExportAdapterNBD.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/dwc/SEPAExportAdapterNBD.java index ce85ecf..3c30897 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/dwc/SEPAExportAdapterNBD.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/dwc/SEPAExportAdapterNBD.java @@ -1,14 +1,37 @@ package com.alexanderlogistics.dwc; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; import java.util.logging.Logger; +import org.apache.poi.ss.usermodel.CellCopyPolicy; +import org.apache.poi.ss.util.CellReference; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.imixs.ai.workflow.OpenAIAPIAdapter; +import org.imixs.archive.core.SnapshotService; +import org.imixs.workflow.FileData; import org.imixs.workflow.ItemCollection; import org.imixs.workflow.SignalAdapter; +import org.imixs.workflow.engine.DocumentService; import org.imixs.workflow.engine.ReportService; +import org.imixs.workflow.engine.WorkflowService; import org.imixs.workflow.exceptions.AdapterException; import org.imixs.workflow.exceptions.PluginException; +import org.imixs.workflow.exceptions.QueryException; import org.imixs.workflow.sepa.services.SepaWorkflowService; +import com.alexanderlogistics.OPListExportAdapterByWeek; + import jakarta.ejb.EJB; import jakarta.inject.Inject; @@ -18,6 +41,17 @@ import jakarta.inject.Inject; * This adapter export the payment information in a Excel Sheet acording to the * 'businessONLINE NBD' interface description. * + * * + * + *
+ * {@code
+        
+            ....
+            
+        
+ * }
+ * 
+ * * @version 1.0 * @author rsoika */ @@ -28,12 +62,23 @@ public class SEPAExportAdapterNBD implements SignalAdapter { public static final String ERROR_CONFIG = "CONFIG_ERROR"; public static final String ERROR_MISSING_INVOICE = "ERROR_MISSING_INVOICE"; + final String TYPE_TEXTBLOCK = "textblock"; + @EJB ReportService reportService; @Inject SepaWorkflowService sepaWorkflowService; + @Inject + DocumentService documentService; + + @Inject + WorkflowService workflowService; + + @Inject + SnapshotService snapshotService; + /** * This method collects a data set with all invoices and computes a NBA Excel * File. The templated is loaded from a text block @@ -45,27 +90,173 @@ public class SEPAExportAdapterNBD implements SignalAdapter { public ItemCollection execute(ItemCollection sepaExport, ItemCollection event) throws AdapterException, PluginException { - // Textblock laden - // load the text block - // FileData fileData = loadTextBlockFileData(textblockRef, template); - - // // do we found the document? - // if (fileData == null) { - // throw new PluginException(OPListExportAdapterByWeek.class.getSimpleName(), - // ERROR_CONFIG, - // "invalid op-list configuration in model event - template=" + template + " not - // found!"); - // } - // fileData.setName(targetName); - // // append document - // logger.info("...append new op-list Template: " + targetName); - - // document.addFileData(fileData); - - /* Processing .... */ String key = sepaExport.getItemValueString("name"); + // Textblock laden + List sepaConfigList = workflowService.evalWorkflowResultXML(event, "imixs-sepa", "CONFIG", + sepaExport, + false); + if (sepaConfigList == null || sepaConfigList.size() != 1) { + // no configuration found! + throw new PluginException(OpenAIAPIAdapter.class.getSimpleName(), ERROR_CONFIG, + "Missing or invalid imixs-sepa definition in Event " + sepaExport.getTaskID() + "." + + sepaExport.getEventID()); + } + + ItemCollection sepaConf = sepaConfigList.get(0); + String template = sepaConf.getItemValueString("template"); + FileData fileData = loadTextBlockFileData(sepaConf.getItemValueString("textblock"), template); + + // do we found the document? + if (fileData == null) { + throw new PluginException(OPListExportAdapterByWeek.class.getSimpleName(), + ERROR_CONFIG, + "invalid sepa configuration in model event - template not found!"); + } + fileData.setName(template); + // create the attachment based on the report definition + // attach a file to the current workitem + // create a harmonized debitor name for the filename..... + String sDepName = sepaExport.getItemValueString(SepaWorkflowService.ITEM_DBTR_NAME); + sDepName = sDepName.replace("&", "_"); + sDepName = sDepName.replace(">", "_"); + sDepName = sDepName.replace("<", "_"); + sDepName = sDepName.replace(" ", "_"); + // build a timestamp for the filename + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HHmm"); + String sepaFileName = "sepa_" + sDepName + "_" + df.format(new Date()) + ".xlsx"; + + fileData.setName(sepaFileName); + + // append document + logger.info("...append invoices to Template: " + template); + + // get the data source based on the $workitemref .... + List refList = sepaExport.getItemValue("$workitemref"); + List data = new ArrayList(); + logger.info("...SEPA export started - " + refList.size() + " invoices found..."); + + for (String ref : refList) { + // load invoice + ItemCollection invoice = sepaWorkflowService.loadInvoice(ref); + if (invoice == null) { + logger.warning("Invoice '" + ref + "' not found! SEPA Export can not be executed"); + continue; + } + // avoid unsupported characters in sepa fields + invoice = sepaWorkflowService.harmonizeSEPAItem(invoice, SepaWorkflowService.ITEM_CDTR_NAME); + invoice = sepaWorkflowService.harmonizeSEPAItem(invoice, SepaWorkflowService.ITEM_DBTR_NAME); + data.add(invoice); + } + + // finally we add the teh invoices + try { + insertInvoiceRows(sepaExport, fileData, data); + } catch (PluginException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (QueryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return sepaExport; } + /** + * This helper method inserts a row for each invoice of the OPListe at row 16 + * into the excel template file + *

+ * The method copies the Row A16 as a reference row + *

+ * The named cell 'TOTAL' should contain the summary formula. It will be + * evaluated at the end. + * + * @throws PluginException + * @throws QueryException + */ + private void insertInvoiceRows(ItemCollection workitem, FileData fileData, List invoices) + throws PluginException, QueryException { + + // load XSSFWorkbook + try (InputStream imputStream = new ByteArrayInputStream(fileData.getContent())) { + XSSFWorkbook doc = new XSSFWorkbook(imputStream); + // NOTE: we only take the first sheet ! + XSSFSheet sheet = doc.getSheetAt(0); + CellReference cr = new CellReference("A2"); + XSSFRow referenceRow = sheet.getRow(cr.getRow()); + + int rowPos = 1; + + // int lastRow = sheet.getLastRowNum(); + int lastRow = 999; + logger.finest("Last rownum=" + lastRow); + sheet.shiftRows(rowPos, lastRow, invoices.size(), true, true); + + for (ItemCollection invoice : invoices) { + logger.finest("......copy row..."); + // now create a new line.. + XSSFRow row = sheet.createRow(rowPos); + row.copyRowFrom(referenceRow, new CellCopyPolicy()); + // insert values + row.getCell(0).setCellValue(invoice.getItemValueString("numsequencenumber")); + row.getCell(1).setCellValue(invoice.getItemValueDate("invoice.date")); + row.getCell(2).setCellValue(invoice.getItemValueString("invoice.number")); + row.getCell(3).setCellValue(invoice.getItemValueDate("invoice.duedate")); + + row.getCell(4).setCellValue(invoice.getItemValueDouble("invoice.total")); + + rowPos++; + } + // delete reference row A2 + // sheet.shiftRows(1, 1 + invoices.size(), -1, true, true); + // sheet.shiftRows(1, lastRow + invoices.size(), -1, true, true); + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + // write back the file + + doc.write(byteArrayOutputStream); + doc.close(); + byte[] newContent = byteArrayOutputStream.toByteArray(); + FileData fileDataNew = new FileData(fileData.getName(), newContent, fileData.getContentType(), null); + // update the fileData + workitem.addFileData(fileDataNew); + logger.finest("......new document added"); + + } catch (IOException e) { + throw new PluginException(SEPAExportAdapterNBD.class.getSimpleName(), ERROR_CONFIG, + "failed to update sepa export: " + e.getMessage()); + } + } + + /** + * This method returns a text-block ItemCollection for a specified name. + * + * @param name in attribute txtname + * + * + */ + public FileData loadTextBlockFileData(String name, String fileName) { + ItemCollection textBlockItemCollection = null; + + // load text-block by name.... + String sQuery = "(type:\"" + TYPE_TEXTBLOCK + "\" AND txtname:\"" + name + "\")"; + Collection col; + try { + // find the textblock... + col = documentService.find(sQuery, 1, 0); + if (col.size() > 0) { + textBlockItemCollection = col.iterator().next(); + // fetch the fileData... + return snapshotService.getWorkItemFile(textBlockItemCollection.getUniqueID(), fileName); + + } else { + logger.warning("Missing text-block : '" + name + "'"); + } + } catch (QueryException e) { + logger.warning("getTextBlock - invalid query: " + e.getMessage()); + } + + return null; + } } \ No newline at end of file diff --git a/templates/sepa/sepa-dwc.xlsx b/templates/sepa/sepa-dwc.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..030a6096ea0bf533ba615ffd0b55f572e4fe0a3c GIT binary patch literal 5558 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 literal 0 HcmV?d00001 diff --git a/workflow/sepa-export-manual-dwc-3.0.0.bpmn b/workflow/sepa-export-manual-dwc-3.0.0.bpmn index 3d5ac75..933bc83 100644 --- a/workflow/sepa-export-manual-dwc-3.0.0.bpmn +++ b/workflow/sepa-export-manual-dwc-3.0.0.bpmn @@ -460,15 +460,14 @@ false - + +if (workitem.getItemValueString('txtcomment') == '') { + result.isValid=false; + result.errorMessage='Bitte geben Sie einen Kommentar ein.'; +}]]> @@ -565,7 +564,10 @@ result.isValid=true; - + + SEPA-DWC + +]]> @@ -674,7 +676,10 @@ result.isValid=true; - + + SEPA-DWC + +]]> @@ -688,15 +693,14 @@ result.isValid=true; - + +if (workitem.getItemValueString('txtcomment') == '') { + result.isValid=false; + result.errorMessage='Bitte geben Sie einen Kommentar ein.'; +}]]> @@ -854,9 +858,9 @@ result.isValid=true; - + - + @@ -940,11 +944,12 @@ result.isValid=true; - + - + + @@ -971,7 +976,7 @@ result.isValid=true; - +