Workflow: Skripte am Stufenwechsel¶
Ein Workflow bringt einen Antrag von Person zu Person: Jemand stellt ihn, jemand prüft ihn, jemand genehmigt ihn. Das klickst du im Formular-Editor zusammen — ganz ohne Skript.
Manchmal soll beim Weiterleiten aber noch etwas passieren:
- Ein Feld soll ausgefüllt werden. Zum Beispiel: „Wer hat genehmigt?"
- Jemand soll eine zusätzliche E-Mail bekommen. Zum Beispiel der Einkauf.
- Der fertige Antrag soll als PDF abgelegt werden. Zum Beispiel für ein Archiv-System.
- Ein anderes Programm soll Bescheid bekommen. Zum Beispiel die Buchhaltung.
- Das Weiterleiten soll verhindert werden, wenn etwas fehlt.
Dafür gibt es Workflow-Skripte. Diese Seite zeigt sie Schritt für Schritt. Du brauchst keine Vorkenntnisse im Programmieren. Jedes Beispiel kannst du kopieren und anpassen.
Wie man einen Workflow zusammenklickt, steht im Workflow-Workshop.
Alles einmal fertig eingebaut
Das Demo-Formular Bestellfreigabe mit Workflow (Skript-Demo) benutzt viele dieser Beispiele an einem echten Ablauf. Du findest es im Katalog Demo, Ordner Workflow. Installiert wird es unter Administration → Formular-Bausteine → Beispiele.
Wörter, die du brauchst¶
| Wort | Bedeutung |
|---|---|
| Vorgang | ein ausgefüllter Antrag, der durch den Workflow läuft |
| Stufe | eine Station im Workflow, zum Beispiel „Prüfung". Jede Stufe hat eine Nummer und einen Namen. |
| Wechsel | der Vorgang geht von einer Stufe zur nächsten |
| Übergang | ein bestimmter Wechsel, zum Beispiel „von Prüfung nach Genehmigung" |
| Bearbeiter | die Person, die gerade auf „Zustimmen" oder „Zurückgeben" klickt |
| Skript | eine kleine Anleitung, die KCForms Zeile für Zeile ausführt |
Das Übungsformular¶
Alle Beispiele benutzen denselben einfachen Antrag mit fünf Stufen:
| Nr. | Stufe | Was passiert dort |
|---|---|---|
| 1 | Entwurf | Der Antragsteller füllt aus. |
| 2 | Prüfung | Die Sachbearbeitung prüft. Sie kann zurückgeben (zurück zu 1). |
| 3 | Genehmigung | Die Leitung genehmigt. Sie kann zurückgeben (zurück zu 2). |
| 99 | Abgeschlossen | Der Antrag ist fertig. |
| 98 | Abgelehnt | Der Antrag wurde endgültig abgelehnt. |
Der Antrag hat diese Felder: betreff, betrag, kostenstelle,
begruendung, angebot, antragsteller_login, bearbeiter, geaendert_am,
schritte, brutto, eilig, frist, belegnummer, hinweis und verlauf.
Dein eigenes Formular hat andere Stufen und andere Felder. Dann ersetzt du in den Beispielen einfach die Nummern und die Feldnamen.
Wo trage ich ein Skript ein?¶
- Öffne dein Formular im Formular-Editor.
-
Klicke über der Vorschau auf Formulareigenschaften bearbeiten.

-
Klappe den Abschnitt Workflow auf.
-
Bei jeder Stufe steht ganz unten eine Zeile Skripte. Klicke dort auf einen Knopf.

-
Der Editor öffnet sich. Füge dein Skript ein.
- Klicke oben auf Speichern.
So liest du das Bild: Die Stufe 3 heißt „Genehmigung". Bei Zustimmung geht der Vorgang zur Stufe 99, bei Zurückgabe zur Stufe 2. Für jeden dieser beiden Wege gibt es zwei Knöpfe: Prüfung und Aktion. Dazu kommt der Knopf Beim Erreichen für die Stufe selbst.
Es gibt vier Arten von Knöpfen. Jeder Knopf steht für einen Zeitpunkt:
| Knopf | Wann läuft das Skript? |
|---|---|
| Beim Erreichen | wenn der Vorgang bei dieser Stufe ankommt. Egal, woher er kommt. |
| Prüfung | bevor der Vorgang weitergeht. Das Skript kann das Weitergehen verhindern. |
| Aktion | nachdem der Vorgang weitergegangen ist. |
| Bei jedem Wechsel | bei jedem Wechsel im ganzen Workflow. Diese Knöpfe stehen unter den Stufen. |
Ein Punkt (●) am Knopf bedeutet: Hier liegt schon ein Skript. Ein Plus (+) bedeutet: Hier liegt noch keins.
Die Knöpfe für jeden Wechsel stehen unter der letzten Stufe:

Fertige Bausteine
Im Editor gibt es oben das Menü Baustein einfügen. Dort findest du
fertigen Code für die häufigsten Aufgaben. Du musst nur die Stellen ändern,
an denen ANPASSEN steht.
So sieht der Editor aus, wenn du auf einen Knopf ohne Skript klickst:

- Links stehen alle Skripte des Formulars. Unter dem Namen steht in Klartext, wozu das Skript gehört.
- Oben ist das Menü Baustein einfügen.
- Die braunen Zeilen mit
//am Anfang sind Hinweise für dich. KCForms führt sie nicht aus. Du kannst sie stehen lassen oder löschen. - Dein Skript schreibst du unter die Hinweise.
Über jedem Beispiel auf dieser Seite steht, welchen Knopf du brauchst.
Zwei Dinge, die in jedem Skript vorkommen¶
ctx.form ist der Antrag. Mit ctx.form.betreff liest du das Feld
„betreff". Mit ctx.form.betreff = "Neu" schreibst du hinein.
wf beschreibt den Wechsel, der gerade passiert:
| Das schreibst du | Das bekommst du |
|---|---|
wf.fromLabel |
Name der alten Stufe, zum Beispiel „Prüfung" |
wf.toLabel |
Name der neuen Stufe |
wf.fromStage, wf.toStage |
die Nummern der beiden Stufen |
wf.approve |
true, wenn der Bearbeiter zugestimmt hat |
wf.returned |
true, wenn er zurückgegeben hat |
wf.declined |
true, wenn er endgültig abgelehnt hat |
wf.comment |
der Kommentar, den er geschrieben hat |
wf.actingLogin |
die Kennung des Bearbeiters |
wf.now |
der Zeitpunkt des Klicks |
Mit log.info("…") schreibt ein Skript eine Zeile ins Protokoll. So kannst
du sehen, was es getan hat.
Einsteiger¶
1. Merken, wann zuletzt etwas passiert ist¶
Knopf: „Bei jedem Wechsel" → Aktion
Das Skript schreibt den Zeitpunkt und den Namen des Bearbeiters in zwei Felder. Du musst nichts speichern: KCForms speichert geänderte Felder selbst.
ctx.form.geaendert_am = wf.now;
ctx.form.bearbeiter = ctx.user.name;
log.info("Wechsel nach " + wf.toLabel);
2. Nur bei einem bestimmten Übergang etwas tun¶
Knopf: Stufe 1 „Entwurf" → Zustimmung → Aktion
Dieses Skript läuft nur, wenn der Antrag eingereicht wird. Also beim Wechsel von „Entwurf" nach „Prüfung". Es merkt sich, wer den Antrag gestellt hat.
ctx.form.antragsteller_login = wf.actingLogin;
ctx.form.hinweis = "Eingereicht am " + new Date().format("dd.MM.yyyy");
3. Etwas tun, wenn der Antrag fertig ist¶
Knopf: Stufe 99 „Abgeschlossen" → Beim Erreichen
„Beim Erreichen" ist praktisch für die letzte Stufe. Es ist egal, von welcher Stufe der Vorgang kommt.
4. Das Weiterleiten verhindern¶
Knopf: Stufe 1 „Entwurf" → Zustimmung → Prüfung
Eine Prüfung läuft, bevor der Vorgang weitergeht. Mit ctx.cancel("…")
bleibt der Vorgang stehen. Der Text in den Klammern erscheint beim Bearbeiter.
Schreibe ihn so, dass er weiß, was zu tun ist.
In diesem Beispiel fehlt die Begründung. Der Antrag bleibt im Entwurf.
Das sieht der Bearbeiter, wenn er trotzdem auf „Versenden" klickt. Die Meldung steht direkt unter dem Knopf, und der Vorgang bleibt bei „Entwurf":

