Commit 39e89bd378e7c9747e3906d8614ea9ea5d450aa7

Authored by YunaiV
1 parent 4657dcf9

重构 bpmn 任务的处理人的逻辑,收拢到 BpmTaskAssignRuleService

Showing 13 changed files with 508 additions and 339 deletions
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java
@@ -29,7 +29,7 @@ public class BpmTaskExtDO extends BaseDO { @@ -29,7 +29,7 @@ public class BpmTaskExtDO extends BaseDO {
29 private Long id; 29 private Long id;
30 30
31 /** 31 /**
32 - * 流程任务key 32 + * 流程任务key TODO 芋艿,看看这个字段的作用
33 */ 33 */
34 private String taskDefKey; 34 private String taskDefKey;
35 /** 35 /**
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/definition/BpmTaskAssignRuleTypeEnum.java
@@ -17,8 +17,6 @@ public enum BpmTaskAssignRuleTypeEnum { @@ -17,8 +17,6 @@ public enum BpmTaskAssignRuleTypeEnum {
17 DEPT_LEADER(21, "部门的负责人"), 17 DEPT_LEADER(21, "部门的负责人"),
18 POST(22, "岗位"), 18 POST(22, "岗位"),
19 USER(30, "用户"), 19 USER(30, "用户"),
20 - USER_SIGN(31, "用户---会签"),  
21 - USER_OR_SIGN(32, "用户---或签"),  
22 USER_GROUP(40, "用户组"), 20 USER_GROUP(40, "用户组"),
23 SCRIPT(50, "自定义脚本"), // 例如说,发起人所在部门的领导、发起人所在部门的领导的领导 21 SCRIPT(50, "自定义脚本"), // 例如说,发起人所在部门的领导、发起人所在部门的领导的领导
24 ; 22 ;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java
@@ -2,12 +2,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.config; @@ -2,12 +2,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.config;
2 2
3 import cn.hutool.core.collection.ListUtil; 3 import cn.hutool.core.collection.ListUtil;
4 import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.BpmActivityBehaviorFactory; 4 import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.BpmActivityBehaviorFactory;
5 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;  
6 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; 5 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
7 -import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;  
8 -import cn.iocoder.yudao.module.system.api.dept.DeptApi;  
9 -import cn.iocoder.yudao.module.system.api.permission.PermissionApi;  
10 -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;  
11 import org.flowable.common.engine.api.delegate.event.FlowableEventListener; 6 import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
12 import org.flowable.spring.SpringProcessEngineConfiguration; 7 import org.flowable.spring.SpringProcessEngineConfiguration;
13 import org.flowable.spring.boot.EngineConfigurationConfigurer; 8 import org.flowable.spring.boot.EngineConfigurationConfigurer;
@@ -15,8 +10,6 @@ import org.springframework.beans.factory.ObjectProvider; @@ -15,8 +10,6 @@ import org.springframework.beans.factory.ObjectProvider;
15 import org.springframework.context.annotation.Bean; 10 import org.springframework.context.annotation.Bean;
16 import org.springframework.context.annotation.Configuration; 11 import org.springframework.context.annotation.Configuration;
17 12
18 -import java.util.List;  
19 -  
20 /** 13 /**
21 * BPM 模块的 Flowable 配置类 14 * BPM 模块的 Flowable 配置类
22 * 15 *
@@ -44,19 +37,10 @@ public class BpmFlowableConfiguration { @@ -44,19 +37,10 @@ public class BpmFlowableConfiguration {
44 } 37 }
45 38
46 @Bean 39 @Bean
47 - public BpmActivityBehaviorFactory bpmActivityBehaviorFactory(BpmTaskAssignRuleService taskRuleService,  
48 - BpmUserGroupService userGroupService,  
49 - PermissionApi permissionApi,  
50 - DeptApi deptApi,  
51 - AdminUserApi adminUserApi,  
52 - List<BpmTaskAssignScript> scripts) { 40 + public BpmActivityBehaviorFactory bpmActivityBehaviorFactory(BpmTaskAssignRuleService taskRuleService) {
53 BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory(); 41 BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory();
54 bpmActivityBehaviorFactory.setBpmTaskRuleService(taskRuleService); 42 bpmActivityBehaviorFactory.setBpmTaskRuleService(taskRuleService);
55 - bpmActivityBehaviorFactory.setUserGroupService(userGroupService);  
56 - bpmActivityBehaviorFactory.setAdminUserApi(adminUserApi);  
57 - bpmActivityBehaviorFactory.setPermissionApi(permissionApi);  
58 - bpmActivityBehaviorFactory.setDeptApi(deptApi);  
59 - bpmActivityBehaviorFactory.setScripts(scripts);  
60 return bpmActivityBehaviorFactory; 43 return bpmActivityBehaviorFactory;
61 } 44 }
  45 +
62 } 46 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java
1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
2 2
3 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;  
4 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; 3 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
5 -import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;  
6 -import cn.iocoder.yudao.module.system.api.dept.DeptApi;  
7 -import cn.iocoder.yudao.module.system.api.permission.PermissionApi;  
8 -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;  
9 import lombok.Data; 4 import lombok.Data;
10 import lombok.EqualsAndHashCode; 5 import lombok.EqualsAndHashCode;
11 import lombok.Setter; 6 import lombok.Setter;
@@ -17,8 +12,6 @@ import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; @@ -17,8 +12,6 @@ import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
17 import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior; 12 import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
18 import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory; 13 import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;
19 14
20 -import java.util.List;  
21 -  
22 /** 15 /**
23 * 自定义的 ActivityBehaviorFactory 实现类,目的如下: 16 * 自定义的 ActivityBehaviorFactory 实现类,目的如下:
24 * 1. 自定义 {@link #createUserTaskActivityBehavior(UserTask)}:实现自定义的流程任务的 assignee 负责人的分配 17 * 1. 自定义 {@link #createUserTaskActivityBehavior(UserTask)}:实现自定义的流程任务的 assignee 负责人的分配
@@ -32,41 +25,18 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory { @@ -32,41 +25,18 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
32 25
33 @Setter 26 @Setter
34 private BpmTaskAssignRuleService bpmTaskRuleService; 27 private BpmTaskAssignRuleService bpmTaskRuleService;
35 - @Setter  
36 - private BpmUserGroupService userGroupService;  
37 -  
38 - @Setter  
39 - private PermissionApi permissionApi;  
40 - @Setter  
41 - private DeptApi deptApi;  
42 - @Setter  
43 - private AdminUserApi adminUserApi;  
44 - @Setter  
45 - private List<BpmTaskAssignScript> scripts;  
46 28
47 @Override 29 @Override
48 public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) { 30 public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) {
49 - BpmUserTaskActivityBehavior userTaskActivityBehavior = new BpmUserTaskActivityBehavior(userTask);  
50 - userTaskActivityBehavior.setBpmTaskRuleService(bpmTaskRuleService);  
51 - userTaskActivityBehavior.setPermissionApi(permissionApi);  
52 - userTaskActivityBehavior.setDeptApi(deptApi);  
53 - userTaskActivityBehavior.setUserGroupService(userGroupService);  
54 - userTaskActivityBehavior.setAdminUserApi(adminUserApi);  
55 - userTaskActivityBehavior.setScripts(scripts);  
56 - return userTaskActivityBehavior; 31 + return new BpmUserTaskActivityBehavior(userTask)
  32 + .setBpmTaskRuleService(bpmTaskRuleService);
57 } 33 }
58 34
59 @Override 35 @Override
60 public ParallelMultiInstanceBehavior createParallelMultiInstanceBehavior(Activity activity, 36 public ParallelMultiInstanceBehavior createParallelMultiInstanceBehavior(Activity activity,
61 - AbstractBpmnActivityBehavior innerActivityBehavior) {  
62 - BpmParallelMultiInstanceActivityBehavior bpmParallelMultiInstanceActivityBehavior =  
63 - new BpmParallelMultiInstanceActivityBehavior(activity, innerActivityBehavior);  
64 - bpmParallelMultiInstanceActivityBehavior.setBpmTaskRuleService(bpmTaskRuleService);  
65 - bpmParallelMultiInstanceActivityBehavior.setPermissionApi(permissionApi);  
66 - bpmParallelMultiInstanceActivityBehavior.setDeptApi(deptApi);  
67 - bpmParallelMultiInstanceActivityBehavior.setUserGroupService(userGroupService);  
68 - bpmParallelMultiInstanceActivityBehavior.setAdminUserApi(adminUserApi);  
69 - bpmParallelMultiInstanceActivityBehavior.setScripts(scripts);  
70 - return bpmParallelMultiInstanceActivityBehavior; 37 + AbstractBpmnActivityBehavior innerActivityBehavior) {
  38 + return new BpmParallelMultiInstanceBehavior(activity, innerActivityBehavior)
  39 + .setBpmTaskRuleService(bpmTaskRuleService);
71 } 40 }
  41 +
72 } 42 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceActivityBehavior.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java
1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.util.StrUtil;  
5 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 4 +import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
6 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; 5 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
7 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;  
8 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;  
9 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; 6 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
10 -import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;  
11 -import cn.iocoder.yudao.module.system.api.dept.DeptApi;  
12 -import cn.iocoder.yudao.module.system.api.permission.PermissionApi;  
13 -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;  
14 -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;  
15 -import com.google.common.annotations.VisibleForTesting;  
16 import lombok.Setter; 7 import lombok.Setter;
17 import lombok.extern.slf4j.Slf4j; 8 import lombok.extern.slf4j.Slf4j;
18 import org.flowable.bpmn.model.Activity; 9 import org.flowable.bpmn.model.Activity;
19 -import org.flowable.common.engine.api.FlowableException;  
20 import org.flowable.engine.delegate.DelegateExecution; 10 import org.flowable.engine.delegate.DelegateExecution;
21 import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; 11 import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
22 import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; 12 import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
23 import org.flowable.engine.impl.util.CommandContextUtil; 13 import org.flowable.engine.impl.util.CommandContextUtil;
24 14
25 -import java.util.*; 15 +import java.util.Set;
26 16
27 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 17 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
28 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;  
29 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; 18 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
30 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER; 19 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER;
31 20
@@ -34,37 +23,21 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_F @@ -34,37 +23,21 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_F
34 * @create 2022-04-21 16:57 23 * @create 2022-04-21 16:57
35 */ 24 */
36 @Slf4j 25 @Slf4j
37 -public class BpmParallelMultiInstanceActivityBehavior extends ParallelMultiInstanceBehavior { 26 +public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehavior {
38 27
39 - @Setter  
40 - private BpmTaskAssignRuleService bpmTaskRuleService;  
41 - @Setter  
42 - private BpmUserGroupService userGroupService;  
43 - @Setter  
44 - private DeptApi deptApi;  
45 - @Setter  
46 - private AdminUserApi adminUserApi;  
47 - @Setter  
48 - private PermissionApi permissionApi;  
49 /** 28 /**
50 * EL表达式集合模板 29 * EL表达式集合模板
51 */ 30 */
52 private final static String EXPRESSION_TEXT_TEMPLATE = "${coll_userList}"; 31 private final static String EXPRESSION_TEXT_TEMPLATE = "${coll_userList}";
53 32
54 - /**  
55 - * 任务分配脚本  
56 - */  
57 - private Map<Long, BpmTaskAssignScript> scriptMap = Collections.emptyMap(); 33 + @Setter
  34 + private BpmTaskAssignRuleService bpmTaskRuleService;
58 35
59 - public BpmParallelMultiInstanceActivityBehavior(Activity activity,  
60 - AbstractBpmnActivityBehavior innerActivityBehavior) { 36 + public BpmParallelMultiInstanceBehavior(Activity activity,
  37 + AbstractBpmnActivityBehavior innerActivityBehavior) {
61 super(activity, innerActivityBehavior); 38 super(activity, innerActivityBehavior);
62 } 39 }
63 40
64 - public void setScripts(List<BpmTaskAssignScript> scripts) {  
65 - this.scriptMap = convertMap(scripts, script -> script.getEnum().getId());  
66 - }  
67 -  
68 /** 41 /**
69 * 创建并行任务 42 * 创建并行任务
70 * 43 *
@@ -75,7 +48,8 @@ public class BpmParallelMultiInstanceActivityBehavior extends ParallelMultiInsta @@ -75,7 +48,8 @@ public class BpmParallelMultiInstanceActivityBehavior extends ParallelMultiInsta
75 @Override 48 @Override
76 protected int createInstances(DelegateExecution multiInstanceRootExecution) { 49 protected int createInstances(DelegateExecution multiInstanceRootExecution) {
77 // 查找任务信息 50 // 查找任务信息
78 - BpmTaskAssignRuleDO taskRule = getTaskRule(multiInstanceRootExecution); 51 +// BpmTaskAssignRuleDO taskRule = getTaskRule(multiInstanceRootExecution);
  52 + BpmTaskAssignRuleDO taskRule = null;
79 // 获取任务用户 53 // 获取任务用户
80 Set<Long> assigneeUserIds = calculateTaskCandidateUsers(multiInstanceRootExecution, taskRule); 54 Set<Long> assigneeUserIds = calculateTaskCandidateUsers(multiInstanceRootExecution, taskRule);
81 // 设置任务集合变量 55 // 设置任务集合变量
@@ -86,13 +60,13 @@ public class BpmParallelMultiInstanceActivityBehavior extends ParallelMultiInsta @@ -86,13 +60,13 @@ public class BpmParallelMultiInstanceActivityBehavior extends ParallelMultiInsta
86 this.collectionExpression = CommandContextUtil.getProcessEngineConfiguration().getExpressionManager() 60 this.collectionExpression = CommandContextUtil.getProcessEngineConfiguration().getExpressionManager()
87 .createExpression(String.format("${%s}", expressionText)); 61 .createExpression(String.format("${%s}", expressionText));
88 // 根据会签,或签类型,设置会签,或签条件 62 // 根据会签,或签类型,设置会签,或签条件
89 - if (BpmTaskAssignRuleTypeEnum.USER_SIGN.getType().equals(taskRule.getType())) {  
90 - // 会签  
91 - this.completionCondition = "${ nrOfInstances == nrOfCompletedInstances }";  
92 - } else {  
93 - // 或签  
94 - this.completionCondition = "${ nrOfCompletedInstances == 1 }";  
95 - } 63 +// if (BpmTaskAssignRuleTypeEnum.USER_SIGN.getType().equals(taskRule.getType())) {
  64 +// // 会签
  65 +// this.completionCondition = "${ nrOfInstances == nrOfCompletedInstances }";
  66 +// } else {
  67 +// // 或签
  68 +// this.completionCondition = "${ nrOfCompletedInstances == 1 }";
  69 +// }
96 // 设置取出集合变量 70 // 设置取出集合变量
97 this.collectionElementVariable = "user"; 71 this.collectionElementVariable = "user";
98 return super.createInstances(multiInstanceRootExecution); 72 return super.createInstances(multiInstanceRootExecution);
@@ -103,7 +77,8 @@ public class BpmParallelMultiInstanceActivityBehavior extends ParallelMultiInsta @@ -103,7 +77,8 @@ public class BpmParallelMultiInstanceActivityBehavior extends ParallelMultiInsta
103 Object collection = null; 77 Object collection = null;
104 if (EXPRESSION_TEXT_TEMPLATE.equals(this.collectionExpression.getExpressionText())) { 78 if (EXPRESSION_TEXT_TEMPLATE.equals(this.collectionExpression.getExpressionText())) {
105 // 查找任务信息 79 // 查找任务信息
106 - BpmTaskAssignRuleDO taskRule = getTaskRule(execution); 80 +// BpmTaskAssignRuleDO taskRule = getTaskRule(execution);
  81 + BpmTaskAssignRuleDO taskRule = null;
107 // 设置任务集合变量 82 // 设置任务集合变量
108 String expressionText = String.format("%s_userList", execution.getCurrentActivityId()); 83 String expressionText = String.format("%s_userList", execution.getCurrentActivityId());
109 // 获取任务用户 84 // 获取任务用户
@@ -125,47 +100,10 @@ public class BpmParallelMultiInstanceActivityBehavior extends ParallelMultiInsta @@ -125,47 +100,10 @@ public class BpmParallelMultiInstanceActivityBehavior extends ParallelMultiInsta
125 return collection; 100 return collection;
126 } 101 }
127 102
128 - private BpmTaskAssignRuleDO getTaskRule(DelegateExecution task) {  
129 - List<BpmTaskAssignRuleDO> taskRules =  
130 - bpmTaskRuleService.getTaskAssignRuleListByProcessDefinitionId(task.getProcessDefinitionId(),  
131 - task.getCurrentActivityId());  
132 - if (CollUtil.isEmpty(taskRules)) {  
133 - throw new FlowableException(  
134 - StrUtil.format("流程任务({}/{}/{}) 找不到符合的任务规则", task.getId(), task.getProcessDefinitionId(),  
135 - task.getCurrentActivityId()));  
136 - }  
137 - if (taskRules.size() > 1) {  
138 - throw new FlowableException(  
139 - StrUtil.format("流程任务({}/{}/{}) 找到过多任务规则({})", task.getId(), task.getProcessDefinitionId(),  
140 - task.getCurrentActivityId(), taskRules.size()));  
141 - }  
142 - return taskRules.get(0);  
143 - }  
144 -  
145 Set<Long> calculateTaskCandidateUsers(DelegateExecution task, BpmTaskAssignRuleDO rule) { 103 Set<Long> calculateTaskCandidateUsers(DelegateExecution task, BpmTaskAssignRuleDO rule) {
146 - Set<Long> assigneeUserIds = null;  
147 - // if (Objects.equals(BpmTaskAssignRuleTypeEnum.ROLE.getType(), rule.getType())) {  
148 - // assigneeUserIds = calculateTaskCandidateUsersByRole(task, rule);  
149 - // } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), rule.getType())) {  
150 - // assigneeUserIds = calculateTaskCandidateUsersByDeptMember(task, rule);  
151 - // } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), rule.getType())) {  
152 - // assigneeUserIds = calculateTaskCandidateUsersByDeptLeader(task, rule);  
153 - // } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.POST.getType(), rule.getType())) {  
154 - // assigneeUserIds = calculateTaskCandidateUsersByPost(task, rule);  
155 - // } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER.getType(), rule.getType())) {  
156 - // assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule);  
157 - // } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) {  
158 - // assigneeUserIds = calculateTaskCandidateUsersByUserGroup(task, rule);  
159 - // } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) {  
160 - // assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule);  
161 - if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_SIGN.getType(), rule.getType())) {  
162 - assigneeUserIds = calculateTaskCandidateUsersSignByUser(task, rule);  
163 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType(), rule.getType())) {  
164 - assigneeUserIds = calculateTaskCandidateUsersSignByUser(task, rule);  
165 - } 104 + Set<Long> assigneeUserIds = SetUtils.asSet(1L, 104L);
166 105
167 // 移除被禁用的用户 106 // 移除被禁用的用户
168 - removeDisableUsers(assigneeUserIds);  
169 // 如果候选人为空,抛出异常 TODO 芋艿:没候选人的策略选择。1 - 挂起;2 - 直接结束;3 - 强制一个兜底人 107 // 如果候选人为空,抛出异常 TODO 芋艿:没候选人的策略选择。1 - 挂起;2 - 直接结束;3 - 强制一个兜底人
170 if (CollUtil.isEmpty(assigneeUserIds)) { 108 if (CollUtil.isEmpty(assigneeUserIds)) {
171 log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}) 找不到候选人]", task.getId(), 109 log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}) 找不到候选人]", task.getId(),
@@ -175,20 +113,4 @@ public class BpmParallelMultiInstanceActivityBehavior extends ParallelMultiInsta @@ -175,20 +113,4 @@ public class BpmParallelMultiInstanceActivityBehavior extends ParallelMultiInsta
175 return assigneeUserIds; 113 return assigneeUserIds;
176 } 114 }
177 115
178 - private Set<Long> calculateTaskCandidateUsersSignByUser(DelegateExecution task, BpmTaskAssignRuleDO rule) {  
179 - return rule.getOptions();  
180 - }  
181 -  
182 - @VisibleForTesting  
183 - void removeDisableUsers(Set<Long> assigneeUserIds) {  
184 - if (CollUtil.isEmpty(assigneeUserIds)) {  
185 - return;  
186 - }  
187 - //TODO 芋艿 这里有数据权限的问题。默认会加上数据权限 dept_id IN (deptId). 导致查询不到数据  
188 - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assigneeUserIds);  
189 - assigneeUserIds.removeIf(id -> {  
190 - AdminUserRespDTO user = userMap.get(id);  
191 - return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus());  
192 - });  
193 - }  
194 } 116 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
@@ -2,25 +2,11 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; @@ -2,25 +2,11 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.RandomUtil; 4 import cn.hutool.core.util.RandomUtil;
5 -import cn.hutool.core.util.StrUtil;  
6 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
7 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; 5 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
8 -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;  
9 -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;  
10 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;  
11 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;  
12 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; 6 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
13 -import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;  
14 -import cn.iocoder.yudao.module.system.api.dept.DeptApi;  
15 -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;  
16 -import cn.iocoder.yudao.module.system.api.permission.PermissionApi;  
17 -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;  
18 -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;  
19 -import com.google.common.annotations.VisibleForTesting;  
20 import lombok.Setter; 7 import lombok.Setter;
21 import lombok.extern.slf4j.Slf4j; 8 import lombok.extern.slf4j.Slf4j;
22 import org.flowable.bpmn.model.UserTask; 9 import org.flowable.bpmn.model.UserTask;
23 -import org.flowable.common.engine.api.FlowableException;  
24 import org.flowable.common.engine.impl.el.ExpressionManager; 10 import org.flowable.common.engine.impl.el.ExpressionManager;
25 import org.flowable.engine.delegate.DelegateExecution; 11 import org.flowable.engine.delegate.DelegateExecution;
26 import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior; 12 import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
@@ -29,14 +15,9 @@ import org.flowable.engine.impl.util.TaskHelper; @@ -29,14 +15,9 @@ import org.flowable.engine.impl.util.TaskHelper;
29 import org.flowable.task.service.TaskService; 15 import org.flowable.task.service.TaskService;
30 import org.flowable.task.service.impl.persistence.entity.TaskEntity; 16 import org.flowable.task.service.impl.persistence.entity.TaskEntity;
31 17
32 -import java.util.*;  
33 -  
34 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;  
35 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;  
36 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;  
37 -import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;  
38 -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS;  
39 -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER; 18 +import java.util.List;
  19 +import java.util.Map;
  20 +import java.util.Set;
40 21
41 /** 22 /**
42 * 自定义的流程任务的 assignee 负责人的分配 23 * 自定义的流程任务的 assignee 负责人的分配
@@ -51,153 +32,24 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { @@ -51,153 +32,24 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
51 32
52 @Setter 33 @Setter
53 private BpmTaskAssignRuleService bpmTaskRuleService; 34 private BpmTaskAssignRuleService bpmTaskRuleService;
54 - @Setter  
55 - private BpmUserGroupService userGroupService;  
56 - @Setter  
57 - private DeptApi deptApi;  
58 - @Setter  
59 - private AdminUserApi adminUserApi;  
60 - @Setter  
61 - private PermissionApi permissionApi;  
62 -  
63 - /**  
64 - * 任务分配脚本  
65 - */  
66 - private Map<Long, BpmTaskAssignScript> scriptMap = Collections.emptyMap();  
67 35
68 public BpmUserTaskActivityBehavior(UserTask userTask) { 36 public BpmUserTaskActivityBehavior(UserTask userTask) {
69 super(userTask); 37 super(userTask);
70 } 38 }
71 39
72 - public void setScripts(List<BpmTaskAssignScript> scripts) {  
73 - this.scriptMap = convertMap(scripts, script -> script.getEnum().getId());  
74 - }  
75 -  
76 @Override 40 @Override
77 @DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据 41 @DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据
78 protected void handleAssignments(TaskService taskService, String assignee, String owner, 42 protected void handleAssignments(TaskService taskService, String assignee, String owner,
79 List<String> candidateUsers, List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager, 43 List<String> candidateUsers, List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager,
80 DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) { 44 DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) {
81 - /*boolean isMultiInstance = hasMultiInstanceCharacteristics();  
82 - if (isMultiInstance) {  
83 - //多实例 会签/或签,执行多次每个人 待办人都在execution里面获取  
84 - Integer assigneeUserId = execution.getVariableLocal("user", Integer.class);  
85 - TaskHelper.changeTaskAssignee(task, String.valueOf(assigneeUserId));  
86 - } else {  
87 - // 第一步,获得任务的规则  
88 - BpmTaskAssignRuleDO rule = getTaskRule(task);  
89 - // 第二步,获得任务的候选用户们  
90 - Set<Long> candidateUserIds = calculateTaskCandidateUsers(task, rule);  
91 - // 第三步,设置一个作为负责人  
92 - Long assigneeUserId = chooseTaskAssignee(execution, candidateUserIds);  
93 - TaskHelper.changeTaskAssignee(task, String.valueOf(assigneeUserId));  
94 - }  
95 - */  
96 - // 第一步,获得任务的规则  
97 - BpmTaskAssignRuleDO rule = getTaskRule(task);  
98 - // 第二步,获得任务的候选用户们  
99 - Set<Long> candidateUserIds = calculateTaskCandidateUsers(task, rule);  
100 - // 第三步,设置一个作为负责人 45 + // 第一步,获得任务的候选用户们
  46 + Set<Long> candidateUserIds = bpmTaskRuleService.calculateTaskCandidateUsers(task);
  47 + // 第二步,选择一个作为候选人
101 Long assigneeUserId = chooseTaskAssignee(execution, candidateUserIds); 48 Long assigneeUserId = chooseTaskAssignee(execution, candidateUserIds);
  49 + // 第三步,设置作为负责人
102 TaskHelper.changeTaskAssignee(task, String.valueOf(assigneeUserId)); 50 TaskHelper.changeTaskAssignee(task, String.valueOf(assigneeUserId));
103 } 51 }
104 52
105 - private BpmTaskAssignRuleDO getTaskRule(TaskEntity task) {  
106 - List<BpmTaskAssignRuleDO> taskRules =  
107 - bpmTaskRuleService.getTaskAssignRuleListByProcessDefinitionId(task.getProcessDefinitionId(),  
108 - task.getTaskDefinitionKey());  
109 - if (CollUtil.isEmpty(taskRules)) {  
110 - throw new FlowableException(  
111 - StrUtil.format("流程任务({}/{}/{}) 找不到符合的任务规则", task.getId(), task.getProcessDefinitionId(),  
112 - task.getTaskDefinitionKey()));  
113 - }  
114 - if (taskRules.size() > 1) {  
115 - throw new FlowableException(  
116 - StrUtil.format("流程任务({}/{}/{}) 找到过多任务规则({})", task.getId(), task.getProcessDefinitionId(),  
117 - task.getTaskDefinitionKey(), taskRules.size()));  
118 - }  
119 - return taskRules.get(0);  
120 - }  
121 -  
122 - Set<Long> calculateTaskCandidateUsers(TaskEntity task, BpmTaskAssignRuleDO rule) {  
123 - Set<Long> assigneeUserIds = null;  
124 - if (Objects.equals(BpmTaskAssignRuleTypeEnum.ROLE.getType(), rule.getType())) {  
125 - assigneeUserIds = calculateTaskCandidateUsersByRole(task, rule);  
126 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), rule.getType())) {  
127 - assigneeUserIds = calculateTaskCandidateUsersByDeptMember(task, rule);  
128 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), rule.getType())) {  
129 - assigneeUserIds = calculateTaskCandidateUsersByDeptLeader(task, rule);  
130 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.POST.getType(), rule.getType())) {  
131 - assigneeUserIds = calculateTaskCandidateUsersByPost(task, rule);  
132 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER.getType(), rule.getType())) {  
133 - assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule);  
134 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) {  
135 - assigneeUserIds = calculateTaskCandidateUsersByUserGroup(task, rule);  
136 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) {  
137 - assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule);  
138 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_SIGN.getType(), rule.getType())) {  
139 - assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule);  
140 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType(), rule.getType())) {  
141 - assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule);  
142 - }  
143 -  
144 - // 移除被禁用的用户  
145 - removeDisableUsers(assigneeUserIds);  
146 - // 如果候选人为空,抛出异常 TODO 芋艿:没候选人的策略选择。1 - 挂起;2 - 直接结束;3 - 强制一个兜底人  
147 - if (CollUtil.isEmpty(assigneeUserIds)) {  
148 - log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}) 找不到候选人]", task.getId(),  
149 - task.getProcessDefinitionId(), task.getTaskDefinitionKey(), toJsonString(rule));  
150 - throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER);  
151 - }  
152 - return assigneeUserIds;  
153 - }  
154 -  
155 - private Set<Long> calculateTaskCandidateUsersByRole(TaskEntity task, BpmTaskAssignRuleDO rule) {  
156 - return permissionApi.getUserRoleIdListByRoleIds(rule.getOptions());  
157 - }  
158 -  
159 - private Set<Long> calculateTaskCandidateUsersByDeptMember(TaskEntity task, BpmTaskAssignRuleDO rule) {  
160 - List<AdminUserRespDTO> users = adminUserApi.getUsersByDeptIds(rule.getOptions());  
161 - return convertSet(users, AdminUserRespDTO::getId);  
162 - }  
163 -  
164 - private Set<Long> calculateTaskCandidateUsersByDeptLeader(TaskEntity task, BpmTaskAssignRuleDO rule) {  
165 - List<DeptRespDTO> depts = deptApi.getDepts(rule.getOptions());  
166 - return convertSet(depts, DeptRespDTO::getLeaderUserId);  
167 - }  
168 -  
169 - private Set<Long> calculateTaskCandidateUsersByPost(TaskEntity task, BpmTaskAssignRuleDO rule) {  
170 - List<AdminUserRespDTO> users = adminUserApi.getUsersByPostIds(rule.getOptions());  
171 - return convertSet(users, AdminUserRespDTO::getId);  
172 - }  
173 -  
174 - private Set<Long> calculateTaskCandidateUsersByUser(TaskEntity task, BpmTaskAssignRuleDO rule) {  
175 - return rule.getOptions();  
176 - }  
177 -  
178 - private Set<Long> calculateTaskCandidateUsersByUserGroup(TaskEntity task, BpmTaskAssignRuleDO rule) {  
179 - List<BpmUserGroupDO> userGroups = userGroupService.getUserGroupList(rule.getOptions());  
180 - Set<Long> userIds = new HashSet<>();  
181 - userGroups.forEach(group -> userIds.addAll(group.getMemberUserIds()));  
182 - return userIds;  
183 - }  
184 -  
185 - private Set<Long> calculateTaskCandidateUsersByScript(TaskEntity task, BpmTaskAssignRuleDO rule) {  
186 - // 获得对应的脚本  
187 - List<BpmTaskAssignScript> scripts = new ArrayList<>(rule.getOptions().size());  
188 - rule.getOptions().forEach(id -> {  
189 - BpmTaskAssignScript script = scriptMap.get(id);  
190 - if (script == null) {  
191 - throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, id);  
192 - }  
193 - scripts.add(script);  
194 - });  
195 - // 逐个计算任务  
196 - Set<Long> userIds = new HashSet<>();  
197 - scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(task)));  
198 - return userIds;  
199 - }  
200 -  
201 private Long chooseTaskAssignee(DelegateExecution execution, Set<Long> candidateUserIds) { 53 private Long chooseTaskAssignee(DelegateExecution execution, Set<Long> candidateUserIds) {
202 // 获取任务变量 54 // 获取任务变量
203 Map<String, Object> variables = execution.getVariables(); 55 Map<String, Object> variables = execution.getVariables();
@@ -214,16 +66,4 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { @@ -214,16 +66,4 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
214 return CollUtil.get(candidateUserIds, index); 66 return CollUtil.get(candidateUserIds, index);
215 } 67 }
216 68
217 - @VisibleForTesting  
218 - void removeDisableUsers(Set<Long> assigneeUserIds) {  
219 - if (CollUtil.isEmpty(assigneeUserIds)) {  
220 - return;  
221 - }  
222 - //TODO 芋艿 这里有数据权限的问题。默认会加上数据权限 dept_id IN (deptId). 导致查询不到数据  
223 - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assigneeUserIds);  
224 - assigneeUserIds.removeIf(id -> {  
225 - AdminUserRespDTO user = userMap.get(id);  
226 - return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus());  
227 - });  
228 - }  
229 } 69 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java
@@ -4,10 +4,12 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAs @@ -4,10 +4,12 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAs
4 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO; 4 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
5 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO; 5 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
6 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; 6 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
  7 +import org.flowable.task.service.impl.persistence.entity.TaskEntity;
