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

Einige einfache Datentypen wie

Number
Number,
Boolean
Booleanund
Guid
Guidwerden bei Bedarf automa­tisch in Zeichenketten umgewandelt.

Beispiel
Wenn eine Funktion einen Parameter vom Typ
String
Stringerwartet und ein Wert vom Typ
Number
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;
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";
var t := 101 + "ers";

Weitere Datentypen können mithilfe der Funktion

cast
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

CisObject
CisObjectbzw.
CisObjectReference
CisObjectReferenceverwenden. Nur bei einer Typisierung wird die korrekte Verwendung von Attributen und deren Datentypen geprüft.

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

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

Bei einem untypisierten

CisObject
CisObjectbzw.
CisObjectReference
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]
String[10]ist eine Liste von Zeichenketten mit 10 Elementen.

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

Unknown[]
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
isEmptygeprüft werden.

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

Die Skript-Funktion

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

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

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

list()
list()erzeugt eine neue leere Liste vom Datentyp
Unknown[]
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
add
addführt zu einem Fehler, da eine Zeichenkette nicht in eine Zahl umgewandelt werden kann.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
var list1 := Number[];
add(list1, "500");
var list1 := Number[]; add(list1, "500");
var list1 := Number[];
add(list1, "500");

Ist die Liste dagegen als

String[]
String[]deklariert, dann ist der Ausdruck
add(list1, 500)
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[]
Unknown[]deklarieren und mithilfe der Funktion
add
addElemente unterschiedlicher Datentypen zuweisen. Einer Liste, die den Datentypen
Unknown[]
Unknown[]besitzt, können Elemente beliebiger Datentypen hinzugefügt werden, da alle anderen Datentypen in
Unknown
Unknownumgewandelt werden können.

Somit lässt sich z. B. eine Parameterliste auch dann für die Funktionen

getCisObjectList
getCisObjectListund
getResultList
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
getCisObjectList
getCisObjectListdie ersten 100 internen Personen zu ermitteln und auf der Konsole auszugeben:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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);
}
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); }
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
castggf. typisiert werden, bevor sie verwendet werden können, wie das folgende Beispiel zeigt.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
var myList as Unknown[];
add(myList, 800);
add(myList, "°");
var song := cast(String, myList[0]) + cast(String, myList[1]);
var myList as Unknown[]; add(myList, 800); add(myList, "°"); var song := cast(String, myList[0]) + cast(String, myList[1]);
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
null. Der Wert
null
null ist keinem Datentyp zugeordnet. Wenn ein Wert
null
nullist, so ist dieser Wert undefiniert. Viele Funktionen und Operatoren in der System-Skriptsprache liefern als Ergebnis
null
null, wenn einer der Parameter
null
nullist. Wenn also auf Basis eines undefinierten Wer­tes etwas berechnet werden soll, so ist auch das Ergebnis undefiniert. Mit den spe­ziellen Funktionen
isNull
isNullund
first
firstkann ein Wert
null
nullgesondert behandelt werden.

Eine Übergangsbedingung in einer Aktivitätsdefinition gilt beim Wert

null
nullals nicht erfüllt (
false
false). Eine Vorbedingung dagegen gilt beim Wert
null
null als erfüllt (
true
true). Prüfen Sie daher besonders optionale Attribute mit Fremdschlüsseln auf den Wert
null
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)
not(contains(resolvePartner(parameters.object:responsible),
parameters.userGuid))
parameters.userGuid))besitzt den undefinerten Wert
null
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)
isNull(parameters.object:responsible) or not(contains(resolvePartner(parameters.object:responsible),
parameters.userGuid))
parameters.userGuid))und

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

,

parameters.userGuid))
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
null verfolgt, führt zu einem undefinierten Ergebnis.

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

Die System-Skriptsprache umfasst zwei Funktionen

isNull
isNullund
first
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
    INVALID_GUIDstellt einen ungültigen Wert für den Datentyp
    Guid
    Guiddar.
  • MAX_DATE – Der größte darstellbare Zeitpunkt (
    Timestamp
    Timestamp). Das
    MAX_DATE
    MAX_DATEkann z. B. für Gültigkeitsbereiche verwendet werden, die nach oben offen sind.
    MAX_DATE
    MAX_DATE entspricht dem konstanten
    MAX_TIME_STAMP
    MAX_TIME_STAMPeiner OQL-Abfrage.
  • MIN_DATE – Der kleinste darstellbare Zeitpunkt (
    Timestamp
    Timestamp). Das
    MIN_DATE
    MIN_DATEkann z. B. für Gültigkeitsbereiche verwendet werden, die nach unten offen sind.
    MIN_DATE
    MIN_DATEentspricht dem konstanten
    MIN_TIME_STAMP
    MIN_TIME_STAMPeiner OQL-Abfrage.
  • UNDEFINED_DATE – Ein undefinierter Zeitpunkt (
    Timestamp
    Timestamp). Das
    UNDEFINED_DATE
    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
    updateInfo.updateTime), welches seit dem Erfassen nicht mehr geändert wurde.
    UNDEFINED_DATE
    UNDEFINED_DATEentspricht dem konstanten
    UNDEFINED_TIME_STAMP
    UNDEFINED_TIME_STAMPeiner OQL-Abfrage.
  • ZERO_GUID – Die
    ZERO-GUID
    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_GUID
    ZERO_GUIDentspricht dem Konstanten
    ZEROGUID
    ZEROGUIDeiner OQL-Abfrage.
