Einführung: System-Skriptsprache

Inhaltsverzeichnis

Die System-Skriptsprache wird u. a. im Workflow-Management verwendet, um beispielsweise eine Vorbedingung oder Übergangsbedingung zu formulieren oder um Bearbeiter zu ermitteln, die nicht in einer Workflowrolle zusammengefasst sind.

Die Workflow-Engine unterstützt sowohl die eigene System-Skriptsprache als auch JavaScript, um komplexe Zusammenhänge auszudrücken. Dieses Dokument behandelt nur die System-Skriptsprache. Es ist in folgende Kapitel aufgeteilt:

Die Einführung in die System-Skriptsprache ist auf mehrere Dokumente aufgeteilt. In diesem Dokument erhalten Sie ausführliche Informationen zum Aufbau und der Syntax der System-Skriptsprache. Für weitere Informationen zu den einzelnen Funktionen und Befehlen lesen Sie folgende Dokumentationen:

  • System-Skriptsprache: Allgemeine Funktionen
  • System-Skriptsprache: OLTP-Funktionen
  • System-Skriptsprache: Workflow-Funktionen

Informationen zu der Workflow-Engine erhalten Sie in der gleichnamigen Dokumentation Workflow-Engine. Informationen zur Verwendung der System-Skriptsprache in Workflow-Definitionen erhalten Sie in den Dokumentationen Aktivitätsdefinitionen und Prozessdefinitionen.

Darüber hinaus kann die System-Skriptsprache u. a. in den folgenden Anwendungen verwendet werden:

  • Individuelle Prüfungen
  • Individuelle Hook-Implementierungen

Weitere Informationen entnehmen Sie den jeweiligen Dokumentationen.

Zielgruppe

Die Zielgruppe dieses Dokuments besteht aus Entwicklern und technischen Beratern, die Workflows bei Kunden erstellen oder anpassen, sowie Kunden, die eigene Workflows verwalten.

Für dieses Dokument wird das Verständnis des für den Benutzer sichtbaren Funktionsumfangs des Workflow-Managements vorausgesetzt. Weiterhin sollte der Leser zum Verständnis der System-Skriptsprache grundlegende Kenntnisse in SQL oder einer beliebigen Programmiersprache haben.

Begriffsbestimmung

  • Aktivitätsdefinition – Aktivitätsdefinitionen legen fest, ob beim Auftreten eines bestimmten Ereignisses eine Aktivität erzeugt werden soll und welche Merkmale diese Aktivität haben soll. Eine Aktivitätsdefinition muss aktiviert sein. Wenn das der Fall ist, dann erzeugt die Workflow-Engine beim Auftreten des dort angegebenen Ereignisses eine neue Aktivität, sofern die Übergangs- und Vorbedingung erfüllt sind. Alle für die Aktivität notwendigen Daten werden aus der Aktivitätsdefinition berechnet. Die Aktivitätsdefinition stellt somit die Vorlage für die aus ihr erzeugten Aktivitäten dar. Aktivitätsdefinitionen sind unabhängig von der OLTP-Datenbank und dem System, in dem sie erfasst wurden, da sie weder System- noch OLTP-spezifische Daten enthalten. Aktivitätsdefinitionen werden in der Repository-Datenbank abgelegt.
  • Deklarationen – Deklarationen sind Skripte in den Prozessdefinitionen und Aktivitätsdefinitionen, die Methoden zur Verfügung stellen, welche beim Erzeugen von Aktivitäten, bei Statuswechseln und bei der Eingabe von bestimmten Parameterwerten aufgerufen werden. Durch Anpassung der Deklarationen lassen sich die Eigenschaften von Prozessen und Aktivitäten flexibel festlegen. Deklarationen werden in einer Skriptsprache erfasst.
  • GUID – GUID ist die Abkürzung für Globally Unique Identifier und entspricht einem Global eindeutigen Bezeichner. Eine GUID ist eine 128-Bit Zahl, die nach dem Schema der Open Software Foundation (OSF) für verteilte Berechnungen (Distributed Computing Environment, DCE) berechnet wurde. Sie enthält u. a. die IP-Adresse der erzeugenden Rechner, eine Zeit-Komponente und eine Zufalls-Komponente. So können zwei unabhängige Rechner ohne Synchonisation immer unterschiedliche GUIDs berechnen. In Comarch ERP Enterprise werden GUIDs als Java-Byte-Arrays der Länge 16 repräsentiert und vor allem als kompakte Primär- und Fremdschlüssel in Business Objects verwendet.
  • Hook Contract – Ein Hook ist eine Schnittstelle, mit der vorhandener Programmcode unabhängig von einem Release und damit konfliktfrei erweitert werden kann. Hooks werden beispielsweise verwendet, wenn in einer Adaptierung oder einer App für eine Business-Object-Erweiterung zusätzliche Prüfungen durchgeführt werden müssen, die die vorhandenen Prüfungen ergänzen.
  • Hook-Contract-Implementierung – In der Hook-Contract-Implementierung werden die zu implementierenden Hooks und die jeweilige Implementierungsklasse angegeben. Die Hook-Contract-Implementierung bezieht sich immer auf eine Hook-Contract-Definition, in der die implementierbaren Hooks enthalten sind.
  • Individuelle Prüfung – Bestimmte Business Entitys bieten Hook-Contracts für die Prüfung an, die mithilfe der System-Skriptsprache und ohne Zugang zu einem Entwicklungssystem implementiert werden können. Diese erweiterten Prüfungen werden in allen Ein- und Ausgabekanälen verwendet, also sowohl in den Dialog-Anwendungen als auch beim Import oder Export.
  • System-Skriptsprache – Terme, Bedingungen, Befehle und Deklarationen werden verwendet, um komplexe Zusammenhänge auszudrücken. Alle diese Ausdrücke sind Teil einer gemeinsamen Skriptsprache, die System-Skriptsprache genannt wird. Die Syntax der System-Skriptsprache lehnt sich an SQL, Pascal und Java an. Die System-Skriptsprache wird im Workflow-Management verwendet, um z. B. eine Vorbedingung oder Übergangsbedingung zu formulieren oder um Bearbeiter zu ermitteln, die nicht in einer Workflowrolle zusammengefasst sind.
  • Workflow-Engine –  Zusammen mit dem Ereignisdienst koordiniert und überwacht die Workflow-Engine die Ausführung von Workflows. Die Workflow-Engine wird in jedem System auf dem Message-Server ausgeführt.

Aufbau und Syntax

Terme, Bedingungen, Befehle, Funktionen und Deklarationen werden verwendet, um komplexe Zusammenhänge auszudrücken. Alle diese Ausdrücke sind Teil einer gemeinsamen Skriptsprache, die System-Skriptsprache genannt wird. Die Syntax der System-Skriptsprache lehnt sich an SQL, Pascal und Java an.

Da im Allgemeinen keine komplexen Algo­rith­men mit dieser Sprache ausgedrückt werden müssen, sollten Vorkenntnisse in SQL zum Erlernen der Sprache ausreichend sein.

Die System-Skriptsprache umfasst folgende Elemente:

Datentypen

Der Datentyp definiert gültige Wertebereiche und erlaubte Operationen. Die System-Skriptsprache kennt sowohl einfache als auch komplexe Datentypen. Beispiele von einfachen Datentypen sind Zeichenketten und Zahlen. Zu den komplexen Datentypen gehören z. B. Listen, Business Objects und Objektsichten.

Alle Datentypen in der System-Skriptsprache besitzen einen Standardwert (Default). Der Standardwert wird immer dann verwendet, wenn ein neuer, noch undefi­nier­ter Wert dieses Datentyps benötigt wird. Beim Parsen (Auswerten) eines Ausdrucks in der System-Skriptsprache werden die Verwendungen der Datentypen als Argumente von Funktionen, Befehlen und Operatoren über­prüft. Stimmt ein übergebener Wert nicht mit dem erwarteten Datentyp überein, wird eine Fehlermeldung ausgegeben.

Die System-Skriptsprache kennt die fol­genden Datentypen:

  • Boolean – Wahrheitswerte (Boolean) können nur die Werte truefür wahr und falsefür falsch annehmen. Der Standardwert des Datentyps Boolean ist false.
  • Bytes – Der Datentyp Bytessind binäre Daten mit beliebigem Inhalt. Dieser Daten­typ kann insbesondere bei programmierten Ereig­nissen und Dateien als Parameter verwendet werden. Der Stan­dardwert des Datentyps Bytes ist null.
  • Class – Eine Klasse (Class) ist ein strukturierter Datentyp mit einer Menge von Attributen. Jedes Attribut hat einen Namen und einen Datentyp. Der Standard­wert einer Klasse ist null.
  • CisDate – Ein CisDateist die Kombination eines Zeitpunkts mit einer Zeitzone. Der Stan­dardwert des Datentyps CisDateist null.
  • CisObjectReference – Business Objects werden mit den Datentypen CisObjectoder CisObjectReferenceverwaltet, Parts mit dem Datentyp CisObject. Referenzen auf Business Objects enthalten den Schlüssel des Business Objects. Der Standardwert des Datentyps CisObjectReferenceist null. Um eine typisierte CisObjectReferencezu erhalten, geben Sie den Namen eines Business Objects in Klammern an. Wenn Sie keinen Namen angeben, erhalten Sie eine untypisierte CisObjectReference.
    Hinweis
    Um Skripte performant auszuwerten und unnötige Datenbankzugriffe zu vermeiden, sind auch als CisObjectReferencedeklarierte Variablen nur als Werte verfügbar, wie beim Datentyp CisObject. Möchten Sie den aktuellen Wert eines Business Object auswerten, dann sollten Sie es erneut öffnen, z. B. mithilfe der Funktionen getByPrimaryKeyoder getByBusinessKey.
  • CisObject – Business Objects werden mit den Datentypen CisObjectoder CisObjectReferenceverwaltet, Parts mit dem Datentyp CisObject. Business Objects und ihre Parts sind auch als Werte ver­fügbar. Der Standardwert des Datentyps CisObjectist null. Um ein typisiertes CisObjectzu erhalten, geben Sie den Namen eines Business Objects in Klammern an. Wenn Sie keinen Namen angeben, erhalten Sie ein untypisiertes CisObject.
  • DataView – Objektsichten (DataView) sind eine Sicht auf den Zustand eines komplexen Business Entitys. Objektsichten werden insbesondere in individuellen Prüfungen verwendet. Der Standardwert des Datentyps DataViewist null. Um eine typisierte DataViewzu erhalten, geben Sie den Namen einer Objektsicht in Klammern an. Wenn Sie keinen Namen angeben, erhalten Sie eine untypisierte DataView.
  • Guid – GUIDs werden häufig benötigt, um Business Objects über dessen Primärschlüssel zu identifizieren. Der Standardwert des Datentyps Guidist null.
  • HashMap – Eine Hash-Tabelle (HashMap) speichert Schlüssel-Wert-Paare. Jedem Schlüssel kann genau ein Wert zugeordnet werden. Mithilfe des Schlüssels kann der Wert immer wieder gefunden werden. Als Schlüs­sel sind nur Zeichenketten erlaubt. Der Stan­dardwert des Datentyps HashMapist eine leere Hash-Tabelle.
  • Number – Zahlen (Number) enthalten immer ein Vorzeichen. Sie können Nachkommastellen haben, die mit ei­nem Punkt zu trennen sind. Der Standardwert des Datentyps Numberist 0.
  • String – Zeichenketten (String) können eine beliebige Län­ge haben. Der Standardwert des Datentyps Stringist eine leere Zeichenkette.
  • Timestamp – Ein Zeitpunkt (Timestamp) ist ein auf Millisekun­den genauer Punkt in der Zeit. Alle Zeitangaben werden in Zeitpunkten abgebildet. Der Standardwert des Datentyps Timestampist die Konstante UNDEFINED_DATE.
  • Unknown – Dem Datentyp Unknownkann jeder beliebige andere Datentyp zugeordnet werden. Der Standardwert des Daten­typs Unknownist null.
Automatische Umwandlung von einfachen Datentypen

Einige einfache Datentypen wie Number, Booleanund Guidwerden bei Bedarf automa­tisch in Zeichenketten umgewandelt.

Beispiel
Wenn eine Funktion einen Parameter vom Typ Stringerwartet und ein Wert vom Typ Numberüber­ge­ben wird, so wird die Zahl in eine Zeichenkette umgewandelt.

Beachten Sie bitte, dass der Datentyp vom ersten Term eines Ausdrucks bestimmt wird.

Beispiel
Bei folgender Zuweisung wird die Zahl 40 automatisch in die Zeichenkette „40“ umgewandelt:

var t := "UB" + 40;

Beispiel
Folgende Zuweisung ergibt einen Fehler, da die Zeichenkette „ers“ nicht in eine Zahl umgewandelt werden kann:

var t := 101 + "ers";

Weitere Datentypen können mithilfe der Funktion castumgewandelt werden. Weitere Informationen und Beispiele finden Sie in der Dokumentation System-Skriptsprache: Allgemeine Funktionen.

Prüfungen bei typisierten CisObject und CisObjectReference

Wenn Ihnen der Typ des Business Objects oder Parts bekannt ist, sollten Sie immer ein typisiertes CisObjectbzw. CisObjectReferenceverwenden. Nur bei einer Typisierung wird die korrekte Verwendung von Attributen und deren Datentypen geprüft.

Beispiel
CisObject (com.cisag.app.general.obj.Partner) ist ein Business Object vom Typ Partner.

CisObject (com.cisag.app.general.obj.DomesticAmount) ist ein Part vom Typ Hauswährung.

Bei einem untypisierten CisObjectbzw. CisObjectReferencewird weder geprüft, ob der Attributname auch tatsächlich an dem Objekt definiert ist, noch wird geprüft, ob das Attribut tatsächlich den angeforderten Datentyp hat.

Listen

Eine Liste ist eine geordnete Folge von Werten. Eine Liste besitzt einen Ele­ment­datentyp und optional eine Länge. Alle Listenelemente müssen in diesen Elementdatentyp umwandelbar sein. Wenn der Datentyp einer Liste eine Länge besitzt, so ist diese Länge festgelegt und kann nicht nachträglich verändert werden.

