Commit 040a1bcfad61bb6083dd6dae2f869fed312f56b4

Authored by YunaiV
1 parent e7815dd7

【代码评审】工作流:连续多级部门负责人的实现

yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateAbstractDeptLeaderStrategy.java
@@ -6,10 +6,7 @@ import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCand @@ -6,10 +6,7 @@ import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCand
6 import cn.iocoder.yudao.module.system.api.dept.DeptApi; 6 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
7 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; 7 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
8 8
9 -import java.util.Collections;  
10 -import java.util.LinkedHashSet;  
11 -import java.util.List;  
12 -import java.util.Set; 9 +import java.util.*;
13 10
14 /** 11 /**
15 * 部门的负责人 {@link BpmTaskCandidateStrategy} 抽象类 12 * 部门的负责人 {@link BpmTaskCandidateStrategy} 抽象类
@@ -25,44 +22,43 @@ public abstract class BpmTaskCandidateAbstractDeptLeaderStrategy implements BpmT @@ -25,44 +22,43 @@ public abstract class BpmTaskCandidateAbstractDeptLeaderStrategy implements BpmT
25 } 22 }
26 23
27 /** 24 /**
28 - * 获取上级部门的负责人 25 + * 获得指定层级的部门负责人,只有第 level 的负责人
29 * 26 *
30 - * @param assignDept 指定部门  
31 - * @param level 第几级  
32 - * @return 部门负责人 Id 27 + * @param dept 指定部门
  28 + * @param level 第几级
  29 + * @return 部门负责人的编号
33 */ 30 */
34 - protected Long getAssignLevelDeptLeaderId(DeptRespDTO assignDept, Integer level) { 31 + protected Long getAssignLevelDeptLeaderId(DeptRespDTO dept, Integer level) {
35 Assert.isTrue(level > 0, "level 必须大于 0"); 32 Assert.isTrue(level > 0, "level 必须大于 0");
36 - if (assignDept == null) { 33 + if (dept == null) {
37 return null; 34 return null;
38 } 35 }
39 - DeptRespDTO dept = assignDept; 36 + DeptRespDTO currentDept = dept;
40 for (int i = 1; i < level; i++) { 37 for (int i = 1; i < level; i++) {
41 - DeptRespDTO parentDept = deptApi.getDept(dept.getParentId()); 38 + DeptRespDTO parentDept = deptApi.getDept(currentDept.getParentId());
42 if (parentDept == null) { // 找不到父级部门,到了最高级。返回最高级的部门负责人 39 if (parentDept == null) { // 找不到父级部门,到了最高级。返回最高级的部门负责人
43 break; 40 break;
44 } 41 }
45 - dept = parentDept; 42 + currentDept = parentDept;
46 } 43 }
47 - return dept.getLeaderUserId(); 44 + return currentDept.getLeaderUserId();
48 } 45 }
49 46
50 /** 47 /**
51 - * 获取连续上级部门的负责人, 包含指定部门的负责人 48 + * 获得连续层级的部门负责人,包含 [1, level] 的负责人
52 * 49 *
53 - * @param assignDeptIds 指定部门 Ids  
54 - * @param level 第几级 50 + * @param deptIds 指定部门编号数组
  51 + * @param level 最大层级
55 * @return 连续部门负责人 Id 52 * @return 连续部门负责人 Id
56 */ 53 */
57 - protected Set<Long> getMultiLevelDeptLeaderIds(List<Long> assignDeptIds, Integer level) { 54 + protected Set<Long> getMultiLevelDeptLeaderIds(List<Long> deptIds, Integer level) {
58 Assert.isTrue(level > 0, "level 必须大于 0"); 55 Assert.isTrue(level > 0, "level 必须大于 0");
59 - if (CollUtil.isEmpty(assignDeptIds)) {  
60 - return Collections.emptySet(); 56 + if (CollUtil.isEmpty(deptIds)) {
  57 + return new HashSet<>();
61 } 58 }
62 Set<Long> deptLeaderIds = new LinkedHashSet<>(); // 保证有序 59 Set<Long> deptLeaderIds = new LinkedHashSet<>(); // 保证有序
63 - DeptRespDTO dept;  
64 - for (Long deptId : assignDeptIds) {  
65 - dept = deptApi.getDept(deptId); 60 + for (Long deptId : deptIds) {
  61 + DeptRespDTO dept = deptApi.getDept(deptId);
66 for (int i = 0; i < level; i++) { 62 for (int i = 0; i < level; i++) {
67 if (dept.getLeaderUserId() != null) { 63 if (dept.getLeaderUserId() != null) {
68 deptLeaderIds.add(dept.getLeaderUserId()); 64 deptLeaderIds.add(dept.getLeaderUserId());
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateMultiLevelDeptLeaderStrategy.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptLeaderMultiStrategy.java
@@ -18,20 +18,21 @@ import java.util.Set; @@ -18,20 +18,21 @@ import java.util.Set;
18 * @author jason 18 * @author jason
19 */ 19 */
20 @Component 20 @Component
21 -public class BpmTaskCandidateMultiLevelDeptLeaderStrategy extends BpmTaskCandidateAbstractDeptLeaderStrategy { 21 +public class BpmTaskCandidateDeptLeaderMultiStrategy extends BpmTaskCandidateAbstractDeptLeaderStrategy {
22 22
23 - public BpmTaskCandidateMultiLevelDeptLeaderStrategy(DeptApi deptApi) { 23 + public BpmTaskCandidateDeptLeaderMultiStrategy(DeptApi deptApi) {
24 super(deptApi); 24 super(deptApi);
25 } 25 }
26 26
27 @Override 27 @Override
28 public BpmTaskCandidateStrategyEnum getStrategy() { 28 public BpmTaskCandidateStrategyEnum getStrategy() {
29 - return BpmTaskCandidateStrategyEnum.MULTI_LEVEL_DEPT_LEADER; 29 + return BpmTaskCandidateStrategyEnum.MULTI_DEPT_LEADER_MULTI;
30 } 30 }
31 31
32 @Override 32 @Override
33 public void validateParam(String param) { 33 public void validateParam(String param) {
34 - // 参数格式: ,分割。前面的部门Id. 可以为多个。 最后一个为部门层级 34 + // TODO @jason:是不是可以 | 分隔 deptId 数组,和 level;这样后续可以加更多的参数。
  35 + // 参数格式: , 分割。前面的部门编号,可以为多个。最后一个为部门层级
35 List<Long> params = StrUtils.splitToLong(param, ","); 36 List<Long> params = StrUtils.splitToLong(param, ",");
36 List<List<Long>> splitList = CollUtil.split(params, params.size() - 1); 37 List<List<Long>> splitList = CollUtil.split(params, params.size() - 1);
37 Assert.isTrue(splitList.size() == 2, "参数格式不匹配"); 38 Assert.isTrue(splitList.size() == 2, "参数格式不匹配");
@@ -41,6 +42,7 @@ public class BpmTaskCandidateMultiLevelDeptLeaderStrategy extends BpmTaskCandida @@ -41,6 +42,7 @@ public class BpmTaskCandidateMultiLevelDeptLeaderStrategy extends BpmTaskCandida
41 42
42 @Override 43 @Override
43 public Set<Long> calculateUsers(DelegateExecution execution, String param) { 44 public Set<Long> calculateUsers(DelegateExecution execution, String param) {
  45 + // TODO @jason:是不是可以 | 分隔 deptId 数组,和 level;这样后续可以加更多的参数。
44 // 参数格式: ,分割。前面的部门Id. 可以为多个。 最后一个为部门层级 46 // 参数格式: ,分割。前面的部门Id. 可以为多个。 最后一个为部门层级
45 List<Long> params = StrUtils.splitToLong(param, ","); 47 List<Long> params = StrUtils.splitToLong(param, ",");
46 List<List<Long>> splitList = CollUtil.split(params, params.size() - 1); 48 List<List<Long>> splitList = CollUtil.split(params, params.size() - 1);
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateStartUserMultiLevelDeptLeaderStrategy.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateStartUserDeptLeaderMultiStrategy.java
@@ -15,7 +15,7 @@ import org.flowable.engine.runtime.ProcessInstance; @@ -15,7 +15,7 @@ import org.flowable.engine.runtime.ProcessInstance;
15 import org.springframework.context.annotation.Lazy; 15 import org.springframework.context.annotation.Lazy;
16 import org.springframework.stereotype.Component; 16 import org.springframework.stereotype.Component;
17 17
18 -import java.util.Collections; 18 +import java.util.HashSet;
19 import java.util.Set; 19 import java.util.Set;
20 20
21 import static cn.hutool.core.collection.ListUtil.toList; 21 import static cn.hutool.core.collection.ListUtil.toList;
@@ -26,7 +26,7 @@ import static cn.hutool.core.collection.ListUtil.toList; @@ -26,7 +26,7 @@ import static cn.hutool.core.collection.ListUtil.toList;
26 * @author jason 26 * @author jason
27 */ 27 */
28 @Component 28 @Component
29 -public class BpmTaskCandidateStartUserMultiLevelDeptLeaderStrategy extends BpmTaskCandidateAbstractDeptLeaderStrategy { 29 +public class BpmTaskCandidateStartUserDeptLeaderMultiStrategy extends BpmTaskCandidateAbstractDeptLeaderStrategy {
30 30
31 @Resource 31 @Resource
32 @Lazy 32 @Lazy
@@ -35,13 +35,13 @@ public class BpmTaskCandidateStartUserMultiLevelDeptLeaderStrategy extends BpmTa @@ -35,13 +35,13 @@ public class BpmTaskCandidateStartUserMultiLevelDeptLeaderStrategy extends BpmTa
35 @Resource 35 @Resource
36 private AdminUserApi adminUserApi; 36 private AdminUserApi adminUserApi;
37 37
38 - public BpmTaskCandidateStartUserMultiLevelDeptLeaderStrategy(DeptApi deptApi) { 38 + public BpmTaskCandidateStartUserDeptLeaderMultiStrategy(DeptApi deptApi) {
39 super(deptApi); 39 super(deptApi);
40 } 40 }
41 41
42 @Override 42 @Override
43 public BpmTaskCandidateStrategyEnum getStrategy() { 43 public BpmTaskCandidateStrategyEnum getStrategy() {
44 - return BpmTaskCandidateStrategyEnum.START_USER_MULTI_LEVEL_DEPT_LEADER; 44 + return BpmTaskCandidateStrategyEnum.START_USER_DEPT_LEADER_MULTI;
45 } 45 }
46 46
47 @Override 47 @Override
@@ -55,9 +55,10 @@ public class BpmTaskCandidateStartUserMultiLevelDeptLeaderStrategy extends BpmTa @@ -55,9 +55,10 @@ public class BpmTaskCandidateStartUserMultiLevelDeptLeaderStrategy extends BpmTa
55 // 获得流程发起人 55 // 获得流程发起人
56 ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId()); 56 ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
57 Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId()); 57 Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
  58 + // 获取发起人的 multi 部门负责人
58 DeptRespDTO dept = getStartUserDept(startUserId); 59 DeptRespDTO dept = getStartUserDept(startUserId);
59 if (dept == null) { 60 if (dept == null) {
60 - return Collections.emptySet(); 61 + return new HashSet<>();
61 } 62 }
62 return getMultiLevelDeptLeaderIds(toList(dept.getId()), Integer.valueOf(param)); // 参数是部门的层级 63 return getMultiLevelDeptLeaderIds(toList(dept.getId()), Integer.valueOf(param)); // 参数是部门的层级
63 } 64 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateStartUserDeptLeaderStrategy.java
@@ -15,10 +15,10 @@ import org.flowable.engine.runtime.ProcessInstance; @@ -15,10 +15,10 @@ import org.flowable.engine.runtime.ProcessInstance;
15 import org.springframework.context.annotation.Lazy; 15 import org.springframework.context.annotation.Lazy;
16 import org.springframework.stereotype.Component; 16 import org.springframework.stereotype.Component;
17 17
  18 +import java.util.HashSet;
18 import java.util.Set; 19 import java.util.Set;
19 20
20 import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; 21 import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
21 -import static java.util.Collections.emptySet;  
22 22
23 /** 23 /**
24 * 发起人的部门负责人, 可以是上级部门负责人 {@link BpmTaskCandidateStrategy} 实现类 24 * 发起人的部门负责人, 可以是上级部门负责人 {@link BpmTaskCandidateStrategy} 实现类
@@ -27,11 +27,14 @@ import static java.util.Collections.emptySet; @@ -27,11 +27,14 @@ import static java.util.Collections.emptySet;
27 */ 27 */
28 @Component 28 @Component
29 public class BpmTaskCandidateStartUserDeptLeaderStrategy extends BpmTaskCandidateAbstractDeptLeaderStrategy { 29 public class BpmTaskCandidateStartUserDeptLeaderStrategy extends BpmTaskCandidateAbstractDeptLeaderStrategy {
  30 +
30 @Resource 31 @Resource
31 - @Lazy 32 + @Lazy // 避免循环依赖
32 private BpmProcessInstanceService processInstanceService; 33 private BpmProcessInstanceService processInstanceService;
  34 +
33 @Resource 35 @Resource
34 private AdminUserApi adminUserApi; 36 private AdminUserApi adminUserApi;
  37 +
35 @Override 38 @Override
36 public BpmTaskCandidateStrategyEnum getStrategy() { 39 public BpmTaskCandidateStrategyEnum getStrategy() {
37 return BpmTaskCandidateStrategyEnum.START_USER_DEPT_LEADER; 40 return BpmTaskCandidateStrategyEnum.START_USER_DEPT_LEADER;
@@ -52,10 +55,13 @@ public class BpmTaskCandidateStartUserDeptLeaderStrategy extends BpmTaskCandidat @@ -52,10 +55,13 @@ public class BpmTaskCandidateStartUserDeptLeaderStrategy extends BpmTaskCandidat
52 // 获得流程发起人 55 // 获得流程发起人
53 ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId()); 56 ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
54 Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId()); 57 Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
55 - 58 + // 获取发起人的部门负责人
56 DeptRespDTO dept = getStartUserDept(startUserId); 59 DeptRespDTO dept = getStartUserDept(startUserId);
  60 + if (dept == null) {
  61 + return new HashSet<>();
  62 + }
57 Long deptLeaderId = getAssignLevelDeptLeaderId(dept, Integer.valueOf(param)); // 参数是部门的层级 63 Long deptLeaderId = getAssignLevelDeptLeaderId(dept, Integer.valueOf(param)); // 参数是部门的层级
58 - return deptLeaderId != null ? asSet(deptLeaderId) : emptySet(); 64 + return deptLeaderId != null ? asSet(deptLeaderId) : new HashSet<>();
59 } 65 }
60 66
61 /** 67 /**
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmTaskCandidateStrategyEnum.java
@@ -21,13 +21,13 @@ public enum BpmTaskCandidateStrategyEnum implements IntArrayValuable { @@ -21,13 +21,13 @@ public enum BpmTaskCandidateStrategyEnum implements IntArrayValuable {
21 ROLE(10, "角色"), 21 ROLE(10, "角色"),
22 DEPT_MEMBER(20, "部门的成员"), // 包括负责人 22 DEPT_MEMBER(20, "部门的成员"), // 包括负责人
23 DEPT_LEADER(21, "部门的负责人"), 23 DEPT_LEADER(21, "部门的负责人"),
24 - MULTI_LEVEL_DEPT_LEADER(23, "连续多级部门的负责人"), 24 + MULTI_DEPT_LEADER_MULTI(23, "连续多级部门的负责人"),
25 POST(22, "岗位"), 25 POST(22, "岗位"),
26 USER(30, "用户"), 26 USER(30, "用户"),
27 START_USER_SELECT(35, "发起人自选"), // 申请人自己,可在提交申请时选择此节点的审批人 27 START_USER_SELECT(35, "发起人自选"), // 申请人自己,可在提交申请时选择此节点的审批人
28 START_USER(36, "发起人自己"), // 申请人自己, 一般紧挨开始节点,常用于发起人信息审核场景 28 START_USER(36, "发起人自己"), // 申请人自己, 一般紧挨开始节点,常用于发起人信息审核场景
29 - START_USER_DEPT_LEADER(37, "发起人部门负责人"), // 可以是发起人上级部门负责人  
30 - START_USER_MULTI_LEVEL_DEPT_LEADER(38, "发起人连续多级部门的负责人"), 29 + START_USER_DEPT_LEADER(37, "发起人部门负责人"),
  30 + START_USER_DEPT_LEADER_MULTI(38, "发起人连续多级部门的负责人"),
31 USER_GROUP(40, "用户组"), 31 USER_GROUP(40, "用户组"),
32 EXPRESSION(60, "流程表达式"), // 表达式 ExpressionManager 32 EXPRESSION(60, "流程表达式"), // 表达式 ExpressionManager
33 ASSIGN_EMPTY(1, "审批人为空"), 33 ASSIGN_EMPTY(1, "审批人为空"),