diff --git a/office-alexander-logistics-app/pom.xml b/office-alexander-logistics-app/pom.xml index f164950..3809eb2 100644 --- a/office-alexander-logistics-app/pom.xml +++ b/office-alexander-logistics-app/pom.xml @@ -6,7 +6,7 @@ office-alexander-logistics com.alexander-logistics - 1.3.0 + 1.3.1 office-alexander-logistics-app war diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticExcelAdapterDebitor.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticExcelAdapterDebitor.java index aa9e948..7a24e5b 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticExcelAdapterDebitor.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/AGLAnalyticExcelAdapterDebitor.java @@ -23,6 +23,7 @@ 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.POIUtil; import org.imixs.workflow.util.XMLParser; import jakarta.inject.Inject; @@ -61,255 +62,318 @@ import jakarta.inject.Inject; */ public class AGLAnalyticExcelAdapterDebitor extends POIFindReplaceAdapter { - private static Logger logger = Logger.getLogger(AGLAnalyticExcelAdapter.class.getName()); + private static Logger logger = Logger.getLogger(AGLAnalyticExcelAdapter.class.getName()); - @Inject - WorkflowService workflowService; + @Inject + WorkflowService workflowService; - @Inject - OPListExportService opListExportService; + @Inject + OPListExportService opListExportService; - @Inject - DocumentService documentService; + @Inject + DocumentService documentService; - @Inject - ConfigService configService; + @Inject + ConfigService configService; - /** - * This method - * - * @throws PluginException - */ - @SuppressWarnings("unchecked") - @Override - public ItemCollection execute(ItemCollection document, ItemCollection event) - throws AdapterException, PluginException { + /** + * This method + * + * @throws PluginException + */ + @SuppressWarnings("unchecked") + @Override + public ItemCollection execute(ItemCollection document, ItemCollection event) + throws AdapterException, PluginException { - // ermittle die Hauptwährungen - ItemCollection configItemCollection = configService.loadConfiguration("AGL_CONFIGURATION"); - List currencyList = configItemCollection.getItemValue("currency.out"); - if (currencyList == null || currencyList.size() < 2) { - throw new PluginException(AGLAnalyticExcelAdapter.class.getSimpleName(), - OPListExportService.ERROR_CONFIG, - "missing Currency configuration - please check parameters"); - } - - // read the Steuerbescheide options - ItemCollection ausgangsrechnungConfig = workflowService.evalWorkflowResult(event, "soa", - document, - false); - if (ausgangsrechnungConfig == null || !ausgangsrechnungConfig.hasItem("excel-export")) { - throw new PluginException(AGLAnalyticExcelAdapterDebitor.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 { - appendExcelTemplate(document, textblock, template, targetName); - insertInvoiceRows(document, targetName); - - logger.info("... loading poi configuration.."); - // 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"); - - logger.info("... update template with normal poi information.."); - this.updateFileData(document.getFileData(targetName), document, replaceDevList, eval); - - } catch (PluginException | IOException | QueryException e) { - throw new PluginException(AGLAnalyticExcelAdapter.class.getSimpleName(), - OPListExportService.ERROR_CONFIG, - "failed to update steuerbescheide: " + e.getMessage()); - } - logger.info("... completed!"); - return document; + // ermittle die Hauptwährungen + ItemCollection configItemCollection = configService.loadConfiguration("AGL_CONFIGURATION"); + List currencyList = configItemCollection.getItemValue("currency.out"); + if (currencyList == null || currencyList.size() < 1) { + throw new PluginException(AGLAnalyticExcelAdapter.class.getSimpleName(), + OPListExportService.ERROR_CONFIG, + "missing Currency configuration - please check parameters"); } - /** - * 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; + // read the options + ItemCollection ausgangsrechnungConfig = workflowService.evalWorkflowResult(event, "soa", + document, + false); + if (ausgangsrechnungConfig == null || !ausgangsrechnungConfig.hasItem("excel-export")) { + throw new PluginException(AGLAnalyticExcelAdapterDebitor.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)); - /** - * 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(ItemCollection document, String fileName) - throws PluginException, QueryException { + String textblock = excelDefCollection.getItemValueString("textblock"); + String template = excelDefCollection.getItemValueString("template"); + String targetName = excelDefCollection.getItemValueString("target-name"); - // load dummy rechnungen - List invoices = loadInvoices(getDbtNr(document)); + // adapt text.... + targetName = workflowService.adaptText(targetName, document); - FileData fileData = document.getFileData(fileName); + try { + FileData fileData = appendExcelTemplate(document, textblock, template, targetName); - // load XSSFWorkbook - 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); - 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); + // 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); - // jetzt füge alle Rechnungen an. - int totalRowCount = invoices.size(); - sheet.shiftRows(referenceRowPos, lastRow, totalRowCount, true, true); - 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")); + // first add the columns for the currency list + addCurrencyColumns(sheet, currencyList); - // Waehrung? - if (invoice.getItemValueDouble("invoice.rate") == 0) { - row.getCell(6, MissingCellPolicy.CREATE_NULL_AS_BLANK) - .setCellValue(invoice.getItemValueDouble("invoice.total")); - row.getCell(7, MissingCellPolicy.CREATE_NULL_AS_BLANK) - .setCellValue(invoice.getItemValueDouble("invoice.saldo")); - } else { - row.getCell(8, MissingCellPolicy.CREATE_NULL_AS_BLANK) - .setCellValue(invoice.getItemValueDouble("invoice.total")); - row.getCell(9, MissingCellPolicy.CREATE_NULL_AS_BLANK) - .setCellValue(invoice.getItemValueDouble("invoice.saldo")); - } - row.getCell(10, MissingCellPolicy.CREATE_NULL_AS_BLANK) - .setCellValue(invoice.getItemValueString("$workflowstatus")); + // insertInvoiceRows(document, targetName); - rowPos++; - } + // write back the updated excel file + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + doc.write(byteArrayOutputStream); - // Leerzeile - // categoryRow = sheet.createRow(rowPos); - rowPos++; + byte[] newContent = byteArrayOutputStream.toByteArray(); + FileData fileDataNew = new FileData(fileData.getName(), newContent, fileData.getContentType(), + null); + document.addFileData(fileDataNew); + logger.finest("......new document added"); - // write back the file - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - doc.write(byteArrayOutputStream); - - 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(AGLAnalyticExcelAdapter.class.getSimpleName(), - OPListExportService.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(); - } - } - } - } - - /** - * 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(AGLAnalyticExcelAdapter.class.getSimpleName(), - OPListExportService.ERROR_CONFIG, - "invalid SOA configuration in model event - textblock/template reference not defined!"); - } - - // load the text block - FileData fileData = opListExportService.loadTextBlockFileData(textblockRef, template); - - // do we found the document? - if (fileData == null) { - throw new PluginException(AGLAnalyticExcelAdapter.class.getSimpleName(), - OPListExportService.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); - - } - - /** - * Diese Methode läd alle offenen Steuerbescheide - * - * @return - */ - private List loadInvoices(String dbtrNumber) { - List result = new ArrayList<>(); - - String query = "(type:workitem) AND dbtr.number:" + dbtrNumber - + " AND $modelversion:rechnungsausgang-*"; - try { - result = documentService.find( - query, 9999, 0, - "invoice.number", false); - } catch (QueryException e) { + } catch (IOException e) { + throw new PluginException(AGLAnalyticExcelAdapter.class.getSimpleName(), + OPListExportService.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(); + } } - return result; + } + + // Process POI instructions + // processPOIUpdate(document, event, targetName); + // // 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"); + + // logger.info("... update template with normal poi information.."); + // this.updateFileData(document.getFileData(targetName), document, + // replaceDevList, eval); + + } catch (PluginException e) { + throw new PluginException(AGLAnalyticExcelAdapter.class.getSimpleName(), + OPListExportService.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(XSSFSheet sheet, List currencyList) { + if (currencyList == null || currencyList.size() <= 1) { + // no extra currencies defined! + return; + } + int newColumns = (currencyList.size() - 1) * 2; + + for (int i = 0; i < newColumns; i++) { + logger.info(".. add currency column..."); + POIUtil.insertColumn(sheet, 6, 8 + i); + // POIUtil.insertColumn(sheet, 6, 8 + i+1); + } + + } + + /** + * 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; + } + + /** + * 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(ItemCollection document, String fileName) + throws PluginException, QueryException { + + // load dummy rechnungen + List invoices = loadInvoices(getDbtNr(document)); + + FileData fileData = document.getFileData(fileName); + + // load XSSFWorkbook + 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); + 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(); + sheet.shiftRows(referenceRowPos, lastRow, totalRowCount, true, true); + 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? + if (invoice.getItemValueDouble("invoice.rate") == 0) { + row.getCell(6, MissingCellPolicy.CREATE_NULL_AS_BLANK) + .setCellValue(invoice.getItemValueDouble("invoice.total")); + row.getCell(7, MissingCellPolicy.CREATE_NULL_AS_BLANK) + .setCellValue(invoice.getItemValueDouble("invoice.saldo")); + } else { + row.getCell(8, MissingCellPolicy.CREATE_NULL_AS_BLANK) + .setCellValue(invoice.getItemValueDouble("invoice.total")); + row.getCell(9, MissingCellPolicy.CREATE_NULL_AS_BLANK) + .setCellValue(invoice.getItemValueDouble("invoice.saldo")); + } + row.getCell(10, MissingCellPolicy.CREATE_NULL_AS_BLANK) + .setCellValue(invoice.getItemValueString("$workflowstatus")); + + rowPos++; + } + + // Leerzeile + // categoryRow = sheet.createRow(rowPos); + rowPos++; + + // write back the file + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + doc.write(byteArrayOutputStream); + + 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(AGLAnalyticExcelAdapter.class.getSimpleName(), + OPListExportService.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(); + } + } + } + } + + /** + * 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(), + OPListExportService.ERROR_CONFIG, + "invalid SOA configuration in model event - textblock/template reference not defined!"); + } + + // load the text block + FileData fileData = opListExportService.loadTextBlockFileData(textblockRef, template); + + // do we found the document? + if (fileData == null) { + throw new PluginException(AGLAnalyticExcelAdapter.class.getSimpleName(), + OPListExportService.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(String dbtrNumber) { + List result = new ArrayList<>(); + + String query = "(type:workitem) AND dbtr.number:" + dbtrNumber + + " AND $modelversion:rechnungsausgang-*"; + try { + result = documentService.find( + query, 9999, 0, + "invoice.number", false); + } catch (QueryException e) { + e.printStackTrace(); + } + return result; + } } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2d72a65..00de23b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.alexander-logistics office-alexander-logistics - 1.3.0 + 1.3.1 pom Imixs Office Workflow - Custom Build @@ -29,7 +29,7 @@ 6.0.9-SNAPSHOT 5.0.0 3.0.2 - 3.0.2 + 3.0.3-SNAPSHOT 2.0.2 6.0 9.9.1-4 diff --git a/workflow/analyse-debitor-de-1.0.0.bpmn b/workflow/analyse-debitor-de-1.0.0.bpmn index 4554a23..cfffce1 100644 --- a/workflow/analyse-debitor-de-1.0.0.bpmn +++ b/workflow/analyse-debitor-de-1.0.0.bpmn @@ -90,6 +90,7 @@ th { font-weight: bold;} DataObject_1 event_HrHS9A dataObject_00mX6w + event_n40tzw @@ -124,6 +125,7 @@ th { font-weight: bold;} SequenceFlow_10 sequenceFlow_OL83kQ sequenceFlow_1K0l0g + sequenceFlow_P2Q9fQ @@ -322,36 +324,7 @@ th { font-weight: bold;} soa_dbtr.number_$lasteventdate.xlsx - - I6 - $lasteventdate - date - - - D6 - dbtr.name - date - - - G10 - Total EUR - - - H10 - Saldo EUR - - - I10 - Total USD - - - J10 - Saldo USD - - - -TOTAL1;TOTAL2;TOTAL3;TOTAL4 ]]> @@ -391,6 +364,84 @@ th { font-weight: bold;} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + SOA Template + + soa_dbtr.number_$lasteventdate.xlsx + + + + + + + + +]]> + + + + + sequenceFlow_P2Q9fQ + + + + @@ -494,6 +545,18 @@ th { font-weight: bold;} + + + + + + + + + + + +