new ChronicleTextBuilder and custom RAG Plugin

This commit is contained in:
Ralph Soika 2025-12-28 11:24:20 +01:00
parent fe52b43b5a
commit 15116bf299
7 changed files with 1593 additions and 15 deletions

View file

@ -0,0 +1,53 @@
Du bist Geschäftsprozess Architekt und Modellier. Deine Aufgabe ist es Prozessmodelle zu erstellen.
Unsere Software basiert auf BPMN 2.0. Wir modellieren Geschäftsprozesse nach folgemden Prinzip:
**Process** - der Workflow wird jeweils in einem eigenen BPMN Pool abgebildet. Der Prozessname (Name des Pools) bezeichnet den Workflow.
**Tasks** - bilden die Zustaände in einem Prozess ab die üblicherweise von einem Mitarbeiter im Unternehmen verantwortet werden. Z.b. 'Rechnung erstellen', 'Rechnung prüfen', 'Zahlungseingang buchen'.
Tasks werden innerhalb der Sofware als individuelle Aufgaben für den User in einer Taskliste angezeigt. Jeder Task hat eine eindeutige ID.
**Events** - werden bei uns genutzt um den Übergang von einem Task in einen anderen zu beschreiben. Ein Event ist damit die Aktion die der Mitarbeiter ausführt. Z.b. 'Rechnung weiterleiten', 'Prüfung ablehnen', 'Buchung abschließen'.
Jedes Event das einem Task zugeordnet ist hat innerhalb dieses Tasks eine eindeutige ID.
Wir stellen den Prozessablauf textuell stark vereinfacht dar. Diese Darstellung dient dem BPMN Modellierer einen Prozess in unserem Tool zu erstellen.
Beispiel:
Business Process: Product
START
|
|- [Task: 1000] Imported
| |-- [Event: 10] Update --> [Task: 1000] Imported
| |-- [Event: 50] (RAG) --> [Task: 1200] In Stock
|
|- [Task: 1200] In Stock
| |-- [Event: 10] Update --> [Task: 1200] In Stock
| |-- [Event: 105] Reindex --> [Task: 1000] Imported
| |-- [Event: 20] Ordered --> [Task: 1400] Ordered
| |-- [Event: 30] Not in Stock --> [Task: 1500] Not in Stock
| |-- [Event: 990] [CSV Import] --> [Task: 1000] Imported
|
|- [Task: 1400] Ordered
| |-- [Event: 10] Update --> [Task: 1400] Ordered
| |-- [Event: 20] Delievered --> [Task: 1000] Imported
| |-- [Event: 99] [Wiedervorlage] --> [Task: 1400] Ordered
|
|- [Task: 1500] Not in Stock
| |-- [Event: 10] Update --> [Task: 1500] Not in Stock
| |-- [Event: 20] Delievered --> [Task: 1000] Imported
| |-- [Event: 30] Delete --> [Task: 1990] Deleted
|
END
|
|- [Task: 1990] Deleted
|
Erstelle einen neuen Prozess für eine "Supplier Compliance Prüfung" innerhalb eines Lieferkettenprozesses für ein großes Export Unternehmen.
Erstelle eine formatierte Text Datei für den Ablauf

View file

@ -0,0 +1,50 @@
START
|
|- [Task: 1000] Supplier angelegt
| |-- [Event: 10] Stammdaten aktualisieren --> [Task: 1000] Supplier angelegt
| |-- [Event: 20] Compliance-Prüfung starten --> [Task: 1100] Compliance-Prüfung in Vorbereitung
|
|- [Task: 1100] Compliance-Prüfung in Vorbereitung
| |-- [Event: 10] Prüfumfang anpassen --> [Task: 1100] Compliance-Prüfung in Vorbereitung
| |-- [Event: 30] Dokumente anfordern --> [Task: 1200] Dokumente angefordert
| |-- [Event: 40] Prüfung abbrechen --> [Task: 1900] Prüfung abgebrochen
|
|- [Task: 1200] Dokumente angefordert
| |-- [Event: 10] Erinnerung senden --> [Task: 1200] Dokumente angefordert
| |-- [Event: 20] Dokumente erhalten --> [Task: 1300] Dokumente eingegangen
| |-- [Event: 99] [Wiedervorlage] --> [Task: 1200] Dokumente angefordert
|
|- [Task: 1300] Dokumente eingegangen
| |-- [Event: 10] Dokumente aktualisieren --> [Task: 1300] Dokumente eingegangen
| |-- [Event: 30] Formale Prüfung durchführen --> [Task: 1400] Formale Prüfung
|
|- [Task: 1400] Formale Prüfung
| |-- [Event: 10] Prüfung wiederholen --> [Task: 1400] Formale Prüfung
| |-- [Event: 20] Formal unvollständig --> [Task: 1250] Nachforderung Dokumente
| |-- [Event: 30] Formal korrekt --> [Task: 1500] Inhaltliche Compliance-Prüfung
|
|- [Task: 1250] Nachforderung Dokumente
| |-- [Event: 10] Nachforderung senden --> [Task: 1200] Dokumente angefordert
|
|- [Task: 1500] Inhaltliche Compliance-Prüfung
| |-- [Event: 10] Prüfung vertiefen --> [Task: 1500] Inhaltliche Compliance-Prüfung
| |-- [Event: 20] Compliance erfüllt --> [Task: 1600] Supplier freigegeben
| |-- [Event: 30] Abweichungen festgestellt --> [Task: 1700] Abweichungen klären
| |-- [Event: 40] Kritischer Verstoß --> [Task: 1800] Supplier gesperrt
|
|- [Task: 1700] Abweichungen klären
| |-- [Event: 10] Maßnahmen anfordern --> [Task: 1700] Abweichungen klären
| |-- [Event: 20] Maßnahmen akzeptiert --> [Task: 1600] Supplier freigegeben
| |-- [Event: 30] Maßnahmen abgelehnt --> [Task: 1800] Supplier gesperrt
|
|- [Task: 1600] Supplier freigegeben
| |-- [Event: 10] Freigabe aktualisieren --> [Task: 1600] Supplier freigegeben
| |-- [Event: 90] Re-Compliance-Prüfung starten --> [Task: 1100] Compliance-Prüfung in Vorbereitung
|
|- [Task: 1800] Supplier gesperrt
| |-- [Event: 10] Sperrung prüfen --> [Task: 1800] Supplier gesperrt
| |-- [Event: 20] Sperrung aufheben --> [Task: 1100] Compliance-Prüfung in Vorbereitung
|
END
|
|- [Task: 1900] Prüfung abgebrochen

View file

