7 Decyzje, formularze, wykonanie
Po spotkaniu: zapiszesz tabelę decyzyjną w tok i sprawdzisz ją poleceniem tok eval · dodasz do modelu formularze, wyrażenia FEEL i profil wykonywalny · wyeksportujesz komplet plików dla Camunda 8 i uruchomisz proces w silniku · Czas: Nauka 40 min, Wyzwanie 50 min
7.1 Nauka
Od modelu do procesu, który działa
Na kursie BPMN uruchomiłeś w Camunda 8 Run gotowy proces „Propozycja zakupu książki” (rozdział 12 kursu BPMN). Do wdrożenia potrzebował pięciu plików: modelu .bpmn, tabeli decyzyjnej .dmn i trzech formularzy .form, a w modelu trzeba było ustawić w panelu właściwości identyfikatory formularzy, decyzji i warunki FEEL.
W tok cały ten komplet mieści się w jednym pliku tekstowym. Tabele decyzyjne i formularze są w nim osobnymi blokami, a polecenie tok export rozkłada go na pliki, które przyjmuje silnik. Na tym spotkaniu zbudujesz w ten sposób proces udostępniania zbiorów specjalnych.
Tabela decyzyjna w tekście
Zbiory specjalne (rękopisy, stare druki, archiwalia) udostępnia się według reguł. Materiał z danymi osobowymi młodszy niż 30 lat wymaga zgody kierownika, a do celów prywatnych nie jest udostępniany wcale. Takie reguły zapisujesz blokiem decision:
decision tryb-udostepnienia "Tryb udostępnienia" hit=first
| cel: string | wiek: number | dane: boolean || tryb: string || uwagi |
| "prywatny" | < 30 | true || "odmowa" || ochrona danych osobowych |
| - | < 30 | true || "zgoda kierownika" || dane osobowe, materiał młodszy niż 30 lat |
| - | - | - || "czytelnia" || pozostałe wnioski |
Tabela wygląda jak tabela w Markdown. Każdy wiersz zaczyna się i kończy znakiem |:
- pierwszy wiersz to nagłówek. Kolumny przed
||to wejścia, po||to wyjścia. Każda komórka nagłówka ma postaćnazwa: typ, gdzie typ tostring,number,booleanalbodate. Nazwa wejścia to zmienna procesu (np.cenaz formularza), nazwa wyjścia to zmienna, w której zapisze się wynik; - kolejne wiersze to reguły. Komórki wejść to testy jednoargumentowe (unary tests) z języka FEEL, komórki wyjść to wartości;
- opcjonalna ostatnia kolumna, po drugim
||, to adnotacje. Nie wpływają na wynik, ale wyjaśniają regułę czytelnikowi. W pliku DMN trafiają do opisu reguły.
Najczęstsze testy w komórkach wejść:
| Komórka | Pasuje, gdy wartość wejścia |
|---|---|
- |
jest dowolna (także pusta) |
"prywatny", 30, true |
jest równa podanej |
< 30, <= 150, >= 18 |
spełnia porównanie |
[18..65], ]18..65], [1..5[ |
leży w przedziale; nawias kwadratowy do środka oznacza, że koniec należy do przedziału, na zewnątrz — że nie należy |
"naukowy", "urzędowy" |
spełnia którykolwiek test z listy |
not("prywatny") |
nie spełnia żadnego testu z listy |
Pełny opis podzbioru FEEL, który obsługuje tok, jest w dokumentacji języka (docs/feel.md).
Polityka trafień
Atrybut hit= mówi, co zrobić, gdy pasuje kilka reguł. Znasz to z rozdziału 8 kursu BPMN.
hit= |
Znaczenie | Typowe użycie |
|---|---|---|
unique (domyślna) |
może pasować najwyżej jedna reguła | reguły wzajemnie się wykluczają |
first |
wygrywa pierwsza pasująca reguła, kolejność wierszy ma znaczenie | wyjątki na górze, przypadek ogólny na dole |
any |
może pasować kilka reguł, ale wszystkie dają ten sam wynik | |
priority |
wygrywa reguła o najwyższym priorytecie wyniku | w tok 0.1 działa jak first |
collect |
wynikiem jest lista wyników wszystkich pasujących reguł | zbieranie wszystkich wymagań, np. listy dokumentów do dołączenia |
Nasza tabela ma hit=first, bo ostatnia reguła („pozostałe wnioski”) pasuje zawsze. Co by było przy domyślnej polityce unique? tok check wykrywa reguły, które mogą pasować jednocześnie, i podaje przykład takich danych:
uniq.tok:35: ostrzeżenie D010: reguły 1 i 2 mogą pasować jednocześnie, np. cel="prywatny", wiek=29, dane=true (polityka unique)
uniq.tok:36: ostrzeżenie D010: reguły 1 i 3 mogą pasować jednocześnie, np. cel="prywatny", wiek=29, dane=true (polityka unique)
uniq.tok:36: ostrzeżenie D010: reguły 2 i 3 mogą pasować jednocześnie, np. cel="prywatny", wiek=29, dane=true (polityka unique)
uniq.tok: błędy 0, ostrzeżenia 3, uwagi 0
Każde takie ostrzeżenie to pytanie do autora tabeli: czy reguły naprawdę się nakładają, czy brakuje warunku? Tu nakładanie jest celowe, więc właściwą odpowiedzią jest zmiana polityki na first.
Sprawdzanie tabeli: tok eval
Zanim podłączysz tabelę do procesu, sprawdź ją na przykładowych danych. Polecenie tok eval oblicza decyzję dla podanych wartości:
> tok eval 07-udostepnienie-zbiorow.tok tryb-udostepnienia cel=prywatny wiek=12 dane=true
{"tryb": "odmowa"}
> tok eval 07-udostepnienie-zbiorow.tok tryb-udostepnienia cel=naukowy wiek=12 dane=true
{"tryb": "zgoda kierownika"}
> tok eval 07-udostepnienie-zbiorow.tok tryb-udostepnienia cel=naukowy wiek=45 dane=true
{"tryb": "czytelnia"}
> tok eval 07-udostepnienie-zbiorow.tok tryb-udostepnienia cel=prywatny wiek=30 dane=true
{"tryb": "czytelnia"}
Ostatni przypadek warto zauważyć. Materiał ma dokładnie 30 lat, a test < 30 go nie obejmuje. Czy tak ma być? To pytanie do regulaminu czytelni, nie do narzędzia. Testowanie wartości granicznych odsłania takie miejsca (por. rozdział 14 kursu BPMN).
Jeśli pominiesz zmienną, ma ona wartość pustą (null). Wtedy tok eval … cel=naukowy wiek=40 daje {"tryb": "czytelnia"}, bo pusta wartość nie spełnia testu true. W procesie taka sytuacja nie wystąpi, bo pole wyboru (checkbox) w formularzu daje zawsze true albo false.
Przy polityce collect wynik jest listą, np. [{"tryb": "odmowa"}, {"tryb": "zgoda kierownika"}, {"tryb": "czytelnia"}]. Warunki na bramkach zwykle oczekują jednej wartości. Dlatego w tabelach wywoływanych z procesu stosuje się najczęściej unique albo first.
Decyzja w procesie
Tabelę wywołuje zadanie reguły biznesowej:
rule tryb "Ustalenie trybu udostępnienia" decision=tryb-udostepnienia result=tryb
decision=wskazuje identyfikator tabeli;result=to nazwa zmiennej procesu, w której silnik zapisze wynik. Jeśli tabela ma jedno wyjście, wynik jest wartością tego wyjścia, tu tekstem"czytelnia","zgoda kierownika"albo"odmowa".
Na wynik reagują warunki na wyjściach bramki:
flow jaki -> scalenie "czytelnia" when="tryb = \"czytelnia\""
flow jaki -> decyzja "zgoda kierownika" when="tryb = \"zgoda kierownika\""
flow jaki -> odmowa-auto "odmowa" default
Wyrażenie FEEL piszesz w cudzysłowie, a cudzysłów wewnątrz poprzedzasz ukośnikiem: \"czytelnia\". Nie piszesz znaku = na początku wyrażenia. Camunda go wymaga, ale tok export dopisuje go sam.
Zadanie skryptowe
Zadanie skryptowe oblicza wartość wyrażeniem FEEL i zapisuje ją w zmiennej:
script termin "Wyznaczenie terminu w czytelni" expr="if pilne = true then 2 else 7" result=dni
Wniosek pilny ma być obsłużony w 2 dni, pozostałe w 7. Zadanie skryptowe zastępuje na zajęciach zadanie usługowe, które w Camunda 8 wymaga osobnego programu (workera).
Formularze
Zadania użytkownika i zdarzenie początkowe mogą mieć formularz. Formularz zapisujesz blokiem form:
form f-decyzja "Decyzja kierownika"
text "## Wniosek: {{sygnatura}}\nCel: {{cel}} · wiek materiału: {{wiek}} lat"
field zgoda "Decyzja" required type=radio options="true:zgoda, false:odmowa"
field uzasadnienie "Uzasadnienie" type=textarea
textto fragment tekstu wyświetlany w formularzu. Obsługuje formatowanie Markdown (##to nagłówek),\nto przejście do nowego wiersza, a{{nazwa}}wstawia wartość zmiennej procesu.field KLUCZ "Etykieta" type=…to pole. Klucz pola staje się nazwą zmiennej procesu. Po zatwierdzeniu formularza zmiennazgodama wartośćtruealbofalse.- Typy pól:
textfield(wiersz tekstu),textarea(dłuższy tekst),number,checkbox(tak/nie),select(lista rozwijana),radio(przyciski wyboru),datetime. requiredoznacza pole obowiązkowe. Przy liczbach można podaćmin=imax=.options="wartość:Etykieta, …"podaje możliwości dlaselectiradio. Wartościtrueifalsestają się wartościami logicznymi, liczby liczbami, a wszystko inne tekstem.
Zadanie wskazuje formularz atrybutem form=:
user decyzja "Decyzja kierownika" form=f-decyzja
Najważniejsza zasada: nazwy pól formularza, zmienne w tabelach decyzyjnych i zmienne w warunkach muszą być identyczne. Pole wiek w formularzu wniosku zasila wejście wiek w tabeli. Pole zgoda w formularzu kierownika zasila warunek zgoda = true na bramce.
Cały model
tok 0.1 "Udostępnienie zbiorów specjalnych" executable
pool biblioteka "Biblioteka uczelniana" process=udostepnienie-zbiorow
lane czytelnik "Czytelnik"
start wniosek "Wniosek złożony" form=f-wniosek
lane system "System biblioteczny"
rule tryb "Ustalenie trybu udostępnienia" decision=tryb-udostepnienia result=tryb
xor jaki "Jaki tryb udostępnienia?"
end odmowa-auto "Odmowa udostępnienia"
xor scalenie
script termin "Wyznaczenie terminu w czytelni" expr="if pilne = true then 2 else 7" result=dni
lane kierownik "Kierownik Oddziału Zbiorów Specjalnych"
user decyzja "Decyzja kierownika" form=f-decyzja
boundary brak "Minęło 5 dni" on=decyzja timer=P5D
xor zgoda "Czy kierownik się zgodził?"
end odmowa "Wniosek odrzucony"
end wygasl "Wniosek wygasł"
lane czytelnia "Czytelnia zbiorów specjalnych"
user przygotowanie "Przygotowanie materiałów" form=f-przygotowanie
end udostepnione "Materiały udostępnione"
flow wniosek -> tryb -> jaki
flow jaki -> scalenie "czytelnia" when="tryb = \"czytelnia\""
flow jaki -> decyzja "zgoda kierownika" when="tryb = \"zgoda kierownika\""
flow jaki -> odmowa-auto "odmowa" default
flow decyzja -> zgoda
flow zgoda -> scalenie "tak" when="zgoda = true"
flow zgoda -> odmowa "nie" default
flow brak -> wygasl
flow scalenie -> termin -> przygotowanie -> udostepnione
decision tryb-udostepnienia "Tryb udostępnienia" hit=first
| cel: string | wiek: number | dane: boolean || tryb: string || uwagi |
| "prywatny" | < 30 | true || "odmowa" || ochrona danych osobowych |
| - | < 30 | true || "zgoda kierownika" || dane osobowe, materiał młodszy niż 30 lat |
| - | - | - || "czytelnia" || pozostałe wnioski |
form f-wniosek "Wniosek o udostępnienie"
field sygnatura "Sygnatura" required type=textfield
field wiek "Wiek materiału (lata)" required type=number min=0
field cel "Cel" required type=select options="naukowy:naukowy, urzędowy:urzędowy, prywatny:prywatny"
field dane "Materiał zawiera dane osobowe" type=checkbox
field pilne "Sprawa pilna" type=checkbox
form f-decyzja "Decyzja kierownika"
text "## Wniosek: {{sygnatura}}\nCel: {{cel}} · wiek materiału: {{wiek}} lat"
field zgoda "Decyzja" required type=radio options="true:zgoda, false:odmowa"
field uzasadnienie "Uzasadnienie" type=textarea
form f-przygotowanie "Przygotowanie materiałów"
text "## {{sygnatura}}\nMateriały mają być gotowe w ciągu {{dni}} dni."
field stanowisko "Stanowisko w czytelni" required type=textfield
Rysunek 7.1: Udostępnienie zbiorów specjalnych: model wykonywalny wygenerowany z tok.
Pobierz model (.tok) Pobierz eksport BPMN (.bpmn)
Zwróć uwagę na nagłówek: flaga executable oznacza, że proces ma działać w silniku. Atrybut process=udostepnienie-zbiorow w basenie ustala identyfikator procesu, pod którym zobaczysz go w Operate i Tasklist.
Profil wykonywalny
W dokumencie z flagą executable tok check sprawdza dodatkowo, czy silnik będzie miał wszystko, czego potrzebuje. Te komunikaty mają kody C i są takie same jak w trybie --camunda skryptu bpmn.py z kursu BPMN.
| Kod | Problem |
|---|---|
C011 (uwaga) |
zadanie użytkownika bez formularza: w Tasklist da się je tylko zakończyć, bez wpisywania danych |
C020 |
zadanie usługowe bez type= (typu zadania dla workera) |
C030 |
zadanie reguły biznesowej bez decision= |
C040 |
zadanie skryptowe bez expr= |
C052 |
oczekiwanie na wiadomość bez correlation= (klucza, po którym silnik dopasuje wiadomość do sprawy) |
C070 |
wyjście z bramki xor lub or bez warunku when= i bez flagi default |
Na przykład w procesie z zadaniem użytkownika bez formularza i zadaniem reguły bez tabeli:
c.tok:3: uwaga C011: Zadanie użytkownika „a” nie ma formularza (form=).
c.tok:4: błąd C030: Zadanie reguły biznesowej „r” wymaga decision=ID.
c.tok: błędy 1, ostrzeżenia 0, uwagi 1
Eksport dla Camunda 8
Polecenie tok export zapisuje do wskazanego folderu wszystko, czego potrzebuje silnik:
> tok export 07-udostepnienie-zbiorow.tok -o out
out\07-udostepnienie-zbiorow.bpmn
out\07-udostepnienie-zbiorow.svg
out\tryb-udostepnienia.dmn
out\f-wniosek.form
out\f-decyzja.form
out\f-przygotowanie.form
Model .bpmn ma już rozszerzenia zeebe:, które na kursie BPMN ustawiałeś w panelu właściwości Camunda Modeler: zeebe:userTask i zeebe:formDefinition przy zadaniach użytkownika, zeebe:calledDecision przy zadaniu reguły, zeebe:script z wyrażeniem =if pilne = true then 2 else 7 przy zadaniu skryptowym. Nazwy plików .dmn i .form biorą się z identyfikatorów tabel i formularzy.
Wdrożenie przebiega tak samo jak na kursie BPMN. Uruchom Camunda 8 Run, otwórz pliki z folderu out w Camunda Modeler i wdróż najpierw tabelę decyzyjną i formularze, a na końcu model. Pliki można też wdrożyć jednym poleceniem przez interfejs REST silnika (w PowerShell pisz curl.exe, nie curl):
curl.exe -X POST http://localhost:8080/v2/deployments -F resources=@out/tryb-udostepnienia.dmn -F resources=@out/f-wniosek.form -F resources=@out/f-decyzja.form -F resources=@out/f-przygotowanie.form -F resources=@out/07-udostepnienie-zbiorow.bpmn
Po wdrożeniu proces zachowuje się dokładnie tak, jak wynika z tabeli. Trzy sprawy uruchomione z różnymi danymi przeszły w silniku takie ścieżki:
| Dane wniosku | Wynik tabeli (tryb) |
Gdzie zatrzymała się sprawa |
|---|---|---|
| cel naukowy, materiał sprzed 12 lat, dane osobowe | "zgoda kierownika" |
zadanie „Decyzja kierownika”; po zgodzie: „Przygotowanie materiałów”, dni = 7 |
| cel prywatny, materiał sprzed 135 lat, bez danych osobowych, pilne | "czytelnia" |
zadanie „Przygotowanie materiałów”, dni = 2 |
| cel prywatny, materiał sprzed 16 lat, dane osobowe | "odmowa" |
sprawa zakończona zdarzeniem „Odmowa udostępnienia” |
Zmienne każdej sprawy i jej ścieżkę zobaczysz w Operate, tak jak na kursie BPMN.
Jeden plik, wiele widoków
Zasada z pierwszego spotkania, „tekst jest modelem”, ma tu praktyczne skutki. Zmiana regulaminu czytelni, np. podniesienie granicy wieku materiału z 30 do 50 lat, to zmiana dwóch komórek tabeli w pliku .tok. Po niej uruchamiasz tok eval na kilku przypadkach i tok export, a potem wdrażasz nową wersję. Historia zmian modelu w repozytorium jest jednocześnie historią zmian procedury.
7.2 Wyzwanie
Polecenie: rozbuduj model udostępniania zbiorów specjalnych o nową regułę i nowe pole formularza, sprawdź tabelę, wyeksportuj model i uruchom dwie sprawy w Camunda 8 Run.
Dane wejściowe: model 07-udostepnienie-zbiorow.tok z części Nauka. Nowe wymaganie regulaminu: materiały w złym stanie zachowania (ocenia je czytelnik przy składaniu wniosku, a w praktyce magazynier) udostępnia się tylko jako kopię cyfrową, niezależnie od celu i wieku.
Kroki:
- Dodaj do formularza
f-wniosekpolestantypuselectz możliwościamidobryizly(etykiety „dobry” i „zły”). - Dodaj do tabeli wejście
stan: stringi na samej górze regułę: stan"zly"→ tryb"kopia cyfrowa", z adnotacją. Uzupełnij pozostałe reguły komórką-. - Dodaj w linii czytelni zadanie użytkownika „Przygotowanie kopii cyfrowej” z formularzem (pole
adres_kopii, tekstowe, wymagane), nową gałąź bramkijakiz warunkiemtryb = "kopia cyfrowa"i nazwane zakończenie. - Uruchom
tok check --lang pli popraw komunikaty. Sprawdź tabelę poleceniemtok evaldla czterech przypadków, w tym materiału w złym stanie do celu prywatnego. Zapisz wyniki. - Uruchom
tok fmt -witok export -o out. Wdróż pliki do Camunda 8 Run i uruchom w Tasklist dwie sprawy: jedną, która trafi do kopii cyfrowej, i jedną, która trafi do kierownika. Sprawdź ich ścieżki i zmienne w Operate.
Rezultat: plik udostepnienie.tok, notatka notatka-07.md z wynikami tok eval i opisem dwóch spraw z Operate. Nie oddajesz ich na Pegazie, ale wykorzystasz je w projekcie.
Praca: indywidualnie.
Czas: 50 minut.
Na co zwrócić uwagę
- Wartości w komórkach wyjść i w warunkach muszą być identyczne co do znaku:
"kopia cyfrowa"w tabeli itryb = \"kopia cyfrowa\"w warunku. - Identyfikator wartości w
options(zly) zapisuj bez polskich znaków, bo trafia do zmiennej i do tabeli. Polskie znaki mają tylko etykiety (zly:zły). - Przy
hit=firstnowa reguła musi stać nad regułą ogólną, która pasuje zawsze. Inaczej nigdy nie wygra. - Jeśli sprawa zatrzyma się z incydentem w Operate, sprawdź, czy wdrożyłeś nową wersję tabeli decyzyjnej i formularzy, a nie tylko modelu.
- Jeśli nowa reguła ma pierwszeństwo przed odmową, uzasadnij to w notatce. To decyzja merytoryczna, nie techniczna.
7.3 Pytania sprawdzające
- Jak zbudowany jest nagłówek tabeli decyzyjnej w tok? Co oznacza
||? - Czym różnią się polityki trafień
uniqueifirst? Kiedytok checkzgłasza ostrzeżenieD010? - Dlaczego warto sprawdzać tabele na wartościach granicznych? Podaj przykład z tabeli trybu udostępnienia.
- Jak łączą się ze sobą pole formularza, wejście tabeli decyzyjnej i warunek na bramce? Co się stanie, jeśli nazwy się różnią?
- Jakie pliki tworzy
tok exportdla modelu wykonywalnego i do czego służy każdy z nich?