7 import org.springframework.lang.Nullable; 8 import org.springframework.lang.Nullable;
8 9
9 import javax.validation.Valid; 10 import javax.validation.Valid;
10 import java.util.List; 11 import java.util.List;
  12 +import java.util.Set;
11 13
12 /** 14 /**
13 * BPM 任务分配规则 Service 接口 15 * BPM 任务分配规则 Service 接口
@@ -84,4 +86,6 @@ public interface BpmTaskAssignRuleService { @@ -84,4 +86,6 @@ public interface BpmTaskAssignRuleService {
84 */ 86 */
85 void checkTaskAssignRuleAllConfig(String id); 87 void checkTaskAssignRuleAllConfig(String id);
86 88
  89 + Set<Long> calculateTaskCandidateUsers(TaskEntity task);
  90 +
87 } 91 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
@@ -3,25 +3,35 @@ package cn.iocoder.yudao.module.bpm.service.definition; @@ -3,25 +3,35 @@ package cn.iocoder.yudao.module.bpm.service.definition;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
5 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
7 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 8 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  9 +import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
8 import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils; 10 import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
9 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO; 11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO; 12 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO; 13 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
12 import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert; 14 import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert;
13 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; 15 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
  16 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
14 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; 17 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
15 -import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;  
16 import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum; 18 import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
  19 +import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
  20 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
