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.KreditorDebitorService; import com.alexanderlogistics.OPListExportAdapterByWeek; import jakarta.ejb.EJB; import jakarta.inject.Inject; /** * TheSEPAExportAdapterNBD is an extension of the SEPAExportAdapter. * * This adapter export the payment information in a Excel Sheet acording to the * 'businessONLINE NBD' interface description. * * * * *
 * {@code
        
            ....
            
        
 * }
 * 
* * @version 1.0 * @author rsoika */ public class SEPAExportAdapterNBD implements SignalAdapter { private static Logger logger = Logger.getLogger(SEPAExportAdapterNBD.class.getName()); 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; @Inject KreditorDebitorService kreditorDebitorService; /** * This method collects a data set with all invoices and computes a NBA Excel * File. The templated is loaded from a text block * * @throws PluginException */ @SuppressWarnings("unchecked") @Override public ItemCollection execute(ItemCollection sepaExport, ItemCollection event) throws AdapterException, PluginException { 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(workitem.getItemValueString("dbtr.iban")); row.getCell(1).setCellValue(invoice.getItemValueString("sequencenumber")); row.getCell(2).setCellValue(invoice.getItemValueString("invoice.ttc")); row.getCell(3).setCellValue(invoice.getItemValueString("cdtr.name")); row.getCell(4).setCellValue(buildAddressString(invoice)); row.getCell(5).setCellValue(getVendorField(invoice, "_vendor_country")); row.getCell(6).setCellValue("A"); row.getCell(7).setCellValue(invoice.getItemValueString("cdtr.iban")); row.getCell(8).setCellValue(invoice.getItemValueString("invoice.spc")); row.getCell(9).setCellValue(invoice.getItemValueString("cdtr.bic")); row.getCell(10).setCellValue(invoice.getItemValueString("invoice.lcc")); row.getCell(11).setCellValue(getVendorField(invoice, "_vendor_country")); row.getCell(12).setCellValue(invoice.getItemValueString("invoice.rpc")); row.getCell(13).setCellValue(""); row.getCell(14).setCellValue(invoice.getItemValueString("invoice.currency")); row.getCell(15).setCellValue("" + invoice.getItemValueDouble("invoice.total")); row.getCell(16).setCellValue("Invoice No. " + invoice.getItemValueString("invoice.number")); row.getCell(17).setCellValue(""); row.getCell(18).setCellValue(""); row.getCell(19).setCellValue(""); 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; } /** * This helper method lookups the creditor in the CArgosoft dataset and builds a * address line needed for the export. * * @param workitem * @return */ private String buildAddressString(ItemCollection workitem) { String result = ""; ItemCollection cdtrItemCol = null; String cdtrNumber = workitem.getItemValueString("cdtr.number"); try { cdtrItemCol = kreditorDebitorService.findCreditor(cdtrNumber); } catch (PluginException e) { logger.warning("Unable to resolve address for " + cdtrNumber + " : " + e.getMessage()); } if (cdtrItemCol != null) { result = result + cdtrItemCol.getItemValueString("_vendor_zip_code") + " "; result = result + cdtrItemCol.getItemValueString("_vendor_city") + " "; result = result + cdtrItemCol.getItemValueString("_vendor_str") + " "; } // length max 255 result = result.trim(); return result.length() > 255 ? result.substring(0, 255) : result; } private String getVendorField(ItemCollection workitem, String fieldname) { String result = ""; ItemCollection cdtrItemCol = null; String cdtrNumber = workitem.getItemValueString("cdtr.number"); try { cdtrItemCol = kreditorDebitorService.findCreditor(cdtrNumber); } catch (PluginException e) { logger.warning("Unable to resolve address for " + cdtrNumber + " : " + e.getMessage()); } if (cdtrItemCol != null) { return cdtrItemCol.getItemValueString(fieldname); } return ""; } }