@ -0,0 +1,178 @@
================================================================================
BUSINESS PROCESS: Supplier Compliance Prüfung
================================================================================
Beschreibung: Workflow zur Prüfung und Freigabe von Lieferanten gemäß
Export-Compliance-Anforderungen (Sanktionslisten, Zertifikate,
Dual-Use-Prüfung, Qualitätsstandards)
================================================================================
START
|
|- [Task: 1000] Lieferant erfasst
| |-- [Event: 10] Update --> [Task: 1000] Lieferant erfasst
| |-- [Event: 20] Zur Vorprüfung --> [Task: 1100] Vorprüfung
| |-- [Event: 30] Direktablehnung --> [Task: 9000] Abgelehnt
| |-- [Event: 990] [CSV Import] --> [Task: 1000] Lieferant erfasst
|
|- [Task: 1100] Vorprüfung
| |-- [Event: 10] Update --> [Task: 1100] Vorprüfung
| |-- [Event: 20] Stammdaten vollständig --> [Task: 1200] Sanktionsprüfung
| |-- [Event: 30] Daten unvollständig --> [Task: 1050] Datenanforderung
| |-- [Event: 40] Abbrechen --> [Task: 9000] Abgelehnt
|
|- [Task: 1050] Datenanforderung
| |-- [Event: 10] Update --> [Task: 1050] Datenanforderung
| |-- [Event: 20] Daten erhalten --> [Task: 1100] Vorprüfung
| |-- [Event: 30] Keine Rückmeldung --> [Task: 9000] Abgelehnt
| |-- [Event: 99] [Wiedervorlage] --> [Task: 1050] Datenanforderung
|
|- [Task: 1200] Sanktionsprüfung
| |-- [Event: 10] Update --> [Task: 1200] Sanktionsprüfung
| |-- [Event: 20] Keine Treffer --> [Task: 1300] Export-Kontrollprüfung
| |-- [Event: 30] Treffer gefunden --> [Task: 1250] Sanktionstreffer Klärung
| |-- [Event: 40] (API Sanktionsliste) --> [Task: 1200] Sanktionsprüfung
|
|- [Task: 1250] Sanktionstreffer Klärung
| |-- [Event: 10] Update --> [Task: 1250] Sanktionstreffer Klärung
| |-- [Event: 20] False Positive bestätigt --> [Task: 1300] Export-Kontrollprüfung
| |-- [Event: 30] Treffer bestätigt --> [Task: 9100] Gesperrt
| |-- [Event: 40] Eskalation --> [Task: 1260] Compliance Officer Review
|
|- [Task: 1260] Compliance Officer Review
| |-- [Event: 10] Update --> [Task: 1260] Compliance Officer Review
| |-- [Event: 20] Freigabe erteilt --> [Task: 1300] Export-Kontrollprüfung
| |-- [Event: 30] Sperrung angeordnet --> [Task: 9100] Gesperrt
|
|- [Task: 1300] Export-Kontrollprüfung
| |-- [Event: 10] Update --> [Task: 1300] Export-Kontrollprüfung
| |-- [Event: 20] Keine Einschränkungen --> [Task: 1400] Dokumentenprüfung
| |-- [Event: 30] Dual-Use relevant --> [Task: 1350] Dual-Use Bewertung
| |-- [Event: 40] Embargo betroffen --> [Task: 9100] Gesperrt
|
|- [Task: 1350] Dual-Use Bewertung
| |-- [Event: 10] Update --> [Task: 1350] Dual-Use Bewertung
| |-- [Event: 20] Genehmigung vorhanden --> [Task: 1400] Dokumentenprüfung
| |-- [Event: 30] Genehmigung erforderlich --> [Task: 1360] Genehmigungsantrag
| |-- [Event: 40] Nicht genehmigungsfähig --> [Task: 9000] Abgelehnt
|
|- [Task: 1360] Genehmigungsantrag
| |-- [Event: 10] Update --> [Task: 1360] Genehmigungsantrag
| |-- [Event: 20] Genehmigung erteilt --> [Task: 1400] Dokumentenprüfung
| |-- [Event: 30] Genehmigung abgelehnt --> [Task: 9000] Abgelehnt
| |-- [Event: 99] [Wiedervorlage] --> [Task: 1360] Genehmigungsantrag
|
|- [Task: 1400] Dokumentenprüfung
| |-- [Event: 10] Update --> [Task: 1400] Dokumentenprüfung
| |-- [Event: 20] Dokumente vollständig --> [Task: 1500] Qualitätsprüfung
| |-- [Event: 30] Dokumente fehlen --> [Task: 1450] Dokumentenanforderung
| |-- [Event: 40] Dokumente ungültig --> [Task: 1450] Dokumentenanforderung
|
|- [Task: 1450] Dokumentenanforderung
| |-- [Event: 10] Update --> [Task: 1450] Dokumentenanforderung
| |-- [Event: 20] Dokumente erhalten --> [Task: 1400] Dokumentenprüfung
| |-- [Event: 30] Frist abgelaufen --> [Task: 9000] Abgelehnt
| |-- [Event: 99] [Wiedervorlage] --> [Task: 1450] Dokumentenanforderung
|
|- [Task: 1500] Qualitätsprüfung
| |-- [Event: 10] Update --> [Task: 1500] Qualitätsprüfung
| |-- [Event: 20] Qualität bestätigt --> [Task: 1600] Freigabeentscheidung
| |-- [Event: 30] Audit erforderlich --> [Task: 1550] Lieferanten-Audit
| |-- [Event: 40] Qualität unzureichend --> [Task: 9000] Abgelehnt
|
|- [Task: 1550] Lieferanten-Audit
| |-- [Event: 10] Update --> [Task: 1550] Lieferanten-Audit
| |-- [Event: 20] Audit bestanden --> [Task: 1600] Freigabeentscheidung
| |-- [Event: 30] Audit nicht bestanden --> [Task: 1560] Maßnahmenplan
| |-- [Event: 40] Audit abgebrochen --> [Task: 9000] Abgelehnt
| |-- [Event: 99] [Wiedervorlage] --> [Task: 1550] Lieferanten-Audit
|
|- [Task: 1560] Maßnahmenplan
| |-- [Event: 10] Update --> [Task: 1560] Maßnahmenplan
| |-- [Event: 20] Maßnahmen umgesetzt --> [Task: 1550] Lieferanten-Audit
| |-- [Event: 30] Maßnahmen abgelehnt --> [Task: 9000] Abgelehnt
| |-- [Event: 99] [Wiedervorlage] --> [Task: 1560] Maßnahmenplan
|
|- [Task: 1600] Freigabeentscheidung
| |-- [Event: 10] Update --> [Task: 1600] Freigabeentscheidung
| |-- [Event: 20] Vollfreigabe --> [Task: 2000] Aktiver Lieferant
| |-- [Event: 30] Bedingte Freigabe --> [Task: 2100] Bedingt freigegeben
| |-- [Event: 40] Ablehnung --> [Task: 9000] Abgelehnt
|
|- [Task: 2000] Aktiver Lieferant
| |-- [Event: 10] Update --> [Task: 2000] Aktiver Lieferant
| |-- [Event: 20] Re-Validierung fällig --> [Task: 3000] Re-Validierung
| |-- [Event: 30] Compliance-Vorfall --> [Task: 3500] Vorfallprüfung
| |-- [Event: 40] Lieferant deaktivieren --> [Task: 9200] Inaktiv
| |-- [Event: 99] [Wiedervorlage] --> [Task: 2000] Aktiver Lieferant
|
|- [Task: 2100] Bedingt freigegeben
| |-- [Event: 10] Update --> [Task: 2100] Bedingt freigegeben
| |-- [Event: 20] Bedingungen erfüllt --> [Task: 2000] Aktiver Lieferant
| |-- [Event: 30] Bedingungen nicht erfüllt --> [Task: 9000] Abgelehnt
| |-- [Event: 40] Re-Validierung fällig --> [Task: 3000] Re-Validierung
| |-- [Event: 99] [Wiedervorlage] --> [Task: 2100] Bedingt freigegeben
|
|- [Task: 3000] Re-Validierung
| |-- [Event: 10] Update --> [Task: 3000] Re-Validierung
| |-- [Event: 20] Validierung bestanden --> [Task: 2000] Aktiver Lieferant
| |-- [Event: 30] Sanktionsprüfung erforderlich --> [Task: 1200] Sanktionsprüfung
| |-- [Event: 40] Dokumentenprüfung erforderlich --> [Task: 1400] Dokumentenprüfung
| |-- [Event: 50] Validierung nicht bestanden --> [Task: 9100] Gesperrt
|
|- [Task: 3500] Vorfallprüfung
| |-- [Event: 10] Update --> [Task: 3500] Vorfallprüfung
| |-- [Event: 20] Vorfall unbegründet --> [Task: 2000] Aktiver Lieferant
| |-- [Event: 30] Vorfall bestätigt --> [Task: 3600] Maßnahmenfestlegung
| |-- [Event: 40] Sofortige Sperrung --> [Task: 9100] Gesperrt
|
|- [Task: 3600] Maßnahmenfestlegung
| |-- [Event: 10] Update --> [Task: 3600] Maßnahmenfestlegung
| |-- [Event: 20] Maßnahmen akzeptiert --> [Task: 2100] Bedingt freigegeben
| |-- [Event: 30] Zusammenarbeit beenden --> [Task: 9100] Gesperrt
|
END
|
|- [Task: 9000] Abgelehnt
| |-- [Event: 10] Update --> [Task: 9000] Abgelehnt
| |-- [Event: 20] Reaktivieren --> [Task: 1000] Lieferant erfasst
|
|- [Task: 9100] Gesperrt
| |-- [Event: 10] Update --> [Task: 9100] Gesperrt
| |-- [Event: 20] Sperrung aufheben --> [Task: 1200] Sanktionsprüfung
| |-- [Event: 30] Endgültig sperren --> [Task: 9900] Blacklist
|
|- [Task: 9200] Inaktiv
| |-- [Event: 10] Update --> [Task: 9200] Inaktiv
| |-- [Event: 20] Reaktivieren --> [Task: 3000] Re-Validierung
| |-- [Event: 30] Archivieren --> [Task: 9990] Archiviert
|
|- [Task: 9900] Blacklist
|
|- [Task: 9990] Archiviert
|
================================================================================
LEGENDE
================================================================================
[Task: XXXX] = Prozessschritt / Zustand mit eindeutiger ID
[Event: XX] = Aktion / Übergang mit eindeutiger ID innerhalb des Tasks
--> = Ziel-Task nach Ausführung des Events
(API ...) = Automatisierter Event (Systemintegration)
[CSV Import] = Massenimport-Event
[Wiedervorlage] = Zeitgesteuertes Erinnerungs-Event
================================================================================
TASK-ÜBERSICHT
================================================================================
1000-1099 Erfassung & Vorprüfung
1100-1199 Vorprüfung
1200-1299 Sanktionsprüfung
1300-1399 Export-Kontrollprüfung
1400-1499 Dokumentenprüfung
1500-1599 Qualitätsprüfung
1600-1699 Freigabeentscheidung
2000-2999 Aktive Lieferanten
3000-3999 Re-Validierung & Vorfallmanagement
9000-9999 Endstatus (Abgelehnt, Gesperrt, Archiviert)
================================================================================