17 import cn.iocoder.yudao.module.system.api.dept.DeptApi; 21 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
18 import cn.iocoder.yudao.module.system.api.dept.PostApi; 22 import cn.iocoder.yudao.module.system.api.dept.PostApi;
  23 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
19 import cn.iocoder.yudao.module.system.api.dict.DictDataApi; 24 import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
  25 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
20 import cn.iocoder.yudao.module.system.api.permission.RoleApi; 26 import cn.iocoder.yudao.module.system.api.permission.RoleApi;
21 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 27 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  28 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  29 +import com.google.common.annotations.VisibleForTesting;
22 import lombok.extern.slf4j.Slf4j; 30 import lombok.extern.slf4j.Slf4j;
23 import org.flowable.bpmn.model.BpmnModel; 31 import org.flowable.bpmn.model.BpmnModel;
24 import org.flowable.bpmn.model.UserTask; 32 import org.flowable.bpmn.model.UserTask;
  33 +import org.flowable.common.engine.api.FlowableException;
  34 +import org.flowable.task.service.impl.persistence.entity.TaskEntity;
25 import org.springframework.context.annotation.Lazy; 35 import org.springframework.context.annotation.Lazy;
26 import org.springframework.stereotype.Service; 36 import org.springframework.stereotype.Service;
27 import org.springframework.validation.annotation.Validated; 37 import org.springframework.validation.annotation.Validated;
@@ -31,6 +41,9 @@ import javax.validation.Valid; @@ -31,6 +41,9 @@ import javax.validation.Valid;
31 import java.util.*; 41 import java.util.*;
32 42
33 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 43 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  44 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  45 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  46 +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
34 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; 47 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
35 48
36 /** 49 /**
@@ -61,6 +74,17 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { @@ -61,6 +74,17 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
61 private AdminUserApi adminUserApi; 74 private AdminUserApi adminUserApi;
62 @Resource 75 @Resource
63 private DictDataApi dictDataApi; 76 private DictDataApi dictDataApi;
  77 + @Resource
  78 + private PermissionApi permissionApi;
  79 + /**
  80 + * 任务分配脚本
  81 + */
  82 + private Map<Long, BpmTaskAssignScript> scriptMap = Collections.emptyMap();
  83 +
  84 + @Resource
  85 + public void setScripts(List<BpmTaskAssignScript> scripts) {
  86 + this.scriptMap = convertMap(scripts, script -> script.getEnum().getId());
  87 + }