Hinweis
Um zu überprüfen, ob ein Wert vom Datentyp
CisDate
CisDateden kleinsten bzw. den größten darstellbaren Wert besitzt, können Sie die Funktionen
isMinDate
isMinDateund
isMaxDate
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/**
* 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
*/
/** * 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 */
/**
* 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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/**
* 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 := "";
/** * 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 := "";
/**
* 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
true). Da eine Bedingung, die aus nur einem Kommentar besteht, nicht leer ist, gilt folgende Übergangsbedingung als nicht erfüllt (
false
false), auch wenn sie keinen auswertbaren Ausdruck enthält, und erzeugt somit keine Aktivität.

/* parameters.object:status = OrderStatus.RELEASED */
/* 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
trueersetzen.

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

Terme und Bedingungen

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

Beispiele von Termen:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
a * a + b * b
max(a, b) * min(c, d)
a * a + b * b max(a, b) * min(c, d)
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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
a * a + b * b = c * c
max(a, b) > 0
parameters.object:updateInfo.createUser <> parameters.userGuid
a * a + b * b = c * c max(a, b) > 0 parameters.object:updateInfo.createUser <> parameters.userGuid
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
null. Ist einer der Operanden
null
null, so ist das Ergebnis der Operation ebenfalls
null
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 + 3
1 + 3und
3 * 4 - 8
3 * 4 - 8sind gültige Terme mit diesen Operatoren und liefern beide das Ergebnis
4
4zurück.

1 * "a"
1 * "a" liefert
null
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"
"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
Number,
String
String,
CisDate
CisDate,
Timestamp
Timestampund
Boolean
Booleanmöglich.

Die linke Seite einer Vergleichsoperation bestimmt den verglichenen Datentyp.

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

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

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

1 > "a"
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) = false
(1 = 3) = falseist eine wahre Bedingung.

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

true = false
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)
("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
toTimestampdas CisDate in einen Zeitpunkt umwandeln.

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

Bedingungen können beliebig mit den logischen Operatoren

AND
ANDund
OR
ORverknüpft werden:

Operator Erläuterung
a AND b
AND
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
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
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
ANDund
OR
ORkönnen beliebig kombiniert werden. Wie üblich be­sitzt dabei der Operator
AND
ANDeine höhere Bindung als der Operator
OR
OR.

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

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

1 = 0 OR 2 = 2 AND 3 = 4
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 b
a AND bund
a und b
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 = 10
(2 + 3) * 2 = 10ist eine wahre Bedingung.

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

(1 = 1 OR 3 < 1) AND 2 = 2
(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
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
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
null.

Beide Arten des Zugriffs auf Hash-Tabellen sind äquivalent. Der Zugriff mit Punkt (

b.a
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"]
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), ("x1", 11), ("x2", 12) , ("x3", 13)}

h.a = 1
h.a = 1 ist eine wahre Bedingung.

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

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

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

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

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

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

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

l[2 * 3] = "a"
l[2 * 3] = "a"liefert den Wert
null
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
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
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.city
loadPartner("10010"):address.cityist ein gültiger Zugriff auf das Attribut
city
cityin dem komplexen Attribut
address
addressdes Business Objects Partner mit der Identifikation 10010.

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

loadPartner("10010")->Language:isoCode
loadPartner("10010")->Language:isoCode ist ein gültiger Zugriff auf das Attribut
isoCode
isoCodedesjenigen Business Objects, das durch die Beziehung
Language
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

getAttribute
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")))):isoCode
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.object
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
call
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
isPythagorean
isPythagoreanbesitzt die Parameter
A
A,
B
B und
C
C vom Typ
Number
Number sowie den Rückgabewert
RESULT
RESULTvom Typ
Boolean
Boolean. Die Aktivitätsdefinition wird wie folgt aufgerufen:

var result := @isPythagoreanTheorem(A:=3, B:=4, C:=5).RESULT;
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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
echo(definition:code);
setMailRecipientsTo("somebody@localhost.local");
echo(definition:code); setMailRecipientsTo("somebody@localhost.local");
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>
var <VariableName> as <Type>
Variablendeklaration (Term)
var <VariableName> := <Expression>
var <VariableName> := <Expression>
Konstantendeklaration
const <VariableName> := <Expression>
const <VariableName> := <Expression>
Value-Set-Deklaration
const <VariableName> as valueSet(<Name>)
const <VariableName> as valueSet(<Name>)
Typdefinition
type <TypeName> as <Type>
type <TypeName> as <Type>
Typdefinition (class)
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
type <TypeName> as class {
<AttributeName> as <Type>;
...
<AttributeName> as <Type>;
}
type <TypeName> as class { <AttributeName> as <Type>; ... <AttributeName> as <Type>; }
type <TypeName> as class {
<AttributeName> as <Type>;
...
<AttributeName> as <Type>;
}
Zuweisung
<VariableName> := <Expression>
<VariableName> := <Expression>
Bedingter Befehl
if (<Condition>) <Command>
if (<Condition>) <Command>
Bedingter Befehl mit Alternative
if (<Condition>) <Command> else <Command>
if (<Condition>) <Command> else <Command>
Schleife mit Bedingung
while (<Condition>) <Command>
while (<Condition>) <Command>
Schleife über alle Elemente
for (<VariableName> : <List>) <Command>
for (<VariableName> : <List>) <Command>
Schleife über alle Elemente mit Typisierung
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
for (<VariableName> as <Type> : <List>)
<Command>
for (<VariableName> as <Type> : <List>) <Command>
for (<VariableName> as <Type> : <List>)
<Command>
Befehl beenden
return
return
Funktion beenden
return <Expression>
return <Expression>
Anweisungsblock
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
<Command>
...
<Command>
}
{ <Command> ... <Command> }
{
<Command>
...
<Command>
}

Die System-Skriptsprache umfasst auch die Funktion

if
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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/**
* 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 := "";
/** * 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 := "";
/**
* 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;
var n as Number;

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

var m := 1 + 5;
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>)
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
Classund darin für jeden Valueset-Eintrag eine Konstante mit dem technischen Namen des Eintrags und dessen ID.

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const OrderStatus as valueSet(com.cisag.app.general.OrderStatus);
function create()
{
if (parameters.object:status = OrderStatus.RELEASED)
echo(valueSetName(OrderStatus, parameters.object:status);
}
const OrderStatus as valueSet(com.cisag.app.general.OrderStatus); function create() { if (parameters.object:status = OrderStatus.RELEASED) echo(valueSetName(OrderStatus, parameters.object:status); }
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

class
classkann nur bei einer Typdekla­ration verwendet werden.

Beispiel
Definition und Verwendung unterschiedlicher Datentypen:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
type PartnerCode as String;
type PartnerCodeList as PartnerCode[];
type WeekdaySum as Number[7];
var code as PartnerCode;
code := "4711";
type PartnerCode as String; type PartnerCodeList as PartnerCode[]; type WeekdaySum as Number[7]; var code as PartnerCode; code := "4711";
type PartnerCode as String;
type PartnerCodeList as PartnerCode[];
type WeekdaySum as Number[7];

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

Definition und Verwendung einer Klasse:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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";
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";
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;
x := 2;

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

x := x * x + 3;
x := x * x + 3;

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
var l as String[2];
l[0] := "Hallo";
l[1] := "Welt";
var l as String[2]; l[0] := "Hallo"; l[1] := "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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
var c as HashMap;
c.a := "X";
c["a"] := "X";
var c as HashMap; c.a := "X"; c["a"] := "X";
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

null
nullals Parameter bekommen.

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
x := 2;
x := x * x + 3;
}
{ x := 2; x := x * x + 3; }
{
x := 2;
x := x * x + 3;
}

Bedingter Befehl (if)

Der bedingte Befehl

if
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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
x := -13;
if (x < 0)
x := 0;
x := -13; if (x < 0) x := 0;
x := -13;
if (x < 0)
x := 0;

Bedingter Befehl mit Alternative (if … else)

Der bedingte Befehl mit Alternative

if else
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
else
elseausgeführt. Wenn die Bedingung nicht wahr ist, so wird der Befehl vor dem
else
else übersprungen und der Befehl nach dem
else
else ausgeführt.

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
x := 13;
if (x < 0) {
x := -1;
} else if (x > 0) {
x := 1;
}
x := 13; if (x < 0) { x := -1; } else if (x > 0) { x := 1; }
x := 13;
if (x < 0) {
x := -1;
} else if (x > 0) {
x := 1;
}

Schleife mit Bedingung (while)

Die Schleife mit Bedingung

while
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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
var i := 10;
var r := 0;
while (i > 0) {
r := r + i:
i := i - 1;
}
var i := 10; var r := 0; while (i > 0) { r := r + i: i := i - 1; }
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
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
var l := list(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
var r := 0;
for (e : l) {
r := r + e:
}
var l := list(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); var r := 0; for (e : l) { r := r + e: }
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
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
as in einen bestimmten Typ umgewandelt werden.

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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);
}
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); }
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
return beendet die aktuell ausgeführte Funktion.

Beispiel

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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;
}
}
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; } }
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
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_text
r_textbeendet die Funktion und übergibt das Ergebnis an den Aufrufer.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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;
}
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; }
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
ParserFunctionssind die möglichen Gültigkeitsbereiche in Form von Konstanten definiert.

Verwendungskontext Beschreibung
SYS_SCRIPT_OLTP
SYS_SCRIPT_OLTP
Verwendbar in Skript-Objekten, individuellen Prüfungen und individuellen Hook-Implementierungen im Kontext einer OLTP-Datenbank.
WF_TRANSITION_REPOSITORY
WF_TRANSITION_REPOSITORY
Verwendbar in Übergangsbedingungen und in der Funktion
create
createvon Aktivitätsdefinitionen für Aktivitäten in der Repository-Datenbank.
WF_TRANSITION_OLTP
WF_TRANSITION_OLTP
Verwendbar in Übergangsbedingungen und in der Funktion
create
create von Aktivitätsdefinitionen für Aktivitäten in einer OLTP-Datenbank.
WF_ACTIVITY_REPOSITORY
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
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
WF_REPOSITORY
Entspricht den Verwendungskontexten
WF_TRANSITION_REPOSITORY
WF_TRANSITION_REPOSITORYund
WF_ACTIVITY_REPOSITORY
WF_ACTIVITY_REPOSITORY. Verwendbar in Aktivitätsdefinitionen für Aktivitäten in der Repository-Datenbank.
WF_OLTP
WF_OLTP
Entspricht den Verwendungskontexten
WF_TRANSITION_OLTP
WF_TRANSITION_OLTPund
WF_ACTIVITY_OLTP
WF_ACTIVITY_OLTP. Verwendbar in Aktivitätsdefinitionen für Aktivitäten in einer OLTP-Datenbank.
OLTP
OLTP
Entspricht den Verwendungskontexten
WF_SYS_SCRIPT_OLTP
WF_SYS_SCRIPT_OLTPund
WF_OLTP
WF_OLTP. D. h. der Verwendungskontext setzt keine Aktivitätsdefinition, aber eine OLTP-Datenbank voraus. Hierzu gehören Funktionen wie z. B.
loadPartner
loadPartnerund
loadItem
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
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
createCisDate,
getByPrimaryKey
getByPrimaryKey
und
getCisObjectList
getCisObjectList
.

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

  • System-Skriptsprache: Allgemeine Funktionen
    Funktionen des Verwendungskontexts
    ALL
    ALL.
  • System-Skriptsprache: OLTP-Funktionen
    Funktionen des Verwendungskontexts
    OLTP
    OLTPoder
    SYS_SCRIPT_OLTP
    SYS_SCRIPT_OLTP.
  • System-Skriptsprache: Workflow-Funktionen
    Funktionen des Verwendungskontexts
    WF_REPOSITORY
    WF_REPOSITORY,
    WF_OLTP
    WF_OLTP,
    WF_ACTIVITY_REPOSITORY
    WF_ACTIVITY_REPOSITORY,
    WF_ACTIVITY_OLTP
    WF_ACTIVITY_OLTP,
    WF_TRANSITION_REPOSITORY
    WF_TRANSITION_REPOSITORYoder
    WF_TRANSITION_OLTP
    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
null.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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)
}
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) }
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)
R f(D1 p1, ..., Dn pn)

Wenn der Datentyp völlig frei ist, so wird der Datentyp

Unknown
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
create
Die Funktion
create
createwird beim Erzeugen der Aktivität aufgerufen.
Da zum Zeitpunkt des Aufrufs die Aktivität noch nicht erzeugt ist, stehen in der Funktion
create
create die Informationen zur Aktivität nur eingeschränkt zur Verfügung.
applyDefaults
applyDefaults
Die Funktion
applyDefaults
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
applyDefaultsvor der Funktion
create
createaufgerufen. Bei allen anderen Aktivitäten erfolgt der Aufruf erst, nachdem die Funktion
create
create aufgerufen wurde.

Da der Zweck der Funktion

applyDefaults
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
applyDefaults stehen anderen Funktionen somit nicht zur Verfügung.

validate
validate
Die Funktion
validate
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
stategibt den künftigen Status der Aktivität wieder.Die Funktion
validate
validate liefert einen Rückgabewert vom Datentyp
Boolean
Booleanzurück. Ist der Rückgabewert
false
false, dann können die Aktivitätsergebnisse nicht übernommen werden. In einem Startknoten verhindert die Ausgabe einer Fehlermeldung mithilfe des Befehls
sendMessage
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
validate
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
validate stehen anderen Funktionen somit nicht zur Verfügung.
validatePrecondition
validatePrecondition
Die Funktion
validatePrecondition
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
validatePrecondition liefert einen Rückgabewert vom Datentyp
Boolean
Booleanzurück. Ist die Vorbedingung
false
false, dann wird die Aktivität automatisch unbearbeitet erledigt. In einem Startknoten wird keine Aktivität erzeugt, wenn die Funktion mithilfe des Befehls
sendMessage
sendMessageeine Fehlermeldung ausgibt.

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

Der Parameter

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

Die Funktion

validatePostcondition
validatePostcondition liefert einen Rückgabewert vom Datentyp
Boolean
Boolean zurück. Ist die Nachbedingung
false
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
sendMessage eine Fehlermeldung ausgibt.

Die Funktion

validatePostcondition
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
validateSeriesCondition
Die Funktion
validateSeriesCondition
validateSeriesCondition wird gemäß des in der Serienvorlage hinterlegten Serienmusters aufgerufen, wenn im Feld Serienbedingung der Wert Deklaration ausgewählt ist.

Die Funktion

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

validateSelection
validateSelection
Die Funktion
validateSelection
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
validateSelection liefert einen Rückgabewert vom Datentyp
Boolean
Boolean zurück. Ist die Auswahlbedingung
false
false, dann wird die Verknüpfung mit einer Fehlermeldung abgewiesen. Die Verknüpfung wird auch dann abgewiesen, wenn die Funktion mithilfe des Befehls
sendMessage
sendMessageeine Fehlermeldung ausgibt.

close
close
Die Funktion
close
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const MaxAmount := "123";
function helloWorld () as String
{
return "Hello World!";
}
const MaxAmount := "123"; function helloWorld () as String { return "Hello World!"; }
const MaxAmount := "123";
function helloWorld () as String
{
return "Hello World!";
}

Die Konstante

MaxAmount
MaxAmountund die Funktion
helloWorld
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
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

applyDefaults
applyDefaultsund
validate
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

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

Die Funktionen

applyDefaults
applyDefaultsund
validate
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

validatePostcondition
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
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
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
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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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));
}
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)); }
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
editorswird im Feld Ausdruck für Bearbeiter verwendet. Die Variable
customer
customerwird als Wert für den Parameter Partner der Anwendung
com.cisag.app.general.partner.ui.PartnerMaintenance
com.cisag.app.general.partner.ui.PartnerMaintenanceverwendet.

Um die Befehle in Deklarationen zu überführen, werden die Deklaration der Variablen

editors
editorsund
customer
customeraußerhalb der Funktion
create
createplatziert.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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));
}
}
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)); } }
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
import, um das Skript-Objekt bzw. die Bibliothek einzubinden. Ist das Skript in JavaScript erfasst, dann verwenden Sie den Befehl
load
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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))
{ }
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)) { }
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
persistentund
current
currentkönnen Sie die zu validierenden Änderungen in
current
current mit dem persistent gespeicherten Zustand des Business Objects in
persistent
persistent vergleichen. Bei manchen Hook-Contracts (wie z. B. Kampagnen) haben die Funktionen keinen Parameter
current
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
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
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]}
{EXTNUM_val=[S=], EXTNUM_id=[N=707070]}haben.

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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."));
}
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.")); }
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
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

create
createnoch keine Aktivität vorhanden. Daher stehen die Werte der Variablen
activity
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

event
eventeine Hash-Tabellle mit Informationen zum ausgelösten Ereignis.

Variable Wert
type
type
Die Variable type enthält den Ereignistyp. Die möglichen Werte sind im ValueSet
com.cisag.sys.workflow.EventTypeLimited
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
subtype
Die Variable
subtype
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
null. Beim Ereignistyp Business Entity sind die möglichen Wert im ValueSet
com.cisag.sys.kernel.ObjectChangeType
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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
var itemNumber := String;
if (event.subtype = 3)
itemNumber := parameters.oldObject:number;
else
itemNumber := parameters.newObject:number;
format("itemNumber", itemNumber);
var itemNumber := String; if (event.subtype = 3) itemNumber := parameters.oldObject:number; else itemNumber := parameters.newObject:number; format("itemNumber", itemNumber);
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.object
parameters.objectoder
parametrers.newObject
parametrers.newObjectauswertet, würde ein Laufzeitfehler entstehen, da das Business Object nicht mehr existiert.

guid
guid
Die Variable
guid
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)
objectName(event.guid)verwenden.
database
database
Die Variable
database
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)
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()
Java.type('com.cisag.pgm.util.ServerInfo').getSystemName()aufrufen. Die Java-Methode
Java.type('com.cisag.pgm.util.ServerInfo').getSVMName()
Java.type('com.cisag.pgm.util.ServerInfo').getSVMName()gibt den den Namen des Servers zurück.
parameters
parameters
Die Variable
parameters
parametersenthält eine Hash-Tabelle mit weiteren Informationen zum ausgelösten Ereignis. Welche Informationen
parameters
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
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

parameters
parameterseine Hash-Tabelle mit weiteren Informationen zum ausgelösten Ereignis. Die Variable
parameters
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.GenericOLTPEvent
com.cisag.pgm.workflow.GenericOLTPEventbesitzt die beiden Parameter
name
nameund
parameters
parameters, die als
String
Stringbzw.
HashMap
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
parameters.name = definition:codeverwendet werden.

Folgende Zuweisung übernimmt den Wert des Hash-Tabellen-Eintrags

user
userals Prozessauslöser:

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

Da die Hash-Tabelle untypisiert ist, müssen die Einträge mithilfe der Funktion

cast
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
userGuid
Die Variable
userGuid
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.Initiator
process.Initiatorautomatisch vorbelegt. Folgende Zuweisung legt den Prozessauslöser auch als Prozessverantwortlicher fest:

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

object
object
Die Variable
object
objectenthält eine Referenz auf das veränderte Business Object. Die Variable
object
objectgibt den aktuellen Zustand des Business Objects zum Zeitpunkt der Auswertung wider. Beim Subtyp Löschen hat
object
object den Wert
null
null.
Die Variable
object
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 */
parameters.object:status = 2 /* ORDER_RELEASED */
oldObject
oldObject
Die Variable
oldObject
oldObjectenthält den Wert des veränderten Business Objects unmittelbar vor dem Auslösen des Ereignisses. Beim Subtyp Einfügen hat
oldObject
oldObject den Wert
null
null.

