package com.alexanderlogistics; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Collection; 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.archive.core.SnapshotService; import org.imixs.workflow.FileData; import org.imixs.workflow.ItemCollection; import org.imixs.workflow.engine.DocumentService; 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.poi.POIFindReplaceAdapter; import jakarta.inject.Inject; /** * Der ZahlungsavisAdapter importiert eine Excel Datei aus einem Textblock * *
 * {@code
        textblock-ref
        filename
        filename
   }
 * 
*

* Der Adapter erweitert den POIAdapter somit können felder aktualisiert werden * (siehe POIFineReplaceAdapter). * *

* Der Adapter kopiert die Rechnungsdaten in neue Zeilen, welche ab Zeilnenummer * 16 eingefügt werden. *

* Dabei werden Gutschriften in spalte E und Rechnungen in Spalte F eingetrgen. *

* Abschliessend wird die Zelle 'TOTAL' noch aktualisiert. * * @version 1.0 * @author rsoika */ public class ZahlungsavisExportAdapter extends POIFindReplaceAdapter { private static Logger logger = Logger.getLogger(ZahlungsavisExportAdapter.class.getName()); public static final String ERROR_CONFIG = "CONFIG_ERROR"; final String TYPE_TEXTBLOCK = "textblock"; @Inject WorkflowService workflowService; @Inject DocumentService documentService; @Inject SnapshotService snapshotService; /** * This method finds or create the Zahlungsavis and adds a reference * ($workitemref) to the current invoice. * * @throws PluginException */ @SuppressWarnings("unchecked") @Override public ItemCollection execute(ItemCollection document, ItemCollection event) throws AdapterException, PluginException { // read the zahlungsavis options ItemCollection evalItemCollection = workflowService.evalWorkflowResult(event, "zahlungsavis", document, false); if (evalItemCollection == null) { throw new PluginException(ZahlungsavisExportAdapter.class.getSimpleName(), ERROR_CONFIG, "missing zahlungsavis configuration in model event - please check model configuration"); } String textblock = evalItemCollection.getItemValueString("textblock"); String template = evalItemCollection.getItemValueString("template"); String targetName = evalItemCollection.getItemValueString("target-name"); // adapt text.... targetName = workflowService.adaptText(targetName, document); appendExcelTemplate(document, textblock, template, targetName); // Process POI instructions // read the config ItemCollection poiConfig = workflowService.evalWorkflowResult(event, "poi-update", document, false); if (poiConfig == null || !poiConfig.hasItem("findreplace")) { throw new PluginException(POIFindReplaceAdapter.class.getSimpleName(), CONFIG_ERROR, "missing poi configuration"); } List replaceDevList = poiConfig.getItemValue("findreplace"); String eval = poiConfig.getItemValueString("eval"); try { this.updateFileData(document.getFileData(targetName), document, replaceDevList, eval); } catch (PluginException | IOException e) { throw new PluginException(ZahlungsavisExportAdapter.class.getSimpleName(), ERROR_CONFIG, "failed to update zahlungsavis - wrong POI configuraiton: " + e.getMessage()); } // now we add separate lines for each invoice.... insertInvoiceRows(document, targetName); return document; } /** * This helper method inserts a row for each invoice of the current Zahlunsavis * 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 */ @SuppressWarnings("unchecked") private void insertInvoiceRows(ItemCollection document, String fileName) throws PluginException { List invoiceIDs = document.getItemValue("$workitemref"); FileData fileData = document.getFileData(fileName); // 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("A16"); XSSFRow referenceRow = sheet.getRow(cr.getRow()); int referenceRowPos = 16; int rowPos = 16; // int lastRow = sheet.getLastRowNum(); int lastRow = 999; logger.finest("Last rownum=" + lastRow); sheet.shiftRows(rowPos, lastRow, invoiceIDs.size(), true, true); for (String invoiceID : invoiceIDs) { logger.finest("......copy row..."); ItemCollection invoice = documentService.load(invoiceID); // 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")); if ("credit".equals(invoice.getItemValueString("payment.type"))) { // Gutschrift row.getCell(4).setCellValue(invoice.getItemValueDouble("invoice.total")); row.getCell(5).setCellValue(0.00); } else { // Rechnung row.getCell(4).setCellValue(0.00); row.getCell(5).setCellValue(invoice.getItemValueDouble("invoice.total")); } rowPos++; } // delete reference row 16 sheet.shiftRows(referenceRowPos, lastRow + invoiceIDs.size(), -1, true, true); // finally update the total formula... evalXSSFSheet(doc, sheet, "TOTAL"); 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 document.addFileData(fileDataNew); logger.finest("......new document added"); } catch (IOException e) { throw new PluginException(ZahlungsavisExportAdapter.class.getSimpleName(), ERROR_CONFIG, "failed to update zahlungsavis: " + e.getMessage()); } } /** * This method loads a text-block for a specified ref and appends the named * fileData object of this document. * * @param document * @throws PluginException */ private void appendExcelTemplate(ItemCollection document, String textblockRef, String template, String targetName) throws PluginException { if ((template == null || template.isEmpty()) || (textblockRef == null || textblockRef.isEmpty())) { throw new PluginException(ZahlungsavisExportAdapter.class.getSimpleName(), ERROR_CONFIG, "invalid zahlungsavis configuration in model event - textblock/template reference not defined!"); } // load the text block FileData fileData = loadTextBlockFileData(textblockRef, template); // do we found the document? if (fileData == null) { throw new PluginException(ZahlungsavisExportAdapter.class.getSimpleName(), ERROR_CONFIG, "invalid zahlungsavis configuration in model event - template=" + template + " not found!"); } fileData.setName(targetName); // append document logger.info("...append new Zahlugnsavis Template: " + targetName); document.addFileData(fileData); } /** * 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; } }