64 88
65 @Override 89 @Override
66 public List<BpmTaskAssignRuleDO> getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId, 90 public List<BpmTaskAssignRuleDO> getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId,
@@ -198,10 +222,6 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { @@ -198,10 +222,6 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
198 adminUserApi.validUsers(options); 222 adminUserApi.validUsers(options);
199 } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_GROUP.getType())) { 223 } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_GROUP.getType())) {
200 userGroupService.validUserGroups(options); 224 userGroupService.validUserGroups(options);
201 - } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_SIGN.getType())) {  
202 - adminUserApi.validUsers(options);  
203 - } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType())) {  
204 - adminUserApi.validUsers(options);  
205 } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) { 225 } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) {
206 dictDataApi.validDictDatas(DictTypeConstants.TASK_ASSIGN_SCRIPT, 226 dictDataApi.validDictDatas(DictTypeConstants.TASK_ASSIGN_SCRIPT,
207 CollectionUtils.convertSet(options, String::valueOf)); 227 CollectionUtils.convertSet(options, String::valueOf));
@@ -209,4 +229,117 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { @@ -209,4 +229,117 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
209 throw new IllegalArgumentException(StrUtil.format("未知的规则类型({})", type)); 229 throw new IllegalArgumentException(StrUtil.format("未知的规则类型({})", type));
210 } 230 }
211 } 231 }
  232 +
  233 + @Override
  234 + @DataPermission(enable = false) // 忽略数据权限,不然分配会存在问题
  235 + public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
  236 + BpmTaskAssignRuleDO rule = getTaskRule(task);
  237 + return calculateTaskCandidateUsers(task, rule);
  238 + }
  239 +
  240 + @VisibleForTesting
  241 + BpmTaskAssignRuleDO getTaskRule(TaskEntity task) {
  242 + List<BpmTaskAssignRuleDO> taskRules = getTaskAssignRuleListByProcessDefinitionId(
  243 + task.getProcessDefinitionId(), task.getTaskDefinitionKey());
  244 + if (CollUtil.isEmpty(taskRules)) {
  245 + throw new FlowableException(
  246 + StrUtil.format("流程任务({}/{}/{}) 找不到符合的任务规则", task.getId(), task.getProcessDefinitionId(),
  247 + task.getTaskDefinitionKey()));
  248 + }
  249 + if (taskRules.size() > 1) {
  250 + throw new FlowableException(
  251 + StrUtil.format("流程任务({}/{}/{}) 找到过多任务规则({})", task.getId(), task.getProcessDefinitionId(),
  252 + task.getTaskDefinitionKey(), taskRules.size()));
  253 + }
  254 + return taskRules.get(0);
  255 + }
  256 +
  257 + @VisibleForTesting
  258 + Set<Long> calculateTaskCandidateUsers(TaskEntity task, BpmTaskAssignRuleDO rule) {
  259 + Set<Long> assigneeUserIds = null;
  260 + if (Objects.equals(BpmTaskAssignRuleTypeEnum.ROLE.getType(), rule.getType())) {
  261 + assigneeUserIds = calculateTaskCandidateUsersByRole(task, rule);
  262 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), rule.getType())) {
  263 + assigneeUserIds = calculateTaskCandidateUsersByDeptMember(task, rule);
  264 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), rule.getType())) {
  265 + assigneeUserIds = calculateTaskCandidateUsersByDeptLeader(task, rule);
  266 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.POST.getType(), rule.getType())) {
  267 + assigneeUserIds = calculateTaskCandidateUsersByPost(task, rule);
  268 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER.getType(), rule.getType())) {
  269 + assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule);
  270 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) {
  271 + assigneeUserIds = calculateTaskCandidateUsersByUserGroup(task, rule);
  272 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) {
  273 + assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule);
  274 + }
  275 +
  276 + // 移除被禁用的用户
  277 + removeDisableUsers(assigneeUserIds);
  278 + // 如果候选人为空,抛出异常 TODO 芋艿:没候选人的策略选择。1 - 挂起;2 - 直接结束;3 - 强制一个兜底人
  279 + if (CollUtil.isEmpty(assigneeUserIds)) {
  280 + log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}) 找不到候选人]", task.getId(),
  281 + task.getProcessDefinitionId(), task.getTaskDefinitionKey(), toJsonString(rule));
  282 + throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER);
  283 + }
  284 + return assigneeUserIds;
  285 + }
  286 +
  287 + private Set<Long> calculateTaskCandidateUsersByRole(TaskEntity task, BpmTaskAssignRuleDO rule) {
  288 + return permissionApi.getUserRoleIdListByRoleIds(rule.getOptions());
  289 + }
  290 +
  291 + private Set<Long> calculateTaskCandidateUsersByDeptMember(TaskEntity task, BpmTaskAssignRuleDO rule) {
  292 + List<AdminUserRespDTO> users = adminUserApi.getUsersByDeptIds(rule.getOptions());
  293 + return convertSet(users, AdminUserRespDTO::getId);
  294 + }
  295 +
  296 + private Set<Long> calculateTaskCandidateUsersByDeptLeader(TaskEntity task, BpmTaskAssignRuleDO rule) {
  297 + List<DeptRespDTO> depts = deptApi.getDepts(rule.getOptions());
  298 + return convertSet(depts, DeptRespDTO::getLeaderUserId);
  299 + }
  300 +
  301 + private Set<Long> calculateTaskCandidateUsersByPost(TaskEntity task, BpmTaskAssignRuleDO rule) {
  302 + List<AdminUserRespDTO> users = adminUserApi.getUsersByPostIds(rule.getOptions());
  303 + return convertSet(users, AdminUserRespDTO::getId);
  304 + }
  305 +
  306 + private Set<Long> calculateTaskCandidateUsersByUser(TaskEntity task, BpmTaskAssignRuleDO rule) {
  307 + return rule.getOptions();
  308 + }
  309 +
  310 + private Set<Long> calculateTaskCandidateUsersByUserGroup(TaskEntity task, BpmTaskAssignRuleDO rule) {
  311 + List<BpmUserGroupDO> userGroups = userGroupService.getUserGroupList(rule.getOptions());
  312 + Set<Long> userIds = new HashSet<>();
  313 + userGroups.forEach(group -> userIds.addAll(group.getMemberUserIds()));
  314 + return userIds;
  315 + }
  316 +
  317 + private Set<Long> calculateTaskCandidateUsersByScript(TaskEntity task, BpmTaskAssignRuleDO rule) {
  318 + // 获得对应的脚本
  319 + List<BpmTaskAssignScript> scripts = new ArrayList<>(rule.getOptions().size());
  320 + rule.getOptions().forEach(id -> {
  321 + BpmTaskAssignScript script = scriptMap.get(id);
  322 + if (script == null) {
  323 + throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, id);
  324 + }
  325 + scripts.add(script);
  326 + });
  327 + // 逐个计算任务
  328 + Set<Long> userIds = new HashSet<>();
  329 + scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(task)));
  330 + return userIds;
  331 + }
  332 +
  333 + @VisibleForTesting
  334 + void removeDisableUsers(Set<Long> assigneeUserIds) {
  335 + if (CollUtil.isEmpty(assigneeUserIds)) {
  336 + return;
  337 + }
  338 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assigneeUserIds);
  339 + assigneeUserIds.removeIf(id -> {
  340 + AdminUserRespDTO user = userMap.get(id);
  341 + return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus());
  342 + });
  343 + }
  344 +
