Workshop: Workflow-Formulare bauen (von einfach bis Profi)¶
Dieser Workshop führt Schritt für Schritt vom kleinsten mehrstufigen Freigabe-Workflow bis zu Mail-Schablonen, allen Skript-Varianten, Gruppen-Postfächern und dem Kopieren abgeschlossener Vorgänge.
Referenz statt Theorie: Alles hier ist an den mitgelieferten Demo-Formularen (Katalog Demo → Workflow) nachvollziehbar:
Demo Zeigt Urlaubsantrag mit Workflow Grundlagen, Verzweigung, feste Adresse, Gruppen-Postfach, onCopyBegutachtung mit Workflow Seitenleiste + Änderungsprotokoll, Mail-Schablonen für jeden Schritt Bestellfreigabe mit Workflow Skripte je Stufe und Übergang (prüfen, rechnen, ablegen), Abschluss-Sperre Jobticket-Antrag ein ganzer Antrag mit Berechnung, Einwilligung, Unterschrift und Ablehnungs-Stufe — Schritt für Schritt zum Nachbauen Die reine Referenz (Feldtabelle der
<form>_wf, Laufzeit-Ablauf) steht in Workflow (mehrstufige Freigabe). Dieser Workshop baut darauf auf.
Zusammenklicken reicht — das JSON ist zum Nachschauen da
Stufen, Übergänge, Empfänger, Seitenleiste und Änderungsprotokoll richtest du vollständig im Formular-Editor ein, ohne eine Zeile zu tippen; die Mail-Schablonen aus Teil 5 entstehen in der System-Administration. Die eingeklappten Kästen „Hinter den Kulissen" zeigen dir, was dabei in das Formular geschrieben wird. Aufklappen lohnt sich, wenn du einen fertigen Workflow in ein anderes Formular übernehmen willst oder suchst, warum ein Übergang nicht greift — zum Bauen brauchst du es nicht. Nur Teil 6 (Skript-Hooks) verlangt wirklich getippten Code.
Teil 1 — Ein Workflow mit zwei Stufen¶
Ein Workflow ist reine Konfiguration — kein Skript nötig. Er lebt im
Formular-Schema unter dem Schlüssel kc:workflow.
1.1 Ein Status-Feld anlegen¶
Der Workflow merkt sich seinen Stand in einem Zahlenfeld. Konvention:
wf_status (technisch, unsichtbar). Für lesbare Listen/PDF legt man zusätzlich
wf_status_label an (String, das System pflegt es automatisch mit dem
Stufennamen). Zwei Felder, beide unsichtbar:
"wf_status": { "type": "number", "title": "Workflow-Status (technisch)", "kc:visible": false },
"wf_status_label": { "type": "string", "title": "Status", "kc:visible": false, "kc:readonly": true }
1.2 Workflow aktivieren (Formular-Editor)¶
Im Formular-Editor unter Formular-Eigenschaften → Workflow (mehrstufige Freigabe):
- Workflow aktiv anhaken.
- Stufen anlegen (Nummer + Bezeichnung). Nummern frei wählbar — Konvention:
99= Endstufe. - Übergänge je Stufe: „Bei Zustimmung → Stufe X".
So sieht der Block aus — hier am Demo-Formular Urlaubsantrag, dessen erste beide Stufen zu sehen sind:

Der kleinste sinnvolle Fall: Entwurf → Abgeschlossen. Zwei Stufen, ein Übergang — mehr braucht es nicht, damit der Vorgang laufen kann.
Hinter den Kulissen: zwei Stufen und ein Übergang (kc:workflow)
"kc:workflow": {
"enabled": true,
"statusField": "wf_status",
"stages": [
{ "no": 1, "label": "Entwurf", "link": "general" },
{ "no": 99, "label": "Abgeschlossen", "link": "general", "terminal": true }
],
"transitions": {
"1": { "approve": 99 }
}
}
statusField zeigt auf das Zahlenfeld aus 1.1, stages listet die Stufen
in der Reihenfolge der Stufen-Leiste, und transitions ordnet jeder Stufe
ihr Ziel zu. terminal: true markiert die Endstufe.
Sobald ein Datensatz gespeichert ist, erscheint darunter die Workflow-Seite mit Stufen-Leiste, Verlauf und den Buttons Zustimmen / Ablehnen.
Teil 2 — Mehrere Stufen mit Verzweigung (Rücksprung)¶
Echte Freigaben haben Zwischenstufen und einen Rücklauf bei Ablehnung. Das
steuern die transitions: je Stufe ein Ziel für approve und optional reject.
Im Beispiel unten geht es von Entwurf über Prüfung und Freigabe zum Abschluss — und bei Ablehnung jeweils eine Stufe zurück:
- Zustimmung in Stufe 2 → Stufe 3. Ablehnung in Stufe 2 → zurück auf 1.
- Bei einem Rücksprung merkt sich der Workflow den vorherigen Bearbeiter der Ziel-Stufe und benachrichtigt ihn erneut — der Vorgang „kehrt zurück", statt ins Leere zu laufen.
Hinter den Kulissen: vier Stufen mit Rücksprung
"kc:workflow": {
"enabled": true,
"statusField": "wf_status",
"stages": [
{ "no": 1, "label": "Entwurf", "link": "general" },
{ "no": 2, "label": "Prüfung", "link": "general" },
{ "no": 3, "label": "Freigabe", "link": "general" },
{ "no": 99, "label": "Abgeschlossen","link": "general", "terminal": true }
],
"transitions": {
"1": { "approve": 2 },
"2": { "approve": 3, "reject": 1 },
"3": { "approve": 99, "reject": 2 }
}
}
Jeder Eintrag unter transitions trägt den Schlüssel der Ausgangsstufe;
approve und reject nennen die jeweilige Zielstufe. Fehlt reject, gibt
es in dieser Stufe keinen Rücklauf.
optional: truean einer Stufe markiert sie als überspringbar (z. B. eine Vertretungs-Bestätigung, die nicht immer nötig ist).
Beim Bearbeiter sieht eine Stufe mit Rücklauf so aus: oben die Stufen-Leiste,
in der Mitte der Verlauf, unten die Entscheidung. Zurückgeben folgt dem
reject-Übergang der Stufe, Endgültig ablehnen der Ablehnungs-Stufe
(Teil 7).

Teil 3 — Empfänger: Person, feste Adresse, Gruppen-Postfach¶
Beim Weiterleiten wählt der Bearbeiter, an wen die nächste Stufe geht. Es gibt drei Muster.
3.1 Person auswählen (Picker)¶
Standard: der Bearbeiter wählt den Empfänger über den Empfänger-Picker (dieselbe Auswahl wie in der Vorlage Empfängerauswahl). Vor-/Nachname, Personal-Nr., Benutzerkennung und E-Mail werden übernommen.

Ein Klick auf die Zeile übernimmt die Person; erst dann wird der Knopf „Versenden" aktiv:

3.2 Feste Adresse (Sammelpostfach)¶
Soll eine Stufe immer an dieselbe Adresse gehen (z. B. personalabteilung@…),
trägt man an der Stufe eine feste Empfänger-Adresse ein:
{ "no": 4, "label": "Personalabteilung", "link": "general",
"fixedRecipient": "personalabteilung@kehrmann-consulting.com" }
Der Empfänger-Picker entfällt dann für diese Stufe. Im Verlauf erscheint das Postfach als Empfänger; wer den Schritt tatsächlich bearbeitet hat, wird zusätzlich als „bearbeitet von …" ausgewiesen.
3.3 Gruppen-Postfach (mehrere Personen sehen den Vorgang)¶
Eine feste Adresse ist ein Postfach — aber wer darf es bearbeiten? Dazu dient das Gruppen-Sammelpostfach: Alle Mitglieder einer Gruppe sehen die im Umlauf befindlichen Vorgänge in einer eigenen Liste und dürfen die Feststufe bearbeiten.
Das konfigurierst du an einer Liste: Neben der Standard-Liste legst du eine zweite Liste „Personalabteilung (im Umlauf)" an und weist sie der Gruppe zu. Zwei Schalter stehen dafür zur Verfügung:
includeWorkflowAssigned: true— die persönliche Inbox: „mir gerade zugewiesene" Vorgänge tauchen in dieser Liste auf.workflowGroupInbox: "<Gruppe>"— die Gruppen-Inbox: alle Mitglieder der Gruppe Personalabteilung sehen jeden umlaufenden Vorgang.
Hinter den Kulissen: persönliche Inbox und Gruppen-Inbox (kc:lists)
"kc:lists": [
{ "id": "liste", "title": "Urlaubsanträge",
"columns": ["antragsteller", "wf_status_label", "wf_status"],
"default": true, "includeWorkflowAssigned": true },
{ "id": "personalabteilung", "title": "Personalabteilung (im Umlauf)",
"columns": ["antragsteller", "wf_status_label", "wf_status"],
"workflowGroupInbox": "Personalabteilung" }
]
Beide Listen zeigen dieselben Spalten — der Unterschied steckt allein im letzten Schlüssel je Eintrag.
3.4 Wer darf weiterleiten? (Autorisierung)¶
Der „Zustimmen / Ablehnen"-Schritt ist serverseitig abgesichert:
Teil 4 — Seitenleiste + Status + Änderungsprotokoll¶
Zwei Chrome-Bausteine, die jedes Workflow-Formular aufwerten.
4.1 Linke Seitenleiste mit Live-Status¶
Setzt Seiten (kc:pages) voraus. Statt der Reiter oben bekommt das Formular
dann eine Navigation an der linken Seite, die oben den aktuellen
Workflow-Status anzeigt — der Bearbeiter sieht auf jeder Seite, wo der Vorgang
gerade steht. Breite und Anfangszustand (auf- oder zugeklappt) sind
einstellbar.
Hinter den Kulissen: Seitenleiste mit Status (kc:sidebar)
"kc:pageNavStyle": "sidebar",
"kc:sidebar": { "defaultExpanded": true, "showStatus": true, "widthPx": 260 },
"kc:pages": [
{ "id": "antrag", "title": "Antrag", "icon": "01" },
{ "id": "bemerkung", "title": "Bemerkung", "icon": "02" }
]
Jedes Feld bekommt "kc:page": "<seiten-id>", um es einer Seite
zuzuordnen. kc:pageNavStyle schaltet von Reitern auf die Seitenleiste um;
showStatus blendet den Workflow-Status darüber ein.
4.2 Änderungsprotokoll (Audit-Log)¶
kc:auditLog protokolliert jede gespeicherte Änderung und jeden
Workflow-Schritt (Statuswechsel + per Skript gesetzte Werte). Es erscheint als
eigene Seite „Änderungsprotokoll". Eingeschaltet ist das ein Schalter:
Optional feiner justierbar:
| Option | Wirkung |
|---|---|
onlyAfterFirstSave: true |
die Erst-Anlage nicht protokollieren |
onlyForeignEditor: true |
nur protokollieren, wenn NICHT der Ersteller bearbeitet |
Teil 5 — Mail-Schablonen (ohne Skript)¶
Standardmäßig verschickt jeder Stufenwechsel eine schlichte Benachrichtigung mit Datensatz-Link. Über die Property-Mechanik lässt sich pro Statuswechsel Betreff und Text frei gestalten — komplett ohne Skript.
5.1 Welcher Schlüssel wann greift¶
Eine Property mit einem dieser Schlüssel greift (erster Treffer gewinnt). Wert = Betreff, Zusatzwert (langer Text) = Body.
5.2 Beispiel¶
Für begutachtung-workflow, Übergang Stufe 1 → 2:
- Schlüssel:
begutachtung-workflow.msgText.1.2 - Wert (Betreff):
Sichtung angefordert: ${person_name} - Zusatzwert (Body):
Angelegt werden Schablonen am bequemsten im Formular-Editor unter … Mehr → Properties … (nur die Einträge dieses Formulars). Alternativ unter System-Administration → Formular-Konfiguration → Properties (alle Formulare, mit Excel-Import) — siehe Properties.
5.3 Mailtexte per Knopfdruck erzeugen¶
Sie müssen die Schlüssel nicht von Hand zusammensetzen. Ein Knopf legt für jeden Stufenwechsel einen fertigen Mailtext an. Danach passen Sie nur noch die Formulierung an. So geht es:
Schritt 1 — Workflow speichern. Richten Sie die Stufen ein (Teil 1 und 2) und speichern Sie das Formular. Der Knopf arbeitet mit dem gespeicherten Stand.
Schritt 2 — Properties öffnen. Klicken Sie im Formular-Editor oben auf „⋯ Mehr" → „🔧 Properties …". Ein Fenster zeigt die Properties dieses Formulars (Bilder dazu unter Properties → Pflege im Formular-Editor).
Schritt 3 — Knopf drücken. Klicken Sie auf „✉ Workflow-Mailtexte erzeugen". Der Knopf erscheint nur bei Formularen mit eingeschaltetem Workflow. Über der Liste steht danach, was passiert ist, und die neuen Einträge stehen in der Liste.