Der Datentyp Liste wird durch die Angabe eines Elementdatentyps, gefolgt von eckigen Klammern, ausgedrückt. In den eckigen Klammern steht optional die feste Länge der Liste.

Beispiel
String[10]ist eine Liste von Zeichenketten mit 10 Elementen.

Number[] ist eine Liste von Zahlen mit unbestimmt vielen Elementen.

Unknown[] ist eine Liste mit beliebigen Objekten mit unbestimmt vielen Elementen.

Der Standardwert einer Liste mit vorgegebener Länge ist eine Liste dieser Länge. Wenn die Liste keine Länge hat, so ist der Standardwert eine leere Liste. Eine leere Liste kann mithilfe der Skript-Funktion isEmptygeprüft werden.

Beispiel
isEmpty(new(String[]))gibt den Wahrheitswert truezurück.

Die Skript-Funktion listerzeugt eine neue Liste mit Elementen. Der Datentyp des ersten Elements bestimmt dabei den Datentyp der Liste. Wird kein Element angegeben, dann gibt list eine leere Liste vom Datentyp Unknown[]zurück.

Beispiel
list("UB", 40)erzeugt eine Liste vom Datentyp String[]mit zwei Elementen von Datentyp String.

list(101, "ers") ist keine gültige Liste, da die Zeichenkette „ers“ nicht in den Elementdatentyp Numberumgewandelt werden kann.

list()erzeugt eine neue leere Liste vom Datentyp Unknown[].

Ein Element kann nur dann einer vorhandenen Liste hinzugefügt werden, wenn der Datentyp des Elements mit dem Datentyp der Liste übereinstimmt oder in diesen umgewandelt werden kann.

Beispiel
Der Aufruf der Funktion addführt zu einem Fehler, da eine Zeichenkette nicht in eine Zahl umgewandelt werden kann.

var list1 := Number[];
add(list1, "500");

Ist die Liste dagegen als String[]deklariert, dann ist der Ausdruck add(list1, 500)syntaktisch korrekt, da eine Zahl in eine Zeichenkette umgewandelt werden kann.

Wenn Sie einer Liste Elemente unterschiedlicher Datentypen zuweisen (z. B. als Parameterliste für den Aufruf einer Hintergrundanwendung), dann sollten Sie das erste Element so wählen, dass die weiteren Elemente in den Datentyp des ersten Elements umgewandelt werden können. Beispielweise können Zahlen in Zeichenketten umgewandelt werden, aber nicht umgekehrt. Ist das nicht möglich, dann können Sie eine Liste vom Datentyp Unknown[]deklarieren und mithilfe der Funktion addElemente unterschiedlicher Datentypen zuweisen. Einer Liste, die den Datentypen Unknown[]besitzt, können Elemente beliebiger Datentypen hinzugefügt werden, da alle anderen Datentypen in Unknownumgewandelt werden können.

Somit lässt sich z. B. eine Parameterliste auch dann für die Funktionen getCisObjectListund getResultListerzeugen, wenn die OQL-Abfrage Parameter unterschiedlicher Datentypen besitzt, die nicht automatisch (in den Datentyp des ersten Parameters) umgewandelt werden können. Das folgende Beispiel erzeugt eine Parameterliste, um mithilfe der Funktion getCisObjectListdie ersten 100 internen Personen zu ermitteln und auf der Konsole auszugeben:

const PartnerType as valueSet(com.cisag.app.general.PartnerType);
function create()
{
var params as Unknown[];
var OQL :=
"SELECT FROM com.cisag.app.general.obj.Partner p" +
" WHERE p:type = ? AND p:human = ?" +
" ORDER BY p:number";

add(params, PartnerType.INTERNAL);
add(params, true);

var pList := getCisObjectList(OQL, params, BlockSize);

for (p as CisObject(com.cisag.app.general.obj.Partner) : pList)
echo(p:number);
}

Besitzt eine Liste Elemente unterschiedlicher Datentypen, dann müssen die Elemente mithilfe der Funktion castggf. typisiert werden, bevor sie verwendet werden können, wie das folgende Beispiel zeigt.

var myList as Unknown[];
add(myList, 800);
add(myList, "°");
var song := cast(String, myList[0]) + cast(String, myList[1]);

Die System-Skriptsprache umfasst viele Funktionen, um Listen zu erzeugen und zu bearbeiten. Weitere Informationen und Beispiele finden Sie im Kapitel Listenfunktionen der Dokumentation System-Skriptsprache: Allgemeine Funktionen.

Der Wert null

Zusätzlich zu den Werten der Datentypen existiert der Wert null. Der Wert null ist keinem Datentyp zugeordnet. Wenn ein Wert nullist, so ist dieser Wert undefiniert. Viele Funktionen und Operatoren in der System-Skriptsprache liefern als Ergebnis null, wenn einer der Parameter nullist. Wenn also auf Basis eines undefinierten Wer­tes etwas berechnet werden soll, so ist auch das Ergebnis undefiniert. Mit den spe­ziellen Funktionen isNullund firstkann ein Wert nullgesondert behandelt werden.

Eine Übergangsbedingung in einer Aktivitätsdefinition gilt beim Wert nullals nicht erfüllt (false). Eine Vorbedingung dagegen gilt beim Wert null als erfüllt (true). Prüfen Sie daher besonders optionale Attribute mit Fremdschlüsseln auf den Wert null.

Beispiel
Eine Workflow-Aktivität soll erzeugt werden, wenn ein Vertriebsauftrag freigegeben wird und der Vertriebsauftrag nicht vom zuständigen Mitarbeiter freigegeben wurde.

Die Übergangsbedingung not(contains(resolvePartner(parameters.object:responsible), parameters.userGuid))besitzt den undefinerten Wert null, wenn kein zuständiger Mitarbeiter im Vertriebsauftrag hinterlegt ist. Daher wird in diesem Fall keine Aktivität erzeugt.

Die Übergangsbedingungen isNull(parameters.object:responsible) or not(contains(resolvePartner(parameters.object:responsible),parameters.userGuid))und