212 } 345 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
@@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; @@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
15 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; 15 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
16 import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper; 16 import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper;
17 import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper; 17 import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper;
18 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;  
19 import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum; 18 import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
20 import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; 19 import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
21 import cn.iocoder.yudao.module.business.hi.task.inst.service.HiTaskInstService; 20 import cn.iocoder.yudao.module.business.hi.task.inst.service.HiTaskInstService;
@@ -214,11 +213,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -214,11 +213,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
214 taskAssignRuleMapper.selectListByProcessDefinitionId(task.getProcessDefinitionId(), 213 taskAssignRuleMapper.selectListByProcessDefinitionId(task.getProcessDefinitionId(),
215 task.getTaskDefinitionKey()); 214 task.getTaskDefinitionKey());
216 if (CollUtil.isNotEmpty(bpmTaskAssignRuleList) && bpmTaskAssignRuleList.size() > 0) { 215 if (CollUtil.isNotEmpty(bpmTaskAssignRuleList) && bpmTaskAssignRuleList.size() > 0) {
217 - if (BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType().equals(bpmTaskAssignRuleList.get(0).getType())) {  
218 - taskExtMapper.delTaskByProcInstIdAndTaskIdAndTaskDefKey(  
219 - new BpmTaskExtDO().setTaskId(task.getId()).setTaskDefKey(task.getTaskDefinitionKey())  
220 - .setProcessInstanceId(task.getProcessInstanceId()));  
221 - } 216 + // edit by 芋艿
  217 +// if (BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType().equals(bpmTaskAssignRuleList.get(0).getType())) {
  218 +// taskExtMapper.delTaskByProcInstIdAndTaskIdAndTaskDefKey(
  219 +// new BpmTaskExtDO().setTaskId(task.getId()).setTaskDefKey(task.getTaskDefinitionKey())
  220 +// .setProcessInstanceId(task.getProcessInstanceId()));
  221 +// }
222 } 222 }
223 } 223 }
224 224
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/business/hi/task/inst/service/HiTaskInstService.java
@@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPage @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPage
9 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; 9 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
10 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; 10 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
11 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; 11 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
12 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;  
13 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 12 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
14 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; 13 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
15 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; 14 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
@@ -21,14 +20,18 @@ import org.flowable.common.engine.impl.de.odysseus.el.ExpressionFactoryImpl; @@ -21,14 +20,18 @@ import org.flowable.common.engine.impl.de.odysseus.el.ExpressionFactoryImpl;
21 import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext; 20 import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext;
22 import org.flowable.common.engine.impl.javax.el.ExpressionFactory; 21 import org.flowable.common.engine.impl.javax.el.ExpressionFactory;
23 import org.flowable.common.engine.impl.javax.el.ValueExpression; 22 import org.flowable.common.engine.impl.javax.el.ValueExpression;
24 -import org.flowable.engine.*; 23 +import org.flowable.engine.HistoryService;
  24 +import org.flowable.engine.RepositoryService;
