255 lines
No EOL
10 KiB
Java
255 lines
No EOL
10 KiB
Java
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
|
|
*
|
|
* <pre>
|
|
* {@code
|
|
<zahlungsavis name="textblock">textblock-ref</zahlungsavis>
|
|
<zahlungsavis name="template">filename</zahlungsavis>
|
|
<zahlungsavis name="targetname">filename</zahlungsavis>
|
|
}
|
|
* </pre>
|
|
* <p>
|
|
* Der Adapter erweitert den POIAdapter somit können felder aktualisiert werden
|
|
* (siehe POIFineReplaceAdapter).
|
|
*
|
|
* <p>
|
|
* Der Adapter kopiert die Rechnungsdaten in neue Zeilen, welche ab Zeilnenummer
|
|
* 16 eingefügt werden.
|
|
* <p>
|
|
* Dabei werden Gutschriften in spalte E und Rechnungen in Spalte F eingetrgen.
|
|
* <p>
|
|
* 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<String> 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
|
|
* <p>
|
|
* The method copies the Row A16 as a reference row
|
|
* <p>
|
|
* 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<String> 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<ItemCollection> 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;
|
|
}
|
|
|
|
} |