Folgende Übergangsbedingung prüft, ob das Attribut

number
numbergeändert wurde:

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

newObject
newObject
Die Variable
newObject
newObject enthält den Wert des veränderten Business Objects unmittelbar nach der Än­derung. Beim Subtyp Löschen hat
newObject
newObject den Wert
null
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
parameters.object:updateInfo.updateTime = parameters.newObject:updateInfo.updateTime

entity
entity
Ist das veränderte Business Object ein De­pendent, dann enthält die Variable
entity
entity eine Referenz auf das mit dem Business Object über die Beziehung
_entity
_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.object
parameters.objectdas Business Object
com.cisag.app.sales.obj.SalesOrderDetail
com.cisag.app.sales.obj.SalesOrderDetail(Vertriebsauftragsposition) und
parameters.entity
parameters.entitydas Business Object
com.cisag.app.sales.obj.SalesOrder
com.cisag.app.sales.obj.SalesOrder(Vertriebsauftrag).

Ist das Business Object kein Dependent, dann ist

entity
entitynicht definiert. Beim Subtyp Löschen hat
entity
entity den Wert
null
null.

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

Ist das Business Object kein Dependent, dann ist

oldEntity
oldEntitynicht definiert. Beim Subtyp Einfügen hat
oldEntity
oldEntityden Wert
null
null.

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

