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 to string, number, boolean albo date. Nazwa wejścia to zmienna procesu (np. cena z 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
  • text to fragment tekstu wyświetlany w formularzu. Obsługuje formatowanie Markdown (## to nagłówek), \n to 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 zmienna zgoda ma wartość true albo false.
  • Typy pól: textfield (wiersz tekstu), textarea (dłuższy tekst), number, checkbox (tak/nie), select (lista rozwijana), radio (przyciski wyboru), datetime.
  • required oznacza pole obowiązkowe. Przy liczbach można podać min= i max=.
  • options="wartość:Etykieta, …" podaje możliwości dla select i radio. Wartości true i false stają 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
Udostępnienie zbiorów specjalnych: model wykonywalny wygenerowany z tok.

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:

  1. Dodaj do formularza f-wniosek pole stan typu select z możliwościami dobry i zly (etykiety „dobry” i „zły”).
  2. Dodaj do tabeli wejście stan: string i na samej górze regułę: stan "zly" → tryb "kopia cyfrowa", z adnotacją. Uzupełnij pozostałe reguły komórką -.
  3. Dodaj w linii czytelni zadanie użytkownika „Przygotowanie kopii cyfrowej” z formularzem (pole adres_kopii, tekstowe, wymagane), nową gałąź bramki jaki z warunkiem tryb = "kopia cyfrowa" i nazwane zakończenie.
  4. Uruchom tok check --lang pl i popraw komunikaty. Sprawdź tabelę poleceniem tok eval dla czterech przypadków, w tym materiału w złym stanie do celu prywatnego. Zapisz wyniki.
  5. Uruchom tok fmt -w i tok 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 i tryb = \"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=first nowa 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

  1. Jak zbudowany jest nagłówek tabeli decyzyjnej w tok? Co oznacza ||?
  2. Czym różnią się polityki trafień unique i first? Kiedy tok check zgłasza ostrzeżenie D010?
  3. Dlaczego warto sprawdzać tabele na wartościach granicznych? Podaj przykład z tabeli trybu udostępnienia.
  4. Jak łączą się ze sobą pole formularza, wejście tabeli decyzyjnej i warunek na bramce? Co się stanie, jeśli nazwy się różnią?
  5. Jakie pliki tworzy tok export dla modelu wykonywalnego i do czego służy każdy z nich?