View file

@ -0,0 +1,71 @@
# Business Process: Supplier Compliance Prüfung
## Pool: Supplier Compliance Prüfung (Workflow-Name)
### Task: 50 | Prüfung beauftragt (Initialer Zustand)
* **Beschreibung:** Der Prozess ist gestartet und die Compliance-Prüfung wurde initialisiert.
* **Events (Aktionen des Users/Systems):**
* [Event: 10] Aktualisieren --> [Task: 50] Prüfung beauftragt
* [Event: 20] Zuordnung Compliance Manager --> [Task: 100] Compliance Prüfung in Bearbeitung
* [Event: 90] Prozess abbrechen --> [Task: 990] Abgeschlossen - Abgebrochen
---
### Task: 100 | Compliance Prüfung in Bearbeitung (Hauptbearbeitung)
* **Beschreibung:** Der zugewiesene Compliance Manager arbeitet aktiv an der Prüfung, sammelt und bewertet Unterlagen.
* **Events (Aktionen des Users/Systems):**
* [Event: 10] Aktualisieren --> [Task: 100] Compliance Prüfung in Bearbeitung
* [Event: 20] Unterlagen fehlen - Nachforderung --> [Task: 200] Warten auf Unterlagen Lieferant
* [Event: 30] Compliance positiv - Freigeben --> [Task: 500] Compliance Positiv
* [Event: 40] Compliance negativ - Sperren --> [Task: 550] Compliance Negativ - Gesperrt
* [Event: 50] (RAG) Prüfung zur Freigabe --> [Task: 300] Prüfung zur Freigabe Compliance Management
---
### Task: 200 | Warten auf Unterlagen Lieferant (Blockierender Zustand)
* **Beschreibung:** Der Prozess ist blockiert und wartet auf die vom Lieferanten nachzufordernden Dokumente.
* **Events (Aktionen des Users/Systems):**
* [Event: 10] Aktualisieren --> [Task: 200] Warten auf Unterlagen Lieferant
* [Event: 20] Unterlagen erhalten - Fortsetzen --> [Task: 100] Compliance Prüfung in Bearbeitung
* [Event: 30] Eskalation (Fristüberschreitung) --> [Task: 250] Eskalation (Fristüberschreitung)
* [Event: 40] Lieferant nicht kooperativ - Sperren --> [Task: 550] Compliance Negativ - Gesperrt
---
### Task: 250 | Eskalation (Fristüberschreitung) (Entscheidungsbedarf)
* **Beschreibung:** Eine Frist wurde überschritten; eine Führungskraft oder der Einkauf muss eine Entscheidung über das weitere Vorgehen treffen.
* **Events (Aktionen des Users/Systems):**
* [Event: 10] Aktualisieren --> [Task: 250] Eskalation (Fristüberschreitung)
* [Event: 20] Prüfprozess fortsetzen --> [Task: 100] Compliance Prüfung in Bearbeitung
* [Event: 30] Lieferant sofort sperren --> [Task: 550] Compliance Negativ - Gesperrt
---
### Task: 300 | Prüfung zur Freigabe Compliance Management (Vier-Augen-Prinzip)
* **Beschreibung:** Die finale Entscheidung zur Freigabe muss von einer übergeordneten Stelle überprüft und genehmigt werden.
* **Events (Aktionen des Users/Systems):**
* [Event: 10] Aktualisieren --> [Task: 300] Prüfung zur Freigabe Compliance Management
* [Event: 20] Freigabe genehmigen --> [Task: 500] Compliance Positiv
* [Event: 30] Prüfung ablehnen - Zurück zur Bearbeitung --> [Task: 100] Compliance Prüfung in Bearbeitung
---
### Task: 500 | Compliance Positiv (Endzustand - Positiv)
* **Beschreibung:** Die Prüfung ist erfolgreich abgeschlossen, der Lieferant ist freigegeben.
* **Events (Aktionen des Users/Systems):**
* [Event: 10] Abschließen (Archivieren) --> [Task: 900] Abgeschlossen - Positiv
* [Event: 20] Sperre initiieren (Bei neuer Info) --> [Task: 550] Compliance Negativ - Gesperrt
---
### Task: 550 | Compliance Negativ - Gesperrt (Endzustand - Negativ)
* **Beschreibung:** Die Prüfung ist abgeschlossen, der Lieferant ist nicht konform und wurde gesperrt.
* **Events (Aktionen des Users/Systems):**
* [Event: 10] Abschließen (Archivieren) --> [Task: 950] Abgeschlossen - Negativ
* [Event: 20] Re-Evaluierung beauftragen --> [Task: 50] Prüfung beauftragt
---
### Task: 900 | Abgeschlossen - Positiv
### Task: 950 | Abgeschlossen - Negativ
### Task: 990 | Abgeschlossen - Abgebrochen

View file