Ist das Business Object kein Dependent, dann ist

newEntity
newEntitynicht definiert. Beim Subtyp Einfügen hat
newEntity
newEntityden Wert
null
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
userGuid
Die Variable
userGuid
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.Initiator
process.Initiatorautomatisch vorbelegt. Folgende Zuweisung legt den Prozessauslöser auch als Prozessverantwortlicher fest:

process.Owner := userName(parameters.userGuid);
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

false
falseund die Benutzeraktion ist im Kontextmenü des Belegs für den Benutzer deaktiviert:

parameters.userGuid = cast(Guid, first(parameters.object:responsible, parameters.userGuid))
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
object
Die Variable
object
object enthält eine Referenz auf das Business Entity, für das die Benutzeraktion ausgelöst wurde. Die Variable
object
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

false
falseund die Benutzeraktion ist im Kontextmenü des Belegs deaktiviert:

parameters.object:status = 1 /* ORDER_ENTERED */
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

parameters
parametersauch dann relevante Informationen zur Verfügung, wenn kein Ereignis vorliegt.

Variable Wert
userGuid
userGuid
Die Variable
userGuid
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)
contains(resolveRole("MANAGERS", parameters.userGuid)

database
database
Die Variable
database
database enthält die GUID der Datenbank, in der der Prozess gestartet wird. Siehe Kapitel Ereignis (event)  für Anwendungsbeispiele.
organization
organization
Die Variable
organization
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
processeine Hash-Tabellle mit Informationen zum Prozess.

Variable Beschreibung
Code
Code
Die Variable
Code
Code enthält die Identifikation des Prozesses.
Database
Database
Die Variable
Database
Database enthält die GUID der Datenbank. Diese Variable ist nur in der Funktion
create
createeines Startknotens verfügbar.
Description
Description
Die Variable
Description
Description enthält die Bezeichnung des Prozesses.
EndTime
EndTime
Die Variable
EndTime
EndTime enthält den Zeitpunkt für das Ende des Bearbeitungszeitraums.
ErrorCode
ErrorCode
Die Variable
ErrorCode
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

abortProcess
abortProcessverwendet werden, um den Prozess über den Fehlerknoten zu beenden.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
process.ErrorCode := "USER_ERROR";
process.ErrorDescription := "Error raised by user in create() of activity " + activity:code + ".";
abortProcess();
process.ErrorCode := "USER_ERROR"; process.ErrorDescription := "Error raised by user in create() of activity " + activity:code + "."; abortProcess();
process.ErrorCode := "USER_ERROR";
process.ErrorDescription := "Error raised by user in create() of activity " + activity:code + ".";
abortProcess();
ErrorDescription
ErrorDescription
Die Variable
ErrorDescription
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
FinishTime
Die Variable
FinishTime
FinishTime enthält den Erledigungszeitpunkt des Prozesses.
Initiator
Initiator
Die Variable
Initiator
Initiatorenthält den Prozessauslöser. Der Prozessauslöser steht erst ab der Funktion
close
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)
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.MinimumOnhand
com.cisag.app.inventory.MinimumOnhandausgelöst hat.

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

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

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

