Jako repozytorium i silnik bpmn używamy Activiti. Poniższa dokumentacja jest rozszerzeniem http://www.activiti.org/userguide/index.html#bpmn20 i należy się z nią wcześniej zapoznać.
W pliku występują następujące znaczniki:
<startEvent id="start" activiti:initiator="owner"> <extensionElements> <activiti:formProperty id="ID:firTytul;TYPE:FIRMATIC_FIELD;ARGS:FIR_NAME:Tytul;" name="Tytuł" type="string" /> <activiti:formProperty id="ID:firDate_Realize;TYPE:FIRMATIC_FIELD;ARGS:FIR_NAME:Date_Realize;" name="Data realizacji" type="string" /> <activiti:formProperty id="ID:firAPartnerIdent;TYPE:FIRMATIC_FIELD;ARGS:FIR_NAME:APartnerIdent;" name="Kontrahent symbol" type="string" /> <activiti:formProperty id="ID:firAPartnerName;TYPE:FIRMATIC_FIELD;ARGS:FIR_NAME:APartnerName;" name="Kontrahent" type="string" /> <activiti:formProperty id="ID:firDescription;TYPE:FIRMATIC_FIELD;ARGS:{FIR_NAME:Description, FIELD_OPT:TEXTAREA};" name="Opis" type="string" /> <activiti:formProperty id="ID:firBtn;TYPE:FIRMATIC_SIGNAL;ARGS:KEY:306;" name="Pokaż WKT" type="string" /> </extensionElements> </startEvent>
Wartości parametru name mogą być dowolne i nie mają wpływu na pracę workflow.
Jest to najważniejszy znacznik w workflow i definiuje on co będzie widział użytkownik na formatce. Istotne znaczenie mają atrybuty id i type.
Atrybuty dodatkowe:
Znaczenie poszczególnych wartości w atrybutach zostanie pokazana na przykładach:
<activiti:formProperty id="ID:firTytul;TYPE:FIRMATIC_FIELD;ARGS:FIR_NAME:Tytul;" name="Tytuł" type="string" />
W tym polu można używać atrybutu writable w celu ograniczenia edytowalności pola (tzn. z pola edytowalnego w firmaticu można zrobić nieedytowalne w workflow).
Domyślnie pola firmaticowe w zakładce „Informacje o procesie” nie są odświeżane. Można wymusić odświeżanie poprzez zastosowanie opcji MUTABLE
<activiti:formProperty id="ID:firPrefix;TYPE:FIRMATIC_FIELD;ARGS:{FIR_NAME:NumberPrefix, MUTABLE:true};" name="Prefix" type="string" />
<activiti:formProperty id="ID:firDescription;TYPE:FIRMATIC_FIELD;ARGS:{FIR_NAME:Description, FIELD_OPT:TEXTAREA};" name="Opis" type="string" />
Dodatkowy parametr w ARGS to FIELD_OPT.
Pole to tworzy na formatce przycisk o dowolnej nazwie. Jego kliknięcie powoduje wysłanie komunikatu do Firmatica.
<activiti:formProperty id="ID:firBtn;TYPE:FIRMATIC_SIGNAL;ARGS:{KEY:1097,CODEPROC:121};" name="Oferta" type="string" />
<activiti:formProperty id="ID:wp_o_1_comment;" name="Komentarz" type="string" required="true" />
<activiti:formProperty id="ID:wp_o_1_comment;TYPE:TEXTAREA;" name="Komentarz" type="string" required="true" />
<activiti:formProperty id="ID:PTP_boss;TYPE:FIRMATIC_USER;" name="Sekcja PTP" type="string" variable="PTP_boss" required="false" default="user:tadkob" />
W powyższym przykładzie wykorzystano atrybut variable, który zawsze musi mieć wartość taką jak „ID”. Jest on używany do przypisywania zadań do użytkowników za pomocą zmiennych.
Jest to specjalne pole, które umożliwia dodanie nowej linii firmaticowej dla użytkownika, nawet jeżeli nie jest on przypisany do żadnego zadania.
<activiti:formProperty id="ID:dw_1;TYPE:FIRMATIC_USER;ARGS:DW:TRUE;" name="DW PT" type="string" variable="dw_1" required="false" writable="true" default="user:b" />
Jest to pole wyboru użytkownika ze specjalnymi opcjami. Pierwszą z nich wskazanie listy z której można wybierać użytkowników. Drugim elementem jest wartość domyślna. Może ona zarówno określać pojedynczego użytkownika jak i całą listę.
<activiti:formProperty id="ID:user;TYPE:FIRMATIC_USER;ARGS:INNER_LIST:PTP-330;" name="Sekcja PTP-330" type="string" variable="user" required="false" writable="true" default="user:b" />
<activiti:formProperty id="ID:firLineAff0;TYPE:FIRMATIC_LINEAFF2;ARGS:{NUM:9, FIELD_OPT:TEXTAREA, FIELD_HEIGHT:100};" name="Komentarz do sprawy" type="string" writable="true" />
<activiti:formProperty id="ID:nextStep;DEFAULT:;" name="Czy zakończyć?" type="enum" required="true" variable="nextStep"> <activiti:value id="isEnd" name="Koniec sprawy" /> <activiti:value id="answer" name="Odpowiedź do osoby" /> </activiti:formProperty>
<activiti:formProperty id="ID:firLog;TYPE:FIRMATIC_LINEAFF2_LOG;ARGS:{NUM:0, FIELD_OPT:TEXTAREA, FIELD_HEIGHT:100};ARGS2:{firDescription};" name="Historia zmian" type="string" writable="true" />
<activiti:formProperty id="ID:worker;TYPE:FIRMATIC_USER;REQUIRED_IF_EXPR:{#is_to_board == 'false'};" name="Osoba odpowiedzialna" type="string" variable="worker" writable="true" />
Ogólnie o przepływach i warunkach należy przeczytać w dokumentacji do Activiti.
W startEvent lub userTask można zdefiniować pole logiczne lub enum które będzie użyte w sterowaniu przepływem.
Najpierw w userTask definiujemy zmienną logiczną:
<activiti:formProperty id="ID:is_claim_valid;" name="Czy reklamacja zasadna?" type="boolean" variable="is_claim_valid" />
Następnie możemy zdefiniować warunek:
<sequenceFlow sourceRef="do_work" targetRef="after_worker_decision" /> <exclusiveGateway id="after_worker_decision" /> <sequenceFlow sourceRef="after_worker_decision" targetRef="claim_denied_work"> <conditionExpression xsi:type="tFormalExpression">${is_claim_valid == 'false'}</conditionExpression> </sequenceFlow> <sequenceFlow sourceRef="after_worker_decision" targetRef="claim_accept_work"> <conditionExpression xsi:type="tFormalExpression">${is_claim_valid == 'true'}</conditionExpression> </sequenceFlow>
Najpierw w userTask definiujemy zmienną enum:
<activiti:formProperty id="ID:is_to_board_approval;DEFAULT:;" name="Czy skierować do zarządu?" type="enum" required="true" variable="is_to_board_approval"> <activiti:value id="toBoard" name="Skierować do zarządu (ostateczne zatwierdzenie)" /> <activiti:value id="sendToWorker" name="Do kolejnej osoby (opis pozycji)" /> </activiti:formProperty>
Następnie możemy zdefiniować warunek:
<sequenceFlow sourceRef="describe_invoice" targetRef="after_describe_decision" /> <exclusiveGateway id="after_describe_decision" default="after_describe_decision_flow3" /> <!-- do zatwierdzenia do zarządu --> <sequenceFlow id="after_describe_decision_flow1" sourceRef="after_describe_decision" targetRef="board_approval"> <conditionExpression xsi:type="tFormalExpression">${is_to_board_approval == 'toBoard'}</conditionExpression> </sequenceFlow> <!-- do kolejnego pracownika --> <sequenceFlow id="after_describe_decision_flow3" sourceRef="after_describe_decision" targetRef="describe_invoice"> </sequenceFlow>