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:
- Aufbau und Syntax
- Deklarationen
- Informationsauswertung
- Fehlerbehandlung
- Erweiterung der System-Skriptsprache
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 Algorithmen 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 undefinierter 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 überprüft. Stimmt ein übergebener Wert nicht mit dem erwarteten Datentyp überein, wird eine Fehlermeldung ausgegeben.
Die System-Skriptsprache kennt die folgenden Datentypen:
- Boolean – Wahrheitswerte (
Boolean
) können nur die Wertetrue
für wahr undfalse
für falsch annehmen. Der Standardwert des Datentyps Boolean istfalse
. - Bytes – Der Datentyp
Bytes
sind binäre Daten mit beliebigem Inhalt. Dieser Datentyp kann insbesondere bei programmierten Ereignissen und Dateien als Parameter verwendet werden. Der Standardwert des Datentyps Bytes istnull
. - Class – Eine Klasse (
Class
) ist ein strukturierter Datentyp mit einer Menge von Attributen. Jedes Attribut hat einen Namen und einen Datentyp. Der Standardwert einer Klasse istnull
. - CisDate – Ein
CisDate
ist die Kombination eines Zeitpunkts mit einer Zeitzone. Der Standardwert des DatentypsCisDate
istnull
. - CisObjectReference – Business Objects werden mit den Datentypen
CisObject
oderCisObjectReference
verwaltet, Parts mit dem DatentypCisObject
. Referenzen auf Business Objects enthalten den Schlüssel des Business Objects. Der Standardwert des DatentypsCisObjectReference
istnull
. Um eine typisierteCisObjectReference
zu erhalten, geben Sie den Namen eines Business Objects in Klammern an. Wenn Sie keinen Namen angeben, erhalten Sie eine untypisierteCisObjectReference
.HinweisUm Skripte performant auszuwerten und unnötige Datenbankzugriffe zu vermeiden, sind auch alsCisObjectReference
deklarierte Variablen nur als Werte verfügbar, wie beim DatentypCisObject
. Möchten Sie den aktuellen Wert eines Business Object auswerten, dann sollten Sie es erneut öffnen, z. B. mithilfe der FunktionengetByPrimaryKey
odergetByBusinessKey
. - CisObject – Business Objects werden mit den Datentypen
CisObject
oderCisObjectReference
verwaltet, Parts mit dem DatentypCisObject
. Business Objects und ihre Parts sind auch als Werte verfügbar. Der Standardwert des DatentypsCisObject
ist null. Um ein typisiertesCisObject
zu erhalten, geben Sie den Namen eines Business Objects in Klammern an. Wenn Sie keinen Namen angeben, erhalten Sie ein untypisiertesCisObject
. - DataView – Objektsichten (
DataView
) sind eine Sicht auf den Zustand eines komplexen Business Entitys. Objektsichten werden insbesondere in individuellen Prüfungen verwendet. Der Standardwert des DatentypsDataView
istnull
. Um eine typisierteDataView
zu erhalten, geben Sie den Namen einer Objektsicht in Klammern an. Wenn Sie keinen Namen angeben, erhalten Sie eine untypisierteDataView
. - Guid – GUIDs werden häufig benötigt, um Business Objects über dessen Primärschlüssel zu identifizieren. Der Standardwert des Datentyps
Guid
istnull
. - 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üssel sind nur Zeichenketten erlaubt. Der Standardwert des DatentypsHashMap
ist eine leere Hash-Tabelle. - Number – Zahlen (
Number
) enthalten immer ein Vorzeichen. Sie können Nachkommastellen haben, die mit einem Punkt zu trennen sind. Der Standardwert des DatentypsNumber
ist0
. - String – Zeichenketten (
String
) können eine beliebige Länge haben. Der Standardwert des DatentypsString
ist eine leere Zeichenkette. - Timestamp – Ein Zeitpunkt (
Timestamp
) ist ein auf Millisekunden genauer Punkt in der Zeit. Alle Zeitangaben werden in Zeitpunkten abgebildet. Der Standardwert des DatentypsTimestamp
ist die KonstanteUNDEFINED_DATE
. - Unknown – Dem Datentyp
Unknown
kann jeder beliebige andere Datentyp zugeordnet werden. Der Standardwert des DatentypsUnknown
istnull
.
Automatische Umwandlung von einfachen Datentypen
Einige einfache Datentypen wie Number
, Boolean
und Guid
werden bei Bedarf automatisch in Zeichenketten umgewandelt. String
erwartet und ein Wert vom Typ Number
übergeben wird, so wird die Zahl in eine Zeichenkette umgewandelt.
Beachten Sie bitte, dass der Datentyp vom ersten Term eines Ausdrucks bestimmt wird.
var t := "UB" + 40;
var t := 101 + "ers";
Weitere Datentypen können mithilfe der Funktion cast
umgewandelt 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 CisObject
bzw. CisObjectReference
verwenden. Nur bei einer Typisierung wird die korrekte Verwendung von Attributen und deren Datentypen geprüft.
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 CisObject
bzw. CisObjectReference
wird 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 Elementdatentyp 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.
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 isEmpty
geprüft werden.
isEmpty(new(String[]))
gibt den Wahrheitswert true
zurück.Die Skript-Funktion list
erzeugt 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.
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 Number
umgewandelt 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.
add
fü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 add
Elemente unterschiedlicher Datentypen zuweisen. Einer Liste, die den Datentypen Unknown[]
besitzt, können Elemente beliebiger Datentypen hinzugefügt werden, da alle anderen Datentypen in Unknown
umgewandelt werden können.
Somit lässt sich z. B. eine Parameterliste auch dann für die Funktionen getCisObjectList
und getResultList
erzeugen, 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 getCisObjectList
die 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 cast
ggf. 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 null
ist, so ist dieser Wert undefiniert. Viele Funktionen und Operatoren in der System-Skriptsprache liefern als Ergebnis null
, wenn einer der Parameter null
ist. Wenn also auf Basis eines undefinierten Wertes etwas berechnet werden soll, so ist auch das Ergebnis undefiniert. Mit den speziellen Funktionen isNull
und first
kann ein Wert null
gesondert behandelt werden.
Eine Übergangsbedingung in einer Aktivitätsdefinition gilt beim Wert Die Übergangsbedingung Die Übergangsbedingungen , null
als 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
. 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.isNull(parameters.object:responsible) or not(contains(resolvePartner(parameters.object:responsible)
,parameters.userGuid))
undnot(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.
parameters.object->Responsible:number
besitzt den undefinerten Wert null
, wenn im dem von parameters.object
referenzierten Business Object kein zuständiger Mitarbeiter hinterlegt ist.Die System-Skriptsprache umfasst zwei Funktionen isNull
und 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_GUID
stellt einen ungültigen Wert für den DatentypGuid
dar. - MAX_DATE – Der größte darstellbare Zeitpunkt (
Timestamp
). DasMAX_DATE
kann z. B. für Gültigkeitsbereiche verwendet werden, die nach oben offen sind.MAX_DATE
entspricht dem konstantenMAX_TIME_STAMP
einer OQL-Abfrage. - MIN_DATE – Der kleinste darstellbare Zeitpunkt (
Timestamp
). DasMIN_DATE
kann z. B. für Gültigkeitsbereiche verwendet werden, die nach unten offen sind.MIN_DATE
entspricht dem konstantenMIN_TIME_STAMP
einer OQL-Abfrage. - UNDEFINED_DATE – Ein undefinierter Zeitpunkt (
Timestamp
). DasUNDEFINED_DATE
wird z. B. für Zeitpunkte verwendet, bevor ein konkreter Wert zugewiesen wurde. Zum Beispiel der Zeitpunkt der letzten Änderung eines Business Objects (im AttributupdateInfo.updateTime
), welches seit dem Erfassen nicht mehr geändert wurde.UNDEFINED_DATE
entspricht dem konstantenUNDEFINED_TIME_STAMP
einer OQL-Abfrage. - ZERO_GUID – Die
ZERO-GUID
wird 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_GUID
entspricht dem KonstantenZEROGUID
einer OQL-Abfrage.
CisDate
den kleinsten bzw. den größten darstellbaren Wert besitzt, können Sie die Funktionen isMinDate
und isMaxDate
verwenden.Kommentare
Kommentare werden mit /*
eingeleitet und mit */
abgeschlossen. Kommentare 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 true
ersetzen.
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 kombiniert werden. Wie üblich haben dabei die Operatoren *
,/
und %
eine höhere Bindung als die Operatoren +
und -
. Operatoren mit gleicher Bindung werden von links nach rechts ausgeführt.
1 + 3
und 3 * 4 - 8
sind gültige Terme mit diesen Operatoren und liefern beide das Ergebnis 4
zurück.
1 * "a"
liefert null
zurü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.
"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
, Timestamp
und Boolean
möglich.
Die linke Seite einer Vergleichsoperation bestimmt den verglichenen Datentyp.
3 <= 1 + 2
ist 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.
(1 = 3) = false
ist 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.
("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 toTimestamp
das CisDate in einen Zeitpunkt umwandeln.
toTimestamp(today()) <= now()
ist eine wahre Bedingung.Bedingungen
Bedingungen können beliebig mit den logischen Operatoren AND
und OR
verknü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 AND
und OR
können beliebig kombiniert werden. Wie üblich besitzt dabei der Operator AND
eine höhere Bindung als der Operator OR
.
1 = 1 AND 3 = 3
ist eine wahre Bedingung.
1 = 1 OR 2 = 2 AND 3 = 4
ist eine wahre Bedingung.
1 = 0 OR 2 = 2 AND 3 = 4
ist falsche Bedingung.
a AND b
und a und b
sind 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.
(2 + 3) * 2 = 10
ist 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 Operatoren:
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 Index 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-Tabelle 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.
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 null
zurück.
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 null
zurü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 Ergebnis 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.
loadPartner("10010"):address.city
ist ein gültiger Zugriff auf das Attribut city
in dem komplexen Attribut address
des 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 name
in dem komplexen Attribut organizationalUnit
des Business Objects Partner mit der Identifikation 10010.
loadPartner("10010")->Language:isoCode
ist ein gültiger Zugriff auf das Attribut isoCode
desjenigen Business Objects, das durch die Beziehung Language
von dem Business Object Partner mit der Identifikation 10010 referenziert wird.
Um Attribute, deren Namen mit einem Unterstrich beginnen, auszuwerten, können Sie die Funktion getAttribute
verwenden. Bevor Sie das Ergebnis verwenden, sollten Sie es in einen zum Attribut passenden Datentyp umwandeln.
loadCurrency(getCorporateCurrency(cast(Guid, getAttribute(parameters.object, "_organization")))):isoCode
gibt den ISO-Code der Leitwährung der Organization zurück, in dessen Kontext das vom parameters.object
referenzierte 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 call
aufgerufen 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.
isPythagorean
besitzt die Parameter A
, B
und C
vom Typ Number
sowie den Rückgabewert RESULT
vom 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 liefert. In der System-Skriptsprache werden Befehle durch ein Strichkomma (;
) getrennt.
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.
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.
/** * 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 := "";
Variablen
Alle verwendeten Variablen und Konstanten müssen deklariert werden. Variablen können mit einem Typ oder einem Initialwert deklariert werden. Wenn ein Typ angegeben wird, so besitzt die Variable den Standardwert des Typs als Initialwert. Wenn eine Variable über einen Term deklariert wird, so hat diese den Ergebniswert des Terms als Wert und dessen Datentypen als Datentyp.
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 Class
und darin für jeden Valueset-Eintrag eine Konstante mit dem technischen Namen des Eintrags und dessen ID.
parameters.object
referenzierter 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 Verwendung von Typen erleichtert durch die besseren Abstraktionsmöglichkeiten das Verständnis des Programms. Für jede Verwendung von Klassen muss ein Typ definiert werden. Das Schlüsselwort class
kann nur bei einer Typdeklaration verwendet werden.
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";
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 Zuweisung. 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 Variablen.
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 Elementen 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 Anweisungsblock 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 null
als Parameter bekommen.
{ x := 2; x := x * x + 3; }
Bedingter Befehl (if)
Der bedingte Befehl if
fü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.
x := -13; if (x < 0) x := 0;
Bedingter Befehl mit Alternative (if … else)
Der bedingte Befehl mit Alternative if else
fü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 else
ausgeführt. Wenn die Bedingung nicht wahr ist, so wird der Befehl vor dem else
übersprungen und der Befehl nach dem else
ausgeführt.
x := 13; if (x < 0) { x := -1; } else if (x > 0) { x := 1; }
Schleife mit Bedingung (while)
Die Schleife mit Bedingung while
fü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.
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.
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.
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.
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.
r_text
beendet 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 ParserFunctions
sind 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 create von 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_REPOSITORY und WF_ACTIVITY_REPOSITORY . Verwendbar in Aktivitätsdefinitionen für Aktivitäten in der Repository-Datenbank. |
WF_OLTP |
Entspricht den Verwendungskontexten WF_TRANSITION_OLTP und WF_ACTIVITY_OLTP . Verwendbar in Aktivitätsdefinitionen für Aktivitäten in einer OLTP-Datenbank. |
OLTP |
Entspricht den Verwendungskontexten WF_SYS_SCRIPT_OLTP und WF_OLTP . D. h. der Verwendungskontext setzt keine Aktivitätsdefinition, aber eine OLTP-Datenbank voraus. Hierzu gehören Funktionen wie z. B. loadPartner und 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 , getByPrimaryKey und getCisObjectList . |
Weitere Informationen und Beispiele zu den Funktionen und Befehlen finden Sie in folgenden Dokumentationen:
- System-Skriptsprache: Allgemeine Funktionen
Funktionen des VerwendungskontextsALL
.
- System-Skriptsprache: OLTP-Funktionen
Funktionen des VerwendungskontextsOLTP
oderSYS_SCRIPT_OLTP
.
- System-Skriptsprache: Workflow-Funktionen
Funktionen des VerwendungskontextsWF_REPOSITORY
,WF_OLTP
,WF_ACTIVITY_REPOSITORY
,WF_ACTIVITY_OLTP
,WF_TRANSITION_REPOSITORY
oderWF_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 Eingangsparameter. Diese Voraussetzungen werden wie folgt ausgedrückt:
R f(D1 p1, ..., Dn pn)
Wenn der Datentyp völlig frei ist, so wird der Datentyp Unknown
verwendet.
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 create wird 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 applyDefaults vor der Funktion create aufgerufen. Bei allen anderen Aktivitäten erfolgt der Aufruf erst, nachdem die Funktion create aufgerufen wurde.
Da der Zweck der Funktion |
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 state gibt den künftigen Status der Aktivität wieder.Die Funktion validate liefert einen Rückgabewert vom Datentyp Boolean zurü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 sendMessage die Ü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 validate ist, 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 validatePrecondition wird 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 |
validatePostcondition |
Die Funktion validatePostcondition wird vor dem Erledigen der Aktivität aufgerufen, wenn im Feld Nachbedingung der Wert Deklaration ausgewählt ist.
Der Parameter Die Funktion Die Funktion |
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 |
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 |
close |
Die Funktion close wird 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.
const MaxAmount := "123"; function helloWorld () as String { return "Hello World!"; }
Die Konstante MaxAmount
und die Funktion helloWorld
kö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:
- Globale Deklarationen der Prozessdefinition
- Globale Deklarationen der Aktivitätsdefinition (außerhalb der Funktionen)
- applyDefaults
- validate
- create
- validatePrecondition
- close
Die Funktionen applyDefaults
und validate
werden 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:
- Globale Deklarationen der Prozessdefinition
- Globale Deklarationen der Aktivitätsdefinition (außerhalb der Funktionen)
- Übergangsbedingung
- create
- Anwendungsparameter
- Ausdruck für Bearbeiter
- validatePrecondition
- applyDefaults
- validate
- validatePostcondition
- close
Die Funktion validatePrecondition
wird bei jedem Statuswechsel der Aktivität aufgerufen, d. h. der Aufruf erfolgt in der Regel mehrmals.
Die Funktionen applyDefaults
und validate
werden 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 validatePostcondition
nicht 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 create
auf 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.
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 editors
wird im Feld Ausdruck für Bearbeiter verwendet. Die Variable customer
wird als Wert für den Parameter Partner der Anwendung com.cisag.app.general.partner.ui.PartnerMaintenance
verwendet.
Um die Befehle in Deklarationen zu überführen, werden die Deklaration der Variablen editors
und customer
außerhalb der Funktion create
platziert.
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.
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 persistent
und current
kö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 extension
automatisch 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 create
noch keine Aktivität vorhanden. Daher stehen die Werte der Variablen activity
nicht 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)
- Parameter (parameters)
- Prozess (process)
- Aktivität (activity)
- Aktivitätsdefinition (definition)
- Aktionsparameter (actionParameters)
- Aktivitätsergebnisse (results)
- Dialogsteuerung (dialog)
- Funktionsaufrufe (parameters und result)
- Hintergrundanwendungen (getJobResult)
- Webservices (getServiceResponse)
- Individuelle Prüfungen (environment)
Ereignis (event)
Besitzt die Aktivitätsdefinition einer Ereignisdefinition, dann enthält die Variable event
eine 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.EventTypeLimited definiert. Folgende Werte sind hier relevant:
|
subtype |
Die Variable subtype enthält den Subtyp des Ereignisses. Bei programmierten Ereignissen ist dies der Wert des ValueSet-Eintrags. Ist kein ValueSet dem Ereignis zugeordnet, dann ist der Wert null . Beim Ereignistyp Business Entity sind die möglichen Wert im ValueSet com.cisag.sys.kernel.ObjectChangeType definiert:
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. 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 |
guid |
Die Variable guid enthält die GUID des programmierten Ereignisses oder die GUID des Business Objects beim Ereignis Business 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 Ereignis 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 parameters enthä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:
Die Variable |
Parameter (parameters)
In Abhängigkeit des Typs und Subtyps des Ereignisses enthält die Variable parameters
eine 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.
com.cisag.pgm.workflow.GenericOLTPEvent
besitzt die beiden Parameter name
und parameters
, die als String
bzw. 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:code
verwendet werden.
Folgende Zuweisung übernimmt den Wert des Hash-Tabellen-Eintrags user
als Prozessauslöser:
process.Initiator := cast(String, parameters.parameters.user);
Da die Hash-Tabelle untypisiert ist, müssen die Einträge mithilfe der Funktion cast
in 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 Business Objects ab.
Variable | Wert |
userGuid |
Die Variable userGuid enthält die GUID des Benutzers, der das Business Object verändert hat.
Bei einem Ereignis des typs Business Entity ist der Prozessauslöser in
|
object |
Die Variable object enthält eine Referenz auf das veränderte Business Object. Die Variable object gibt den aktuellen Zustand des Business Objects zum Zeitpunkt der Auswertung wider. Beim Subtyp Löschen hat object den Wert null .Die Variable object kann 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 oldObject enthä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
|
newObject |
Die Variable newObject enthält den Wert des veränderten Business Objects unmittelbar nach der Änderung. 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:
|
entity |
Ist das veränderte Business Object ein Dependent, dann enthält die Variable entity eine Referenz auf das mit dem Business Object über die Beziehung _entity verkü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 Ist das Business Object kein Dependent, dann ist |
oldEntity |
Ist das veränderte Business Object ein Dependent, dann enthält die Variable oldEntity den Wert des mit dem Business Object über die Beziehung_entity verküpften Business Entitys unmittelbar vor der Änderung.
Ist das Business Object kein Dependent, dann ist |
newEntity |
Ist das veränderte Business Object ein Dependent, dann enthält die Variable newEntity den Wert des mit dem Business Object über die Beziehung _entity verküpften Business Entitys unmittelbar nach der Änderung.
Ist das Business Object kein Dependent, dann ist |
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
Folgende Übergangsbedingung prüft, ob der Benutzer der zuständige Mitarbeiter des Belegs ist. Ist dies nicht der Fall, dann ist die Übergangsbedingung
|
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
|
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 parameters
auch 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.
|
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 process
eine 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 create eines 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 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 Initiator enthält den Prozessauslöser. Der Prozessauslöser steht erst ab der Funktion close des 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.
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.
|
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 close des Startknotens zur Verfügung. Bei einem manuellen Prozess mit Aktivitätsergbnissen im Startknoten, kann der Owner in den Funktionen applyDefaults und validate nicht ausgewertet werden.
Der Wert kann durch Zuweisung eines Benutzernamens oder der Identifikation einer Workflowrolle geändert werden.
Die Herkunft des Prozessverantwortlichen kann im Attribut |
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 |
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 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
|
Text1 |
Die Variable Text1 enthält das erste allgemeine Ergebnisattribut für Zeichenketten. Der Wert kann durch Zuweisung beliebig geändert werden.
|
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.
|
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 applyDefaults
und validate
eines Startknotens besitzen alle Attribute noch ihre Standardwerte. Da der Startknoten keinen Vorgänger hat, besitzen die Attribute previousStep
und previousSteps
immer den Standardwert null
in einem Startknoten.
In der Funktion create
eines Startknotens besitzen die Attribute OrganizationalUnit
und 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 event
und parameters
auswerten.
In der Funktion close
eines Startknotens sowie in allen Funktionen der darauf folgenden Aktivitäts- und Ereignisknoten besitzen sämtliche Attribute außer OrganizationalUnit
und Database
Werte aus dem aktuellen Kontext. Möchten Sie diese beiden Werte zu einem späteren Zeitpunkt im Prozess auswerten, sollten Sie sie in der Funktion close
in Prozessvariablen speichern.
Aktivität (activity)
Wenn die Übergangsbedingung erfüllt ist und die Funktion create
ausgeführt wurde, wird die neue Aktivität erzeugt. Ab diesem Zeitpunkt stellt die Variable activity
eine 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 close
zur Verfügung, die erst nach dem Erledigen der Aktivität persistent gespeichert werden. So können Sie z. B. mithilfe des Attributs activity:completeUser
auswerten, welcher Benutzer die Aktivität gerade erledigt.
Nach der Ausführung der Funktion create
können Sie den Prozess über die Beziehung Process auswerten. So bestimmt z. B. der Ausdruck
activity->Process:code
die Identifikation des Prozesses.
Aktivitätsdefinition (definition)
Die Variable definition
enthält eine Referenz auf die Aktivitätsdefinition, die das Ereignis empfangen hat und mit der die neue Aktivität erzeugt werden soll. Diese Variable steht überall in einer Aktivitätsdefinition zur Verfügung.
Mithilfe der Übergangsbedingung parameters.name = definition:code
in einer Aktivitätsdefinition für das programmierte Ereignis com.cisag.pgm.workflow.GenericOLTPEvent
kann 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 definition
kann auch die mit der Aktivitätsdefinition verknüpfte Prozessdefinition ausgewertet werden. So bestimmt z. B. der Ausdruck
definition->ProcessDefinition:code
die Identifikation der Prozessdefinition.
Aktionsparameter (actionParameters)
Wenn die Funktion create
ausgeführt und die Aktivität erzeugt wurde, dann enthält die die Variable actionParameters
eine Hash-Tabelle mit den Werten aller Anwendungsparameter. Diese Variable kann z. B. in einer Vorbedingung oder in der Funktion close
ausgewertet werden.
Aktivitätsergebnisse (results)
Wenn die Funktion create
ausgeführt und die Aktivität erzeugt wurde, dann enthält die die Variable results
eine Hash-Tabelle mit den Werten aller Aktivitätsergebnisse. Die Variable results
wird oft in der Funktion close
verwendet, um die Aktivitätsergebnisse in Prozessvariablen zu speichern.
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 validate
wird 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 _id
hinter dem Namen des Aktivitätsergebnisses bewirkt, dass die farbige Ecke für die Meldung im Kommentarfeld erscheint.
In der Funktion close
werden 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.approvalStatus
möglich. Der Unterschied ist, dass durch eine solche Zuweisung die Prozessvariable process.approvalStatus
ein 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 parameters
folgende 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 page eine 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 parameters
und 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 null
und können durch die Aktivitätsdefinition berechnet werden.
ITEMNUMBER
mit der Bezeichnung Artikelnummer und dem Datentyp Zeichenkette sowie den Rückgabewert PRICE
mit der Bezeichnung Preis und dem Datentyp Nummer. In diesem Fall gibt es die folgenden Variablen:
parameters.ITEMNUMBER result.PRICE
Der Wert der Variablen ITEMNUMBER
wird beim Aufruf der Aktivitätsdefinition gesetzt. Der Wert der Variablen PRICE
muss 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 close
kann die Skriptfunktion getJobResult
verwendet 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.
com.cisag.app.inventory.physical.log.PhysicalInventoryCountProcessing
und 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 getJobResult
folgende 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 close
wertet 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 close
kann die Skriptfunktion getServiceResponse
verwendet 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 parseJson
oder parseXml
verwenden, um die von getServiceResponse
zurü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 environment
mit dem Wert userGuid
zur 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 statusBackup
verwendet 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 statusBackup
bekommt 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
|
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.MaxExpressionComplexity
kö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.
a/b
liefert 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ätsdefinitionen 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, erreichen Sie schnell die Grenzen der Skriptsprache im Bezug auf die Ausdrucksfähigkeit oder Leistungsfähigkeit. In diesem Fall können Sie die Probleme über spezialisierte Funktionen beheben.
Weitere Informationen finden Sie im Kapitel Erweitern der Skriptsprache der Dokumentation Schnittstellen zum Workflow-Management.