@ -0,0 +1,475 @@
package ai.dynamixs;
/*******************************************************************************
* Imixs Workflow Technology
* Copyright (C) 2003, 2008 Imixs Software Solutions GmbH,
* http://www.imixs.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You can receive a copy of the GNU General Public
* License at http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Imixs Software Solutions GmbH - initial API and implementation
* Ralph Soika
*
*******************************************************************************/
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.imixs.workflow.FileData;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.WorkflowKernel;
import org.imixs.workflow.engine.DocumentService;
import org.imixs.workflow.engine.plugins.HistoryPlugin;
import org.imixs.workflow.office.forms.WorkitemService;
import jakarta.inject.Inject;
/**
* The ChronicleTextBuilder creates a text representation of all chronicle data
* for a given workitem.
*
* <p>
* The output format is structured by year and month:
*
* <pre>
* 2025
*
* December
* 27. Dec 2025 (14:37) - Ralph Soika
* Offer sent
* Products are out of stock now!
*
* 27. Dec 2025 (14:35) - imixs-workflow-service
* Retrieve Products
* Retrieve Address
* </pre>
*
* <p>
* Usage example:
*
* <pre>
* ChronicleTextBuilder builder = new ChronicleTextBuilder(workitem, locale);
* builder.setDmsController(dmsController);
* builder.setWorkitemLinkController(workitemLinkController);
* builder.setWorkitemService(workitemService);
* builder.setDocumentService(documentService);
* String chronicleText = builder.build();
* </pre>
*
* <p>
* The builder supports filtering by entry type (history, comment, dms,
* reference, version, imixs-ai).
*
* @author rsoika
*/
public class ChronicleTextBuilder implements Serializable {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(ChronicleTextBuilder.class.getName());
private ItemCollection workitem;
private Locale locale;
private String filterType;
@Inject
private WorkitemService workitemService;
@Inject
private DocumentService documentService;
// Internal data structures
private List<ChronicleEntry> chronicleEntries;
private Map<Integer, Set<Integer>> yearsMonths;
// Date formatters
private DateTimeFormatter dayFormatter;
private DateTimeFormatter timeFormatter;
private DateTimeFormatter monthFormatter;
/**
* Constructor with workitem and locale.
*
* @param workitem the workitem to build the chronicle for
* @param locale the locale for date formatting (e.g., Locale.ENGLISH,
* Locale.GERMAN)
*/
public ChronicleTextBuilder(ItemCollection workitem, Locale locale) {
this.workitem = workitem;
this.locale = locale != null ? locale : Locale.ENGLISH;
this.filterType = null;
this.chronicleEntries = new ArrayList<>();
this.yearsMonths = new HashMap<>();
// Initialize date formatters
this.dayFormatter = DateTimeFormatter.ofPattern("d. MMM yyyy", this.locale);
this.timeFormatter = DateTimeFormatter.ofPattern("HH:mm", this.locale);
this.monthFormatter = DateTimeFormatter.ofPattern("MMMM", this.locale);
}
/**
* Constructor with workitem only (uses English locale as default).
*
* @param workitem the workitem to build the chronicle for
*/
public ChronicleTextBuilder(ItemCollection workitem) {
this(workitem, Locale.ENGLISH);
}
/**
* Sets a filter to include only entries of a specific type. Valid types:
* history, comment, dms, reference, version, imixs-ai
*
* @param filterType the type to filter by, or null to include all
* @return this builder for method chaining
*/
public ChronicleTextBuilder setFilter(String filterType) {
this.filterType = filterType;
return this;
}
/**
* Builds and returns the text representation of the chronicle.
*
* @return formatted chronicle text
*/
public String build() {
long startTime = System.currentTimeMillis();
if (workitem == null) {
return "";
}
// Collect all chronicle data
collectHistoryEntries();
collectCommentEntries();
collectDMSEntries();
collectVersionEntries();
// Sort entries by date (newest first)
Collections.sort(chronicleEntries, new ChronicleEntryComparator(false));
// Build the text output
String result = buildTextOutput();
logger.fine("ChronicleTextBuilder.build() completed in " + (System.currentTimeMillis() - startTime) + "ms");
return result;
}
/**
* Collects workflow history entries from the workitem.
*/
@SuppressWarnings("unchecked")
private void collectHistoryEntries() {
List<List<?>> history = null;
// Check for deprecated field 'txtworkflowhistory'
if (!workitem.hasItem(HistoryPlugin.ITEM_HISTORY_LOG)
&& workitem.hasItem("txtworkflowhistory")) {
history = workitem.getItemValue("txtworkflowhistory");
// Sort old history entries chronologically
Collections.sort(history, new Comparator<List<?>>() {
@Override
public int compare(List<?> entry1, List<?> entry2) {
Date date1 = (Date) entry1.get(0);
Date date2 = (Date) entry2.get(0);
return date1.compareTo(date2);
}
});
} else {
history = workitem.getItemValue(HistoryPlugin.ITEM_HISTORY_LOG);
}
// Reverse to get newest first
// Collections.reverse(history);
if (history.size() > 0 && history.get(0) instanceof List) {
for (List<?> entries : history) {
Date date = (Date) entries.get(0);
String message = (String) entries.get(1);
String user = (String) entries.get(2);
addEntry(date, user, message, "history");
}
}
}
/**
* Collects comment entries from the workitem.
*/
private void collectCommentEntries() {
List<Map<String, List<Object>>> comments = workitem.getItemValue("txtCommentLog");
for (Map<String, List<Object>> comment : comments) {
ItemCollection itemCol = new ItemCollection(comment);
Date date = itemCol.getItemValueDate("datcomment");
String message = itemCol.getItemValueString("txtcomment");
String user = itemCol.getItemValueString("nameditor");
addEntry(date, user, message, "comment");
}
}
/**
* Collects DMS (attachment) entries if dmsController is available.
*/
private void collectDMSEntries() {
List<FileData> fileDataList = workitem.getFileData();
for (FileData fileData : fileDataList) {
ItemCollection fileAttributes = new ItemCollection(fileData.getAttributes());
String content = fileAttributes.getItemValueString("text");
if (!content.isBlank()) {
String user = fileAttributes.getItemValueString("$creator");
Date date = fileAttributes.getItemValueDate("$created");
if (fileData.getAttribute("$modified") != null) {
date = fileAttributes.getItemValueDate("$modified");
}
if (date == null) {
date = new Date();
}
addEntry(date, user, "Attachment: " + fileData.getName() + "\n\n" + content + "\n\n", "dms");
}
}
}
/**
* Collects version entries if workitemService and documentService are
* available.
*/
private void collectVersionEntries() {
if (workitemService == null || documentService == null) {
return;
}
List<ItemCollection> versions = workitemService.findAllVersions(workitem);
for (ItemCollection version : versions) {
// Skip current workitem
if (workitem.getUniqueID().equals(version.getUniqueID())) {
continue;
}
ItemCollection versionFull = documentService.load(version.getUniqueID());
Date date = version.getItemValueDate(WorkflowKernel.CREATED);
String message = version.getItemValueString("$WorkflowSummary");
String user = version.getItemValueString(WorkflowKernel.EDITOR);
if (!versionFull.getItemValueString("$uniqueIdSource").isEmpty()) {
if (versionFull.hasItem(WorkflowKernel.CREATED + ".version")) {
date = versionFull.getItemValueDate(WorkflowKernel.CREATED + ".version");
}
message = "Version (Branch): " + message;
} else {
message = "Version: " + message;
}
addEntry(date, user, message, "version");
}
}
/**
* Adds a chronicle entry to the internal list. Applies filter if set and
* updates the year/month index.
*/
private void addEntry(Date date, String user, String message, String type) {
if (date == null) {
return;
}
// Apply filter if set
if (filterType != null && !filterType.isEmpty() && !filterType.equals(type)) {
return;
}
// Truncate to minutes
LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
localDateTime = localDateTime.truncatedTo(ChronoUnit.MINUTES);
ChronicleEntry entry = new ChronicleEntry(localDateTime, user, message, type);
chronicleEntries.add(entry);
// Update year/month index
LocalDate localDate = localDateTime.toLocalDate();
int year = localDate.getYear();
int month = localDate.getMonthValue();
yearsMonths.computeIfAbsent(year, k -> new HashSet<>()).add(month);
}
/**
* Builds the formatted text output from collected entries.
*/
private String buildTextOutput() {
StringBuilder sb = new StringBuilder();
// Add title
sb.append(
"# " + workitem.getWorkflowGroup() + " : " + workitem.getItemValueString(WorkflowKernel.WORKFLOWSTATUS))
.append("\n\n");
// Get sorted years (descending)
List<Integer> years = new ArrayList<>(yearsMonths.keySet());
for (int i = 0; i < years.size(); i++) {
int year = years.get(i);
// Year header
// sb.append(year).append("\n\n");
// Get sorted months for this year (descending)
List<Integer> months = new ArrayList<>(yearsMonths.get(year));
for (int j = 0; j < months.size(); j++) {
int month = months.get(j);
// Get entries for this month
List<ChronicleEntry> monthEntries = getEntriesForMonth(year, month);
if (monthEntries.isEmpty()) {
continue;
}
// Month header
// String monthName = LocalDate.of(year, month, 1).format(monthFormatter);
// sb.append(monthName).append("\n\n");
// Group entries by user and timestamp
List<GroupedEntry> groupedEntries = groupEntries(monthEntries);
for (GroupedEntry grouped : groupedEntries) {
// Format: "27. Dec 2025 (14:37) - Ralph Soika"
String dayStr = grouped.dateTime.format(dayFormatter);
String timeStr = grouped.dateTime.format(timeFormatter);
sb.append("\n" + dayStr).append(" (").append(timeStr).append(") - ").append(grouped.user)
.append("\n");
// Add all messages for this group
for (String message : grouped.messages) {
sb.append(message).append("\n");
}
}
// Add spacing between months (but not after the last month of the last year)
if (j < months.size() - 1 || i < years.size() - 1) {
sb.append("\n");
}
}
}
return sb.toString().trim();
}
/**
* Returns all entries for a specific year and month.
*/
private List<ChronicleEntry> getEntriesForMonth(int year, int month) {
List<ChronicleEntry> result = new ArrayList<>();
for (ChronicleEntry entry : chronicleEntries) {
if (entry.dateTime.getYear() == year && entry.dateTime.getMonthValue() == month) {
result.add(entry);
}
}
return result;
}
/**
* Groups entries by user and timestamp (same minute). This consolidates
* multiple actions by the same user at the same time.
*/
private List<GroupedEntry> groupEntries(List<ChronicleEntry> entries) {
List<GroupedEntry> grouped = new ArrayList<>();
GroupedEntry current = null;
for (ChronicleEntry entry : entries) {
if (current == null ||
!current.user.equals(entry.user) ||
!current.dateTime.equals(entry.dateTime)) {
// Start a new group
current = new GroupedEntry(entry.dateTime, entry.user);
grouped.add(current);
}
current.messages.add(entry.message);
}
return grouped;
}
/**
* Internal class representing a single chronicle entry.
*/
private static class ChronicleEntry {
LocalDateTime dateTime;
String user;
String message;
String type;
ChronicleEntry(LocalDateTime dateTime, String user, String message, String type) {
this.dateTime = dateTime;
this.user = user != null ? user : "";
this.message = message != null ? message : "";
this.type = type;
}
}
/**
* Internal class for grouping entries by user and timestamp.
*/
private static class GroupedEntry {
LocalDateTime dateTime;
String user;
List<String> messages;
GroupedEntry(LocalDateTime dateTime, String user) {
this.dateTime = dateTime;
this.user = user;
this.messages = new ArrayList<>();
}
}
/**
* Comparator for sorting chronicle entries by date.
*/
private static class ChronicleEntryComparator implements Comparator<ChronicleEntry> {
private boolean descending;
ChronicleEntryComparator(boolean descending) {
this.descending = descending;
}
@Override
public int compare(ChronicleEntry e1, ChronicleEntry e2) {
int result = e1.dateTime.compareTo(e2.dateTime);
return descending ? -result : result;
}
}
}

View file

