Doku restrukturiert: README als Index, je Task eigene Datei unter tasks/
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
# `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>` — `approved` oder `rejected`
|
||||
- `<prefix>_reason` — Begründung (Plain Text, ggf. leer)
|
||||
- `<prefix>_at` — ISO-8601-Zeitstempel der Entscheidung
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,25 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,38 @@
|
||||
# `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 Datum `d.m.Y` (z. B. für Mails)
|
||||
- `<prefix>_frist` — formatierte Frist `d.m.Y` (oder leer)
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
# `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>` (Default `share_url`) — öffentliche Freigabe-URL
|
||||
- `<token_var>` — Share-Token (nur wenn konfiguriert)
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,34 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,30 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,26 @@
|
||||
# `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`
|
||||
|
||||
```xml
|
||||
<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}} … -->
|
||||
```
|
||||
@@ -0,0 +1,25 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<task type="log_step" id="log_genehmigung">
|
||||
<config>
|
||||
<aktion>Antrag genehmigt</aktion>
|
||||
<benutzer>{{current_assignee}}</benutzer>
|
||||
<details>Entscheidung: {{decision}}, Grund: {{reason}}</details>
|
||||
</config>
|
||||
</task>
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,36 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,36 @@
|
||||
# `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`.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,25 @@
|
||||
# `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).
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,30 @@
|
||||
# `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` — `1` wenn gedreht wurde, sonst `0`
|
||||
- optional `<output_var>` und `<output_var>_url`
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,31 @@
|
||||
# `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).
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,39 @@
|
||||
# `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)
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,35 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,38 @@
|
||||
# `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`
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
# `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).
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
# `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)
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,37 @@
|
||||
# `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 Stempeltexte `gez. {{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 nachfolgenden `if`-Tasks
|
||||
|
||||
```xml
|
||||
<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}} … -->
|
||||
```
|
||||
@@ -0,0 +1,27 @@
|
||||
# `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-Stimmen
|
||||
- `quorum_rejected_count` — Anzahl Nein-Stimmen
|
||||
- `quorum_votes` — Liste aller Stimmen (Abstimmender, Stimme, Kommentar)
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,31 @@
|
||||
# `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`).
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
# `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`.
|
||||
|
||||
```xml
|
||||
<task type="signal_fire" id="emit_done">
|
||||
<config>
|
||||
<event>massnahme.saved</event>
|
||||
<load type="massnahme" md5="{{massnahme_md5}}" />
|
||||
<arg>{{ICH.id}}</arg>
|
||||
</config>
|
||||
</task>
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<task type="stop" id="abort_process">
|
||||
<message>Der Antrag wurde abgelehnt.</message>
|
||||
</task>
|
||||
```
|
||||
@@ -0,0 +1,31 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,31 @@
|
||||
# `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
|
||||
|
||||
```xml
|
||||
<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}} -->
|
||||
```
|
||||
@@ -0,0 +1,50 @@
|
||||
# `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`
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,26 @@
|
||||
# `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.
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
# `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)
|
||||
|
||||
```xml
|
||||
<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>
|
||||
```
|
||||
Reference in New Issue
Block a user