Commit 040a1bcfad61bb6083dd6dae2f869fed312f56b4
1 parent
e7815dd7
【代码评审】工作流:连续多级部门负责人的实现
Showing
5 changed files
with
44 additions
and
39 deletions
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, "审批人为空"), |