Number2
Number2
Die Variable
Number2
Number2 enthält das zweite allgemeine numerische Ergebnisattribut. Der Wert kann durch Zuweisung beliebig geändert werden.
OrganizationalUnit
OrganizationalUnit
Die Variable
OrganizationalUnit
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
Owner
Die Variable
Owner
Owner enthält den Prozessverantwortlichen. Der Prozessverantwortliche steht erst in der Funktion
close
closedes Startknotens zur Verfügung. Bei einem manuellen Prozess mit Aktivitätsergbnissen im Startknoten, kann der Owner in den Funktionen
applyDefaults
applyDefaultsund
validate
validatenicht ausgewertet werden.

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

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

Die Herkunft des Prozessverantwortlichen kann im Attribut

activity->Process:processData.sourceOfOwner
activity->Process:processData.sourceOfOwnerabgefragt werden. Der Wert 1 steht für Benutzer und der Wert 2 für Workflowrolle.

previousStep
previousStep
Wenn die Aktivität nur eine einzige Vorgängeraktivität hat, dann enthält die Variable
previousStep
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
null.

Der Ausdruck

process.previousStep:completeUser
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
previousSteps
Wenn die Aktivität mehrere Vorgängeraktivitäten hat, z. B. durch die Verwendung eines Zusammenführungsknotens, enthält die Variable
previousSteps
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
null.

