# 9.審批流程
提示
在ELCube中,我們不推薦工作流直接參與業務邏輯的處理;
可以使用工作流驅動任務的分配、以及對通過對單據狀態的修改觸發響應的單據業務邏輯;
# 創建流程圖
電梯:https://loan.elcube.cloud/#/apps/def/bpm/process/definitions (opens new window)
# 用戶任務流轉
提示
在工作流BPM中,我們可以給User Task增加多個出口,來控制流程的不同走向;
每一個出口線路,在工作流表單中將生成一個提交按鈕,用戶點擊不同的按鈕,在工作流變量中設置其key值;
為出口線路設置表達式條件類型,使用表達式${NK$TRANSITION_ID == 線路KEY}來決定流轉的線路;
# 控制單據狀態
在工作流BPM中,我們可以增加Service Task來控制當前單據的狀態,為此,我們默認提供以下集中JavaDelegate來執行程序
${NkDocStateChangeJavaDelegate}工作流啟動時,改變單據狀態${NkDocStateUpdateJavaDelegate}任務被提交時,需要修改單據狀態${NkDocStateUpdateAgainJavaDelegate}任務被提交時,需要在同一個進程中第二次修改單據狀態
# ${NkDocStateChangeJavaDelegate}
字段注入: state-String-目標單據狀態
TIP
NkDocStateChangeJavaDelegate是一個比較特殊的JavaDelegate,它僅適用在工作流被啟動的時候,第一個用戶任務或者其他異步任務介入之前。
它的邏輯就是將當前的單據的docState設置為一個值,剩下的工作交還給DocEngine
NkDocEngineThreadLocal.getCurr().setDocState(
(String) state.getValue(delegateExecution)
);
2
3
# ${NkDocStateUpdateJavaDelegate}
字段注入: state-String-目標單據狀態
TIP
NkDocStateUpdateJavaDelegate是平時使用最多的JavaDelegate,它適用在一個異步的Task(包括User Task)節點之后, 它會獲取當前bpm的關聯的doc,將doc的docState設置為一個值,在保存doc。因此,它會觸發doc完整的update生命周期
docEngine.doUpdate(
delegateExecution.getBusinessKey(),
"BPM:"+delegateExecution.getEventName(),
(doc)-> doc.setDocState((String) state.getValue(delegateExecution))
);
2
3
4
5
# ${NkDocStateUpdateAgainJavaDelegate}
字段注入: state 目標單據狀態
TIP
NkDocStateUpdateAgainJavaDelegate 是由于流程自動化的需要而產生的。
我們知道,在DocEngine中,單據的修改是會加鎖,且在事務提交之前,鎖不會被釋放,也因此,我們想在一個事務中連續更新單據兩次,是達不到的。 因此有了這個JavaDelegate。
UpdateAgainJavaDelegate必須使用在NkDocStateUpdateJavaDelegate之后的Service Task,且他們需要運行在一個事務里。
UpdateAgainJavaDelegate會越過DocEngine的鎖機制,將被修改過的單據從內存中加載出來,再一次進行修改。
# 指定審批流待辦人
# ${NkAssigneeExecutionListener} 代理人選擇監聽器
功能待實現
# ${NkCandidateExecutionListener} 候選組選擇監聽器
| 注入字段 | 描述 |
|---|---|
| groupKey | 用戶組的KEY |
| groupExamine | 注入到工作流上下文中的變量名 |
# 轉辦
TIP
轉辦直接將辦理人assignee 換成別人,這時任務的擁有著不再是轉辦人,而是為空,相當于將任務轉出
轉辦配置:代理表達式${NkForwardTaskListener} 注入字段:groupKey,值:用戶組KEY
# 委派
TIP
委派是將任務節點分給其他人處理,等其他人處理好之后,委派任務還會 自動回到委派人的任務中
委派配置:代理表達式${NkDelegateTaskListener} 注入字段:groupKey,值:用戶組KEY
# 自定義表單
TIP
自定義表單可以用于為節點選擇審批人員
# 自定義類型 NkTaskFieldUserSelector
# 表單字段
| 字段 | 描述 |
|---|---|
| ID | 自定義變量 |
| 類型 | 選擇custom type,輸入NkTaskFieldUserSelector |
| 名稱 | 自定義,eg:指派下一節點審批人員 |
# 校驗
| 名稱 | 配置 | 描述 |
|---|---|---|
| function | function(value){ return !(value.indexOf(props.mustUserName)>-1 && value.length === 5); } | 執行的JS函數,mustUserName是下面屬性的編號 |
| required | "true" | 說明表單必填 |
# 屬性
| 編號 | 值實例 | 描述 |
|---|---|---|
| groupKey | eg:reviewCommittee | 用戶組的KEY |
| groupKey_var | eg:areaMagGroupKey | areaMagGroupKey是流程變量的KEY,value值時用戶組的KEY |
| selectMode | multiple | 表單可多選 |
| mustUserName | ${@hbf.getUserId('安宏斌')} | 必須選擇的人 |
| errorMessage | 請選定5人并且包含安宏斌 | 錯誤提示語 |
# 綁定工作流到模型
在單據配置詳情-業務邏輯-工作流中添加工作流
| 屬性 | 描述 |
|---|---|
| 流程定義 | 工作流程圖的KEY |
| 啟動狀態 | 單據狀態,當單據保存為該狀態時,將啟動工作流實例 |
| 終止時回退狀態 | 單據狀態,當工作流被異常終止時,將單據還原為該狀態值 |
WARNING
一定要避免同一個單據同時啟動多個工作流實例;
多個實例如果同時操作一個單據,會帶來不可控的并發問題;
# 啟動工作流
TIP
根據模型中的配置,當單據狀態被修改時,滿足啟動狀態條件,便會啟動一個工作流實例
# 關閉工作流
TIP
已經在運行中的工作流可以手動關閉
操作方式:運維-流程實例-單據ID搜索-點擊KILL按鈕
此時該單據狀態將會更改為單據審批流配置中的終止時回退狀態的值
# 提交工作流任務
TIP
當一個單據有激活的工作流實例時,待辦人進入單據詳情界面,會出現工作流表單,來提交或轉辦任務;
| 辦理方式 | 說明 |
|---|---|
| 提交 | 根據用戶點擊的按鈕進行工作流流轉 |
| 轉辦 | 將當前任務移交給其他用戶,由其他用戶代為提交 |
| 委派 | 將當前任務移交給其他用戶,由其他用戶提供審批意見后,再次將任務流轉到當前用戶 |
# 會簽
關于多實例任務
為什么不用 ExecutionListener ? 因為會執行 實例數量+1 次事件,暫時找不到判斷方法,isMultipleRoot 參數似乎不好用
# 多實例節點私有變量
- nrOfInstances: 會簽中總共的實例數
- nrOfCompletedInstances: 已經完成的實例數量
- nrOfActiviteInstances: 當前活動的實例數量,即還沒有完成的實例數量
# ${NkCountersignatureJavaDelegate} 會簽人員選擇
選擇一個 Service Task 節點,并設置
- Delegate Expression = ${NkCountersignatureJavaDelegate}
- Other Params = groupKey:用戶組key;groupExamine:會簽人員變量key 當然你也可以選擇在執行監聽配置
- Delegate Expression = ${NkCandidateExecutionListener}
- Other Params = groupKey:用戶組key;groupExamine:會簽人員變量key
# ${NkCountersignatureTaskListener} 會簽監聽器
這是一個通用的會簽結果統計監聽器
在任務監聽器中的完成(complete)事件中使用
字段注入的配置
名稱:pass;
類型:表達式;
值:${NK$TRANSITION_ID=='Flow_0z10s78'}(會簽通過的箭頭key)
# ${NkCountersignatureCleanListener} 會簽結清清零監聽器
這是一個通用的會簽結清清零監聽器,避免上一個流程的數據影響其他流程 在任務監聽器中的創建(create)事件中使用
# 多實例節點配置:
選擇一個多實例 User Task 節點,并設置
- Assignee 指定任務人 = ${userId}
- Collection 指定會簽人員集合 = ${會簽人員變量key}
- Element Variable 任務人變量 = userId
- Completion Condition 會簽結束條件 = 自定義,例如:所有會簽人員都要審批:${nrOfInstances == nrOfCompletedInstances}
- Task Listener = ${NkCountersignatureTaskListener}
- eventType = complete
- pass = ${nkFlowId=='Flow_0kz1ipm'}
# 多實例節點后的路徑走向判斷:
- 通過路線 Expression = ${NK$COUNTERSIGNATURE_PASS_COUNT>=nrOfInstances}
- 否決路線 Expression = ${NK$COUNTERSIGNATURE_PASS_COUNT< nrOfInstances}
TIP
通過測試得知,多實例的路徑走向是由最后一個會簽人員決定的,當完成條件為
${nrOfInstances == nrOfCompletedInstances},該節點的路徑走向為最后一個會簽人員的走向
如果有其他路徑走向,可以在此節點完成時增加變量,通過網關去控制路徑走向
# 自定義表單
流程圖的表單頁可以配置自定義的表單類,NkTaskFieldUserSelector是用戶選擇器,經辦人可以在辦理任務時選擇任意節點的處理人
關于多實例任務
類型選擇:custom type 填入:NkTaskFieldUserSelector 添加屬性:編號:groupKey,值為某一個用戶組的key 編號:selectMode,值為multiple,代表可多選 經辦人選完之后,這個表單key作為任意節點的候選用戶的參數
# 擴展
通過擴展參數修改審批按鈕樣式
在箭頭的擴展屬性中可以添加屬性值,修改審批按鈕樣式
| 名稱 | 值 | 說明 |
|---|---|---|
| buttonType | 可選值為 primary、dashed、danger、link | |
| style | 示例:background-color:red;color:white | 自定義樣式 |