@ -0,0 +1,124 @@
/****************************************************************************
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* This Source Code may also be made available under the terms of the
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
****************************************************************************/
package ai.dynamixs;
import java.util.List;
import java.util.logging.Logger;
import org.imixs.ai.rag.RAGService;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.AdapterException;
import org.imixs.workflow.exceptions.PluginException;
import jakarta.inject.Inject;
/**
* This RAGIndexPlugin extends the default imixs-ai RAGIndexPlugin.
*
* In the mode INDEX this plugins generates a default prompt template if no
* prompt definition was found. This is to simplify the models.
* <p>
*
* <pre>
{@code
<imixs-ai name="INDEX">
<debug>false</debug>
</imixs-ai>
}
* </pre>
* <p>
* The tag 'debug' is optional
*
*
* @author rsoika
*
*/
public class RAGDefaultIndexPlugin extends org.imixs.ai.rag.RAGIndexPlugin {
private static final Logger logger = Logger.getLogger(RAGDefaultIndexPlugin.class.getName());
@Inject
private WorkflowService workflowService;
@Inject
private RAGService ragService;
@Override
public ItemCollection run(ItemCollection workitem, ItemCollection event) throws PluginException {
// do not run on Snapshots!
if (workitem.getType().startsWith("snapshot-")) {
// no op!
return workitem;
}
logger.info("├── running Dynamixs.AI RAGPlugin");
// read optional configuration form the model or imixs.properties....
List<ItemCollection> ragIndexDefinitions = workflowService.evalWorkflowResultXML(event, "imixs-ai",
RAGService.RAG_INDEX, workitem, false);
try {
// INDEX Mode?
if (ragIndexDefinitions != null && ragIndexDefinitions.size() > 0) {
// do we have a prompt template?
ItemCollection indexDefinition = ragIndexDefinitions.get(0);
String promptTemplate = indexDefinition.getItemValueString("promptTemplate");
if (promptTemplate.isBlank()) {
// generate default template
ChronicleTextBuilder chronicleTextBuilder = new ChronicleTextBuilder(workitem);
promptTemplate = chronicleTextBuilder.build();
workitem.setItemValue("ai.chronicle.summary", promptTemplate);
indexDefinition.setItemValue("promptTemplate", embedTemplate(promptTemplate));
ragService.createIndex(ragIndexDefinitions, workitem, event);
return workitem;
}
}
// default behavior
return super.run(workitem, event);
} catch (AdapterException e) {
throw new PluginException(e);
}
}
/**
* Embedds a prompt into a imixs prompt template
*
*
* @param prompt
* @return
*/
private String embedTemplate(String prompt) {
String template = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
"<PromptDefinition>\n" + //
" <prompt_options>{}</prompt_options>\n" + //
" <prompt><![CDATA[";
template = template + prompt;
template = template + "]]>\n" + //
"</prompt>\n" + //
"</PromptDefinition> ";
return template;
}
}

View file