Folgendes Skript weist der Variable

users
userseine Liste mit den GUIDs aller Benutzer zu, die mit ihrer Aufgabe eine Vorgängeraktivität erledigt haben.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
var users as Guid[];
for (a : process.previousSteps)
users := union(users, list(a:completeUser));
var users as Guid[]; for (a : process.previousSteps) users := union(users, list(a:completeUser));
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
StartTime
Die Variable
StartTime
StartTime enthält den Zeitpunkt für den Beginn des Bearbeitungszeitraums.
State
State
Die Variable
State
State enthält den Prozessstatus.
Result
Result
Die Variable
Result
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

close
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);
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
approvalResult.

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

process.Text1 := "APPROVED"
process.Text1 := "APPROVED"

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

process.Timestamp1 := now();
process.Timestamp1 := now();

Timestamp2
Timestamp2
Die Variable
Timestamp2
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
applyDefaultsund
validate
validateeines Startknotens besitzen alle Attribute noch ihre Standardwerte. Da der Startknoten keinen Vorgänger hat, besitzen die Attribute
previousStep
previousStepund
previousSteps
previousStepsimmer den Standardwert
null
nullin einem Startknoten.

In der Funktion

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

In der Funktion

close
closeeines Startknotens sowie in allen Funktionen der darauf folgenden Aktivitäts- und Ereignisknoten besitzen sämtliche Attribute außer
OrganizationalUnit
OrganizationalUnitund
Database
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
close
closein Prozessvariablen speichern.

