Workflow-System
Dieses System führt Workflows aus, die vollständig als XML-Dateien definiert sind. Eine Workflow-Datei beschreibt eine Abfolge von Schritten (Tasks) — Formulare, Genehmigungen, E-Mails, PDF-Verarbeitung, Bedingungen — und die Engine arbeitet diese Schritte sequenziell oder parallel ab.
Die wichtigsten Eigenschaften:
- XML statt Code: Neue Abläufe entstehen durch Anlegen einer XML-Datei, nicht durch Programmierung.
- Tokenbasiert und zustandslos: Jeder Schritt ist ein normaler Web-Aufruf. Der komplette Zustand (erledigte Tasks, gesammelte Variablen) wird serverseitig gespeichert — Bearbeiter können Tage später weitermachen, ohne dass etwas verloren geht.
- Benutzer-Interaktion per Weblink: Wenn ein Schritt eine Person erfordert (Formular ausfüllen, genehmigen, abstimmen), erhält diese automatisch eine E-Mail mit einem persönlichen Link.
- E-Mail-Benachrichtigungen: Zuweisungen, Rückgaben und Erinnerungen werden automatisch verschickt.
- PDF-Verarbeitung: Hochgeladene PDFs können gestempelt, mit Text befüllt, zusammengeführt und kryptografisch signiert werden.
- Parallelität und Abstimmungen: Unabhängige Zweige laufen parallel; N-von-M-Abstimmungen (Quorum) sind eingebaut.
Typischer Ablauf: Ein Mitarbeiter startet einen Workflow, füllt ein Formular aus, ein Vorgesetzter bekommt per Mail einen Genehmigungslink, das Dokument wird gestempelt und das Ergebnis per Mail zugestellt — alles definiert in einer einzigen XML-Datei.
Grundkonzepte
Workflow-Definition als XML-Datei
Jeder Workflow ist eine .xml-Datei im Workflow-Ordner der Installation. Der Dateiname (ohne .xml) ist gleichzeitig der Name des Workflow-Typs. Die Datei beschreibt alle Schritte deklarativ; die Engine liest sie bei jedem Aufruf neu ein — Änderungen an der XML wirken sofort auf neue Durchläufe.
Einen Workflow starten
Ein neuer Durchlauf wird über die Start-Seite ausgelöst:
start.php?xml=<name>
<name> ist der Dateiname der Workflow-XML ohne Endung (z. B. start.php?xml=dienstreise). Es wird ein neuer Workflow-Datensatz angelegt, der eingeloggte Benutzer als Antragsteller in den Kontext eingetragen und sofort zum ersten Schritt weitergeleitet.
Lebenszyklus und Status
Jeder Workflow-Durchlauf hat genau einen Gesamtstatus:
| Status | Bedeutung |
|---|---|
RUNNING |
Workflow läuft; die Engine arbeitet automatische Schritte ab (auch nach einer Rückgabe zur Überarbeitung) |
WAITING |
Workflow wartet auf eine Person (z. B. Formular ausfüllen, genehmigen) |
COMPLETED |
Alle Tasks erfolgreich abgeschlossen |
ERROR |
Ein Task ist mit einem technischen Fehler abgebrochen |
CANCELLED |
Workflow wurde bewusst gestoppt (z. B. Ablehnung mit stop-Task) |
Bei jedem Aufruf läuft die Engine die XML von oben durch, überspringt bereits abgeschlossene Tasks und führt den ersten offenen Task aus. Liefert dieser waiting, pausiert der Workflow und der zuständige Bearbeiter wird benachrichtigt.
Zugriffs- und Schritt-Token (Sicherheit)
Jeder Durchlauf ist über zwei Token geschützt:
- Zugriffs-Token (
token): identifiziert den Workflow-Durchlauf. Ohne gültigen Token gibt es keinen Zugriff. - Schritt-Token (
step): wird für jeden neuen interaktiven Schritt frisch erzeugt und nur per Benachrichtigungs-Mail an den zugewiesenen Bearbeiter verschickt.
Der Link in der E-Mail hat die Form:
index.php?token=<zugriffs-token>&step=<schritt-token>
Nur der aktuell zugewiesene Bearbeiter sieht das interaktive Formular — alle anderen erhalten lediglich eine Status-Ansicht. Wechselt der Bearbeiter oder beginnt ein neuer Schritt, wird ein neues Schritt-Token erzeugt und der alte Link damit für interaktive Aktionen ungültig. Formulare sind zusätzlich automatisch CSRF-geschützt.
Kontext-Variablen und Mustache-Templating
Der Kontext ist der gemeinsame Variablenspeicher eines Workflow-Durchlaufs. Jeder abgeschlossene Formular-Task schreibt seine Eingabefelder hinein, jeder Task kann Werte ergänzen — nachfolgende Tasks können alles davon nutzen.
In allen Textknoten der XML (E-Mail-Texte, Empfänger, Bedingungen, Dateiangaben, HTML) können Variablen im Mustache-Format eingesetzt werden:
{{variable}}— einfacher Wert aus dem Kontext{{objekt.feld}}— verschachtelter Zugriff, z. B.{{ICH.mail}}
Wichtige Systemvariablen, die ab dem Start automatisch verfügbar sind:
| Variable | Inhalt |
|---|---|
{{ICH.id}} |
Personen-ID des Antragstellers (der Person, die den Workflow gestartet hat) |
{{ICH.vorname}}, {{ICH.nachname}} |
Name des Antragstellers |
{{ICH.mail}} |
E-Mail-Adresse des Antragstellers |
{{ICH.funktion}} |
Funktion/Rolle des Antragstellers |
{{DATE}} |
Datum des Workflow-Starts (tt.mm.jjjj) |
{{TODAY}} |
Tagesdatum zum Zeitpunkt des jeweiligen Schritts (z. B. für Stempel) |
{{WORKFLOW_ID}} |
Eindeutige numerische ID des laufenden Durchlaufs |
{{URL_WORKFLOW}} |
Basis-Webadresse der Workflow-Anwendung (für selbstgebaute Links) |
{{temp_dir}} |
Arbeitsverzeichnis des Durchlaufs für erzeugte Dateien |
{{latest_pdf_path}} |
Pfad der zuletzt erzeugten/bearbeiteten PDF-Datei — wird von jedem PDF-Task automatisch aktualisiert (dazu passend {{latest_pdf_url}} als Web-Adresse) |
Zuweisung mit <assign_to>
Interaktive Tasks (Formulare, Genehmigungen, Abstimmungen) erhalten ein <assign_to>-Element, das bestimmt, wer den Schritt bearbeiten soll:
<task type="html_form" id="genehmigung">
<assign_to>max.mustermann@example.org</assign_to>
...
</task>
Erlaubt sind eine E-Mail-Adresse, eine Personen-ID aus der Benutzerverwaltung oder ein Namens-Präfix — natürlich auch als Variable ({{ICH.mail}}, {{chef_mail}}). Die Engine löst den Bearbeiter auf und verschickt automatisch eine Benachrichtigungs-Mail mit dem persönlichen Bearbeitungslink, inklusive persönlicher Anrede, sofern die Person im System bekannt ist.
Zwei Komfort-Regeln vermeiden Mail-Flut:
- Selbstzuweisung: Ist der nächste Bearbeiter der aktuell eingeloggte Benutzer, wird keine Mail verschickt — die Folgeseite erscheint direkt im Browser (Schritt-für-Schritt-Durchklicken).
- Unveränderter Schritt: Bleiben Bearbeiter und Schritt gleich (z. B. Seite neu geladen), wird keine erneute Mail verschickt.
Struktur-Elemente
<workflow id="..."> — Wurzelelement
Jede Datei beginnt mit dem <workflow>-Wurzelelement. Direkt darunter steht genau ein <task type="sequence"> als Haupt-Container:
<?xml version="1.0" encoding="UTF-8"?>
<workflow id="mein_workflow_v1">
<task type="sequence" id="haupt">
<!-- Schritte hier -->
</task>
</workflow>
Jedes id-Attribut muss innerhalb der Datei eindeutig sein — die Engine merkt sich anhand der IDs, welche Tasks bereits erledigt sind.
<task type="sequence"> — Reihenfolge
Führt seine Kind-Tasks strikt nacheinander aus. Ein Task startet erst, wenn der vorherige erfolgreich abgeschlossen ist. Sequenzen können beliebig verschachtelt werden.
<task type="parallel"> mit <branch> — parallele Zweige
Führt mehrere unabhängige Zweige aus. Der Parallel-Block gilt erst als abgeschlossen, wenn alle Zweige fertig sind.
<task type="parallel" id="benachrichtigungen">
<branch id="zweig_a">
<task type="email" id="mail_a">...</task>
</branch>
<branch id="zweig_b">
<task type="email" id="mail_b">...</task>
</branch>
</task>
Wartet ein Zweig auf eine Person, pausiert der Parallel-Block an dieser Stelle und wird beim nächsten Aufruf nahtlos fortgesetzt.
Watchdog-Zweige: Zweige, die ausschließlich aus Wächter-Tasks der Typen escalate, wait_until oder external_trigger bestehen (Fristen-Überwachung, Zeitpunkt abwarten, externes Signal), werden automatisch geschlossen, sobald mindestens ein Arbeits-Zweig komplett fertig ist. So blockiert z. B. ein noch laufender Eskalations-Zweig den Abschluss nicht, wenn die eigentliche Arbeit bereits erledigt wurde — typisches Muster: ein Zweig mit dem Genehmigungsformular, daneben ein Watchdog-Zweig, der nach Ablauf einer Frist eskalieren würde.
Testmodus
Für gefahrloses Testen gibt es eine einfache Konvention: Enthält der Kontext eine Variable test_modus_mail mit einer E-Mail-Adresse, werden alle E-Mails des Workflows auf diese Adresse umgeleitet — sowohl die Benachrichtigungs-Mails der Engine als auch die per email-Task verschickten Mails (CC/BCC entfallen dabei komplett). Die Zuweisungen (assign_to) bleiben unverändert, damit auch die Bearbeiter-Logik realistisch getestet werden kann.
Am einfachsten setzt man die Variable ganz am Anfang des Workflows per set_var-Task:
<task type="set_var" id="konfiguration">
<var name="test_modus_mail">tester@example.org</var>
</task>
Zum Produktivschalten den Wert leeren. Der Testmodus gilt nur für Workflows, die die Variable selbst setzen — andere Workflows laufen unverändert.
Minimalbeispiel
Ein vollständiger kleiner Workflow: Antragsteller füllt ein Formular aus, eine zweite Person genehmigt oder lehnt ab, der Antragsteller erhält das Ergebnis per Mail.
<?xml version="1.0" encoding="UTF-8"?>
<workflow id="minimal_antrag_v1">
<task type="sequence" id="haupt">
<!-- 1. Antrag: Formular für den Antragsteller (Person, die den Workflow startet) -->
<task type="html_form" id="antrag">
<assign_to>{{ICH.mail}}</assign_to>
<config>
<required>betreff,begruendung</required>
<html><![CDATA[
<!DOCTYPE html>
<html lang="de">
<head><meta charset="UTF-8"></head>
<body>
<form method="post">
<h2>Antrag stellen</h2>
<p><label>Betreff<br>
<input type="text" name="betreff"></label></p>
<p><label>Begründung<br>
<textarea name="begruendung"></textarea></label></p>
<button type="submit">Absenden</button>
</form>
</body>
</html>
]]></html>
</config>
</task>
<!-- 2. Genehmigung: die zuständige Person erhält automatisch eine Mail mit Link -->
<task type="approve_reject" id="genehmigung">
<assign_to>chefin@example.org</assign_to>
<config>
<title>Antrag prüfen: {{betreff}}</title>
<subtitle>Antrag von {{ICH.vorname}} {{ICH.nachname}}</subtitle>
<output_var>decision</output_var>
</config>
</task>
<!-- 3a. Bei Ablehnung: Mail an Antragsteller, dann Workflow beenden -->
<task type="if" condition="{{decision}} == 'rejected'">
<then>
<task type="email" id="mail_ablehnung">
<config>
<an>{{ICH.mail}}</an>
<titel>Ihr Antrag wurde abgelehnt</titel>
<text><![CDATA[
Hallo {{ICH.vorname}},<br><br>
Ihr Antrag "{{betreff}}" vom {{DATE}} wurde abgelehnt.<br>
<strong>Begründung:</strong> {{decision_reason}}
]]></text>
</config>
</task>
<task type="stop" id="ende_abgelehnt">
<message>Der Antrag wurde abgelehnt.</message>
</task>
</then>
</task>
<!-- 3b. Bei Genehmigung: Bestätigungsmail -->
<task type="email" id="mail_genehmigt">
<config>
<an>{{ICH.mail}}</an>
<titel>Ihr Antrag wurde genehmigt</titel>
<text><![CDATA[
Hallo {{ICH.vorname}},<br><br>
Ihr Antrag "{{betreff}}" vom {{DATE}} wurde genehmigt.
]]></text>
</config>
</task>
</task>
</workflow>
Ablauf: Datei z. B. als minimal_antrag.xml speichern, dann per start.php?xml=minimal_antrag starten. Nach dem Absenden des Antrags erhält chefin@example.org automatisch eine Benachrichtigungs-Mail mit dem persönlichen Genehmigungslink; nach der Entscheidung wird der Antragsteller informiert und der Workflow steht auf COMPLETED (bzw. CANCELLED bei Ablehnung).
Task-Referenz
Alle Task-Typen im Überblick, gruppiert nach Einsatzzweck. Konventionen:
- Pflicht? bezieht sich auf das jeweilige XML-Element innerhalb von
<config>(sofern nicht anders vermerkt). - Alle Werte unterstützen Mustache-Platzhalter
{{...}}. - Interaktive Tasks blockieren den Workflow (
WAITING), bis der zugewiesene Bearbeiter reagiert;<assign_to>steht direkt unter<task>, nicht in<config>.
Steuerung, Logik und Zeit
calc — Berechnung
Zweck: Wertet einen oder mehrere arithmetische bzw. logische Ausdrücke aus und schreibt die Ergebnisse als Kontextvariablen — über einen sicheren eigenen Parser (kein eval).
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
<var name="…" expr="…"/> |
ja (min. 1) | — | Wiederholbar. name = Ziel-Kontextvariable, expr = Ausdruck (Fallback: Element-Text statt expr-Attribut). |
Unterstützte Operatoren: + - * / %, == != < > <= >=, and/or/not (XML-freundliche Alternative zu &&/||/!). Funktionen: round(x, stellen), ceil, floor, abs, min, max, len, upper, lower, concat(...), ifelse(bedingung, dann, sonst). true/false werden zu 1/0. Dezimalkomma (1,50) wird toleriert.
Eingangswerte: Beliebige Kontextvariablen via {{platzhalter}} — sie werden vor dem Parsen aufgelöst.
Ausgangswerte: Jede <var> wird unter ihrem name in den Kontext geschrieben. Vorherige <var>-Zeilen sind in nachfolgenden sofort verfügbar. Bei Auswertungsfehler bricht der Task mit error ab.
<task type="calc" id="berechne">
<var name="brutto" expr="{{netto}} * 1.19" />
<var name="rabatt" expr="round({{brutto}} * {{rabatt_pct}} / 100, 2)" />
<var name="endsumme" expr="{{brutto}} - {{rabatt}}" />
<var name="grosskunde" expr="{{endsumme}} > 10000" />
<var name="info" expr="concat('Endsumme: ', {{endsumme}}, ' EUR')" />
</task>
escalate — Eskalation bei Fristüberschreitung
Zweck: Hält den Workflow bis zum Ablauf einer Frist im Wartezustand; solange bleibt der ursprüngliche Bearbeiter zuständig. Nach Fristablauf wird ein Eskalationsziel per E-Mail benachrichtigt und der Workflow läuft weiter. Typischer Einsatz: parallel zu einem Formular-Task (Watchdog-Zweig), damit liegengebliebene Aufgaben an die nächste Ebene gehen.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
after_days |
eines von beiden | 0 |
Frist in Tagen (Dezimalwerte erlaubt). |
after_hours |
eines von beiden | 0 |
Frist in Stunden; wird mit after_days addiert. |
escalate_to |
ja | — | E-Mail-Adresse des Eskalationsziels. |
original_assignee |
nein | leer | Bearbeiter, der bis zur Eskalation zuständig bleibt (assign_to während der Wartezeit). |
message |
nein | „Eskalation: Frist verstrichen." | Text der Eskalations-Mail. |
flag_var |
nein | — | Kontextvariable, die bei Eskalation auf "1" gesetzt wird. |
Eingangswerte: Platzhalter in escalate_to, original_assignee, message (z. B. {{chef_mail}}).
Ausgangswerte: Bei Eskalation assign_to = Eskalationsziel; optional <flag_var> = "1". Der Fristbeginn wird beim ersten Lauf eingefroren, erneutes Rendern startet die Frist nicht neu. Für vollautomatisches Aufwachen sorgt ein regelmäßiger Hintergrund-Prozess, der wartende Workflows reaktiviert.
<task type="escalate" id="esc_vorsitz">
<config>
<after_days>3</after_days>
<original_assignee>{{vorsitz_mail}}</original_assignee>
<escalate_to>{{chef_mail}}</escalate_to>
<message>Frist verstrichen — bitte stellvertretend genehmigen.</message>
<flag_var>eskaliert</flag_var>
</config>
</task>
external_trigger — Auf externen Callback warten
Zweck: Pausiert den Workflow, bis ein externes System (Signatur-Dienst, Webhook, Pipeline, manueller Klick) eine generierte Callback-URL mit einmaligem Token aufruft. Die mitgesendete Payload landet im Workflow-Kontext. Optional wird das externe System beim Pausieren aktiv per HTTP benachrichtigt (Gegenstück zum ausgehenden webhook-Task).
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
notify_url |
nein | — | URL, die beim Pausieren einmalig aufgerufen wird (z. B. um dem externen System die Callback-URL mitzuteilen). |
notify_method |
nein | POST |
HTTP-Methode für den Notify-Aufruf. |
notify_body |
nein | leer | Request-Body (Content-Type application/json), Platzhalter erlaubt. |
notify_header name="…" |
nein | — | Wiederholbar; zusätzliche HTTP-Header für den Notify-Aufruf. |
url_var |
nein | trigger_url |
Name der Kontextvariable, in der die Callback-URL abgelegt wird. |
store_payload_var |
nein | — | Kontextvariable, unter der die eingehende Callback-Payload gespeichert wird. |
allowed_ips |
nein | — | CSV erlaubter Absender-IPs (exakter Match, kein CIDR). |
hmac_secret |
nein | — | HMAC-Secret; Callback muss dann Header X-Signature: sha256=<hex(hmac(secret, body))> mitsenden. |
timeout_days |
nein | 0 (kein Timeout) |
Hard-Timeout in Tagen; danach endet der Task mit error. |
Eingangswerte: Platzhalter in allen Notify-Feldern; {{trigger_url}} ist im notify_body bereits verfügbar.
Ausgangswerte: <url_var> (Default trigger_url) = Callback-URL mit Token; nach Empfang optional <store_payload_var> = Payload des Callbacks.
<task type="external_trigger" id="warte_auf_signatur">
<config>
<notify_url>https://sign.example.org/api/sign</notify_url>
<notify_body>{"document":"{{pdf_url}}","callback":"{{trigger_url}}"}</notify_body>
<notify_header name="Authorization">Bearer {{api_token}}</notify_header>
<store_payload_var>signatur_antwort</store_payload_var>
<timeout_days>7</timeout_days>
</config>
</task>
if — Bedingte Verzweigung
Zweck: Führt abhängig von einer Bedingung die Tasks im <then>- oder im optionalen <else>-Zweig aus. Auch innerhalb der Zweige funktionieren wartende Tasks — der Workflow setzt beim nächsten Trigger an derselben Stelle fort.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
condition (Attribut) |
ja | — | Bedingung mit Platzhaltern. Operatoren: ==, !=, >, < (numerisch). Ohne Operator: leerer Wert = falsch, nicht-leerer Wert = wahr. Anführungszeichen um Werte werden entfernt. |
<then> |
ja | — | Container mit beliebigen Tasks für den Wahr-Fall. |
<else> |
nein | — | Container mit Tasks für den Falsch-Fall. |
Eingangswerte: Kontextvariablen in der Bedingung (z. B. {{decision}}).
Ausgangswerte: Keine eigenen; Ausgaben der Kind-Tasks werden in den Kontext übernommen.
<task type="if" condition="{{decision}} == 'approved'">
<then>
<task type="email" id="mail_ok">…</task>
</then>
<else>
<task type="email" id="mail_nok">…</task>
<task type="stop" id="abbruch" />
</else>
</task>
log_step — Audit-Log-Eintrag
Zweck: Schreibt einen unveränderlichen Eintrag in das Audit-Log des Workflows (mit Task-ID, Aktion, Benutzer, Details und Zeitstempel). Nützlich zur Nachvollziehbarkeit nach Genehmigungen, Ablehnungen oder anderen wichtigen Schritten.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
aktion |
nein | „Schritt ausgeführt" | Kurzbezeichnung der protokollierten Aktion. |
benutzer |
nein | aktueller Bearbeiter bzw. system |
Wer die Aktion ausgeführt hat. |
details |
nein | leer | Freitext mit Zusatzinformationen. |
Eingangswerte: Platzhalter in allen Feldern (z. B. {{current_assignee}}, {{decision}}).
Ausgangswerte: Keine Kontextvariablen; der Eintrag wird ausschließlich ans Audit-Log angehängt.
<task type="log_step" id="log_genehmigung">
<config>
<aktion>Antrag genehmigt</aktion>
<benutzer>{{current_assignee}}</benutzer>
<details>Entscheidung: {{decision}}, Grund: {{reason}}</details>
</config>
</task>
loop_foreach — Schleife über eine Liste
Zweck: Iteriert über ein Array aus dem Kontext und führt die direkt enthaltenen Kind-Tasks pro Element aus. Voll wartefähig: Pausiert der Workflow mitten in einer Iteration (z. B. für eine Benutzeraktion), geht es beim nächsten Trigger exakt dort weiter. Jede Iteration hat einen eigenen Sub-State, damit sich Abschluss-Marker nicht vermischen.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
items |
ja | — | Quelle der Elemente: Kontext-Array ({{anlagen}}), JSON-String oder kommaseparierte Liste. |
as |
nein | item |
Variablenname des aktuellen Elements im Kontext. |
index_var |
nein | — | Variable für den 0-basierten Index. |
total_var |
nein | — | Variable für die Gesamtanzahl. |
| Kind-Tasks | ja | — | Beliebige <task>-Elemente direkt im Schleifen-Element (analog zu einer Sequenz). assign_to an Kind-Tasks wird bei Wartezuständen automatisch übernommen. |
Eingangswerte: Die referenzierte Liste unter items.
Ausgangswerte: Pro Durchlauf {{<as>}} (aktuelles Element); bei Objekt-Elementen zusätzlich flache Felder {{<as>_feld}} bzw. {{<as>.feld}}; optional {{<index_var>}} und {{<total_var>}}. Ausgaben der Kind-Tasks landen im Kontext. Leere Liste = Schleife wird übersprungen.
<task type="loop_foreach" id="alle_anlagen">
<items>{{anlagen}}</items>
<as>anlage</as>
<index_var>i</index_var>
<total_var>n</total_var>
<task type="pdf_stamp_interactive" id="stempel">
<assign_to>{{ICH.mail}}</assign_to>
<config>
<file>{{anlage.pdf_pfad}}</file>
</config>
</task>
</task>
map_lookup — Wertetabelle / Mapping
Zweck: Bildet einen Eingabewert über eine Inline-Tabelle auf einen Zielwert ab — spart lange <if>-Kaskaden für Zuordnungen wie Status → Empfänger oder Typ → Feldname. Bei fehlendem Treffer greift ein Default.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
input |
ja | leer | Zu vergleichender Wert (Platzhalter erlaubt). |
target_var |
ja | — | Name der Ziel-Kontextvariable. |
default |
nein | leer | Wert bei fehlendem Treffer. |
case_sensitive |
nein | false |
true = Groß-/Kleinschreibung beachten. |
<map><entry from="…" to="…"/></map> |
ja | — | Wiederholbare Einträge; erste Übereinstimmung gewinnt. Statt to-Attribut auch Element-Form <entry from="…"><to>{{…}}</to></entry>. Platzhalter in from/to erlaubt. |
Eingangswerte: Der Wert aus input (z. B. {{subart}}).
Ausgangswerte: <target_var> = gemappter Wert bzw. Default; <target_var>_matched = "1" (Treffer) oder "0" (Default) — praktisch für nachfolgende <if>-Blöcke.
<task type="map_lookup" id="status_zu_feld">
<input>{{subart}}</input>
<target_var>ziel_feld</target_var>
<default>Sonstiges</default>
<map>
<entry from="Planung abgeschlossen" to="PlanungEnde" />
<entry from="Schlussabnahme" to="IstBE" />
</map>
</task>
return_to — Zur Überarbeitung zurückgeben
Zweck: Setzt frühere Schritte zurück, indem die angegebenen Task-IDs aus dem Ausführungsstatus gelöscht werden — sie laufen beim nächsten Trigger erneut. Die ursprüngliche Person wird benachrichtigt; der Workflow bleibt aktiv (kein Abbruch). Typischer Einsatz in einem <if>-Block nach einer Genehmigungsentscheidung „zurückgeben".
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
clear_tasks |
nein | leer | Kommaseparierte Task-IDs, deren Abschluss-Status gelöscht wird (zugehörige Formular-Token werden mit zurückgesetzt). |
assign_to |
nein | leer | Empfänger der Rückgabe-Benachrichtigung. |
message |
nein | „Der Antrag wurde zur Überarbeitung zurückgegeben." | Nachricht an den Empfänger. |
Eingangswerte: Platzhalter in assign_to und message (z. B. {{comment}}).
Ausgangswerte: assign_to und return_message (falls assign_to gesetzt). Der Task wird bewusst nie als abgeschlossen markiert und läuft bei jedem Trigger erneut, solange die Bedingung ihn erreicht.
<task type="if" condition="{{decision}} == 'return'">
<then>
<task type="return_to" id="zurueck_zu_schritt1">
<config>
<clear_tasks>schritt_1_upload,schritt_2_sign_in</clear_tasks>
<assign_to>{{antragsteller_mail}}</assign_to>
<message>Bitte überarbeiten: {{comment}}</message>
</config>
</task>
</then>
</task>
schedule_resume — Geplante automatische Fortsetzung
Zweck: Pausiert den Workflow und plant einen Weck-Zeitpunkt, zu dem der Workflow automatisch fortgesetzt wird — im Gegensatz zu wait_until, das passiv auf den nächsten Trigger wartet. Optional wird beim Pausieren eine Info-Mail versendet.
Parameter (eine Zeitangabe genügt; Priorität: at > after > weekday+time)
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
at |
eines von A/B/C | — | Absoluter Zeitpunkt, z. B. 2026-05-20 08:00. |
after |
eines von A/B/C | — | Relativ zu jetzt (strtotime-Syntax), z. B. +3 days 09:00. |
weekday |
eines von A/B/C | — | Nächster Wochentag (monday … sunday, englisch). |
time |
nein | — | Uhrzeit zum weekday, z. B. 08:00. |
pause_notify_to |
nein | — | Empfänger einer Info-Mail beim Pausieren. |
message |
nein | automatischer Text | Text der Info-Mail. |
store_var |
nein | — | Kontextvariable mit dem Zielzeitpunkt (Format d.m.Y H:i), z. B. für Templates. |
Eingangswerte: Platzhalter in allen Zeit- und Mail-Feldern.
Ausgangswerte: Optional <store_var> = geplanter Zeitpunkt. Der Zielzeitpunkt wird beim ersten Lauf eingefroren. Während der Wartezeit wird bewusst keine Aufgaben-Mail versendet (kein assign_to).
<task type="schedule_resume" id="weckruf_montag">
<config>
<weekday>monday</weekday>
<time>08:00</time>
<pause_notify_to>{{antragsteller_mail}}</pause_notify_to>
<message>Antrag wird {{resume_at}} weiterverarbeitet.</message>
<store_var>resume_at</store_var>
</config>
</task>
set_var — Kontextvariablen setzen
Zweck: Setzt eine oder mehrere Kontextvariablen ohne Benutzerinteraktion. Alle Werte unterstützen Platzhalter; nachfolgende Tasks und E-Mail-Templates können auf die Variablen zugreifen.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
<var name="…">wert</var> |
ja (min. 1) | — | Wiederholbar. name = Variablenname, Element-Text = Wert (Platzhalter erlaubt). |
Eingangswerte: Beliebige Kontextvariablen in den Werten (z. B. {{antragsteller_name}}, {{DATE}}).
Ausgangswerte: Jede <var> unter ihrem Namen im Kontext; frühere <var>-Zeilen sind in späteren sofort nutzbar.
<task type="set_var" id="vars_setzen">
<var name="betreff">Antrag von {{antragsteller_name}} vom {{DATE}}</var>
<var name="empfaenger">registratur@example.org</var>
<var name="betrag_formatiert">{{betrag}} EUR</var>
</task>
signal_fire — Internes Ereignis auslösen
Zweck: Feuert ein Ereignis auf dem internen Event-Bus der Anwendung, sodass registrierte Listener reagieren — ohne Umweg über die HTTP-API. Als Argumente können skalare Werte oder geladene Fachobjekte übergeben werden. Ist der Event-Bus nicht verfügbar, wird der Task mit Warnhinweis übersprungen.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
event |
ja | — | Ereignisname. |
<arg> |
nein | — | Wiederholbar; skalares Argument (Platzhalter erlaubt). |
<load type="massnahme" md5="…"/> |
nein | — | Lädt eine Maßnahme als Argument. |
<load type="person" id="…"/> |
nein | — | Lädt eine Person als Argument. |
<load type="ereignis" id="…"/> |
nein | — | Lädt ein Ereignis als Argument. |
Die Argumente werden in XML-Reihenfolge übergeben; nicht ladbare <load>-Objekte werden übersprungen.
Eingangswerte: Platzhalter in event, <arg> und <load>-Attributen (z. B. {{massnahme_md5}}, {{ICH.id}}).
Ausgangswerte: Keine Kontextvariablen. Wirft ein Listener eine Exception, endet der Task mit error.
<task type="signal_fire" id="emit_done">
<config>
<event>massnahme.saved</event>
<load type="massnahme" md5="{{massnahme_md5}}" />
<arg>{{ICH.id}}</arg>
</config>
</task>
stop — Workflow abbrechen
Zweck: Bricht den gesamten Workflow sofort ab; die Engine setzt den Gesamtstatus auf CANCELLED. Typischer Einsatz nach einer Ablehnung.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
message |
nein | Standard-Abbruchseite | Abbruch-Nachricht (Platzhalter erlaubt). |
Eingangswerte: Platzhalter in message.
Ausgangswerte: Keine; der Task wird nie als abgeschlossen markiert, da der Workflow endet.
<task type="stop" id="abort_process">
<message>Der Antrag wurde abgelehnt.</message>
</task>
subworkflow — Anderen Workflow einbetten
Zweck: Lädt eine zweite Workflow-XML (Name ohne .xml aus dem Workflow-Verzeichnis) und führt sie synchron im laufenden Workflow aus — inklusive Wartezuständen. Sub- und Parent-Workflow teilen sich keinen Ausführungsstatus, dieselbe XML kann also mehrfach eingebettet werden. Variablen werden per <pass> hinein- und per <return>/merge_prefix herausgereicht.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
xml |
ja | — | Name der Sub-Workflow-Definition (ohne .xml). |
<pass><var name="…">wert</var></pass> |
nein | — | Eingangsvariablen für den Sub-Workflow. Ohne <pass> erbt er den gesamten Parent-Kontext. |
<return><var name="…" from="…"/></return> |
nein | — | Rückgabevariablen: from = Name im Sub-Kontext (Default: wie name), name = Zielname im Parent-Kontext. |
merge_prefix |
nein | — | Hängt alternativ/zusätzlich den kompletten Sub-Kontext mit diesem Präfix in den Parent-Kontext. |
Eingangswerte: Parent-Kontext (komplett geerbt) plus explizite <pass>-Variablen.
Ausgangswerte: Die <return>-Variablen bzw. alle Sub-Variablen unter <merge_prefix>…. Wartezustände (inkl. assign_to) werden aus dem Sub-Workflow durchgereicht. Hinweis: Der Sub-Workflow erscheint nicht als eigener Eintrag im Dashboard — dafür stattdessen einen regulären Workflow-Start nutzen.
<task type="subworkflow" id="freigabe">
<config>
<xml>freigabe-modul</xml>
<pass>
<var name="betrag">{{summe}}</var>
</pass>
<return>
<var name="freigabe_decision" from="decision" />
<var name="freigabe_comment" from="comment" />
</return>
</config>
</task>
wait_until — Bis Zeitpunkt warten
Zweck: Pausiert den Workflow bis zu einem festen oder relativen Zeitpunkt. Der Task ist passiv: Er prüft die Uhrzeit beim nächsten Trigger (erneutes Öffnen des Links oder automatischer Weckruf) und schließt sich ab, sobald der Zeitpunkt erreicht ist. Für vollautomatisches Wecken zum Zeitpunkt selbst eignet sich schedule_resume.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
until |
eines von beiden | — | Absoluter Zeitpunkt, z. B. 2026-06-01 09:00 (Vorrang vor relative). |
relative |
eines von beiden | — | Relativ ab jetzt (strtotime-Syntax), z. B. +14 days. |
assign_to |
nein | — | Optionale Zuständigkeit/Benachrichtigung während der Wartezeit. |
store_var |
nein | — | Kontextvariable mit dem Zielzeitpunkt (Format Y-m-d H:i:s). |
Eingangswerte: Platzhalter in until, relative, assign_to.
Ausgangswerte: Optional <store_var> = eingefrorener Zielzeitpunkt. Der Zeitpunkt wird beim ersten Lauf berechnet und fixiert — +14 days zählt also ab dem ersten Lauf, nicht ab jedem Wiederaufruf.
<task type="wait_until" id="frist_2_wochen">
<config>
<relative>+14 days</relative>
<assign_to>{{antragsteller_mail}}</assign_to>
<store_var>frist_zeitpunkt</store_var>
</config>
</task>
Interaktion und Kommunikation
approve_reject — Genehmigen/Ablehnen
Zweck: Zeigt dem Bearbeiter eine JA/NEIN-Entscheidungsseite, optional mit eingebetteter PDF-Vorschau im Vollbild. Der Workflow blockiert, bis der Benutzer entscheidet; <assign_to> bestimmt den Bearbeiter und wer benachrichtigt wird. Bei Ablehnung wird (standardmäßig verpflichtend) eine Begründung über ein Dialogfenster abgefragt.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
pdf |
nein | — | Pfad-Variable zu einer PDF-Datei; wenn gesetzt und vorhanden, wird sie als Vorschau eingebettet |
title |
nein | Genehmigung erforderlich |
Überschrift der Seite |
subtitle |
nein | (leer) | Untertitel |
approve_label |
nein | Genehmigen |
Beschriftung des Zustimmen-Buttons |
reject_label |
nein | Ablehnen |
Beschriftung des Ablehnen-Buttons |
require_reason_on_reject |
nein | true |
Begründung bei Ablehnung erzwingen |
require_reason_on_approve |
nein | false |
Begründung auch bei Genehmigung erzwingen |
output_var |
nein | entscheidung |
Prefix der Ausgabevariablen |
Eingangswerte: Alle Parameter unterstützen Platzhalter, z. B. {{latest_pdf_path}} in <pdf>.
Ausgangswerte:
<prefix>—approvedoderrejected<prefix>_reason— Begründung (Plain Text, ggf. leer)<prefix>_at— ISO-8601-Zeitstempel der Entscheidung
<task type="approve_reject" id="freigabe">
<assign_to>{{fbl_mail}}</assign_to>
<config>
<pdf>{{latest_pdf_path}}</pdf>
<title>Antrag freigeben</title>
<output_var>entscheidung</output_var>
</config>
</task>
calendar_event — Kalendereintrag anlegen
Zweck: Legt vollautomatisch (ohne Benutzerinteraktion) einen Ereignis-Eintrag an — Termin, Frist oder Vermerk — und verknüpft ihn mit einem Bezugsobjekt (z. B. Maßnahme, Person, Verfahren, Vertrag). Optional können Erinnerungen für Personen hinterlegt werden.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
referenz_typ |
ja | — | Typ des Bezugsobjekts, z. B. Massnahme, Person, TG, Vertrag |
referenz_id |
ja | — | ID/Hash des Bezugsobjekts (als String) |
subart |
nein | — | Subkategorie, z. B. Frist |
kommentar |
nein | — | Text/Inhalt des Eintrags |
datum |
nein | jetzt | Termin-Datum |
frist |
nein | (keine) | Fristdatum |
kosten |
nein | 0 |
Kostenangabe (Komma oder Punkt als Dezimaltrenner) |
person |
nein | — | Numerische ID des Erstellers, z. B. {{ICH.id}} |
zuerinnern |
nein | — | CSV numerischer Personen-IDs, die erinnert werden sollen |
output_var |
nein | ereignis_id |
Prefix der Ausgabevariablen |
Eingangswerte: Datumsangaben akzeptieren Unix-Timestamp (rein numerisch), ISO-Format (2026-05-20 oder 2026-05-20 09:00) oder relative Angaben (+14 days, monday 09:00).
Ausgangswerte:
<prefix>— ID des neuen Eintrags<prefix>_datum— formatiertes Datumd.m.Y(z. B. für Mails)<prefix>_frist— formatierte Fristd.m.Y(oder leer)
<task type="calendar_event" id="frist_setzen">
<config>
<referenz_typ>Massnahme</referenz_typ>
<referenz_id>{{massnahme_id}}</referenz_id>
<subart>Frist</subart>
<kommentar>{{betreff}}</kommentar>
<frist>+14 days</frist>
<zuerinnern>{{gewaehlte_person}}</zuerinnern>
</config>
</task>
cloud_link — Öffentlichen Cloud-Freigabelink erzeugen
Zweck: Gibt eine Datei im angebundenen Cloud-Speicher per öffentlichem Link frei und schreibt die Link-URL in den Kontext. Optional wird eine lokale Datei zuvor hochgeladen. Standardberechtigung ist „nur lesen"; Passwortschutz und Ablaufdatum werden unterstützt.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
remote |
ja | — | Zielpfad in der Cloud (relativ, ohne führenden /) |
local |
nein | — | Lokale Datei, die vor der Freigabe an remote hochgeladen wird; Upload-Fehler bricht den Task ab |
password |
nein | (keins) | Passwort für den Freigabelink |
expire_days |
nein | 0 (kein Ablauf) |
Ablauf des Links in Tagen ab heute |
permissions |
nein | 1 |
Berechtigungen: 1 = nur lesen, 15 = Vollzugriff |
cloud_user |
nein | (Standardzugang) | Alias eines konfigurierten Cloud-Zugangs |
link_var |
nein | share_url |
Name der Kontextvariablen für die öffentliche URL |
token_var |
nein | (keine) | Name der Kontextvariablen für das Share-Token |
Eingangswerte: Pfad-Variablen wie {{latest_pdf_path}} für <local>; alle Felder unterstützen Platzhalter.
Ausgangswerte:
<link_var>(Defaultshare_url) — öffentliche Freigabe-URL<token_var>— Share-Token (nur wenn konfiguriert)
<task type="cloud_link" id="share_pdf">
<config>
<remote>Workflow/{{WORKFLOW_ID}}/{{filename}}.pdf</remote>
<local>{{latest_pdf_path}}</local>
<expire_days>14</expire_days>
<link_var>share_url</link_var>
</config>
</task>
email — E-Mail versenden
Zweck: Versendet eine E-Mail (ohne Benutzerinteraktion) mit Betreff, Text und optionalen Anhängen. Der Versand erfolgt über den Mail-Spooler des Systems; Empfänger, Betreff, Text und Anhänge unterstützen Platzhalter. Im Testmodus (test_modus_mail gesetzt) wird der Empfänger umgeleitet und CC/BCC unterdrückt.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
an |
ja | — | Empfängeradresse(n) |
titel |
ja | — | Betreff |
text |
ja | — | Mailtext (HTML erlaubt, CDATA empfohlen) |
cc |
nein | — | CC-Empfänger, kommagetrennt |
bcc |
nein | — | BCC-Empfänger, kommagetrennt |
attachments/file |
nein | — | Ein <file>-Element je Anhang (Pfad); optionales Attribut name="…" setzt einen sprechenden Anzeigenamen (ebenfalls mit Platzhaltern), sonst wird der Dateiname des Pfads verwendet |
Eingangswerte: Beliebige Kontextvariablen in allen Feldern. Zwei Komfort-Anreicherungen (nur für das Rendern dieser Mail):
- Jede Variable mit Suffix
_json, die gültiges JSON enthält, steht zusätzlich ohne Suffix als Liste zur Verfügung — nutzbar als Template-Section:{{#mkz_auswahl}}<li>{{mkz}} — {{name}}</li>{{/mkz_auswahl}} - Ist
{{vkz}}gesetzt, werden{{tg_name}}und{{tg_kurzname}}automatisch nachgeschlagen, sofern noch nicht vorhanden.
Ausgangswerte: keine.
<task type="email" id="info_mail">
<config>
<an>{{gewaehlte_person_mail}}</an>
<cc>info@example.org</cc>
<titel>Neuer Vorgang {{WORKFLOW_ID}}</titel>
<text><![CDATA[Sehr geehrte Damen und Herren, ...]]></text>
<attachments>
<file name="Antrag_{{vkz}}.pdf">{{latest_pdf_path}}</file>
</attachments>
</config>
</task>
html_form — Freies HTML-Formular
Zweck: Rendert ein beliebiges, selbst definiertes HTML-Formular und blockiert den Workflow, bis der Benutzer es absendet; <assign_to> bestimmt Bearbeiter und Benachrichtigung. Nach dem Absenden werden alle POST-Felder unter ihrem Feldnamen in den Workflow-Kontext übernommen und stehen nachfolgenden Tasks als {{feldname}} zur Verfügung. Ein CSRF-Schutz wird automatisch in jedes <form>-Tag injiziert — dafür ist nichts zu konfigurieren.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
html |
ja | — | Vollständiger HTML-Inhalt der Seite (mit mindestens einem <form method="post">); Platzhalter werden gerendert |
required |
nein | (keine) | CSV von Feldnamen, die nicht leer sein dürfen (gilt für Text- und Dateifelder); bei Verstoß wird das Formular mit Hinweis erneut angezeigt |
Eingangswerte: Beliebige Kontextvariablen im HTML; zusätzlich steht {{TASK_ID}} zur Verfügung.
Ausgangswerte:
- Jedes abgesendete Formularfeld als
{{feldname}}(Strings getrimmt) - Datei-Uploads (
<input type="file" name="feld">): pro Datei drei Variablen —{{feld}}— Ablagepfad der hochgeladenen Datei (für Folgetasks wie PDF-Verarbeitung oder Mail-Anhang){{feld}}_name— ursprünglicher Dateiname{{feld}}_url— abrufbare URL der Datei
Uploads sind auf 20 MB begrenzt; ausführbare Formate (Skripte, Programme) werden serverseitig abgelehnt.
<task type="html_form" id="antrag_erfassen">
<assign_to>{{antragsteller_mail}}</assign_to>
<config>
<required>betreff,anlage</required>
<html><![CDATA[
<!DOCTYPE html><html><body>
<form method="post" enctype="multipart/form-data">
<input type="text" name="betreff" placeholder="Betreff">
<textarea name="beschreibung"></textarea>
<input type="file" name="anlage">
<button type="submit">Absenden</button>
</form>
</body></html>
]]></html>
</config>
</task>
load_person — Personendaten nachladen
Zweck: Lädt einen Personen-Stammdatensatz anhand einer ID, E-Mail-Adresse oder Login-Kennung aus der Personenverwaltung und stellt ihn strukturiert im Kontext bereit — typisch, um Anrede oder Mail-Adresse einer über eine ID referenzierten Person zu ermitteln. Läuft ohne Benutzerinteraktion.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
source_id |
ja | — | Ausdruck, der die ID liefert, z. B. {{fbl_id}}; akzeptiert numerische ID, E-Mail oder Login |
target_var |
ja | — | Prefix der Ausgabevariablen, z. B. FBL |
Eingangswerte: Die per source_id referenzierte Kontextvariable. Ist sie leer, wird der Task übersprungen (Erfolg ohne Daten); ist die Person nicht auffindbar, schlägt der Task fehl.
Ausgangswerte:
<target_var>— Personendatensatz als Struktur (id,Vorname,Nachname,mail,telefon,funktion)- Flache Einzelvariablen für einfaches Templating:
<target_var>_id,<target_var>_Vorname,<target_var>_Nachname,<target_var>_mail,<target_var>_telefon,<target_var>_funktion
<task type="load_person" id="fbl_laden">
<config>
<source_id>{{fbl_id}}</source_id>
<target_var>FBL</target_var>
</config>
</task>
<!-- danach nutzbar: {{FBL_mail}}, {{FBL_Nachname}} … -->
mkz_pick — Maßnahmen auswählen
Zweck: Interaktive (Mehrfach-)Auswahl von Maßnahmen (MKZ) eines Verfahrens aus einer filterbaren Liste. Der Workflow blockiert bis zur Auswahl; <assign_to> bestimmt Bearbeiter und Benachrichtigung. Die Auswahl wird serverseitig nachgeladen und validiert (Manipulationsschutz). Optional kann der Bearbeiter direkt im Dialog eine neue („virtuelle") MKZ anlegen.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
vkz |
ja | — | Verfahrenskennziffer, deren Maßnahmen angeboten werden, z. B. {{vkz}} |
multiple |
nein | true |
Mehrfachauswahl erlauben |
only_bau |
nein | true |
Nur Bau-Maßnahmen anzeigen |
allow_virtual |
nein | false |
Button „virtuelle MKZ anlegen" anbieten (mit Prüfziffern-Berechnung) |
required |
nein | true |
Mindestens eine Auswahl erzwingen |
title |
nein | Maßnahmen auswählen |
Überschrift |
text |
nein | (leer) | Einleitungstext |
output_var |
nein | mkz_auswahl |
Prefix der Ausgabevariablen |
Eingangswerte: vkz (typischerweise aus einem vorangegangenen tg_pick).
Ausgangswerte:
<prefix>_json— JSON-Array[{uuid, mkz, name}, …]<prefix>_csv—"MKZ1, MKZ2, …"(lesbare Liste)<prefix>_count— Anzahl
Im email-Task wird <prefix>_json automatisch als Section {{#<prefix>}}…{{/<prefix>}} nutzbar.
<task type="mkz_pick" id="massnahmen_waehlen">
<assign_to>{{bearbeiter_mail}}</assign_to>
<config>
<vkz>{{vkz}}</vkz>
<allow_virtual>true</allow_virtual>
<output_var>mkz_auswahl</output_var>
</config>
</task>
person_pick — Person auswählen
Zweck: Interaktive Auswahl einer oder mehrerer Personen über ein durchsuchbares Dropdown. Die Auswahlliste stammt aus in der Organisation gepflegten Gruppen (oder allen Personen, wenn keine Gruppe angegeben ist). Der Workflow blockiert bis zur Auswahl. Die gewählten IDs werden serverseitig nachgeladen und validiert (Manipulationsschutz).
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
group |
nein | (alle Personen) | Name einer Gruppe oder CSV mehrerer Gruppen (Vereinigungsmenge), z. B. GRUPPE_A,GRUPPE_B |
title |
nein | Person auswählen |
Überschrift |
text |
nein | (leer) | Einleitungstext |
multiple |
nein | false |
Mehrfachauswahl erlauben |
required |
nein | true |
Mindestens eine Person erzwingen |
output_var |
nein | gewaehlte_person |
Prefix der Ausgabevariablen |
Eingangswerte: keine besonderen; alle Parameter unterstützen Platzhalter.
Ausgangswerte:
<prefix>— Personen-ID(s), bei Mehrfachauswahl kommagetrennt<prefix>_json— JSON-Array[{id, vorname, nachname, mail, funktion, name}, …]<prefix>_mail— E-Mail-Adresse(n), CSV<prefix>_name— „Vorname Nachname", bei Mehrfachauswahl CSV<prefix>_nachname— Nachname(n), CSV — z. B. für Stempeltextegez. {{prefix_nachname}}<prefix>_count— Anzahl<prefix>_groups— CSV der konfigurierten Gruppen, in denen die gewählte Person Mitglied ist (Schnittmenge mit<group>); nützlich für Verzweigungen in nachfolgendenif-Tasks
<task type="person_pick" id="pruefer_waehlen">
<assign_to>{{ICH.mail}}</assign_to>
<config>
<group>GRUPPE_LEITUNG</group>
<title>Prüfer auswählen</title>
<output_var>pruefer</output_var>
</config>
</task>
<!-- danach: {{pruefer_mail}}, {{pruefer_name}}, {{pruefer_nachname}} … -->
quorum — Abstimmung (N von M)
Zweck: Mehrpersonen-Abstimmung: Jede in <assign_to> genannte Person darf eine Stimme (Zustimmen/Ablehnen, optional mit Kommentar) abgeben. Der Workflow blockiert, bis required_votes Ja-Stimmen erreicht sind (→ Erfolg) oder das Quorum rechnerisch nicht mehr erreichbar ist (→ Workflow-Stopp). Benachrichtigt werden jeweils nur die noch ausstehenden Abstimmenden. Doppelte Stimmabgaben werden ignoriert.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
assign_to |
ja | — | (direkt unter <task>) kommagetrennte Liste der Stimmberechtigten (E-Mail-Adressen oder IDs) |
required_votes |
nein | 1 |
Anzahl benötigter Ja-Stimmen |
html |
nein | (Standard-Formular) | Eigenes Abstimmungsformular; muss ein Feld quorum_vote (approved/rejected) und optional quorum_comment senden |
Eingangswerte: Im eigenen <html>-Template stehen während der Abstimmung zusätzlich bereit: {{quorum_approved_count}}, {{quorum_rejected_count}}, {{quorum_required}}, {{quorum_total}}, {{quorum_pending}}, {{quorum_already_voted}}, {{quorum_my_vote}}.
Ausgangswerte (nach erreichtem Quorum):
quorum_approved_count— Anzahl Ja-Stimmenquorum_rejected_count— Anzahl Nein-Stimmenquorum_votes— Liste aller Stimmen (Abstimmender, Stimme, Kommentar)
<task type="quorum" id="vorstand_abstimmung">
<assign_to>person1@example.org,person2@example.org,person3@example.org</assign_to>
<config>
<required_votes>2</required_votes>
</config>
</task>
tg_pick — Verfahren auswählen
Zweck: Interaktive Auswahl eines Verfahrens (Teilnehmergemeinschaft) über ein durchsuchbares Dropdown (Suche nach VKZ oder Name). Der Workflow blockiert bis zur Auswahl. Die gewählte VKZ wird serverseitig validiert.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
title |
nein | Teilnehmergemeinschaft auswählen |
Überschrift |
text |
nein | (leer) | Einleitungstext |
vkz_range |
nein | (kein Filter) | Beschränkt die Liste auf einen VKZ-Nummernbereich, Format min-max, z. B. 10-100 |
required |
nein | true |
Auswahl erzwingen |
output_var |
nein | vkz |
Prefix der Ausgabevariablen |
Eingangswerte: keine besonderen.
Ausgangswerte:
<prefix>— die gewählte VKZ (String)<prefix>_name— Langname des Verfahrens<prefix>_kurzname— Kurzname des Verfahrens
<task type="tg_pick" id="tg_waehlen">
<assign_to>{{ICH.mail}}</assign_to>
<config>
<title>Verfahren auswählen</title>
<vkz_range>10-100</vkz_range>
</config>
</task>
<!-- danach: {{vkz}}, {{vkz_name}}, {{vkz_kurzname}} -->
webhook — HTTP-Aufruf an externe URL
Zweck: Sendet einen HTTP-Request an eine beliebige URL (z. B. um ein Drittsystem zu informieren) und kann die Antwort in den Kontext übernehmen. Läuft ohne Benutzerinteraktion; alle Felder unterstützen Platzhalter.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
url |
ja | — | Ziel-URL |
method |
nein | POST |
GET, POST, PUT oder PATCH |
body |
nein | (leer) | Request-Body (bei POST/PUT/PATCH), z. B. JSON |
header |
nein | Content-Type: application/json |
Beliebig viele <header name="…">Wert</header>-Elemente; Werte mit Platzhaltern |
timeout |
nein | 10 |
Timeout in Sekunden |
response_var |
nein | (keine) | Kontextvariable für den Antwort-Body |
fail_on_error |
nein | true |
Bei false gilt der Task auch bei HTTP ≥ 400 oder Verbindungsfehler als erfolgreich (Workflow läuft weiter) |
Eingangswerte: Beliebige Kontextvariablen in url, body und Header-Werten.
Ausgangswerte (nur wenn response_var gesetzt):
<response_var>— Antwort-Body als String<response_var>_data— Antwort zusätzlich als Struktur, falls sie gültiges JSON ist (Felder z. B. per{{antwort_data.feld}}nutzbar)
<task type="webhook" id="archivieren">
<config>
<url>https://api.example.org/archiv</url>
<method>POST</method>
<body>{"id":"{{WORKFLOW_ID}}","file":"{{pdf_url}}"}</body>
<header name="Authorization">Bearer {{api_token}}</header>
<response_var>archiv_antwort</response_var>
</config>
</task>
PDF- und Dokument-Verarbeitung
Wichtige Konvention — Signatur ans Ende der Kette:
pdf_signundpdf_sign_at_textmüssen als letzte PDF-Bearbeitungsschritte einer zusammenhängenden Kette stehen. Text- und Stempel-Tasks (pdf_text,pdf_text_at_text,pdf_stamp_interactive,pdf_merge,pdf_rotate…) importieren das PDF beim Bearbeiten neu und verwerfen dabei vorhandene Annotationen — auch kryptografische Signaturen. Erst alle inhaltlichen Änderungen, dann signieren. (Mehrere Signaturen nacheinander — z. B. Antragsteller, dann später Genehmiger — sind möglich, solange zwischen ihnen kein Text-/Stempel-Task läuft bzw. die erneute Signatur bewusst die letzte Aktion des jeweiligen Abschnitts ist.)
pdf_from_template — PDF aus HTML-Vorlage
Zweck: Erzeugt ein neues PDF aus HTML — entweder direkt inline im XML oder aus einer hinterlegten HTML-Vorlagendatei. Platzhalter werden vor dem Rendern ersetzt. Erspart das manuelle Setzen von Koordinaten, wie es pdf_text erfordern würde.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
output |
ja | — | Zielpfad der erzeugten PDF-Datei (Platzhalter erlaubt, z. B. {{temp_dir}}/antrag_{{WORKFLOW_ID}}.pdf). Verzeichnis wird bei Bedarf angelegt. |
html |
ja¹ | — | Inline-HTML (CDATA empfohlen); wird mit Kontext-Platzhaltern gerendert. |
template |
ja¹ | — | Name einer hinterlegten HTML-Vorlagendatei; fehlt die Dateiendung, wird sie automatisch ergänzt. |
titel |
nein | Dokument |
Dokumenttitel (Kopfbereich). |
untertitel |
nein | (leer) | Untertitel, z. B. Stand {{DATE}}. |
orientation |
nein | P |
P (Hochformat) oder L (Querformat). |
format |
nein | A4 |
A4 oder A3. |
cover |
nein | false |
true = zusätzliche Deckblatt-Seite. |
¹ Genau eine der beiden Quellen html oder template angeben.
Eingangswerte: beliebige Kontext-Variablen für die Platzhalter im HTML; {{temp_dir}} für den Ausgabepfad.
Ausgangswerte: latest_pdf_path, latest_pdf_url.
<task type="pdf_from_template" id="erstelle_pdf">
<config>
<output>{{temp_dir}}/antrag_{{WORKFLOW_ID}}.pdf</output>
<titel>Antrag {{antragsteller_name}}</titel>
<untertitel>Stand {{DATE}}</untertitel>
<html><![CDATA[
<h1>Antrag</h1>
<p>Ihr Antrag vom {{DATE}} wurde mit Vorgang {{WORKFLOW_ID}} aufgenommen.</p>
]]></html>
</config>
</task>
pdf_merge — PDFs zusammenführen
Zweck: Fügt mehrere PDF-Dateien in der angegebenen Reihenfolge zu einem Gesamtdokument zusammen.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
output |
ja | — | Zielpfad des zusammengeführten PDFs. Verzeichnis wird bei Bedarf angelegt. |
file |
ja (mehrfach) | — | Eingabedatei; Element beliebig oft wiederholen. Mindestens 2 existierende Dateien nötig; nicht gefundene Dateien werden mit Warnung übersprungen. Reihenfolge im XML = Reihenfolge im Ergebnis. |
Eingangswerte: Kontext-Variablen mit PDF-Pfaden, z. B. {{antrag_pdf}}, {{anlage_pdf}} oder {{latest_pdf_path}}.
Ausgangswerte: latest_pdf_path, latest_pdf_url (zeigen auf das zusammengeführte Dokument).
<task type="pdf_merge" id="zusammenfuehren">
<config>
<output>{{temp_dir}}/gesamt.pdf</output>
<file>{{antrag_pdf}}</file>
<file>{{anlage_pdf}}</file>
<file>{{unterschrift_pdf}}</file>
</config>
</task>
pdf_rotate — Interaktive Seitendrehung
Zweck: Zeigt dem Bearbeiter eine Vorschau aller Seiten mit Dreh-Buttons (0°/90°/180°/270° je Seite, plus „Alle gleich drehen"). Der Workflow wartet, bis der Nutzer die Drehung bestätigt; erst dann wird das gedrehte PDF erzeugt. Werden alle Winkel auf 0° belassen, wird das Original unverändert durchgereicht.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
file |
ja | — | Eingabe-PDF (z. B. {{latest_pdf_path}}). |
output_var |
nein | — | Zusätzlicher Variablenname für den Ergebnispfad (setzt auch <output_var>_url). |
Die Winkel sind relativ zur angezeigten Vorschau — die Ausgabe zeigt exakt die Drehung, die der Nutzer in der Vorschau gewählt hat.
Eingangswerte: {{latest_pdf_path}} oder eine andere PDF-Pfad-Variable.
Ausgangswerte:
latest_pdf_path,latest_pdf_url(gedrehtes PDF; bei 0°-Passthrough weiterhin das Original)<task_id>_rotations— gewählte Winkel als JSON, z. B.{"1":0,"2":90}<task_id>_geaendert—1wenn gedreht wurde, sonst0- optional
<output_var>und<output_var>_url
<task type="pdf_rotate" id="drehung">
<assign_to>{{bearbeiter_mail}}</assign_to>
<config>
<file>{{latest_pdf_path}}</file>
<output_var>gedrehtes_pdf</output_var>
</config>
</task>
pdf_sign — PDF stempeln und signieren (feste Position)
Zweck: Bringt einen aus Text erzeugten Sichtvermerk-Stempel an einer festen Koordinate auf und versieht das Dokument mit einer kryptografischen Signatur (systemweit hinterlegtes Zertifikat). Der Stempeltext wird dauerhaft „eingebrannt". Die Datei wird in-place überschrieben.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
file |
ja | — | Zu signierendes PDF; wird in-place ersetzt. |
text |
ja | — | Stempeltext (Platzhalter erlaubt), z. B. gez. {{ICH.nachname}}. |
x |
nein | 40 |
X-Position des Stempels in PDF-Punkten, gemessen vom linken Rand. |
y |
nein | 250 |
Y-Position in PDF-Punkten, Y=0 oben (top-down). |
seite (oder page) |
nein | 1 |
Seitennummer, auf der der Stempel platziert wird. |
Die Stempelgröße ist fest (ca. 60 × 25); der Text wird dunkelblau, zentriert gerendert. Vor dem Signieren wird das PDF bei Bedarf automatisch in ein kompatibles Format konvertiert (verlustfrei).
Eingangswerte: {{latest_pdf_path}} bzw. eine PDF-Pfad-Variable wie {{antrag_pdf}}.
Ausgangswerte: latest_pdf_path, latest_pdf_url (zeigen auf die signierte Datei — gleicher Pfad, neuer Inhalt).
<task type="pdf_sign" id="freigabe_sig">
<config>
<file>{{latest_pdf_path}}</file>
<text>Freigegeben: {{ICH.vorname}} {{ICH.nachname}}, {{DATE}}</text>
<x>40</x>
<y>250</y>
<seite>1</seite>
</config>
</task>
pdf_sign_at_text — Stempeln/Signieren an gefundener Textstelle
Zweck: Sucht eine Phrase im PDF-Text (z. B. eine Unterschriftszeile) und platziert relativ dazu einen Sichtvermerk-Stempel samt kryptografischer Signatur — ohne feste Koordinaten pflegen zu müssen. Robust gegen Layout-Verschiebungen der Vorlage. Der Stempel wird eingebrannt, die Datei in-place überschrieben. Wird die Phrase nicht gefunden, bricht der Task mit Fehler ab.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
file |
ja | — | Zu signierendes PDF (in-place). |
search |
ja | — | Exakte Suchphrase (ein oder mehrere Wörter, Whitespace wird normalisiert). Anker ist das erste Wort der Phrase. |
text |
ja | — | Stempeltext; {{TODAY}} steht hier zusätzlich bereit (Datum zum Signierzeitpunkt, nicht Workflow-Start). |
seite |
nein | auto |
auto = alle Seiten durchsuchen, erste Treffer-Seite gewinnt; oder konkrete Seitennummer. |
case_sensitive |
nein | false |
Groß-/Kleinschreibung bei der Suche beachten. |
x_offset_pt |
nein | 0 |
X-Versatz in PDF-Punkten relativ zur linken Kante des Fundworts. |
y_offset_pt |
nein | 0 |
Y-Versatz in PDF-Punkten relativ zur Oberkante des Fundworts. Y=0 oben; negativ = nach oben (über den Text). |
breite_pt |
nein | 120 |
Stempelbreite in PDF-Punkten. |
hoehe_pt |
nein | 30 |
Stempelhöhe in PDF-Punkten. |
fontsize |
nein | 12 |
Schriftgröße des Stempeltexts (vertikal zentriert im Stempelrechteck). |
Eingangswerte: {{latest_pdf_path}} (typisch als file); Kontext-Variablen für den Stempeltext (z. B. {{pruefer_nachname}}).
Ausgangswerte:
latest_pdf_path,latest_pdf_url- Diagnose:
<task_id>_matched_page(Fundseite),<task_id>_matched_x,<task_id>_matched_y_top(Fundposition in pt, Y top-down),<task_id>_stamp_x,<task_id>_stamp_y(tatsächliche Stempelposition inkl. Offsets)
<task type="pdf_sign_at_text" id="vorsitz_sig">
<config>
<file>{{latest_pdf_path}}</file>
<search>Anordnungsbefugten</search>
<seite>auto</seite>
<x_offset_pt>0</x_offset_pt>
<y_offset_pt>-25</y_offset_pt>
<breite_pt>120</breite_pt>
<hoehe_pt>30</hoehe_pt>
<text>{{TODAY}}, gez. {{pruefer_nachname}}</text>
</config>
</task>
pdf_split — PDF aufteilen
Zweck: Teilt ein PDF in Einzelseiten oder benannte Seitenbereiche auf. Die Ergebnis-Pfade landen als Array im Kontext — ideal als Eingabe für loop_foreach.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
file |
ja | — | Quell-PDF. |
output_dir |
ja | — | Zielverzeichnis für die Teil-PDFs (wird bei Bedarf angelegt). Dateiname: <Quellname>_<Bereichsname>.pdf. |
range |
nein (mehrfach) | — | Benannter Bereich mit Attributen name und pages. Seitenangabe: einzelne Seiten, Bereiche und offene Enden kombinierbar, z. B. 1, 2-5, 6-, 1,3-5,8-. Ohne range-Einträge wird jede Seite einzeln gespeichert (Bereichsnamen page_1, page_2, …). |
files_var |
nein | <task_id>_parts |
Name der Kontext-Variable für das Ergebnis-Array. |
Eingangswerte: PDF-Pfad-Variable, z. B. {{antrag_pdf}}; {{temp_dir}} als Zielverzeichnis.
Ausgangswerte:
<files_var>— Array aller Teil-Pfade (in Bereichsreihenfolge)<files_var>_named— Zuordnung Bereichsname → Pfad<files_var>_count— Anzahl erzeugter Teile<task_id>_part_<name>— Einzelpfad je Bereich (z. B.{{split_bereich_part_deckblatt}})
Hinweis: latest_pdf_path wird von diesem Task nicht verändert.
<task type="pdf_split" id="split_bereich">
<config>
<file>{{antrag_pdf}}</file>
<output_dir>{{temp_dir}}</output_dir>
<range name="deckblatt" pages="1" />
<range name="inhalt" pages="2-5" />
<range name="anhang" pages="6-" />
<files_var>teile_pdfs</files_var>
</config>
</task>
pdf_stamp_interactive — Interaktive Stempelplatzierung
Zweck: Zeigt dem Bearbeiter eine PDF-Vorschau, in der er per Doppelklick (Desktop) bzw. langem Drücken (Tablet) die Stempelposition setzt; ein Schieberegler skaliert den Stempel live (30–300 %). Der Workflow wartet, bis platziert wurde; dann wird das Stempelbild dauerhaft eingebrannt. Keine kryptografische Signatur — dafür ist pdf_sign zuständig.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
file |
ja | — | Eingabe-PDF. |
vorlage |
ja¹ | — | Vordefinierter Stempelgenerator: posteingang, postausgang oder bau. |
vorlage_params |
nein | — | Query-Parameter für den Stempelgenerator (nur mit vorlage). |
stempel |
ja¹ | — | Pfad zu einer fertigen Stempelbild-Datei (PNG/JPG). |
stempel_text |
ja¹ | — | Text, aus dem automatisch ein Stempelbild erzeugt wird (dunkelblau, zentriert). |
breite_mm / hoehe_mm |
nein | auto |
Stempelmaße in mm. auto = aus der Bildgröße abgeleitet; ist nur eine Achse auto, bleibt das Seitenverhältnis erhalten. Text-Stempel ohne Bild: Fallback 60 × 25 mm. |
output_var |
nein | — | Zusätzlicher Variablenname für den Ergebnispfad (setzt auch <output_var>_url). |
¹ Genau eine Stempelquelle angeben; Priorität bei Mehrfachangabe: vorlage → stempel → stempel_text.
Die geklickte Position ist der Mittelpunkt des Stempels; der Task rechnet auf die Seitengröße um und begrenzt den Stempel auf den Seitenrand. Das Ergebnis wird als neue Datei im Arbeitsverzeichnis abgelegt.
Eingangswerte: {{latest_pdf_path}} bzw. PDF-Pfad-Variable; {{temp_dir}}.
Ausgangswerte:
latest_pdf_path,latest_pdf_url(gestempeltes PDF)<task_id>_page,<task_id>_x_mm,<task_id>_y_mm(Position obere linke Ecke in mm),<task_id>_breite,<task_id>_hoehe(finale Maße in mm),<task_id>_scale_pct- optional
<output_var>und<output_var>_url
<task type="pdf_stamp_interactive" id="eingangsstempel">
<assign_to>{{registratur_mail}}</assign_to>
<config>
<file>{{latest_pdf_path}}</file>
<vorlage>posteingang</vorlage>
<breite_mm>50</breite_mm>
<hoehe_mm>auto</hoehe_mm>
</config>
</task>
pdf_text — Text an feste Koordinate schreiben
Zweck: Schreibt einen (dynamischen) Text an eine feste Koordinate in ein bestehendes PDF — z. B. um Kopffelder oder Formularpositionen automatisch zu befüllen.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
datei |
ja | — | Quell-PDF. |
dateiout |
nein | = datei |
Ausgabepfad; ohne Angabe wird die Quelldatei in-place überschrieben. |
text |
ja | — | Zu schreibender Text (Platzhalter erlaubt). |
position |
ja | — | x,y in mm, gemessen von der oberen linken Ecke (Y=0 oben). |
seite |
nein | 1 |
Zielseite. |
Eingangswerte: PDF-Pfad-Variable; Kontext-Variablen für den Text.
Ausgangswerte: latest_pdf_path, latest_pdf_url (zeigen auf die Ausgabedatei).
<task type="pdf_text" id="fill_header">
<config>
<datei>{{antrag_pdf}}</datei>
<dateiout>{{temp_dir}}/v0.pdf</dateiout>
<text>{{ICH.vorname}} {{ICH.nachname}}</text>
<position>100,20</position>
<seite>1</seite>
</config>
</task>
pdf_text_at_text — Text an gefundener Textstelle schreiben
Zweck: Sucht eine Phrase im PDF und schreibt relativ dazu einen Text — typischer Anwendungsfall: ein „x" in eine Checkbox neben einem gefundenen Formular-Label setzen. Schwester-Task von pdf_sign_at_text, aber ohne Signatur (reine Textausgabe); kann daher beliebig mitten in der Bearbeitungskette stehen. Wird die Phrase nicht gefunden, bricht der Task mit Fehler ab.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
file |
ja | — | Zu bearbeitendes PDF (in-place). |
search |
ja | — | Suchphrase (1+ Wörter); Anker ist das erste Wort des Treffers. |
text |
ja | — | Zu schreibender Text, z. B. x. |
seite |
nein | auto |
auto = alle Seiten, erste Treffer-Seite; oder Seitennummer. |
case_sensitive |
nein | false |
Groß-/Kleinschreibung beachten. |
x_offset_mm |
nein | 0 |
X-Versatz in mm relativ zur linken Kante des Fundworts; negativ = links davon. |
y_offset_mm |
nein | 0 |
Y-Versatz in mm; Y=0 oben, positiv = nach unten. |
Eingangswerte: {{latest_pdf_path}} bzw. PDF-Pfad-Variable.
Ausgangswerte:
latest_pdf_path,latest_pdf_url- Diagnose:
<task_id>_matched_page,<task_id>_matched_x_pt,<task_id>_matched_y_pt(Fundposition in pt, Y top-down),<task_id>_write_x_mm,<task_id>_write_y_mm(tatsächliche Schreibposition in mm)
<task type="pdf_text_at_text" id="kreuz_a">
<config>
<file>{{latest_pdf_path}}</file>
<search>Reisekostenstelle</search>
<x_offset_mm>-5</x_offset_mm>
<y_offset_mm>0</y_offset_mm>
<text>x</text>
</config>
</task>
vorlage_docx — DOCX aus Vorlagen-Skript erzeugen
Zweck: Ruft serverseitig eine Vorlage des zentralen Vorlagen-Dienstes auf (dieselbe, die auch interaktiv im Browser genutzt wird), befüllt deren Formularfelder aus dem Workflow-Kontext und übernimmt das erzeugte DOCX in den Workflow. Läuft einphasig durch — kein Warten auf Nutzereingaben. Parallele Workflows sind durch einen eindeutigen Vorgangs-Schlüssel und einen Zeitstempel-Check gegen veraltete Ergebnisse abgesichert.
Parameter
| Name | Pflicht? | Default | Beschreibung |
|---|---|---|---|
vorlage |
ja | — | Relativer Pfad der Vorlage innerhalb des Vorlagen-Katalogs (muss auf .php enden; .. ist nicht erlaubt). |
docx_name |
ja | — | Dokumentname, unter dem die Vorlage ihr DOCX ablegt. |
prefill |
nein | — | Block aus <var>-Einträgen: die Formularfelder der Vorlage (siehe unten). |
output_var |
nein | — | Zusätzlicher Variablenname für den DOCX-Pfad (setzt auch <output_var>_url). |
timeout |
nein | 30 |
Timeout des Aufrufs in Sekunden (min. 5). |
<var>-Attribute im <prefill>-Block
| Attribut | Beschreibung |
|---|---|
name |
Feldname im Vorlagen-Formular. Suffix [] = Array-Sammelposten (Element mehrfach wiederholen oder per from_json expandieren). |
from_json |
JSON-String aus einer Kontext-Variable (Platzhalter erlaubt); Einträge werden expandiert. |
field |
Bei from_json: Schlüssel innerhalb der JSON-Einträge, dessen Wert übernommen wird. |
index |
Bei from_json: nur den Eintrag an diesem Index als Einzelwert übernehmen. |
join |
Bei from_json ohne index: alle Werte zu einem String mit diesem Trenner verbinden (z. B. ,). |
lookup_mail |
1 = Wert als E-Mail-Adresse interpretieren und über das Personenverzeichnis in die Personen-ID auflösen (bei Nicht-Treffer bleibt der Originalwert erhalten). |
unique |
1 = Duplikate entfernen (greift nach lookup_mail, dedupliziert also auf ID-Ebene). |
Eingangswerte: Kontext-Variablen für die Prefill-Werte, z. B. {{vkz}}, {{ICH.id}}, JSON-Variablen aus Auswahl-Tasks wie {{mkz_auswahl_json}}.
Ausgangswerte:
latest_docx_path,latest_docx_url(Kopie des DOCX im Arbeitsverzeichnis des Workflows)<task_id>_uuid— Vorgangs-Schlüssel des Vorlagen-Aufrufs<task_id>_quelle— Herkunft des Dokuments (Diagnose)- optional
<output_var>und<output_var>_url
<task type="vorlage_docx" id="erstelle_bestaetigung">
<config>
<vorlage>Beispielbereich/Eingangsbestaetigung/Eingangsbestaetigung.php</vorlage>
<docx_name>Eingangsbestätigung</docx_name>
<prefill>
<var name="vkz">{{vkz}}</var>
<var name="bearbeiter">{{ICH.id}}</var>
<var name="massnahmen[]" from_json="{{mkz_auswahl_json}}" field="mkz" />
<var name="planer" from_json="{{planer_zuordnung_json}}"
field="planer_mail" lookup_mail="1" join="," unique="1" />
</prefill>
<output_var>bestaetigung_docx</output_var>
</config>
</task>