@ -20,7 +20,7 @@
<imixs:value><![CDATA[Liefertermin|order.delivery]]></imixs:value>
</imixs:item>
<imixs:item name="txtplugins" type="xs:string">
<imixs:value><![CDATA[org.imixs.ai.rag.RAGIndexPlugin]]></imixs:value>
<imixs:value><![CDATA[ai.dynamixs.RAGDefaultIndexPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ResultPlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.RulePlugin]]></imixs:value>
<imixs:value><![CDATA[org.imixs.marty.profile.ProfilePlugin]]></imixs:value>
@ -88,6 +88,17 @@
<bpmn2:flowNodeRef>ExclusiveGateway_2</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>TextAnnotation_4</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>dataObject_u4ZytA</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_oOnn8A</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_YGXi9A</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>task_qvmKNg</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>task_BRnorw</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_nzILHw</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_tm9U6A</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>dataObject_gVhkEg</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_20Geow</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>event_pxwPEw</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>dataObject_QIYhww</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>textAnnotation_ASEpEw</bpmn2:flowNodeRef>
</bpmn2:lane>
</bpmn2:laneSet>
<bpmn2:startEvent id="StartEvent_1" name="Start">
@ -222,6 +233,7 @@ Color: <itemvalue>_color</itemvalue><br />
</bpmn2:extensionElements>
<bpmn2:documentation id="Documentation_27"><![CDATA[<textblock><itemvalue>$workflowgroup</itemvalue> - <itemvalue>$workflowstatus</itemvalue></textblock>]]></bpmn2:documentation>
<bpmn2:incoming>SequenceFlow_42</bpmn2:incoming>
<bpmn2:incoming>sequenceFlow_1TkjsQ</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_HCxYvw</bpmn2:outgoing>
<bpmn2:incoming>sequenceFlow_RppP5Q</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_ZtZaBQ</bpmn2:outgoing>
@ -272,6 +284,7 @@ Color: <itemvalue>_color</itemvalue><br />
<bpmn2:incoming>SequenceFlow_40</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_19</bpmn2:outgoing>
<bpmn2:outgoing>SequenceFlow_25</bpmn2:outgoing>
<bpmn2:outgoing>sequenceFlow_oWlcYg</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:task id="Task_5" imixs:processid="1900" name="Eingestellt">
<bpmn2:extensionElements>
@ -1115,7 +1128,7 @@ Color: <itemvalue>_color</itemvalue><br />
<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>
@ -1689,6 +1702,7 @@ Color: <itemvalue>_color</itemvalue><br />
<bpmn2:incoming>sequenceFlow_WRPdIA</bpmn2:incoming>
<bpmn2:incoming>sequenceFlow_hZg0iw</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_kkTZbA</bpmn2:outgoing>
<bpmn2:outgoing>sequenceFlow_VQusBA</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:boundaryEvent attachedToRef="task_HL0KNA" id="event_ZdM0Zg" name="">
<bpmn2:documentation id="documentation_81qC0g"/>
@ -1938,6 +1952,7 @@ Color: <itemvalue>_color</itemvalue><br />
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_UyEkJg"><![CDATA[Update Data]]></bpmn2:documentation>
<bpmn2:incoming>sequenceFlow_BM0t3w</bpmn2:incoming>
<bpmn2:incoming>sequenceFlow_VQusBA</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_hkBSvg</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="sequenceFlow_hkBSvg" sourceRef="event_LHADMg" targetRef="task_ol2R9A">
@ -1953,6 +1968,498 @@ Color: <itemvalue>_color</itemvalue><br />
<bpmn2:association id="association_jW6RnQ" sourceRef="event_KwpMKw" targetRef="dataObject_iq4agg">
<bpmn2:documentation id="documentation_XBh77Q"/>
</bpmn2:association>
<bpmn2:intermediateCatchEvent id="event_oOnn8A" imixs:activityid="42" name="AI Assist &#128161;︎">
<bpmn2:extensionElements>
<imixs:item name="keylogtimeformat" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keyarchive" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="txtmailsubject" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyaccessmode" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyscheduledactivity" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="rtfmailbody" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyversion" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[namCreator]]></imixs:value>
<imixs:value><![CDATA[namCurrentEditor]]></imixs:value>
<imixs:value><![CDATA[namprocessmanager]]></imixs:value>
<imixs:value><![CDATA[namprocessteam]]></imixs:value>
</imixs:item>
<imixs:item name="numnextactivityid" type="xs:int">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyfollowup" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keypublicresult" type="xs:string">
<imixs:value><![CDATA[1]]></imixs:value>
</imixs:item>
<imixs:item name="keylogdateformat" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[namCurrentEditor]]></imixs:value>
<imixs:value><![CDATA[namCreator]]></imixs:value>
</imixs:item>
<imixs:item name="numnextid" type="xs:int">
<imixs:value><![CDATA[5000]]></imixs:value>
</imixs:item>
<imixs:item name="txtnextprocesstree" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="txtactivityresult" type="xs:string">
<imixs:value><![CDATA[<item name="comment" ignore="true"/>]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Speichern]]></imixs:value>
</imixs:item>
<imixs:item name="keyownershipmode" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:boolean">
<imixs:value>false</imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_D4Kkgw"><![CDATA[Update Data]]></bpmn2:documentation>
<bpmn2:outgoing>sequenceFlow_1TkjsQ</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="sequenceFlow_1TkjsQ" sourceRef="event_oOnn8A" targetRef="Task_3">
<bpmn2:documentation id="documentation_BWhi0Q"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sequenceFlow_VQusBA" sourceRef="task_HL0KNA" targetRef="event_LHADMg">
<bpmn2:documentation id="documentation_AzTmsQ"/>
</bpmn2:sequenceFlow>
<bpmn2:intermediateCatchEvent id="event_YGXi9A" imixs:activityid="12" name="RAG INDEX TEST">
<bpmn2:extensionElements>
<imixs:item name="keylogtimeformat" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keyarchive" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="txtmailsubject" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyaccessmode" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyscheduledactivity" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="rtfmailbody" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyversion" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[namCreator]]></imixs:value>
<imixs:value><![CDATA[namCurrentEditor]]></imixs:value>
<imixs:value><![CDATA[namprocessmanager]]></imixs:value>
<imixs:value><![CDATA[namprocessteam]]></imixs:value>
</imixs:item>
<imixs:item name="numnextactivityid" type="xs:int">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyfollowup" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keypublicresult" type="xs:string">
<imixs:value><![CDATA[1]]></imixs:value>
</imixs:item>
<imixs:item name="keylogdateformat" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[namCurrentEditor]]></imixs:value>
<imixs:value><![CDATA[namCreator]]></imixs:value>
</imixs:item>
<imixs:item name="numnextid" type="xs:int">
<imixs:value><![CDATA[5000]]></imixs:value>
</imixs:item>
<imixs:item name="txtnextprocesstree" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="txtactivityresult" type="xs:string">
<imixs:value><![CDATA[<item name="comment" ignore="true"/>
<imixs-ai name="INDEX">
<endpoint>https://embeddings.llama.cpp.imixs.com/</endpoint>
<debug>true</debug>
</imixs-ai>
]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Speichern]]></imixs:value>
</imixs:item>
<imixs:item name="keyownershipmode" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:boolean">
<imixs:value>false</imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_ha4lhQ"><![CDATA[Update Data]]></bpmn2:documentation>
<bpmn2:incoming>sequenceFlow_oWlcYg</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_FFp2sQ</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="sequenceFlow_FFp2sQ" sourceRef="event_YGXi9A" targetRef="task_qvmKNg">
<bpmn2:documentation id="documentation_ZJT0XA"/>
</bpmn2:sequenceFlow>
<bpmn2:task id="task_qvmKNg" imixs:processid="1401" name="Process Erkenntnis">
<bpmn2:extensionElements>
<imixs:item name="txtworkflowabstract" type="xs:string">
<imixs:value><![CDATA[<strong>Product: <itemvalue>_name</itemvalue></strong><br />
EAN: <itemvalue>_ean</itemvalue><br />
Category: <itemvalue>_category</itemvalue><br />
Brand: <itemvalue>_brand</itemvalue><br />
<hr />
Description: <br />
<itemvalue>_description</itemvalue><br />
<hr />
Price: <itemvalue>_price</itemvalue> <itemvalue>_currency</itemvalue><br />
Stock: <itemvalue>_stock</itemvalue><br />
Size: <itemvalue>_size</itemvalue><br />
Color: <itemvalue>_color</itemvalue><br />
]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-download-outline|typcn-stopwatch,imixs-info,icon-sub-ne]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:boolean">
<imixs:value>true</imixs:value>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string"/>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[namCreator]]></imixs:value>
<imixs:value><![CDATA[namprocessmanager]]></imixs:value>
<imixs:value><![CDATA[namprocessteam]]></imixs:value>
<imixs:value><![CDATA[namspacemanager]]></imixs:value>
<imixs:value><![CDATA[namspaceteam]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_UIPQCw"><![CDATA[<textblock><itemvalue>$workflowgroup</itemvalue> - <itemvalue>$workflowstatus</itemvalue></textblock>]]></bpmn2:documentation>
<bpmn2:incoming>SequenceFlow_40</bpmn2:incoming>
<bpmn2:incoming>sequenceFlow_6AvkzQ</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_25</bpmn2:outgoing>
<bpmn2:incoming>sequenceFlow_FFp2sQ</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_C79hSw</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:sequenceFlow id="sequenceFlow_oWlcYg" sourceRef="Task_4" targetRef="event_YGXi9A">
<bpmn2:documentation id="documentation_t0BOlw"/>
</bpmn2:sequenceFlow>
<bpmn2:task id="task_BRnorw" imixs:processid="1402" name="Process Erkenntnis">
<bpmn2:extensionElements>
<imixs:item name="txtworkflowabstract" type="xs:string">
<imixs:value><![CDATA[<strong>Product: <itemvalue>_name</itemvalue></strong><br />
EAN: <itemvalue>_ean</itemvalue><br />
Category: <itemvalue>_category</itemvalue><br />
Brand: <itemvalue>_brand</itemvalue><br />
<hr />
Description: <br />
<itemvalue>_description</itemvalue><br />
<hr />
Price: <itemvalue>_price</itemvalue> <itemvalue>_currency</itemvalue><br />
Stock: <itemvalue>_stock</itemvalue><br />
Size: <itemvalue>_size</itemvalue><br />
Color: <itemvalue>_color</itemvalue><br />
]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
</imixs:item>
<imixs:item name="txtimageurl" type="xs:string">
<imixs:value><![CDATA[typcn-download-outline|typcn-stopwatch,imixs-info,icon-sub-ne]]></imixs:value>
</imixs:item>
<imixs:item name="txtworkflowsummary" type="xs:string">
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:boolean">
<imixs:value>true</imixs:value>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string"/>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[namCreator]]></imixs:value>
<imixs:value><![CDATA[namprocessmanager]]></imixs:value>
<imixs:value><![CDATA[namprocessteam]]></imixs:value>
<imixs:value><![CDATA[namspacemanager]]></imixs:value>
<imixs:value><![CDATA[namspaceteam]]></imixs:value>
</imixs:item>
<imixs:item name="txttype" type="xs:string">
<imixs:value><![CDATA[workitem]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_zQjdfQ"><![CDATA[<textblock><itemvalue>$workflowgroup</itemvalue> - <itemvalue>$workflowstatus</itemvalue></textblock>]]></bpmn2:documentation>
<bpmn2:incoming>sequenceFlow_FFp2sQ</bpmn2:incoming>
<bpmn2:incoming>sequenceFlow_zyO0wQ</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_VtEF4g</bpmn2:outgoing>
<bpmn2:outgoing>sequenceFlow_11vZNA</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:intermediateCatchEvent id="event_nzILHw" imixs:activityid="200" name="(Summary)">
<bpmn2:extensionElements>
<imixs:item name="keylogtimeformat" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keyarchive" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="txtmailsubject" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyaccessmode" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyscheduledactivity" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="rtfmailbody" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyversion" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[namCreator]]></imixs:value>
<imixs:value><![CDATA[namCurrentEditor]]></imixs:value>
<imixs:value><![CDATA[namprocessmanager]]></imixs:value>
<imixs:value><![CDATA[namprocessteam]]></imixs:value>
</imixs:item>
<imixs:item name="numnextactivityid" type="xs:int">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyfollowup" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keypublicresult" type="xs:string">
<imixs:value><![CDATA[1]]></imixs:value>
</imixs:item>
<imixs:item name="keylogdateformat" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[namCurrentEditor]]></imixs:value>
<imixs:value><![CDATA[namCreator]]></imixs:value>
</imixs:item>
<imixs:item name="numnextid" type="xs:int">
<imixs:value><![CDATA[5000]]></imixs:value>
</imixs:item>
<imixs:item name="txtnextprocesstree" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="txtactivityresult" type="xs:string">
<imixs:value><![CDATA[<imixs-ai name="DISABLED"></imixs-ai>
<imixs-ai name="ASSIST">
<endpoint><propertyvalue>llm.service.endpoint</propertyvalue></endpoint>
<result-item>ai.workflow.summary</result-item>
<debug>true</debug>
</imixs-ai>
<validation name="required">false</validation>
]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Speichern]]></imixs:value>
</imixs:item>
<imixs:item name="keyownershipmode" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="rtfresultlog" type="xs:string">
<imixs:value><![CDATA[compute summary]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:boolean">
<imixs:value>false</imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_kJbGZA"><![CDATA[Compute Summary]]></bpmn2:documentation>
<bpmn2:incoming>sequenceFlow_C79hSw</bpmn2:incoming>
<bpmn2:incoming>sequenceFlow_7s3Yfw</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_zyO0wQ</bpmn2:outgoing>
<bpmn2:signalEventDefinition id="signalEventDefinition_UL7VJw" signalRef="signal_5"/>
<bpmn2:incoming>sequenceFlow_InfPdQ</bpmn2:incoming>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="sequenceFlow_C79hSw" sourceRef="task_qvmKNg" targetRef="event_nzILHw">
<bpmn2:documentation id="documentation_Gr3D0g"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sequenceFlow_zyO0wQ" sourceRef="event_nzILHw" targetRef="task_BRnorw">
<bpmn2:documentation id="documentation_at4eJA"/>
</bpmn2:sequenceFlow>
<bpmn2:boundaryEvent attachedToRef="task_qvmKNg" id="event_tm9U6A" name="">
<bpmn2:documentation id="documentation_zYZ2RA"/>
<bpmn2:outgoing>sequenceFlow_7s3Yfw</bpmn2:outgoing>
<bpmn2:timerEventDefinition id="timerEventDefinition_00qCgw"/>
</bpmn2:boundaryEvent>
<bpmn2:sequenceFlow id="sequenceFlow_7s3Yfw" sourceRef="event_tm9U6A" targetRef="event_nzILHw">
<bpmn2:documentation id="documentation_E0eZxQ"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sequenceFlow_VtEF4g" sourceRef="task_BRnorw" targetRef="event_20Geow">
<bpmn2:documentation id="documentation_0B00KQ"/>
</bpmn2:sequenceFlow>
<bpmn2:dataObject id="dataObject_gVhkEg" imixs:datatype="prompt-data" name="Prompot">
<bpmn2:documentation id="documentation_Mcz35Q"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<PromptDefinition>
<prompt_options>{"n_predict": 4096, "temperature": 0.0}</prompt_options>
<prompt role="system"><![CDATA[
You are a project analyst. A workflow has just been completed.
Create a brief project insight:
- What specifically happened? (Include relevant names from people, companies, products when mentioned.)
- Is there anything unusual or important to remember for the future? (Pay attention to user comments - they often contain important warnings or decisions.)
No general advice. Only project-specific facts and insights.]]]]><![CDATA[>
</prompt>
<prompt role="user"><![CDATA[
<itemvalue>ai.chronicle.summary</itemvalue> ]]]]><![CDATA[>
</prompt>
</PromptDefinition> ]]></bpmn2:documentation>
<bpmn2:dataState id="dataState_9qGGUQ"/>
</bpmn2:dataObject>
<bpmn2:association id="association_icBtwA" sourceRef="dataObject_gVhkEg" targetRef="event_nzILHw">
<bpmn2:documentation id="documentation_NvIFKA"/>
</bpmn2:association>
<bpmn2:endEvent id="event_20Geow" name="Event-24">
<bpmn2:documentation id="documentation_I20ysQ"/>
<bpmn2:incoming>sequenceFlow_VtEF4g</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:intermediateCatchEvent id="event_pxwPEw" imixs:activityid="10" name="Retry Summary">
<bpmn2:extensionElements>
<imixs:item name="keylogtimeformat" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keyarchive" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="txtmailsubject" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyaccessmode" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyscheduledactivity" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="rtfmailbody" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="keyversion" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyaddwritefields" type="xs:string">
<imixs:value><![CDATA[namCreator]]></imixs:value>
<imixs:value><![CDATA[namCurrentEditor]]></imixs:value>
<imixs:value><![CDATA[namprocessmanager]]></imixs:value>
<imixs:value><![CDATA[namprocessteam]]></imixs:value>
</imixs:item>
<imixs:item name="numnextactivityid" type="xs:int">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyfollowup" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keypublicresult" type="xs:string">
<imixs:value><![CDATA[1]]></imixs:value>
</imixs:item>
<imixs:item name="keylogdateformat" type="xs:string">
<imixs:value><![CDATA[2]]></imixs:value>
</imixs:item>
<imixs:item name="keyownershipfields" type="xs:string">
<imixs:value><![CDATA[namCurrentEditor]]></imixs:value>
<imixs:value><![CDATA[namCreator]]></imixs:value>
</imixs:item>
<imixs:item name="numnextid" type="xs:int">
<imixs:value><![CDATA[5000]]></imixs:value>
</imixs:item>
<imixs:item name="txtnextprocesstree" type="xs:string">
<imixs:value/>
</imixs:item>
<imixs:item name="txtactivityresult" type="xs:string">
<imixs:value><![CDATA[<item name="comment" ignore="true"/>]]></imixs:value>
</imixs:item>
<imixs:item name="txtname" type="xs:string">
<imixs:value><![CDATA[Speichern]]></imixs:value>
</imixs:item>
<imixs:item name="keyownershipmode" type="xs:string">
<imixs:value><![CDATA[0]]></imixs:value>
</imixs:item>
<imixs:item name="keyupdateacl" type="xs:boolean">
<imixs:value>false</imixs:value>
</imixs:item>
<imixs:item name="rtfresultlog" type="xs:string">
<imixs:value><![CDATA[retry summary computation]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:documentation id="documentation_Z0OWeg"><![CDATA[Update Data]]></bpmn2:documentation>
<bpmn2:incoming>sequenceFlow_11vZNA</bpmn2:incoming>
<bpmn2:outgoing>sequenceFlow_6AvkzQ</bpmn2:outgoing>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="sequenceFlow_11vZNA" sourceRef="task_BRnorw" targetRef="event_pxwPEw">
<bpmn2:documentation id="documentation_XorhQA"/>
</bpmn2:sequenceFlow>
<bpmn2:sequenceFlow id="sequenceFlow_6AvkzQ" sourceRef="event_pxwPEw" targetRef="task_qvmKNg">
<bpmn2:documentation id="documentation_JJok3w"/>
</bpmn2:sequenceFlow>
<bpmn2:dataObject id="dataObject_QIYhww" imixs:datatype="form-data" name="Order Form">
<bpmn2:documentation id="documentation_2gSSFQ"><![CDATA[<?xml version="1.0"?>
<imixs-form>
<imixs-form-section columns="2" label="">
<item name="customer.ref"
type="custom" required="false"
path="workitemlink"
options="($workflowgroup:Product)((type:workitem) OR (type:workitemarchive))"
label="Customer:" />
</imixs-form-section>
<imixs-form-section columns="1" label="" readonly="false">
<item name="request.subject" type="text" label="Inquiry:" />
</imixs-form-section>
<imixs-form-section columns="1" label="Offer:" readonly="true" >
<item name="ai.workflow.summary" type="custom" path="markdowneditor" />
</imixs-form-section>
</imixs-form>
]]></bpmn2:documentation>
<bpmn2:dataState id="dataState_dDS0jQ"/>
</bpmn2:dataObject>
<bpmn2:association id="association_OseGrQ" sourceRef="dataObject_QIYhww" targetRef="task_BRnorw">
<bpmn2:documentation id="documentation_DZ40yg"/>
</bpmn2:association>
<bpmn2:textAnnotation id="textAnnotation_ASEpEw" textFormat="">
<bpmn2:documentation id="documentation_VV5imw"/>
<bpmn2:text id="text_MAeKTw"><![CDATA[TODO:
Wir müssten das jetzt irgendwie intelligeent zusammenfassen.
Erst mal die Summary als Textbaustein erstelen - ChronicleTextBuilder
Dann das LLM die Final Summary erstellen lassen
Und erst am Ende alles zurück ins RAG - inklusive der Anfrage des Kunden und des Angebots!]]></bpmn2:text>
</bpmn2:textAnnotation>
</bpmn2:process>
<bpmn2:process id="process_2" name="Default Process" processType="Public">
<bpmn2:documentation id="documentation_imRbaw"/>
@ -2125,11 +2632,68 @@ Color: <itemvalue>_color</itemvalue><br />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_LHADMg" id="BPMNShape_mijagQ">
<dc:Bounds height="36.0" width="36.0" x="1237.0" y="167.0"/>
<dc:Bounds height="36.0" width="36.0" x="917.0" y="177.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_0h0Wrw">
<dc:Bounds height="20.0" width="100.0" x="1205.0" y="206.0"/>
<dc:Bounds height="20.0" width="100.0" x="885.0" y="216.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_oOnn8A" id="BPMNShape_5MzWQg">
<dc:Bounds height="36.0" width="36.0" x="1006.0" y="710.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_tnZNmw">
<dc:Bounds height="20.0" width="100.0" x="974.0" y="749.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_YGXi9A" id="BPMNShape_yo3tuA">
<dc:Bounds height="36.0" width="36.0" x="1447.0" y="1487.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_xKoR3A">
<dc:Bounds height="20.0" width="100.0" x="1415.0" y="1526.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_qvmKNg" id="BPMNShape_rxPfsA">
<dc:Bounds height="50.0" width="110.0" x="1470.0" y="1660.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="task_BRnorw" id="BPMNShape_SCUkMw">
<dc:Bounds height="50.0" width="110.0" x="1740.0" y="1660.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_nzILHw" id="BPMNShape_JTPINQ">
<dc:Bounds height="36.0" width="36.0" x="1637.0" y="1667.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_0r0juw">
<dc:Bounds height="20.0" width="100.0" x="1605.0" y="1706.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_tm9U6A" id="BPMNShape_ybPDSA">
<dc:Bounds height="36.0" width="36.0" x="1537.0" y="1642.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_1Xrf7A">
<dc:Bounds height="20.0" width="100.0" x="1505.0" y="1681.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="dataObject_gVhkEg" id="BPMNShape_H8yBMg">
<dc:Bounds height="50.0" width="35.0" x="1640.0" y="1760.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_A0X4vg">
<dc:Bounds height="20.0" width="100.0" x="1607.5" y="1815.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_20Geow" id="BPMNShape_NNSegQ">
<dc:Bounds height="36.0" width="36.0" x="1917.0" y="1667.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_PfBkvA">
<dc:Bounds height="20.0" width="100.0" x="1885.0" y="1706.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="event_pxwPEw" id="BPMNShape_djr1NQ">
<dc:Bounds height="36.0" width="36.0" x="1777.0" y="1767.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_tiUXUw">
<dc:Bounds height="20.0" width="100.0" x="1745.0" y="1806.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="dataObject_QIYhww" id="BPMNShape_q4uvGg">
<dc:Bounds height="50.0" width="35.0" x="1780.0" y="1520.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_An9tRg">
<dc:Bounds height="20.0" width="100.0" x="1747.5" y="1575.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="textAnnotation_ASEpEw" id="BPMNShape_rGwFFA">
<dc:Bounds height="340.0" width="397.0" x="1050.0" y="1610.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="Association_2" id="BPMNEdge_Association_2" sourceElement="BPMNShape_DataObject_1" targetElement="BPMNShape_Task_5">
<di:waypoint x="280.0" y="260.0"/>
<di:waypoint x="280.0" y="285.0"/>
@ -2182,10 +2746,8 @@ Color: <itemvalue>_color</itemvalue><br />
<bpmndi:BPMNLabel id="BPMNLabel_12"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="SequenceFlow_17" id="BPMNEdge_SequenceFlow_18" sourceElement="BPMNShape_IntermediateCatchEvent_14" targetElement="BPMNShape_Task_10">
<di:waypoint x="1515.0" y="1350.0"/>
<di:waypoint x="1515.0" y="1336.0"/>
<di:waypoint x="1527.0" y="1336.0"/>
<di:waypoint x="1527.0" y="1310.0"/>
<di:waypoint x="1525.0" y="1347.0"/>
<di:waypoint x="1525.0" y="1310.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_71"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="SequenceFlow_22" id="BPMNEdge_SequenceFlow_22" sourceElement="BPMNShape_Task_4" targetElement="BPMNShape_EndEvent_2">
@ -2325,13 +2887,13 @@ Color: <itemvalue>_color</itemvalue><br />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="dataObject_u4ZytA" id="BPMNShape_zNuYaQ">
<dc:Bounds height="50.0" width="35.0" x="1280.0" y="800.0"/>
<dc:Bounds height="50.0" width="35.0" x="1270.0" y="800.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_aquA5Q">
<dc:Bounds height="20.0" width="100.0" x="1290.0" y="1805.0"/>
<dc:Bounds height="20.0" width="100.0" x="1232.0" y="856.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="association_0SKl0g" id="BPMNEdge_XpKvAg" sourceElement="BPMNShape_zNuYaQ" targetElement="BPMNShape_Task_9">
<di:waypoint x="1280.0" y="825.0"/>
<di:waypoint x="1270.0" y="825.0"/>
<di:waypoint x="1170.0" y="825.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape bpmnElement="event_EyDvQQ" id="BPMNShape_yKgIag">
@ -2386,13 +2948,14 @@ Color: <itemvalue>_color</itemvalue><br />
<di:waypoint x="1447.0" y="335.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_hkBSvg" id="BPMNEdge_i0Xtag" sourceElement="BPMNShape_mijagQ" targetElement="BPMNShape_GaaSuQ">
<di:waypoint x="1237.0" y="185.0"/>
<di:waypoint x="683.0" y="185.0"/>
<di:waypoint x="917.0" y="195.0"/>
<di:waypoint x="683.0" y="195.0"/>
<di:waypoint x="683.0" y="310.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_BM0t3w" id="BPMNEdge_IilYsw" sourceElement="BPMNShape_wu0GaA" targetElement="BPMNShape_mijagQ">
<di:waypoint x="1255.0" y="310.0"/>
<di:waypoint x="1255.0" y="203.0"/>
<di:waypoint x="1256.0" y="310.0"/>
<di:waypoint x="1256.0" y="195.0"/>
<di:waypoint x="953.0" y="195.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="association_XvFOIw" id="BPMNEdge_i0LSJA" sourceElement="BPMNShape_DataObject_1" targetElement="BPMNShape_Participant_1">
<di:waypoint x="277.5" y="235.0"/>
@ -2409,6 +2972,70 @@ Color: <itemvalue>_color</itemvalue><br />
<di:waypoint x="1468.0" y="289.0"/>
<di:waypoint x="1468.0" y="260.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_1TkjsQ" id="BPMNEdge_k0IlIw" sourceElement="BPMNShape_5MzWQg" targetElement="BPMNShape_Task_9">
<di:waypoint x="1024.0" y="746.0"/>
<di:waypoint x="1024.0" y="773.0"/>
<di:waypoint x="1115.0" y="773.0"/>
<di:waypoint x="1115.0" y="800.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_VQusBA" id="BPMNEdge_H6ynug" sourceElement="BPMNShape_Q9M4JQ" targetElement="BPMNShape_mijagQ">
<di:waypoint x="955.0" y="310.0"/>
<di:waypoint x="955.0" y="262.0"/>
<di:waypoint x="935.0" y="262.0"/>
<di:waypoint x="935.0" y="213.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_FFp2sQ" id="BPMNEdge_xVzADA" sourceElement="BPMNShape_yo3tuA" targetElement="BPMNShape_rxPfsA">
<di:waypoint x="1465.0" y="1523.0"/>
<di:waypoint x="1465.0" y="1592.0"/>
<di:waypoint x="1525.0" y="1592.0"/>
<di:waypoint x="1525.0" y="1660.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_oWlcYg" id="BPMNEdge_plKybg" sourceElement="BPMNShape_Task_10" targetElement="BPMNShape_yo3tuA">
<di:waypoint x="1489.0" y="1310.0"/>
<di:waypoint x="1489.0" y="1399.0"/>
<di:waypoint x="1465.0" y="1399.0"/>
<di:waypoint x="1465.0" y="1487.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_C79hSw" id="BPMNEdge_BWGQDw" sourceElement="BPMNShape_rxPfsA" targetElement="BPMNShape_JTPINQ">
<di:waypoint x="1580.0" y="1685.0"/>
<di:waypoint x="1637.0" y="1685.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_zyO0wQ" id="BPMNEdge_1DOxjA" sourceElement="BPMNShape_JTPINQ" targetElement="BPMNShape_SCUkMw">
<di:waypoint x="1673.0" y="1685.0"/>
<di:waypoint x="1740.0" y="1685.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_7s3Yfw" id="BPMNEdge_2UB0ng" sourceElement="BPMNShape_ybPDSA" targetElement="BPMNShape_JTPINQ">
<di:waypoint x="1555.0" y="1642.0"/>
<di:waypoint x="1555.0" y="1613.0"/>
<di:waypoint x="1655.0" y="1613.0"/>
<di:waypoint x="1655.0" y="1667.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_VtEF4g" id="BPMNEdge_wj7A0Q" sourceElement="BPMNShape_SCUkMw" targetElement="BPMNShape_NNSegQ">
<di:waypoint x="1850.0" y="1685.0"/>
<di:waypoint x="1917.0" y="1685.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="association_icBtwA" id="BPMNEdge_96B5Gg" sourceElement="BPMNShape_H8yBMg" targetElement="BPMNShape_JTPINQ">
<di:waypoint x="1658.0" y="1760.0"/>
<di:waypoint x="1658.0" y="1732.0"/>
<di:waypoint x="1655.0" y="1732.0"/>
<di:waypoint x="1655.0" y="1703.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_11vZNA" id="BPMNEdge_rnr0SQ" sourceElement="BPMNShape_SCUkMw" targetElement="BPMNShape_djr1NQ">
<di:waypoint x="1795.0" y="1710.0"/>
<di:waypoint x="1795.0" y="1767.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_6AvkzQ" id="BPMNEdge_FqsbUA" sourceElement="BPMNShape_djr1NQ" targetElement="BPMNShape_rxPfsA">
<di:waypoint x="1795.0" y="1803.0"/>
<di:waypoint x="1795.0" y="1867.0"/>
<di:waypoint x="1516.0" y="1867.0"/>
<di:waypoint x="1516.0" y="1710.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="association_OseGrQ" id="BPMNEdge_wCq8Ag" sourceElement="BPMNShape_q4uvGg" targetElement="BPMNShape_SCUkMw">
<di:waypoint x="1798.0" y="1570.0"/>
<di:waypoint x="1798.0" y="1615.0"/>
<di:waypoint x="1795.0" y="1615.0"/>
<di:waypoint x="1795.0" y="1660.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
<dc:Font name="arial" size="9.0"/>