Aktivität (activity)

Wenn die Übergangsbedingung erfüllt ist und die Funktion

create
createausgeführt wurde, wird die neue Aktivität erzeugt. Ab diesem Zeitpunkt stellt die Variable
activity
activityeine Referenz auf die erzeugte Aktivität zur Verfügung.

Um die Auswertung zu vereinfachen, stehen einige Attribute bereits in der Funktion

create
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
create auswerten.

Aus dem gleichen Grund stehen einige Attribute in der Funktion

close
closezur Verfügung, die erst nach dem Erledigen der Aktivität persistent gespeichert werden. So können Sie z. B. mithilfe des Attributs
activity:completeUser
activity:completeUserauswerten, welcher Benutzer die Aktivität gerade erledigt.

Nach der Ausführung der Funktion

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

Aktivitätsdefinition (definition)

Die Variable

definition
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:code
parameters.name = definition:codein einer Aktivitätsdefinition für das programmierte Ereignis
com.cisag.pgm.workflow.GenericOLTPEvent
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

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

Aktionsparameter (actionParameters)

Wenn die Funktion

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

Aktivitätsergebnisse (results)

Wenn die Funktion

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

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

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

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function applyDefaults()
{
results.approvalStatus := "REJECTED";
}
function applyDefaults() { results.approvalStatus := "REJECTED"; }
function applyDefaults()
{
results.approvalStatus := "REJECTED";
}