Im Bild gab es den Eintrag msgText.1.2 schon vorher, mit einem eigenen
Betreff („Bitte um Sichtung …"). Er ist unverändert geblieben; nur die vier
fehlenden sind dazugekommen.
Schritt 4 — Text anpassen. Klicken Sie auf eine Zeile. Im Feld Wert
steht der Betreff, im Feld Zusatzwert der Mailtext. Ändern Sie, was Sie
möchten, und klicken Sie auf Speichern. Die Platzhalter in ${…} füllt
KCForms beim Versenden aus, zum Beispiel ${url} mit dem Link zum Vorgang.

Zeilen, die nur bei Bedarf erscheinen: ${comment?}
${comment} ist der Text, den die bearbeitende Person beim Weiterleiten
eingibt. Oft schreibt sie nichts. Damit dann kein leeres „Hinweis des
Absenders:" in der Mail steht, schreiben die erzeugten Texte
${comment?} — mit Fragezeichen.
Das Fragezeichen bedeutet: Ist der Wert leer, entfällt die ganze Zeile. Ist er gefüllt, steht er wie gewohnt da.
| Im Mailtext | Mit Kommentar „Bitte bis Freitag" | Ohne Kommentar |
|---|---|---|
Hinweis des Absenders: ${comment?} |
Hinweis des Absenders: Bitte bis Freitag | (Zeile fehlt) |
Hinweis des Absenders: ${comment} |
Hinweis des Absenders: Bitte bis Freitag | Hinweis des Absenders: |
Das Fragezeichen geht an jedem Platzhalter, auch an Feldnamen, zum
Beispiel Kostenstelle: ${kostenstelle?}. Ohne Fragezeichen bleibt die
Zeile immer stehen — so verschwindet die Anrede nicht, nur weil ein
Vorname fehlt.
Schritt 5 — später nachgenerieren. Haben Sie eine Stufe dazugenommen, klicken Sie einfach noch einmal auf den Knopf. Es kommen nur die fehlenden Einträge dazu. Ist schon alles da, sagt die Meldung das, und nichts wird geändert:

Mehrsprachige Formulare bekommen je Sprache eine eigene Fassung: die
Basissprache ohne Zusatz, jede weitere mit @sv bzw. @en am Schlüssel
(siehe 5.4). Welche Sprachen das sind,
bestimmen die Sprachen des Formulars (Reiter „Sprachen") und die eingestellte
Sprache der Workflow-Mails. Die schwedische Fassung beginnt mit „Hej", die
englische mit „Hello", und Formulartitel sowie Stufennamen stehen in der
Übersetzung — soweit Sie sie im Reiter „Sprachen" eingetragen haben. Ein
deutsches Formular ohne weitere Sprachen bekommt weiterhin nur deutsche
Einträge.
Ein Eintrag entsteht für genau die Wechsel, die eine Mail auslösen:
| Wechsel | Woher | Mail geht an |
|---|---|---|
| Weiterleiten | „Zustimmung → n" einer Stufe | den nächsten Bearbeiter |
| Abschließen | „Zustimmung" auf eine Endstufe | den Antragsteller |
| Zurückgeben | „Zurückgabe → n" einer Stufe | den Bearbeiter der früheren Stufe |
| Endgültig ablehnen | Ablehnungs-Stufe, an jeder Stufe mit „Zurückgabe" | den Antragsteller |
Für die Begutachtungs-Demo entstehen so genau die fünf Einträge 1.2, 2.1,
2.3, 3.2 und 3.99.
Drei Dinge, auf die Sie sich verlassen können:
- Vorhandenes bleibt, wie es ist. Steht ein Eintrag schon da, wird er nicht angefasst. Klicken Sie nach einer neuen Stufe einfach noch einmal — es kommen nur die fehlenden dazu.
- Eine Kurzform wird nicht ausgehebelt. Gibt es schon
<formId>.msgText.<nach>(ohne Von-Stufe), legt der Knopf für diesen Wechsel nichts an. Der längere Schlüssel würde sonst vorgehen und Ihren Text still ersetzen. Die Meldung nennt den betroffenen Eintrag. - Es zählt der gespeicherte Stand. Haben Sie gerade Stufen geändert und noch nicht gespeichert, fragt der Editor nach. Speichern Sie im Zweifel zuerst.
Eine global.msgText.*-Schablone gilt weiter für alle anderen Formulare. Für
dieses Formular gehen die neuen Einträge vor; die Meldung nennt dann die
abgelöste Schablone.
Hinter den Kulissen: ein erzeugter Eintrag
Für die Begutachtungs-Demo, Stufe 1 → 2:
| Feld | Inhalt |
|---|---|
| Schlüssel | begutachtung-workflow.msgText.1.2 |
| Wert | Begutachtung mit Workflow (Demo) – Sichtung zu beurteilende Person |
| Zusatzwert | Guten Tag ${recipient.firstName} ${recipient.lastName}, … |
| Bemerkung | E-Mail-Schablone 1→2 Entwurf → Sichtung zu beurteilende Person (Weiterleitung, erzeugt) |
Die Texte benutzen nur Platzhalter, die die Engine auch füllt:
${url}, ${comment}, ${recipient.*}, ${sender.*} und Feldnamen.
Der Kommentar steht als ${comment?} darin, die Zeile entfällt also ohne
Kommentar.
Abschluss- und Ablehnungs-Mails beginnen mit „Guten Tag," ohne Namen — der
Antragsteller hat keinen Empfänger-Datensatz, ${recipient.*} wäre leer.
5.4 Mails in einer anderen Sprache¶
Ein Formular verschickt seine Workflow-Mails in einer festen Sprache. Sie stellen sie in den Formular-Eigenschaften im Workflow-Block ein, unter „Sprache der Workflow-Mails". Ohne Auswahl gilt die Basissprache des Formulars.
Die Einstellung wirkt auf drei Dinge:
- Den Standardtext, wenn es keine Schablone gibt. Er liegt für Deutsch, Schwedisch und Englisch bei.
- Den Formulartitel im Betreff. Er kommt aus der Übersetzung des Formulars (Reiter „Sprachen" im Editor). Fehlt sie, steht der Titel in der Basissprache da.
- Die Schablonen. Eine Schablone in einer anderen Sprache bekommt den
Sprachcode mit
@hinten an den Schlüssel:
| Schlüssel | Sprache |
|---|---|
begutachtung-workflow.msgText.1.2 |
Basissprache des Formulars |
begutachtung-workflow.msgText.1.2@sv |
Schwedisch |
begutachtung-workflow.msgText.1.2@en |
Englisch |
Gesucht wird erst die Variante in der Mail-Sprache, dann der Eintrag ohne @.
Ein genauerer Schlüssel geht dabei immer vor: Gibt es für das Formular nur die
deutsche Fassung …msgText.1.2, wird sie genommen — auch wenn es eine
schwedische global.msgText.2@sv gäbe. So kann eine globale Übersetzung nie
still den Text eines einzelnen Formulars verdrängen.
Die Namen der Stufen übersetzen Sie im Editor im Reiter „Sprachen". Dort steht jede Stufe als eigene Zeile „Workflow-Stufe · 2". Die Übersetzung gilt überall: in der Mail („Steg: Granskning"), in der Workflow-Leiste unter dem Formular und in den Knöpfen („✓ Godkänn → Granskning"). Fehlt sie, steht der Name in der Basissprache da.
Eingegebene Daten wie ${person_name} bleiben, wie sie sind — sie werden nie
übersetzt.
Stufennamen im Verlauf
In einer anderen Sprache als der Basissprache zeigt die Tabelle „Verlauf" die Stufennamen in dieser Sprache — so wie die Stufenleiste darüber.
In der Basissprache steht dagegen der Name, der beim Weiterleiten gespeichert wurde. Benennen Sie eine Stufe später um, bleibt der Verlauf dort, wie er war: Er ist ein Protokoll.
5.5 Die Workflow-Leiste in der Sprache des Formulars¶
Die Leiste unter dem Formular — Stufen, Knöpfe, Verlauf, Empfängerauswahl,
Bestätigungen und Fehlermeldungen — spricht dieselbe Sprache wie das Formular
darüber. Schaltet jemand das Formular oben auf Svenska um, wechselt auch die
Leiste. Das gilt auch für die Meldungen des Servers, etwa „Vidarebefordrat
till steg 2 (Granskning)." oder den Hinweis, dass ein Skript den Wechsel
verhindert hat. Den Grund, den Ihr Skript dabei nennt (ctx.cancel("…")),
zeigt KCForms unverändert — schreiben Sie ihn bei Bedarf selbst mehrsprachig,
etwa mit ctx.lang.
Die Sprache der Mail richtet sich noch nicht nach dem Empfänger. Ein Team, in dem Deutsch und Schwedisch gemischt gelesen wird, wählt am besten die Sprache, die alle verstehen.
Teil 6 — Rechnen und Eingreifen per Skript¶
Für alles jenseits der zusammengeklickten Verzweigung stehen Skripte bereit: Werte setzen, ein Fremdsystem benachrichtigen, den Vorgang für ein DMS exportieren, eine zusätzliche Mail verschicken — oder einen Schritt verhindern.
Hinweis Log: Meldungen aus
log.info(...)landen NICHT auf der Docker- Konsole, sondern in/app/logs/script.log(+by-user/<user>.log) und werden automatisch mit[form:<id>]präfixt — so findet man sie im Betrieb wieder.
6.1 Skripte am Stufenwechsel¶
Ein Workflow-Skript hängt an dem Ort, an dem es wirkt. Angelegt wird es deshalb nicht in der Skriptliste, sondern direkt im Workflow-Block: Formular-Eigenschaften → Workflow, Zeile Skripte an der jeweiligen Stufe. Ein Klick öffnet den Editor mit einer passenden Vorlage; ein gefüllter Punkt (●) am Knopf zeigt, dass dort schon ein Skript liegt.
| Knopf | Läuft | Typischer Einsatz |
|---|---|---|
| Beim Erreichen (an der Stufe) | sobald der Vorgang die Stufe erreicht, egal woher | Export bei „Abgeschlossen", Mitteilung bei „Abgelehnt" |
| Prüfung (am Übergang) | vor dem Wechsel — kann ihn verhindern | Pflichtangaben je Schritt, Rückfrage an ein Fremdsystem |
| Aktion (am Übergang) | nach dem Wechsel | Meldung an ein Fremdsystem nur bei Zustimmung |
| Bei jedem Wechsel (unter den Stufen) | bei jedem Stufenwechsel | Zeitstempel, Verlauf fortschreiben |

Im Editor steht über dem Code „Baustein einfügen". Die Bausteine sind
lauffähiger Code für die üblichen Aufgaben — Werte setzen, Meldung an ein
Fremdsystem (REST), Export fürs DMS, zusätzliche E-Mail, Standard-Mail
anpassen, Wechsel verhindern. Anzupassen sind nur die Stellen, die im Baustein
mit ANPASSEN markiert sind.

Fertig eingebaut: die Demo „Bestellfreigabe“
Das Demo-Formular Bestellfreigabe mit Workflow (Skript-Demo) trägt an jeder Stufe Skripte — öffne es im Formular-Editor und sieh unter Formulareigenschaften → Workflow nach, wo ein Punkt (●) steht:
| Stelle | Skript | Was es tut |
|---|---|---|
| Stufe 1, Zustimmung | Prüfung | verlangt Bezeichnung und Betrag |
| Stufe 1, Zustimmung | Aktion | merkt sich, wer eingereicht hat |
| Stufe 2, Zustimmung | Prüfung | verlangt die Kostenstelle |
| Stufe 2, Zustimmung | Aktion | gibt der Benachrichtigung einen eigenen Betreff |
| Stufe 2, Zurückgabe | Prüfung | verlangt einen Kommentar |
| Stufe 3, Zustimmung | Prüfung | Vier-Augen-Prinzip ab 1.000 € brutto |
| Stufe 99 | Beim Erreichen | legt die Bestellung als PDF ab; meldet sie optional an ein anderes Programm |
| Bei jedem Wechsel | Aktion | rechnet Brutto, zählt Schritte, schreibt den Verlauf fort |
Zum Ausprobieren: Mit einem Netto-Betrag unter 840 € kommst du allein bis zum Abschluss. Darüber greift an Stufe 3 das Vier-Augen-Prinzip — dann muss eine andere Person freigeben.
27 Beispiele zum Kopieren
Die Seite Workflow: Skripte am Stufenwechsel erklärt dasselbe Schritt für Schritt in einfachen Worten — von „Feld setzen" bis „Buchhaltung benachrichtigen und PDF ins Archiv legen". Jedes Beispiel dort wird automatisch gegen ein echtes KCForms ausgeführt.
Adressen gehören in die Properties
Die Bausteine lesen Ziel-Adressen aus ctx.params (zum Beispiel
ctx.params.sapUrl). Lege den Wert unter Administration → Properties
an (<formular-id>.sapUrl). So zeigt das Testsystem auf das Test-SAP und
die Produktion auf das echte, ohne dass jemand das Skript anfasst.
Vorher: eine Prüfung kann den Wechsel verhindern¶
Die Prüfung läuft, bevor etwas geschrieben wird. ctx.cancel('Grund')
lässt den Vorgang auf der alten Stufe; der Bearbeiter liest den Grund im
Workflow-Bereich.
// Prüfung vor „3 · Genehmigung" → „4 · Personalabteilung"
if (wf.approve && !$begruendung) {
ctx.cancel('Bitte zuerst eine Begründung eintragen.');
return;
}
ctx.form zeigt in der Prüfung, was der Bearbeiter gerade im Formular stehen
hat. Änderungen an ctx.form werden hier nicht gespeichert — eine Prüfung
prüft nur.
Nachher: Aktionen¶
Aktionen laufen nach dem Statuswechsel und vor der Benachrichtigung. Was das
Skript in ctx.form setzt, wird gespeichert und steht schon in der
Mail-Schablone bereit.
// Aktion nach „3 · Genehmigung" → „4 · Personalabteilung"
// 1. Fremdsystem melden — steht vorn, weil es scheitern kann
var sap = http.post(ctx.params.sapUrl, {
vorgang: ctx.instanceId,
status: wf.toStage,
von: wf.actingLogin
}, { timeout: 15000, retries: 2 });
if (!sap.ok) {
throw new Error('Fremdsystem meldet HTTP ' + sap.status);
}
// 2. Werte setzen — werden automatisch gespeichert
ctx.form.sap_belegnr = sap.json().belegnummer;
ctx.form.letzter_bearbeiter = ctx.user.name || wf.actingLogin;
Scheitert eine Aktion, wird der Wechsel zurückgenommen
Wirft ein Aktions-Skript einen Fehler (oder ruft es ctx.cancel(...)),
steht der Vorgang danach wieder auf der alten Stufe — Status, Verlauf und
Feldwerte wie vor dem Klick. Der Bearbeiter sieht die Meldung und kann es
erneut versuchen.
Was sich nicht zurückholen lässt, ist alles außerhalb des Vorgangs: eine bereits verschickte Mail, eine geschriebene Datei, ein Aufruf, der im Fremdsystem schon gebucht hat. Deshalb die Reihenfolge im Skript: erst, was scheitern kann — zuletzt, was sich nicht zurückholen lässt.
Soll eine Aktion den Vorgang nicht aufhalten (eine Zusatz-Mail etwa), fängst du ihren Fehler selbst ab:
Reihenfolge¶
Bei einem Wechsel von Stufe A nach B laufen die Skripte in dieser Reihenfolge — erst allgemein, dann speziell:
- Prüfung „bei jedem Wechsel", dann Prüfung am Übergang A → B
- der Statuswechsel
- Aktion „bei jedem Wechsel", dann Aktion am Übergang A → B, dann „Beim Erreichen" von B
- die Benachrichtigung
Das wf-Objekt¶
| Feld | Inhalt |
|---|---|
fromStage / toStage |
Nummer der alten und der neuen Stufe |
fromLabel / toLabel |
deren Bezeichnung |
action |
"approve" (Zustimmen), "return" (Zurückgeben) oder "decline" (endgültig ablehnen) |
approve / returned / declined |
dasselbe als true/false |
terminal |
true, wenn die neue Stufe eine Endstufe ist |
comment |
Kommentar des Bearbeiters |
recipient.email / .login / .firstName / .lastName |
Empfänger der neuen Stufe |
initiatorEmail |
Adresse des Antragstellers |
actingLogin, now |
wer entschieden hat und wann |
url |
Link zum Vorgang für den Empfänger (nur in Aktionen) |
mail.skip |
auf true setzen: die Standard-Benachrichtigung dieses Wechsels entfällt |
mail.subject / mail.text |
setzen: ersetzt Betreff bzw. Text der Standard-Benachrichtigung |
wf.decision ("approve"/"reject") gibt es weiterhin; es unterscheidet aber
nicht zwischen Zurückgeben und endgültigem Ablehnen — dafür ist wf.action da.
In allen Workflow-Skripten stehen dieselben Bausteine bereit wie in jedem
anderen Hook: mail,
http,
fs,
pdf, db, log,
ctx.params,
ctx.attachments, die
Bibliotheken und die
Hilfsfunktionen des
Formulars.
Hinter den Kulissen: wie die Skripte heißen
Die Zuordnung steckt im Namen des Skripts — in der Skriptliste steht darunter jeweils der Klartext mit den Stufennamen.
| Name | Bedeutung |
|---|---|
onWorkflowCheck |
Prüfung vor jedem Wechsel |
onWorkflowCheck_3_4 |
Prüfung vor dem Wechsel 3 → 4 |
onWorkflowStep |
Aktion nach jedem Wechsel |
onWorkflowStep_3_4 |
Aktion nach dem Wechsel 3 → 4 |
onWorkflowEnter_99 |
Aktion beim Erreichen der Stufe 99 |
Ändert jemand die Nummer einer Stufe oder das Ziel eines Übergangs, bleibt das Skript unter seinem alten Namen in der Skriptliste stehen und läuft nicht mehr mit. Es wird nicht still gelöscht: benenne es um oder übernimm den Code in das Skript des neuen Übergangs.
6.2 onCopy — die Kopie vorbereiten¶
Läuft beim „Als neuen Satz kopieren". Der zurückgegebene ctx.form wird der
neue Entwurf — ideal, um Unterschriften zu löschen, Vorgabewerte zurückzusetzen
oder den Workflow-Status zu leeren.
// onCopy – frischer Entwurf statt Erbe des abgeschlossenen Originals
ctx.form.wf_status = null; // Workflow zurück auf Anfang
ctx.form.wf_status_label = null;
ctx.form.unterschrift = null; // Signatur-Feld leeren
ctx.form.bemerkung = ""; // Vorgabewert zurücksetzen
// ctx.isNew === true, copy.sourceInstanceId === ID des Quell-Satzes
6.3 Weitere Hooks im Workflow-Kontext¶
Die allgemeinen Lebenszyklus-Hooks greifen auch bei Workflow-Formularen:
| Hook | Typischer Workflow-Einsatz |
|---|---|
onLoad |
Vorbelegen (Antragsteller = angemeldeter Nutzer, Datum = heute). |
onValidate |
Pflichtfelder/Plausibilität prüfen — ctx.addError(feld, meldung). |
onBeforeSave |
Vetoable: ctx.cancel(grund) verhindert das Speichern. |
onSubmit |
Nach dem Speichern: eigene Mail/WebService-Aufrufe (mail, http, ws). |
onAfterSave |
Abschluss der Save-Pipeline; ctx.isNew unterscheidet Neuanlage/Update. |
canEdit |
Versionierung: entscheidet, ob ein geladener Satz bearbeitbar ist. |
Details: Lebenszyklus-Hooks.
Teil 7 — Abschluss-Sperre & Kopieren¶
7.1 Abgeschlossene Vorgänge sperren¶
Erreicht ein Vorgang die Endstufe (terminal: true), ist er standardmäßig
schreibgeschützt — serverseitig durchgesetzt. Diese Sperre kannst du ganz
abschalten oder für einzelne Gruppen lockern:
lockAfterTerminal: false— Sperre ganz aus.editAfterTerminalRoles: [...]— benannte Gruppen/Berechtigungen, die auch danach noch bearbeiten dürfen (Admin darf immer).
Im Formular-Editor stehen beide Einstellungen unter den Stufen — zusammen mit der Position des Workflow-Bereichs und der Stufe für „Endgültig ablehnen":

Hinter den Kulissen: Sperre lockern (lockAfterTerminal)
Beide Schlüssel stehen direkt in kc:workflow, neben stages und
transitions — die Zeile "…": "…" steht hier nur für den übrigen Inhalt.
Ein gesperrter Vorgang zeigt einen Hinweis samt Button „Als neuen Satz kopieren".
7.2 Kopieren¶
„Als neuen Satz kopieren" übernimmt die Werte des (ggf. schreibgeschützten)
Vorgangs in einen neuen Entwurf der aktuellen Formularversion. Mit dem
onCopy-Hook (Teil 6.2) bereitet man diesen Entwurf gezielt vor — im
urlaub-workflow-Demo wird so der Status auf „Entwurf" zurückgesetzt, während
der Antragsteller erhalten bleibt.
Kurz-Referenz¶
kc:workflow-Schlüssel¶
| Schlüssel | Bedeutung |
|---|---|
enabled |
Workflow an/aus |
statusField |
Status-Zahlenfeld (Standard wf_status) |
stages[].no / label |
Stufennummer + Bezeichnung |
stages[].link |
general (Vertreter ok) / personal (nur Empfänger 🔒) |
stages[].terminal |
Endstufe |
stages[].fixedRecipient |
feste Empfänger-Adresse (Postfach-Stufe) |
stages[].optional |
überspringbare Stufe |
transitions.<no>.approve/reject |
Zielstufen der Verzweigung |
lockAfterTerminal |
Abschluss-Sperre (Default true) |
editAfterTerminalRoles[] |
Ausnahme-Gruppen/-Berechtigungen |
Verwandte Schlüssel¶
| Schlüssel | Zweck |
|---|---|
kc:lists[].includeWorkflowAssigned |
persönliche Inbox in einer Liste |
kc:lists[].workflowGroupInbox |
Gruppen-Sammelpostfach |
kc:sidebar.showStatus + kc:pageNavStyle:"sidebar" |
Seitenleiste mit Status |
kc:auditLog.enabled |
Änderungsprotokoll |
<formId>.msgText.[<von>.]<ziel> (Property) |
Mail-Schablone |
Skript-Hooks¶
onWorkflowCheck / onWorkflowStep / onWorkflowEnter (Stufenwechsel, wf-Objekt — Teil 6) · onCopy (copy.sourceInstanceId)
· onLoad · onValidate · onBeforeSave · onSubmit · onAfterSave · canEdit