not(contains(resolvePartner(cast(Guid, first(parameters.object:responsible, ZERO_GUID))

, parameters.userGuid))besitzen auch dann einen gültigen Wert, wenn kein zuständiger Mitarbeiter im Vertriebsauftrag hinterlegt ist.

Auch ein Ausdruck, der eine Beziehung über ein Attribut mit dem Wert null verfolgt, führt zu einem undefinierten Ergebnis.

Beispiel
parameters.object->Responsible:numberbesitzt den undefinerten Wert null, wenn im dem von parameters.objectreferenzierten Business Object kein zuständiger Mitarbeiter hinterlegt ist.

Die System-Skriptsprache umfasst zwei Funktionen isNullund first, um Null-Werte zu behandeln. Weitere Informationen und Beispiele finden Sie im Kapitel Listenfunktionen der Dokumentation System-Skriptsprache: Allgemeine Funktionen.

Feste Konstanten

Eine Konstante kann nur einen einzigen vorbestimmten Wert annehmen. Konstanten werden u. a. dazu verwendet, um die Verwendung der System-Skriptsprache verständlicher und kompakter zu machen. Folgende Konstanten sind fest definiert und immer verfügbar:

  • INVALID_GUID – Die INVALID_GUIDstellt einen ungültigen Wert für den Datentyp Guiddar.
  • MAX_DATE – Der größte darstellbare Zeitpunkt (Timestamp). Das MAX_DATEkann z. B. für Gültigkeitsbereiche verwendet werden, die nach oben offen sind. MAX_DATE entspricht dem konstanten MAX_TIME_STAMPeiner OQL-Abfrage.
  • MIN_DATE – Der kleinste darstellbare Zeitpunkt (Timestamp). Das MIN_DATEkann z. B. für Gültigkeitsbereiche verwendet werden, die nach unten offen sind. MIN_DATEentspricht dem konstanten MIN_TIME_STAMPeiner OQL-Abfrage.
  • UNDEFINED_DATE – Ein undefinierter Zeitpunkt (Timestamp). Das UNDEFINED_DATEwird z. B. für Zeitpunkte verwendet, bevor ein konkreter Wert zugewiesen wurde. Zum Beispiel der Zeitpunkt der letzten Änderung eines Business Objects (im Attribut updateInfo.updateTime), welches seit dem Erfassen nicht mehr geändert wurde. UNDEFINED_DATEentspricht dem konstanten UNDEFINED_TIME_STAMPeiner OQL-Abfrage.
  • ZERO_GUID – Die ZERO-GUIDwird immer dann verwendet, wenn eine GUID nicht null sein darf, aber dennoch undefiniert ist. Dies ist in z. B. dann der Fall, wenn die GUID Bestandteil eines Primärschlüssels ist. ZERO_GUIDentspricht dem Konstanten ZEROGUIDeiner OQL-Abfrage.
Hinweis
Um zu überprüfen, ob ein Wert vom Datentyp CisDateden kleinsten bzw. den größten darstellbaren Wert besitzt, können Sie die Funktionen isMinDateund isMaxDateverwenden.

Kommentare

Kommentare werden mit /*eingeleitet und mit */abgeschlossen. Kom­mentare können mehrere Zeilen umfassen.

Bei komplexeren Workflow-Prozessen ist es ratsam, ausreichend Kommentare in den Aktivitätsdefinitionen zu erfassen, um die Anpassung und Pflege zu erleichtern. Folgender beispielhafter Kommentar aus einer Prozessdefinition beschreibt den Prozess.

/**
* This process exports changes to the Partner object every 15
* minutes. The process ends automaticallly when the processing
* duration has been exceeded.
*
* Start: Manual process without event definition
*
* Owner: If the process owner is not defined in the process
* definition then the start node automatically sets the owner to
* the initiator (user who triggered the event) so that he or she
* can display the process and be notified in case of errors.
* Number1: Total number of export runs
* Number2: Total number of Partners exported
* Timestamp1: Begin time of Partner query of the last export run
* Timestamp2: End time of Partner query of the last export run
*/

Es ist auch ratsam, globale Konstanten in Prozessdefinitionen zu deklarieren und zu kommentieren, um die Konfiguration von Workflow-Prozessen zu vereinfachen.

/**
* JOB_QUEUE is the name of the job queue for the batch job.
* If no job queue is specified in this constant then the default
* job queue from the Customizing function 'Workflow Management'
* is used.
*/
const JOB_QUEUE := "";

Ein leerer Ausdruck in einem Bedingungsfeld gilt als erfüllt (true). Da eine Bedingung, die aus nur einem Kommentar besteht, nicht leer ist, gilt folgende Übergangsbedingung als nicht erfüllt (false), auch wenn sie keinen auswertbaren Ausdruck enthält, und erzeugt somit keine Aktivität.

/* parameters.object:status = OrderStatus.RELEASED */

Wenn Sie z. B. im Ramen einer Fehlersuche erreichen möchten, dass eine Aktivität unabhängig von der Übergangsbedingung immer erzeugt wird, aber die Übergangsbedingung nicht löschen möchten, dann können Sie stattdessen die Übergangsbedingung auskommentieren und durch den Wert trueersetzen.

true /* parameters.object:status = OrderStatus.RELEASED */

Terme und Bedingungen

Ein Term ist ein Ausdruck oder eine Formel, die einen Wert berechnet.

Beispiele von Termen:

a * a + b * b
max(a, b) * min(c, d)

Eine Bedingung ist ein Ausdruck, der einen Wahrheitswert zurückgibt und somit eine Ja/Nein-Entscheidung ermöglicht.

Beispiele von Bedingungen:

a * a + b * b = c * c
max(a, b) > 0
parameters.object:updateInfo.createUser <> parameters.userGuid

Die Syntax der Terme und Bedingungen ist ähnlich der in SQL. Wenn einer der Operanden nicht dem erwarteten Datentyp entspricht, so ist das Ergebnis der Operation null. Ist einer der Operanden null, so ist das Ergebnis der Operation ebenfalls null.

Arithmetische Operatoren

Für Zahlen sind die folgenden Operatoren definiert:

Operator Beschreibung
a * b Multiplikation der Zahlen a und b.
a / b Division der Zahl a durch die Zahl b.
a % b Rest der ganzzahligen Division der Zahl a durch die Zahl b.
a + b Addition der Zahlen a und b.
a – b Subtraktion der Zahl b von der Zahl a.

Arithmetische Operatoren, auch unterschiedlicher Art, können beliebig kombi­niert werden. Wie üblich haben dabei die Operatoren *,/und %eine höhe­re Bindung als die Operatoren +und -. Operatoren mit gleicher Bin­dung werden von links nach rechts ausgeführt.

Beispiel
1 + 3und 3 * 4 - 8sind gültige Terme mit diesen Operatoren und liefern beide das Ergebnis 4zurück.

1 * "a" liefert nullzurück.

Die System-Skriptsprache umfasst auch viele arithmetische Funktionen. Weitere Informationen und Beispiele finden Sie im Kapitel Arithmetische Funktionen der Dokumentation System-Skriptsprache: Allgemeine Funktionen.

Operatoren auf Zeichenketten

Für Zeichenketten sind die folgenden Operatoren definiert:

Operator Erläuterung
a + b Verknüpfung der Strings a und b.

Beliebig viele Strings können zu einem Term verknüpft werden.

Beispiel
"Hello" + " " + "world"ist ein gültiger Term mit diesem Operator.

Die System-Skriptsprache umfasst auch viele Funktionen für Zeichenketten. Weitere Informationen und Beispiele finden Sie im Kapitel Funktionen für Zeichenketten der Dokumentation System-Skriptsprache: Allgemeine Funktionen.

Vergleichsoperatoren

Vergleichsoperatoren (Komparatoren) sind:

Operator Erläuterung
a = b Vergleicht, ob die Werte der Terme a und b gleich sind.
a < b Vergleicht, ob der Wert des Terms a kleiner als der Wert des Terms b ist.
a <= b Vergleicht, ob der Wert des Terms a kleiner gleich dem Wert des Terms b ist.
a > b Vergleicht, ob der Wert des Terms a größer als der Wert des Terms b ist.
a >= b Vergleicht, ob der Wert des Terms a größer gleich dem Wert des Terms b ist.
a <> b Vergleicht, ob die Werte der Terme a und b ungleich sind. Alle Datentypen können mit <> verglichen werden.

Alle Datentypen können mit den Operatoren =und <>verglichen werden. Bei Business Objects werden dabei die vollständigen Inhalte verglichen. Ein Vergleich mit den anderen Operatoren ist nur für die Datentypen Number, String, CisDate, Timestampund Booleanmöglich.

Die linke Seite einer Vergleichsoperation bestimmt den verglichenen Datentyp.

Beispiel
3 <= 1 + 2ist eine wahre Bedingung.

"a" < "b" ist eine wahre Bedingung.

"a" > 1 ist eine wahre Bedingung, da die Zahl 1 in eine Zeichenkette umgewandelt werden kann.

1 > "a" liefert null zurück, da die Zeichenkette „a“ nicht in eine Zahl umgewandelt werden kann.

Das Ergebnis einer Vergleichsoperation ist vom Datentyp Wahrheitswert.

Beispiel
(1 = 3) = falseist eine wahre Bedingung.

today() < addDays(today(), 1) ist eine wahre Bedingung.

true = false ist eine falsche Bedingung.

Werden zwei CisDates mit einander verglichen, dann wird die Zeitzone mit berücksichtigt.

Beispiel
createCisDate

("CET", 2020, 1, 1, 0,0,0,0) < createCisDate("NST", 2019, 12, 31, 23,0,0,0)

ist eine wahre Bedingung, da sich die Zeitzone NST mehr als eine Stunde nach der Zeitzone CET. befindet.

Um ein CisDate mit einem Zeitpunkt zu vergleichen, können Sie mithilfe der Skript-Funktion toTimestampdas CisDate in einen Zeitpunkt umwandeln.

Beispiel
toTimestamp(today()) <= now()ist eine wahre Bedingung.
Bedingungen

Bedingungen können beliebig mit den logischen Operatoren ANDund ORverknüpft werden:

Operator Erläuterung
a AND b AND ist eine Und-Verknüpfung von zwei Bedingungen. Das Ergebnis ist wahr, wenn sowohl die Bedingung a als auch die Bedingung b wahr sind.
a OR b OR ist eine Oder-Verknüpfung von zwei Bedingungen. Das Ergebnis ist wahr, wenn entweder die Bedingung a oder die Bedingung b oder a und b wahr sind.
NOT a NOT ist eine Negierung einer Bedingung. Das Ergebnis ist wahr, wenn die Bedingung a falsch ist, und falsch, wenn die Bedingung a wahr ist.

Die Operatoren ANDund ORkönnen beliebig kombiniert werden. Wie üblich be­sitzt dabei der Operator ANDeine höhere Bindung als der Operator OR.

Beispiel
1 = 1 AND 3 = 3ist eine wahre Bedingung.

1 = 1 OR 2 = 2 AND 3 = 4 ist eine wahre Bedingung.

1 = 0 OR 2 = 2 AND 3 = 4ist falsche Bedingung.

Hinweis
Bei den logischen Operatoren können Sie sowohl Groß- als auch Kleinschreibung verwenden. D. h. a AND bund a und bsind syntaktisch identische und gültige Bedingungen.
Klammerung

Terme und Bedingung können beliebig geklammert werden:

Operator Erläuterung
(a) Klammerungen von Termen und Bedingungen.

Ein geklammerter Term wird immer als Einheit ausgeführt, unabhängig von den Unterschieden der Bindungen der Operatoren.

Beispiel
(2 + 3) * 2 = 10ist eine wahre Bedingung.

(2 * (7 - 6) + 1) = 3 ist eine wahre Bedingung.

(1 = 1 OR 3 < 1) AND 2 = 2 ist eine wahre Bedingung.

Zugriff auf Listen und Hash-Tabellen

Für den Zugriff auf Listen und Hash-Tabellen existieren die folgenden Operato­ren:

Operator Erläuterung
b[a] Zugriff auf das Element mit dem Index a der Liste b, beginnend beim Index 0. Der Index a muss eine Zahl sein. Ist a keine Ganzzahl, so wird nur der ganzzahlige Anteil berücksichtigt. Liegt der In­dex außerhalb des gültigen Bereiches für die Liste, so ist das Ergebnis null.
b.a Zugriff auf den Wert mit dem Schlüssel a in der Hash-Tabelle b. Wenn zu dem Schlüssel kein Wert existiert, so ist das Ergebnis null.
b[“a”] Zugriff auf den Wert mit dem Schlüssel a in der Hash-Tabelle b. Wenn zu dem Schlüssel kein Wert existiert, so ist das Ergebnis null.

Beide Arten des Zugriffs auf Hash-Tabellen sind äquivalent. Der Zugriff mit Punkt (b.a) ist kompakter und eignet sich insbesondere dann, wenn die Einträge der Hash-Ta­belle zu dem Zeitpunkt, zu dem der Ausdruck geschrieben wird, bekannt sind. Wenn die Einträge sich dynamisch während der Laufzeit berechnen, so ist der Zugriff mit eckigen Klammern (b["a"]) sinnvoller.

Beispiel
h sei eine Hash-Tabelle mit den folgenden Einträgen (Schlüssel, Wert):

h = {("a" ,1), ("x1", 11), ("x2", 12) , ("x3", 13)}

h.a = 1 ist eine wahre Bedingung.

h["a"] = 1 ist eine wahre Bedingung.

h["x" + (3 - 2)] = 11 ist eine wahre Bedingung.

h.x = 1 liefert den Wert nullzurück.

Beispiel
l sei eine Liste mit den folgenden Einträgen:

l = {"a", "b", "c"}

l[0] = "a" ist eine wahre Bedingung.

l[2] = "c"ist eine wahre Bedingung.

l[2 * 3] = "a"liefert den Wert nullzurück.

Zugriff auf Business Objects, Parts und Objektsichten

Für Business Objects und Parts sind die folgenden Operatoren verfügbar:

Operator Erläuterung
o:a Zugriff auf das Attribut a des Business Objects, Parts oder der Objektsicht o. Wenn das Attribut a in dem Objekt o nicht existiert oder einen nicht unterstützten Datentyp enthält, so ist das Er­gebnis null.

Das Attribut a kann ein komplexer Zugriffspfad auf die Attribute von den in das Objekt o eingebetteten Parts und Feldern sein.

o->R Zugriff auf die 1:1-Beziehung R eines Business Objects, Parts oder der Objektsicht o. Wenn die Beziehung nicht existiert oder auf kein Objekt zeigt, so ist das Ergebnis null. Das Ergebnis des Zugriffs auf eine Beziehung ist ein Business Object als Wert.

Der Zugriff auf Business Objects, Parts und Objektsichten wird häufig benötigt, da diese Objekte die wichtigsten Datencontainer im System sind.

Beispiel
loadPartner("10010"):address.cityist ein gültiger Zugriff auf das Attribut cityin dem komplexen Attribut addressdes Business Objects Partner mit der Identifikation 10010.

loadPartner("10010"):organizationalUnit.name[1] ist ein gültiger Zugriff auf das Feld mit dem Index 1 in dem Feld-Attribut namein dem komplexen Attribut organizationalUnitdes Business Objects Partner mit der Identifikation 10010.

loadPartner("10010")->Language:isoCode ist ein gültiger Zugriff auf das Attribut isoCodedesjenigen Business Objects, das durch die Beziehung Languagevon dem Business Object Partner mit der Identifikation 10010 referenziert wird.

Um Attribute, deren Namen mit einem Unterstrich beginnen, auszuwerten, können Sie die Funktion getAttributeverwenden. Bevor Sie das Ergebnis verwenden, sollten Sie es in einen zum Attribut passenden Datentyp umwandeln.

Beispiel
loadCurrency(getCorporateCurrency(cast(Guid, getAttribute(parameters.object, "_organization")))):isoCodegibt den ISO-Code der Leitwährung der Organization zurück, in dessen Kontext das vom parameters.objectreferenzierte Business Object erfasst wurde.
Aktivitätsdefinitionen aufrufen

Sie können Aktivitätsdefinitionen mit der Kategorie Funktionsaufruf wie Funktionen aufrufen. Der Name der Aktivitätsdefinition darf für den Aufruf nur Buchstaben, Zahlen und die Sonderzeichen Punkt (.), Unterstrich (_), Dollarzeichen ($) oder Raute (#) enthalten. Falls der Name andere Zeichen enthält, muss die Aktivitätsdefinition mit der Funktion callaufgerufen werden. Siehe auch Kapitel Sonstige Funktionen der Dokumentation System-Skriptsprache: Allgemeine Funktionen.

Um den Aufruf einer Aktivitätsdefinition von einem Funktionsaufruf zu unterscheiden, wird dem Namen der Aktivitätsdefinition das At-Zeichen (@) vorangestellt. Bei dem Aufruf muss jedem Parameter der Aktivitätsdefinition ein Wert zugeordnet werden. Die Parameter werden alphabetisch sortiert. Die Rückgabewerte der Aktivitätsdefinition werden als Klasse zurückgegeben. Die einzelnen Rückgabewerte sind Attribute dieser Klasse.

Beispiel
Die Aktivitätsdefinition isPythagoreanbesitzt die Parameter A, B und C vom Typ Number sowie den Rückgabewert RESULTvom Typ Boolean. Die Aktivitätsdefinition wird wie folgt aufgerufen:

var result := @isPythagoreanTheorem(A:=3, B:=4, C:=5).RESULT;

Die maximale Rekursionstiefe ist beschränkt. Weitere Informationen finden Sie in dem Kapitel Komplexität von Ausdrücken beschränken.

Befehle

Ein Befehl ist ein Ausdruck, der eine Operation ausführt, die kein Ergebnis lie­fert. In der System-Skriptsprache werden Befehle durch ein Strichkomma (;) getrennt.

Beispiel

echo(definition:code);
setMailRecipientsTo("somebody@localhost.local");

Abhängig vom Verwendungskontext können unterschiedliche Befehle definiert sein. In den folgenden Abschnitten werden die Befehle gruppiert nach den Verwendungskontexten beschrieben.

Hinweis
Auch wenn ein Befehl keinen Rückgabewert besitzt, werden Sie in den Dokumentationen System-Skriptsprache: Allgemeine Funktionen, System-Skriptsprache: OLTP-Funktionen und System-Skriptsprache: Workflow-Funktionen zusammen mit den Funktionen beschrieben.
Kontrollfluss und Variablenzuweisung

Die Befehle zum Steuern des Kontrollflusses und die Variablenzuweisung sind in die System-Skriptsprache fest eingebaut.

Beschreibung Syntax
Variablendeklaration (Typ) var <VariableName> as <Type>
Variablendeklaration (Term) var <VariableName> := <Expression>
Konstantendeklaration const <VariableName> := <Expression>
Value-Set-Deklaration const <VariableName> as valueSet(<Name>)
Typdefinition type <TypeName> as <Type>
Typdefinition (class)
type <TypeName> as class {
<AttributeName> as <Type>;
...
<AttributeName> as <Type>;
}
Zuweisung <VariableName> := <Expression>
Bedingter Befehl if (<Condition>) <Command>
Bedingter Befehl mit Alternative if (<Condition>) <Command> else <Command>
Schleife mit Bedingung while (<Condition>) <Command>
Schleife über alle Elemente for (<VariableName> : <List>) <Command>
Schleife über alle Elemente mit Typisierung
for (<VariableName> as <Type> : <List>)
<Command>
Befehl beenden return
Funktion beenden return <Expression>
Anweisungsblock
{
<Command>
...
<Command>
}

Die System-Skriptsprache umfasst auch die Funktion if, um den Kontrollfluss innerhalb eines Ausdrucks zu bestimmen. Weitere Informationen und Beispiele finden Sie im Kapitel Sonstige Funktionen der Dokumentation System-Skriptsprache: Allgemeine Funktionen.

Konstanten

Eine Konstante kann nur einen einzigen vorbestimmten Wert annehmen. Konstanten werden u. a. dazu verwendet, um die Verwendung der System-Skriptsprache verständlicher und kompakter zu machen.

Konstanten werden wie Variablen mit einem Term deklariert. Im Unterschied zu Variablen kann der Wert einer Konstante nach deren Deklaration nicht mehr verändert werden.

Bei komplexeren Workflow-Prozessen ist es ratsam, globale Konstanten in der Prozessdefinition zu deklarieren, mit denen der Workflow-Prozess zentral konfigurieren lässt, damit die Aktivitätsdefinitionen der einzelnen Prozessschritte möglichst nicht angepasst werden müssen.

Beispiel

/**
* JOB_QUEUE is the name of the job queue for the batch job.
* If no job queue is specified in this constant then the
* default job queue from the Customizing function 'Workflow
* Management' is used.
*/
const JOB_QUEUE := "";

Hinweis
Wenn Sie Prozessdefinitionen in JavaScript erfassen, dann können Sie globale Konstanten in der Prozessdefinition als Variablen deklarieren, falls die verwendete Script-Engine die Deklaration von Konstanten nicht erlaubt.
Variablen

Alle verwendeten Variablen und Konstanten müssen deklariert werden. Varia­blen können mit einem Typ oder einem Initialwert deklariert werden. Wenn ein Typ angegeben wird, so besitzt die Variable den Standardwert des Typs als Ini­tialwert. Wenn eine Variable über einen Term deklariert wird, so hat diese den Ergebniswert des Terms als Wert und dessen Datentypen als Datentyp.

Beispiel
Nach der Deklaration der Variablen n besitzt n den Standardwert 0 für Zahlen:

var n as Number;

Nach der Deklaration von m besitzt m den numerischen Wert 6:

var m := 1 + 5;

Um Konstanten von Variablen besser unterscheiden zu können, wird empfohlen, Konstanten, die in Prozessdefinitionen definiert sind, durchgehend mit Großbuchstaben zu deklarieren, Konstanten, die in Aktivitätsdefinitionen definiert sind, mit einem Großbuchstaben und Variablen mit einem Kleinbuchstaben anfangen zu lassen.

ValueSets

Um ein Valueset zu verwenden, müssen Sie dieses mit der Anweisung const <VariableName> as valueSet(<Name>)deklarieren, um später auf dessen Einträge zugreifen zu können. Die Deklaration erzeugt eine Variable vom Typ Classund darin für jeden Valueset-Eintrag eine Konstante mit dem technischen Namen des Eintrags und dessen ID.

Beispiel
Ist ein von parameters.objectreferenzierter Vertriebsauftrag freigegeben, dann wird die Zeichenkette RELEASED ins Protokoll ausgegeben:

const OrderStatus as valueSet(com.cisag.app.general.OrderStatus);
function create()
{
if (parameters.object:status = OrderStatus.RELEASED)
echo(valueSetName(OrderStatus, parameters.object:status);
}

Typdefinitionen

Zur Vereinfachung können Sie in der System-Skriptsprache eigene Datentypen deklarieren und verwenden. Die Ver­wendung von Typen erleichtert durch die besseren Abstraktionsmöglichkei­ten das Verständnis des Programms. Für jede Verwendung von Klassen muss ein Typ definiert werden. Das Schlüsselwort classkann nur bei einer Typdekla­ration verwendet werden.

Beispiel
Definition und Verwendung unterschiedlicher Datentypen:

type PartnerCode as String;
type PartnerCodeList as PartnerCode[];
type WeekdaySum as Number[7];

var code as PartnerCode;
code := "4711";

Definition und Verwendung einer Klasse:

type Bike as class {
name   as String;
weight as Number;
chainset as String;
}

var myBike := new(Bike);
myBike.name := "Niner RLT";
myBike.weight := 9250;
myBike.chainset := "Shimano 105";

Hinweis
Typdefinitionen sind nur in Aktivitätsdefinitionen möglich. In den Deklarationen einer Prozessdefinition sind sie nicht zulässig.
Zuweisungen

Bei der Zuweisung kann einer Variablen, einem Attribut einer Klasse, einem Eintrag in einer Liste oder einer Hash-Tabelle ein Wert zugewiesen werden. Das Element, wlechem etwas zugewiesen wird, steht auf der linken Seite der Zuwei­sung. Der zugewiesene Wert wird aus dem Term auf der rechten Seite der Zuweisung berechnet.

Jede verwendete Variable muss deklariert sein und besitzt somit einen festen Typ. Einer Variablen können nur Werte dieses Typs zugewiesen werden.

Nachfolgend einige Beispiele für die Zuweisung eines Wertes zu einer Variab­len.

Beispiel
Nach dem Ausführen dieses Befehls hat die Variable x den Wert 2:

x := 2;

Nach dem Ausführen dieses Befehls hat die Variable x den Wert 7:

x := x * x + 3;

Nach dem Ausführen dieser Befehle enthält die Variable l ein Feld mit den Ele­menten Hallo und Welt

var l as String[2];
l[0] := "Hallo";
l[1] := "Welt";

 

Die folgenden beiden Befehle sind äquivalent und weisen in der Hash-Tabelle c dem Schlüssel a den Wert X zu:

var c as HashMap;
c.a := "X";
c["a"] := "X";

 

Anweisungsblöcke

Mit geschweiften Klammern kann eine Folge von Befehlen zu einem Befehl in einem Anweisungsblock zusammengefasst werden. Alle Befehle in einem Anwei­sungsblock werden in der Reihenfolge ausgeführt, die in dem Block vorgegeben ist. Wenn ein Befehl bei der Ausführung einen Fehler meldet, so bricht der gesamte Anweisungsblock mit einem Fehler ab. Viele Befehle und Funktionen melden einen Fehler, wenn sie den Wert nullals Parameter bekommen.

Beispiel
Nach dem Ausführen dieses Blockes hat die Variable x den Wert 7:

{
x := 2;
x := x * x + 3;
}

Bedingter Befehl (if)

Der bedingte Befehl ifführt einen Befehl abhängig von dem Ergebnis einer Bedingung aus. Wenn die Bedingung wahr ist, dann wird der Befehl ausgeführt. Wenn die Bedingung nicht wahr ist, wird der Befehl übersprungen.

Beispiel
Nach dem Ausführen dieser Befehle hat die Variable x den Wert 0:

x := -13;
if (x < 0)
x := 0;

Bedingter Befehl mit Alternative (if … else)

Der bedingte Befehl mit Alternative if elseführt abhängig von dem Ergebnis einer Bedingung einen von zwei alternativen Befehlen aus. Wenn die Bedingung wahr ist, dann wird der Befehl vor dem elseausgeführt. Wenn die Bedingung nicht wahr ist, so wird der Befehl vor dem else übersprungen und der Befehl nach dem else ausgeführt.

Beispiel
Nach dem Ausführen dieser Befehle hat die Variable x den Wert 1:

x := 13;
if (x < 0) {
x := -1;
} else if (x > 0) {
x := 1;
}

Schleife mit Bedingung (while)

Die Schleife mit Bedingung whileführt solange einen Befehl aus, wie eine Bedingung erfüllt ist. Die Bedingung wird vor jeder Ausführung des Befehls geprüft, das bedeutet insbesondere auch, vor der ersten Ausführung. Wenn die Bedingung nicht erfüllt ist, wird der Befehl nicht ausgeführt.

Beispiel
Mit dem folgenden Befehl wird die Summe der Zahlen 1 bis 10 berechnet:

var i := 10;
var r := 0;
while (i > 0) {
r := r + i:
i := i - 1;
}

Die Anzahl der Durchläufe in einer while-Schleife ist beschränkt. Weitere Informationen finden Sie im Kapitel Komplexität von Ausdrücken beschränken.

Schleife über alle Elemente (for)

Die for-Schleife führt einen Befehl für alle Elemente einer Liste aus. Die Reihenfolge der Elemente in der Liste wird dabei eingehalten. Wenn die Liste keine Elemente hat, wird der Befehl nicht ausgeführt.

Beispiel
Mit dem folgenden Befehl wird die Summe der Zahlen 1 bis 10 berechnet.

var l := list(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
var r := 0;
for (e : l) {
r := r + e:
}

Schleife über alle Elemente (for … as)

Die for-Schleife führt einen Befehl für alle Elemente einer Liste aus. Die Reihenfolge der Elemente in der Liste wird dabei eingehalten. Das Element kann mit as in einen bestimmten Typ umgewandelt werden.

Beispiel
Die folgenden Befehle geben 10 Artikel auf der Konsole aus:

var objects := getCisObjectList(
"SELECT FROM com.cisag.app.general.obj.Item o", list(), 10);
for (item as CisObject(com.cisag.app.general.obj.Item) : objects)
{
echo(item:number);
}

Befehl beenden (return)

Der Befehl return beendet die aktuell ausgeführte Funktion.

Beispiel

function validate(state as Number)
{
if (state = State.CANCELED)
return;

if (results.COMMENT = "") {
sendMessage(results.COMMENT_id, "ERROR", "Comment is missing.");
return;
}

if (length(results.COMMENT) < 20) {
sendMessage(results.COMMENT_id, "WARNING", "Comment should be at least 20 characters.");
return;
}
}

 

Funktion beenden (return mit Rückgabewert)

Der Befehl return beendet die aktuell ausgeführte Funktion und gibt den Rückgabewert als Funktionsergebnis zurück.

Beispiel
Folgende Funktion fügt eine Liste von Zeichenketten mithilfe von einem Trennzeichen zu einer Zeichenkette zusammen. Der Befehl return r_textbeendet die Funktion und übergibt das Ergebnis an den Aufrufer.

function join(p_textList as String[], p_separator as String) as String
{
var r_text as String;

for (word as String : p_textList)
r_text := r_text + p_separator + word;
if (r_text <> "")
r_text := substring(r_text, length(p_separator));

return r_text;
}

 

Funktionen

Funktionen der System-Skriptsprache

Die System-Skriptsprache stellt viele Funktionen zur Verfügung. Um korrekt zu funktionieren, benötigen Funktionen die geeignete Umgebung, d. h. bestimmte Rahmenbedingungen müssen erfüllt sein. Unterschieden wird zum einen die Datenbank und zum anderen, ob eine Aktivität benötigt wird oder nicht. Soll die Funktion z. B. in der Übergangsbedingung (Transition) der Aktivitätsdefinition genutzt werden, so kann die Funktion nicht auf die Aktivität zugreifen, da diese erst zu einem späteren Zeitpunkt erzeugt wird.

Die Festlegung des Gültigkeitsbereichs einer Funktion erfolgt im Konstruktor der Funktion. In der Klasse ParserFunctionssind die möglichen Gültigkeitsbereiche in Form von Konstanten definiert.

Verwendungskontext Beschreibung
SYS_SCRIPT_OLTP Verwendbar in Skript-Objekten, individuellen Prüfungen und individuellen Hook-Implementierungen im Kontext einer OLTP-Datenbank.
WF_TRANSITION_REPOSITORY Verwendbar in Übergangsbedingungen und in der Funktion createvon Aktivitätsdefinitionen für Aktivitäten in der Repository-Datenbank.
WF_TRANSITION_OLTP Verwendbar in Übergangsbedingungen und in der Funktion create von Aktivitätsdefinitionen für Aktivitäten in einer OLTP-Datenbank.
WF_ACTIVITY_REPOSITORY Verwendbar in Ausdrücken und Deklarationen, aber nicht in Übergangsbedingungen von Aktivitätsdefinitionen für Aktivitäten in der Repository-Datenbank.
WF_ACTIVITY_OLTP Verwendbar in Ausdrücken und Deklarationen, aber nicht in Übergangsbedingungen von Aktivitätsdefinitionen für Aktivitäten in einer OLTP-Datenbank.
WF_REPOSITORY Entspricht den Verwendungskontexten WF_TRANSITION_REPOSITORYund WF_ACTIVITY_REPOSITORY. Verwendbar in Aktivitätsdefinitionen für Aktivitäten in der Repository-Datenbank.
WF_OLTP Entspricht den Verwendungskontexten WF_TRANSITION_OLTPund WF_ACTIVITY_OLTP. Verwendbar in Aktivitätsdefinitionen für Aktivitäten in einer OLTP-Datenbank.
OLTP Entspricht den Verwendungskontexten WF_SYS_SCRIPT_OLTPund WF_OLTP. D. h. der Verwendungskontext setzt keine Aktivitätsdefinition, aber eine OLTP-Datenbank voraus. Hierzu gehören Funktionen wie z. B. loadPartnerund loadItem. Verwendbar in Aktivitätsdefinitionen für Aktivitäten in einer OLTP-Datenbank sowie in Skript-Objekten, individuellen Prüfungen und individuellen Hook-Implementierungen im Kontext einer OLTP-Datenbank.
ALL Verwendbar in allen Kontexten, d. h. weder eine Aktivitätsdefinition noch eine OLTP-Datenbank wird vorausgesetzt. Hierzu gehören Funktionen wie z. B. createCisDate, getByPrimaryKeyund getCisObjectList.

Weitere Informationen und Beispiele zu den Funktionen und Befehlen finden Sie in folgenden Dokumentationen:

  • System-Skriptsprache: Allgemeine Funktionen
    Funktionen des Verwendungskontexts ALL.
  • System-Skriptsprache: OLTP-Funktionen
    Funktionen des Verwendungskontexts OLTPoder SYS_SCRIPT_OLTP.
  • System-Skriptsprache: Workflow-Funktionen
    Funktionen des Verwendungskontexts WF_REPOSITORY, WF_OLTP,WF_ACTIVITY_REPOSITORY, WF_ACTIVITY_OLTP, WF_TRANSITION_REPOSITORYoder WF_TRANSITION_OLTP.
Eigene Funktionsdeklarationen

Funktionen fassen unterschiedliche Elemente der System-Skriptsprache zusammen, um komplexe Zusammenhänge auszudrücken. Liefert eine Funktion keinen Wert zurück, dann ist der Wert der Funktion null.

function isPythagoreanTheorem(a as Number, b as Number, c as Number) as Boolean
{
return a * a + b * b = c * c;
}

function create()
{
var tryPythagoreanTheorem := isPythagoreanTheorem(3, 4, 5)
}

In den Termen können Funktionen aufgerufen werden. Funktionen berechnen aufgrund ihrer Eingangsparameter ein Ergebnis. Abhängig von der jeweiligen Funktion existieren Voraussetzungen an die Anzahl und den Typ der Eingangs­parameter. Diese Voraussetzungen werden wie folgt ausgedrückt:

Beispiel
f sei eine Funktion, deren Ergebnis den Datentyp R hat und die von ihren Parametern p1 bis pn die Datentypen D1 bis Dn erwartet. Dies wird wie folgt aufgeschrieben:

R f(D1 p1, ..., Dn pn)

Wenn der Datentyp völlig frei ist, so wird der Datentyp Unknownver­wendet.

Deklarationen

In diesem Kapitel wird beschrieben, wo Deklarationen erfasst und verwendet werden können, welche vorbelegten Funktionen dabei jeweils zur Verfügung stehen, sowie die Reihenfolge der Auswertung.

Deklarationen in Aktivitätsdefinitionen

Die Deklarationen einer Aktivitätsdefinition besitzen folgende vorbelegte Funktionen:

Funktion Beschreibung
create Die Funktion createwird beim Erzeugen der Aktivität aufgerufen.
Da zum Zeitpunkt des Aufrufs die Aktivität noch nicht erzeugt ist, stehen in der Funktion create die Informationen zur Aktivität nur eingeschränkt zur Verfügung.
applyDefaults Die Funktion applyDefaults wird beim Öffnen des Dialogs Aktivitätsergebnisse aufgerufen. Bei einem Startknoten mit einem Aktivitätsergebnis, wird der Dialog und somit auch die Funktion applyDefaultsvor der Funktion createaufgerufen. Bei allen anderen Aktivitäten erfolgt der Aufruf erst, nachdem die Funktion create aufgerufen wurde.

Da der Zweck der Funktion applyDefaults ist, die Felder des Dialogs Aktivitätsergebnisse zu initalisieren und mit Werten vorzubelegen, wird die Umgebung am Ende des Aufrufs nicht persistent gespeichert. Eventuelle Zuweisungen von Variablen innerhalb der Funktion applyDefaults stehen anderen Funktionen somit nicht zur Verfügung.

validate Die Funktion validate wird vor dem Übernehmen der Aktivitätsergebnisse im Dialog Aktivitätsergebnisse aufgerufen. Die Funktion wird auch dann aufgerufen, wenn die Aktivität in der Anwendung Aktivitäten gespeichert wird.
Der Parameter stategibt den künftigen Status der Aktivität wieder.Die Funktion validate liefert einen Rückgabewert vom Datentyp Booleanzurück. Ist der Rückgabewert false, dann können die Aktivitätsergebnisse nicht übernommen werden. In einem Startknoten verhindert die Ausgabe einer Fehlermeldung mithilfe des Befehls sendMessagedie Übernahme der Aktivitätsergebnisse. Schließt der Benutzer den Dialog Aktivitätsergebnisse mithilfe des Buttons [Abbrechen], wird keine Aktivität erzeugt. Da der Zweck der Funktion validateist, die Benutzereingaben im Dialog Aktivitätsergebnisse zu überprüfen, wird die Umgebung am Ende des Aufrufs nicht persistent gespeichert. Eventuelle Zuweisungen von Variablen innerhalb der Funktion validate stehen anderen Funktionen somit nicht zur Verfügung.
validatePrecondition Die Funktion validatePreconditionwird bei einem Statuswechsel der Aktivität aufgerufen, wenn im Feld Vorbedingung der Wert Deklaration ausgewählt ist. Die Funktion wird auch dann aufgerufen, wenn die Aktivität gespeichert wird, auch wenn sich der Status nicht ändert.

Der Parameter state gibt den künftigen Status der Aktivität wieder.

Die Funktion validatePrecondition liefert einen Rückgabewert vom Datentyp Booleanzurück. Ist die Vorbedingung false, dann wird die Aktivität automatisch unbearbeitet erledigt. In einem Startknoten wird keine Aktivität erzeugt, wenn die Funktion mithilfe des Befehls sendMessageeine Fehlermeldung ausgibt.

validatePostcondition Die Funktion validatePostcondition wird vor dem Erledigen der Aktivität aufgerufen, wenn im Feld Nachbedingung der Wert Deklaration ausgewählt ist.

Der Parameter stategibt den künftigen Status der Aktivität wieder.

Die Funktion validatePostcondition liefert einen Rückgabewert vom Datentyp Boolean zurück. Ist die Nachbedingung false, dann kann die Aktivität nicht erledigt werden. Die Aktivität kann auch dann nicht erledigt werden, wenn die Funktion mithilfe des Befehls sendMessage eine Fehlermeldung ausgibt.

Die Funktion validatePostcondition wird nur aufgerufen, wenn der Bearbeiter ein Benutzer ist. Bei Aktivitäten, die vom System oder von einem Verarbeitungsauftrag bearbeitet werden, erfolgt kein Aufruf.

validateSeriesCondition Die Funktion validateSeriesCondition wird gemäß des in der Serienvorlage hinterlegten Serienmusters aufgerufen, wenn im Feld Serienbedingung der Wert Deklaration ausgewählt ist.

Die Funktion validateSeriesCondition liefert einen Rückgabewert vom Datentyp Boolean zurück. Ist die Serienbedingung false, dann bricht die Serie ab und keine weiteren Serienaktivitäten werden erzeugt.

validateSelection Die Funktion validateSelection wird in einer Aktivität des Typs Auswahlknoten aufgerufen, wenn der Benutzer ein Business Object mit der Aktivität verknüpft.

Die Funktion validateSelection liefert einen Rückgabewert vom Datentyp Boolean zurück. Ist die Auswahlbedingung false, dann wird die Verknüpfung mit einer Fehlermeldung abgewiesen. Die Verknüpfung wird auch dann abgewiesen, wenn die Funktion mithilfe des Befehls sendMessageeine Fehlermeldung ausgibt.

close Die Funktion closewird beim Erledigen bzw. Erledigen ohne Bearbeitung der Aktivität aufgerufen.

Der Parameter state gibt den künftigen Status der Aktivität wieder.

Deklarationen in Prozessdefinitionen

Die Deklarationen einer Prozessdefinition werden den globalen Deklarationen der Aktivitätsdefinitionen hinzugefügt, bevor sie ausgewertet werden. Aus diesem Grund dürfen die Deklarationen einer Prozessdefinition nur Deklarationen enthalten, die auch außerhalb der Deklarationen der Aktivitätsdefinition deklariert werden können.

Beispiel
Auf dem Karteireiter Deklarationen einer Prozessdefinition sind eine Konstante zum Konfigurieren des Prozesses und eine Funktion definiert.

const MaxAmount := "123";
function helloWorld () as String
{
return "Hello World!";
}

Die Konstante MaxAmountund die Funktion helloWorldkönnen uneingeschränkt in allen Aktivitätsdefinitionen der Prozessdefinition verwendet werden, die die gleiche Skriptsprache wie die Prozessdefinition verwenden.

Beachten Sie bitte, dass je nach verwendeter Skript-Engine weitere Einschränkungen vorliegen können. Beispielsweise erlaubt die JavaScript-Engine Nashorn keine Deklaration von Konstanten.

Beachten Sie bitte auch, dass eine eigene Typdefinition (Class), die in einer Prozessdefinition deklariert ist, nicht in den Aktivitätsdefinitionen verwendet werden kann.

Reihenfolge der Auswertung in Aktivitätsdefinitionen

Wenn eine neue Aktivität aufgrund eines Ereignisses erzeugt wird, dann wird die Umgebung, in der die Bedingungen, Befehle und Terme ausgeführt werden, mit den durch das Ereignis vorgegebenen Variablenwerten initialisiert. Wenn eine aktivierte Aktivitätsdefinition ein Ereignis empfängt, dann werden die Ausdrücke dieser Aktivitätsdefinition in der unten beschriebenen Reihenfolge ausgewertet.

In einem Startknoten

Beim Erzeugen einer Aktivität für einen Startknoten werden die Funktionen in der folgenden Reihenfolge aufgerufen:

  1. Globale Deklarationen der Prozessdefinition
  2. Globale Deklarationen der Aktivitätsdefinition (außerhalb der Funktionen)
  3. applyDefaults
  4. validate
  5. create
  6. validatePrecondition
  7. close

Die Funktionen applyDefaultsund validatewerden nur dann aufgerufen, wenn die Aktivitätsdefinition ein Aktivitätsergbnis besitzt und der Prozess manuell gestartet wird, d. h. beim Ereignistyp Benutzeraktion oder bei Startknoten ohne eine Ereignisdefinition. Bei den Ereignistypen Programmiertes Ereignis und Business Entity werden die beiden Funktionen nicht aufgerufen.

Allgemein

Handelt es sich nicht um einen Startknoten, werden die Funktionen in der folgenden Reihenfolge aufgerufen:

  1. Globale Deklarationen der Prozessdefinition
  2. Globale Deklarationen der Aktivitätsdefinition (außerhalb der Funktionen)
  3. Übergangsbedingung
  4. create
  5. Anwendungsparameter
  6. Ausdruck für Bearbeiter
  7. validatePrecondition
  8. applyDefaults
  9. validate
  10. validatePostcondition
  11. close

Die Funktion validatePreconditionwird bei jedem Statuswechsel der Aktivität aufgerufen, d. h. der Aufruf erfolgt in der Regel mehrmals.

Die Funktionen applyDefaultsund validatewerden nur dann aufgerufen, wenn die Aktivitätsdefinition ein Aktivitätsergbnis besitzt und der Bearbeiter ein Benutzer ist. Wird die Aktivität durch eine Cockpit-Anwendung erledigt, dann wird der Dialog Aktivitätsergebnisse nicht geöffnet und beiden Funktionen nicht aufgerufen.

Ist der Bearbeiter der Aktivität kein Benutzer, sondern das System oder ein Verarbeitungsauftrag, wird die Funktion validatePostconditionnicht aufgerufen.

Befehle

Aktivitätsdefinitionen, die im Release 5.1 oder früher erfasst sind, können Befehle statt Deklarationen besitzen. Die Befehle werden beim Erzeugen der Aktivität ausgeführt und entsprechen in etwa der Funktion create. Aktivitätsdefinitionen, die Befehle verwenden, können keine Skripte beim Eingeben von Ergebnissen und beim Erledigen der Aktivität ausführen. Daher wird empfohlen, Befehle in Deklarationen zu überführen.

Dazu kopieren Sie das Skript von dem Karteireiter Befehle in die Funktion createauf dem Karteireiter Deklarationen und löschen das Skript auf dem Karteireiter Befehle. Nachdem Sie die Aktivitätsdefinition gespeichert haben, wird der Karteireiter Befehle ausgeblendet, sobald dessen Editorfeld leer ist.

Da Konstanten und Variablen, die auf dem Karteireiter Befehle deklariert sind, in allen Feldern der Aktivitätsdefinition zur Verfügung stehen, müssen Sie zusätzlich alle Konstanten, Variablen und Typdefinitionen, die in anderen Feldern der Aktivitätsdefinition verwendet werden, z. B. in der Vorbedingung oder in einem Feld für die Anwendungsparameter, außerhalb der Funktion create deklarieren.

Beispiel
Eine alte Aktivitätsdefinition erzeugt beim Kommissionieren eines Vertriebsauftrags eine Aktivität für den zuständigen Mitarbeiter des Kunden, damit er oder sie den Kunden benachrichtigen kann. Die Aktivität öffnet die Anwendung Partner, um die Kontaktdaten des Kunden anzuzeigen.

Auf dem Karteireiter Befehle ist folgendes Skript hinterlegt:

var editors as Guid[];
var customer := parameters.object->CustomerData->CustomerPartner;
var responsible := loadTargetsOfPartnerRelations(customer:guid, parameters.object->DeliveryPartnerData->Organization:guid, "Responsible");
for (r : responsible) {
editors := union(editors, resolvePartner(r:guid));
}

Die Variable editorswird im Feld Ausdruck für Bearbeiter verwendet. Die Variable customerwird als Wert für den Parameter Partner der Anwendung com.cisag.app.general.partner.ui.PartnerMaintenanceverwendet.

Um die Befehle in Deklarationen zu überführen, werden die Deklaration der Variablen editorsund customeraußerhalb der Funktion createplatziert.

const State as valueSet(com.cisag.sys.workflow.ActivityState);

var editors as Guid[];
var customer := parameters.object->CustomerData->CustomerPartner;

function create()
{
var responsible := loadTargetsOfPartnerRelations(customer:guid, parameters.object->DeliveryPartnerData->Organization:guid, "Responsible");
for (r : responsible) {
editors := union(editors, resolvePartner(r:guid));
}
}

Skript-Objekte und Bibliotheken

Eigene Deklarationen von Funktionen, Variablen und Konstanten können in Kundensystemen als Skript-Objekte erfasst werden. Verwenden Sie dazu die Anwendung Entwicklungsobjekte. Das Einbinden von Skript-Objekten hat den Vorteil, dass eigene Deklarationen zentral verwaltet werden können; Änderungen zu den Skript-Objekten wirken sich unmittelbar auf die Skripte aus, in denen sie eingebunden sind.

Als Entwicklungsobjekt unterliegen Skript-Objekte der Versionierung. Mithilfe der Anwendung Cockpit: Produktivsystem-Entwicklungsobjekte lassen sich die auf einem Testsystem erfassten Skript-Objekte (ähnlich wie die Workflow-Vorlagen) auf ein Produktivsystem übertragen.

Eigene Deklarationen können Sie auch in der Anwendung Bibliotheken erfassen und zu einer Bibliothek zusammenfassen. Wie die Workflow-Vorlagen werden auch Bibliotheken in der Repository-Datenbank gespeichert und stehen somit in allen OLTP-Datenbanken eines Systems zur Verfügung.

Um eingebunden werden zu können, muss das Skript-Objekt bzw. die Bibliothek die gleiche Skriptsprache wie das Skript verwenden. Ist das Skript in der System-Skriptsprache erfasst, dann verwenden Sie den Befehl import, um das Skript-Objekt bzw. die Bibliothek einzubinden. Ist das Skript in JavaScript erfasst, dann verwenden Sie den Befehl load. Weitere Informationen und Beispielen zu den beiden Befehlen finden Sie im Kapitel Sonstige Funktionen der Dokumentation System-Skriptsprache: Allgemeine Funktionen.

Hinweis
Bibliotheken können nur in der System-Skriptsprache erfasst werden.

Individuelle Prüfungen

Eine individuelle Prüfung erweitert die Prüfung eines bestimmten Business Entitys. Diese erweiterte Prüfung wird in allen Ein- und Ausgabekanälen verwendet, also sowohl in den Dialog-Anwendungen als auch beim Import oder Export. Sie können das Ergebnis dieser individuellen Prüfungen als individuelle Meldung ausgeben. Diese individuelle Meldung wird gemeinsam mit den Meldungen, die in der Repository-Datenbank erfasst sind, im jeweiligen Kontext angezeigt.

Die Anwendung Individuelle Prüfungen zeigt die Funktionen des ausgewählten Hook-Contracts an. So besitzt z. B. das Hook-Contract für Vertriebsaufträge folgende Funktionen.

function validateHeader(
persistent as DataView(com.cisag.app.sales.order.model.SalesOrder),
current as DataView(com.cisag.app.sales.order.model.SalesOrder))
{ }

function validateDetail(
persistent as DataView(com.cisag.app.sales.order.model.SalesOrderDetail),
current as DataView(com.cisag.app.sales.order.model.SalesOrderDetail))
{ }

function validateDeleteHeader(
persistent as DataView(com.cisag.app.sales.order.model.SalesOrder))
{ }

function validateDeleteDetail(
persistent as DataView(com.cisag.app.sales.order.model.SalesOrderDetail))
{ }

Mithilfe der übergebenen Objektsichten persistentund currentkönnen Sie die zu validierenden Änderungen in current mit dem persistent gespeicherten Zustand des Business Objects in persistent vergleichen. Bei manchen Hook-Contracts (wie z. B. Kampagnen) haben die Funktionen keinen Parameter current. Um auch in solchen Fällen den gespeicherten Zustand des Business Entitys auszuwerten, können Sie das Business Entity mithilfe z. B. der Skriptfunktion getByPrimaryKeyöffnen, da viele der Attribute der Objektsicht auch im Business Entity vorhanden sind.

Besitzt ein Business Entity ein weiteres Feld, dann können Sie dessen Wert mithilfe einer weiteren Funktion mit dem gleichen Namen aber mit dem Suffix Extension_ gefolgt vom Schemanamen prüfen. Die Funktion umfasst einen zusätzlichen Parameter extension, der eine Hash-Tabelle mit den Namen und Werten aller weiteren Felder des Business Entity zur Verfügung stellt. Besitzt der Artikel ein weiteres Feld in der Basisansicht mit dem Namen EXTNUM und dem Feldtyp Text, dann könnte die Hash-Tabelle den Inhalt {EXTNUM_val=[S=], EXTNUM_id=[N=707070]}haben.

Folgende Individuelle Prüfung gibt eine Fehlermeldung aus, wenn das weitere Feld EXTNUM leer ist:

function validate(
view as DataView(com.cisag.app.general.item.model.Item))
{ }

function validateExtension_EXTItem(
view as DataView(com.cisag.app.general.item.model.Item),
extension as Extension_EXTItem)
{
if (extension.EXTNUM_val = "")
sendMessage(extension.EXTNUM_id, "ERROR", list("No value."));
}

Wenn Sie das erste weitere Feld eines Business Entitys anlegen, nachdem Sie die individuelle Prüfung bereits erfasst haben, dann können Sie die individuelle Prüfung erneut erfassen, damit ein Muster für die zusätzliche Funktion mit dem Parameter extensionautomatisch generiert wird.

Informationsauswertung

Abhängig vom Initialisierungsstatus der neuen Aktivität werden die unterschiedlichen Variablen gefüllt. Beispielsweise ist zum Zeitpunkt der Auswertung der Übergangsbedingung und der Funktion createnoch keine Aktivität vorhanden. Daher stehen die Werte der Variablen activitynicht bzw. nur eingeschränkt zur Verfügung.

In den folgenden Kapiteln wird die Verwendung der zur Verfügung stehenden Variablen näher erläutert:

Ereignis (event)

Besitzt die Aktivitätsdefinition einer Ereignisdefinition, dann enthält die Variable eventeine Hash-Tabellle mit Informationen zum ausgelösten Ereignis.

Variable Wert
type Die Variable type enthält den Ereignistyp. Die möglichen Werte sind im ValueSet com.cisag.sys.workflow.EventTypeLimiteddefiniert. Folgende Werte sind hier relevant:

  • 3 steht für ein programmiertes Er­eignis
  • 5 steht für den Ereignistyp Business Entity
  • 8 steht für den Ereignistyp Benutzeraktion
subtype Die Variable subtypeenthält den Subtyp des Ereignisses. Bei programmierten Ereignissen ist dies der Wert des ValueSet-Eintrags. Ist kein ValueSet dem Ereignis zugeord­net, dann ist der Wert null. Beim Ereignistyp Business Entity sind die möglichen Wert im ValueSet com.cisag.sys.kernel.ObjectChangeTypedefiniert:

  • 1 steht für Einfügen
  • 2 steht für Ändern
  • 3 steht für Löschen

Beachten Sie bitte, dass das Setzen einer Löschmarkierung für ein Business Object als eine Änderung gilt. Erst beim Reorganisieren wird das Business Object aus der Datenbank gelöscht.
Der Subtyp kann beim Ereignistyp Business Entity dazu verwendet werden, um bei Ereignisdefinitionen unterschiedlicher Subtypen das Business Entity korrekt auszuwerten. Soll z. B. die Nummer eines Artikels bei allen drei Subtypen im Aktivitätstext ausgegeben werden, dann kann folgendes Skript verwendet werden:

var itemNumber := String;
if (event.subtype = 3)
itemNumber := parameters.oldObject:number;
else
itemNumber := parameters.newObject:number;
format("itemNumber", itemNumber);

Wenn das Script beim Subtyp 3 parameters.objectoder parametrers.newObjectauswertet, würde ein Laufzeitfehler entstehen, da das Business Object nicht mehr existiert.

guid Die Variable guidenthält die GUID des programmierten Ereignisses oder die GUID des Business Objects beim Ereignis Busi­ness Entity.
Um den vollständigen technischen Namen des Business Objects beim Ereignistyp Business Entity zu bestimmen, können Sie den Ausdruck objectName(event.guid)verwenden.
database Die Variable database enthält die GUID der Datenbank, in der das Er­eignis ausgelöst wurde.
Um den Namen der Datenbank zu bestimmen, können Sie den Ausdruck databaseName(event.database)verwenden.
Um den Namen des Systems zu ermitteln, können Sie in einer Deklaration, die JavaScript verwendet, Java.type('com.cisag.pgm.util.ServerInfo').getSystemName()aufrufen. Die Java-Methode Java.type('com.cisag.pgm.util.ServerInfo').getSVMName()gibt den den Namen des Servers zurück.
parameters Die Variable parametersenthält eine Hash-Tabelle mit weiteren Informationen zum ausgelösten Ereignis. Welche Informationen parameters enthält, ist je nach Typ und Subtyp des Ereignisses unterschiedlich:

  • Bei programmierten Ereignissen werden die Ereignisparameter beim Erfassen des Ereignisses festgelegt.
  • Beim Ereignis Bu­siness Entity geändert ist der Umfang der Para­meter fest vorgegeben.

Die Variable parameters wird in Kapitel Parameter (parameters) näher erläutert.

Parameter (parameters)

In Abhängigkeit des Typs und Subtyps des Ereignisses enthält die Variable parameterseine Hash-Tabelle mit weiteren Informationen zum ausgelösten Ereignis. Die Variable parameters ist nur in Aktivitätsdefinitionen ohne Bezug zu einer Prozessdefinition sowie in Ereignisknoten verfügbar. Daher sollten Sie im Startknoten diejenigen Parameter, die Sie später im Prozess brauchen, in Prozessvariablen speichern.

Ereignistyp Programmiertes Ereignis

Programmierte Ereignisse besitzen genau diejenigen Parameter, die in der Anwendung Entwicklungsobjekte für das Ereignis eingetragen sind.

Beispiel
Das Ereignis com.cisag.pgm.workflow.GenericOLTPEventbesitzt die beiden Parameter nameund parameters, die als Stringbzw. HashMapübergeben werden.

Soll nur dann eine Aktivität erzeugt werden, wenn der Name den gleichen Wert wie die Aktivitätsdefinition hat, dann kann die Übergangsbedingung parameters.name = definition:codeverwendet werden.

Folgende Zuweisung übernimmt den Wert des Hash-Tabellen-Eintrags userals Prozessauslöser:

process.Initiator := cast(String, parameters.parameters.user);

Da die Hash-Tabelle untypisiert ist, müssen die Einträge mithilfe der Funktion castin den korrekten Datentypen umgewandelt werden, bevor sie in den Deklarationen verwendet werden können.

Ereignistyp Business Entity

Ein Ereignis des Typs Business Entity ist für Business Objects in der Repository-Datenbank oder der OLTP-Datenbank möglich. Welche Parameter das Ereignis besitzt, hängt vom Subtyp Einfü­gen, Ändern oder Löschen und vom Typ des überwachten Busi­ness Objects ab.

Variable Wert
userGuid Die Variable userGuidenthält die GUID des Benutzers, der das Business Object verändert hat.

Bei einem Ereignis des typs Business Entity ist der Prozessauslöser in process.Initiatorautomatisch vorbelegt. Folgende Zuweisung legt den Prozessauslöser auch als Prozessverantwortlicher fest:

process.Owner := userName(parameters.userGuid);

object Die Variable objectenthält eine Referenz auf das veränderte Business Object. Die Variable objectgibt den aktuellen Zustand des Business Objects zum Zeitpunkt der Auswertung wider. Beim Subtyp Löschen hat object den Wert null.
Die Variable objectkann z. B. dazu verwendet werden, um den aktuellen Zustand des veränderten Business Objects beim Beginn des Bearbeitungszeitraumes auszuwerten.
Folgende Vorbedingung prüft, ob der Beleg, für den das Ereignis ausgelöst wurde, freigegeben ist. Ist dies nicht der Fall, dann ist die Vorbedingung false und die Aktivität wird automatisch unbearbeitet erledigt:parameters.object:status = 2 /* ORDER_RELEASED */
oldObject Die Variable oldObjectenthält den Wert des veränderten Business Objects unmittelbar vor dem Auslösen des Ereignisses. Beim Subtyp Einfügen hat oldObject den Wert null.

Folgende Übergangsbedingung prüft, ob das Attribut numbergeändert wurde:

parameters.oldObject:number <> parameters.newObject:number

newObject Die Variable newObject enthält den Wert des veränderten Business Objects unmittelbar nach der Än­derung. Beim Subtyp Löschen hat newObject den Wert null.

Folgende Vorbedingung prüft, ob zwischen dem Auslösen des Ereignisses und dem Beginn des Bearbeitungszeitraumes der Beleg bzw. das Business Object erneut verändert wurde:

parameters.object:updateInfo.updateTime = parameters.newObject:updateInfo.updateTime

entity Ist das veränderte Business Object ein De­pendent, dann enthält die Variable entity eine Referenz auf das mit dem Business Object über die Beziehung _entityverküpfte Business Entity. Ob ein Business Object ein Dependent ist, können Sie in der Anwendung Entwicklungsobjekte sehen. Ist im Feld Typ der Wert Dependent ausgewählt, dann ist das Business Object ein Dependent.

Ein Beispiel für ein Dependent ist die Vertriebsauftragsposition. Besitzt eine Aktivitätsdefinition eine Ereignisdefinition für eine Vertriebsauftragsposition, dann referenziert parameters.objectdas Business Object com.cisag.app.sales.obj.SalesOrderDetail(Vertriebsauftragsposition) und parameters.entitydas Business Object com.cisag.app.sales.obj.SalesOrder(Vertriebsauftrag).

Ist das Business Object kein Dependent, dann ist entitynicht definiert. Beim Subtyp Löschen hat entity den Wert null.

oldEntity Ist das veränderte Business Object ein De­pendent, dann enthält die Variable oldEntity den Wert des mit dem Business Object über die Beziehung_entityverküpften Business Entitys unmittelbar vor der Änderung.

Ist das Business Object kein Dependent, dann ist oldEntitynicht definiert. Beim Subtyp Einfügen hat oldEntityden Wert null.

newEntity Ist das veränderte Business Object ein De­pendent, dann enthält die Variable newEntity den Wert des mit dem Business Object über die Beziehung _entityverküpften Business Entitys unmittelbar nach der Änderung.

Ist das Business Object kein Dependent, dann ist newEntitynicht definiert. Beim Subtyp Einfügen hat newEntityden Wert null.

Ereignistyp Benutzeraktion

Ein Ereignis des Typs Benutzeraktion ist für Business Entitys in der Repository-Datenbank oder der OLTP-Datenbank möglich. Ereignisse für Dependents werden nicht unterstützt. Das Ereignis besitzt folgende Parameter.

Variable Wert
userGuid Die Variable userGuid enthält die GUID des Benutzers, der das Business Entity verändert hat.

Bei einem Ereignis des typs Benutzeraktion ist der Prozessauslöser in process.Initiatorautomatisch vorbelegt. Folgende Zuweisung legt den Prozessauslöser auch als Prozessverantwortlicher fest:

process.Owner := userName(parameters.userGuid);

Folgende Übergangsbedingung prüft, ob der Benutzer der zuständige Mitarbeiter des Belegs ist. Ist dies nicht der Fall, dann ist die Übergangsbedingung falseund die Benutzeraktion ist im Kontextmenü des Belegs für den Benutzer deaktiviert:

parameters.userGuid = cast(Guid, first(parameters.object:responsible, parameters.userGuid))Hat der Beleg keinen zuständigen Mitarbeiter, dann bleibt die Benutzeraktion im Kontextmenü aller Benutzer aktiviert.

object Die Variable object enthält eine Referenz auf das Business Entity, für das die Benutzeraktion ausgelöst wurde. Die Variable object gibt den aktuellen Zustand des Business Entitys zum Zeitpunkt der Auswertung wider.

Folgende Übergangsbedingung prüft, ob ein Beleg in Bearbeitung ist. Ist dies nicht der Fall, dann ist die Übergangsbedingung falseund die Benutzeraktion ist im Kontextmenü des Belegs deaktiviert:

parameters.object:status = 1 /* ORDER_ENTERED */

Ohne Ereignisdefinition

Ein Prozess ohne Ereignisdefinition im Startknoten kann nur manuell gestartet werden. Um im Startknoten entscheiden zu können, ob der Benutzer berechtigt ist, den Prozess zu starten, stellt die Variable parametersauch dann relevante Informationen zur Verfügung, wenn kein Ereignis vorliegt.

Variable Wert
userGuid Die Variable userGuid enthält die GUID des Benutzers, der den Prozess manuell startet.

Folgender Ausdruck im Feld Ausdruck für Vorbedingung unterbindet den Prozessstart, wenn der Benutzer der Workflowrolle MANAGERS nicht zugeordnet ist.

contains(resolveRole("MANAGERS", parameters.userGuid)

database Die Variable database enthält die GUID der Datenbank, in der der Prozess gestartet wird. Siehe Kapitel Ereignis (event)  für Anwendungsbeispiele.
organization Die Variable organization enthält bei einem manuell gestarteten Prozess die GUID der in der Anwendung ausgewählten Organisation, aus welcher der Prozess gestartet wurde.

Prozess (process)

Ist die Aktivitätsdefinition mit einer Prozessdefinition verknüpft dann enthält die Variable processeine Hash-Tabellle mit Informationen zum Prozess.

Variable Beschreibung
Code Die Variable Code enthält die Identifikation des Prozesses.
Database Die Variable Database enthält die GUID der Datenbank. Diese Variable ist nur in der Funktion createeines Startknotens verfügbar.
Description Die Variable Description enthält die Bezeichnung des Prozesses.
EndTime Die Variable EndTime enthält den Zeitpunkt für das Ende des Bearbeitungszeitraums.
ErrorCode Die Variable ErrorCode enthält den Fehlercode, nachdem ein Fehler im Prozess aufgetreten ist. Eine Auswertung ist daher nur im Fehlerknoten sinnvoll.

Der Fehlercode und die Fehlerbeschreibung können per Zuweisung gesetzt werden. Anschließend kann der Befehl abortProcessverwendet werden, um den Prozess über den Fehlerknoten zu beenden.

process.ErrorCode := "USER_ERROR";
process.ErrorDescription := "Error raised by user in create() of activity " + activity:code + ".";
abortProcess();
ErrorDescription Die Variable ErrorDescription enthält die zum Fehlercode zugehörige Fehlerbezeichnung, nachdem ein Fehler im Prozess aufgetreten ist. Eine Auswertung ist daher nur im Fehlerknoten sinnvoll.
FinishTime Die Variable FinishTime enthält den Erledigungszeitpunkt des Prozesses.
Initiator Die Variable Initiatorenthält den Prozessauslöser. Der Prozessauslöser steht erst ab der Funktion closedes Startknotens zur Verfügung. Der Prozessauslöser wird bei Ereignissen des Typs Business Entity und Benutzeraktion automatisch gesetzt. Beim Ereignistyp Programmiertes Ereignis sowie bei Prozessen ohne Ereignisdefinition kann der Prozessauslöser nur per Zuweisung eines Benutzernamens festgelegt werden.

process.Initiator := userName(getByBusinessKey(CisObject(com.cisag.app.inventory.obj.InventoryTransaction), parameters.internalNumber):updateInfo.createUser)weist dem Prozess denjenigen Benutzer als Auslöser zu, der die Materialbuchung erfasst bzw. erzeugt hat, welche das programmierte Ereignis com.cisag.app.inventory.MinimumOnhandausgelöst hat.

Der Auslöser kann während der Ausführung des Prozesses beliebig geändert werden.

Number1 Die Variable Number1 enthält das erste allgemeine numerische Ergebnisattribut. Der Wert kann durch Zuweisung beliebig geändert werden.

process.Number1 := parameters.object:totalValues.grossValue.amountweist dem Attribut Number1 den Brutto-Gesamtbetrag eines von parameters.objectreferenzierten Beschaffungsauftrags zu.

Number2 Die Variable Number2 enthält das zweite allgemeine numerische Ergebnisattribut. Der Wert kann durch Zuweisung beliebig geändert werden.
OrganizationalUnit Die Variable OrganizationalUnit enthält die GUID der Organisation. Der Organisationskontext des Ereignisses kann per Zuweisung auf den Prozess übertragen werden. Die zugeordnete Organisation hat u. a. Auswirkungen auf die Berechtigung unbeteiligter Benutzer. Ist in der Prozessdefinition die Fähigkeit Standard für unbeteiligte Benutzer ausgewählt und die Aktivität ist einer Organisation zugeordnet, dann können nur solche unbeteiligte Benutzer den Prozess anzeigen, die derselben Organisation zugeordnet sind.
Owner Die Variable Owner enthält den Prozessverantwortlichen. Der Prozessverantwortliche steht erst in der Funktion closedes Startknotens zur Verfügung. Bei einem manuellen Prozess mit Aktivitätsergbnissen im Startknoten, kann der Owner in den Funktionen applyDefaultsund validatenicht ausgewertet werden.

Der Wert kann durch Zuweisung eines Benutzernamens oder der Identifikation einer Workflowrolle geändert werden.

process.Owner := process.Initiatorweist dem Prozess den Auslöser auch als Verantwortlicher zu.

Die Herkunft des Prozessverantwortlichen kann im Attribut activity->Process:processData.sourceOfOwnerabgefragt werden. Der Wert 1 steht für Benutzer und der Wert 2 für Workflowrolle.

previousStep Wenn die Aktivität nur eine einzige Vorgängeraktivität hat, dann enthält die Variable previousStep eine Referenz auf die Vorgängeraktivität. Wenn die Aktivität keine Vorgängeraktivität hat, was z. B. für den Startknoten der Fall ist, oder mehrere Vorgängeraktivitäten hat, dann besitzt die Variable den Standardwert null.

Der Ausdruck process.previousStep:completeUsergibt die GUID desjenigen Benutzers zurück, der mit seiner Aufgabe die Vorgängeraktivität erledigt hat. Beachten Sie bitte, dass der Name dieses Attributs mit einem Kleinbuchstaben anfängt.

previousSteps Wenn die Aktivität mehrere Vorgängeraktivitäten hat, z. B. durch die Verwendung eines Zusammenführungsknotens, enthält die Variable previousSteps eine Liste mit einer Referenz für jede Vorgängeraktivität. Wenn die Aktivität keine oder nur eine einzige Vorgängeraktivität hat, dann hat die Variable den Standardwert null.

Folgendes Skript weist der Variable userseine Liste mit den GUIDs aller Benutzer zu, die mit ihrer Aufgabe eine Vorgängeraktivität erledigt haben.

var users as Guid[];
for (a : process.previousSteps)
users := union(users, list(a:completeUser));

Beachten Sie bitte, dass der Name dieses Attributs mit einem Kleinbuchstaben anfängt.

StartTime Die Variable StartTime enthält den Zeitpunkt für den Beginn des Bearbeitungszeitraums.
State Die Variable State enthält den Prozessstatus.
Result Die Variable Result enthält das allgemeine Prozessergebnis. Der Wert kann durch Zuweisung beliebig geändert werden, ist aber auf 80 Zeichen limitiert.

Folgende Zuweisung in der Funktion closefasst viele Einzelergebnisse eines Genehmigungsprozesses für den in der Prozessvariablen „PO“ referenzierten Beschaffungsauftrag zu einem allgemeinen Prozessergebnis zusammen:

process.result := process.PO:number + " submitted by " + process.Initiator + " was " + results.approvalResult + " by " + userName(activity:completeUser);Das Ergebnis der Prüfung befindet sich im Aktivitätsergebnis approvalResult.

Text1 Die Variable Text1 enthält das erste allgemeine Ergebnisattribut für Zeichenketten. Der Wert kann durch Zuweisung beliebig geändert werden.

process.Text1 := "APPROVED"

Text2 Die Variable Text2 enthält das zweite allgemeine Ergebnisattribut für Zeichenketten. Der Wert kann durch Zuweisung beliebig geändert werden.
Text3 Die Variable Text3 enthält das dritte allgemeine Ergebnisattribut für Zeichenketten. Der Wert kann durch Zuweisung beliebig geändert werden.
Text4 Die Variable Text4 enthält das vierte allgemeine Ergebnisattribut für Zeichenketten. Der Wert kann durch Zuweisung beliebig geändert werden.
Text5 Die Variable Text5 enthält das fünfte allgemeine Ergebnisattribut für Zeichenketten. Der Wert kann durch Zuweisung beliebig geändert werden.
Timestamp1 Die Variable Timestamp1 enthält das erste allgemeine Ergebnisattribut für Zeitpunkte. Der Wert kann durch Zuweisung beliebig geändert werden.

process.Timestamp1 := now();

Timestamp2 Die Variable Timestamp2 enthält das zweite allgemeine Ergebnisattribut für Zeitpunkte. Der Wert kann durch Zuweisung beliebig geändert werden.

Je nach Ausführungskontext und Aktivitätsstatus stehen unterschiedliche Attribute zur Verfügung. In den Funktionen applyDefaultsund validateeines Startknotens besitzen alle Attribute noch ihre Standardwerte. Da der Startknoten keinen Vorgänger hat, besitzen die Attribute previousStepund previousStepsimmer den Standardwert nullin einem Startknoten.

In der Funktion createeines Startknotens besitzen die Attribute OrganizationalUnitund Database Werte aus dem aktuellen Kontext. Um diese Attribute auch in den Funktionen applyDefaults und validate eines Startknotens abzufragen, können Sie stattdessen die Variablen eventund parametersauswerten.

In der Funktion closeeines Startknotens sowie in allen Funktionen der darauf folgenden Aktivitäts- und Ereignisknoten besitzen sämtliche Attribute außer OrganizationalUnitund DatabaseWerte aus dem aktuellen Kontext. Möchten Sie diese beiden Werte zu einem späteren Zeitpunkt im Prozess auswerten, sollten Sie sie in der Funktion closein Prozessvariablen speichern.

Aktivität (activity)

Wenn die Übergangsbedingung erfüllt ist und die Funktion createausgeführt wurde, wird die neue Aktivität erzeugt. Ab diesem Zeitpunkt stellt die Variable activityeine Referenz auf die erzeugte Aktivität zur Verfügung.

Um die Auswertung zu vereinfachen, stehen einige Attribute bereits in der Funktion create zur Verfügung. So können Sie z. B. die Identifikation und den Status der Aktivität auswerten. Andere Informationen, wie z. B. Beziehungen zu anderen Business Objects, lassen sich erst nach dem Ausführen der Funktion create auswerten.

Aus dem gleichen Grund stehen einige Attribute in der Funktion closezur Verfügung, die erst nach dem Erledigen der Aktivität persistent gespeichert werden. So können Sie z. B. mithilfe des Attributs activity:completeUserauswerten, welcher Benutzer die Aktivität gerade erledigt.

Nach der Ausführung der Funktion createkönnen Sie den Prozess über die Beziehung Process auswerten. So bestimmt z. B. der Ausdruck
activity->Process:codedie Identifikation des Prozesses.

Aktivitätsdefinition (definition)

Die Variable definitionenthält eine Referenz auf die Aktivitätsdefinition, die das Ereignis empfangen hat und mit der die neue Akti­vität erzeugt werden soll. Diese Variable steht überall in einer Aktivitätsdefinition zur Verfügung.

Mithilfe der Übergangsbedingung parameters.name = definition:codein einer Aktivitätsdefinition für das programmierte Ereignis com.cisag.pgm.workflow.GenericOLTPEventkann das programmierte Ereignis mit der Identifikation derjenigen Aktivitätsdefinition als Name ausgelöst werden, die zum Generieren der Aktivität verwendet werden soll.

Über die Variable definitionkann auch die mit der Aktivitätsdefinition verknüpfte Prozessdefinition ausgewertet werden. So bestimmt z. B. der Ausdruck
definition->ProcessDefinition:codedie Identifikation der Prozessdefinition.

Aktionsparameter (actionParameters)

Wenn die Funktion createausgeführt und die Aktivität erzeugt wurde, dann enthält die die Variable actionParameterseine Hash-Tabelle mit den Werten aller Anwendungsparameter. Diese Variable kann z. B. in einer Vorbedingung oder in der Funktion closeausgewertet werden.

Aktivitätsergebnisse (results)

Wenn die Funktion createausgeführt und die Aktivität erzeugt wurde, dann enthält die die Variable resultseine Hash-Tabelle mit den Werten aller Aktivitätsergebnisse. Die Variable results wird oft in der Funktion closeverwendet, um die Aktivitätsergebnisse in Prozessvariablen zu speichern.

Beispiel
Eine Aktivitätsdefinition besitzt folgende zwei Aktivitätsergebnisse:

  • approvalStatus vom Feldtyp Auswahlfeld mit den beiden Werten APPROVED und REJECTED.
  • comment vom Feldtyp Mehrzeiliges Textfeld.

In der Funktion applyDefaults wird das Auswahlfeld approvalStatus mit REJECTED vorbelegt:

function applyDefaults()
{
results.approvalStatus := "REJECTED";
}

In der Funktion validatewird die individuelle Meldung COMMENT ausgegeben, wenn der Benutzer den Wert APPROVED ausgewählt hat, ohne einen Kommentar zu erfassen:

function validate(state as Number)
{
if (results.approvalStatus <> "APPROVED" and results.comment = "")
sendMessage(results.comment_id, "COMMENT", list());
}

Das Suffix _idhinter dem Namen des Aktivitätsergebnisses bewirkt, dass die farbige Ecke für die Meldung im Kommentarfeld erscheint.

In der Funktion closewerden schließlich die beiden Aktivitätsergebnisse in gleichnamigen Prozessvariablen gespeichert:

function close(state as Number)
{
if(results.approvalStatus = "APPROVED")
process.approvalStatus := "APPROVED";
else
process.approvalStatus := "REJECTED";
process.comment := results.comment;
}

Danach können andere Aktivitäten im Prozess die Werte verwenden.

 

In dem obigen Beispiel wäre auch die einfachere Zuweisung process.approvalStatus := results.approvalStatusmöglich. Der Unterschied ist, dass durch eine solche Zuweisung die Prozessvariable process.approvalStatusein undefiniertes Ergebnis hätte, wenn der Benutzer die Aufgabe oder die Aktivität durch eine Cockpit-Anwendung erledigt, da in diesem Fall keine Eingabe von Ergebnissen möglich ist.

Eine weitere Variante wäre, das Aktivitätseregbnis abhängig vom Status der Aktivität zuzuweisen: erledigt der Benutzer die Aktivität durch eine Cockpit-Anwendung, gilt dies als eine implizite Genehmigung. Wird die Aktivität unbearbeitet erledigt, dann gilt dies als eine implizite Ablehnung:

function close(state as Number)
{
if(results.approvalStatus = "APPROVED")
process.approvalStatus := "APPROVED";
else if(results.approvalStatus <> "")
process.approvalStatus := "REJECTED";
else if (state = State:DONE)
process.approvalStatus := "APPROVED";
else
process.approvalStatus := "REJECTED";
}

Es ist auch möglich, im Feld Erledigungsbestätigung auf dem Karteireiter Bearbeitung der Aktivitätsdefinition den Wert Erledigen durch Workflow-Symbolleiste auszuwählen, um das Erledigen durch eine Cockpit-Anwendung zu unterbinden.

Dialogsteuerung (dialog)

Besitzt die Aktivitätsdefinition ein Aktivitätsergebnis des Feldtyps Seite, dann besteht der Dialog Aktivitätsergebnisse eingeben aus mehreren Seiten. Um per Scripting zwischen den Seiten wechseln zu können, stellt die Variable parametersfolgende Attribute zur Verfügung:

Variable Beschreibung
page Die Variable page enthält den technischen Namen der aktuellen Seite im Dialog Aktivitätsergebnisse eingeben. Ist die aktuelle Seite die erste Seite des Dialogs, dann ist der Wert von pageeine leere Zeichenkette.
nextPage Wird der Variable nextPage der technische Name eines Aktivitätsergbnisses des Feldtyps Seite zugewiesen, und diese Seite befindet sich nach der aktuellen Seite, dann wechselt der Dialog direkt zu dieser Seite, auch wenn andere Seiten dadurch übersprungen werden müssen. Es ist nicht möglich, auf der gleichen Seite zu bleiben oder zu einer Seite zu wechseln, die sich vor der aktuellen Seite befindet.

Im folgenden Beispiel besitzt eine Aktivitätsdefinition vier Dialogseiten mit den Namen page1, page2, page3 und page4. Jede Seite besitzt ein Textfeld mit den Namen text1, text2, text3 und text4. Ist das Textfeld auf einer Seite leer, dann soll nicht zur darauf folgenden Seite sondern direkt zur letzten Seite page4 gewechselt werden.

function validate(state as Number)
{
if (dialog.page = "page1" or dialog.page = "") {
if (results.text1 = "")
dialog.nextPage := "page4";
}
if (dialog.page = "page2") {
if (results.text2 = "")
dialog.nextPage := "page4";
}
}

Eine Prüfung auf der Seite page3 ist nicht erforderlich, da die Seite page4 ohnehin die nächste Seite ist.

Funktionsaufrufe (parameters und result)

Ein Funktionsaufruf ist eine Aktivitätsdefinition, die statt Aktivitäten zu erzeugen ein Ergebnis berechnet und zurückgibt. Funktionsaufrufe werden z. B. eingesetzt, um komplexe Berechnungen einmalig zu erfassen oder Ausdrücke in JavaScript auch in Aktivitätsdefinitionen verwenden zu können, die in der System-Skriptsprache erfasst sind.

Die Parameter und Rückgabewerte von Aktivitätsdefinitionen des Typs Funktionsaufruf werden mit der Aktivitätsdefinition erfasst. Jeder Parameter und jeder Rückgabewert hat in der Aktivitätsdefinition die folgenden Eigenschaften:

  • Einen innerhalb der Aktivitätsdefinition eindeutigen technischen Namen
  • Eine übersetzbare Bezeichnung
  • Einen Datentyp

Für jeden Parameter P1,…,Pn und Rückgabewert R1,…,Rm gibt es eine Variable mit dem technischen Namen in den Variablen parametersund result, d.h.:

parameters.P1,…,parameters.Pn
result.R1,…,result.Rm

Die Werte der Parameter werden beim Aufruf der Aktivitätsdefinition übergeben und gesetzt. Die Werte der Rückgabewerte sind beim Aufruf nullund können durch die Aktivitätsdefinition berechnet werden.

Beispiel
Die Aktivitätsdefinition X hat den Parameter ITEMNUMBERmit der Bezeichnung Artikelnummer und dem Datentyp Zeichenkette sowie den Rückgabewert PRICEmit der Bezeichnung Preis und dem Datentyp Nummer. In diesem Fall gibt es die folgenden Variablen:

parameters.ITEMNUMBER
result.PRICE

Der Wert der Variablen ITEMNUMBERwird beim Aufruf der Aktivitätsdefinition gesetzt. Der Wert der Variablen PRICEmuss durch die Aktivitätsdefinition gesetzt werden.

Beachten Sie bitte, dass in einer Aktivitätsdefinitionen des Typs Funktionsaufruf die üblichen Umgebungsvariablen für die Datenbank und den Benutzer nicht zur Verfügung stehen, da solche Aktivitätsdefinitionen in der Regel nicht interaktiv durch einen Benutzer beendet werden.

Hintergrundanwendungen (getJobResult)

Der Knotentyp Serviceknoten wird in Prozessdefinitionen verwendet, um eine Aktivität zu erzeugen, die eine Hintergrund-Anwendung aufruft. Ein Serviceknoten wird von einem Verarbeitungsauftrag bearbeitet. Auch in einer Aktivitätsdefinition des Typs Einzelaktivität kann Verarbeitungsauftrag als Bearbeiter ausgewählt werden.

In der Funktion closekann die Skriptfunktion getJobResultverwendet werden, um die Ergebnisse der aufgerufenen Hintergrundanwendung auszuwerten, vorausgesetzt die Aktivität wartet auf den Verarbeitungsauftrag, entweder durch das Aktivieren der Checkbox Auf Verarbeitungsauftrag warten in dem Karteireiter Bearbeitung oder durch den Befehl setJobWaitFinish(true)in der Funktion create.

Die Funktion getJobResult übergibt eine Hash-Tabelle mit den Variablenwerten, die hinter CisParameterList: auf dem Karteireiter Ausführung im Eigenschaftendialog des Verarbeitungsauftrags stehen.

Beispiel
Ein Verarbeitungsauftrag zum Generieren einer Inventurzählliste für eine Liste von Lagerplätzen (Hintergrundanwendung com.cisag.app.inventory.physical.log.PhysicalInventoryCountProcessingund Aktion CreateCountLists) hat folgende Ausführungsergebnisse:

CisParameterList:
{batchJobGuids:null}
{com.cisag.pgm.base.CisApplicationCallResult:true}
{nextAction:0}
{nextParameters:null}
{outQueueEntryGuids:null}
{result:1}
{resultParmeters:CisParameterList:
{ResultNumberOfSuccessfulResults:1}
{ResultPhysicalInventoryCountListGuids:[[B@22833e99]}}
{state:2}
{waitingResult:0}

Wenn eine Aktivität auf den Verarbeitungsauftrag wartet, dann könnte getJobResultfolgende Hash-Tabelle zurückgeben:

{batchJobGuids=[103=null], com.cisag.pgm.base.CisApplicationCallResult=[B=true], nextAction=[N=0], nextParameters=[103=null], outQueueEntryGuids=[103=null], result=[N=1], resultParmeters=[H={ResultNumberOfSuccessfulResults=[N=1], ResultPhysicalInventoryCountListGuids=[L=[[G=0080EED3CBFB2E10B118AD1BAABC0000]]]}], state=[N=2], waitingResult=[N=0]}

Die eigentlichen Ergebnisse der aufgerufenen Hintergrundanwendung befinden sich im Variablen resultParmeters. (Bitte auf die Schreibweise achten!). Folgendes Skript in der Funktion closewertet diese aus, öffnet die generierten Inventurzähllisten und gibt deren Identifikation ins Protokoll aus:

function close(state as Number)
{
var rp as HashMap;
var cls as Number; /* number of count lists generated */
var clGuids as Guid[]; /* list of count list GUIDs */
var cl as CisObject(com.cisag.app.inventory.physical.obj.PhysicalInventoryCountList);

rp := cast(HashMap, getJobResult().resultParmeters);
cls := cast(Number, rp.ResultNumberOfSuccessfulResults);
clGuids := cast(Guid[], rp.ResultPhysicalInventoryCountListGuids);

echo(format(cls, "0") + " count list(s) generated:");
for (g : clGuids) {
cl := getByPrimaryKey(CisObject(com.cisag.app.inventory.physical.obj.PhysicalInventoryCountList), g);
echo(cl->PhysicalInventory->Type:code + "-" + cl->PhysicalInventory:number + " " + cl:number);
}
}

Webservices (getServiceResponse)

Der Knotentyp Webservice-Knoten wird in Prozessdefinitionen verwendet, um einen externen Webservice mit Hilfe der Hintergrundanwendung Service-Client aufzurufen. Die Hintergrundanwendung nutzt das HTTP-Protokoll und kann per JSON/REST und XML/SOAP externe Webservices aufrufen.

In der Funktion closekann die Skriptfunktion getServiceResponseverwendet werden, um die Ergebnisse auszuwerten. Die Funktion gibt den Ergebnisparameter responseBody der Hintergrundanwendung als eine Zeichenkette zurück. Die Funktion ist eine kompaktere Schreibweise für den Ausdruck getJobResult()["resultParmeters"]["responseBody"]. Voraussetzung einer Auswertung ist, dass die Aktivität auf den Verarbeitungsauftrag wartet, entweder durch das Aktivieren der Checkbox Auf Verarbeitungsauftrag warten auf dem Karteireiter Bearbeitung oder durch den Befehl setJobWaitFinish(true)in der Funktion create. Je nach ausgewählter Aktion der Hintergrundanwendung (JSON oder XML) können Sie die Funktionen parseJsonoder parseXmlverwenden, um die von getServiceResponsezurückgegebene Zeichenkette in eine Hash-Tabelle umzuwandeln.

Folgendes Beispiel gibt die vier Ergebnisvariablen data, errors, promise, und ready einer Aktivitätsdefinition des Typs Webservice-Knoten ins Protokoll aus:

function close(state as Number)
{
var response := parseJson(getServiceResponse());
echo((cast(HashMap, response.data));
echo((cast(String[],response.errors));
echo((cast(Guid, response.promise));
echo((cast(Boolean, response.ready));
}

Individuelle Prüfungen (environment)

Zusätzlich zu den übergebenen Parametern der Funktionen stellt eine individuelle Prüfung die Variable environmentmit dem Wert userGuidzur Verfügung. Mithilfe dieser Variable können Sie auswerten, für welchen Benutzer das Business Entity validiert wird. Folgendes Beispiel erlaubt nur dem zuständigen Mitarbeiter eines Beschaffungsauftrags sowie den der Workflowrolle MANAGERS zugeordneten Benutzern, Beschaffungsaufträge freizugeben. Für alle anderen Mitarbeiter bleibt die Freigabe unterbunden.

function validateHeader(
persistent as DataView(com.cisag.app.purchasing.order.model.PurchaseOrder),
current as DataView(com.cisag.app.purchasing.order.model.PurchaseOrder))
{
const OrderStatus as valueSet(com.cisag.app.general.OrderStatus);
if ((persistent:status=OrderStatus.ORDER_ENTERED or persistent:status=OrderStatus.ORDER_HELD or persistent:status=OrderStatus.ORDER_CANCELED or (persistent:status=OrderStatus.ORDER_INVALID and persistent:statusBackup=OrderStatus.ORDER_RELEASED)) and current:status=OrderStatus.ORDER_RELEASED) {
var authorizedUsers := resolveRole("MANAGERS");
if (not isNull(persistent:responsible))
authorizedUsers := union(authorizedUsers, list(persistent:responsible));
if (not contains(authorizedUsers, environment.userGuid))
sendMessage(null, "ERROR", "No authorization to release.");
}
}

Beachten Sie bitte, dass das Attribut statusBackupverwendet wird, wenn der Beschaffungsauftrag mehr Positionen umfasst, als in einer Datenbank-Transaktion freigegeben werden können. In diesem Fall wird mit der ersten Datenbank-Transaktion der Status des Beschaffungsauftrags auf Ungültig geändert, und das Attribut statusBackupbekommt den künftigen Status Freigegeben zugewiesen. Erst mit der letzten Datenbank-Transaktion wird der Status des Beschaffungsauftrags auf Freigegeben geändert.

Fehlerbehandlung

Komplexität von Ausdrücken beschränken

Die System-Skriptsprache ist für längere Berechnungen oder die Verarbeitung von größeren Datenmengen ungeeignet. Aus diesem Grund wird die Laufzeit von Bedingungen und Befehlen beschränkt.

Die Standardeinstellungen sind:

Operation Beschränkung Erläuterung
while 1.000.000 while-Schleifen brechen nach 1.000.000 Durchläufen ab.
getResultList

getCisObjectList

10.000 getResultList und getCisObjectList können bis zu 10.000 Zeilen oder Objekte abfragen.
call

@

100 call und @ können maximal 100 Mal rekursiv Aktivitätsdefinitionen aufrufen. Der Vorschlagswert kann nicht verändert werden.

Mit der System-Property com.cisag.pgm.workflow.MaxExpressionComplexitykönnen Sie die Prüfung der Komplexität verändern. Der Vorschlagswert ist 1.000. Die Grenzwerte aller Operationen bis auf die Begrenzung der Rekursionstiefe sind linear vom Wert dieser Property abhängig. Mit dem Wert 0 schalten Sie die Prüfung vollständig ab.

Behandlung von Laufzeitfehlern

Einige Fehler in Ausdrücken können bei der Prüfung des Skripts nicht erkannt werden.

Beispiel
Der Ausdruck a/bliefert einen Fehler, wenn b=0.

Laufzeitfehler in der Workflow-Engine haben die Meldungsklasse WFL. Fehler, die bei der Auswertung der Ausdrücke auftreten, werden abhängig von der Aktivitätsdefinition in das OLTP- oder Repository-Protokoll geschrieben. Das OLTP- bzw. Repository-Protokoll kann mit der Anwendung Meldungsprotokolle abgefragt werden. Wenn die Vorbedingung fehlerhaft ist, dann wird abhängig von der Aktivität eine Meldung in das OLTP- oder Repository-Protokoll geschrieben. Die Aktivität wird jedoch so behandelt, als ob die Vorbedingung erfüllt wäre.

Bei Fehlern in der Übergangsbedingung, der Berechnung der Bearbeiter oder im Befehlsblock wird keine neue Aktivität erzeugt. Eine Meldung wird in das Systemprotokoll geschrieben. Das Meldungsprotokoll sollte in regelmäßigen Abständen auf Fehler kontrolliert werden, insbesondere dann, wenn Aktivitäts­definitionen verändert oder neu erfasst wurden.

Erweiterung der System-Skriptsprache

Über eine vorgegebene Programmierschnittstelle kann die System-Skriptsprache um neue Befehle und Funktionen erweitert werden. Insbesondere wenn komplexe Bedingungen geprüft werden sollen, errei­chen Sie schnell die Grenzen der Skriptspra­che im Bezug auf die Ausdrucksfähigkeit oder Leistungsfähigkeit. In diesem Fall können Sie die Probleme über spezia­li­sierte Funk­tionen beheben.

Weitere Informationen finden Sie im Kapitel Erweitern der Skriptsprache der Dokumentation Schnittstellen zum Workflow-Management.

Czy ten artykuł był pomocny?