Język skryptowy systemu jest używany w Workflow Management, na przykład do formułowania warunku wstępnego lub warunku przejścia lub do określania operatorów, którzy nie są podsumowani w roli workflow.
Silnik workflow obsługuje zarówno własny język skryptowy systemu, jak i JavaScript do wyrażania złożonych relacji. Niniejszy dokument dotyczy wyłącznie systemowego języka skryptowego. Jest on podzielony na następujące rozdziały:
- Struktura i składnia
- Deklaracje
- Ocena informacji
- Obsługa błędów
- Rozszerzenie języka skryptowego systemu
Wprowadzenie do języka skryptowego systemu jest podzielone na kilka dokumentów. Niniejszy dokument zawiera szczegółowe informacje na temat struktury i składni języka skryptowego systemu. Więcej informacji na temat poszczególnych funkcji i poleceń można znaleźć w poniższej dokumentacji:
- Systemowy język skryptowy: Funkcje ogólne
- Systemowy język skryptowy: Funkcje OLTP
- Systemowy język skryptowy: Funkcje workflow
Informacje na temat silnika workflow można znaleźć w dokumentacji Silnik workflow. Informacje na temat korzystania z języka skryptowego systemu w definicjach workflow można znaleźć w dokumentacji Definicje działań i Definicje procesów.
Systemowy język skryptowy może być również używany między innymi w następujących aplikacjach:
- Indywidualne implementacje hook
- Indywidualne weryfikacje
Więcej informacji można znaleźć w odpowiedniej dokumentacji.
Grupa docelowa
Grupą docelową tego dokumentu są programiści i konsultanci techniczni, którzy tworzą lub dostosowują workflow dla klientów, a także klienci, którzy zarządzają własnym workflow.
Niniejszy dokument zakłada zrozumienie zakresu funkcji Workflow Management widocznych dla użytkownika. Ponadto, czytelnik powinien posiadać podstawową znajomość SQL lub innego języka programowania w celu zrozumienia języka skryptowego systemu.
Definicje terminów
Definicja działania
Definicja działania jest szablonem dla działań generowanych na jej podstawie. Jeśli definicja działania jest aktywna, silnik workflow generuje nowe działanie, gdy wystąpi zarejestrowane zdarzenie, pod warunkiem spełnienia warunku przejścia. Definicje działań są niezależne od bazy danych OLTP i systemu, w którym zostały zarejestrowane, ponieważ nie zawierają ani danych specyficznych dla systemu, ani danych specyficznych dla OLTP. Definicje działań są zapisywane w bazie danych repozytorium.
Deklaracje
Deklaracje to skrypty w definicjach procesów i działań, które zapewniają metody wywoływane podczas tworzenia działań, zmiany statusu i wprowadzania określonych wartości parametrów. Właściwości procesów i działań mogą być elastycznie definiowane poprzez dostosowanie deklaracji. Deklaracje są zapisywane w języku skryptowym.
GUID
GUID jest skrótem od Globally Unique Identifier i odpowiada globalnie unikalnemu identyfikatorowi. GUID to 128-bitowy numer obliczany zgodnie ze schematem Open Software Foundation (OSF) dla rozproszonych środowisk obliczeniowych (DCE). Zawiera on między innymi adres IP komputera generującego, składnik czasu i składnik losowy. Oznacza to, że dwa niezależne komputery mogą zawsze obliczyć różne identyfikatory GUID bez synchronizacji. W Comarch ERP Enterprise identyfikatory GUID są reprezentowane jako tablice bajtów Java o długości 16 i są używane głównie jako kompaktowe klucze podstawowe i obce w Business Objects.
Hook Contract
Hook to interfejs, za pomocą którego istniejący kod programu można rozszerzyć niezależnie od wydania, a zatem bez konfliktu. Hooki są używane na przykład wtedy, gdy konieczne jest przeprowadzenie dodatkowych kontroli w adaptacji lub aplikacji dla rozszerzenia obiektu biznesowego w celu uzupełnienia istniejących kontroli.
Wdrożenie Hook Contract
Hooki, które mają zostać zaimplementowane i odpowiednia klasa implementacji są określone w implementacji Hook Contract. Implementacja Hook Contract zawsze odnosi się do definicji Hook Contract, która zawiera implementowalne hooki.
Indywidualne walidacje
Niektóre jednostki biznesowe oferują Hook Contract dla kontroli, które mogą być zaimplementowane przy użyciu języka skryptowego systemu i bez dostępu do systemu deweloperskiego. Te rozszerzone kontrole są używane we wszystkich kanałach wejściowych i wyjściowych, tj. w aplikacjach dialogowych, a także podczas importu lub eksportu.
Systemowy język skryptowy
Wyrażenia, warunki, polecenia, funkcje i deklaracje są używane do wyrażania złożonych relacji. Wszystkie te wyrażenia są częścią wspólnego języka skryptowego zwanego językiem skryptowym systemu. Składnia języka skryptowego systemu jest oparta na SQL, Pascal i Java. Język skryptowy systemu jest używany w Workflow Management, na przykład do formułowania warunku wstępnego lub warunku przejścia lub do określania operatorów, którzy nie są podsumowani w roli workflow.
Silnik workflow
Wraz z usługą zdarzeń, silnik workflow koordynuje i monitoruje wykonywanie workflow Silnik workflow jest wykonywany na serwerze komunikatów w każdym systemie.
Struktura i składnia
Wyrażenia, warunki, polecenia, funkcje i deklaracje są używane do wyrażania złożonych relacji. Wszystkie te wyrażenia są częścią wspólnego języka skryptowego zwanego językiem skryptowym systemu. Składnia języka skryptowego systemu jest oparta na SQL, Pascalu i Javie.
Ponieważ generalnie nie ma potrzeby wyrażania złożonych algorytmów za pomocą tego języka, wcześniejsza znajomość SQL powinna być wystarczająca do nauki tego języka.
Język skryptowy systemu składa się z następujących elementów:
- Typy danych
- Stałe stałe
- Komentarze
- Zasady i warunki
- Polecenia
- Funkcje
Typy danych
Typ danych definiuje prawidłowe zakresy wartości i dozwolone operacje. Język skryptowy systemu rozpoznaje zarówno proste, jak i złożone typy danych. Przykładami prostych typów danych są ciągi znaków i liczby. Złożone typy danych obejmują na przykład listy, obiekty biznesowe i widoki obiektów.
Wszystkie typy danych w języku skryptowym systemu mają wartość standardową (domyślną). Wartość domyślna jest zawsze używana, jeśli wymagana jest nowa, jeszcze niezdefiniowana wartość tego typu danych. Podczas analizowania (oceny) wyrażenia w języku skryptowym systemu sprawdzane jest użycie typów danych jako argumentów funkcji, poleceń i operatorów. Jeśli przekazana wartość nie jest zgodna z oczekiwanym typem danych, wyświetlany jest komunikat o błędzie.
Język skryptowy systemu rozpoznaje następujące typy danych:
Nazwa | Opis |
Boolean | Wartości logiczne (Boolean) mogą przyjmować tylko wartości true dla true i false dla false. Domyślną wartością typu danych Boolean jest false. |
Bytes | Typ danych bytes to dane binarne o dowolnej zawartości. Ten typ danych może być używany w szczególności jako parametr dla zaprogramowanych zdarzeń i plików. Domyślną wartością typu danych bytes jest null. |
Class | Klasa to ustrukturyzowany typ danych z zestawem atrybutów. Każdy atrybut ma nazwę i typ danych. Domyślną wartością class jest null. |
CisDate | CisDate to połączenie punktu w czasie ze strefą czasową. Domyślną wartością typu danych CisDate jest null. |
CisObjectReference | Obiekty biznesowe są zarządzane za pomocą typów danych CisObject lub CisObjectReference, części z typem danych CisObject. Odniesienia do obiektów biznesowych zawierają klucz obiektu biznesowego. Domyślną wartością typu danych CisObjectReference jest null.
Aby uzyskać typowaną referencję CisObjectReference, należy wprowadzić nazwę obiektu biznesowego w nawiasach. Jeśli użytkownik nie określi nazwy, otrzyma nieokreślony CisObjectReference.
|
CisObject | Obiekty biznesowe są zarządzane za pomocą typów danych CisObject lub CisObjectReference, części z typem danych CisObject. Obiekty biznesowe i ich części są również dostępne jako wartości. Domyślną wartością typu danych CisObject jest null.
Aby uzyskać wpisany obiekt CisObject, nalezy wprowadzić nazwę obiektu biznesowego w nawiasach. Jeśli nazwa nie zostanie wprowadzona, użytkownik otrzyma niewpisany obiekt CisObject. |
DataView | Widoki obiektów (DataView) to widok statusu złożonej jednostki biznesowej. Widoki obiektów są wykorzystywane w szczególności w indywidualnych kontrolach. Domyślną wartością typu danych DataView jest null. Aby uzyskać typowany widok DataView, nalezy wprowadzić nazwę widoku obiektu w nawiasach. Jeśli nazwa nie zostanie wprowadzona, użytkownik otrzyma niewpisany widok DataView. |
GUID | Identyfikatory GUID są często wymagane do identyfikacji obiektów biznesowych za pomocą klucza podstawowego. Domyślną wartością typu danych Guid jest null. |
HashMap | HashMap przechowuje pary klucz-wartość. Każdemu kluczowi można przypisać dokładnie jedną wartość. Wartość może być wielokrotnie wyszukiwana przy użyciu klucza. Jako klucze dozwolone są tylko ciągi znaków. Domyślną wartością typu danych HashMap jest pusta tablica. |
Number | Liczby zawsze zawierają znak. Mogą mieć miejsca dziesiętne, które są oddzielone kropką. Domyślną wartością typu danych Number jest 0. |
String | Ciągi znaków (String) mogą mieć dowolną długość. Domyślną wartością typu danych String jest pusty ciąg znaków. |
Timestamp | Punkt czasowy (Timestamp) to punkt w czasie z dokładnością do milisekund. Wszystkie specyfikacje czasu są odwzorowywane w punktach w czasie. Domyślną wartością typu danych timestamp jest stała UNDEFINED_DATE. |
Unknown | Do typu danych Unknown można przypisać dowolny inny typ danych. Domyślną wartością typu danych Unknown jest null. |
Automatyczna konwersja prostych trybów danych
Niektóre proste typy danych, takie jak Number, Boolean i Guid, są w razie potrzeby automatycznie konwertowane na ciągi znaków.
Należy pamiętać, że typ danych jest określany przez pierwszy człon wyrażenia. Przy następującym przypisaniu liczba 40 jest automatycznie konwertowana na ciąg znaków 40: var t := „UB” + 40; Następujące przypisanie powoduje błąd, ponieważ ciąg znaków ers nie może zostać przekonwertowany na liczbę: var t := 101 + „ers”;
Inne typy danych można konwertować za pomocą funkcji rzutowania. Więcej informacji i przykładów można znaleźć w dokumentacji Język skryptowy systemu: Funkcje podstawowe.
Weryfikacja typowania CisObject i CisObjectReference
Jeśli użytkownik zna typ obiektu biznesowego lub części, powinien zawsze używać typowanego CisObject lub CisObjectReference. Prawidłowe użycie atrybutów i ich typów danych jest sprawdzane tylko w przypadku typowania.
CisObject (com.cisag.app.general.obj.DomesticAmount) jest częścią typu Waluta krajowa.
W przypadku nieoznaczonego CisObject lub CisObjectReference, system nie sprawdza, czy nazwa atrybutu jest faktycznie zdefiniowana na obiekcie, ani nie sprawdza, czy atrybut faktycznie ma wymagany typ danych.
Listy
Lista jest uporządkowaną sekwencją wartości. Lista ma typ danych elementu i opcjonalnie długość. Wszystkie elementy listy muszą być konwertowalne do tego typu danych elementu. Jeśli typ danych listy ma długość, długość ta jest stała i nie można jej później zmienić.
Typ danych List jest wyrażany poprzez określenie typu danych elementu, po którym następują nawiasy kwadratowe. Nawiasy kwadratowe opcjonalnie zawierają stałą długość listy.
Number[] to lista liczb o nieokreślonej liczbie elementów. Unknown[] to lista dowolnych obiektów o nieokreślonej liczbie elementów.
Domyślną wartością listy o określonej długości jest lista o tej długości. Jeśli lista nie ma długości, wartością domyślną jest pusta lista. Pustą listę można sprawdzić za pomocą funkcji skryptowej isEmpty.
Funkcja skryptu list tworzy nową listę z elementami. Typ danych pierwszego elementu określa typ danych listy. Jeśli nie określono żadnego elementu, funkcja list zwraca pustą listę typu danych Unknown[].
list(101, „ers”) nie jest prawidłową listą, ponieważ ciąg znaków ers nie może zostać przekonwertowany na typ danych elementu Number. list() tworzy nową pustą listę danych typu Unknown[].
Element może zostać dodany do istniejącej listy tylko wtedy, gdy typ danych elementu jest zgodny z typem danych listy lub może zostać do niego przekonwertowany.
var list1 := Number[]; add(list1, „500”); Jeśli jednak lista jest zadeklarowana jako string[], wówczas wyrażenie add(list1, 500) jest poprawne składniowo, ponieważ liczba może zostać przekonwertowana na ciąg znaków.
W przypadku przypisywania do listy elementów o różnych typach danych (np. jako listy parametrów do wywoływania aplikacji działającej w tle), należy wybrać pierwszy element, aby pozostałe elementy mogły zostać przekonwertowane na typ danych pierwszego elementu. Na przykład, liczby mogą być konwertowane na ciągi znaków, ale nie odwrotnie. Jeśli nie jest to możliwe, można zadeklarować listę typu danych Unknown[] i przypisać elementy różnych typów danych za pomocą funkcji add. Elementy dowolnego typu danych mogą być dodawane do listy o typie danych Unknown[], ponieważ wszystkie inne typy danych mogą być konwertowane na Unknown.
Oznacza to na przykład, że lista parametrów może być również generowana dla funkcji getCisObjectList i getResultList, jeśli zapytanie OQL ma parametry o różnych typach danych, których nie można przekonwertować automatycznie (na typ danych pierwszego parametru). Poniższy przykład tworzy listę parametrów w celu określenia pierwszych 100 osób wewnętrznych za pomocą funkcji getCisObjectList i wyprowadzenia ich na konsolę:
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);
}
Jeśli lista zawiera elementy o różnych typach danych, może być konieczne wpisanie elementów za pomocą funkcji rzutowania przed ich użyciem, jak pokazuje poniższy przykład.
var myList as Unknown[];
add(myList, 800);
add(myList, „°”);
var song := cast(String, myList[0]) + cast(String, myList[1]);
Język skryptowy systemu zawiera wiele funkcji służących do tworzenia i edytowania list. Więcej informacji i przykładów można znaleźć w rozdziale Funkcje list w dokumentacji Systemowy język skryptowy: Funkcje ogólne.
Wartość null
Wartość null istnieje oprócz wartości typów danych. Wartość null nie jest przypisana do typu danych. Jeśli wartość ma wartość null, jest ona niezdefiniowana. Wiele funkcji i operatorów w języku skryptowym systemu zwraca wynik null, jeśli jeden z parametrów ma wartość null. Jeśli więc coś ma zostać obliczone na podstawie niezdefiniowanej wartości, wynik jest również niezdefiniowany. Funkcje specjalne isNull i first mogą być używane do oddzielnej obsługi wartości null.
Warunek przejścia w definicji działania nie jest uważany za spełniony, jeśli jego wartość wynosi null (false). Z drugiej strony, warunek wstępny jest uważany za spełniony, jeśli jego wartość wynosi null (true). Należy zatem sprawdzać atrybuty opcjonalne z kluczami obcymi w szczególności pod kątem wartości null.
Warunek przejścia not(contains(resolvePartner(parameters.object:responsible), parameters.userGuid)) ma niezdefiniowaną wartość null, jeśli żaden odpowiedzialny pracownik nie jest zapisany w zamówieniu sprzedaży. Dlatego w tym przypadku nie jest generowane żadne działanie. Warunki przejścia isNull(parameters.object:responsible) lub not(contains(resolvePartner(parameters.object:responsible), parameters.userGuid)) i not(contains(resolvePartner(cast(Guid, first(parameters.object:responsible, ZERO_GUID))), parameters.userGuid)) również mają prawidłową wartość, jeśli żaden odpowiedzialny pracownik nie jest zapisany w zamówieniu sprzedaży.
Wyrażenie, które śledzi relację poprzez atrybut z wartością null również prowadzi do niezdefiniowanego wyniku.
Język skryptowy systemu zawiera dwie funkcje isNull i first do obsługi wartości null. Więcej informacji i przykładów można znaleźć w rozdziale Funkcje listy dokumentacji Systemowy język skryptowy: Funkcje ogólne.
Stałe wartości
Stała może przyjmować tylko jedną z góry określoną wartość. Stałe są używane, między innymi, w celu ułatwienia korzystania z języka skryptowego systemu i uczynienia go bardziej zwartym. Następujące stałe są zdefiniowane na stałe i zawsze dostępne:
Operator | Wyjaśnienie |
INVALID_GUID | INVALID_GUID reprezentuje nieprawidłową wartość dla typu danych Guid. |
MAX_DATE | Największy wyświetlany punkt w czasie (TimeStamp). Wartość MAX_DATE może być używana na przykład dla zakresów ważności, które są otwarte od góry.
MAX_DATE odpowiada stałej MAX_TIME_STAMP zapytania OQL. |
MIN_DATE | Najmniejszy czas, jaki może być wyświetlany (TimeStamp). MIN_DATE może być używane na przykład dla zakresów ważności, które są otwarte od dołu.
MIN_DATE odpowiada stałej MIN_TIME_STAMP zapytania OQL. |
UNDEFINED_DATE | Niezdefiniowany punkt w czasie (TimeStamp). Atrybut UNDEFINED_DATE jest używany na przykład dla punktów w czasie przed przypisaniem określonej wartości. Na przykład czas ostatniej zmiany obiektu biznesowego (w atrybucie updateInfo.updateTime), który nie został zmieniony od czasu jego utworzenia.
UNDEFINED_DATE odpowiada stałej UNDEFINED_TIME_STAMP zapytania OQL. |
ZERO_GUID | Identyfikator GUID ZERO jest zawsze używany, gdy identyfikator GUID nie może być zerowy, ale nadal jest niezdefiniowany. Dzieje się tak na przykład, gdy identyfikator GUID jest częścią klucza podstawowego. ZERO_GUID odpowiada stałej ZEROGUID zapytania OQL. |
Komentarze
Komentarze są wprowadzane przez /* i kończone przez */. Komentarze mogą składać się z kilku linii.
W przypadku bardziej złożonych procesów przepływu pracy zaleca się wprowadzenie wystarczającej liczby komentarzy w definicjach działań, aby ułatwić dostosowanie i konserwację. Poniższy przykładowy komentarz z definicji procesu opisuje proces.
/**
* 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
*/
Zaleca się również deklarowanie i komentowanie stałych globalnych w definicjach procesów w celu uproszczenia konfiguracji procesów workflow.
/**
* 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 := „”;
Puste wyrażenie w polu warunku jest uważane za spełnione (true). Ponieważ warunek składający się tylko z jednego komentarza nie jest pusty, następujący warunek przejścia jest uważany za niespełniony (false), nawet jeśli nie zawiera wyrażenia podlegającego ocenie, a zatem nie generuje żadnego działania.
/* parameters.object:status = OrderStatus.RELEASED */
Jeśli na przykład użytkownik chce upewnić się, że działanie jest zawsze tworzone niezależnie od warunku przejścia podczas rozwiązywania problemów, ale nie chce usuwać warunku przejścia, można zamiast tego skomentować warunek przejścia i zastąpić go wartością true.
true /* parameters.object:status = OrderStatus.RELEASED */
Terminy i warunki
Termin to wyrażenie lub formuła, która oblicza wartość.
a * a + b * b
max(a, b) * min(c, d)
Warunek to wyrażenie, które zwraca wartość prawdy, a tym samym umożliwia podjęcie decyzji tak/nie.
a * a + b * b = c * c
max(a, b) > 0
parameters.object:updateInfo.createUser <> parameters.userGuid
Składnia warunków jest podobna do tej w SQL. Jeśli jeden z operandów nie odpowiada oczekiwanemu typowi danych, wynikiem operacji jest null. Jeśli jeden z operandów ma wartość null, wynikiem operacji jest również null.
Operatory arytmetyczne
Następujące operatory są zdefiniowane dla liczb:
Operator | Opis |
a * b | Mnożenie liczb a i b. |
a / b | Podziel liczbę a przez liczbę b. |
a % b | Reszta z dzielenia liczby całkowitej a przez liczbę b. |
a + b | Dodawanie liczb a i b. |
a – b | Odejmowanie liczby b od liczby a. |
Operatory arytmetyczne, nawet różnych typów, mogą być dowolnie łączone. Jak zwykle, operatory *, / i % mają wyższe wiązanie niż operatory + i -. Operatory z tym samym wiązaniem są wykonywane od lewej do prawej.
1 + 3 i 3 * 4 – 8 są poprawnymi wyrażeniami z tymi operatorami i oba zwracają wynik 4.
1 * „a” zwraca null.
Język skryptowy systemu zawiera również wiele funkcji arytmetycznych. Więcej informacji i przykładów można znaleźć w rozdziale Funkcje arytmetyczne dokumentacji Systemowy język skryptowy: Funkcje podstawowe.
Operatory na ciągach znaków
Następujące operatory są zdefiniowane dla ciągów znaków:
Operator | Wyjaśnienie |
a + b | Łączenie ciągów a i b. |
Dowolna liczba ciągów może być połączona w celu utworzenia terminu.
Język skryptowy systemu zawiera również wiele funkcji dla ciągów znaków. Więcej informacji i przykładów można znaleźć w rozdziale Funkcje dla ciągów znaków dokumentacji Systemowy język skryptowy: Funkcje podstawowe.
Operatory porównania
Operatory porównania (komparatory) to:
Operator | Wyjaśnienie |
a = b | Porównuje, czy wartości terminów a i b są takie same. |
a < b | Porównuje, czy wartość terminu a jest mniejsza niż wartość terminu b. |
a <= b | Porównuje, czy wartość wyrażenia a jest mniejsza lub równa wartości wyrażenia b. |
a > b | Porównuje, czy wartość terminu a jest większa niż wartość terminu b. |
a >= b | Porównuje, czy wartość wyrażenia a jest większa lub równa wartości wyrażenia b. |
a <> b | Porównuje, czy wartości terminów a i b nie są równe. Wszystkie typy danych mogą być porównywane za pomocą <>. |
Wszystkie typy danych mogą być porównywane za pomocą operatorów = i <>. W przypadku jednostek biznesowych porównywana jest cała zawartość. Porównanie z innymi operatorami jest możliwe tylko dla typów danych Number, String, CisDate, Timestamp i Boolean.
Lewa strona operacji porównania określa porównywany typ danych.
„a” < „b” jest warunkiem prawdziwym.
„a” > 1 jest warunkiem prawdziwym, ponieważ liczba 1 może zostać przekonwertowana na ciąg znaków.
1 > „a” zwraca null, ponieważ ciąg znaków a nie może zostać przekonwertowany na liczbę.
Wynik operacji porównania jest typu danych wartość prawdy.
today() < addDays(today(), 1) jest warunkiem true.
true = false jest warunkiem fałszywym.
Jeśli porównywane są ze sobą dwie daty CisDate, brana jest również pod uwagę strefa czasowa.
createCisDate(„NST”, 2019, 12, 31, 23,0,0,0) jest warunkiem prawdziwym, ponieważ strefa czasowa NST jest ponad godzinę po strefie czasowej CET.
Aby porównać CisDate z czasem, można użyć funkcji skryptu toTimestamp w celu przekonwertowania CisDate na czas.
Warunki
Warunki mogą być łączone zgodnie z wymaganiami za pomocą operatorów logicznych AND i OR:
Operator | Wyjaśnienie |
a i b | AND jest kombinacją dwóch warunków. Wynik jest prawdziwy, jeśli oba warunki a i b są prawdziwe. |
a LUB b | OR jest operacją LUB dwóch warunków. Wynik jest prawdziwy, jeśli warunek a lub warunek b lub a i b są prawdziwe. |
NIE | NOT jest zaprzeczeniem warunku. Wynik jest prawdziwy, jeśli warunek a jest fałszywy i fałszywy, jeśli warunek a jest prawdziwy. |
Operatory AND i OR można dowolnie łączyć. Jak zwykle, operator AND ma wyższe wiązanie niż operator OR.
1 = 1 LUB 2 = 2 ORAZ 3 = 4 jest warunkiem prawdziwym.
1 = 0 LUB 2 = 2 ORAZ 3 = 4 to nieprawidłowy warunek.
Nawiasy
Warunki mogą być umieszczone w nawiasach zgodnie z wymaganiami:
Operator | Wyjaśnienie |
(a) | Nawiasy warunków umowy. |
Wyrażenie w nawiasie jest zawsze wykonywane jako jednostka, niezależnie od różnic między wiązaniami operatorów.
(2 * (7 – 6) + 1) = 3 jest warunkiem prawdziwym.
(1 = 1 LUB 3 < 1) ORAZ 2 = 2 jest warunkiem prawdziwym.
Dostęp do list i tablic hash
Istnieją następujące operatory dostępu do list i HashMap:
Operator | Wyjaśnienie |
b[a] | Dostęp do elementu o indeksie a listy b, począwszy od indeksu 0. Indeks a musi być liczbą. Jeśli a nie jest liczbą całkowitą, pod uwagę brana jest tylko część całkowita. Jeśli indeks jest poza prawidłowym zakresem listy, wynikiem jest null. |
b.a | Dostęp do wartości z kluczem a w HashMap b. Jeśli dla klucza nie istnieje żadna wartość, wynikiem jest null. |
b[„a”] | Dostęp do wartości z kluczem a w HashMap b. Jeśli dla klucza nie istnieje żadna wartość, wynikiem jest null. |
Oba typy dostępu do HasMap są równoważne. Dostęp za pomocą kropki (b.a) jest bardziej kompaktowy i jest szczególnie odpowiedni, jeśli wpisy HashMap są znane w momencie pisania wyrażenia. Jeśli wpisy są obliczane dynamicznie w czasie wykonywania, dostęp za pomocą nawiasów kwadratowych (b[„a”]) ma większy sens.
h = {(„a”,1), („x1”, 11), („x2”, 12) , („x3”, 13)}
h.a = 1 jest warunkiem prawdziwym.
h[„a”] = 1 jest warunkiem prawdziwym.
h[„x” + (3 – 2)] = 11 jest warunkiem prawdziwym.
h.x = 1 zwraca wartość zero.
l jest listą zawierającą następujące wpisy:
l = {„a”, „b”, „c”}
l[0] = „a” jest warunkiem prawdziwym.
l[2] = „c” jest warunkiem prawdziwym.
l[2 * 3] = „a” zwraca wartość null.
Dostęp do obiektów biznesowych, części i widoków obiektów
Następujące operatory są dostępne dla jednostek biznesowych i części:
Operator | Wyjaśnienie |
o:a | Dostęp do atrybutu a obiektu biznesowego, części lub widoku obiektu o. Jeśli atrybut a nie istnieje w obiekcie o lub zawiera nieobsługiwany typ danych, wynikiem jest null. Atrybut a może być złożoną ścieżką dostępu do atrybutów części i pól osadzonych w obiekcie o. |
o->R | Dostęp do relacji 1:1 R obiektu biznesowego, części lub widoku obiektu o. Jeśli relacja nie istnieje lub nie wskazuje na żaden obiekt, wynikiem jest null. Wynikiem dostępu do relacji jest obiekt biznesowy jako wartość. |
Dostęp do obiektów biznesowych, części i widoków obiektów jest często wymagany, ponieważ obiekty te są najważniejszymi kontenerami danych w systemie.
loadPartner(„10010”):organizationalUnit.name[1] jest prawidłowym dostępem do pola o indeksie 1 w atrybucie pola name w atrybucie złożonym organizationalUnit obiektu biznesowego Partner o identyfikatorze 10010.
loadPartner(„10010”)->Language:isoCode jest prawidłowym dostępem do atrybutu isoCode obiektu biznesowego, do którego odwołuje się relacja Language obiektu biznesowego Partner o identyfikatorze 10010.
Aby ocenić atrybuty, których nazwy zaczynają się od podkreślenia, można użyć funkcji getAttribute. Przed użyciem wyniku należy przekonwertować go na typ danych pasujący do atrybutu.
getAttribute(parameters.object, „_organisation”)))):isoCode zwraca kod ISO kluczowej waluty organizacji, w której kontekście zarejestrowano obiekt biznesowy, do którego odwołuje się parametr parameters.object.
Wywoływanie definicji działania
Definicje działania z kategorią Wywołanie funkcji można wywoływać jak funkcje. Nazwa definicji działania może zawierać tylko litery, cyfry i znaki specjalne: kropkę (.), podkreślenie (_), znak dolara ($) lub hash (#) dla wywołania. Jeśli nazwa zawiera inne znaki, definicja działania musi zostać wywołana za pomocą funkcji wywołania. Więcej informacji znajduje się w rozdziale Inne funkcje w dokumentacji Język skryptowy systemu: Funkcje podstawowe.
Aby odróżnić wywołanie definicji działania od wywołania funkcji, znak at (@) jest umieszczany przed nazwą definicji działania. Wartość musi być przypisana do każdego parametru definicji działania, gdy jest ona wywoływana. Parametry są sortowane alfabetycznie. Zwracane wartości definicji działania są zwracane jako klasa. Poszczególne wartości zwracane są atrybutami tej klasy.
var result := @isPythagoreanTheorem(A:=3, B:=4, C:=5).RESULT;
Maksymalna głębokość rekurencji jest ograniczona. Więcej informacji można znaleźć w rozdziale Ograniczenia złożoności wyrażeń.
Polecenia
Polecenie to wyrażenie wykonujące operację, która nie zwraca wyniku. W języku skryptowym systemu polecenia są oddzielone średnikiem (;).
setMailRecipientsTo(„somebody@localhost.local”);
W zależności od kontekstu zastosowania można zdefiniować różne polecenia. Poniższe sekcje opisują polecenia pogrupowane według kontekstów zastosowania.
Przepływ sterowania i przypisywanie zmiennych
Polecenia do sterowania przepływem sterowania i przypisywania zmiennych są wbudowane w język skryptowy systemu.
Opis | Składnia |
Deklaracja zmiennej (typ) | var <VariableName> as <Type> |
Deklaracja zmiennej (termin) | var <VariableName> := <Expression> |
Stała deklaracja | const <VariableName> := <Expression> |
Deklaracja zestawu wartości | const <VariableName> as valueSet(<Name>) |
Definicja typu | type <TypeName> as <Type> |
Definicja typu (klasa) | type <TypeName> as class {<AttributeName> jako <Type>;
… <AttributeName> as <Type>; } |
Przydział | <VariableName> := <Expression> |
Polecenie warunkowe | if (<Condition>) <Command> |
Polecenie warunkowe z alternatywą | if (<Condition>) <Command> else <Command> |
Pętla z warunkiem | while (<Condition>) <Command> |
Pętla nad wszystkimi elementami | for (<VariableName> : <List>) <Command> |
Pętla nad wszystkimi elementami z wpisywaniem | for (<VariableName> as <Type> : <List>)<Command> |
Zakończ polecenie | return |
Koniec funkcji | return <Expression> |
Blok instrukcji | {<Command>
… <Command> } |
Język skryptowy systemu zawiera również funkcję if, która służy do określania przepływu sterowania w wyrażeniu. Więcej informacji i przykładów można znaleźć w rozdziale Inne funkcje dokumentacji Język skryptowy systemu: Funkcje podstawowe.
Stałe
Stała może przyjmować tylko jedną z góry określoną wartość. Stałe są używane, między innymi, w celu ułatwienia korzystania z języka skryptowego systemu i uczynienia go bardziej zwartym.
Stałe są deklarowane podobnie jak zmienne z terminem. W przeciwieństwie do zmiennych, wartość stałej nie może zostać zmieniona po jej zadeklarowaniu.
W przypadku bardziej złożonych procesów workflow zaleca się zadeklarowanie stałych globalnych w definicji procesu, za pomocą których proces workflow można skonfigurować centralnie, tak aby definicje działania poszczególnych kroków procesu nie musiały być dostosowywane, jeśli to możliwe.
/**
* 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 := „”;
Zmienne
Wszystkie używane zmienne i stałe muszą być zadeklarowane. Zmienne mogą być deklarowane z typem lub wartością początkową. Jeśli określono typ, zmienna ma wartość domyślną typu jako wartość początkową. Jeśli zmienna jest zadeklarowana za pomocą wyrażenia, jako wartość ma wartość wynikową wyrażenia, a jako typ danych, jego typ danych.
var n as Number;
Po zadeklarowaniu m, m ma wartość liczbową 6:
var m := 1 + 5;
Aby ułatwić odróżnienie stałych od zmiennych, zaleca się, aby stałe zdefiniowane w definicjach procesów były zawsze deklarowane wielkimi literami, stałe zdefiniowane w definicjach działań zaczynały się wielką literą, a zmienne zaczynały się małą literą.
ValueSets
Aby użyć zestawu wartości, należy zadeklarować go za pomocą instrukcji const <VariableName> as valueSet(<Name>), aby móc później uzyskać dostęp do jego wpisów. Deklaracja tworzy zmienną typu Class i stałą z techniczną nazwą wpisu i jego identyfikatorem dla każdego wpisu zestawu wartości.
const OrderStatus as
valueSet(com.cisag.app.general.OrderStatus);
function create()
{
if (parameters.object:status = OrderStatus.RELEASED)
echo(valueSetName(OrderStatus, parameters.object:status);
}
Definicje typów
Aby uprościć sprawę, można zadeklarować i używać własnych typów danych w języku skryptowym systemu. Użycie typów ułatwia zrozumienie programu dzięki lepszym opcjom abstrakcji. Typ musi być zdefiniowany dla każdego użycia klas. Słowo kluczowe class może być używane tylko z deklaracją typu.
type PartnerCode as String;
type PartnerCodeList as PartnerCode[];
type WeekdaySum as Number[7];
var code as PartnerCode;
code := „4711”;
Definicja i zastosowanie klasy:
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”;
Przydziały
Podczas przypisywania, wartość może być przypisana do zmiennej, atrybutu klasy, wpisu na liście lub HashMap. Element, do którego coś jest przypisywane, znajduje się po lewej stronie przypisania. Przypisana wartość jest obliczana na podstawie terminu po prawej stronie przypisania.
Każda używana zmienna musi być zadeklarowana i dlatego ma ustalony typ. Tylko wartości tego typu mogą być przypisane do zmiennej.
Poniżej znajduje się kilka przykładów przypisywania wartości do zmiennej.
Po wykonaniu tego polecenia zmienna x ma wartość 2:
x := 2;
Po wykonaniu tego polecenia zmienna x ma wartość 7:
x := x * x + 3;
Po wykonaniu tych poleceń zmienna l zawiera pole z elementami Hello i World
var l as String[2];
l[0] := „Hello”;
l[1] := „World”;
Poniższe dwa polecenia są równoważne i przypisują wartość X do klucza a w HashMap c:
var c as HashMap;
c.a := „X”;
c[„a”] := „X”;
Bloki poleceń
Nawiasy klamrowe mogą być używane do łączenia sekwencji poleceń w jedno polecenie w bloku instrukcji. Wszystkie polecenia w bloku instrukcji są wykonywane w kolejności określonej w bloku. Jeśli polecenie zgłasza błąd podczas wykonywania, cały blok instrukcji kończy się błędem. Wiele poleceń i funkcji zgłasza błąd, jeśli otrzymają wartość zero jako parametr.
{
x := 2;
x := x * x + 3;
}
Polecenie warunkowe (if)
Polecenie warunkowe if wykonuje polecenie w zależności od wyniku warunku. Jeśli warunek jest prawdziwy, polecenie jest wykonywane. Jeśli warunek nie jest prawdziwy, polecenie jest pomijane.
x := -13;
if (x < 0)
x := 0;
Polecenie warunkowe z alternatywą (if … else )
Polecenie warunkowe z alternatywą if else wykonuje jedno z dwóch alternatywnych poleceń w zależności od wyniku warunku. Jeśli warunek jest prawdziwy, polecenie jest wykonywane przed else. Jeśli warunek nie jest prawdziwy, polecenie przed else jest pomijane i wykonywane jest polecenie po else.
x := 13;
if (x < 0) {
x := -1;
} else if (x > 0) {
x := 1;
}
Pętla z warunkiem (while)
Pętla z warunkiem while wykonuje polecenie tak długo, jak długo spełniony jest warunek. Warunek jest sprawdzany przed każdym wykonaniem polecenia, czyli w szczególności przed pierwszym wykonaniem. Jeśli warunek nie jest spełniony, polecenie nie jest wykonywane.
var i := 10;
var r := 0;
while (i > 0) {
r := r + i:
i := i – 1;
}
Liczba przebiegów w pętli while jest ograniczona. Więcej informacji można znaleźć w rozdziale Ograniczenie złożoności wydarzeń.
Pętla po wszystkich elementach (for)
Pętla for wykonuje polecenie dla wszystkich elementów listy. Kolejność elementów na liście jest zachowana. Jeśli lista nie zawiera żadnych elementów, polecenie nie jest wykonywane.
var l := list(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
var r := 0;
for (e : l) {
r := r + e:
}
Pętla po wszystkich elementach (for … as)
Pętla for wykonuje polecenie dla wszystkich elementów listy. Kolejność elementów na liście jest zachowana. Element można przekonwertować na określony typ za pomocą as.
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);
}
Polecenie końcowe (return)
Polecenie return kończy aktualnie wykonywaną funkcję.
{
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;
}
}
Wyjście z funkcji (return z wartością zwrotną)
Polecenie return kończy aktualnie wykonywaną funkcję i zwraca wartość zwracaną jako wynik funkcji.
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;
}
Funkcje
Funkcje języka skryptowego systemu
Język skryptowy systemu udostępnia wiele funkcji. Aby działać poprawnie, funkcje wymagają odpowiedniego środowiska, tj. muszą być spełnione pewne warunki ramowe. Rozróżnia się bazę danych z jednej strony i to, czy działanie jest wymagane, czy nie, z drugiej strony. Jeśli na przykład funkcja ma być używana w warunku przejścia definicji działania, funkcja nie może uzyskać dostępu do działania, ponieważ jest ono generowane dopiero w późniejszym czasie.
Zakres funkcji jest definiowany w konstruktorze funkcji. W klasie ParserFunctions możliwe zakresy są zdefiniowane w postaci stałych.
Kontekst użytkowania | Opis |
SYS_SCRIPT_OLTP | Może być używany w obiektach skryptowych, indywidualnych kontrolach i indywidualnych implementacjach hooków w kontekście bazy danych OLTP. |
WF_TRANSITION_REPOSITORY | Może być używany w warunkach przejścia i w funkcji tworzenia definicji działań dla działań w bazie danych repozytorium. |
WF_TRANSITION_OLTP | Może być używany w warunkach przejścia i w funkcji tworzenia definicji działań dla działań w bazie danych OLTP. |
WF_ACTIVITY_REPOSITORY | Może być używany w wyrażeniach i deklaracjach, ale nie w warunkach przejścia definicji działań dla działań w bazie danych repozytorium. |
WF_ACTIVITY_OLTP | Może być używany w wyrażeniach i deklaracjach, ale nie w warunkach przejścia definicji działań dla działań w bazie danych OLTP. |
WF_REPOSITORY | Odpowiada kontekstom użycia WF_TRANSITION_REPOSITORY i WF_ACTIVITY_REPOSITORY. Może być używany w definicjach działań dla działań w bazie danych repozytorium. |
WF_OLTP | Odpowiada kontekstom użycia WF_TRANSITION_OLTP i WF_ACTIVITY_OLTP. Może być używany w definicjach działań dla działań w bazie danych OLTP. |
OLTP | Odpowiada kontekstom użycia WF_SYS_SCRIPT_OLTP i WF_OLTP. Oznacza to, że kontekst użycia nie wymaga definicji działań, ale wymaga bazy danych OLTP. Obejmuje to funkcje takie jak loadPartner i loadItem. Może być używany w definicjach działań dla działań w bazie danych OLTP, a także w obiektach skryptów, indywidualnych kontrolach i indywidualnych implementacjach hooków w kontekście bazy danych OLTP. |
ALL | Może być używany we wszystkich kontekstach, tj. nie jest wymagana definicja działania ani baza danych OLTP. Obejmuje to funkcje takie jak createCisDate, getByPrimaryKey i getCisObjectList. |
Dalsze informacje i przykłady funkcji i poleceń można znaleźć w poniższej dokumentacji:
- Systemowy język skryptowy: Funkcje podstawowe
Funkcje kontekstu użytkowania ALL.
- Systemowy język skryptowy: Funkcje OLTP
Funkcje kontekstu użycia OLTP lub SYS_SCRIPT_OLTP.
- Systemowy język skryptowy: Funkcje workflow
Funkcje kontekstu użycia WF_REPOSITORY, WF_OLTP, WF_ACTIVITY_REPOSITORY, WF_ACTIVITY_OLTP, WF_TRANSITION_REPOSITORY lub WF_TRANSITION_OLTP.
Własne deklaracje funkcji
Funkcje podsumowują różne elementy języka skryptowego systemu w celu wyrażenia złożonych relacji. Jeśli funkcja nie zwraca wartości, jej wartość wynosi null.
function isPythagoreanTheorem(a as Number, b as Number, c as
Number) as Boolean
{
return a * a + b * b = c * c;
}
function create()
{
var tryPythagoreanTheorem := isPythagoreanTheorem(3, 4, 5)
}
Funkcje mogą być wywoływane w terminach. Funkcje obliczają wynik na podstawie parametrów wejściowych. W zależności od danej funkcji istnieją wymagania wstępne dotyczące liczby i typu parametrów wejściowych. Wymagania te są wyrażone w następujący sposób:
niech f będzie funkcją, której wynik ma typ danych R i która oczekuje typów danych od D1 do Dn od swoich parametrów od p1 do pn. Zapisuje się to następująco:
R f(D1 p1, …, Dn pn)
Jeśli typ danych jest całkowicie wolny, używany jest typ danych Unknown.
Deklaracje
W tym rozdziale opisano, gdzie można wprowadzać i używać deklaracji, które wstępnie przypisane funkcje są dostępne w każdym przypadku oraz kolejność oceny.
Deklaracje w definicjach działań
Deklaracje definicji działań mają następujące wstępnie przypisane funkcje:
Funkcja | Opis |
create | Funkcja create jest wywoływana podczas tworzenia działania. Ponieważ działanie nie zostało jeszcze utworzone w momencie wywołania, informacje o działaniu są dostępne tylko w ograniczonym zakresie w funkcji create. |
applyDefaults | Funkcja applyDefaults jest wywoływana po otwarciu okna dialogowego Wyniki działania. W przypadku węzła początkowego z wynikiem działania dialog, a tym samym funkcja applyDefaults, jest wywoływana przed funkcją create. W przypadku wszystkich innych działań wywołanie następuje dopiero po wywołaniu funkcji create. Ponieważ celem funkcji applyDefaults jest inicjalizacja pól okna dialogowego Wyniki działania i wstępne przypisanie wartości, środowisko nie jest trwale zapisywane po zakończeniu wywołania. Wszelkie przypisania zmiennych w ramach funkcji applyDefaults nie są zatem dostępne dla innych funkcji. |
validate | Funkcja walidacji jest wywoływana w oknie dialogowym Wyniki działania przed zaakceptowaniem wyników działania. Funkcja ta jest również wywoływana podczas zapisywania działania w aplikacji Działania. Parametr stanu wskazuje przyszły status działania.
Funkcja validate zwraca wartość typu danych Boolean. Jeśli zwracana wartość jest false, wyniki działań nie mogą zostać zaakceptowane. W węźle startowym wyświetlenie komunikatu o błędzie za pomocą polecenia sendMessage uniemożliwia zaakceptowanie wyników działań. Jeśli użytkownik zamknie okno dialogowe Wyniki działania za pomocą przycisku [Usuń], żadne działanie nie zostanie utworzone. Ponieważ celem funkcji validate jest sprawdzenie danych wprowadzonych przez użytkownika w oknie dialogowym Wyniki działania, środowisko nie jest zapisywane na stałe po zakończeniu wywołania. Wszelkie przypisania zmiennych w ramach funkcji validate nie są zatem dostępne dla innych funkcji. |
validatePrecondition | Funkcja validatePrecondition jest wywoływana, gdy zmienia się status działania, jeśli w polu Prognoza wybrano wartość Deklaracja. Funkcja ta jest również wywoływana, gdy działanie jest zapisywane, nawet jeśli status nie ulega zmianie. Parametr stanu wskazuje przyszły status działania.
Funkcja validatePrecondition zwraca wartość typu danych Boolean. Jeśli warunek wstępny ma wartość false, działanie jest automatycznie kończone bez przetwarzania. Żadne działanie nie zostanie utworzona w węźle początkowym, jeśli funkcja wyświetli komunikat o błędzie za pomocą polecenia sendMessage. |
validatePostcondition | Funkcja validatePostcondition jest wywoływana przed zakończeniem działania, jeśli w polu Warunek końcowy wybrano wartość Deklaracja. Parametr stanu wskazuje przyszły status aktywności.
Funkcja validatePostcondition zwraca wartość typu danych Boolean. Jeśli warunek końcowy wynosi false, działanie nie może zostać zakończone. Działanie nie może zostać zakończone, nawet jeśli funkcja wysyła komunikat o błędzie za pomocą polecenia sendMessage. Funkcja validatePostcondition jest wywoływana tylko wtedy, gdy operatorem jest użytkownik. Nie jest ona wywoływana w przypadku działań przetwarzanych przez system lub zlecenie przetwarzania. |
validateSeriesCondition | Funkcja validateSeriesCondition jest wywoływana zgodnie z wzorcem serii zapisanym w szablonie serii, jeśli w polu Warunek serii wybrano wartość Deklaracja. Funkcja validateSeriesCondition zwraca wartość zwrotną typu danych Boolean. Jeśli warunek serii wskazuje false, seria jest anulowana i nie są generowane żadne dalsze działania serii. |
validateSelection | Funkcja validateSelection jest wywoływana w działaniu typu Warunek wstępny, gdy użytkownik łączy obiekt biznesowy z działaniem. Funkcja validateSelection zwraca wartość typu danych Boolean. Jeśli warunek wyboru wskazuje false, link jest odrzucany z komunikatem o błędzie. Link jest również odrzucany, jeśli funkcja wysyła komunikat o błędzie za pomocą polecenia sendMessage. |
close | Funkcja zamknięcia jest wywoływana, gdy działanie zostanie zakończone lub zakończone bez przetwarzania. Parametr stanu wskazuje przyszły status działania. |
Deklaracje w definicjach procesów
Deklaracje definicji procesu są dodawane do globalnych deklaracji definicji działania przed ich oceną. Z tego powodu deklaracje definicji procesu mogą zawierać tylko deklaracje, które mogą być również zadeklarowane poza deklaracjami definicji działań.
const MaxAmount := „123”;
function helloWorld () as String
{
return „Hello World!”;
}
Stała MaxAmount i funkcja helloWorld mogą być używane bez ograniczeń we wszystkich definicjach działań definicji procesu, które używają tego samego języka skryptowego co definicja procesu.
Należy pamiętać, że mogą istnieć dalsze ograniczenia w zależności od używanego silnika skryptowego. Na przykład silnik JavaScript Nashorn nie pozwala na deklarowanie stałych.
Należy również pamiętać, że oddzielna definicja typu (klasa) zadeklarowana w definicji procesu nie może być używana w definicjach działań.
Kolejność oceny w definicjach działania
Gdy nowe działanie jest tworzone z powodu zdarzenia, środowisko, w którym wykonywane są warunki, polecenia i warunki, jest inicjowane wartościami zmiennych określonymi przez zdarzenie. Jeśli aktywowana definicja działania otrzyma zdarzenie, wyrażenia tej definicji działania są oceniane w kolejności opisanej poniżej.
W węźle startowym
Podczas tworzenia działania dla węzła początkowego funkcje są wywoływane w następującej kolejności:
- Globalne deklaracje definicji procesu
- Globalne deklaracje definicji działania (poza funkcjami)
- applyDefaults
- validate
- create
- validatePrecondition
- close
Funkcje applyDefaults i validate są wywoływane tylko wtedy, gdy definicja działania ma zdarzenie działania, a proces jest uruchamiany ręcznie, tj. dla typu zdarzenia Akcja użytkownika lub dla węzłów startowych bez definicji zdarzenia. Te dwie funkcje nie są wywoływane dla typów zdarzeń Zaprogramowane zdarzenie i Jednostka biznesowa.
Ogólne
Jeśli nie jest to węzeł początkowy, funkcje są wywoływane w następującej kolejności:
- Globalne deklaracje definicji procesu
- Globalne deklaracje definicji działania (poza funkcjami)
- Stan przejściowy
- create
- Parametry aplikacji
- Wydruk dla operatorów
- validatePrecondition
- applyDefaults
- validate
- validatePostcondition
- close
Funkcja validatePrecondition jest wywoływana za każdym razem, gdy zmienia się stan działania, tj. zwykle jest wywoływana kilka razy.
Funkcje applyDefaults i validate są wywoływane tylko wtedy, gdy definicja działania ma wynik działania, a operatorem jest użytkownik. Jeśli działanie jest zakończone przez aplikację typu lista, okno dialogowe wyników działania nie jest otwierane i żadna z funkcji nie jest wywoływana.
Jeśli operatorem działania nie jest użytkownik, ale system lub zlecenie przetwarzania, funkcja validatePostcondition nie jest wywoływana.
Polecenia
Definicje działania zarejestrowane w wersji 5.1 lub wcześniejszej mogą zawierać polecenia zamiast deklaracji. Polecenia są wykonywane podczas tworzenia działania i odpowiadają w przybliżeniu funkcji create. Definicje działania używające poleceń nie mogą wykonywać skryptów podczas wprowadzania zdarzeń i kończenia działania. Dlatego zaleca się przekształcenie poleceń w deklaracje.
W tym celu należy skopiować skrypt z zakładki Polecenia do funkcji create na zakładce Deklaracje i usunąć skrypt z zakładki Polecenia. Po zapisaniu definicji działania karta Polecenia zostanie ukryta, gdy jej pole edytora będzie puste.
Ponieważ stałe i zmienne zadeklarowane na zakładce Polecenia są dostępne we wszystkich polach definicji działania, należy również zadeklarować wszystkie stałe, zmienne i definicje typów, które są używane w innych polach definicji działania, np. w warunku wstępnym lub w polu parametrów aplikacji, poza funkcją tworzenia.
Poniższy skrypt jest przechowywany na zakładce Polecenia:
var editors as Guid[];
var customer := parameters.object->CustomerData->CustomerPartner;
var responsible := loadTargetsOfPartnerRelations(customer:guid, parameters.object->DeliveryPartnerData->Organisation:guid, „Responsible”);
for (r : responsible) {
editors := union(editors, resolvePartner(r:guid));
}
Zmienna editors jest używana jako wyrażenie operatora. Zmienna customer jest używana jako wartość parametru Partner aplikacji com.cisag.app.general.partner.ui.PartnerMaintenance.
Aby przekształcić polecenia w deklaracje, deklaracja edytorów i zmiennych klienta jest umieszczana poza funkcją create.
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->Organisation:guid, „Responsible”);
for (r : responsible) {
editors := union(editors, resolvePartner(r:guid));
}
}
Obiekty i biblioteki skryptów
Niestandardowe deklaracje funkcji, zmiennych i stałych mogą być zapisywane w systemach klienta jako obiekty skryptów. W tym celu należy użyć aplikacji Obiekty deweloperskie. Zaletą integracji obiektów skryptu jest to, że niestandardowe deklaracje mogą być zarządzane centralnie; zmiany w obiektach skryptu mają natychmiastowy wpływ na skrypty, z którymi są zintegrowane.
Jako obiekty deweloperskie, obiekty skryptów podlegają wersjonowaniu. Aplikacja Lista: Obiekty deweloperskie systemu produkcyjnego może być używana do przenoszenia obiektów skryptów utworzonych w systemie testowym (podobnie jak szablony workflow) do systemu produkcyjnego.
W aplikacji Biblioteki można również wprowadzać własne deklaracje i podsumowywać je w bibliotece. Podobnie jak szablony workflow na wszystkich bazach danych OLTP systemu.
Aby obiekt skryptu lub biblioteka mogły zostać zintegrowane, muszą używać tego samego języka skryptowego co skrypt. Jeśli skrypt został utworzony w języku skryptowym systemu, do zintegrowania obiektu skryptu lub biblioteki należy użyć polecenia importu. Jeśli skrypt został utworzony w języku JavaScript, należy użyć polecenia load. Więcej informacji i przykładów tych dwóch poleceń można znaleźć w dokumentacji Język skryptowy systemu: Funkcje podstawowe.
Indywidualne weryfikacje
Indywidualna weryfikacja rozszerza kontrolę określonej jednostki biznesowej. Ta rozszerzona kontrola jest używana we wszystkich kanałach wejściowych i wyjściowych, tj. w aplikacjach dialogowych, a także podczas importu lub eksportu. Wynik tych niestandardowych kontroli można wyświetlić jako niestandardowy komunikat. Ten indywidualny komunikat jest wyświetlany wraz z komunikatami zapisanymi w bazie danych repozytorium w odpowiednim kontekście.
Aplikacja Indywidualne weryfikacje wyświetla funkcje wybranego hook contract. Na przykład hook contract dla zamówień sprzedaży ma następujące funkcje.
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))
{ }
Można użyć przekazanych widoków obiektów persistent i current, aby porównać zmiany, które mają zostać zweryfikowane w current z trwale zapisanym stanem jednostki biznesowej w persistent. W przypadku niektórych hook contract (takich jak kampanie) funkcje nie mają parametru current. Aby ocenić zapisany stan jednostki biznesowej również w takich przypadkach, można otworzyć jednostkę biznesową za pomocą funkcji skryptu getByPrimaryKey, na przykład, ponieważ wiele atrybutów widoku obiektu jest również dostępnych w jednostce biznesowej.
Jeśli jednostka biznesowa ma inne pole, można sprawdzić jego wartość za pomocą innej funkcji o tej samej nazwie, ale z przyrostkiem Extension_, po którym następuje nazwa schematu. Funkcja ta zawiera dodatkowy parametr extension, który zapewnia tablicę hash z nazwami i wartościami wszystkich innych pól jednostki biznesowej. Jeśli element ma inne pole w widoku podstawowym o nazwie EXTNUM i typie pola Tekst, tabela hash może mieć zawartość {EXTNUM_val=[S=], EXTNUM_id=[N=7070]}.
Poniższe indywidualne sprawdzenie powoduje wyświetlenie komunikatu o błędzie, jeśli dodatkowe pole EXTNUM jest puste:
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(„Brak wartości.”));
}
Jeśli pierwsze dodatkowe pole jednostki biznesowej zostanie utworzone po wprowadzeniu indywidualnej weryfikacji, można ponownie wprowadzić indywidualną weryfikację, aby automatycznie wygenerować szablon dodatkowej funkcji z parametrem rozszerzenia.
Ocena informacji
Różne zmienne są wypełniane w zależności od stanu inicjalizacji nowego działania. Na przykład żadne działanie nie istnieje w momencie oceny warunku przejścia i funkcji tworzenia. Wartości zmiennej działania są zatem niedostępne lub dostępne tylko w ograniczonym zakresie.
Wydarzenie (event)
Jeśli definicja działania zawiera definicję zdarzenia, zmienna zdarzenia zawiera tablicę hash z informacjami o wywołanym zdarzeniu.
Zmienna | Wartość |
type |
Zmienna type zawiera typ zdarzenia. Możliwe wartości są zdefiniowane w ValueSet com.cisag.sys.workflow.EventTypeLimited. Istotne są tutaj następujące wartości:
|
subtype | Zmienna subtype zawiera podtyp zdarzenia. W przypadku zaprogramowanych zdarzeń jest to wartość wpisu ValueSet. Jeśli do zdarzenia nie przypisano żadnego ValueSet, wartość wynosi 0. Dla typu zdarzenia Jednostka biznesowa możliwe wartości są zdefiniowane w ValueSet com.cisag.sys.kernel.ObjectChangeType:
Należy pamiętać, że ustawienie znacznika usunięcia dla obiektu biznesowego jest uważane za zmianę. Obiekt biznesowy nie jest usuwany z bazy danych, dopóki nie zostanie zreorganizowany. Podtyp może być używany z typem zdarzenia Jednostka biznesowa, aby poprawnie ocenić obiekt biznesowy dla definicji zdarzeń różnych podtypów. Jeśli na przykład numer artykułu ma być wyświetlany w tekście działania dla wszystkich trzech podtypów, można użyć następującego skryptu: var itemNumber := String; if (event.subtype = 3) itemNumber := parameters.oldObject:number; else itemNumber := parameters.newObject:number; format(„itemNumber”, itemNumber); Jeśli skrypt oceni parametry parameters.object lub parametryrers.newObject dla podtypu 3, wystąpi błąd uruchomieniowy, ponieważ obiekt biznesowy już nie istnieje. |
guid | Zmienna guid zawiera identyfikator GUID zaprogramowanego zdarzenia lub identyfikator GUID obiektu biznesowego dla zdarzenia Jednostka biznesowa. Można użyć wyrażenia objectName(event.guid), aby określić pełną nazwę techniczną obiektu biznesowego dla typu zdarzenia Jednostka biznesowa. |
database | Zmienna bazy danych zawiera identyfikator GUID bazy danych, w której zdarzenie zostało wywołane. Aby określić nazwę bazy danych, można użyć wyrażenia databaseName(event.database).
Aby określić nazwę systemu, można wywołać metodę Java.type(’com.cisag.pgm.util.ServerInfo’).getSystemName() w deklaracji wykorzystującej JavaScript. Metoda Java.type(’com.cisag.pgm.util.ServerInfo’).getSVMName() zwraca nazwę serwera. |
parameters |
Zmienna parameters zawiera tablicę hash z dodatkowymi informacjami na temat wywołanego zdarzenia. Informacje zawarte w parametrach różnią się w zależności od typu i podtypu zdarzenia:
Zmienna parametrów została opisana szczegółowo w rozdziale Parametry. |
Parametry
W zależności od typu i podtypu zdarzenia, zmienna parameters zawiera tablicę hash z dalszymi informacjami na temat wywołanego zdarzenia. Zmienna parametrów jest dostępna tylko w definicjach działania bez odniesienia do definicji procesu i w węzłach zdarzeń. Należy zatem zapisać parametry, które będą potrzebne później w procesie, w zmiennych procesu w węźle startowym.
Typ zdarzenia Zaprogramowane zdarzenie
Zaprogramowane zdarzenia mają dokładnie te parametry, które zostały wprowadzone dla danego zdarzenia w aplikacji Obiekty deweloperskie.
Jeśli działanie ma zostać utworzone tylko wtedy, gdy nazwa ma taką samą wartość jak definicja działania, można użyć warunku przejścia parameters.name = definition:code.
Poniższe przypisanie przyjmuje wartość wpisu user tabeli hash jako wyzwalacz procesu:
process.initiator := cast(String, parameters.parameters.user);
Ponieważ tablica hash nie jest typowana, wpisy muszą zostać przekonwertowane na prawidłowe typy danych za pomocą funkcji rzutowania, zanim będą mogły zostać użyte w deklaracjach.
Typ zdarzenia Jednostka biznesowa
Zdarzenie typu Jednostka biznesowa jest możliwe dla obiektów biznesowych w bazie danych repozytorium lub bazie danych OLTP. Parametry zdarzenia zależą od podtypu Insert, Change lub Delete i typu monitorowanego obiektu biznesowego.
Zmienna | Wartość |
userGuid | Zmienna userGuid zawiera identyfikator GUID użytkownika, który zmienił obiekt biznesowy. W przypadku zdarzenia typu Jednostka biznesowa wyzwalacz procesu jest automatycznie wstępnie przypisywany w process.Initiator. Następujące przypisanie definiuje również wyzwalacz procesu jako właściciela procesu:
process.Owner := userName(parameters.userGuid); |
obiect | Zmienna obiektu zawiera odniesienie do zmienionego obiektu biznesowego. Zmienna object odzwierciedla aktualny stan obiektu biznesowego w momencie oceny. Dla podtypu Delete zmienna object ma wartość zero. Zmienna obiektu może być używana na przykład do oceny bieżącego stanu zmienionego obiektu biznesowego na początku okresu przetwarzania.
Poniższy warunek wstępny sprawdza, czy dokument, dla którego zdarzenie zostało wywołane, został zwolniony. Jeśli tak nie jest, warunek wstępny jest fałszywy, a działanie jest automatycznie kończone bez przetwarzania: parameters.object:status = 2 /* ORDER_RELEASED */ |
oldObject | Zmienna oldObject zawiera wartość zmienionego obiektu biznesowego bezpośrednio przed wyzwoleniem zdarzenia. Dla podtypu Insert zmienna oldObject ma wartość zero. Poniższy warunek przejścia sprawdza, czy atrybut number został zmieniony:
parameters.oldObject:number <> parameters.newObject:number |
newObject | Zmienna newObject zawiera wartość zmienionego obiektu biznesowego bezpośrednio po zmianie. Dla podtypu Delete zmienna newObject ma wartość zero. Poniższy warunek wstępny sprawdza, czy dokument lub obiekt biznesowy został ponownie zmieniony między wyzwoleniem zdarzenia a rozpoczęciem okresu przetwarzania:
parameters.object:updateInfo.updateTime = parameters.newObject:updateInfo.updateTime |
entity | Jeśli zmodyfikowany obiekt biznesowy jest zależny, zmienna encji zawiera odniesienie do encji biznesowej powiązanej z obiektem biznesowym poprzez relację _entity. To, czy obiekt biznesowy jest zależny, można sprawdzić w aplikacji Obiekty deweloperskie. Jeśli w polu Typ wybrana jest wartość Dependent, obiekt biznesowy jest zależny. Przykładem elementu zależnego jest pozycja zamówienia sprzedaży. Jeśli definicja działania ma definicję zdarzenia dla pozycji zamówienia sprzedaży, wówczas parameters.object odwołuje się do obiektu biznesowego com.cisag.app.sales.obj.SalesOrderDetail (pozycja zamówienia sprzedaży), a parameters.entity odwołuje się do obiektu biznesowego com.cisag.app.sales.obj.SalesOrder (zamówienie sprzedaży).
Jeśli obiekt biznesowy nie jest zależny, jednostka nie jest zdefiniowana. Dla podtypu Delete zmienna entity ma wartość zero. |
oldEntity | Jeśli zmieniony obiekt biznesowy jest zależny, zmienna oldEntity zawiera wartość jednostki biznesowej powiązanej z obiektem biznesowym poprzez relację _entity bezpośrednio przed zmianą. Jeśli obiekt biznesowy nie jest zależny, oldEntity nie jest zdefiniowane. Dla podtypu Insert oldEntity ma wartość zero. |
newEntity | Jeśli zmieniony obiekt biznesowy jest zależny, zmienna newEntity zawiera wartość jednostki biznesowej powiązanej z obiektem biznesowym poprzez relację _entity bezpośrednio po zmianie. Jeśli obiekt biznesowy nie jest zależny, newEntity nie jest zdefiniowane. Dla podtypu Insert newEntity ma wartość zero. |
Typ zdarzenia Akcja użytkownika
Zdarzenie typu Akcja użytkownika jest możliwe dla jednostek biznesowych w bazie danych repozytorium lub bazie danych OLTP. Zdarzenia dla jednostek zależnych nie są obsługiwane. Zdarzenie ma następujące parametry.
Zmienna | Wartość |
userGuid | Zmienna userGuid zawiera identyfikator GUID użytkownika, który zmienił jednostkę biznesową. W przypadku zdarzenia typu Akcja użytkownika wyzwalacz procesu jest automatycznie wstępnie przypisywany w process.initiator. Następujące przypisanie definiuje również wyzwalacz procesu jako właściciela procesu:
process.Owner := userName(parameters.userGuid); Poniższy warunek przejścia sprawdza, czy użytkownik jest pracownikiem odpowiedzialnym za dokument. Jeśli tak nie jest, warunek przejścia jest fałszywy, a akcja użytkownika jest dezaktywowana dla użytkownika w menu kontekstowym dokumentu: parameters.userGuid = cast(Guid, first(parameters.object:responsible, parameters.userGuid)) Jeśli dokument nie ma odpowiedzialnego pracownika, akcja użytkownika pozostaje aktywna w menu kontekstowym wszystkich użytkowników. |
obiect | Zmienna obiektu zawiera odniesienie do jednostki biznesowej, dla której wywołano akcję użytkownika. Zmienna obiektowa odzwierciedla aktualny stan obiektu biznesowego w momencie oceny. Poniższy warunek przejścia sprawdza, czy dokument jest przetwarzany. Jeśli tak nie jest, warunek przejścia jest fałszywy, a akcja użytkownika jest dezaktywowana w menu kontekstowym dokumentu:
parameters.object:status = 1 /* ORDER_ENTERED */ |
Bez definicji zdarzenia
Proces bez definicji zdarzenia w węźle startowym można uruchomić tylko ręcznie. Aby móc zdecydować w węźle startowym, czy użytkownik jest upoważniony do uruchomienia procesu, zmienna parametrów dostarcza odpowiednich informacji, nawet jeśli nie ma zdarzenia.
Zmienna | Wartość |
userGuid | Zmienna userGuid zawiera identyfikator GUID użytkownika, który uruchamia proces ręcznie. Poniższe wyrażenie w polu Wyrażenie dla warunku wstępnego uniemożliwia uruchomienie procesu, jeśli użytkownik nie jest przypisany do roli workflow MANAGERS.
contains(resolveRole(„MANAGERS”, parameters.userGuid) |
database | Zmienna bazy danych zawiera identyfikator GUID bazy danych, w której uruchamiany jest proces. Przykłady zostały przedstawione w rozdziale Zdarzenia (events). |
organization | W przypadku ręcznie uruchomionego procesu zmienna organizacji zawiera identyfikator GUID organizacji wybranej w aplikacji, z której proces został uruchomiony. |
Proces
Jeśli definicja działania jest powiązana z definicją procesu, zmienna procesu zawiera tablicę hash z informacjami o procesie.
Zmienna | Opis |
Code | Zmienna Code zawiera identyfikator procesu. |
Database | Zmienna Database zawiera identyfikator GUID bazy danych. Ta zmienna jest dostępna tylko w funkcji tworzenia węzła początkowego. |
Description | Zmienna Description zawiera nazwę procesu. |
EndTime | Zmienna EndTime zawiera czas zakończenia okresu przetwarzania. |
ErrorCode | Zmienna ErrorCode zawiera kod błędu po wystąpieniu błędu w procesie. Ocena ma zatem sens tylko w węźle błędu. Kod błędu i opis błędu można ustawić przez przypisanie. Polecenie abortProcess może być następnie użyte do zakończenia procesu za pośrednictwem węzła błędu.
process.ErrorCode := „USER_ERROR”; process.ErrorDescription := „Błąd zgłoszony przez użytkownika w funkcji create() aktywności ” + activity:code + „.”; abortProcess(); |
ErrorDescription | Zmienna ErrorDescription zawiera opis błędu powiązany z kodem błędu po wystąpieniu błędu w procesie. Ocena ma zatem sens tylko w węźle błędu. |
FinishTime | Zmienna FinishTime zawiera czas zakończenia procesu. |
Initiator |
Zmienna Initiator zawiera wyzwalacz procesu. Wyzwalacz procesu jest dostępny tylko z funkcji zamykania węzła początkowego. Wyzwalacz procesu jest ustawiany automatycznie dla zdarzeń typu Jednostka biznesowa i Akcja użytkownika. Dla typu zdarzenia Zaprogramowane zdarzenie i dla procesów bez definicji zdarzenia, wyzwalacz procesu może być zdefiniowany tylko poprzez przypisanie nazwy użytkownika. process.Initiator := userName(getByBusinessKey(CisObject(com.cisag.app.inventory.obj.InventoryTransaction), parameters.internalNumber):updateInfo.createUser) przypisuje użytkownikowi, który wprowadził lub utworzył rezerwację materiału, która wywołała zaprogramowane zdarzenie com.cisag.app.inventory.MinimumOnhand proces jako inicjator. Wyzwalacz można zmienić w razie potrzeby podczas wykonywania procesu. |
Number1 |
Zmienna Number1 zawiera pierwszy ogólny atrybut wyniku liczbowego. Wartość może być zmieniana zgodnie z wymaganiami przez przypisanie. process.Number1 := parameters.object:totalValues.grossValue.amount przypisuje całkowitą kwotę brutto zamówienia, do którego odwołuje się parametr parameters.object, do atrybutu Number1. |
Number2 | Zmienna Number2 zawiera drugi ogólny atrybut wyniku liczbowego. Wartość może być zmieniana zgodnie z wymaganiami przez przypisanie. |
OrganizationalUnit | Zmienna OrganizationalUnit zawiera identyfikator GUID organizacji. Kontekst organizacyjny zdarzenia może zostać przekazany do procesu poprzez przypisanie. Przypisana organizacja ma wpływ między innymi na autoryzację niezaangażowanych użytkowników. Jeśli w definicji procesu wybrano opcję Standard dla niezaangażowanych użytkowników, a działanie jest przypisane do organizacji, tylko ci niezaangażowani użytkownicy, którzy są przypisani do tej samej organizacji, mogą wyświetlić proces. |
Owner | Zmienna Owner zawiera osobę odpowiedzialną za proces. Właściciel procesu jest dostępny tylko w funkcji zamykania węzła początkowego. W procesie ręcznym ze zdarzeniami działania w węźle początkowym, właściciel nie może zostać oceniony w funkcjach applyDefaults i validate. Wartość można zmienić, przypisując nazwę użytkownika lub określając rolę workflow.
process.Owner := process.Initiator również przypisuje wyzwalacz do procesu jako osoby odpowiedzialnej. Pochodzenie osoby odpowiedzialnej za proces można sprawdzić w atrybucie activity->Process:processData.sourceOfOwner. Wartość 1 oznacza użytkownika, a wartość 2 — rolę workflow. |
previousStep | Jeśli działanie ma tylko jedno działanie poprzedzające, zmienna previousStep zawiera odniesienie do działania poprzedzającego. Jeśli działanie nie ma działania poprzedzającego, co ma miejsce na przykład w przypadku węzła początkowego, lub ma kilka działań poprzedzających, zmienna ma wartość domyślną zero. Wyrażenie process.previousStep:completeUser zwraca identyfikator GUID użytkownika, który zakończył poprzednie działanie swoim zadaniem.
Należy pamiętać, że nazwa tego atrybutu zaczyna się od małej litery. |
previousSteps | Jeśli działanie ma kilka działań poprzedzających, np. poprzez użycie węzła scalania, zmienna previousSteps zawiera listę z odniesieniem do każdego działania poprzedzającego. Jeśli działanie nie ma poprzednika lub ma tylko jednego poprzednika, zmienna ma wartość domyślną zero. Poniższy skrypt przypisuje do zmiennej users listę z identyfikatorami GUID wszystkich użytkowników, którzy ukończyli poprzednie działanie ze swoim zadaniem.
var users as Guid[]; for (a : process.previousSteps) users := union(users, list(a:completeUser)); Należy pamiętać, że nazwa tego atrybutu zaczyna się od małej litery. |
StartTime | Zmienna StartTime zawiera czas rozpoczęcia okresu przetwarzania. |
State | Zmienna State zawiera status procesu. |
Result | Zmienna Result zawiera ogólny wynik procesu. Wartość może być zmieniana zgodnie z wymaganiami przypisania, ale jest ograniczona do 80 znaków. Poniższe przypisanie w funkcji close podsumowuje wiele indywidualnych wyników procesu zatwierdzania dla zamówienia, do którego odwołuje się zmienna procesowa PO, w ogólny wynik procesu:
process.result := process.PO:number + ” złożony przez ” + process.Initiator + ” został ” + results.approvalResult + ” przez ” + userName(activity:completeUser); Wynik sprawdzenia można znaleźć w wyniku działania approvalResult. |
Text1 |
Zmienna Text1 zawiera pierwszy ogólny atrybut wyniku dla łańcuchów znaków. Wartość może być zmieniana zgodnie z wymaganiami przez przypisanie. process.Text1 := „APPROVED” |
Text2 | Zmienna Text2 zawiera drugi ogólny atrybut wyniku dla łańcuchów znaków. Wartość może być zmieniana zgodnie z wymaganiami przez przypisanie. |
Text3 | Zmienna Text3 zawiera trzeci ogólny atrybut wyniku dla łańcuchów znaków. Wartość może być zmieniana zgodnie z wymaganiami przez przypisanie. |
Text4 | Zmienna Text4 zawiera czwarty ogólny atrybut wyniku dla łańcuchów znaków. Wartość może być zmieniana zgodnie z wymaganiami przez przypisanie. |
Text5 | Zmienna Text5 zawiera piąty ogólny atrybut wyniku dla łańcuchów znaków. Wartość może być zmieniana zgodnie z wymaganiami przez przypisanie. |
Timestamp1 |
Zmienna Timestamp1 zawiera pierwszy ogólny atrybut wyniku dla punktów w czasie. Wartość może być zmieniana zgodnie z wymaganiami przez przypisanie. process.Timestamp1 := now(); |
Timestamp2 | Zmienna Timestamp2 zawiera drugi ogólny atrybut wyniku dla punktów w czasie. Wartość może być zmieniana zgodnie z wymaganiami przez przypisanie. |
W zależności od kontekstu wykonania i stanu działania dostępne są różne atrybuty. W funkcjach applyDefaults i validate węzła startowego wszystkie atrybuty nadal mają swoje wartości domyślne. Ponieważ węzeł startowy nie ma poprzednika, atrybuty previousStep i previousSteps zawsze mają wartość domyślną zero w węźle startowym.
W funkcji tworzenia węzła początkowego atrybuty OrganizationalUnit i Database mają wartości z bieżącego kontekstu. Aby również zapytać o te atrybuty w funkcjach applyDefaults i validate węzła startowego, można zamiast tego ocenić zmienne event i parameters.
W funkcji zamykania węzła początkowego i we wszystkich funkcjach kolejnych węzłów działań i zdarzeń wszystkie atrybuty z wyjątkiem OrganisationalUnit i Database mają wartości z bieżącego kontekstu. Jeśli użytkownik chce ocenić te dwie wartości w późniejszym momencie procesu, powinien zapisać je w funkcji zamykania w zmiennych procesu.
Działanie (activity)
Jeśli warunek przejścia jest spełniony i funkcja create została wykonana, tworzone jest nowe działanie. Od tego momentu zmienna działania stanowi odniesienie do utworzonego działania.
Aby uprościć ocenę, niektóre atrybuty są już dostępne w funkcji tworzenia. Można na przykład przeanalizować identyfikację i status działania. Inne informacje, takie jak relacje z innymi obiektami biznesowymi, można analizować dopiero po wykonaniu funkcji tworzenia.
Z tego samego powodu niektóre atrybuty są dostępne w funkcji zamykania, które są zapisywane na stałe dopiero po zakończeniu działania. Na przykład można użyć atrybutu activity:completeUser, aby przeanalizować, który użytkownik aktualnie kończy działanie.
Po wykonaniu funkcji tworzenia można ocenić proces przy użyciu relacji Process. Na przykład wyrażenie
activity->Process:code określa identyfikację procesu.
Definicja działania (definition)
Zmienna definicji zawiera odniesienie do definicji działania, która otrzymała zdarzenie i za pomocą której ma zostać utworzone nowe działanie. Ta zmienna jest dostępna wszędzie w definicji działania.
Używając warunku przejścia parameters.name = definition:code w definicji działania dla zaprogramowanego zdarzenia com.cisag.pgm.workflow.GenericOLTPEvent, zaprogramowane zdarzenie może zostać wyzwolone z identyfikacją definicji działania jako nazwy, która ma zostać użyta do wygenerowania działania.
Definicja procesu powiązana z definicją działania może być również oceniana za pomocą zmiennej definicji. Na przykład wyrażenie definition->ProcessDefinition:code określa identyfikację definicji procesu.
Parametry akcji (actionParameters)
Jeśli funkcja create została wykonana i działanie została wygenerowane, zmienna actionParameters zawiera tablicę hash z wartościami wszystkich parametrów aplikacji. Zmienna ta może zostać obliczona na przykład w warunku wstępnym lub w funkcji zamykania.
Wyniki działania (results)
Po wykonaniu funkcji create i utworzeniu działania zmienna results zawiera tablicę hash z wartościami wszystkich wyników działania. Zmienna results jest często używana w funkcji close do zapisywania wyników działania w zmiennych procesu.
- approvalStatus typu pola Pole wyboru z dwiema wartościami APPROVED i REJECTED.
- komentarz typu pola Wielowierszowe pole tekstowe.
W funkcji applyDefaults pole wyboru approvalStatus jest wstępnie przypisane do REJECTED:
function applyDefaults()
{
results.approvalStatus := „REJECTED”;
}
W funkcji zatwierdzania wyświetlany jest indywidualny komunikat COMMENT, jeśli użytkownik wybrał wartość APPROVED bez wprowadzania komentarza:
function validate(state as Number)
{
if (results.approvalStatus <> „APPROVED” and results.comment = „”)
sendMessage(results.comment_id, „COMMENT”, list());
}
Przyrostek _id po nazwie wyniku działania powoduje wyświetlenie kolorowego narożnika komunikatu w polu komentarza.
Na koniec, dwa wyniki działania są zapisywane w zmiennych procesowych o tej samej nazwie w funkcji zamykania:
function close(state as Number)
{
if(results.approvalStatus = „APPROVED”)
process.approvalStatus := „APPROVED”;
inny
process.approvalStatus := „REJECTED”;
process.comment := results.comment;
}
Inne działania w procesie mogą następnie wykorzystać te wartości.
W powyższym przykładzie możliwe byłoby również prostsze przypisanie process.approvalStatus := results.approvalStatus. Różnica polega na tym, że przy takim przypisaniu zmienna process.approvalStatus miałaby niezdefiniowany wynik, jeśli użytkownik ukończy zadanie lub działanie za pośrednictwem aplikacji typu lista, ponieważ w tym przypadku nie jest możliwe wprowadzenie wyników.
Innym wariantem byłoby przypisanie zdarzenia działania w zależności od statusu działania: jeśli użytkownik ukończy działanie za pomocą aplikacji typu lista, jest to uważane za niejawne zatwierdzenie. Jeśli działanie zostanie zakończone bez przetworzenia, jest to uważane za niejawne odrzucenie:
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”;
inny
process.approvalStatus := „REJECTED”;
}
Możliwe jest również wybranie wartości Wykonaj za pomocą paska narzędzi workflow w polu Potwierdzenie realizacji na zakładce Opracowanie definicji działania, aby uniemożliwić jej ukończenie przez aplikację typu lista.
Kontrola dialogów (dialog)
Jeśli definicja działania ma wynik działania typu pola page, okno dialogowe wprowadzania wyników działania składa się z kilku stron. Aby móc przełączać się między stronami za pomocą skryptów, zmienna parametrów udostępnia następujące atrybuty:
Zmienna | Opis |
page | Zmienna page zawiera techniczną nazwę bieżącej strony w oknie dialogowym wprowadzania wyników działania. Jeśli bieżąca strona jest pierwszą stroną okna dialogowego, wartość page jest pustym ciągiem znaków. |
nextPage | Jeśli nazwa techniczna zdarzenia działania typu pola Page jest przypisana do zmiennej nextPage i strona ta znajduje się po bieżącej stronie, dialog przełącza się bezpośrednio na tę stronę, nawet jeśli w rezultacie inne strony muszą zostać pominięte. Nie jest możliwe pozostanie na tej samej stronie lub przejście do strony, która znajduje się przed bieżącą stroną. |
function validate(state as Number)
{
if (dialogue.page = „page1” lub dialogue.page = „”) {
if (results.text1 = „”)
dialogue.nextPage := „page4”;
}
if (dialogue.page = „page2”) {
if (results.text2 = „”)
dialogue.nextPage := „page4”;
}
}
Sprawdzanie strony page3 nie jest konieczne, ponieważ strona page4 i tak jest następną stroną.
Wywołania funkcji (parameters i result)
Wywołanie funkcji to definicja działania, która oblicza i zwraca wynik zamiast generowania działania. Wywołania funkcji są używane na przykład do jednokrotnego wprowadzania złożonych obliczeń lub do używania wyrażeń w języku JavaScript w definicjach działań wprowadzanych w języku skryptowym systemu.
Parametry i wartości zwracane definicji działań typu Wywołanie funkcji są rejestrowane wraz z definicją działania. Każdy parametr i każda wartość zwracana ma następujące właściwości w definicji działania:
- Unikalna nazwa techniczna w ramach definicji działania
- Termin, który można przetłumaczyć
- Typ danych
Dla każdego parametru P1,…,Pn i wartości zwracanej R1,…,Rm istnieje zmienna o nazwie technicznej w zmiennych parametry i wynik, tj:
parameters.P1,…,parameters.Pn
result.R1,…,result.Rm
Wartości parametrów są przekazywane i ustawiane w momencie wywołania definicji działania. Wartości zwracane są zerowe w momencie wywołania i mogą być obliczane przez definicję działania.
parameters.ITEMNUMBER
result.PRICE
Wartość zmiennej ITEMNUMBER jest ustawiana podczas wywoływania definicji działania. Wartość zmiennej PRICE musi być ustawiona przez definicję działania.
Należy pamiętać, że zwykłe zmienne środowiskowe dla bazy danych i użytkownika nie są dostępne w definicji działania typu Wywołanie funkcji, ponieważ takie definicje działań nie są zwykle kończone interaktywnie przez użytkownika.
Aplikacje działające w tle (getJobResult)
Typ węzła Węzeł usług jest używany w definicjach procesów do tworzenia działanie, które wywołuje aplikację działającą w tle. Węzeł usługi jest przetwarzany przez zlecenie przetwarzania. Zlecenie przetwarzania może być również wybrane jako procesor w definicji działania typu Pojedyncze działanie.
W funkcji zamykania funkcja skryptu getJobResult może być użyta do oceny wyników wywołanej aplikacji działającej w tle, pod warunkiem, że działanie oczekuje na zadanie przetwarzania, albo poprzez aktywację pola wyboru Oczekuje na zadanie przetwarzania na zakładce Opracowanie, albo poprzez użycie polecenia setJobWaitFinish(true) w funkcji tworzenia.
Funkcja getJobResult przesyła tabelę hash z wartościami zmiennych, które znajdują się za CisParameterList: na zakładce Wyniki w oknie dialogowym właściwości przetwarzanego zadania.
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}
Jeśli działanie oczekuje na przetworzenie zadania, wówczas getJobResult może zwrócić następującą tabelę skrótów:
{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]}
Rzeczywiste wyniki wywołanej aplikacji działającej w tle można znaleźć w zmiennej resultParmeters. Poniższy skrypt w funkcji zamykania analizuje je, otwiera wygenerowane listy inwentaryzacji i wyprowadza ich identyfikację do dziennika:
function close(state as Number)
{
var rp as HashMap;
var cls as Number; /* liczba wygenerowanych list zliczania */
var clGuids as Guid[]; /* lista identyfikatorów GUID listy zliczania */
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);
}
}
Usługi sieci Web (getServiceResponse)
Typ działania Węzeł usługi sieci Web jest używany w definicjach procesów do wywoływania zewnętrznej usługi internetowej za pomocą aplikacji w tle. Aplikacja działająca w tle korzysta z protokołu HTTP i może wywoływać zewnętrzne usługi sieciowe za pośrednictwem JSON/REST i XML/SOAP.
W funkcji close do oceny wyników można użyć funkcji skryptu getServiceResponse. Funkcja zwraca parametr wyniku responseBody aplikacji działającej w tle jako ciąg znaków. Funkcja ta jest bardziej kompaktowym zapisem wyrażenia getJobResult()[„resultParmeters”][„responseBody”]. Warunkiem wstępnym oceny jest to, że działanie oczekuje na zadanie przetwarzania, albo poprzez aktywację pola wyboru Oczekuje na zadanie przetwarzania na zakładce Opracowanie, albo poprzez użycie polecenia setJobWaitFinish(true) w funkcji tworzenia. W zależności od wybranej akcji aplikacji działającej w tle (JSON lub XML), można użyć funkcji parseJson lub parseXml, aby przekonwertować ciąg znaków zwrócony przez getServiceResponse na tablicę hash.
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.”);
}
}
Należy pamiętać, że atrybut statusBackup jest używany, jeśli zamówienie zawiera więcej pozycji niż można zwolnić w transakcji bazy danych. W takim przypadku status zamówienia jest zmieniany na Nieprawidłowy przy pierwszej transakcji bazy danych, a atrybut statusBackup otrzymuje przyszły status Zwolniony. Status zamówienia jest zmieniany na Zwolniony dopiero przy ostatniej transakcji w bazie danych.
Obsługa błędów
Ograniczenie złożoności wyrażeń
Język skryptowy systemu nie nadaje się do dłuższych obliczeń lub przetwarzania dużych ilości danych. Z tego powodu czas działania warunków i poleceń jest ograniczony.
Ustawienia domyślne to:
Działanie | Ograniczenie | Wyjaśnienie |
while | 1.000.000 | Pętle while kończą się po 1 000 000 uruchomień. |
getResultList getCisObjectList |
10.000 | getResultList i getCisObjectList mogą wyszukiwać do 10 000 wierszy lub obiektów. |
call @ |
100 | call i @ mogą wywoływać definicje działania rekurencyjnie maksymalnie 100 razy. Wartości domyślnej nie można zmienić. |
Można użyć właściwości systemowej com.cisag.pgm.workflow.MaxExpressionComplexity, aby zmienić sprawdzanie złożoności. Domyślną wartością jest 1000. Wartości graniczne wszystkich operacji z wyjątkiem limitu głębokości rekurencji są liniowo zależne od wartości tej właściwości. Wartość 0 całkowicie wyłącza sprawdzanie.
Obsługa błędów uruchomieniowych
Niektóre błędy w wyrażeniach nie mogą zostać rozpoznane podczas sprawdzania skryptu.
Błędy uruchomieniowe w silniku workflow mają klasę komunikatów WFL. Błędy występujące podczas oceny wyrażeń są zapisywane w dzienniku OLTP lub repozytorium, w zależności od definicji działania. Rejestry OLTP lub rejestry repozytorium można przeszukiwać za pomocą aplikacji Rejestr komunikatów. Jeśli warunek wstępny jest nieprawidłowy, komunikat jest zapisywany w dzienniku OLTP lub repozytorium, w zależności od działania. Działanie jest jednak traktowane tak, jakby warunek wstępny został spełniony.
Jeśli wystąpią błędy w warunku przejścia, obliczeniach operatorów lub w bloku poleceń, nie zostanie wygenerowane żadne nowe działanie. Komunikat jest zapisywany w rejestrze systemowym. Dziennik komunikatów powinien być sprawdzany pod kątem błędów w regularnych odstępach czasu, zwłaszcza jeśli definicje działań zostały zmienione lub nowo wprowadzone.
Rozszerzenie języka skryptowego systemu
Nowe polecenia i funkcje można dodawać do języka skryptowego systemu za pośrednictwem predefiniowanego interfejsu programowania. Zwłaszcza gdy sprawdzane mają być złożone warunki, można szybko osiągnąć granice języka skryptowego pod względem ekspresyjności lub wydajności. W takim przypadku można rozwiązać problemy za pomocą wyspecjalizowanych funkcji.
Więcej informacji można znaleźć w rozdziale Rozszerzanie języka skryptowego w dokumentacji Interfejsy Workflow Management.