package com.alexanderlogistics.dataview; import java.util.List; import java.util.logging.Logger; import org.apache.poi.ss.usermodel.CellCopyPolicy; import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.imixs.workflow.ItemCollection; import org.imixs.workflow.dataview.DataViewExportEvent; import org.imixs.workflow.engine.DocumentService; import org.imixs.workflow.engine.WorkflowService; import org.imixs.workflow.exceptions.PluginException; import org.imixs.workflow.exceptions.QueryException; import org.imixs.workflow.office.config.ConfigService; import org.imixs.workflow.poi.POIFindReplaceAdapter; import org.imixs.workflow.poi.XSSFUtil; import com.alexanderlogistics.InvoiceService; import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; /** * Der AGLDataViewDebitorAdapter exportiert eine Dateview in eine Excel Datei * und berücksichtigt dabei separate Spalten für die Währungen * * * @version 1.0 * @author rsoika */ public class AGLDataViewDebitorAdapter extends POIFindReplaceAdapter { private static Logger logger = Logger.getLogger(AGLDataViewDebitorAdapter.class.getName()); @Inject WorkflowService workflowService; @Inject InvoiceService invoiceService; @Inject DocumentService documentService; @Inject ConfigService configService; /** * Spezial Adapter der den Debitor exporteirt. * * @param event */ public void onEvent(@Observes DataViewExportEvent event) { if ("Debitor SOA".equals(event.getDataViewDefinition().getItemValueString("name"))) { try { logger.info("Custom Insert Rows for Debitor SOA"); // ermittle die Hauptwährungen List currencyList; currencyList = invoiceService.getCurrenciesOut(); // NOTE: we only take the first sheet ! XSSFSheet sheet = event.getXssfWorkbook().getSheetAt(0); // first add the columns for the currency list addCurrencyColumns(event.getXssfWorkbook(), sheet, currencyList); // add rows insertInvoiceRows(sheet, event.getDataset(), currencyList); event.setCompleted(true); } catch (PluginException | QueryException e) { logger.severe("Failed to insert rows: " + e.getMessage()); } } } // /** // * This method // * // * @throws PluginException // */ // @SuppressWarnings("unchecked") // @Override // public ItemCollection execute(ItemCollection document, ItemCollection event) // throws AdapterException, PluginException { // // ermittle die Hauptwährungen // List currencyList = invoiceService.getCurrenciesOut(); // // read the options // ItemCollection ausgangsrechnungConfig = // workflowService.evalWorkflowResult(event, "soa", document, false); // if (ausgangsrechnungConfig == null || // !ausgangsrechnungConfig.hasItem("excel-export")) { // throw new PluginException(AGLDataViewAdapterDebitor.class.getSimpleName(), // CONFIG_ERROR, // "missing soa configuration in model event - please check model // configuration"); // } // List excelDefList = // ausgangsrechnungConfig.getItemValue("excel-export"); // ItemCollection excelDefCollection = // XMLParser.parseItemStructure(excelDefList.get(0)); // String textblock = excelDefCollection.getItemValueString("textblock"); // String template = excelDefCollection.getItemValueString("template"); // String targetName = excelDefCollection.getItemValueString("target-name"); // // adapt text.... // targetName = workflowService.adaptText(targetName, document); // try { // FileData fileData = appendExcelTemplate(document, textblock, template, // targetName); // // get workbook // XSSFWorkbook doc = null; // try (InputStream imputStream = new // ByteArrayInputStream(fileData.getContent())) { // doc = new XSSFWorkbook(imputStream); // // NOTE: we only take the first sheet ! // XSSFSheet sheet = doc.getSheetAt(0); // // first add the columns for the currency list // addCurrencyColumns(doc, sheet, currencyList); // // add rows // insertInvoiceRows(sheet, document, currencyList); // // write back the updated excel file // ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // doc.write(byteArrayOutputStream); // byte[] newContent = byteArrayOutputStream.toByteArray(); // FileData fileDataNew = new FileData(fileData.getName(), newContent, // fileData.getContentType(), null); // document.addFileData(fileDataNew); // logger.finest("......new document added"); // } catch (IOException | QueryException e) { // throw new PluginException(AGLAnalyticExcelAdapter.class.getSimpleName(), // InvoiceService.ERROR_CONFIG, // "failed to update opliste: " + e.getMessage()); // } finally { // if (doc != null) { // try { // doc.close(); // } catch (IOException e) { // logger.severe("Failed to close workbook: " + e.getMessage()); // e.printStackTrace(); // } // } // } // // Finally process POI instructions // processPOIUpdate(document, event, targetName); // } catch (PluginException e) { // throw new PluginException(AGLAnalyticExcelAdapter.class.getSimpleName(), // InvoiceService.ERROR_CONFIG, // "failed to update steuerbescheide: " + e.getMessage()); // } // logger.info("... completed!"); // return document; // } /** * A SOA can be created for one or multiple currencies. This helper method adds * the Total and Saldo Colum for each currency * * The template provided only the columns for the first currency. * * @param sheet * @param currencyList */ private void addCurrencyColumns(XSSFWorkbook doc, XSSFSheet sheet, List currencyList) { if (currencyList == null || currencyList.size() <= 1) { // no extra currencies defined! return; } // zusaetzliche Zellen einfuegen... int newColumns = (currencyList.size() - 1) * 2; for (int i = 0; i < newColumns; i++) { logger.info(".. add currency column..."); XSSFUtil.insertColumn(sheet, 6, 8 + i); } // Beschriftungen eintragen int col = 6; XSSFCell cell = null; XSSFRow labelRow = sheet.getRow(9); for (String currency : currencyList) { cell = labelRow.getCell(col); cell.setCellValue("Total " + currency); col++; cell = labelRow.getCell(col); cell.setCellValue("Balance " + currency); col++; } } /** * Hilfsmethode die das fuehrende K/D aus der Debitorennummer entfernt * * @return */ private String getDbtNr(ItemCollection workitem) { String dbtNr = workitem.getItemValueString("dbtr.number"); if (dbtNr.startsWith("D") || dbtNr.startsWith("K")) { dbtNr = dbtNr.substring(1); } return dbtNr; } /** * Hilfsmethode die auch alte Rechnungen ohne D/K findet * * @return */ private String getDbtNrQuery(ItemCollection workitem) { String dbtNr = workitem.getItemValueString("dbtr.number"); String shortDbtNr = dbtNr.substring(1); String query = " (dbtr.number:" + dbtNr + " OR dbtr.number:" + shortDbtNr + ") "; return query; } /** * This helper method inserts a row for each invoice 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(XSSFSheet sheet, List invoices, List currencyList) throws PluginException, QueryException { // load XSSFWorkbook CellReference invoiceRefCell = new CellReference("A11"); XSSFRow referenceRowInvoice = sheet.getRow(invoiceRefCell.getRow()); int referenceRowPos = 10; int rowPos = referenceRowPos; int lastRow = 2999; logger.finest("Last rownum=" + lastRow); // jetzt füge alle Rechnungen an. int totalRowCount = invoices.size(); XSSFUtil.insertRows(sheet, "A11", totalRowCount - 0); for (ItemCollection invoice : invoices) { logger.fine("......add invoice " + invoice.getUniqueID()); // now create a new line.. XSSFRow row = sheet.createRow(rowPos); row.copyRowFrom(referenceRowInvoice, new CellCopyPolicy()); // insert values row.getCell(0).setCellValue(invoice.getItemValueDate("$created")); row.getCell(1, MissingCellPolicy.CREATE_NULL_AS_BLANK) .setCellValue(invoice.getItemValueString("invoice.number")); row.getCell(2, MissingCellPolicy.CREATE_NULL_AS_BLANK) .setCellValue(invoice.getItemValueDate("invoice.date")); row.getCell(3, MissingCellPolicy.CREATE_NULL_AS_BLANK) .setCellValue(invoice.getItemValueDate("invoice.duedate")); row.getCell(4, MissingCellPolicy.CREATE_NULL_AS_BLANK) .setCellValue(invoice.getItemValueString("space.name")); row.getCell(5, MissingCellPolicy.CREATE_NULL_AS_BLANK) .setCellValue(invoice.getItemValueString("invoice.text")); // Waehrung? String currency = invoice.getItemValueString("invoice.currency"); int totalCol = findTotalPos(currency, currencyList); row.getCell(totalCol, MissingCellPolicy.CREATE_NULL_AS_BLANK) .setCellValue(invoice.getItemValueDouble("invoice.total")); row.getCell(totalCol + 1, MissingCellPolicy.CREATE_NULL_AS_BLANK) .setCellValue(invoice.getItemValueDouble("invoice.saldo")); // Status row.getCell(6 + (currencyList.size() * 2), MissingCellPolicy.CREATE_NULL_AS_BLANK) .setCellValue(invoice.getItemValueString("$workflowstatus")); rowPos++; } // setze Summen Formeln for (int column = 6; column < currencyList.size() * 2 + 6; column++) { XSSFCell cell = sheet.getRow(totalRowCount + 11).getCell(column); // G11 String cellRefFrom = XSSFUtil.getCellReference(column, 10); String cellRefTo = XSSFUtil.getCellReference(column, totalRowCount + 10); String formula = "SUM(" + cellRefFrom + ":" + cellRefTo + ")"; cell.setCellFormula(formula); } // Optional: Formel direkt evaluieren XSSFFormulaEvaluator.evaluateAllFormulaCells(sheet.getWorkbook()); } /** * Findet die Total Spalte für eine Währung * * @param currency * @return */ private int findTotalPos(String currency, List currencyList) { int result = 6; if (currency != null) { for (String cur : currencyList) { if (currency.equals(cur)) { return result; } result = result + 2; } } return result; } /** * This method loads a text-block for a specified ref and appends the named * fileData object of this document. * * @param document * @throws PluginException */ // private FileData appendExcelTemplate(ItemCollection document, String // textblockRef, String template, // String targetName) throws PluginException { // if ((template == null || template.isEmpty()) || (textblockRef == null || // textblockRef.isEmpty())) { // throw new PluginException(AGLAnalyticExcelAdapter.class.getSimpleName(), // InvoiceService.ERROR_CONFIG, // "invalid SOA configuration in model event - textblock/template reference not // defined!"); // } // // load the text block // FileData fileData = invoiceService.loadTextBlockFileData(textblockRef, // template); // // do we found the document? // if (fileData == null) { // throw new PluginException(AGLAnalyticExcelAdapter.class.getSimpleName(), // InvoiceService.ERROR_CONFIG, // "invalid SOA configuration in model event - template=" + template + " not // found!"); // } // fileData.setName(targetName); // // append document // logger.info("...append new SOA Template: " + targetName); // document.addFileData(fileData); // return fileData; // } /** * Diese Methode läd alle offenen Steuerbescheide * * @return */ // private List loadInvoices(ItemCollection workitem) { // List result = new ArrayList<>(); // String query = "(type:workitem) AND " + getDbtNrQuery(workitem) + " AND // $modelversion:rechnungsausgang-*"; // try { // result = documentService.find(query, 9999, 0, "invoice.number", false); // } catch (QueryException e) { // e.printStackTrace(); // } // return result; // } }