344 lines
11 KiB
Java
344 lines
11 KiB
Java
package com.alexanderlogistics.mahnlauf;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.io.Serializable;
|
|
import java.text.SimpleDateFormat;
|
|
import java.time.YearMonth;
|
|
import java.time.ZoneId;
|
|
import java.util.Calendar;
|
|
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.usermodel.Name;
|
|
import org.apache.poi.ss.util.CellReference;
|
|
import org.apache.poi.xssf.usermodel.XSSFCell;
|
|
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.exceptions.PluginException;
|
|
import org.imixs.workflow.exceptions.QueryException;
|
|
import org.imixs.workflow.faces.data.DocumentController;
|
|
import org.imixs.workflow.faces.data.WorkflowController;
|
|
import org.imixs.workflow.office.forms.CustomFormItem;
|
|
|
|
import com.alexanderlogistics.ZahlungsavisExportAdapter;
|
|
|
|
import jakarta.annotation.PostConstruct;
|
|
import jakarta.enterprise.context.ConversationScoped;
|
|
import jakarta.faces.context.ExternalContext;
|
|
import jakarta.faces.context.FacesContext;
|
|
import jakarta.inject.Inject;
|
|
import jakarta.inject.Named;
|
|
|
|
/**
|
|
* Der ExcelExportController exportiert rechnungen anhand von Filterangaben
|
|
* (excel_export_rechnungsausgang.xhmlt) nach Excel.
|
|
*
|
|
* Die Ausgabe ist auf maximal 3000 Zeilen eingeschränkt
|
|
*
|
|
* @author rsoika
|
|
*
|
|
*/
|
|
@Named
|
|
@ConversationScoped
|
|
public class ExcelExportController implements Serializable {
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
private static Logger logger = Logger.getLogger(ExcelExportController.class.getName());
|
|
|
|
public static final String ERROR_CONFIG = "CONFIG_ERROR";
|
|
final String TYPE_TEXTBLOCK = "textblock";
|
|
|
|
public static final int MAX_ROWS = 3000;
|
|
@Inject
|
|
protected DocumentService documentService;
|
|
|
|
@Inject
|
|
WorkflowController workflowController;
|
|
|
|
@Inject
|
|
DocumentController documentController;
|
|
|
|
@Inject
|
|
SnapshotService snapshotService;
|
|
|
|
private ItemCollection filter;
|
|
private CustomFormItem dbtrItem;
|
|
|
|
public ExcelExportController() {
|
|
}
|
|
|
|
@PostConstruct
|
|
public void init() {
|
|
reset();
|
|
}
|
|
|
|
public ItemCollection getFilter() {
|
|
return filter;
|
|
}
|
|
|
|
public void setFilter(ItemCollection filter) {
|
|
this.filter = filter;
|
|
}
|
|
|
|
/**
|
|
* Fuert verschiedene Queries aus um eine Analyse der Sachprufung durchzuführen.
|
|
*
|
|
* @throws PluginException
|
|
*/
|
|
public String export() throws PluginException {
|
|
|
|
logger.info("start export....");
|
|
Date start = filter.getItemValueDate("start");
|
|
Date stop = filter.getItemValueDate("stop");
|
|
logger.info("...daterange=" + start + " - " + stop);
|
|
|
|
// serach date range?
|
|
String sDateFrom = "191401070000"; // because * did not work here
|
|
String sDateTo = "211401070000";
|
|
SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMMddHHmm");
|
|
|
|
if (start != null) {
|
|
Calendar cal = Calendar.getInstance();
|
|
cal.setTime(start);
|
|
sDateFrom = dateformat.format(cal.getTime());
|
|
}
|
|
if (stop != null) {
|
|
Calendar cal = Calendar.getInstance();
|
|
cal.setTime(stop);
|
|
cal.add(Calendar.DATE, 1);
|
|
sDateTo = dateformat.format(cal.getTime());
|
|
}
|
|
|
|
// query zeit
|
|
String query = "(type:workitem OR type:workitemarchive) AND ($workflowgroup:Rechnungsausgang) ";
|
|
if (start != null && stop != null) {
|
|
query += "AND (invoice.date:[" + sDateFrom + " TO " + sDateTo + "]) ";
|
|
} else {
|
|
throw new PluginException("ERROR", "Bitte geben Sie einen Zeitraum an", null);
|
|
}
|
|
logger.info(query);
|
|
|
|
// query Sachprüfung
|
|
|
|
if (!filter.getItemValueString("space.ref").isEmpty()
|
|
&& !"-".equals(filter.getItemValueString("space.ref"))) {
|
|
query += " AND ($uniqueidref:" + filter.getItemValueString("space.ref") + ")";
|
|
}
|
|
if (workflowController.getWorkitem() != null
|
|
&& !workflowController.getWorkitem().getItemValueString("dbtr.number").isEmpty()) {
|
|
query += " AND (dbtr.number:" + workflowController.getWorkitem().getItemValueString("dbtr.number") + ")";
|
|
}
|
|
if (!filter.getItemValueString("invoice.text").isEmpty()) {
|
|
query += " AND (invoice.positions:" + filter.getItemValueString("invoice.text") + ")";
|
|
}
|
|
|
|
// load the text block
|
|
String template = "ausgangsrechnungen-export_template.xlsx";
|
|
FileData fileData = loadTextBlockFileData("Excel-Export Template", template);
|
|
|
|
// do we found the document?
|
|
if (fileData == null) {
|
|
throw new PluginException(InkassoExportAdapter.class.getSimpleName(), ERROR_CONFIG,
|
|
"Missing Excel Export Template - template=" + template + " not found!");
|
|
}
|
|
String targetName = "ausgangsrechnungen-export_" + dateformat.format(new Date()) + ".xlsx";
|
|
try {
|
|
List<ItemCollection> invoices = documentService.find(query, MAX_ROWS, 0, "invoice.date", true);
|
|
if (invoices.size() > 0) {
|
|
insertInvoiceRows(invoices, fileData);
|
|
}
|
|
fileData.setName(targetName);
|
|
|
|
// See:
|
|
// https://stackoverflow.com/questions/9391838/how-to-provide-a-file-download-from-a-jsf-backing-bean
|
|
download(fileData);
|
|
} catch (IOException | QueryException e) {
|
|
throw new PluginException(InkassoExportAdapter.class.getSimpleName(), ERROR_CONFIG,
|
|
"Failed to generate Excel Export: " + e.getMessage());
|
|
}
|
|
|
|
logger.info("Query=" + query);
|
|
return "/pages/admin/excel_export_rechnungsausgang.jsf?faces-redirect=true";
|
|
}
|
|
|
|
/**
|
|
* Helper method to initialize a download
|
|
*
|
|
* @throws IOException
|
|
*/
|
|
public void download(FileData fileData) throws IOException {
|
|
|
|
FacesContext facesContext = FacesContext.getCurrentInstance();
|
|
ExternalContext externalContext = facesContext.getExternalContext();
|
|
|
|
externalContext.responseReset();
|
|
externalContext.setResponseContentType("application/vnd.ms-excel");
|
|
externalContext.setResponseContentLength(fileData.getContent().length);
|
|
externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"" + fileData.getName() + "\"");
|
|
|
|
OutputStream output = externalContext.getResponseOutputStream();
|
|
|
|
// Now you can write the InputStream of the file to the above OutputStream the
|
|
// usual way.
|
|
output.write(fileData.getContent());
|
|
|
|
facesContext.responseComplete(); // Important! Otherwise Faces will attempt to render the response which
|
|
// obviously will fail since it's already written with a file and closed.
|
|
}
|
|
|
|
/**
|
|
* This method returns a text-block ItemCollection for a specified name.
|
|
*
|
|
* @param name in attribute txtname
|
|
*
|
|
*
|
|
*/
|
|
private 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;
|
|
}
|
|
|
|
/**
|
|
* This method reset the search and input state.
|
|
*/
|
|
public void reset() {
|
|
filter = new ItemCollection();
|
|
|
|
// compute start stop based on current month
|
|
YearMonth startYearMonth = YearMonth.now();
|
|
java.time.LocalDate startOfMonthDate = startYearMonth.atDay(1);
|
|
java.time.LocalDate endOfMonthDate = startYearMonth.atEndOfMonth();
|
|
filter.setItemValue("start",
|
|
java.util.Date.from(startOfMonthDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
|
|
filter.setItemValue("stop",
|
|
java.util.Date.from(endOfMonthDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
|
|
workflowController.setWorkitem(new ItemCollection());
|
|
|
|
// debtr item
|
|
dbtrItem = new CustomFormItem("dbtr.number", "text", "", false, false, false, "", null, false, 0);
|
|
|
|
}
|
|
|
|
public CustomFormItem getItem() {
|
|
// dbtrItem.setName("dbtr.number");
|
|
return dbtrItem;
|
|
}
|
|
|
|
/**
|
|
* This helper method inserts a row for each invoice
|
|
*
|
|
* @throws PluginException
|
|
*/
|
|
private void insertInvoiceRows(List<ItemCollection> invoices, FileData fileData) throws PluginException {
|
|
// 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);
|
|
|
|
XSSFCell standCell = getCellByRef(doc, sheet, "F6");
|
|
standCell.setCellValue(new Date());
|
|
|
|
CellReference cr = new CellReference("A11");
|
|
XSSFRow referenceRow = sheet.getRow(cr.getRow());
|
|
int referenceRowPos = referenceRow.getRowNum() + 1;
|
|
int rowPos = referenceRowPos;
|
|
// 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(invoice.getItemValueString("invoice.number"));
|
|
row.getCell(1).setCellValue(invoice.getItemValueString("dbtr.number"));
|
|
row.getCell(2).setCellValue(invoice.getItemValueString("space.name"));
|
|
row.getCell(3).setCellValue(invoice.getItemValueString("invoice.text"));
|
|
row.getCell(4).setCellValue(invoice.getItemValueDate("invoice.date"));
|
|
row.getCell(5).setCellValue(invoice.getItemValueDate("invoice.duedate"));
|
|
row.getCell(6).setCellValue(invoice.getItemValueDouble("invoice.total"));
|
|
|
|
rowPos++;
|
|
}
|
|
// delete reference row
|
|
sheet.shiftRows(referenceRowPos, lastRow + invoices.size(), -1, true, true);
|
|
|
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
// write back the file
|
|
doc.write(byteArrayOutputStream);
|
|
doc.close();
|
|
byte[] newContent = byteArrayOutputStream.toByteArray();
|
|
fileData.setContent(newContent);
|
|
|
|
} catch (IOException e) {
|
|
throw new PluginException(ZahlungsavisExportAdapter.class.getSimpleName(), ERROR_CONFIG,
|
|
"failed to update excel export: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a Cell by name or an optional absolute cell postion
|
|
* <p>
|
|
* Examples for refs are 'A1', 'AB3', 'MyCell' where 'MyCell' is a named cell.
|
|
* <p>
|
|
*
|
|
*/
|
|
public static XSSFCell getCellByRef(XSSFWorkbook doc, XSSFSheet sheet, String cellReference) {
|
|
XSSFCell cell = null;
|
|
|
|
// first we test if the cellName is a named cell
|
|
Name aNamedCell = doc.getName(cellReference);
|
|
if (aNamedCell != null) {
|
|
// yes its a named cell so we need to get the referrer Formula
|
|
logger.finest("...resolving named cell = " + aNamedCell.getNameName());
|
|
cellReference = aNamedCell.getRefersToFormula();
|
|
// now we can find the cell by its ref
|
|
}
|
|
|
|
CellReference cr = new CellReference(cellReference);
|
|
XSSFRow row = sheet.getRow(cr.getRow());
|
|
if (row == null) {
|
|
logger.severe("Unable to resolve cell ref '" + cellReference + "'!");
|
|
return null;
|
|
}
|
|
cell = row.getCell(cr.getCol());
|
|
return cell;
|
|
}
|
|
|
|
}
|