提交 | 用户 | 时间
|
e7c126
|
1 |
package com.iailab.module.bpm.framework.flowable.core.candidate; |
H |
2 |
|
|
3 |
import cn.hutool.core.collection.CollUtil; |
|
4 |
import cn.hutool.core.lang.Assert; |
|
5 |
import cn.hutool.core.util.StrUtil; |
|
6 |
import com.iailab.framework.common.enums.CommonStatusEnum; |
|
7 |
import com.iailab.framework.datapermission.core.annotation.DataPermission; |
|
8 |
import com.iailab.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; |
|
9 |
import com.iailab.module.bpm.framework.flowable.core.util.BpmnModelUtils; |
|
10 |
import com.iailab.module.system.api.user.AdminUserApi; |
|
11 |
import com.iailab.module.system.api.user.dto.AdminUserRespDTO; |
|
12 |
import com.google.common.annotations.VisibleForTesting; |
|
13 |
import lombok.extern.slf4j.Slf4j; |
|
14 |
import org.flowable.bpmn.model.BpmnModel; |
|
15 |
import org.flowable.bpmn.model.UserTask; |
|
16 |
import org.flowable.engine.delegate.DelegateExecution; |
|
17 |
|
|
18 |
import java.util.HashMap; |
|
19 |
import java.util.List; |
|
20 |
import java.util.Map; |
|
21 |
import java.util.Set; |
|
22 |
|
|
23 |
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception; |
|
24 |
import static com.iailab.module.bpm.enums.ErrorCodeConstants.MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG; |
|
25 |
import static com.iailab.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER; |
|
26 |
|
|
27 |
/** |
|
28 |
* {@link BpmTaskCandidateStrategy} 的调用者,用于调用对应的策略,实现任务的候选人的计算 |
|
29 |
* |
|
30 |
* @author iailab |
|
31 |
*/ |
|
32 |
@Slf4j |
|
33 |
public class BpmTaskCandidateInvoker { |
|
34 |
|
|
35 |
private final Map<BpmTaskCandidateStrategyEnum, BpmTaskCandidateStrategy> strategyMap = new HashMap<>(); |
|
36 |
|
|
37 |
private final AdminUserApi adminUserApi; |
|
38 |
|
|
39 |
public BpmTaskCandidateInvoker(List<BpmTaskCandidateStrategy> strategyList, |
|
40 |
AdminUserApi adminUserApi) { |
|
41 |
strategyList.forEach(strategy -> { |
|
42 |
BpmTaskCandidateStrategy oldStrategy = strategyMap.put(strategy.getStrategy(), strategy); |
|
43 |
Assert.isNull(oldStrategy, "策略(%s) 重复", strategy.getStrategy()); |
|
44 |
}); |
|
45 |
this.adminUserApi = adminUserApi; |
|
46 |
} |
|
47 |
|
|
48 |
/** |
|
49 |
* 校验流程模型的任务分配规则全部都配置了 |
|
50 |
* 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去! |
|
51 |
* |
|
52 |
* @param bpmnBytes BPMN XML |
|
53 |
*/ |
|
54 |
public void validateBpmnConfig(byte[] bpmnBytes) { |
|
55 |
BpmnModel bpmnModel = BpmnModelUtils.getBpmnModel(bpmnBytes); |
|
56 |
assert bpmnModel != null; |
|
57 |
List<UserTask> userTaskList = BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class); |
|
58 |
// 遍历所有的 UserTask,校验审批人配置 |
|
59 |
userTaskList.forEach(userTask -> { |
|
60 |
// 1. 非空校验 |
|
61 |
Integer strategy = BpmnModelUtils.parseCandidateStrategy(userTask); |
|
62 |
String param = BpmnModelUtils.parseCandidateParam(userTask); |
|
63 |
if (strategy == null) { |
|
64 |
throw exception(MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG, userTask.getName()); |
|
65 |
} |
|
66 |
BpmTaskCandidateStrategy candidateStrategy = getCandidateStrategy(strategy); |
|
67 |
if (candidateStrategy.isParamRequired() && StrUtil.isBlank(param)) { |
|
68 |
throw exception(MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG, userTask.getName()); |
|
69 |
} |
|
70 |
// 2. 具体策略校验 |
|
71 |
getCandidateStrategy(strategy).validateParam(param); |
|
72 |
}); |
|
73 |
} |
|
74 |
|
|
75 |
/** |
|
76 |
* 计算任务的候选人 |
|
77 |
* |
|
78 |
* @param execution 执行任务 |
|
79 |
* @return 用户编号集合 |
|
80 |
*/ |
|
81 |
@DataPermission(enable = false) // 忽略数据权限,避免因为过滤,导致找不到候选人 |
|
82 |
public Set<Long> calculateUsers(DelegateExecution execution) { |
|
83 |
Integer strategy = BpmnModelUtils.parseCandidateStrategy(execution.getCurrentFlowElement()); |
|
84 |
String param = BpmnModelUtils.parseCandidateParam(execution.getCurrentFlowElement()); |
|
85 |
// 1.1 计算任务的候选人 |
|
86 |
Set<Long> userIds = getCandidateStrategy(strategy).calculateUsers(execution, param); |
|
87 |
// 1.2 移除被禁用的用户 |
|
88 |
removeDisableUsers(userIds); |
|
89 |
|
|
90 |
// 2. 校验是否有候选人 |
|
91 |
if (CollUtil.isEmpty(userIds)) { |
|
92 |
log.error("[calculateUsers][流程任务({}/{}/{}) 任务规则({}/{}) 找不到候选人]", execution.getId(), |
|
93 |
execution.getProcessDefinitionId(), execution.getCurrentActivityId(), strategy, param); |
|
94 |
throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER); |
|
95 |
} |
|
96 |
return userIds; |
|
97 |
} |
|
98 |
|
|
99 |
@VisibleForTesting |
|
100 |
void removeDisableUsers(Set<Long> assigneeUserIds) { |
|
101 |
if (CollUtil.isEmpty(assigneeUserIds)) { |
|
102 |
return; |
|
103 |
} |
|
104 |
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assigneeUserIds); |
|
105 |
assigneeUserIds.removeIf(id -> { |
|
106 |
AdminUserRespDTO user = userMap.get(id); |
|
107 |
return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus()); |
|
108 |
}); |
|
109 |
} |
|
110 |
|
|
111 |
private BpmTaskCandidateStrategy getCandidateStrategy(Integer strategy) { |
|
112 |
BpmTaskCandidateStrategyEnum strategyEnum = BpmTaskCandidateStrategyEnum.valueOf(strategy); |
|
113 |
Assert.notNull(strategyEnum, "策略(%s) 不存在", strategy); |
|
114 |
BpmTaskCandidateStrategy strategyObj = strategyMap.get(strategyEnum); |
|
115 |
Assert.notNull(strategyObj, "策略(%s) 不存在", strategy); |
|
116 |
return strategyObj; |
|
117 |
} |
|
118 |
|
|
119 |
} |