25 import org.flowable.engine.history.HistoricProcessInstance; 25 import org.flowable.engine.history.HistoricProcessInstance;
26 import org.flowable.task.api.history.HistoricTaskInstance; 26 import org.flowable.task.api.history.HistoricTaskInstance;
27 import org.flowable.variable.api.history.HistoricVariableInstance; 27 import org.flowable.variable.api.history.HistoricVariableInstance;
28 import org.springframework.stereotype.Service; 28 import org.springframework.stereotype.Service;
29 29
30 import javax.annotation.Resource; 30 import javax.annotation.Resource;
31 -import java.util.*; 31 +import java.util.HashMap;
  32 +import java.util.LinkedList;
  33 +import java.util.List;
  34 +import java.util.Map;
32 import java.util.function.Function; 35 import java.util.function.Function;
33 import java.util.stream.Collectors; 36 import java.util.stream.Collectors;
34 37
@@ -259,10 +262,11 @@ public class HiTaskInstService { @@ -259,10 +262,11 @@ public class HiTaskInstService {
259 DeptDO deptDO = deptMap.get(adminUserDO.getDeptId()); 262 DeptDO deptDO = deptMap.get(adminUserDO.getDeptId());
260 bpmTaskRespVO.setAssigneeUser(setUser(adminUserDO)); 263 bpmTaskRespVO.setAssigneeUser(setUser(adminUserDO));
261 bpmTaskRespVO.getAssigneeUser().setDeptName(deptDO.getName()); 264 bpmTaskRespVO.getAssigneeUser().setDeptName(deptDO.getName());
262 - if (!bpmTaskAssignRuleDO.getType().equals(BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType())  
263 - && !bpmTaskAssignRuleDO.getType().equals(BpmTaskAssignRuleTypeEnum.USER_SIGN.getType())) {  
264 - break;  
265 - } 265 + // edit by 芋艿
  266 +// if (!bpmTaskAssignRuleDO.getType().equals(BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType())
  267 +// && !bpmTaskAssignRuleDO.getType().equals(BpmTaskAssignRuleTypeEnum.USER_SIGN.getType())) {
  268 +// break;
  269 +// }
266 } 270 }
267 } 271 }
268 getFlow(bpmnModel, nextTaskDefKey, tmpBpmTaskAssignRuleDOList, bpmTaskRespVOList, userDoMap, deptMap, 272 getFlow(bpmnModel, nextTaskDefKey, tmpBpmTaskAssignRuleDOList, bpmTaskRespVOList, userDoMap, deptMap,
yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmActivityMapper.xml
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 SELECT * 21 SELECT *
22 FROM act_hi_taskinst; 22 FROM act_hi_taskinst;
23 </select> 23 </select>
  24 +
24 <select id="listAllByProcInstIdAndDelete" 25 <select id="listAllByProcInstIdAndDelete"
25 resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO"> 26 resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmActivityDO">
26 SELECT id_ AS `id`, 27 SELECT id_ AS `id`,
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  5 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  6 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  7 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  8 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  9 +import org.flowable.task.service.impl.persistence.entity.TaskEntity;
  10 +import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
  11 +import org.junit.jupiter.api.Test;
  12 +import org.mockito.InjectMocks;
  13 +import org.mockito.Mock;
  14 +
  15 +import java.util.Set;
  16 +
  17 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  18 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  19 +import static org.junit.jupiter.api.Assertions.assertEquals;
  20 +import static org.mockito.ArgumentMatchers.eq;
  21 +import static org.mockito.Mockito.when;
  22 +
  23 +public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
  24 +
  25 + @InjectMocks
  26 + private BpmTaskAssignLeaderX2Script script;
  27 +
  28 + @Mock
  29 + private AdminUserApi adminUserApi;
  30 + @Mock
  31 + private DeptApi deptApi;
  32 + @Mock
  33 + private BpmProcessInstanceService bpmProcessInstanceService;
  34 +
  35 + @Test
  36 + public void testCalculateTaskCandidateUsers_noDept() {
  37 + // 准备参数
  38 + TaskEntity task = buildTaskEntity(1L);
  39 + // mock 方法(startUser)
  40 + AdminUserRespDTO startUser = randomPojo(AdminUserRespDTO.class, o -> o.setDeptId(10L));
  41 + when(adminUserApi.getUser(eq(1L))).thenReturn(startUser);
  42 +
  43 + // 调用
  44 + Set<Long> result = script.calculateTaskCandidateUsers(task);
  45 + // 断言
  46 + assertEquals(0, result.size());
  47 + }
  48 +
  49 + @Test
  50 + public void testCalculateTaskCandidateUsers_noParentDept() {
  51 + // 准备参数
  52 + TaskEntity task = buildTaskEntity(1L);
  53 + // mock 方法(startUser)
  54 + AdminUserRespDTO startUser = randomPojo(AdminUserRespDTO.class, o -> o.setDeptId(10L));
  55 + when(adminUserApi.getUser(eq(1L))).thenReturn(startUser);
  56 + DeptRespDTO startUserDept = randomPojo(DeptRespDTO.class, o -> o.setId(10L).setParentId(100L)
  57 + .setLeaderUserId(20L));
  58 + when(deptApi.getDept(eq(10L))).thenReturn(startUserDept);
  59 +
  60 + // 调用
  61 + Set<Long> result = script.calculateTaskCandidateUsers(task);
  62 + // 断言
  63 + assertEquals(asSet(20L), result);
  64 + }
  65 +
  66 + @Test
  67 + public void testCalculateTaskCandidateUsers_existParentDept() {
  68 + // 准备参数
  69 + TaskEntity task = buildTaskEntity(1L);
  70 + // mock 方法(startUser)
  71 + AdminUserRespDTO startUser = randomPojo(AdminUserRespDTO.class, o -> o.setDeptId(10L));
  72 + when(adminUserApi.getUser(eq(1L))).thenReturn(startUser);
  73 + DeptRespDTO startUserDept = randomPojo(DeptRespDTO.class, o -> o.setId(10L).setParentId(100L)
  74 + .setLeaderUserId(20L));
  75 + when(deptApi.getDept(eq(10L))).thenReturn(startUserDept);
  76 + // mock 方法(父 dept)
  77 + DeptRespDTO parentDept = randomPojo(DeptRespDTO.class, o -> o.setId(100L).setParentId(1000L)
  78 + .setLeaderUserId(200L));
  79 + when(deptApi.getDept(eq(100L))).thenReturn(parentDept);
  80 +
  81 + // 调用
  82 + Set<Long> result = script.calculateTaskCandidateUsers(task);
  83 + // 断言
  84 + assertEquals(asSet(200L), result);
  85 + }
  86 +
  87 + @SuppressWarnings("SameParameterValue")
  88 + private TaskEntity buildTaskEntity(Long startUserId) {
  89 + TaskEntityImpl task = new TaskEntityImpl();
  90 +// task.setProcessInstance(new ExecutionEntityImpl());
  91 +// task.getProcessInstance().setStartUserId(String.valueOf(startUserId));
  92 + // TODO
  93 + return task;
  94 + }
  95 +
  96 +}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImplTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.hutool.core.map.MapUtil;
  4 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  5 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  6 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  7 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
  8 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
  9 +import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
  10 +import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum;
  11 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
  12 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  13 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  14 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
  15 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  16 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  17 +import org.flowable.task.service.impl.persistence.entity.TaskEntity;
  18 +import org.junit.jupiter.api.Test;
  19 +import org.springframework.boot.test.mock.mockito.MockBean;
  20 +import org.springframework.context.annotation.Import;
  21 +
  22 +import javax.annotation.Resource;
  23 +import java.util.Arrays;
  24 +import java.util.List;
  25 +import java.util.Map;
  26 +import java.util.Set;
  27 +
  28 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  29 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  30 +import static java.util.Collections.singleton;
  31 +import static org.junit.jupiter.api.Assertions.assertEquals;
  32 +import static org.mockito.ArgumentMatchers.eq;
  33 +import static org.mockito.Mockito.when;
  34 +
  35 +/**
  36 + * {@link BpmTaskAssignRuleService} 的单元测试
  37 + *
  38 + * @author 芋道源码
  39 + */
  40 +@Import(BpmTaskAssignRuleServiceImpl.class)
  41 +public class BpmTaskAssignRuleServiceImplTest extends BaseDbUnitTest {
  42 +
  43 + @Resource
  44 + private BpmTaskAssignRuleServiceImpl bpmTaskRuleService;
  45 +
  46 + @MockBean
  47 + private BpmUserGroupService userGroupService;
  48 + @MockBean
  49 + private DeptApi deptApi;
  50 + @MockBean
  51 + private AdminUserApi adminUserApi;
  52 + @MockBean
  53 + private PermissionApi permissionApi;
  54 +
  55 + @Test
  56 + public void testCalculateTaskCandidateUsers_Role() {
  57 + // 准备参数
  58 + BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
  59 + .setType(BpmTaskAssignRuleTypeEnum.ROLE.getType());
  60 + // mock 方法
  61 + when(permissionApi.getUserRoleIdListByRoleIds(eq(rule.getOptions())))
  62 + .thenReturn(asSet(11L, 22L));
  63 + mockGetUserMap(asSet(11L, 22L));
  64 +
  65 + // 调用
  66 + Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
  67 + // 断言
  68 + assertEquals(asSet(11L, 22L), results);
  69 + }
  70 +
  71 + @Test
  72 + public void testCalculateTaskCandidateUsers_DeptMember() {
  73 + // 准备参数
  74 + BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
  75 + .setType(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType());
  76 + // mock 方法
  77 + List<AdminUserRespDTO> users = CollectionUtils.convertList(asSet(11L, 22L),
  78 + id -> new AdminUserRespDTO().setId(id));
  79 + when(adminUserApi.getUsersByDeptIds(eq(rule.getOptions()))).thenReturn(users);
  80 + mockGetUserMap(asSet(11L, 22L));
  81 +
  82 + // 调用
  83 + Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
  84 + // 断言
  85 + assertEquals(asSet(11L, 22L), results);
  86 + }
  87 +
  88 + @Test
  89 + public void testCalculateTaskCandidateUsers_DeptLeader() {
  90 + // 准备参数
  91 + BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
  92 + .setType(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType());
  93 + // mock 方法
  94 + DeptRespDTO dept1 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(11L));
  95 + DeptRespDTO dept2 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(22L));
  96 + when(deptApi.getDepts(eq(rule.getOptions()))).thenReturn(Arrays.asList(dept1, dept2));
  97 + mockGetUserMap(asSet(11L, 22L));
  98 +
  99 + // 调用
  100 + Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
  101 + // 断言
  102 + assertEquals(asSet(11L, 22L), results);
  103 + }
  104 +
  105 + @Test
  106 + public void testCalculateTaskCandidateUsers_Post() {
  107 + // 准备参数
  108 + BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
  109 + .setType(BpmTaskAssignRuleTypeEnum.POST.getType());
  110 + // mock 方法
  111 + List<AdminUserRespDTO> users = CollectionUtils.convertList(asSet(11L, 22L),
  112 + id -> new AdminUserRespDTO().setId(id));
  113 + when(adminUserApi.getUsersByPostIds(eq(rule.getOptions()))).thenReturn(users);
  114 + mockGetUserMap(asSet(11L, 22L));
  115 +
  116 + // 调用
  117 + Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
  118 + // 断言
  119 + assertEquals(asSet(11L, 22L), results);
  120 + }
  121 +
  122 + @Test
  123 + public void testCalculateTaskCandidateUsers_User() {
  124 + // 准备参数
  125 + BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
  126 + .setType(BpmTaskAssignRuleTypeEnum.USER.getType());
  127 + // mock 方法
  128 + mockGetUserMap(asSet(1L, 2L));
  129 +
  130 + // 调用
  131 + Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
  132 + // 断言
  133 + assertEquals(asSet(1L, 2L), results);
  134 + }
  135 +
  136 + @Test
  137 + public void testCalculateTaskCandidateUsers_UserGroup() {
  138 + // 准备参数
  139 + BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
  140 + .setType(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType());
  141 + // mock 方法
  142 + BpmUserGroupDO userGroup1 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(11L, 12L)));
  143 + BpmUserGroupDO userGroup2 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(21L, 22L)));
  144 + when(userGroupService.getUserGroupList(eq(rule.getOptions()))).thenReturn(Arrays.asList(userGroup1, userGroup2));
  145 + mockGetUserMap(asSet(11L, 12L, 21L, 22L));
  146 +
  147 + // 调用
  148 + Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
  149 + // 断言
  150 + assertEquals(asSet(11L, 12L, 21L, 22L), results);
  151 + }
  152 +
  153 + @Test
  154 + public void testCalculateTaskCandidateUsers_Script() {
  155 + // 准备参数
  156 + BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(20L, 21L))
  157 + .setType(BpmTaskAssignRuleTypeEnum.SCRIPT.getType());
  158 + // mock 方法
  159 + BpmTaskAssignScript script1 = new BpmTaskAssignScript() {
  160 +
  161 + @Override
  162 + public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
  163 + return singleton(11L);
  164 + }
  165 +
  166 + @Override
  167 + public BpmTaskRuleScriptEnum getEnum() {
  168 + return BpmTaskRuleScriptEnum.LEADER_X1;
  169 + }
  170 + };
  171 + BpmTaskAssignScript script2 = new BpmTaskAssignScript() {
  172 +
  173 + @Override
  174 + public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
  175 + return singleton(22L);
  176 + }
  177 +
  178 + @Override
  179 + public BpmTaskRuleScriptEnum getEnum() {
  180 + return BpmTaskRuleScriptEnum.LEADER_X2;
  181 + }
  182 + };
  183 + bpmTaskRuleService.setScripts(Arrays.asList(script1, script2));
  184 + mockGetUserMap(asSet(11L, 22L));
  185 +
  186 + // 调用
  187 + Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
  188 + // 断言
  189 + assertEquals(asSet(11L, 22L), results);
  190 + }
  191 +
  192 + @Test
  193 + public void testRemoveDisableUsers() {
  194 + // 准备参数. 1L 可以找到;2L 是禁用的;3L 找不到
  195 + Set<Long> assigneeUserIds = asSet(1L, 2L, 3L);
  196 + // mock 方法
  197 + AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)
  198 + .setStatus(CommonStatusEnum.ENABLE.getStatus()));
  199 + AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)
  200 + .setStatus(CommonStatusEnum.DISABLE.getStatus()));
  201 + Map<Long, AdminUserRespDTO> userMap = MapUtil.builder(user1.getId(), user1)
  202 + .put(user2.getId(), user2).build();
  203 + when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);
  204 +
  205 + // 调用
  206 + bpmTaskRuleService.removeDisableUsers(assigneeUserIds);
  207 + // 断言
  208 + assertEquals(asSet(1L), assigneeUserIds);
  209 + }
  210 +
  211 + private void mockGetUserMap(Set<Long> assigneeUserIds) {
  212 + Map<Long, AdminUserRespDTO> userMap = CollectionUtils.convertMap(assigneeUserIds, id -> id,
  213 + id -> new AdminUserRespDTO().setId(id).setStatus(CommonStatusEnum.ENABLE.getStatus()));
  214 + when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);
  215 + }
  216 +
  217 +}