$begruendung ist eine Kurzform für ctx.form.begruendung. Das ! davor
bedeutet „nicht": Wenn es keine Begründung gibt, dann …
return beendet das Skript an dieser Stelle.
5. Eine Grenze prüfen¶
Knopf: Stufe 1 „Entwurf" → Zustimmung → Prüfung
Ab 5.000 Euro muss ein Angebot vorliegen. $betrag.num liefert den Betrag
als Zahl, mit der man rechnen und vergleichen kann.
Hier ist der Betrag kleiner. Die Prüfung lässt den Antrag durch.
if ($betrag.num >= 5000 && $angebot !== "ja") {
ctx.cancel("Ab 5.000 Euro brauchen wir ein Angebot.");
return;
}
log.info("Betrag in Ordnung: " + $betrag.num);
6. Beim Zurückgeben einen Kommentar verlangen¶
Knopf: Stufe 2 „Prüfung" → Zurückgabe → Prüfung
Wer einen Antrag zurückgibt, soll schreiben, warum. Sonst weiß der Antragsteller nicht, was er ändern soll.
if (!wf.comment) {
ctx.cancel("Bitte schreibe einen Kommentar: Was soll geändert werden?");
return;
}
7. Zustimmen und Zurückgeben unterscheiden¶
Knopf: „Bei jedem Wechsel" → Aktion
Ein Skript für jeden Wechsel kann nachsehen, was der Bearbeiter getan hat. Hier gibt er den Antrag zurück.
if (wf.approve) {
ctx.form.hinweis = "Weitergeleitet an: " + wf.toLabel;
}
if (wf.returned) {
ctx.form.hinweis = "Zurückgegeben: " + wf.comment;
}
if (wf.declined) {
ctx.form.hinweis = "Abgelehnt: " + wf.comment;
}
Fortgeschritten¶
8. Rechnen: Brutto und „eilig"¶
Knopf: Stufe 1 „Entwurf" → Zustimmung → Aktion
Beim Einreichen rechnet das Skript den Brutto-Betrag aus. Teure Anträge bekommen eine Markierung.
var netto = $betrag.num;
ctx.form.brutto = Math.round(netto * 1.19 * 100) / 100;
ctx.form.eilig = netto > 10000 ? "ja" : "nein";
Math.round(… * 100) / 100 rundet auf zwei Stellen nach dem Komma.
9. Einen Verlauf fortschreiben¶
Knopf: „Bei jedem Wechsel" → Aktion
Bei jedem Wechsel kommt eine Zeile dazu. So steht im Antrag selbst, was
passiert ist. Das Feld verlauf muss ein mehrzeiliges Textfeld sein —
ein einzeiliges Feld ist nach wenigen Zeilen voll.
var zeile = new Date().format("dd.MM.yyyy HH:mm")
+ " " + wf.fromLabel + " -> " + wf.toLabel
+ " (" + wf.actingLogin + ")";
if (ctx.form.verlauf) {
ctx.form.verlauf = ctx.form.verlauf + "\n" + zeile;
} else {
ctx.form.verlauf = zeile;
}
ctx.form.schritte = $schritte.num + 1;
log.info(zeile);
10. Prüfen, was der Bearbeiter gerade eingetragen hat¶
Knopf: Stufe 2 „Prüfung" → Zustimmung → Prüfung
Die Sachbearbeitung soll die Kostenstelle eintragen, bevor sie weiterleitet. Die Prüfung sieht, was gerade im Formular steht — auch wenn es noch nicht gespeichert ist.
Hier hat die Sachbearbeitung „4711" eingetragen. Der Antrag geht weiter, und die Kostenstelle wird mitgespeichert.
11. Eine Frist setzen¶
Knopf: Stufe 3 „Genehmigung" → Beim Erreichen
Die Leitung hat 14 Tage Zeit. Das Skript rechnet das Datum aus.
var frist = new Date();
frist.setDate(frist.getDate() + 14);
ctx.form.frist = frist.format("yyyy-MM-dd");
Ein Datumsfeld bekommt das Datum immer in der Form Jahr-Monat-Tag.
12. Vier-Augen-Prinzip¶
Knopf: Stufe 3 „Genehmigung" → Zustimmung → Prüfung
Niemand soll seinen eigenen Antrag genehmigen. Das Feld
antragsteller_login wurde in Beispiel 2 beim Einreichen gefüllt.
if (wf.actingLogin === $antragsteller_login) {
ctx.cancel("Vier-Augen-Prinzip: Du kannst deinen eigenen Antrag nicht genehmigen.");
return;
}
13. Eine zusätzliche E-Mail schicken¶
Knopf: Stufe 2 „Prüfung" → Zustimmung → Aktion
Der nächste Bearbeiter bekommt seine Benachrichtigung automatisch. Dieses Skript schickt zusätzlich eine Mail — zum Beispiel an den Einkauf oder an eine Firma außerhalb.
mail.send({
to: "einkauf@example.com",
subject: "Antrag geprüft: " + $betreff,
body: "Guten Tag,\n\nder Antrag wurde geprüft und liegt jetzt bei der Leitung.\n\n"
+ "Betrag: " + $betrag + " Euro\n\nViele Grüße"
});
\n bedeutet „neue Zeile".
14. Eine E-Mail mit dem Antrag als PDF¶
Knopf: Stufe 99 „Abgeschlossen" → Beim Erreichen
Für einen Anhang braucht die Mail zwei Teile: den Text und das PDF.
addOutput hängt den Antrag als PDF an.
var teile = new mail.MessageMultipart();
teile.addText("Guten Tag,\n\nim Anhang finden Sie unsere Bestellung.\n\nViele Grüße");
teile.addOutput("Bestellung-" + ctx.instanceId + ".pdf");
var nachricht = new mail.Message();
nachricht.to = "lieferant@example.com";
nachricht.subject = "Bestellung " + ctx.instanceId;
nachricht.content = teile;
mail.send(nachricht);
ctx.instanceId ist die Nummer des Vorgangs.
15. Der Benachrichtigung einen eigenen Betreff geben¶
Knopf: Stufe 2 „Prüfung" → Zustimmung → Aktion
Die automatische Benachrichtigung hat einen festen Text. Mit wf.mail
änderst du ihn für diesen einen Wechsel. wf.url ist der Link zum Vorgang.
wf.mail.subject = "Bitte genehmigen: " + $betreff;
wf.mail.text = "Guten Tag,\n\nbitte genehmigen Sie diesen Antrag:\n" + wf.url
+ "\n\nViele Grüße";
Für feste Texte brauchst du kein Skript: Dafür gibt es die Mail-Schablonen.
16. Die Benachrichtigung abschalten¶
Knopf: Stufe 2 „Prüfung" → Zurückgabe → Aktion
Manchmal soll bei einem Wechsel keine automatische Mail rausgehen.
17. Den Antragsteller über eine Ablehnung informieren¶
Knopf: Stufe 98 „Abgelehnt" → Beim Erreichen
wf.initiatorEmail ist die Adresse der Person, die den Antrag gestellt hat.
Die Ablehnung kann von jeder Stufe kommen — deshalb „Beim Erreichen".
wf.mail.skip = true; // die automatische Mail ersetzen wir durch unsere
mail.send({
to: wf.initiatorEmail,
subject: "Ihr Antrag wurde abgelehnt: " + $betreff,
body: "Guten Tag,\n\nIhr Antrag wurde leider abgelehnt.\n\n"
+ "Grund: " + wf.comment + "\n\nViele Grüße"
});
Profi¶
Ab hier sprechen die Skripte mit anderen Programmen oder schreiben Dateien. Dabei kann etwas schiefgehen: Das andere Programm antwortet nicht, oder es meldet einen Fehler. Deshalb zuerst die wichtigste Regel.
Wenn ein Skript scheitert, geht der Vorgang zurück
Scheitert ein Skript nach dem Wechsel, dann nimmt KCForms den Wechsel zurück. Der Vorgang steht wieder auf der alten Stufe. Alle Felder haben wieder ihre alten Werte. Der Bearbeiter sieht eine Meldung und kann es später noch einmal versuchen.
Das ist Absicht. Sonst stünde im Antrag „genehmigt", obwohl die Buchhaltung nie davon erfahren hat.
Eines kann KCForms nicht zurücknehmen: was schon draußen ist. Eine verschickte Mail ist verschickt. Eine geschriebene Datei ist geschrieben.
Daraus folgt die Reihenfolge in jedem Skript:
- Zuerst, was schiefgehen kann: der Aufruf an das andere Programm.
- Dann die Felder im Antrag.
- Zuletzt, was man nicht zurückholen kann: Mail und Datei.
Die Übungs-Adresse
Die Beispiele rufen eine Übungs-Adresse auf, die KCForms selbst mitbringt:
http://localhost:8099/api/demo/http/echo. Sie schickt zurück, was sie
bekommt. In deinem Skript steht dort die Adresse des echten Programms.
localhost muss der Administrator einmal freigeben — siehe
Internet (HTTP).
18. Ein anderes Programm benachrichtigen¶
Knopf: Stufe 3 „Genehmigung" → Zustimmung → Aktion
Das Skript schickt die Daten des Antrags an ein anderes Programm, zum Beispiel an die Buchhaltung. Die Antwort enthält eine Belegnummer. Das Skript schreibt sie in den Antrag.
antwort.ok ist true, wenn das andere Programm „alles gut" gemeldet hat.
Wenn nicht, bricht throw new Error("…") das Skript ab. Der Vorgang geht
dann zurück.
var antwort = http.post("http://localhost:8099/api/demo/http/echo", {
vorgang: ctx.instanceId,
betrag: $betrag.num,
kostenstelle: $kostenstelle,
genehmigt_von: wf.actingLogin
}, { timeout: 15000 });
if (!antwort.ok) {
throw new Error("Die Buchhaltung meldet einen Fehler (" + antwort.status + ").");
}
log.info("Buchhaltung hat geantwortet: " + antwort.status);
// Die Übungs-Adresse schickt unsere Daten zurück. Ein echtes Programm
// würde hier seine eigene Belegnummer liefern.
var daten = antwort.json();
ctx.form.belegnummer = "BH-" + daten.body.vorgang;
19. Das andere Programm antwortet nicht¶
Knopf: Stufe 3 „Genehmigung" → Zustimmung → Aktion
Dieses Beispiel zeigt, was bei einem Fehler passiert. Die Übungs-Adresse
…/status/503 meldet immer „nicht verfügbar".
Das Skript hat vorher schon ein Feld gesetzt. Nach dem Fehler ist das Feld wieder leer, und der Vorgang steht wieder bei „Genehmigung".
ctx.form.hinweis = "An die Buchhaltung gemeldet";
var antwort = http.get("http://localhost:8099/api/demo/http/status/503");
if (!antwort.ok) {
throw new Error("Die Buchhaltung ist gerade nicht erreichbar. Bitte später noch einmal versuchen.");
}
Das sieht der Bearbeiter. Die Meldung steht unter den Knöpfen. Oben ist weiter „Genehmigung" markiert, und im Verlauf steht bei „Genehmigung" keine Entscheidung — der Klick ist so, als wäre er nie passiert:

Am Ende der Meldung steht der Name des Skripts. So findest du schnell die Stelle, an der es hakt.
20. Der Vorgang soll trotzdem weitergehen¶
Knopf: Stufe 3 „Genehmigung" → Zustimmung → Aktion
Manchmal ist die Meldung nicht so wichtig. Dann soll ein Fehler den Vorgang
nicht aufhalten. Dafür gibt es try und catch: Versuche es. Wenn es nicht
klappt, mach stattdessen das hier.
try {
var antwort = http.get("http://localhost:8099/api/demo/http/status/503");
if (!antwort.ok) {
throw new Error("Status " + antwort.status);
}
} catch (fehler) {
log.warn("Statistik nicht erreichbar: " + fehler.message);
ctx.form.hinweis = "Meldung an die Statistik fehlt noch (" + fehler.message + ")";
}
21. Vorher nachfragen: Ist noch Budget da?¶
Knopf: Stufe 2 „Prüfung" → Zustimmung → Prüfung
Eine Prüfung kann auch ein anderes Programm fragen. Antwortet es mit „nein", bleibt der Vorgang stehen.
var antwort = http.post("http://localhost:8099/api/demo/http/echo", {
kostenstelle: $kostenstelle,
betrag: $betrag.num
}, { timeout: 10000 });
if (!antwort.ok) {
ctx.cancel("Das Budget kann gerade nicht geprüft werden. Bitte später noch einmal versuchen.");
return;
}
// Ein echtes Programm würde „frei: ja" oder „frei: nein" antworten.
// Die Übungs-Adresse schickt nur unsere Daten zurück. Deshalb rechnen
// wir die Antwort hier selbst aus: Über 1.000 Euro ist kein Budget da.
var daten = antwort.json().body;
var frei = daten.betrag <= 1000;
if (!frei) {
ctx.cancel("Auf der Kostenstelle " + daten.kostenstelle + " ist nicht genug Budget.");
return;
}
22. Den fertigen Antrag für das Archiv ablegen¶
Knopf: Stufe 99 „Abgeschlossen" → Beim Erreichen
Viele Archiv-Systeme (DMS) holen sich Dateien aus einem Ordner ab. Das Skript legt dort drei Dinge ab:
- den Antrag als PDF,
- alle Dateien, die am Antrag hängen,
- eine kleine Datei mit Stichworten. Daran erkennt das Archiv, worum es geht.
var ordner = fs["/beispiele/workflow/archiv/" + ctx.instanceId];
ordner.mkdir(true);
// 1. Der Antrag als PDF
ordner["/antrag.pdf"].writeBytes(pdf.render().bytes);
// 2. Alle Dateien, die am Antrag hängen
for (var i = 0; i < ctx.attachments.length; i++) {
var anlage = ctx.attachments[i];
ordner["/" + anlage.filename].writeAttachment(anlage);
}
// 3. Die Stichworte für das Archiv
ordner["/stichworte.json"].writeText(JSON.stringify({
vorgang: ctx.instanceId,
betreff: $betreff,
kostenstelle: $kostenstelle,
abgeschlossen: wf.now,
von: wf.actingLogin
}, null, 2));
log.info("Abgelegt: " + ordner.list().length + " Dateien in " + ordner.path);
Der Ordner liegt in der Datei-Ablage von KCForms. Mehr dazu: Dateien (fs).
23. Das PDF direkt in ein anderes Programm hochladen¶
Knopf: Stufe 99 „Abgeschlossen" → Beim Erreichen
Manche Archiv-Systeme nehmen Dateien über das Netz an. Das Skript legt das
PDF kurz ab und lädt es dann hoch. Die Übungs-Adresse …/upload antwortet
mit einer Liste der Teile, die angekommen sind.
var datei = fs["/beispiele/workflow/upload/antrag-" + ctx.instanceId + ".pdf"];
datei.writeBytes(pdf.render().bytes);
var antwort = http.post("http://localhost:8099/api/demo/http/upload", null, {
multipart: [
{ name: "vorgang", value: String(ctx.instanceId) },
{ name: "art", value: "Beschaffungsantrag" },
{ name: "datei", filePath: datei.path,
filename: "antrag.pdf", contentType: "application/pdf" }
]
});
if (!antwort.ok) {
throw new Error("Das Archiv hat die Datei nicht angenommen (" + antwort.status + ").");
}
var teile = antwort.json().parts;
log.info("Hochgeladen: " + teile[teile.length - 1].filename);
datei.remove(); // die Zwischendatei brauchen wir nicht mehr
24. Eine Liste für die Buchhaltung führen¶
Knopf: Stufe 99 „Abgeschlossen" → Beim Erreichen
Jeder abgeschlossene Antrag bekommt eine Zeile in einer Datei. Die Datei lässt sich mit Excel öffnen.
var liste = fs["/beispiele/workflow/buchhaltung/abgeschlossen.csv"];
var bisher = liste.exists ? liste.readText() : "Vorgang;Datum;Kostenstelle;Betrag;Betreff\n";
var zeile = ctx.instanceId + ";" + new Date().format("dd.MM.yyyy") + ";"
+ $kostenstelle + ";" + $betrag.num + ";" + $betreff;
liste.writeText(bisher + zeile + "\n");
log.info(zeile);
25. Die Adresse nicht ins Skript schreiben¶
Knopf: Stufe 3 „Genehmigung" → Zustimmung → Aktion
Ein Testsystem soll das Test-Programm aufrufen, das echte System das echte.
Deshalb steht die Adresse besser in den Properties: Administration →
Properties, Name uebung_antrag.buchhaltungUrl. Im Skript liest du sie
mit ctx.params.buchhaltungUrl.
Fehlt die Property, soll das Skript das klar sagen.
var adresse = ctx.params.buchhaltungUrl;
if (!adresse) {
throw new Error("Die Property buchhaltungUrl fehlt. Bitte den Administrator fragen.");
}
var antwort = http.post(adresse, { vorgang: ctx.instanceId });
if (!antwort.ok) {
throw new Error("Die Buchhaltung meldet einen Fehler (" + antwort.status + ").");
}
26. Alles zusammen, in der richtigen Reihenfolge¶
Knopf: Stufe 99 „Abgeschlossen" → Beim Erreichen
Dieses Skript macht vier Dinge. Achte auf die Reihenfolge: zuerst der Aufruf, der scheitern kann — zuletzt die Mail, die man nicht zurückholen kann.
// 1. Das andere Programm benachrichtigen — kann scheitern, steht deshalb vorn
var antwort = http.post("http://localhost:8099/api/demo/http/echo", {
vorgang: ctx.instanceId,
betrag: $betrag.num
}, { timeout: 15000, retries: 2 });
if (!antwort.ok) {
throw new Error("Die Buchhaltung meldet einen Fehler (" + antwort.status + ").");
}
// 2. Felder im Antrag setzen — KCForms speichert sie
ctx.form.belegnummer = "BH-" + antwort.json().body.vorgang;
ctx.form.hinweis = "Abgeschlossen und gemeldet";
// 3. Das PDF für das Archiv ablegen
var ordner = fs["/beispiele/workflow/archiv/" + ctx.instanceId];
ordner.mkdir(true);
ordner["/antrag.pdf"].writeBytes(pdf.render().bytes);
// 4. Zuletzt die Mail — die kann man nicht zurückholen
mail.send({
to: "einkauf@example.com",
subject: "Bitte bestellen: " + $betreff,
body: "Der Antrag ist genehmigt.\nBelegnummer: " + ctx.form.belegnummer
});
retries: 2 bedeutet: Wenn das andere Programm kurz nicht antwortet,
versucht KCForms es noch zweimal.
27. Ein Programm mit Anmeldung aufrufen¶
Knopf: Stufe 3 „Genehmigung" → Zustimmung → Aktion
Die meisten echten Programme verlangen eine Anmeldung. Kennwörter gehören nicht ins Skript. Der Administrator richtet dafür einen Konnektor ein: Administration → HTTP-/WebService-Konnektoren. Dort stehen Adresse und Anmeldung. Im Skript nennst du nur noch den Namen.
Dieses Beispiel läuft erst, wenn es einen Konnektor mit dem Namen sap gibt.
var sap = http.connect("sap");
var antwort = sap.post("/bestellungen", {
vorgang: ctx.instanceId,
betrag: $betrag.num
});
if (!antwort.ok) {
throw new Error("SAP meldet einen Fehler (" + antwort.status + "): " + antwort.text);
}
ctx.form.belegnummer = antwort.json().belegnummer;
Wenn etwas nicht klappt¶
Mein Skript läuft nicht. Sieh nach, ob der Punkt (●) am richtigen Knopf sitzt. Ein Skript am Übergang „2 → 3" läuft nicht beim Übergang „2 → 1".
Ich habe eine Stufe umnummeriert. Jetzt läuft das Skript nicht mehr. Das Skript gehört zur alten Nummer. Es steht noch im Reiter Skripte. Öffne den Knopf an der neuen Stufe und kopiere den Inhalt hinüber.
Der Vorgang springt immer wieder zurück. Ein Skript nach dem Wechsel scheitert. Die Meldung unter den Knöpfen nennt den Grund und den Namen des Skripts.
Ich sehe meine log.info-Zeilen nicht.
Sie stehen im Skript-Protokoll: Administration → System-Logs, Datei
script.log.
Eine Prüfung ändert ein Feld, aber es wird nicht gespeichert. Das ist richtig so. Eine Prüfung prüft nur. Felder ändert man in einer Aktion.
Welches Skript läuft zuerst? Bei einem Wechsel von A nach B in dieser Reihenfolge:
- Prüfung „Bei jedem Wechsel"
- Prüfung am Übergang A → B
- Der Vorgang wechselt die Stufe.
- Aktion „Bei jedem Wechsel"
- Aktion am Übergang A → B
- „Beim Erreichen" von B
- Die Benachrichtigung geht raus.
Aufräumen¶
Die Beispiele 22 bis 26 haben Dateien angelegt. Dieses Skript entfernt den Übungs-Ordner wieder. Du kannst es in der Skript-Konsole ausführen.
var ordner = fs["/beispiele/workflow"];
if (ordner.exists) {
ordner.remove(true);
}
log.info("Übungs-Ordner entfernt");
Mehr dazu¶
- Workflow-Workshop — den Workflow zusammenklicken, Mail-Schablonen, Sammelpostfächer
- Hooks und Reihenfolge
— alle Felder von
wfzum Nachschlagen - E-Mail, Internet (HTTP), Dateien (fs), PDF, ZIP und Word — mehr Beispiele zu den Werkzeugen