Commit e21c262bd7e3ed687b5aa1f640ecdec7066dd352
1 parent
5ae1d0ab
refactor: 重构查找候选人的逻辑
Showing
12 changed files
with
797 additions
and
0 deletions
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/candidate/vo/BpmTaskCandidateVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleBaseVO; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotNull; | ||
| 8 | +import java.util.Set; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 流程任务分配规则 Base VO,提供给添加、修改、详细的子 VO 使用 | ||
| 12 | + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | ||
| 13 | + * | ||
| 14 | + * @see BpmTaskAssignRuleBaseVO | ||
| 15 | + */ | ||
| 16 | +@Data | ||
| 17 | +public class BpmTaskCandidateVO { | ||
| 18 | + | ||
| 19 | + @Schema(description = "规则类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "bpm_task_assign_rule_type") | ||
| 20 | + @NotNull(message = "规则类型不能为空") | ||
| 21 | + private Integer type; | ||
| 22 | + | ||
| 23 | + @Schema(description = "规则值数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3") | ||
| 24 | + @NotNull(message = "规则值数组不能为空") | ||
| 25 | + private Set<Long> options; | ||
| 26 | + | ||
| 27 | +} |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmCandidateProcessorConfiguration.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.framework.bpm.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; | ||
| 4 | +import cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor.*; | ||
| 5 | +import org.springframework.beans.factory.ObjectProvider; | ||
| 6 | +import org.springframework.context.annotation.Bean; | ||
| 7 | +import org.springframework.context.annotation.Configuration; | ||
| 8 | + | ||
| 9 | +import java.util.List; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * BPM 通用的 Configuration 配置类,提供给 Activiti 和 Flowable | ||
| 13 | + * @author kyle | ||
| 14 | + */ | ||
| 15 | +@Configuration(proxyBeanMethods = false) | ||
| 16 | +public class BpmCandidateProcessorConfiguration { | ||
| 17 | + @Bean | ||
| 18 | + public BpmCandidateAdminUserApiSourceInfoProcessor bpmCandidateAdminUserApiSourceInfoProcessor() { | ||
| 19 | + return new BpmCandidateAdminUserApiSourceInfoProcessor(); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + @Bean | ||
| 23 | + public BpmCandidateDeptApiSourceInfoProcessor bpmCandidateDeptApiSourceInfoProcessor() { | ||
| 24 | + return new BpmCandidateDeptApiSourceInfoProcessor(); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + @Bean | ||
| 28 | + public BpmCandidatePostApiSourceInfoProcessor bpmCandidatePostApiSourceInfoProcessor() { | ||
| 29 | + return new BpmCandidatePostApiSourceInfoProcessor(); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + @Bean | ||
| 33 | + public BpmCandidateRoleApiSourceInfoProcessor bpmCandidateRoleApiSourceInfoProcessor() { | ||
| 34 | + return new BpmCandidateRoleApiSourceInfoProcessor(); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + @Bean | ||
| 38 | + public BpmCandidateUserGroupApiSourceInfoProcessor bpmCandidateUserGroupApiSourceInfoProcessor() { | ||
| 39 | + return new BpmCandidateUserGroupApiSourceInfoProcessor(); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * 可以自己定制脚本,然后通过这里设置到处理器里面去 | ||
| 44 | + * @param scriptsOp | ||
| 45 | + * @return | ||
| 46 | + */ | ||
| 47 | + @Bean | ||
| 48 | + public BpmCandidateScriptApiSourceInfoProcessor bpmCandidateScriptApiSourceInfoProcessor(ObjectProvider<BpmTaskAssignScript> scriptsOp) { | ||
| 49 | + BpmCandidateScriptApiSourceInfoProcessor bpmCandidateScriptApiSourceInfoProcessor = new BpmCandidateScriptApiSourceInfoProcessor(); | ||
| 50 | + bpmCandidateScriptApiSourceInfoProcessor.setScripts(scriptsOp); | ||
| 51 | + return bpmCandidateScriptApiSourceInfoProcessor; | ||
| 52 | + } | ||
| 53 | +} |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateVO; | ||
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleBaseVO; | ||
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 6 | +import lombok.AllArgsConstructor; | ||
| 7 | +import lombok.Data; | ||
| 8 | +import lombok.NoArgsConstructor; | ||
| 9 | +import org.flowable.engine.delegate.DelegateExecution; | ||
| 10 | + | ||
| 11 | +import java.util.HashSet; | ||
| 12 | +import java.util.Set; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * 获取候选人信息 | ||
| 16 | + */ | ||
| 17 | +@AllArgsConstructor | ||
| 18 | +@NoArgsConstructor | ||
| 19 | +@Data | ||
| 20 | +public class BpmCandidateSourceInfo { | ||
| 21 | + | ||
| 22 | + @Schema(description = "流程id") | ||
| 23 | + private String processInstanceId; | ||
| 24 | + | ||
| 25 | + @Schema(description = "当前任务ID") | ||
| 26 | + private String taskId; | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * 通过这些规则,生成最终需要生成的用户 | ||
| 30 | + */ | ||
| 31 | + @Schema(description = "当前任务预选规则") | ||
| 32 | + private Set<BpmTaskCandidateVO> rules; | ||
| 33 | + | ||
| 34 | + @Schema(description = "源执行流程") | ||
| 35 | + private DelegateExecution execution; | ||
| 36 | + | ||
| 37 | + public void addRule(BpmTaskCandidateVO vo) { | ||
| 38 | + assert vo != null; | ||
| 39 | + if (rules == null) { | ||
| 40 | + rules = new HashSet<>(); | ||
| 41 | + } | ||
| 42 | + rules.add(vo); | ||
| 43 | + } | ||
| 44 | +} | ||
| 0 | \ No newline at end of file | 45 | \ No newline at end of file |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateVO; | ||
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | ||
| 6 | + | ||
| 7 | +import java.util.Collections; | ||
| 8 | +import java.util.HashSet; | ||
| 9 | +import java.util.Set; | ||
| 10 | + | ||
| 11 | +public interface BpmCandidateSourceInfoProcessor { | ||
| 12 | + /** | ||
| 13 | + * 获取该处理器支持的类型 | ||
| 14 | + * 来自 {@link BpmTaskAssignRuleTypeEnum} | ||
| 15 | + * | ||
| 16 | + * @return | ||
| 17 | + */ | ||
| 18 | + Set<Integer> getSupportedTypes(); | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 对规则和人员做校验 | ||
| 22 | + * | ||
| 23 | + * @param type 规则 | ||
| 24 | + * @param options 人员id | ||
| 25 | + */ | ||
| 26 | + void validRuleOptions(Integer type, Set<Long> options); | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * 默认的处理 | ||
| 30 | + * 如果想去操作所有的规则,则可以覆盖此方法 | ||
| 31 | + * | ||
| 32 | + * @param request | ||
| 33 | + * @param chain | ||
| 34 | + * @return 必须包含的是用户ID,而不是其他的ID | ||
| 35 | + * @throws Exception | ||
| 36 | + */ | ||
| 37 | + default Set<Long> process(BpmCandidateSourceInfo request, BpmCandidateSourceInfoProcessorChain chain) throws Exception { | ||
| 38 | + Set<BpmTaskCandidateVO> rules = request.getRules(); | ||
| 39 | + Set<Long> results = new HashSet<>(); | ||
| 40 | + for (BpmTaskCandidateVO rule : rules) { | ||
| 41 | + // 每个处理器都有机会处理自己支持的事件 | ||
| 42 | + if (CollUtil.contains(getSupportedTypes(), rule.getType())) { | ||
| 43 | + results.addAll(doProcess(request, rule)); | ||
| 44 | + } | ||
| 45 | + } | ||
| 46 | + return results; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + default Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateVO rule) { | ||
| 50 | + return Collections.emptySet(); | ||
| 51 | + } | ||
| 52 | +} | ||
| 0 | \ No newline at end of file | 53 | \ No newline at end of file |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessorChain.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 5 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateVO; | ||
| 6 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 7 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 8 | +import org.flowable.engine.delegate.DelegateExecution; | ||
| 9 | +import org.springframework.beans.factory.ObjectProvider; | ||
| 10 | +import org.springframework.stereotype.Service; | ||
| 11 | + | ||
| 12 | +import javax.annotation.Resource; | ||
| 13 | +import java.util.*; | ||
| 14 | +import java.util.stream.Collectors; | ||
| 15 | + | ||
| 16 | +@Service | ||
| 17 | +public class BpmCandidateSourceInfoProcessorChain { | ||
| 18 | + | ||
| 19 | + // 保存处理节点 | ||
| 20 | + | ||
| 21 | + private List<BpmCandidateSourceInfoProcessor> processorList; | ||
| 22 | + @Resource | ||
| 23 | + private AdminUserApi adminUserApi; | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 可添加其他处理器 | ||
| 27 | + * | ||
| 28 | + * @param processorOp | ||
| 29 | + * @return | ||
| 30 | + */ | ||
| 31 | + @Resource | ||
| 32 | + // 动态扩展处理节点 | ||
| 33 | + public BpmCandidateSourceInfoProcessorChain addProcessor(ObjectProvider<BpmCandidateSourceInfoProcessor> processorOp) { | ||
| 34 | + List<BpmCandidateSourceInfoProcessor> processor = processorOp.orderedStream().collect(Collectors.toList()); | ||
| 35 | + if (null == processorList) { | ||
| 36 | + processorList = new ArrayList<>(processor.size()); | ||
| 37 | + } | ||
| 38 | + processorList.addAll(processor); | ||
| 39 | + return this; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + // 获取处理器处理 | ||
| 43 | + public Set<Long> process(BpmCandidateSourceInfo sourceInfo) throws Exception { | ||
| 44 | + // Verify our parameters | ||
| 45 | + if (sourceInfo == null) { | ||
| 46 | + throw new IllegalArgumentException(); | ||
| 47 | + } | ||
| 48 | + for (BpmCandidateSourceInfoProcessor processor : processorList) { | ||
| 49 | + try { | ||
| 50 | + for (BpmTaskCandidateVO vo : sourceInfo.getRules()) { | ||
| 51 | + processor.validRuleOptions(vo.getType(), vo.getOptions()); | ||
| 52 | + } | ||
| 53 | + } catch (Exception e) { | ||
| 54 | + e.printStackTrace(); | ||
| 55 | + throw e; | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | + Set<Long> saveResult = Collections.emptySet(); | ||
| 59 | + Exception saveException = null; | ||
| 60 | + for (BpmCandidateSourceInfoProcessor processor : processorList) { | ||
| 61 | + try { | ||
| 62 | + saveResult = processor.process(sourceInfo, this); | ||
| 63 | + if (CollUtil.isNotEmpty(saveResult)) { | ||
| 64 | + removeDisableUsers(saveResult); | ||
| 65 | + break; | ||
| 66 | + } | ||
| 67 | + } catch (Exception e) { | ||
| 68 | + saveException = e; | ||
| 69 | + break; | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | + // Return the exception or result state from the last execute() | ||
| 73 | + if ((saveException != null)) { | ||
| 74 | + throw saveException; | ||
| 75 | + } else { | ||
| 76 | + return (saveResult); | ||
| 77 | + } | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution, BpmCandidateSourceInfo sourceInfo) { | ||
| 81 | + sourceInfo.setExecution(execution); | ||
| 82 | + Set<Long> results = Collections.emptySet(); | ||
| 83 | + try { | ||
| 84 | + results = process(sourceInfo); | ||
| 85 | + } catch (Exception e) { | ||
| 86 | + e.printStackTrace(); | ||
| 87 | + } | ||
| 88 | + return results; | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + /** | ||
| 92 | + * 移除禁用用户 | ||
| 93 | + * @param assigneeUserIds | ||
| 94 | + */ | ||
| 95 | + public void removeDisableUsers(Set<Long> assigneeUserIds) { | ||
| 96 | + if (CollUtil.isEmpty(assigneeUserIds)) { | ||
| 97 | + return; | ||
| 98 | + } | ||
| 99 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assigneeUserIds); | ||
| 100 | + assigneeUserIds.removeIf(id -> { | ||
| 101 | + AdminUserRespDTO user = userMap.get(id); | ||
| 102 | + return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus()); | ||
| 103 | + }); | ||
| 104 | + } | ||
| 105 | +} | ||
| 0 | \ No newline at end of file | 106 | \ No newline at end of file |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateAdminUserApiSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | ||
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateVO; | ||
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | ||
| 6 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | ||
| 7 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor; | ||
| 8 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 9 | + | ||
| 10 | +import javax.annotation.Resource; | ||
| 11 | +import java.util.Set; | ||
| 12 | + | ||
| 13 | +public class BpmCandidateAdminUserApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor { | ||
| 14 | + @Resource | ||
| 15 | + private AdminUserApi api; | ||
| 16 | + | ||
| 17 | + @Override | ||
| 18 | + public Set<Integer> getSupportedTypes() { | ||
| 19 | + return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.USER.getType()); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public void validRuleOptions(Integer type, Set<Long> options) { | ||
| 24 | + api.validateUserList(options); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateVO rule) { | ||
| 29 | + return rule.getOptions(); | ||
| 30 | + } | ||
| 31 | +} | ||
| 0 | \ No newline at end of file | 32 | \ No newline at end of file |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateDeptApiSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | ||
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateVO; | ||
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | ||
| 6 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | ||
| 7 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor; | ||
| 8 | +import cn.iocoder.yudao.module.system.api.dept.DeptApi; | ||
| 9 | +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | ||
| 10 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 11 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 12 | + | ||
| 13 | +import javax.annotation.Resource; | ||
| 14 | +import java.util.Collections; | ||
| 15 | +import java.util.List; | ||
| 16 | +import java.util.Objects; | ||
| 17 | +import java.util.Set; | ||
| 18 | + | ||
| 19 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 20 | + | ||
| 21 | +public class BpmCandidateDeptApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor { | ||
| 22 | + @Resource | ||
| 23 | + private DeptApi api; | ||
| 24 | + @Resource | ||
| 25 | + private AdminUserApi adminUserApi; | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public Set<Integer> getSupportedTypes() { | ||
| 29 | + return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), | ||
| 30 | + BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType()); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + @Override | ||
| 34 | + public void validRuleOptions(Integer type, Set<Long> options) { | ||
| 35 | + api.validateDeptList(options); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @Override | ||
| 39 | + public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateVO rule) { | ||
| 40 | + if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), rule.getType())) { | ||
| 41 | + List<AdminUserRespDTO> users = adminUserApi.getUserListByDeptIds(rule.getOptions()); | ||
| 42 | + return convertSet(users, AdminUserRespDTO::getId); | ||
| 43 | + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), rule.getType())) { | ||
| 44 | + List<DeptRespDTO> depts = api.getDeptList(rule.getOptions()); | ||
| 45 | + return convertSet(depts, DeptRespDTO::getLeaderUserId); | ||
| 46 | + } | ||
| 47 | + return Collections.emptySet(); | ||
| 48 | + } | ||
| 49 | +} | ||
| 0 | \ No newline at end of file | 50 | \ No newline at end of file |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidatePostApiSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | ||
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateVO; | ||
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | ||
| 6 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | ||
| 7 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor; | ||
| 8 | +import cn.iocoder.yudao.module.system.api.dept.PostApi; | ||
| 9 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 10 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 11 | + | ||
| 12 | +import javax.annotation.Resource; | ||
| 13 | +import java.util.List; | ||
| 14 | +import java.util.Set; | ||
| 15 | + | ||
| 16 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 17 | + | ||
| 18 | +public class BpmCandidatePostApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor { | ||
| 19 | + @Resource | ||
| 20 | + private PostApi api; | ||
| 21 | + @Resource | ||
| 22 | + private AdminUserApi adminUserApi; | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + public Set<Integer> getSupportedTypes() { | ||
| 26 | + return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.POST.getType()); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + @Override | ||
| 30 | + public void validRuleOptions(Integer type, Set<Long> options) { | ||
| 31 | + api.validPostList(options); | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + @Override | ||
| 35 | + public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateVO rule) { | ||
| 36 | + List<AdminUserRespDTO> users = adminUserApi.getUserListByPostIds(rule.getOptions()); | ||
| 37 | + return convertSet(users, AdminUserRespDTO::getId); | ||
| 38 | + } | ||
| 39 | +} | ||
| 0 | \ No newline at end of file | 40 | \ No newline at end of file |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateRoleApiSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | ||
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateVO; | ||
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | ||
| 6 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | ||
| 7 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor; | ||
| 8 | +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; | ||
| 9 | +import cn.iocoder.yudao.module.system.api.permission.RoleApi; | ||
| 10 | + | ||
| 11 | +import javax.annotation.Resource; | ||
| 12 | +import java.util.Set; | ||
| 13 | + | ||
| 14 | +public class BpmCandidateRoleApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor { | ||
| 15 | + @Resource | ||
| 16 | + private RoleApi api; | ||
| 17 | + | ||
| 18 | + @Resource | ||
| 19 | + private PermissionApi permissionApi; | ||
| 20 | + | ||
| 21 | + @Override | ||
| 22 | + public Set<Integer> getSupportedTypes() { | ||
| 23 | + return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.ROLE.getType()); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + @Override | ||
| 27 | + public void validRuleOptions(Integer type, Set<Long> options) { | ||
| 28 | + api.validRoleList(options); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + @Override | ||
| 32 | + public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateVO rule) { | ||
| 33 | + return permissionApi.getUserRoleIdListByRoleIds(rule.getOptions()); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | +} | ||
| 0 | \ No newline at end of file | 37 | \ No newline at end of file |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateScriptApiSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | ||
| 6 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateVO; | ||
| 7 | +import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants; | ||
| 8 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | ||
| 9 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; | ||
| 10 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | ||
| 11 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor; | ||
| 12 | +import cn.iocoder.yudao.module.system.api.dict.DictDataApi; | ||
| 13 | +import org.flowable.engine.delegate.DelegateExecution; | ||
| 14 | +import org.springframework.beans.factory.ObjectProvider; | ||
| 15 | + | ||
| 16 | +import javax.annotation.Resource; | ||
| 17 | +import java.util.*; | ||
| 18 | +import java.util.stream.Collectors; | ||
| 19 | + | ||
| 20 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 21 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 22 | +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS; | ||
| 23 | + | ||
| 24 | +public class BpmCandidateScriptApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor { | ||
| 25 | + @Resource | ||
| 26 | + private DictDataApi dictDataApi; | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * 任务分配脚本 | ||
| 30 | + */ | ||
| 31 | + private Map<Long, BpmTaskAssignScript> scriptMap = Collections.emptyMap(); | ||
| 32 | + | ||
| 33 | + public void setScripts(ObjectProvider<BpmTaskAssignScript> scriptsOp) { | ||
| 34 | + List<BpmTaskAssignScript> scripts = scriptsOp.orderedStream().collect(Collectors.toList()); | ||
| 35 | + setScripts(scripts); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + public void setScripts(List<BpmTaskAssignScript> scripts) { | ||
| 39 | + this.scriptMap = convertMap(scripts, script -> script.getEnum().getId()); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + @Override | ||
| 43 | + public Set<Integer> getSupportedTypes() { | ||
| 44 | + return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.SCRIPT.getType()); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + @Override | ||
| 48 | + public void validRuleOptions(Integer type, Set<Long> options) { | ||
| 49 | + dictDataApi.validateDictDataList(DictTypeConstants.TASK_ASSIGN_SCRIPT, | ||
| 50 | + CollectionUtils.convertSet(options, String::valueOf)); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + @Override | ||
| 54 | + public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateVO rule) { | ||
| 55 | + return calculateTaskCandidateUsersByScript(request.getExecution(), rule.getOptions()); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + private Set<Long> calculateTaskCandidateUsersByScript(DelegateExecution execution, Set<Long> options) { | ||
| 59 | + // 获得对应的脚本 | ||
| 60 | + List<BpmTaskAssignScript> scripts = new ArrayList<>(options.size()); | ||
| 61 | + options.forEach(id -> { | ||
| 62 | + BpmTaskAssignScript script = scriptMap.get(id); | ||
| 63 | + if (script == null) { | ||
| 64 | + throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, id); | ||
| 65 | + } | ||
| 66 | + scripts.add(script); | ||
| 67 | + }); | ||
| 68 | + // 逐个计算任务 | ||
| 69 | + Set<Long> userIds = new HashSet<>(); | ||
| 70 | + scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(execution))); | ||
| 71 | + return userIds; | ||
| 72 | + } | ||
| 73 | +} | ||
| 0 | \ No newline at end of file | 74 | \ No newline at end of file |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateUserGroupApiSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | ||
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateVO; | ||
| 5 | +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; | ||
| 6 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | ||
| 7 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | ||
| 8 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor; | ||
| 9 | +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; | ||
| 10 | + | ||
| 11 | +import javax.annotation.Resource; | ||
| 12 | +import java.util.HashSet; | ||
| 13 | +import java.util.List; | ||
| 14 | +import java.util.Set; | ||
| 15 | + | ||
| 16 | +public class BpmCandidateUserGroupApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor { | ||
| 17 | + @Resource | ||
| 18 | + private BpmUserGroupService api; | ||
| 19 | + @Resource | ||
| 20 | + private BpmUserGroupService userGroupService; | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public Set<Integer> getSupportedTypes() { | ||
| 24 | + return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType()); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public void validRuleOptions(Integer type, Set<Long> options) { | ||
| 29 | + api.validUserGroups(options); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + @Override | ||
| 33 | + public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateVO rule) { | ||
| 34 | + List<BpmUserGroupDO> userGroups = userGroupService.getUserGroupList(rule.getOptions()); | ||
| 35 | + Set<Long> userIds = new HashSet<>(); | ||
| 36 | + userGroups.forEach(group -> userIds.addAll(group.getMemberUserIds())); | ||
| 37 | + return userIds; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | +} | ||
| 0 | \ No newline at end of file | 41 | \ No newline at end of file |
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessorChainTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate; | ||
| 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.controller.admin.candidate.vo.BpmTaskCandidateVO; | ||
| 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.enums.definition.BpmTaskAssignRuleTypeEnum; | ||
| 11 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; | ||
| 12 | +import cn.iocoder.yudao.module.bpm.framework.bpm.config.BpmCandidateProcessorConfiguration; | ||
| 13 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; | ||
| 14 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl.BpmTaskAssignLeaderX1Script; | ||
| 15 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl.BpmTaskAssignLeaderX2Script; | ||
| 16 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | ||
| 17 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessorChain; | ||
| 18 | +import cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor.BpmCandidateScriptApiSourceInfoProcessor; | ||
| 19 | +import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleServiceImpl; | ||
| 20 | +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; | ||
| 21 | +import cn.iocoder.yudao.module.system.api.dept.DeptApi; | ||
| 22 | +import cn.iocoder.yudao.module.system.api.dept.PostApi; | ||
| 23 | +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | ||
| 24 | +import cn.iocoder.yudao.module.system.api.dict.DictDataApi; | ||
| 25 | +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; | ||
| 26 | +import cn.iocoder.yudao.module.system.api.permission.RoleApi; | ||
| 27 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 28 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 29 | +import org.flowable.engine.delegate.DelegateExecution; | ||
| 30 | +import org.junit.jupiter.api.Test; | ||
| 31 | +import org.springframework.beans.factory.ObjectProvider; | ||
| 32 | +import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 33 | +import org.springframework.context.annotation.Import; | ||
| 34 | + | ||
| 35 | +import javax.annotation.Resource; | ||
| 36 | +import java.util.Arrays; | ||
| 37 | +import java.util.List; | ||
| 38 | +import java.util.Map; | ||
| 39 | +import java.util.Set; | ||
| 40 | + | ||
| 41 | +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; | ||
| 42 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | ||
| 43 | +import static java.util.Collections.singleton; | ||
| 44 | +import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| 45 | +import static org.mockito.ArgumentMatchers.eq; | ||
| 46 | +import static org.mockito.Mockito.when; | ||
| 47 | + | ||
| 48 | +@Import({BpmCandidateSourceInfoProcessorChain.class, BpmCandidateProcessorConfiguration.class, | ||
| 49 | + BpmCandidateScriptApiSourceInfoProcessor.class, BpmTaskAssignLeaderX1Script.class, | ||
| 50 | + BpmTaskAssignLeaderX2Script.class}) | ||
| 51 | +public class BpmCandidateSourceInfoProcessorChainTest extends BaseDbUnitTest { | ||
| 52 | + @Resource | ||
| 53 | + private BpmCandidateSourceInfoProcessorChain processorChain; | ||
| 54 | + | ||
| 55 | + @MockBean | ||
| 56 | + private BpmUserGroupService userGroupService; | ||
| 57 | + @MockBean | ||
| 58 | + private DeptApi deptApi; | ||
| 59 | + @MockBean | ||
| 60 | + private AdminUserApi adminUserApi; | ||
| 61 | + @MockBean | ||
| 62 | + private PermissionApi permissionApi; | ||
| 63 | + @MockBean | ||
| 64 | + private RoleApi roleApi; | ||
| 65 | + @MockBean | ||
| 66 | + private PostApi postApi; | ||
| 67 | + @MockBean | ||
| 68 | + private DictDataApi dictDataApi; | ||
| 69 | + @Resource | ||
| 70 | + private BpmCandidateScriptApiSourceInfoProcessor bpmCandidateScriptApiSourceInfoProcessor; | ||
| 71 | + | ||
| 72 | + @Test | ||
| 73 | + public void testCalculateTaskCandidateUsers_Role() { | ||
| 74 | + // 准备参数 | ||
| 75 | + BpmTaskCandidateVO rule = new BpmTaskCandidateVO().setOptions(asSet(1L, 2L)) | ||
| 76 | + .setType(BpmTaskAssignRuleTypeEnum.ROLE.getType()); | ||
| 77 | + // mock 方法 | ||
| 78 | + when(permissionApi.getUserRoleIdListByRoleIds(eq(rule.getOptions()))) | ||
| 79 | + .thenReturn(asSet(11L, 22L)); | ||
| 80 | + mockGetUserMap(asSet(11L, 22L)); | ||
| 81 | + | ||
| 82 | + // 调用 | ||
| 83 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | ||
| 84 | + sourceInfo.addRule(rule); | ||
| 85 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | ||
| 86 | + // 断言 | ||
| 87 | + assertEquals(asSet(11L, 22L), results); | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + @Test | ||
| 91 | + public void testCalculateTaskCandidateUsers_DeptMember() { | ||
| 92 | + // 准备参数 | ||
| 93 | + BpmTaskCandidateVO rule = new BpmTaskCandidateVO().setOptions(asSet(1L, 2L)) | ||
| 94 | + .setType(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType()); | ||
| 95 | + // mock 方法 | ||
| 96 | + List<AdminUserRespDTO> users = CollectionUtils.convertList(asSet(11L, 22L), | ||
| 97 | + id -> new AdminUserRespDTO().setId(id)); | ||
| 98 | + when(adminUserApi.getUserListByDeptIds(eq(rule.getOptions()))).thenReturn(users); | ||
| 99 | + mockGetUserMap(asSet(11L, 22L)); | ||
| 100 | + | ||
| 101 | + // 调用 | ||
| 102 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | ||
| 103 | + sourceInfo.addRule(rule); | ||
| 104 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | ||
| 105 | + // 断言 | ||
| 106 | + assertEquals(asSet(11L, 22L), results); | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + @Test | ||
| 110 | + public void testCalculateTaskCandidateUsers_DeptLeader() { | ||
| 111 | + // 准备参数 | ||
| 112 | + BpmTaskCandidateVO rule = new BpmTaskCandidateVO().setOptions(asSet(1L, 2L)) | ||
| 113 | + .setType(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType()); | ||
| 114 | + // mock 方法 | ||
| 115 | + DeptRespDTO dept1 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(11L)); | ||
| 116 | + DeptRespDTO dept2 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(22L)); | ||
| 117 | + when(deptApi.getDeptList(eq(rule.getOptions()))).thenReturn(Arrays.asList(dept1, dept2)); | ||
| 118 | + mockGetUserMap(asSet(11L, 22L)); | ||
| 119 | + | ||
| 120 | + // 调用 | ||
| 121 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | ||
| 122 | + sourceInfo.addRule(rule); | ||
| 123 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | ||
| 124 | + // 断言 | ||
| 125 | + assertEquals(asSet(11L, 22L), results); | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + @Test | ||
| 129 | + public void testCalculateTaskCandidateUsers_Post() { | ||
| 130 | + // 准备参数 | ||
| 131 | + BpmTaskCandidateVO rule = new BpmTaskCandidateVO().setOptions(asSet(1L, 2L)) | ||
| 132 | + .setType(BpmTaskAssignRuleTypeEnum.POST.getType()); | ||
| 133 | + // mock 方法 | ||
| 134 | + List<AdminUserRespDTO> users = CollectionUtils.convertList(asSet(11L, 22L), | ||
| 135 | + id -> new AdminUserRespDTO().setId(id)); | ||
| 136 | + when(adminUserApi.getUserListByPostIds(eq(rule.getOptions()))).thenReturn(users); | ||
| 137 | + mockGetUserMap(asSet(11L, 22L)); | ||
| 138 | + | ||
| 139 | + // 调用 | ||
| 140 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | ||
| 141 | + sourceInfo.addRule(rule); | ||
| 142 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | ||
| 143 | + // 断言 | ||
| 144 | + assertEquals(asSet(11L, 22L), results); | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + @Test | ||
| 148 | + public void testCalculateTaskCandidateUsers_User() { | ||
| 149 | + // 准备参数 | ||
| 150 | + BpmTaskCandidateVO rule = new BpmTaskCandidateVO().setOptions(asSet(1L, 2L)) | ||
| 151 | + .setType(BpmTaskAssignRuleTypeEnum.USER.getType()); | ||
| 152 | + // mock 方法 | ||
| 153 | + mockGetUserMap(asSet(1L, 2L)); | ||
| 154 | + | ||
| 155 | + // 调用 | ||
| 156 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | ||
| 157 | + sourceInfo.addRule(rule); | ||
| 158 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | ||
| 159 | + // 断言 | ||
| 160 | + assertEquals(asSet(1L, 2L), results); | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + @Test | ||
| 164 | + public void testCalculateTaskCandidateUsers_UserGroup() { | ||
| 165 | + // 准备参数 | ||
| 166 | + BpmTaskCandidateVO rule = new BpmTaskCandidateVO().setOptions(asSet(1L, 2L)) | ||
| 167 | + .setType(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType()); | ||
| 168 | + // mock 方法 | ||
| 169 | + BpmUserGroupDO userGroup1 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(11L, 12L))); | ||
| 170 | + BpmUserGroupDO userGroup2 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(21L, 22L))); | ||
| 171 | + when(userGroupService.getUserGroupList(eq(rule.getOptions()))).thenReturn(Arrays.asList(userGroup1, userGroup2)); | ||
| 172 | + mockGetUserMap(asSet(11L, 12L, 21L, 22L)); | ||
| 173 | + | ||
| 174 | + // 调用 | ||
| 175 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | ||
| 176 | + sourceInfo.addRule(rule); | ||
| 177 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | ||
| 178 | + // 断言 | ||
| 179 | + assertEquals(asSet(11L, 12L, 21L, 22L), results); | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + private void mockGetUserMap(Set<Long> assigneeUserIds) { | ||
| 183 | + Map<Long, AdminUserRespDTO> userMap = CollectionUtils.convertMap(assigneeUserIds, id -> id, | ||
| 184 | + id -> new AdminUserRespDTO().setId(id).setStatus(CommonStatusEnum.ENABLE.getStatus())); | ||
| 185 | + when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap); | ||
| 186 | + } | ||
| 187 | + | ||
| 188 | + @Test | ||
| 189 | + public void testCalculateTaskCandidateUsers_Script() { | ||
| 190 | + // 准备参数 | ||
| 191 | + BpmTaskCandidateVO rule = new BpmTaskCandidateVO().setOptions(asSet(20L, 21L)) | ||
| 192 | + .setType(BpmTaskAssignRuleTypeEnum.SCRIPT.getType()); | ||
| 193 | + // mock 方法 | ||
| 194 | + BpmTaskAssignScript script1 = new BpmTaskAssignScript() { | ||
| 195 | + | ||
| 196 | + @Override | ||
| 197 | + public Set<Long> calculateTaskCandidateUsers(DelegateExecution task) { | ||
| 198 | + return singleton(11L); | ||
| 199 | + } | ||
| 200 | + | ||
| 201 | + @Override | ||
| 202 | + public BpmTaskRuleScriptEnum getEnum() { | ||
| 203 | + return BpmTaskRuleScriptEnum.LEADER_X1; | ||
| 204 | + } | ||
| 205 | + }; | ||
| 206 | + BpmTaskAssignScript script2 = new BpmTaskAssignScript() { | ||
| 207 | + | ||
| 208 | + @Override | ||
| 209 | + public Set<Long> calculateTaskCandidateUsers(DelegateExecution task) { | ||
| 210 | + return singleton(22L); | ||
| 211 | + } | ||
| 212 | + | ||
| 213 | + @Override | ||
| 214 | + public BpmTaskRuleScriptEnum getEnum() { | ||
| 215 | + return BpmTaskRuleScriptEnum.LEADER_X2; | ||
| 216 | + } | ||
| 217 | + }; | ||
| 218 | + bpmCandidateScriptApiSourceInfoProcessor.setScripts(Arrays.asList(script1, script2)); | ||
| 219 | + mockGetUserMap(asSet(11L, 22L)); | ||
| 220 | + | ||
| 221 | + // 调用 | ||
| 222 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | ||
| 223 | + sourceInfo.addRule(rule); | ||
| 224 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | ||
| 225 | + // 断言 | ||
| 226 | + assertEquals(asSet(11L, 22L), results); | ||
| 227 | + } | ||
| 228 | + | ||
| 229 | + @Test | ||
| 230 | + public void testRemoveDisableUsers() { | ||
| 231 | + // 准备参数. 1L 可以找到;2L 是禁用的;3L 找不到 | ||
| 232 | + Set<Long> assigneeUserIds = asSet(1L, 2L, 3L); | ||
| 233 | + // mock 方法 | ||
| 234 | + AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L) | ||
| 235 | + .setStatus(CommonStatusEnum.ENABLE.getStatus())); | ||
| 236 | + AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L) | ||
| 237 | + .setStatus(CommonStatusEnum.DISABLE.getStatus())); | ||
| 238 | + Map<Long, AdminUserRespDTO> userMap = MapUtil.builder(user1.getId(), user1) | ||
| 239 | + .put(user2.getId(), user2).build(); | ||
| 240 | + when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap); | ||
| 241 | + | ||
| 242 | + // 调用 | ||
| 243 | + processorChain.removeDisableUsers(assigneeUserIds); | ||
| 244 | + // 断言 | ||
| 245 | + assertEquals(asSet(1L), assigneeUserIds); | ||
| 246 | + } | ||
| 247 | + | ||
| 248 | +} | ||
| 0 | \ No newline at end of file | 249 | \ No newline at end of file |