OP Listen update

This commit is contained in:
Ralph Soika 2023-03-07 16:23:11 +01:00
parent 1338d9aae8
commit f6bb14c8de
5 changed files with 679 additions and 418 deletions

View file

@ -6,6 +6,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -58,6 +59,9 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
private static Logger logger = Logger.getLogger(OPListExportAdapter.class.getName());
public static final String ERROR_CONFIG = "CONFIG_ERROR";
public static final int TASK_MAHNUNG_2ND = 5210;
public static final int TASK_MAHNUNG_LAST = 5220;
final String TYPE_TEXTBLOCK = "textblock";
@Inject
@ -69,6 +73,7 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
@Inject
SnapshotService snapshotService;
/**
* This method finds or create the Zahlungsavis and adds a reference
* ($workitemref) to the current invoice.
@ -89,6 +94,7 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
String textblock = evalItemCollection.getItemValueString("textblock");
String template = evalItemCollection.getItemValueString("template");
String targetName = evalItemCollection.getItemValueString("target-name");
boolean filter = evalItemCollection.getItemValueBoolean("filter");
// adapt text....
targetName = workflowService.adaptText(targetName, document);
@ -110,7 +116,7 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
// now we add separate lines for each invoice....
logger.info("... insert invoices..");
insertInvoiceRows(document, targetName);
insertInvoiceRows(document, targetName, filter);
} catch (PluginException | IOException | QueryException e) {
throw new PluginException(OPListExportAdapter.class.getSimpleName(), ERROR_CONFIG,
"failed to update op-liste: " + e.getMessage());
@ -120,8 +126,8 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
}
/**
* This helper method inserts a row for each invoice of the current Zahlunsavis
* at row 16 into the excel template file
* This helper method inserts a row for each invoice of the OPListe at row 16
* into the excel template file
* <p>
* The method copies the Row A16 as a reference row
* <p>
@ -131,7 +137,8 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
* @throws PluginException
* @throws QueryException
*/
private void insertInvoiceRows(ItemCollection document, String fileName) throws PluginException, QueryException {
private void insertInvoiceRows(ItemCollection document, String fileName, boolean filter)
throws PluginException, QueryException {
double saldoUSD = 0;
double saldoEUR = 0;
@ -139,10 +146,10 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
String spaceID = document.getItemValueString("space.ref");
logger.info("... space.ref=" + spaceID + " ...grouping invoices by spaceid....");
Map<String, List<ItemCollection>> invoiceMap = groupInvoicesBySpaceID(spaceID);
Map<String, List<ItemCollection>> invoiceMap = groupInvoicesBySpaceID(spaceID, filter);
FileData fileData = document.getFileData(fileName);
// load XSSFWorkbook
XSSFWorkbook doc = null;
try (InputStream imputStream = new ByteArrayInputStream(fileData.getContent())) {
@ -159,7 +166,7 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
int lastRow = 2999;
logger.finest("Last rownum=" + lastRow);
int totalRowCount = invoiceMap.size()*2;
int totalRowCount = invoiceMap.size() * 2;
for (List<?> list : invoiceMap.values()) {
totalRowCount = totalRowCount + list.size();
}
@ -170,7 +177,6 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
sheet.shiftRows(rowPos, lastRow, totalRowCount, true, true);
for (Map.Entry<String, List<ItemCollection>> entry : invoiceMap.entrySet()) {
String dbtrNumber = entry.getKey();
logger.info("......add debitor " + dbtrNumber);
List<ItemCollection> invoices = entry.getValue();
// erzeuge eine Zwischenüberschrift für den Debitor....
@ -187,18 +193,18 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
for (ItemCollection invoice : invoices) {
if ("EUR".equals(invoice.getItemValueString("invoice.currency"))) {
catSumEUR = catSumEUR + invoice.getItemValueDouble("invoice.saldo");
} else {
catSumUSD = catSumUSD + invoice.getItemValueDouble("invoice.saldo");
}
}
categoryRow.getCell(6).setCellValue(catSumEUR);
categoryRow.getCell(8).setCellValue(catSumUSD);
rowPos++;
// jetzt füge alle Rechnungen an.
for (ItemCollection invoice : invoices) {
logger.fine("......add invoice " + invoice.getUniqueID());
@ -212,23 +218,23 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
row.getCell(4).setCellValue(invoice.getItemValueDate("invoice.date"));
row.getCell(5).setCellValue(invoice.getItemValueDate("invoice.duedate"));
double total = invoice.getItemValueDouble("invoice.saldo");
String currency=invoice.getItemValueString("invoice.currency");
String currency = invoice.getItemValueString("invoice.currency");
if ("EUR".equals(currency)) {
// EUR
row.getCell(6).setCellValue(total);
row.getCell(7).setCellValue(currency);
saldoEUR =roundD( saldoEUR + total);
saldoEUR = roundD(saldoEUR + total);
} else {
// USD
row.getCell(8).setCellValue(total);
row.getCell(9).setCellValue(currency);
saldoUSD = roundD( saldoUSD + total);
saldoUSD = roundD(saldoUSD + total);
}
row.getCell(10).setCellValue(invoice.getItemValueString("$workflowstatus"));
rowPos++;
}
// Leerzeile
categoryRow = sheet.createRow(rowPos);
rowPos++;
@ -334,16 +340,20 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
/**
* Diese Methode groupiert eine Rechnugnsliste nach Debitorennummern
*
* Falls 'filter==true' werden nur Rechnungen ab der 2. Mahnung oder mit einer
* Fälligkeit >21 Tage ausgegeben
*
* @param spaceID
* @return
*/
private Map<String, List<ItemCollection>> groupInvoicesBySpaceID(String spaceID) {
private Map<String, List<ItemCollection>> groupInvoicesBySpaceID(String spaceID, boolean filter) {
Map<String, List<ItemCollection>> result = new HashMap<>();
try {
List<ItemCollection> invoices = documentService.find(
"$modelversion:rechnungsausgang-de-1.0 AND type:workitem AND $uniqueidref:" + spaceID, 9999, 0,"invoice.number",false);
"$modelversion:rechnungsausgang-de-1.0 AND type:workitem AND $uniqueidref:" + spaceID, 9999, 0,
"invoice.number", false);
for (ItemCollection invoice : invoices) {
@ -355,21 +365,40 @@ public class OPListExportAdapter extends POIFindReplaceAdapter {
invoiceList = new ArrayList<ItemCollection>();
}
invoiceList.add(invoice);
if (filter) {
Date date = invoice.getItemValueDate("invoice.duedate");
if (OPListExportAdapter.isOverdue(date, invoice.getTaskID())) {
invoiceList.add(invoice);
}
} else {
// jede Rechnung zählt (manuelle OPListe)
invoiceList.add(invoice);
}
// speicher wieder die neue liste
result.put(dbtrNumber, invoiceList);
// speicher wieder die neue liste wenn es mindestens eine Rechnung gab
if (invoiceList.size()>0) {
result.put(dbtrNumber, invoiceList);
}
}
} catch (QueryException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
private double roundD(double wert) {
return Math.round(wert * 100.0f) / 100.0f;
}
public static boolean isOverdue(Date date, int taskid) {
Date now = new Date();
long diffInMillies = Math.abs(now.getTime() - date.getTime());
int tage = (int) (diffInMillies / 1000 / 60 / 60 / 24);
return ((taskid >= TASK_MAHNUNG_2ND && taskid <= TASK_MAHNUNG_2ND) || tage >= 21);
}
}

View file

@ -26,6 +26,7 @@ import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
@ -52,7 +53,9 @@ import org.imixs.workflow.exceptions.QueryException;
* The OPListExportScheduler erzeugt für jeden Berich ein neues Workitem mit
* einer Excel Datei mit allen offenen Rechnungen.
* <p>
* bei den OP Listen für die Abteilungen dürfen nur Rechnungen aktiviert werden, wo die 2. Mahnung bereits versandt wurde bzw. wo die Fälligkeit der Rechnungen 21 Tage übersteigt.
* bei den OP Listen für die Abteilungen dürfen nur Rechnungen aktiviert werden,
* wo die 2. Mahnung bereits versandt wurde bzw. wo die Fälligkeit der
* Rechnungen 21 Tage übersteigt.
* <p>
* The class implements the interface
* _org.imixs.workflow.engine.scheduler.Scheduler_ and can be used in
@ -66,7 +69,9 @@ public class OPListExportScheduler implements Scheduler {
public static final int MAX_COUNT = 999;
public static final String OPLIST_ERROR = "OPLIST_ERROR";
public static final int TASK_MAHNUNG_2ND = 5210;
public static final int TASK_MAHNUNG_LAST = 5220;
public static DateFormat dateFormat = new SimpleDateFormat("ddMMyyyy");
public static DecimalFormat decimalFormat = new DecimalFormat("0.00",
new DecimalFormatSymbols(java.util.Locale.GERMANY));
@ -99,25 +104,17 @@ public class OPListExportScheduler implements Scheduler {
List<ItemCollection> spaces = teamService.getSpaces();
// Jezt erzeugen wir für jeden Bereich ein neues Workitem .
for (ItemCollection space : spaces) {
// Gibt es Rechnungen?
try {
List<ItemCollection> invoices = documentService
.find("$modelversion:rechnungsausgang-de-1.0 AND type:workitem AND $uniqueidref:"
+ space.getUniqueID(), 1, 0);
if (invoices.size() > 0) {
// erzeuge eine OP-Liste
ItemCollection workitem = new ItemCollection();
workitem.setItemValue("space.ref", space.getUniqueID());
// set creation date!
workitem.setItemValue(WorkflowKernel.CREATED,new Date());
processOPListe(workitem);
}
} catch (QueryException e) {
// not possible
e.printStackTrace();
// Gibt es Rechnungen in diesem Space?
if (existsOverdueInvoices(space)) {
// erzeuge eine OP-Liste
ItemCollection workitem = new ItemCollection();
workitem.setItemValue("space.ref", space.getUniqueID());
// set creation date!
workitem.setItemValue(WorkflowKernel.CREATED, new Date());
processOPListe(workitem);
} else {
logger.info("....no invoices in overdue for "+space.getItemValueString("name"));
}
}
logMessage("...completed", configuration, null);
@ -134,6 +131,37 @@ public class OPListExportScheduler implements Scheduler {
return configuration;
}
/**
* Prüfen ob es Rechnugen in diesem Space gibt die entweder die 2. Mahnstufe
* erreicht habne oder deren Fälligkeit um mehr als 21 Tage überschritten ist.
*
* @param space
* @return
*/
private boolean existsOverdueInvoices(ItemCollection space) {
List<ItemCollection> invoices = new ArrayList<ItemCollection>();
try {
invoices = documentService.find(
"$modelversion:rechnungsausgang-de-1.0 AND type:workitem AND $uniqueidref:" + space.getUniqueID(),
999, 0);
} catch (QueryException e) {
logger.warning("Failed to compute invoice list: " + e.getMessage());
e.printStackTrace();
}
for (ItemCollection invoice : invoices) {
Date date = invoice.getItemValueDate("invoice.duedate");
if (OPListExportAdapter.isOverdue(date,invoice.getTaskID())) {
return true;
}
}
return false;
}
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
public void processOPListe(ItemCollection workitem)
throws PluginException, AccessDeniedException, ProcessingErrorException, ModelException {

View file

@ -251,14 +251,19 @@ Nach Prüfung schließen Sie bitte den Vorgang über die Schaltfläche "Erledigt
<imixs:value><![CDATA[<item name="action">home</item>
<item name="process">Mahnwesen</item>
<opliste name="textblock">OP-Liste Template</opliste>
<opliste name="template">op-liste_template.xlsx</opliste>
<opliste name="template">op-liste_template.xlsx</opliste>
<opliste name="target-name">op-liste_<itemvalue>space.name</itemvalue>_<itemvalue format="yyyy-MM-dd">$lasteventdate</itemvalue>.xlsx</opliste>
<opliste name="filter">true</opliste>
<poi-update name="findreplace">
<find>C6</find>
<replace><itemvalue>sequencenumber</itemvalue></replace>
<type>text</type>
</poi-update>
<poi-update name="findreplace">
<find>D6</find>
<replace>Überfällig / 2. Mahnstufe</replace>
<type>text</type>
</poi-update>
<poi-update name="findreplace">
<find>C8</find>
<replace><itemvalue>space.name</itemvalue></replace>
@ -401,7 +406,7 @@ Nach Prüfung schließen Sie bitte den Vorgang über die Schaltfläche "Erledigt
<imixs:item name="txtactivityresult" type="CDATA">
<imixs:value><![CDATA[<item name="process">Mahnwesen</item>
<opliste name="textblock">OP-Liste Template</opliste>
<opliste name="template">op-liste_template.xlsx</opliste>
<opliste name="template">op-liste_template.xlsx</opliste>
<opliste name="target-name">op-liste_<itemvalue>space.name</itemvalue>_<itemvalue format="yyyy-MM-dd">$lasteventdate</itemvalue>.xlsx</opliste>
<poi-update name="findreplace">
@ -409,6 +414,11 @@ Nach Prüfung schließen Sie bitte den Vorgang über die Schaltfläche "Erledigt
<replace><itemvalue>sequencenumber</itemvalue></replace>
<type>text</type>
</poi-update>
<poi-update name="findreplace">
<find>D6</find>
<replace>Gesamtübersicht</replace>
<type>text</type>
</poi-update>
<poi-update name="findreplace">
<find>C8</find>
<replace><itemvalue>space.name</itemvalue></replace>
@ -487,6 +497,14 @@ Nach Prüfung schließen Sie bitte den Vorgang über die Schaltfläche "Erledigt
<bpmn2:association id="Association_1" sourceRef="DataObject_1" targetRef="Task_2"/>
<bpmn2:association id="Association_3" sourceRef="DataObject_2" targetRef="Task_1"/>
<bpmn2:association id="Association_4" sourceRef="DataObject_1" targetRef="Task_3"/>
<bpmn2:textAnnotation id="TextAnnotation_1">
<bpmn2:text>Filter: 2. Mahnstufe / 21 Tage überfällig</bpmn2:text>
</bpmn2:textAnnotation>
<bpmn2:textAnnotation id="TextAnnotation_2">
<bpmn2:text>Alle Rechnungen</bpmn2:text>
</bpmn2:textAnnotation>
<bpmn2:association id="Association_2" sourceRef="TextAnnotation_2" targetRef="IntermediateCatchEvent_4"/>
<bpmn2:association id="Association_5" sourceRef="TextAnnotation_1" targetRef="IntermediateCatchEvent_1"/>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1" name="Default Process Diagram">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1">
@ -598,6 +616,18 @@ Nach Prüfung schließen Sie bitte den Vorgang über die Schaltfläche "Erledigt
<dc:Bounds height="14.0" width="56.0" x="807.0" y="586.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_TextAnnotation_1" bpmnElement="TextAnnotation_1">
<dc:Bounds height="51.0" width="151.0" x="610.0" y="220.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_17">
<dc:Bounds height="45.0" width="139.0" x="616.0" y="220.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_TextAnnotation_2" bpmnElement="TextAnnotation_2">
<dc:Bounds height="50.0" width="161.0" x="510.0" y="540.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_19">
<dc:Bounds height="44.0" width="149.0" x="516.0" y="540.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_4" bpmnElement="SequenceFlow_4" sourceElement="BPMNShape_1" targetElement="BPMNShape_Task_1">
<di:waypoint xsi:type="dc:Point" x="216.0" y="319.0"/>
<di:waypoint xsi:type="dc:Point" x="253.0" y="319.0"/>
@ -688,6 +718,18 @@ Nach Prüfung schließen Sie bitte den Vorgang über die Schaltfläche "Erledigt
<di:waypoint xsi:type="dc:Point" x="835.0" y="510.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_28"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_Association_2" bpmnElement="Association_2" sourceElement="BPMNShape_TextAnnotation_2" targetElement="BPMNShape_IntermediateCatchEvent_4">
<di:waypoint xsi:type="dc:Point" x="510.0" y="565.0"/>
<di:waypoint xsi:type="dc:Point" x="468.0" y="565.0"/>
<di:waypoint xsi:type="dc:Point" x="468.0" y="503.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_20"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_Association_5" bpmnElement="Association_5" sourceElement="BPMNShape_TextAnnotation_1" targetElement="BPMNShape_IntermediateCatchEvent_1">
<di:waypoint xsi:type="dc:Point" x="610.0" y="245.0"/>
<di:waypoint xsi:type="dc:Point" x="578.0" y="245.0"/>
<di:waypoint xsi:type="dc:Point" x="578.0" y="301.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_24"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
<dc:Font name="arial" size="9.0"/>

View file

@ -984,7 +984,7 @@ Betrag: <itemvalue>_amount</itemvalue> (Brutto € <itemvalue>_amount_brutto</it
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keypublicresult" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
<imixs:value><![CDATA[1]]></imixs:value>
</imixs:item>
<imixs:item name="keylogdateformat" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>

File diff suppressed because it is too large Load diff