In der Funktion

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function validate(state as Number)
{
if (results.approvalStatus <> "APPROVED" and results.comment = "")
sendMessage(results.comment_id, "COMMENT", list());
}
function validate(state as Number) { if (results.approvalStatus <> "APPROVED" and results.comment = "") sendMessage(results.comment_id, "COMMENT", list()); }
function validate(state as Number)
{
if (results.approvalStatus <> "APPROVED" and results.comment = "")
sendMessage(results.comment_id, "COMMENT", list());
}

Das Suffix

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

In der Funktion

close
closewerden schließlich die beiden Aktivitätsergebnisse in gleichnamigen Prozessvariablen gespeichert:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function close(state as Number)
{
if(results.approvalStatus = "APPROVED")
process.approvalStatus := "APPROVED";
else
process.approvalStatus := "REJECTED";
process.comment := results.comment;
}
function close(state as Number) { if(results.approvalStatus = "APPROVED") process.approvalStatus := "APPROVED"; else process.approvalStatus := "REJECTED"; process.comment := results.comment; }
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
process.approvalStatus := results.approvalStatusmöglich. Der Unterschied ist, dass durch eine solche Zuweisung die Prozessvariable
process.approvalStatus
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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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";
}
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"; }
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
parametersfolgende Attribute zur Verfügung:

Variable Beschreibung
page
page
Die Variable
page
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
pageeine leere Zeichenkette.
nextPage
nextPage
Wird der Variable
nextPage
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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";
}
}
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"; } }
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
parametersund
result
result, d.h.:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
parameters.P1,…,parameters.Pn
result.R1,…,result.Rm
parameters.P1,…,parameters.Pn result.R1,…,result.Rm
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
nullund können durch die Aktivitätsdefinition berechnet werden.

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
parameters.ITEMNUMBER
result.PRICE
parameters.ITEMNUMBER result.PRICE
parameters.ITEMNUMBER
result.PRICE

Der Wert der Variablen

ITEMNUMBER
ITEMNUMBERwird beim Aufruf der Aktivitätsdefinition gesetzt. Der Wert der Variablen
PRICE
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

close
closekann die Skriptfunktion
getJobResult
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)
setJobWaitFinish(true)in der Funktion
create
create.

Die Funktion

getJobResult
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.PhysicalInventoryCountProcessing
com.cisag.app.inventory.physical.log.PhysicalInventoryCountProcessingund Aktion CreateCountLists) hat folgende Ausführungsergebnisse:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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}
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}
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
getJobResultfolgende Hash-Tabelle zurückgeben:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{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]}
{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]}
{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
resultParmeters. (Bitte auf die Schreibweise achten!). Folgendes Skript in der Funktion
close
closewertet diese aus, öffnet die generierten Inventurzähllisten und gibt deren Identifikation ins Protokoll aus:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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);
}
}
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); } }
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
closekann die Skriptfunktion
getServiceResponse
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"]
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)
setJobWaitFinish(true)in der Funktion
create
create. Je nach ausgewählter Aktion der Hintergrundanwendung (JSON oder XML) können Sie die Funktionen
parseJson
parseJsonoder
parseXml
parseXmlverwenden, um die von
getServiceResponse
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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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));
}
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)); }
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
environmentmit dem Wert
userGuid
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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.");
}
}
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."); } }
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
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
statusBackup
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
while
1.000.000
while
while-Schleifen brechen nach 1.000.000 Durchläufen ab.
getResultList
getResultList

getCisObjectList
getCisObjectList

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

@
@

100
call
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
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/b
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?