Commit f5f73adcbbe3a5b8c0636c453512d05232d41c26

Authored by YunaiV
1 parent 797fddfb

BPM:重构流程分配人的实现,通过 BpmTaskCandidateStrategy 策略模式

Showing 53 changed files with 940 additions and 1557 deletions
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 <module>yudao-module-system</module> 16 <module>yudao-module-system</module>
17 <module>yudao-module-infra</module> 17 <module>yudao-module-infra</module>
18 <!-- <module>yudao-module-member</module>--> 18 <!-- <module>yudao-module-member</module>-->
19 -<!-- <module>yudao-module-bpm</module>--> 19 + <module>yudao-module-bpm</module>
20 <!-- <module>yudao-module-report</module>--> 20 <!-- <module>yudao-module-report</module>-->
21 <!-- <module>yudao-module-mp</module>--> 21 <!-- <module>yudao-module-mp</module>-->
22 <!-- <module>yudao-module-pay</module>--> 22 <!-- <module>yudao-module-pay</module>-->
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java
1 package cn.iocoder.yudao.framework.common.util.string; 1 package cn.iocoder.yudao.framework.common.util.string;
2 2
  3 +import cn.hutool.core.text.StrPool;
3 import cn.hutool.core.util.ArrayUtil; 4 import cn.hutool.core.util.ArrayUtil;
4 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
5 6
@@ -46,6 +47,10 @@ public class StrUtils { @@ -46,6 +47,10 @@ public class StrUtils {
46 return Arrays.stream(longs).boxed().collect(Collectors.toList()); 47 return Arrays.stream(longs).boxed().collect(Collectors.toList());
47 } 48 }
48 49
  50 + public static Set<Long> splitToLongSet(String value) {
  51 + return splitToLongSet(value, StrPool.COMMA);
  52 + }
  53 +
49 public static Set<Long> splitToLongSet(String value, CharSequence separator) { 54 public static Set<Long> splitToLongSet(String value, CharSequence separator) {
50 long[] longs = StrUtil.splitToLong(value, separator); 55 long[] longs = StrUtil.splitToLong(value, separator);
51 return Arrays.stream(longs).boxed().collect(Collectors.toSet()); 56 return Arrays.stream(longs).boxed().collect(Collectors.toSet());
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
@@ -26,7 +26,7 @@ public interface ErrorCodeConstants { @@ -26,7 +26,7 @@ public interface ErrorCodeConstants {
26 ErrorCode MODEL_NOT_EXISTS = new ErrorCode(1_009_002_001, "流程模型不存在"); 26 ErrorCode MODEL_NOT_EXISTS = new ErrorCode(1_009_002_001, "流程模型不存在");
27 ErrorCode MODEL_KEY_VALID = new ErrorCode(1_009_002_002, "流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!"); 27 ErrorCode MODEL_KEY_VALID = new ErrorCode(1_009_002_002, "流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!");
28 ErrorCode MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG = new ErrorCode(1_009_002_003, "部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置"); 28 ErrorCode MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG = new ErrorCode(1_009_002_003, "部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置");
29 - ErrorCode MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG = new ErrorCode(1_009_002_004, "部署流程失败," + 29 + ErrorCode MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG = new ErrorCode(1_009_002_004, "部署流程失败," +
30 "原因:用户任务({})未配置审批人,请点击【流程设计】按钮,选择该它的【任务(审批人)】进行配置"); 30 "原因:用户任务({})未配置审批人,请点击【流程设计】按钮,选择该它的【任务(审批人)】进行配置");
31 ErrorCode MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS = new ErrorCode(1_009_003_005, "流程定义部署失败,原因:信息未发生变化"); 31 ErrorCode MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS = new ErrorCode(1_009_003_005, "流程定义部署失败,原因:信息未发生变化");
32 32
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java deleted
1 -package cn.iocoder.yudao.module.bpm.enums.definition;  
2 -  
3 -import lombok.AllArgsConstructor;  
4 -import lombok.Getter;  
5 -  
6 -/**  
7 - * BPM 任务规则的脚本枚举  
8 - * 目前暂时通过 TODO 芋艿:硬编码,未来可以考虑 Groovy 动态脚本的方式  
9 - *  
10 - * @author 芋道源码  
11 - */  
12 -@Getter  
13 -@AllArgsConstructor  
14 -public enum BpmTaskRuleScriptEnum {  
15 -  
16 - START_USER(10L, "流程发起人"),  
17 -  
18 - LEADER_X1(20L, "流程发起人的一级领导"),  
19 - LEADER_X2(21L, "流程发起人的二级领导");  
20 -  
21 - /**  
22 - * 脚本编号  
23 - */  
24 - private final Long id;  
25 - /**  
26 - * 脚本描述  
27 - */  
28 - private final String desc;  
29 -  
30 -}  
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmCandidateProcessorConfiguration.java deleted
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 -// TODO @芋艿:Candidate 相关还在完善中,用户可以暂时忽略,仅 yudao 开发的同学需要关注~计划是把 Candidate 和 Assign 融合成一套  
10 -/**  
11 - * BPM 通用的 Configuration 配置类,提供给 Activiti 和 Flowable  
12 - * @author kyle  
13 - */  
14 -@Configuration(proxyBeanMethods = false)  
15 -public class BpmCandidateProcessorConfiguration {  
16 - @Bean  
17 - public BpmCandidateAdminUserApiSourceInfoProcessor bpmCandidateAdminUserApiSourceInfoProcessor() {  
18 - return new BpmCandidateAdminUserApiSourceInfoProcessor();  
19 - }  
20 -  
21 - @Bean  
22 - public BpmCandidateDeptApiSourceInfoProcessor bpmCandidateDeptApiSourceInfoProcessor() {  
23 - return new BpmCandidateDeptApiSourceInfoProcessor();  
24 - }  
25 -  
26 - @Bean  
27 - public BpmCandidatePostApiSourceInfoProcessor bpmCandidatePostApiSourceInfoProcessor() {  
28 - return new BpmCandidatePostApiSourceInfoProcessor();  
29 - }  
30 -  
31 - @Bean  
32 - public BpmCandidateRoleApiSourceInfoProcessor bpmCandidateRoleApiSourceInfoProcessor() {  
33 - return new BpmCandidateRoleApiSourceInfoProcessor();  
34 - }  
35 -  
36 - @Bean  
37 - public BpmCandidateUserGroupApiSourceInfoProcessor bpmCandidateUserGroupApiSourceInfoProcessor() {  
38 - return new BpmCandidateUserGroupApiSourceInfoProcessor();  
39 - }  
40 -  
41 - /**  
42 - * 可以自己定制脚本,然后通过这里设置到处理器里面去  
43 - * @param scriptsOp 脚本包装对象  
44 - * @return  
45 - */  
46 - @Bean  
47 - public BpmCandidateScriptApiSourceInfoProcessor bpmCandidateScriptApiSourceInfoProcessor(ObjectProvider<BpmTaskAssignScript> scriptsOp) {  
48 - BpmCandidateScriptApiSourceInfoProcessor bpmCandidateScriptApiSourceInfoProcessor = new BpmCandidateScriptApiSourceInfoProcessor();  
49 - bpmCandidateScriptApiSourceInfoProcessor.setScripts(scriptsOp);  
50 - return bpmCandidateScriptApiSourceInfoProcessor;  
51 - }  
52 -}  
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java
@@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.config; @@ -2,7 +2,9 @@ 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.service.definition.BpmTaskAssignRuleService; 5 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
  6 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
  7 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
6 import org.flowable.common.engine.api.delegate.event.FlowableEventListener; 8 import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
7 import org.flowable.spring.SpringProcessEngineConfiguration; 9 import org.flowable.spring.SpringProcessEngineConfiguration;
8 import org.flowable.spring.boot.EngineConfigurationConfigurer; 10 import org.flowable.spring.boot.EngineConfigurationConfigurer;
@@ -10,6 +12,8 @@ import org.springframework.beans.factory.ObjectProvider; @@ -10,6 +12,8 @@ import org.springframework.beans.factory.ObjectProvider;
10 import org.springframework.context.annotation.Bean; 12 import org.springframework.context.annotation.Bean;
11 import org.springframework.context.annotation.Configuration; 13 import org.springframework.context.annotation.Configuration;
12 14
  15 +import java.util.List;
  16 +
13 /** 17 /**
14 * BPM 模块的 Flowable 配置类 18 * BPM 模块的 Flowable 配置类
15 * 19 *
@@ -36,11 +40,20 @@ public class BpmFlowableConfiguration { @@ -36,11 +40,20 @@ public class BpmFlowableConfiguration {
36 }; 40 };
37 } 41 }
38 42
  43 + // =========== 审批人相关的 Bean ==========
  44 +
39 @Bean 45 @Bean
40 - public BpmActivityBehaviorFactory bpmActivityBehaviorFactory(BpmTaskAssignRuleService taskRuleService) { 46 + public BpmActivityBehaviorFactory bpmActivityBehaviorFactory(BpmTaskCandidateInvoker bpmTaskCandidateInvoker) {
41 BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory(); 47 BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory();
42 - bpmActivityBehaviorFactory.setBpmTaskRuleService(taskRuleService); 48 + bpmActivityBehaviorFactory.setTaskCandidateInvoker(bpmTaskCandidateInvoker);
43 return bpmActivityBehaviorFactory; 49 return bpmActivityBehaviorFactory;
44 } 50 }
45 51
46 -} 52 + @Bean
  53 + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") // adminUserApi 可以注入成功
  54 + public BpmTaskCandidateInvoker bpmTaskCandidateInvoker(List<BpmTaskCandidateStrategy> strategyList,
  55 + AdminUserApi adminUserApi) {
  56 + return new BpmTaskCandidateInvoker(strategyList, adminUserApi);
  57 + }
  58 +
  59 +}
47 \ No newline at end of file 60 \ No newline at end of file
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.service.definition.BpmTaskAssignRuleService;  
4 -import lombok.Data;  
5 -import lombok.EqualsAndHashCode; 3 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
6 import lombok.Setter; 4 import lombok.Setter;
7 -import lombok.ToString;  
8 import org.flowable.bpmn.model.Activity; 5 import org.flowable.bpmn.model.Activity;
9 import org.flowable.bpmn.model.UserTask; 6 import org.flowable.bpmn.model.UserTask;
10 import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; 7 import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
@@ -18,25 +15,22 @@ import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFacto @@ -18,25 +15,22 @@ import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFacto
18 * 15 *
19 * @author 芋道源码 16 * @author 芋道源码
20 */ 17 */
21 -@Data  
22 -@EqualsAndHashCode(callSuper = true)  
23 -@ToString(callSuper = true) 18 +@Setter
24 public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory { 19 public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
25 20
26 - @Setter  
27 - private BpmTaskAssignRuleService bpmTaskRuleService; 21 + private BpmTaskCandidateInvoker taskCandidateInvoker;
28 22
29 @Override 23 @Override
30 public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) { 24 public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) {
31 return new BpmUserTaskActivityBehavior(userTask) 25 return new BpmUserTaskActivityBehavior(userTask)
32 - .setBpmTaskRuleService(bpmTaskRuleService); 26 + .setTaskCandidateInvoker(taskCandidateInvoker);
33 } 27 }
34 28
35 @Override 29 @Override
36 public ParallelMultiInstanceBehavior createParallelMultiInstanceBehavior(Activity activity, 30 public ParallelMultiInstanceBehavior createParallelMultiInstanceBehavior(Activity activity,
37 AbstractBpmnActivityBehavior innerActivityBehavior) { 31 AbstractBpmnActivityBehavior innerActivityBehavior) {
38 return new BpmParallelMultiInstanceBehavior(activity, innerActivityBehavior) 32 return new BpmParallelMultiInstanceBehavior(activity, innerActivityBehavior)
39 - .setBpmTaskRuleService(bpmTaskRuleService); 33 + .setTaskCandidateInvoker(taskCandidateInvoker);
40 } 34 }
41 35
42 // TODO @ke:SequentialMultiInstanceBehavior 这个抽空也可以看看 36 // TODO @ke:SequentialMultiInstanceBehavior 这个抽空也可以看看
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.iocoder.yudao.framework.flowable.core.util.FlowableUtils; 3 import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
4 -import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; 4 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
5 import lombok.Setter; 5 import lombok.Setter;
6 import lombok.extern.slf4j.Slf4j; 6 import lombok.extern.slf4j.Slf4j;
7 import org.flowable.bpmn.model.Activity; 7 import org.flowable.bpmn.model.Activity;
@@ -23,7 +23,7 @@ import java.util.Set; @@ -23,7 +23,7 @@ import java.util.Set;
23 public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehavior { 23 public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehavior {
24 24
25 @Setter 25 @Setter
26 - private BpmTaskAssignRuleService bpmTaskRuleService; 26 + private BpmTaskCandidateInvoker taskCandidateInvoker;
27 27
28 public BpmParallelMultiInstanceBehavior(Activity activity, 28 public BpmParallelMultiInstanceBehavior(Activity activity,
29 AbstractBpmnActivityBehavior innerActivityBehavior) { 29 AbstractBpmnActivityBehavior innerActivityBehavior) {
@@ -50,7 +50,7 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav @@ -50,7 +50,7 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav
50 super.collectionElementVariable = FlowableUtils.formatCollectionElementVariable(execution.getCurrentActivityId()); 50 super.collectionElementVariable = FlowableUtils.formatCollectionElementVariable(execution.getCurrentActivityId());
51 51
52 // 第二步,获取任务的所有处理人 52 // 第二步,获取任务的所有处理人
53 - Set<Long> assigneeUserIds = bpmTaskRuleService.calculateTaskCandidateUsers(execution); 53 + Set<Long> assigneeUserIds = taskCandidateInvoker.calculateUsers(execution);
54 execution.setVariable(super.collectionVariable, assigneeUserIds); 54 execution.setVariable(super.collectionVariable, assigneeUserIds);
55 return assigneeUserIds.size(); 55 return assigneeUserIds.size();
56 } 56 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
5 import cn.hutool.core.util.RandomUtil; 5 import cn.hutool.core.util.RandomUtil;
6 -import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; 6 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
7 import lombok.Setter; 7 import lombok.Setter;
8 import lombok.extern.slf4j.Slf4j; 8 import lombok.extern.slf4j.Slf4j;
9 import org.flowable.bpmn.model.UserTask; 9 import org.flowable.bpmn.model.UserTask;
@@ -29,7 +29,7 @@ import java.util.Set; @@ -29,7 +29,7 @@ import java.util.Set;
29 public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { 29 public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
30 30
31 @Setter 31 @Setter
32 - private BpmTaskAssignRuleService bpmTaskRuleService; 32 + private BpmTaskCandidateInvoker taskCandidateInvoker;
33 33
34 public BpmUserTaskActivityBehavior(UserTask userTask) { 34 public BpmUserTaskActivityBehavior(UserTask userTask) {
35 super(userTask); 35 super(userTask);
@@ -54,7 +54,7 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { @@ -54,7 +54,7 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
54 54
55 // 情况二,如果非多实例的任务,则计算任务处理人 55 // 情况二,如果非多实例的任务,则计算任务处理人
56 // 第一步,先计算可处理该任务的处理人们 56 // 第一步,先计算可处理该任务的处理人们
57 - Set<Long> candidateUserIds = bpmTaskRuleService.calculateTaskCandidateUsers(execution); 57 + Set<Long> candidateUserIds = taskCandidateInvoker.calculateUsers(execution);
58 // 第二步,后随机选择一个任务的处理人 58 // 第二步,后随机选择一个任务的处理人
59 // 疑问:为什么一定要选择一个任务处理人? 59 // 疑问:为什么一定要选择一个任务处理人?
60 // 解答:项目对 bpm 的任务是责任到人,所以每个任务有且仅有一个处理人。 60 // 解答:项目对 bpm 的任务是责任到人,所以每个任务有且仅有一个处理人。
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java deleted
1 -package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script;  
2 -  
3 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;  
4 -import org.flowable.engine.delegate.DelegateExecution;  
5 -  
6 -import java.util.Set;  
7 -  
8 -/**  
9 - * Bpm 任务分配的自定义 Script 脚本  
10 - * 使用场景:  
11 - * 1. 设置审批人为发起人  
12 - * 2. 设置审批人为发起人的 Leader  
13 - * 3. 甚至审批人为发起人的 Leader 的 Leader  
14 - *  
15 - * @author 芋道源码  
16 - */  
17 -@Deprecated  
18 -public interface BpmTaskAssignScript {  
19 -  
20 - /**  
21 - * 基于执行任务,获得任务的候选用户们  
22 - *  
23 - * @param execution 执行任务  
24 - * @return 候选人用户的编号数组  
25 - */  
26 - Set<Long> calculateTaskCandidateUsers(DelegateExecution execution);  
27 -  
28 - /**  
29 - * 获得枚举值  
30 - *  
31 - * @return 枚举值  
32 - */  
33 - BpmTaskRuleScriptEnum getEnum();  
34 -  
35 -}  
36 -  
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java deleted
1 -package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;  
2 -  
3 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;  
4 -import org.flowable.engine.delegate.DelegateExecution;  
5 -import org.springframework.stereotype.Component;  
6 -  
7 -import java.util.Set;  
8 -  
9 -/**  
10 - * 分配给发起人的一级 Leader 审批的 Script 实现类  
11 - *  
12 - * @author 芋道源码  
13 - */  
14 -@Deprecated  
15 -@Component  
16 -public class BpmTaskAssignLeaderX1Script extends BpmTaskAssignLeaderAbstractScript {  
17 -  
18 - @Override  
19 - public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution) {  
20 - return calculateTaskCandidateUsers(execution, 1);  
21 - }  
22 -  
23 - @Override  
24 - public BpmTaskRuleScriptEnum getEnum() {  
25 - return BpmTaskRuleScriptEnum.LEADER_X1;  
26 - }  
27 -  
28 -}  
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java deleted
1 -package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;  
2 -  
3 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;  
4 -import org.flowable.engine.delegate.DelegateExecution;  
5 -import org.springframework.stereotype.Component;  
6 -  
7 -import java.util.Set;  
8 -  
9 -/**  
10 - * 分配给发起人的二级 Leader 审批的 Script 实现类  
11 - *  
12 - * @author 芋道源码  
13 - */  
14 -@Deprecated  
15 -@Component  
16 -public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript {  
17 -  
18 - @Override  
19 - public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution) {  
20 - return calculateTaskCandidateUsers(execution, 2);  
21 - }  
22 -  
23 - @Override  
24 - public BpmTaskRuleScriptEnum getEnum() {  
25 - return BpmTaskRuleScriptEnum.LEADER_X2;  
26 - }  
27 -  
28 -}  
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.lang.Assert;
  5 +import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  7 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  8 +import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
  9 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
  10 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
  11 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  12 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  13 +import com.google.common.annotations.VisibleForTesting;
  14 +import lombok.extern.slf4j.Slf4j;
  15 +import org.flowable.bpmn.model.BpmnModel;
  16 +import org.flowable.bpmn.model.FlowElement;
  17 +import org.flowable.bpmn.model.UserTask;
  18 +import org.flowable.engine.delegate.DelegateExecution;
  19 +
  20 +import java.util.HashMap;
  21 +import java.util.List;
  22 +import java.util.Map;
  23 +import java.util.Set;
  24 +
  25 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  26 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG;
  27 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER;
  28 +
  29 +/**
  30 + * {@link BpmTaskCandidateStrategy} 的调用者,用于调用对应的策略,实现任务的候选人的计算
  31 + *
  32 + * @author 芋道源码
  33 + */
  34 +@Slf4j
  35 +public class BpmTaskCandidateInvoker {
  36 +
  37 + private final Map<BpmTaskCandidateStrategyEnum, BpmTaskCandidateStrategy> strategyMap = new HashMap<>();
  38 +
  39 + private final AdminUserApi adminUserApi;
  40 +
  41 + public BpmTaskCandidateInvoker(List<BpmTaskCandidateStrategy> strategyList,
  42 + AdminUserApi adminUserApi) {
  43 + strategyList.forEach(strategy -> {
  44 + BpmTaskCandidateStrategy oldStrategy = strategyMap.put(strategy.getStrategy(), strategy);
  45 + Assert.isNull(oldStrategy, "策略(%s) 重复", strategy.getStrategy());
  46 + });
  47 + this.adminUserApi = adminUserApi;
  48 + }
  49 +
  50 + /**
  51 + * 校验流程模型的任务分配规则全部都配置了
  52 + * 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!
  53 + *
  54 + * @param bpmnBytes BPMN XML
  55 + */
  56 + public void validateBpmnConfig(byte[] bpmnBytes) {
  57 + BpmnModel bpmnModel = BpmnModelUtils.getBpmnModel(bpmnBytes);
  58 + assert bpmnModel != null;
  59 + List<UserTask> userTaskList = BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class);
  60 + // 遍历所有的 UserTask,校验审批人配置
  61 + userTaskList.forEach(userTask -> {
  62 + // 1. 非空校验
  63 + Integer strategy = parseCandidateStrategy(userTask);
  64 + String param = parseCandidateParam(userTask);
  65 + if (strategy == null || StrUtil.isBlank(param)) {
  66 + throw exception(MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG, userTask.getName());
  67 + }
  68 + // 2. 具体策略校验
  69 + getCandidateStrategy(strategy).validateParam(param);
  70 + });
  71 + }
  72 +
  73 + /**
  74 + * 计算任务的候选人
  75 + *
  76 + * @param execution 执行任务
  77 + * @return 用户编号集合
  78 + */
  79 + public Set<Long> calculateUsers(DelegateExecution execution) {
  80 + // TODO 芋艿:这里需要重构
  81 +// // 1. 先从提前选好的审批人中获取
  82 +// List<Long> assignee = processInstanceService.getAssigneeByProcessInstanceIdAndTaskDefinitionKey(
  83 +// execution.getProcessInstanceId(), execution.getCurrentActivityId());
  84 +// if (CollUtil.isNotEmpty(assignee)) {
  85 +// // TODO @hai:new HashSet 即可
  86 +// return convertSet(assignee, Function.identity());
  87 +// }
  88 + Integer strategy = parseCandidateStrategy(execution.getCurrentFlowElement());
  89 + String param = parseCandidateParam(execution.getCurrentFlowElement());
  90 + // 1.1 计算任务的候选人
  91 + Set<Long> userIds = getCandidateStrategy(strategy).calculateUsers(execution, param);
  92 + // 1.2 移除被禁用的用户
  93 + removeDisableUsers(userIds);
  94 +
  95 + // 2. 校验是否有候选人
  96 + if (CollUtil.isEmpty(userIds)) {
  97 + log.error("[calculateUsers][流程任务({}/{}/{}) 任务规则({}/{}) 找不到候选人]", execution.getId(),
  98 + execution.getProcessDefinitionId(), execution.getCurrentActivityId(), strategy, param);
  99 + throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER);
  100 + }
  101 + return userIds;
  102 + }
  103 +
  104 + @VisibleForTesting
  105 + void removeDisableUsers(Set<Long> assigneeUserIds) {
  106 + if (CollUtil.isEmpty(assigneeUserIds)) {
  107 + return;
  108 + }
  109 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assigneeUserIds);
  110 + assigneeUserIds.removeIf(id -> {
  111 + AdminUserRespDTO user = userMap.get(id);
  112 + return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus());
  113 + });
  114 + }
  115 +
  116 + private static Integer parseCandidateStrategy(FlowElement userTask) {
  117 + return NumberUtils.parseInt(userTask.getAttributeValue(
  118 + BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY));
  119 + }
  120 +
  121 + private static String parseCandidateParam(FlowElement userTask) {
  122 + return userTask.getAttributeValue(
  123 + BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM);
  124 + }
  125 +
  126 + private BpmTaskCandidateStrategy getCandidateStrategy(Integer strategy) {
  127 + BpmTaskCandidateStrategyEnum strategyEnum = BpmTaskCandidateStrategyEnum.valueOf(strategy);
  128 + Assert.notNull(strategyEnum, "策略(%s) 不存在", strategy);
  129 + BpmTaskCandidateStrategy strategyObj = strategyMap.get(strategyEnum);
  130 + Assert.notNull(strategyObj, "策略(%s) 不存在", strategy);
  131 + return strategyObj;
  132 + }
  133 +
  134 +}
0 \ No newline at end of file 135 \ No newline at end of file
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateStrategy.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
  4 +import org.flowable.engine.delegate.DelegateExecution;
  5 +
  6 +import java.util.Set;
  7 +
  8 +/**
  9 + * BPM 任务的候选人的策略接口
  10 + *
  11 + * 例如说:分配审批人
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +public interface BpmTaskCandidateStrategy {
  16 +
  17 + /**
  18 + * 对应策略
  19 + *
  20 + * @return 策略
  21 + */
  22 + BpmTaskCandidateStrategyEnum getStrategy();
  23 +
  24 + /**
  25 + * 校验参数
  26 + *
  27 + * @param param 参数
  28 + */
  29 + void validateParam(String param);
  30 +
  31 + /**
  32 + * 基于执行任务,获得任务的候选用户们
  33 + *
  34 + * @param execution 执行任务
  35 + * @return 用户编号集合
  36 + */
  37 + Set<Long> calculateUsers(DelegateExecution execution, String param);
  38 +
  39 +}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpression.java
1 -package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; 1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.expression;
2 2
3 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 3 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
4 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;  
5 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 4 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
6 import cn.iocoder.yudao.module.system.api.dept.DeptApi; 5 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
7 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; 6 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
@@ -9,7 +8,7 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -9,7 +8,7 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
9 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; 8 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
10 import org.flowable.engine.delegate.DelegateExecution; 9 import org.flowable.engine.delegate.DelegateExecution;
11 import org.flowable.engine.runtime.ProcessInstance; 10 import org.flowable.engine.runtime.ProcessInstance;
12 -import org.springframework.context.annotation.Lazy; 11 +import org.springframework.stereotype.Component;
13 import org.springframework.util.Assert; 12 import org.springframework.util.Assert;
14 13
15 import jakarta.annotation.Resource; 14 import jakarta.annotation.Resource;
@@ -19,23 +18,23 @@ import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; @@ -19,23 +18,23 @@ import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
19 import static java.util.Collections.emptySet; 18 import static java.util.Collections.emptySet;
20 19
21 /** 20 /**
22 - * 分配给发起人的 Leader 审批的 Script 实现类  
23 - * 目前 Leader 的定义是, 21 + * 分配给发起人的 Leader 审批的 Expression 流程表达式
  22 + * 目前 Leader 的定义是,发起人所在部门的 Leader
24 * 23 *
25 * @author 芋道源码 24 * @author 芋道源码
26 */ 25 */
27 -@Deprecated  
28 -public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript { 26 +@Component
  27 +public class BpmTaskAssignLeaderExpression {
29 28
30 @Resource 29 @Resource
31 private AdminUserApi adminUserApi; 30 private AdminUserApi adminUserApi;
32 @Resource 31 @Resource
33 private DeptApi deptApi; 32 private DeptApi deptApi;
  33 +
34 @Resource 34 @Resource
35 - @Lazy // 解决循环依赖  
36 private BpmProcessInstanceService bpmProcessInstanceService; 35 private BpmProcessInstanceService bpmProcessInstanceService;
37 36
38 - protected Set<Long> calculateTaskCandidateUsers(DelegateExecution execution, int level) { 37 + protected Set<Long> calculateUsers(DelegateExecution execution, int level) {
39 Assert.isTrue(level > 0, "level 必须大于 0"); 38 Assert.isTrue(level > 0, "level 必须大于 0");
40 // 获得发起人 39 // 获得发起人
41 ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId()); 40 ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId());
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignStartUserExpression.java
1 -package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; 1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.expression;
2 2
3 import cn.iocoder.yudao.framework.common.util.collection.SetUtils; 3 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
4 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 4 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
5 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;  
6 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;  
7 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 5 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  6 +import jakarta.annotation.Resource;
8 import org.flowable.engine.delegate.DelegateExecution; 7 import org.flowable.engine.delegate.DelegateExecution;
9 import org.flowable.engine.runtime.ProcessInstance; 8 import org.flowable.engine.runtime.ProcessInstance;
10 -import org.springframework.context.annotation.Lazy;  
11 import org.springframework.stereotype.Component; 9 import org.springframework.stereotype.Component;
12 10
13 -import jakarta.annotation.Resource;  
14 import java.util.Set; 11 import java.util.Set;
15 12
16 /** 13 /**
17 - * 分配给发起人审批的 Script 实现类 14 + * 分配给发起人审批的 Expression 流程表达式
18 * 15 *
19 * @author 芋道源码 16 * @author 芋道源码
20 */ 17 */
21 -@Deprecated  
22 @Component 18 @Component
23 -public class BpmTaskAssignStartUserScript implements BpmTaskAssignScript { 19 +public class BpmTaskAssignStartUserExpression {
24 20
25 @Resource 21 @Resource
26 - @Lazy // 解决循环依赖  
27 private BpmProcessInstanceService bpmProcessInstanceService; 22 private BpmProcessInstanceService bpmProcessInstanceService;
28 23
29 - @Override  
30 - public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution) { 24 + public Set<Long> calculateUsers(DelegateExecution execution) {
31 ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId()); 25 ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId());
32 Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId()); 26 Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
33 return SetUtils.asSet(startUserId); 27 return SetUtils.asSet(startUserId);
34 } 28 }
35 29
36 - @Override  
37 - public BpmTaskRuleScriptEnum getEnum() {  
38 - return BpmTaskRuleScriptEnum.START_USER;  
39 - }  
40 -  
41 } 30 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptLeaderStrategy.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.string.StrUtils;
  4 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
  5 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
  6 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  7 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  8 +import jakarta.annotation.Resource;
  9 +import org.flowable.engine.delegate.DelegateExecution;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import java.util.List;
  13 +import java.util.Set;
  14 +
  15 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  16 +
  17 +/**
  18 + * 部门的负责人 {@link BpmTaskCandidateStrategy} 实现类
  19 + *
  20 + * @author kyle
  21 + */
  22 +@Component
  23 +public class BpmTaskCandidateDeptLeaderStrategy implements BpmTaskCandidateStrategy {
  24 +
  25 + @Resource
  26 + private DeptApi deptApi;
  27 +
  28 + @Override
  29 + public BpmTaskCandidateStrategyEnum getStrategy() {
  30 + return BpmTaskCandidateStrategyEnum.DEPT_LEADER;
  31 + }
  32 +
  33 + @Override
  34 + public void validateParam(String param) {
  35 + Set<Long> deptIds = StrUtils.splitToLongSet(param);
  36 + deptApi.validateDeptList(deptIds);
  37 + }
  38 +
  39 + @Override
  40 + public Set<Long> calculateUsers(DelegateExecution execution, String param) {
  41 + Set<Long> deptIds = StrUtils.splitToLongSet(param);
  42 + List<DeptRespDTO> depts = deptApi.getDeptList(deptIds);
  43 + return convertSet(depts, DeptRespDTO::getLeaderUserId);
  44 + }
  45 +
  46 +}
0 \ No newline at end of file 47 \ No newline at end of file
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptMemberStrategy.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.string.StrUtils;
  4 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
  5 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
  6 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  7 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  8 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  9 +import jakarta.annotation.Resource;
  10 +import org.flowable.engine.delegate.DelegateExecution;
  11 +import org.springframework.stereotype.Component;
  12 +
  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 +/**
  19 + * 部门的成员 {@link BpmTaskCandidateStrategy} 实现类
  20 + *
  21 + * @author kyle
  22 + */
  23 +@Component
  24 +public class BpmTaskCandidateDeptMemberStrategy implements BpmTaskCandidateStrategy {
  25 +
  26 + @Resource
  27 + private DeptApi deptApi;
  28 + @Resource
  29 + private AdminUserApi adminUserApi;
  30 +
  31 + @Override
  32 + public BpmTaskCandidateStrategyEnum getStrategy() {
  33 + return BpmTaskCandidateStrategyEnum.DEPT_MEMBER;
  34 + }
  35 +
  36 + @Override
  37 + public void validateParam(String param) {
  38 + Set<Long> deptIds = StrUtils.splitToLongSet(param);
  39 + deptApi.validateDeptList(deptIds);
  40 + }
  41 +
  42 + @Override
  43 + public Set<Long> calculateUsers(DelegateExecution execution, String param) {
  44 + Set<Long> deptIds = StrUtils.splitToLongSet(param);
  45 + List<AdminUserRespDTO> users = adminUserApi.getUserListByDeptIds(deptIds);
  46 + return convertSet(users, AdminUserRespDTO::getId);
  47 + }
  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/framework/flowable/core/candidate/strategy/BpmTaskCandidateExpressionStrategy.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
  4 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
  5 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
  6 +import org.dromara.hutool.core.convert.Convert;
  7 +import org.flowable.engine.delegate.DelegateExecution;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import java.util.Set;
  11 +
  12 +/**
  13 + * 流程表达式 {@link BpmTaskCandidateStrategy} 实现类
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Component
  18 +public class BpmTaskCandidateExpressionStrategy implements BpmTaskCandidateStrategy {
  19 +
  20 + @Override
  21 + public BpmTaskCandidateStrategyEnum getStrategy() {
  22 + return BpmTaskCandidateStrategyEnum.EXPRESSION;
  23 + }
  24 +
  25 + @Override
  26 + public void validateParam(String param) {
  27 + // do nothing 因为它基本做不了校验
  28 + }
  29 +
  30 + @Override
  31 + public Set<Long> calculateUsers(DelegateExecution execution, String param) {
  32 + Object result = FlowableUtils.getExpressionValue(execution, param);
  33 + return Convert.toSet(Long.class, result);
  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/framework/flowable/core/candidate/strategy/BpmTaskCandidateGroupStrategy.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.string.StrUtils;
  4 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
  5 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
  6 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
  7 +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
  8 +import jakarta.annotation.Resource;
  9 +import org.flowable.engine.delegate.DelegateExecution;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import java.util.Collection;
  13 +import java.util.List;
  14 +import java.util.Set;
  15 +
  16 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
  17 +
  18 +/**
  19 + * 用户组 {@link BpmTaskCandidateStrategy} 实现类
  20 + *
  21 + * @author kyle
  22 + */
  23 +@Component
  24 +public class BpmTaskCandidateGroupStrategy implements BpmTaskCandidateStrategy {
  25 +
  26 + @Resource
  27 + private BpmUserGroupService userGroupService;
  28 +
  29 + @Override
  30 + public BpmTaskCandidateStrategyEnum getStrategy() {
  31 + return BpmTaskCandidateStrategyEnum.USER_GROUP;
  32 + }
  33 +
  34 + @Override
  35 + public void validateParam(String param) {
  36 + Set<Long> groupIds = StrUtils.splitToLongSet(param);
  37 + userGroupService.getUserGroupList(groupIds);
  38 + }
  39 +
  40 + @Override
  41 + public Set<Long> calculateUsers(DelegateExecution execution, String param) {
  42 + Set<Long> groupIds = StrUtils.splitToLongSet(param);
  43 + List<BpmUserGroupDO> groups = userGroupService.getUserGroupList(groupIds);
  44 + return convertSetByFlatMap(groups, BpmUserGroupDO::getMemberUserIds, Collection::stream);
  45 + }
  46 +
  47 +}
0 \ No newline at end of file 48 \ No newline at end of file
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidatePostStrategy.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.string.StrUtils;
  4 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
  5 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
  6 +import cn.iocoder.yudao.module.system.api.dept.PostApi;
  7 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  8 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  9 +import jakarta.annotation.Resource;
  10 +import org.flowable.engine.delegate.DelegateExecution;
  11 +import org.springframework.stereotype.Component;
  12 +
  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 +/**
  19 + * 岗位 {@link BpmTaskCandidateStrategy} 实现类
  20 + *
  21 + * @author kyle
  22 + */
  23 +@Component
  24 +public class BpmTaskCandidatePostStrategy implements BpmTaskCandidateStrategy {
  25 +
  26 + @Resource
  27 + private PostApi postApi;
  28 + @Resource
  29 + private AdminUserApi adminUserApi;
  30 +
  31 + @Override
  32 + public BpmTaskCandidateStrategyEnum getStrategy() {
  33 + return BpmTaskCandidateStrategyEnum.POST;
  34 + }
  35 +
  36 + @Override
  37 + public void validateParam(String param) {
  38 + Set<Long> postIds = StrUtils.splitToLongSet(param);
  39 + postApi.validPostList(postIds);
  40 + }
  41 +
  42 + @Override
  43 + public Set<Long> calculateUsers(DelegateExecution execution, String param) {
  44 + Set<Long> postIds = StrUtils.splitToLongSet(param);
  45 + List<AdminUserRespDTO> users = adminUserApi.getUserListByPostIds(postIds);
  46 + return convertSet(users, AdminUserRespDTO::getId);
  47 + }
  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/framework/flowable/core/candidate/strategy/BpmTaskCandidateRoleStrategy.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.string.StrUtils;
  4 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
  5 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
  6 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
  7 +import cn.iocoder.yudao.module.system.api.permission.RoleApi;
  8 +import jakarta.annotation.Resource;
  9 +import org.flowable.engine.delegate.DelegateExecution;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import java.util.Set;
  13 +
  14 +/**
  15 + * 角色 {@link BpmTaskCandidateStrategy} 实现类
  16 + *
  17 + * @author kyle
  18 + */
  19 +@Component
  20 +public class BpmTaskCandidateRoleStrategy implements BpmTaskCandidateStrategy {
  21 +
  22 + @Resource
  23 + private RoleApi roleApi;
  24 + @Resource
  25 + private PermissionApi permissionApi;
  26 +
  27 + @Override
  28 + public BpmTaskCandidateStrategyEnum getStrategy() {
  29 + return BpmTaskCandidateStrategyEnum.ROLE;
  30 + }
  31 +
  32 + @Override
  33 + public void validateParam(String param) {
  34 + Set<Long> roleIds = StrUtils.splitToLongSet(param);
  35 + roleApi.validRoleList(roleIds);
  36 + }
  37 +
  38 + @Override
  39 + public Set<Long> calculateUsers(DelegateExecution execution, String param) {
  40 + Set<Long> roleIds = StrUtils.splitToLongSet(param);
  41 + return permissionApi.getUserRoleIdListByRoleIds(roleIds);
  42 + }
  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/framework/flowable/core/candidate/strategy/BpmTaskCandidateUserStrategy.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.string.StrUtils;
  4 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
  5 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
  6 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  7 +import jakarta.annotation.Resource;
  8 +import org.flowable.engine.delegate.DelegateExecution;
  9 +import org.springframework.stereotype.Component;
  10 +
  11 +import java.util.Set;
  12 +
  13 +/**
  14 + * 用户 {@link BpmTaskCandidateStrategy} 实现类
  15 + *
  16 + * @author kyle
  17 + */
  18 +@Component
  19 +public class BpmTaskCandidateUserStrategy implements BpmTaskCandidateStrategy {
  20 +
  21 + @Resource
  22 + private AdminUserApi adminUserApi;
  23 +
  24 + @Override
  25 + public BpmTaskCandidateStrategyEnum getStrategy() {
  26 + return BpmTaskCandidateStrategyEnum.USER;
  27 + }
  28 +
  29 + @Override
  30 + public void validateParam(String param) {
  31 + adminUserApi.validateUserList(StrUtils.splitToLongSet(param));
  32 + }
  33 +
  34 + @Override
  35 + public Set<Long> calculateUsers(DelegateExecution execution, String param) {
  36 + return StrUtils.splitToLongSet(param);
  37 + }
  38 +
  39 +}
0 \ No newline at end of file 40 \ No newline at end of file
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmTaskCandidateStrategyEnum.java
1 -package cn.iocoder.yudao.module.bpm.enums.definition; 1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.enums;
2 2
  3 +import cn.hutool.core.util.ArrayUtil;
3 import lombok.AllArgsConstructor; 4 import lombok.AllArgsConstructor;
4 import lombok.Getter; 5 import lombok.Getter;
5 6
6 /** 7 /**
7 - * BPM 任务分配规则的类型枚举 8 + * BPM 任务的候选人策略枚举
  9 + *
  10 + * 例如说:分配给指定人审批
8 * 11 *
9 * @author 芋道源码 12 * @author 芋道源码
10 */ 13 */
11 @Getter 14 @Getter
12 @AllArgsConstructor 15 @AllArgsConstructor
13 -public enum BpmTaskAssignRuleTypeEnum { 16 +public enum BpmTaskCandidateStrategyEnum {
14 17
15 ROLE(10, "角色"), 18 ROLE(10, "角色"),
16 DEPT_MEMBER(20, "部门的成员"), // 包括负责人 19 DEPT_MEMBER(20, "部门的成员"), // 包括负责人
@@ -18,18 +21,20 @@ public enum BpmTaskAssignRuleTypeEnum { @@ -18,18 +21,20 @@ public enum BpmTaskAssignRuleTypeEnum {
18 POST(22, "岗位"), 21 POST(22, "岗位"),
19 USER(30, "用户"), 22 USER(30, "用户"),
20 USER_GROUP(40, "用户组"), 23 USER_GROUP(40, "用户组"),
21 - @Deprecated  
22 - SCRIPT(50, "自定义脚本"), // 例如说,发起人所在部门的领导、发起人所在部门的领导的领导  
23 - EXPRESS(60, "流程表达式"), // 表达式 ExpressionManager 24 + EXPRESSION(60, "流程表达式"), // 表达式 ExpressionManager
24 ; 25 ;
25 26
26 /** 27 /**
27 * 类型 28 * 类型
28 */ 29 */
29 - private final Integer type; 30 + private final Integer strategy;
30 /** 31 /**
31 * 描述 32 * 描述
32 */ 33 */
33 - private final String desc; 34 + private final String description;
  35 +
  36 + public static BpmTaskCandidateStrategyEnum valueOf(Integer strategy) {
  37 + return ArrayUtil.firstMatch(o -> o.getStrategy().equals(strategy), values());
  38 + }
34 39
35 } 40 }
yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java
1 -package cn.iocoder.yudao.framework.flowable.core.enums; 1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.enums;
2 2
3 /** 3 /**
4 * 流程常量信息 4 * 流程常量信息
@@ -9,9 +9,16 @@ public interface BpmnModelConstants { @@ -9,9 +9,16 @@ public interface BpmnModelConstants {
9 9
10 /** 10 /**
11 * BPMN 中的命名空间 11 * BPMN 中的命名空间
12 - *  
13 - * 这个东西有可能导致无法切换工作流程的实现  
14 */ 12 */
15 String NAMESPACE = "http://flowable.org/bpmn"; 13 String NAMESPACE = "http://flowable.org/bpmn";
16 14
  15 + /**
  16 + * BPMN UserTask 的扩展属性,用于标记候选人策略
  17 + */
  18 + String USER_TASK_CANDIDATE_STRATEGY = "candidateStrategy";
  19 + /**
  20 + * BPMN UserTask 的扩展属性,用于标记候选人参数
  21 + */
  22 + String USER_TASK_CANDIDATE_PARAM = "candidateParam";
  23 +
17 } 24 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java deleted
1 -package cn.iocoder.yudao.module.bpm.service.candidate;  
2 -  
3 -import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;  
4 -import io.swagger.v3.oas.annotations.media.Schema;  
5 -import jakarta.validation.constraints.NotEmpty;  
6 -import jakarta.validation.constraints.NotNull;  
7 -import lombok.AllArgsConstructor;  
8 -import lombok.Data;  
9 -import lombok.NoArgsConstructor;  
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 - @Schema(description = "当前任务ID")  
22 - @NotNull  
23 - private String taskId;  
24 - /**  
25 - * 通过这些规则,生成最终需要生成的用户  
26 - */  
27 - @Schema(description = "当前任务预选规则")  
28 - @NotEmpty(message = "不允许空规则")  
29 - private Set<BpmTaskCandidateRuleVO> rules;  
30 -  
31 - @Schema(description = "发起抄送的用户")  
32 - private String creator;  
33 -  
34 - @Schema(description = "抄送原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "请帮忙审查下!")  
35 - @NotEmpty(message = "抄送原因不能为空")  
36 - private String reason;  
37 -  
38 - public void addRule(BpmTaskCandidateRuleVO vo) {  
39 - assert vo != null;  
40 - if (rules == null) {  
41 - rules = new HashSet<>();  
42 - }  
43 - rules.add(vo);  
44 - }  
45 -}  
46 \ No newline at end of file 0 \ 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 deleted
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.BpmTaskCandidateRuleVO;  
5 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;  
6 -import org.flowable.engine.delegate.DelegateExecution;  
7 -  
8 -import java.util.Collections;  
9 -import java.util.HashSet;  
10 -import java.util.Set;  
11 -  
12 -public interface BpmCandidateSourceInfoProcessor {  
13 - /**  
14 - * 获取该处理器支持的类型  
15 - * 来自 {@link BpmTaskAssignRuleTypeEnum}  
16 - *  
17 - * @return  
18 - */  
19 - Set<Integer> getSupportedTypes();  
20 -  
21 - /**  
22 - * 对规则和人员做校验  
23 - *  
24 - * @param type 规则  
25 - * @param options 人员id  
26 - */  
27 - void validRuleOptions(Integer type, Set<Long> options);  
28 -  
29 - /**  
30 - * 默认的处理  
31 - * 如果想去操作所有的规则,则可以覆盖此方法  
32 - *  
33 - * @param request 原始请求  
34 - * @param delegateExecution 审批过程中的对象  
35 - * @return 必须包含的是用户ID,而不是其他的ID  
36 - * @throws Exception  
37 - */  
38 - default Set<Long> process(BpmCandidateSourceInfo request, DelegateExecution delegateExecution) throws Exception {  
39 - Set<BpmTaskCandidateRuleVO> rules = request.getRules();  
40 - Set<Long> results = new HashSet<>();  
41 - for (BpmTaskCandidateRuleVO rule : rules) {  
42 - // 每个处理器都有机会处理自己支持的事件  
43 - if (CollUtil.contains(getSupportedTypes(), rule.getType())) {  
44 - results.addAll(doProcess(request, rule, delegateExecution));  
45 - }  
46 - }  
47 - return results;  
48 - }  
49 -  
50 - default Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {  
51 - return Collections.emptySet();  
52 - }  
53 -}  
54 \ No newline at end of file 0 \ 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 deleted
1 -package cn.iocoder.yudao.module.bpm.service.candidate;  
2 -  
3 -import cn.hutool.core.collection.CollUtil;  
4 -import cn.hutool.core.collection.ListUtil;  
5 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
6 -import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;  
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.engine.delegate.DelegateExecution;  
10 -import org.springframework.beans.factory.ObjectProvider;  
11 -import org.springframework.stereotype.Service;  
12 -  
13 -import jakarta.annotation.Resource;  
14 -import java.util.*;  
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 = ListUtil.toList(processorOp.iterator());  
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, DelegateExecution execution) throws Exception {  
44 - // Verify our parameters  
45 - if (sourceInfo == null) {  
46 - throw new IllegalArgumentException();  
47 - }  
48 - for (BpmCandidateSourceInfoProcessor processor : processorList) {  
49 - try {  
50 - for (BpmTaskCandidateRuleVO vo : sourceInfo.getRules()) {  
51 - if (CollUtil.contains(processor.getSupportedTypes(), vo.getType())) {  
52 - processor.validRuleOptions(vo.getType(), vo.getOptions());  
53 - }  
54 - }  
55 - } catch (Exception e) {  
56 - e.printStackTrace();  
57 - throw e;  
58 - }  
59 - }  
60 - Set<Long> saveResult = Collections.emptySet();  
61 - Exception saveException = null;  
62 - for (BpmCandidateSourceInfoProcessor processor : processorList) {  
63 - try {  
64 - saveResult = processor.process(sourceInfo, execution);  
65 - if (CollUtil.isNotEmpty(saveResult)) {  
66 - removeDisableUsers(saveResult);  
67 - break;  
68 - }  
69 - } catch (Exception e) {  
70 - saveException = e;  
71 - break;  
72 - }  
73 - }  
74 - // Return the exception or result state from the last execute()  
75 - if ((saveException != null)) {  
76 - throw saveException;  
77 - } else {  
78 - return (saveResult);  
79 - }  
80 - }  
81 -  
82 - public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution, BpmCandidateSourceInfo sourceInfo) {  
83 - Set<Long> results = Collections.emptySet();  
84 - try {  
85 - results = process(sourceInfo, execution);  
86 - } catch (Exception e) {  
87 - e.printStackTrace();  
88 - }  
89 - return results;  
90 - }  
91 -  
92 - /**  
93 - * 移除禁用用户  
94 - *  
95 - * @param assigneeUserIds  
96 - */  
97 - public void removeDisableUsers(Set<Long> assigneeUserIds) {  
98 - if (CollUtil.isEmpty(assigneeUserIds)) {  
99 - return;  
100 - }  
101 - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assigneeUserIds);  
102 - assigneeUserIds.removeIf(id -> {  
103 - AdminUserRespDTO user = userMap.get(id);  
104 - return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus());  
105 - });  
106 - }  
107 -}  
108 \ No newline at end of file 0 \ 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 deleted
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.BpmTaskCandidateRuleVO;  
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 -import org.flowable.engine.delegate.DelegateExecution;  
10 -  
11 -import jakarta.annotation.Resource;  
12 -import java.util.Set;  
13 -  
14 -public class BpmCandidateAdminUserApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor {  
15 - @Resource  
16 - private AdminUserApi api;  
17 -  
18 - @Override  
19 - public Set<Integer> getSupportedTypes() {  
20 - return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.USER.getType());  
21 - }  
22 -  
23 - @Override  
24 - public void validRuleOptions(Integer type, Set<Long> options) {  
25 - api.validateUserList(options);  
26 - }  
27 -  
28 - @Override  
29 - public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {  
30 - return rule.getOptions();  
31 - }  
32 -}  
33 \ No newline at end of file 0 \ 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 deleted
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.BpmTaskCandidateRuleVO;  
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 -import org.flowable.engine.delegate.DelegateExecution;  
13 -  
14 -import jakarta.annotation.Resource;  
15 -import java.util.Collections;  
16 -import java.util.List;  
17 -import java.util.Objects;  
18 -import java.util.Set;  
19 -  
20 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;  
21 -  
22 -public class BpmCandidateDeptApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor {  
23 - @Resource  
24 - private DeptApi api;  
25 - @Resource  
26 - private AdminUserApi adminUserApi;  
27 -  
28 - @Override  
29 - public Set<Integer> getSupportedTypes() {  
30 - return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(),  
31 - BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType());  
32 - }  
33 -  
34 - @Override  
35 - public void validRuleOptions(Integer type, Set<Long> options) {  
36 - api.validateDeptList(options);  
37 - }  
38 -  
39 - @Override  
40 - public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {  
41 - if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), rule.getType())) {  
42 - List<AdminUserRespDTO> users = adminUserApi.getUserListByDeptIds(rule.getOptions());  
43 - return convertSet(users, AdminUserRespDTO::getId);  
44 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), rule.getType())) {  
45 - List<DeptRespDTO> depts = api.getDeptList(rule.getOptions());  
46 - return convertSet(depts, DeptRespDTO::getLeaderUserId);  
47 - }  
48 - return Collections.emptySet();  
49 - }  
50 -}  
51 \ No newline at end of file 0 \ 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 deleted
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.BpmTaskCandidateRuleVO;  
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 -import org.flowable.engine.delegate.DelegateExecution;  
12 -  
13 -import jakarta.annotation.Resource;  
14 -import java.util.List;  
15 -import java.util.Set;  
16 -  
17 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;  
18 -  
19 -public class BpmCandidatePostApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor {  
20 - @Resource  
21 - private PostApi api;  
22 - @Resource  
23 - private AdminUserApi adminUserApi;  
24 -  
25 - @Override  
26 - public Set<Integer> getSupportedTypes() {  
27 - return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.POST.getType());  
28 - }  
29 -  
30 - @Override  
31 - public void validRuleOptions(Integer type, Set<Long> options) {  
32 - api.validPostList(options);  
33 - }  
34 -  
35 - @Override  
36 - public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {  
37 - List<AdminUserRespDTO> users = adminUserApi.getUserListByPostIds(rule.getOptions());  
38 - return convertSet(users, AdminUserRespDTO::getId);  
39 - }  
40 -}  
41 \ No newline at end of file 0 \ 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 deleted
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.BpmTaskCandidateRuleVO;  
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 -import org.flowable.engine.delegate.DelegateExecution;  
11 -  
12 -import jakarta.annotation.Resource;  
13 -import java.util.Set;  
14 -  
15 -public class BpmCandidateRoleApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor {  
16 - @Resource  
17 - private RoleApi api;  
18 -  
19 - @Resource  
20 - private PermissionApi permissionApi;  
21 -  
22 - @Override  
23 - public Set<Integer> getSupportedTypes() {  
24 - return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.ROLE.getType());  
25 - }  
26 -  
27 - @Override  
28 - public void validRuleOptions(Integer type, Set<Long> options) {  
29 - api.validRoleList(options);  
30 - }  
31 -  
32 - @Override  
33 - public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {  
34 - return permissionApi.getUserRoleIdListByRoleIds(rule.getOptions());  
35 - }  
36 -  
37 -}  
38 \ No newline at end of file 0 \ 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 deleted
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.BpmTaskCandidateRuleVO;  
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 jakarta.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, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {  
55 - return calculateTaskCandidateUsersByScript(delegateExecution, 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 -}  
74 \ No newline at end of file 0 \ 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 deleted
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.BpmTaskCandidateRuleVO;  
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 -import org.flowable.engine.delegate.DelegateExecution;  
11 -  
12 -import jakarta.annotation.Resource;  
13 -import java.util.HashSet;  
14 -import java.util.List;  
15 -import java.util.Set;  
16 -  
17 -public class BpmCandidateUserGroupApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor {  
18 - @Resource  
19 - private BpmUserGroupService api;  
20 - @Resource  
21 - private BpmUserGroupService userGroupService;  
22 -  
23 - @Override  
24 - public Set<Integer> getSupportedTypes() {  
25 - return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType());  
26 - }  
27 -  
28 - @Override  
29 - public void validRuleOptions(Integer type, Set<Long> options) {  
30 - api.validUserGroups(options);  
31 - }  
32 -  
33 - @Override  
34 - public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {  
35 - List<BpmUserGroupDO> userGroups = userGroupService.getUserGroupList(rule.getOptions());  
36 - Set<Long> userIds = new HashSet<>();  
37 - userGroups.forEach(group -> userIds.addAll(group.getMemberUserIds()));  
38 - return userIds;  
39 - }  
40 -  
41 -}  
42 \ No newline at end of file 0 \ No newline at end of file
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
@@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*; @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
12 import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert; 12 import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
13 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; 13 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
14 import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum; 14 import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
  15 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
15 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO; 16 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
16 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; 17 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
17 import jakarta.annotation.Resource; 18 import jakarta.annotation.Resource;
@@ -54,8 +55,9 @@ public class BpmModelServiceImpl implements BpmModelService { @@ -54,8 +55,9 @@ public class BpmModelServiceImpl implements BpmModelService {
54 private BpmProcessDefinitionService processDefinitionService; 55 private BpmProcessDefinitionService processDefinitionService;
55 @Resource 56 @Resource
56 private BpmFormService bpmFormService; 57 private BpmFormService bpmFormService;
  58 +
57 @Resource 59 @Resource
58 - private BpmTaskAssignRuleService taskAssignRuleService; 60 + private BpmTaskCandidateInvoker taskCandidateInvoker;
59 61
60 @Override 62 @Override
61 public PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO) { 63 public PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO) {
@@ -166,7 +168,7 @@ public class BpmModelServiceImpl implements BpmModelService { @@ -166,7 +168,7 @@ public class BpmModelServiceImpl implements BpmModelService {
166 // 1.3 校验表单已配 168 // 1.3 校验表单已配
167 BpmFormDO form = checkFormConfig(model.getMetaInfo()); 169 BpmFormDO form = checkFormConfig(model.getMetaInfo());
168 // 1.4 校验任务分配规则已配置 170 // 1.4 校验任务分配规则已配置
169 - taskAssignRuleService.checkTaskAssignRuleAllConfig(bpmnBytes); 171 + taskCandidateInvoker.validateBpmnConfig(bpmnBytes);
170 172
171 // 1.5 校验模型是否发生修改。如果未修改,则不允许创建 173 // 1.5 校验模型是否发生修改。如果未修改,则不允许创建
172 BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form) 174 BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form)
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
@@ -5,7 +5,7 @@ import cn.hutool.core.util.ObjectUtil; @@ -5,7 +5,7 @@ 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.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.object.PageUtils; 7 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
8 -import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants; 8 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
9 import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils; 9 import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
10 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; 10 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO; 11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java deleted
1 -package cn.iocoder.yudao.module.bpm.service.definition;  
2 -  
3 -import org.flowable.engine.delegate.DelegateExecution;  
4 -  
5 -import java.util.Set;  
6 -  
7 -/**  
8 - * BPM 任务分配规则 Service 接口  
9 - *  
10 - * @author 芋道源码  
11 - */  
12 -public interface BpmTaskAssignRuleService {  
13 -  
14 - /**  
15 - * 校验流程模型的任务分配规则全部都配置了  
16 - * 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!  
17 - *  
18 - * @param bpmnBytes BPMN XML  
19 - */  
20 - void checkTaskAssignRuleAllConfig(byte[] bpmnBytes);  
21 -  
22 - /**  
23 - * 计算当前执行任务的处理人  
24 - *  
25 - * @param execution 执行任务  
26 - * @return 处理人的编号数组  
27 - */  
28 - Set<Long> calculateTaskCandidateUsers(DelegateExecution execution);  
29 -  
30 -}  
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java deleted
1 -package cn.iocoder.yudao.module.bpm.service.definition;  
2 -  
3 -import cn.hutool.core.collection.CollUtil;  
4 -import cn.hutool.core.util.ObjectUtil;  
5 -import cn.hutool.core.util.StrUtil;  
6 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
7 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
8 -import cn.iocoder.yudao.framework.common.util.number.NumberUtils;  
9 -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;  
10 -import cn.iocoder.yudao.framework.common.util.string.StrUtils;  
11 -import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;  
12 -import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants;  
13 -import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;  
14 -import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;  
15 -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;  
16 -import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;  
17 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;  
18 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;  
19 -import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;  
20 -import cn.iocoder.yudao.module.system.api.dept.DeptApi;  
21 -import cn.iocoder.yudao.module.system.api.dept.PostApi;  
22 -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;  
23 -import cn.iocoder.yudao.module.system.api.dict.DictDataApi;  
24 -import cn.iocoder.yudao.module.system.api.permission.PermissionApi;  
25 -import cn.iocoder.yudao.module.system.api.permission.RoleApi;  
26 -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;  
27 -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;  
28 -import com.google.common.annotations.VisibleForTesting;  
29 -import jakarta.annotation.Resource;  
30 -import lombok.extern.slf4j.Slf4j;  
31 -import org.dromara.hutool.core.convert.Convert;  
32 -import org.flowable.bpmn.model.BpmnModel;  
33 -import org.flowable.bpmn.model.FlowElement;  
34 -import org.flowable.bpmn.model.UserTask;  
35 -import org.flowable.engine.delegate.DelegateExecution;  
36 -import org.springframework.context.annotation.Lazy;  
37 -import org.springframework.stereotype.Service;  
38 -import org.springframework.validation.annotation.Validated;  
39 -  
40 -import java.util.*;  
41 -import java.util.function.Function;  
42 -  
43 -import static cn.hutool.core.text.CharSequenceUtil.format;  
44 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;  
45 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;  
46 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;  
47 -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;  
48 -  
49 -/**  
50 - * BPM 任务分配规则 Service 实现类  
51 - */  
52 -@Service  
53 -@Validated  
54 -@Slf4j  
55 -public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {  
56 -  
57 - @Resource  
58 - private BpmUserGroupService userGroupService;  
59 - @Resource  
60 - @Lazy // 解决循环依赖  
61 - private BpmProcessInstanceService processInstanceService;  
62 -  
63 -// @Resource  
64 -// private ExpressionManager expressionManager;  
65 -  
66 - @Resource  
67 - private RoleApi roleApi;  
68 - @Resource  
69 - private DeptApi deptApi;  
70 - @Resource  
71 - private PostApi postApi;  
72 - @Resource  
73 - private AdminUserApi adminUserApi;  
74 - @Resource  
75 - private DictDataApi dictDataApi;  
76 - @Resource  
77 - private PermissionApi permissionApi;  
78 -  
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 - }  
88 -  
89 - @Override  
90 - public void checkTaskAssignRuleAllConfig(byte[] bpmnBytes) {  
91 - BpmnModel bpmnModel = BpmnModelUtils.getBpmnModel(bpmnBytes);  
92 - assert bpmnModel != null;  
93 - List<UserTask> userTaskList = BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class);  
94 - // 遍历所有的 UserTask,校验审批人配置  
95 - userTaskList.forEach(userTask -> {  
96 - // TODO 芋艿:assignType/assignOptions/, 枚举  
97 - Integer type = NumberUtils.parseInt(userTask.getAttributeValue(BpmnModelConstants.NAMESPACE, "assignType"));  
98 - String options = userTask.getAttributeValue(BpmnModelConstants.NAMESPACE, "assignOptions");  
99 - if (type == null || StrUtil.isBlank(options)) {  
100 - throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, userTask.getName());  
101 - }  
102 - // TODO 芋艿:校验 options  
103 - if (ObjectUtil.equal(type, BpmTaskAssignRuleTypeEnum.EXPRESS.getType())) {  
104 - return;  
105 - }  
106 - validTaskAssignRuleOptions(type, StrUtils.splitToLong(options, ","));  
107 - });  
108 - }  
109 -  
110 - private void validTaskAssignRuleOptions(Integer type, Collection<Long> options) {  
111 - if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) {  
112 - roleApi.validRoleList(options);  
113 - } else if (ObjectUtils.equalsAny(type, BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(),  
114 - BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType())) {  
115 - deptApi.validateDeptList(options);  
116 - } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.POST.getType())) {  
117 - postApi.validPostList(options);  
118 - } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER.getType())) {  
119 - adminUserApi.validateUserList(options);  
120 - } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_GROUP.getType())) {  
121 - userGroupService.validUserGroups(options);  
122 - } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) {  
123 - dictDataApi.validateDictDataList(DictTypeConstants.TASK_ASSIGN_SCRIPT,  
124 - CollectionUtils.convertSet(options, String::valueOf));  
125 - } else {  
126 - throw new IllegalArgumentException(format("未知的规则类型({})", type));  
127 - }  
128 - }  
129 -  
130 - public Long test(DelegateExecution execution) {  
131 - return 1L;  
132 - }  
133 -  
134 - public Long test2(DelegateExecution execution, Long id) {  
135 - return id;  
136 - }  
137 -  
138 - @Override  
139 - @DataPermission(enable = false) // 忽略数据权限,不然分配会存在问题  
140 - public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution) {  
141 - // 1. 先从提前选好的审批人中获取  
142 - List<Long> assignee = processInstanceService.getAssigneeByProcessInstanceIdAndTaskDefinitionKey(  
143 - execution.getProcessInstanceId(), execution.getCurrentActivityId());  
144 - if (CollUtil.isNotEmpty(assignee)) {  
145 - // TODO @hai:new HashSet 即可  
146 - return convertSet(assignee, Function.identity());  
147 - }  
148 - // 2. 通过分配规则,计算审批人  
149 - return calculateTaskCandidateUsers0(execution);  
150 - }  
151 -  
152 - @VisibleForTesting  
153 - Set<Long> calculateTaskCandidateUsers0(DelegateExecution execution) {  
154 - // 获得审批人配置  
155 - // TODO 芋艿:assignType/assignOptions/, 枚举  
156 - FlowElement flowElement = execution.getCurrentFlowElement();  
157 - Integer type = NumberUtils.parseInt(flowElement.getAttributeValue(BpmnModelConstants.NAMESPACE, "assignType"));  
158 - String optionStr = flowElement.getAttributeValue(BpmnModelConstants.NAMESPACE, "assignOptions");  
159 - Set<Long> options = null;  
160 - if (ObjectUtil.notEqual(BpmTaskAssignRuleTypeEnum.EXPRESS.getType(), type)) {  
161 - options = StrUtils.splitToLongSet(optionStr, ",");  
162 - }  
163 -  
164 - // 计算审批人  
165 - Set<Long> assigneeUserIds = null;  
166 - if (Objects.equals(BpmTaskAssignRuleTypeEnum.ROLE.getType(), type)) {  
167 - assigneeUserIds = calculateTaskCandidateUsersByRole(options);  
168 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), type)) {  
169 - assigneeUserIds = calculateTaskCandidateUsersByDeptMember(options);  
170 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), type)) {  
171 - assigneeUserIds = calculateTaskCandidateUsersByDeptLeader(options);  
172 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.POST.getType(), type)) {  
173 - assigneeUserIds = calculateTaskCandidateUsersByPost(options);  
174 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER.getType(), type)) {  
175 - assigneeUserIds = calculateTaskCandidateUsersByUser(options);  
176 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), type)) {  
177 - assigneeUserIds = calculateTaskCandidateUsersByUserGroup(options);  
178 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), type)) {  
179 - assigneeUserIds = calculateTaskCandidateUsersByScript(execution, options);  
180 - } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.EXPRESS.getType(), type)) {  
181 - Object result = FlowableUtils.getExpressionValue(execution, optionStr);  
182 - assigneeUserIds = Convert.toSet(Long.class, result);  
183 - }  
184 -  
185 - // 移除被禁用的用户  
186 - removeDisableUsers(assigneeUserIds);  
187 - // 如果候选人为空,抛出异常  
188 - if (CollUtil.isEmpty(assigneeUserIds)) {  
189 - log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}/{}) 找不到候选人]", execution.getId(),  
190 - execution.getProcessDefinitionId(), execution.getCurrentActivityId(), type, options);  
191 - throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER);  
192 - }  
193 - return assigneeUserIds;  
194 - }  
195 -  
196 - private Set<Long> calculateTaskCandidateUsersByRole(Set<Long> roleIds) {  
197 - return permissionApi.getUserRoleIdListByRoleIds(roleIds);  
198 - }  
199 -  
200 - private Set<Long> calculateTaskCandidateUsersByDeptMember(Set<Long> deptIds) {  
201 - List<AdminUserRespDTO> users = adminUserApi.getUserListByDeptIds(deptIds);  
202 - return convertSet(users, AdminUserRespDTO::getId);  
203 - }  
204 -  
205 - private Set<Long> calculateTaskCandidateUsersByDeptLeader(Set<Long> deptIds) {  
206 - List<DeptRespDTO> depts = deptApi.getDeptList(deptIds);  
207 - return convertSet(depts, DeptRespDTO::getLeaderUserId);  
208 - }  
209 -  
210 - private Set<Long> calculateTaskCandidateUsersByPost(Set<Long> postIds) {  
211 - List<AdminUserRespDTO> users = adminUserApi.getUserListByPostIds(postIds);  
212 - return convertSet(users, AdminUserRespDTO::getId);  
213 - }  
214 -  
215 - private Set<Long> calculateTaskCandidateUsersByUser(Set<Long> userIds) {  
216 - return userIds;  
217 - }  
218 -  
219 - private Set<Long> calculateTaskCandidateUsersByUserGroup(Set<Long> groupIds) {  
220 - List<BpmUserGroupDO> userGroups = userGroupService.getUserGroupList(groupIds);  
221 - Set<Long> userIds = new HashSet<>();  
222 - userGroups.forEach(group -> userIds.addAll(group.getMemberUserIds()));  
223 - return userIds;  
224 - }  
225 -  
226 - private Set<Long> calculateTaskCandidateUsersByScript(DelegateExecution execution, Set<Long> scriptIds) {  
227 - // 获得对应的脚本  
228 - List<BpmTaskAssignScript> scripts = new ArrayList<>(scriptIds.size());  
229 - scriptIds.forEach(scriptId -> {  
230 - BpmTaskAssignScript script = scriptMap.get(scriptId);  
231 - if (script == null) {  
232 - throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, scriptId);  
233 - }  
234 - scripts.add(script);  
235 - });  
236 - // 逐个计算任务  
237 - Set<Long> userIds = new HashSet<>();  
238 - scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(execution)));  
239 - return userIds;  
240 - }  
241 -  
242 - @VisibleForTesting  
243 - void removeDisableUsers(Set<Long> assigneeUserIds) {  
244 - if (CollUtil.isEmpty(assigneeUserIds)) {  
245 - return;  
246 - }  
247 - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assigneeUserIds);  
248 - assigneeUserIds.removeIf(id -> {  
249 - AdminUserRespDTO user = userMap.get(id);  
250 - return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus());  
251 - });  
252 - }  
253 -  
254 -}  
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java
@@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO; 4 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO;
5 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; 5 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO;
6 import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; 6 import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO;
7 -import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo;  
8 7
9 /** 8 /**
10 * 流程抄送 Service 接口 9 * 流程抄送 Service 接口
@@ -13,14 +12,6 @@ import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; @@ -13,14 +12,6 @@ import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo;
13 */ 12 */
14 public interface BpmProcessInstanceCopyService { 13 public interface BpmProcessInstanceCopyService {
15 14
16 - // TODO 芋艿:这块要 review 下;思考下~~  
17 - /**  
18 - * 抄送  
19 - * @param sourceInfo 抄送源信息,方便抄送处理  
20 - * @return  
21 - */  
22 - boolean makeCopy(BpmCandidateSourceInfo sourceInfo);  
23 -  
24 /** 15 /**
25 * 流程实例的抄送 16 * 流程实例的抄送
26 * 17 *
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java
1 package cn.iocoder.yudao.module.bpm.service.task.cc; 1 package cn.iocoder.yudao.module.bpm.service.task.cc;
2 2
3 -import cn.hutool.core.bean.BeanUtil;  
4 -import cn.hutool.core.collection.CollUtil;  
5 import cn.hutool.core.util.ObjectUtil; 3 import cn.hutool.core.util.ObjectUtil;
6 -import cn.hutool.core.util.StrUtil;  
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO; 5 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO;
9 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; 6 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO;
10 import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; 7 import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO;
11 import cn.iocoder.yudao.module.bpm.dal.mysql.cc.BpmProcessInstanceCopyMapper; 8 import cn.iocoder.yudao.module.bpm.dal.mysql.cc.BpmProcessInstanceCopyMapper;
12 import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants; 9 import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
13 -import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo;  
14 -import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessorChain;  
15 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 10 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
16 import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; 11 import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
17 -import cn.iocoder.yudao.module.bpm.service.task.cc.dto.BpmDelegateExecutionDTO;  
18 import jakarta.annotation.Resource; 12 import jakarta.annotation.Resource;
19 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
20 -import org.flowable.engine.RuntimeService;  
21 -import org.flowable.engine.delegate.DelegateExecution;  
22 import org.flowable.engine.runtime.ProcessInstance; 14 import org.flowable.engine.runtime.ProcessInstance;
23 import org.flowable.task.api.Task; 15 import org.flowable.task.api.Task;
24 import org.springframework.context.annotation.Lazy; 16 import org.springframework.context.annotation.Lazy;
25 import org.springframework.stereotype.Service; 17 import org.springframework.stereotype.Service;
26 import org.springframework.validation.annotation.Validated; 18 import org.springframework.validation.annotation.Validated;
27 19
28 -import java.time.LocalDateTime;  
29 -import java.util.ArrayList;  
30 -import java.util.List;  
31 -import java.util.Set;  
32 -  
33 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
34 21
35 /** 22 /**
@@ -46,12 +33,6 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy @@ -46,12 +33,6 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy
46 private BpmProcessInstanceCopyMapper processInstanceCopyMapper; 33 private BpmProcessInstanceCopyMapper processInstanceCopyMapper;
47 34
48 @Resource 35 @Resource
49 - private RuntimeService runtimeService;  
50 -  
51 - @Resource  
52 - private BpmCandidateSourceInfoProcessorChain processorChain;  
53 -  
54 - @Resource  
55 @Lazy 36 @Lazy
56 private BpmTaskService bpmTaskService; 37 private BpmTaskService bpmTaskService;
57 @Resource 38 @Resource
@@ -59,55 +40,6 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy @@ -59,55 +40,6 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy
59 private BpmProcessInstanceService bpmProcessInstanceService; 40 private BpmProcessInstanceService bpmProcessInstanceService;
60 41
61 @Override 42 @Override
62 - public boolean makeCopy(BpmCandidateSourceInfo sourceInfo) {  
63 - if (null == sourceInfo) {  
64 - return false;  
65 - }  
66 -  
67 - Task task = bpmTaskService.getTask(sourceInfo.getTaskId());  
68 - if (ObjectUtil.isNull(task)) {  
69 - return false;  
70 - }  
71 - String processInstanceId = task.getProcessInstanceId();  
72 - if (StrUtil.isBlank(processInstanceId)) {  
73 - return false;  
74 - }  
75 - DelegateExecution executionEntity = new BpmDelegateExecutionDTO(processInstanceId);  
76 - Set<Long> ccCandidates = processorChain.calculateTaskCandidateUsers(executionEntity, sourceInfo);  
77 - if (CollUtil.isEmpty(ccCandidates)) {  
78 - log.warn("相关抄送人不存在 {}", sourceInfo.getTaskId());  
79 - return false;  
80 - } else {  
81 - BpmProcessInstanceCopyDO copyDO = new BpmProcessInstanceCopyDO();  
82 - // 调用  
83 - // 设置任务id  
84 - copyDO.setTaskId(sourceInfo.getTaskId());  
85 - copyDO.setTaskName(task.getName());  
86 - copyDO.setProcessInstanceId(processInstanceId);  
87 - ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()  
88 - .processInstanceId(processInstanceId)  
89 - .singleResult();  
90 - if (null == processInstance) {  
91 - log.warn("相关流程实例不存在 {}", sourceInfo.getTaskId());  
92 - return false;  
93 - }  
94 - copyDO.setStartUserId(Long.parseLong(processInstance.getStartUserId()));  
95 - copyDO.setProcessInstanceName(processInstance.getName());  
96 - copyDO.setCategory(processInstance.getProcessDefinitionCategory());  
97 - copyDO.setReason(sourceInfo.getReason());  
98 - copyDO.setCreator(sourceInfo.getCreator());  
99 - copyDO.setCreateTime(LocalDateTime.now());  
100 - List<BpmProcessInstanceCopyDO> copyList = new ArrayList<>(ccCandidates.size());  
101 - for (Long userId : ccCandidates) {  
102 - BpmProcessInstanceCopyDO copy = BeanUtil.copyProperties(copyDO, BpmProcessInstanceCopyDO.class);  
103 - copy.setUserId(userId);  
104 - copyList.add(copy);  
105 - }  
106 - return processInstanceCopyMapper.insertBatch(copyList);  
107 - }  
108 - }  
109 -  
110 - @Override  
111 public void createProcessInstanceCopy(Long userId, BpmProcessInstanceCopyCreateReqVO reqVO) { 43 public void createProcessInstanceCopy(Long userId, BpmProcessInstanceCopyCreateReqVO reqVO) {
112 // 1.1 校验任务存在 44 // 1.1 校验任务存在
113 Task task = bpmTaskService.getTask(reqVO.getTaskId()); 45 Task task = bpmTaskService.getTask(reqVO.getTaskId());
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvokerTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate;
  2 +
  3 +import cn.hutool.core.map.MapUtil;
  4 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  5 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  6 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.BpmTaskCandidateUserStrategy;
  7 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
  8 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
  9 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  10 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  11 +import org.flowable.bpmn.model.UserTask;
  12 +import org.flowable.engine.delegate.DelegateExecution;
  13 +import org.junit.jupiter.api.Test;
  14 +import org.mockito.InjectMocks;
  15 +import org.mockito.Mock;
  16 +import org.mockito.Spy;
  17 +
  18 +import java.util.Collections;
  19 +import java.util.List;
  20 +import java.util.Map;
  21 +import java.util.Set;
  22 +
  23 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  24 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  25 +import static org.junit.jupiter.api.Assertions.assertEquals;
  26 +import static org.mockito.ArgumentMatchers.eq;
  27 +import static org.mockito.Mockito.mock;
  28 +import static org.mockito.Mockito.when;
  29 +
  30 +/**
  31 + * {@link BpmTaskCandidateInvoker} 的单元测试
  32 + *
  33 + * @author 芋道源码
  34 + */
  35 +public class BpmTaskCandidateInvokerTest extends BaseMockitoUnitTest {
  36 +
  37 + @InjectMocks
  38 + private BpmTaskCandidateInvoker taskCandidateInvoker;
  39 +
  40 + @Mock
  41 + private AdminUserApi adminUserApi;
  42 + @Spy
  43 + private BpmTaskCandidateStrategy strategy = new BpmTaskCandidateUserStrategy();
  44 + @Spy
  45 + private List<BpmTaskCandidateStrategy> strategyList = Collections.singletonList(strategy);
  46 +
  47 + @Test
  48 + public void testCalculateUsers() {
  49 + // 准备参数
  50 + String param = "1,2";
  51 + DelegateExecution execution = mock(DelegateExecution.class);
  52 + // mock 方法(DelegateExecution)
  53 + UserTask userTask = mock(UserTask.class);
  54 + when(execution.getCurrentFlowElement()).thenReturn(userTask);
  55 + when(userTask.getAttributeValue(eq(BpmnModelConstants.NAMESPACE), eq(BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY)))
  56 + .thenReturn(BpmTaskCandidateStrategyEnum.USER.getStrategy().toString());
  57 + when(userTask.getAttributeValue(eq(BpmnModelConstants.NAMESPACE), eq(BpmnModelConstants.USER_TASK_CANDIDATE_PARAM)))
  58 + .thenReturn(param);
  59 + // mock 方法(adminUserApi)
  60 + AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)
  61 + .setStatus(CommonStatusEnum.ENABLE.getStatus()));
  62 + AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)
  63 + .setStatus(CommonStatusEnum.ENABLE.getStatus()));
  64 + Map<Long, AdminUserRespDTO> userMap = MapUtil.builder(user1.getId(), user1)
  65 + .put(user2.getId(), user2).build();
  66 + when(adminUserApi.getUserMap(eq(asSet(1L, 2L)))).thenReturn(userMap);
  67 +
  68 + // 调用
  69 + Set<Long> results = taskCandidateInvoker.calculateUsers(execution);
  70 + // 断言
  71 + assertEquals(asSet(1L, 2L), results);
  72 + }
  73 +
  74 + @Test
  75 + public void testRemoveDisableUsers() {
  76 + // 准备参数. 1L 可以找到;2L 是禁用的;3L 找不到
  77 + Set<Long> assigneeUserIds = asSet(1L, 2L, 3L);
  78 + // mock 方法
  79 + AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)
  80 + .setStatus(CommonStatusEnum.ENABLE.getStatus()));
  81 + AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)
  82 + .setStatus(CommonStatusEnum.DISABLE.getStatus()));
  83 + Map<Long, AdminUserRespDTO> userMap = MapUtil.builder(user1.getId(), user1)
  84 + .put(user2.getId(), user2).build();
  85 + when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);
  86 +
  87 + // 调用
  88 + taskCandidateInvoker.removeDisableUsers(assigneeUserIds);
  89 + // 断言
  90 + assertEquals(asSet(1L), assigneeUserIds);
  91 + }
  92 +
  93 +}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpressionTest.java
1 -package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; 1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.expression;
2 2
3 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; 3 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 4 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
@@ -21,10 +21,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals; @@ -21,10 +21,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.mockito.ArgumentMatchers.eq; 21 import static org.mockito.ArgumentMatchers.eq;
22 import static org.mockito.Mockito.when; 22 import static org.mockito.Mockito.when;
23 23
24 -public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest { 24 +public class BpmTaskAssignLeaderExpressionTest extends BaseMockitoUnitTest {
25 25
26 @InjectMocks 26 @InjectMocks
27 - private BpmTaskAssignLeaderX2Script script; 27 + private BpmTaskAssignLeaderExpression expression;
28 28
29 @Mock 29 @Mock
30 private AdminUserApi adminUserApi; 30 private AdminUserApi adminUserApi;
@@ -34,7 +34,7 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest { @@ -34,7 +34,7 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
34 private BpmProcessInstanceService bpmProcessInstanceService; 34 private BpmProcessInstanceService bpmProcessInstanceService;
35 35
36 @Test 36 @Test
37 - public void testCalculateTaskCandidateUsers_noDept() { 37 + public void testCalculateUsers_noDept() {
38 // 准备参数 38 // 准备参数
39 DelegateExecution execution = mockDelegateExecution(1L); 39 DelegateExecution execution = mockDelegateExecution(1L);
40 // mock 方法(startUser) 40 // mock 方法(startUser)
@@ -44,13 +44,13 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest { @@ -44,13 +44,13 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
44 when(deptApi.getDept(eq(10L))).thenReturn(null); 44 when(deptApi.getDept(eq(10L))).thenReturn(null);
45 45
46 // 调用 46 // 调用
47 - Set<Long> result = script.calculateTaskCandidateUsers(execution); 47 + Set<Long> result = expression.calculateUsers(execution, 1);
48 // 断言 48 // 断言
49 assertEquals(0, result.size()); 49 assertEquals(0, result.size());
50 } 50 }
51 51
52 @Test 52 @Test
53 - public void testCalculateTaskCandidateUsers_noParentDept() { 53 + public void testCalculateUsers_noParentDept() {
54 // 准备参数 54 // 准备参数
55 DelegateExecution execution = mockDelegateExecution(1L); 55 DelegateExecution execution = mockDelegateExecution(1L);
56 // mock 方法(startUser) 56 // mock 方法(startUser)
@@ -63,13 +63,13 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest { @@ -63,13 +63,13 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
63 when(deptApi.getDept(eq(100L))).thenReturn(null); 63 when(deptApi.getDept(eq(100L))).thenReturn(null);
64 64
65 // 调用 65 // 调用
66 - Set<Long> result = script.calculateTaskCandidateUsers(execution); 66 + Set<Long> result = expression.calculateUsers(execution, 2);
67 // 断言 67 // 断言
68 assertEquals(asSet(20L), result); 68 assertEquals(asSet(20L), result);
69 } 69 }
70 70
71 @Test 71 @Test
72 - public void testCalculateTaskCandidateUsers_existParentDept() { 72 + public void testCalculateUsers_existParentDept() {
73 // 准备参数 73 // 准备参数
74 DelegateExecution execution = mockDelegateExecution(1L); 74 DelegateExecution execution = mockDelegateExecution(1L);
75 // mock 方法(startUser) 75 // mock 方法(startUser)
@@ -84,7 +84,7 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest { @@ -84,7 +84,7 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
84 when(deptApi.getDept(eq(100L))).thenReturn(parentDept); 84 when(deptApi.getDept(eq(100L))).thenReturn(parentDept);
85 85
86 // 调用 86 // 调用
87 - Set<Long> result = script.calculateTaskCandidateUsers(execution); 87 + Set<Long> result = expression.calculateUsers(execution, 2);
88 // 断言 88 // 断言
89 assertEquals(asSet(200L), result); 89 assertEquals(asSet(200L), result);
90 } 90 }
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptLeaderStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  5 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  6 +import org.junit.jupiter.api.Test;
  7 +import org.mockito.InjectMocks;
  8 +import org.mockito.Mock;
  9 +
  10 +import java.util.Set;
  11 +
  12 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  13 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  14 +import static java.util.Arrays.asList;
  15 +import static org.junit.jupiter.api.Assertions.assertEquals;
  16 +import static org.mockito.ArgumentMatchers.eq;
  17 +import static org.mockito.Mockito.when;
  18 +
  19 +public class BpmTaskCandidateDeptLeaderStrategyTest extends BaseMockitoUnitTest {
  20 +
  21 + @InjectMocks
  22 + private BpmTaskCandidateDeptLeaderStrategy strategy;
  23 +
  24 + @Mock
  25 + private DeptApi deptApi;
  26 +
  27 + @Test
  28 + public void testCalculateUsers() {
  29 + // 准备参数
  30 + String param = "1,2";
  31 + // mock 方法
  32 + DeptRespDTO dept1 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(11L));
  33 + DeptRespDTO dept2 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(22L));
  34 + when(deptApi.getDeptList(eq(asSet(1L, 2L)))).thenReturn(asList(dept1, dept2));
  35 +
  36 + // 调用
  37 + Set<Long> results = strategy.calculateUsers(null, param);
  38 + // 断言
  39 + assertEquals(asSet(11L, 22L), results);
  40 + }
  41 +
  42 +}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptMemberStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  5 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  6 +import org.junit.jupiter.api.Test;
  7 +import org.mockito.InjectMocks;
  8 +import org.mockito.Mock;
  9 +
  10 +import java.util.List;
  11 +import java.util.Set;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  14 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  15 +import static org.junit.jupiter.api.Assertions.assertEquals;
  16 +import static org.mockito.ArgumentMatchers.eq;
  17 +import static org.mockito.Mockito.when;
  18 +
  19 +public class BpmTaskCandidateDeptMemberStrategyTest extends BaseMockitoUnitTest {
  20 +
  21 + @InjectMocks
  22 + private BpmTaskCandidateDeptMemberStrategy strategy;
  23 +
  24 + @Mock
  25 + private AdminUserApi adminUserApi;
  26 +
  27 + @Test
  28 + public void testCalculateUsers() {
  29 + // 准备参数
  30 + String param = "11,22";
  31 + // mock 方法
  32 + List<AdminUserRespDTO> users = convertList(asSet(11L, 22L),
  33 + id -> new AdminUserRespDTO().setId(id));
  34 + when(adminUserApi.getUserListByDeptIds(eq(asSet(11L, 22L)))).thenReturn(users);
  35 +
  36 + // 调用
  37 + Set<Long> results = strategy.calculateUsers(null, param);
  38 + // 断言
  39 + assertEquals(asSet(11L, 22L), results);
  40 + }
  41 +
  42 +}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateExpressionStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
  4 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  5 +import org.flowable.engine.delegate.DelegateExecution;
  6 +import org.junit.jupiter.api.Test;
  7 +import org.mockito.InjectMocks;
  8 +import org.mockito.MockedStatic;
  9 +
  10 +import java.util.Set;
  11 +
  12 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  13 +import static org.junit.jupiter.api.Assertions.assertEquals;
  14 +import static org.mockito.ArgumentMatchers.eq;
  15 +import static org.mockito.Mockito.*;
  16 +
  17 +public class BpmTaskCandidateExpressionStrategyTest extends BaseMockitoUnitTest {
  18 +
  19 + @InjectMocks
  20 + private BpmTaskCandidateExpressionStrategy strategy;
  21 +
  22 + @Test
  23 + public void testCalculateUsers() {
  24 + try (MockedStatic<FlowableUtils> flowableUtilMockedStatic = mockStatic(FlowableUtils.class)) {
  25 + // 准备参数
  26 + String param = "1,2";
  27 + DelegateExecution execution = mock(DelegateExecution.class);
  28 + // mock 方法
  29 + flowableUtilMockedStatic.when(() -> FlowableUtils.getExpressionValue(same(execution), eq(param)))
  30 + .thenReturn(asSet(1L, 2L));
  31 +
  32 + // 调用
  33 + Set<Long> results = strategy.calculateUsers(execution, param);
  34 + // 断言
  35 + assertEquals(asSet(1L, 2L), results);
  36 + }
  37 + }
  38 +
  39 +}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateGroupStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
  5 +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
  6 +import org.junit.jupiter.api.Test;
  7 +import org.mockito.InjectMocks;
  8 +import org.mockito.Mock;
  9 +
  10 +import java.util.Arrays;
  11 +import java.util.Set;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  14 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  15 +import static org.junit.jupiter.api.Assertions.assertEquals;
  16 +import static org.mockito.ArgumentMatchers.eq;
  17 +import static org.mockito.Mockito.when;
  18 +
  19 +public class BpmTaskCandidateGroupStrategyTest extends BaseMockitoUnitTest {
  20 +
  21 + @InjectMocks
  22 + private BpmTaskCandidateGroupStrategy strategy;
  23 +
  24 + @Mock
  25 + private BpmUserGroupService userGroupService;
  26 +
  27 + @Test
  28 + public void testCalculateUsers() {
  29 + // 准备参数
  30 + String param = "1,2";
  31 + // mock 方法
  32 + BpmUserGroupDO userGroup1 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(11L, 12L)));
  33 + BpmUserGroupDO userGroup2 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(21L, 22L)));
  34 + when(userGroupService.getUserGroupList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(userGroup1, userGroup2));
  35 +
  36 + // 调用
  37 + Set<Long> results = strategy.calculateUsers(null, param);
  38 + // 断言
  39 + assertEquals(asSet(11L, 12L, 21L, 22L), results);
  40 + }
  41 +
  42 +}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidatePostStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.system.api.dept.PostApi;
  5 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  6 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  7 +import org.junit.jupiter.api.Test;
  8 +import org.mockito.InjectMocks;
  9 +import org.mockito.Mock;
  10 +
  11 +import java.util.List;
  12 +import java.util.Set;
  13 +
  14 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  15 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  16 +import static org.junit.jupiter.api.Assertions.assertEquals;
  17 +import static org.mockito.ArgumentMatchers.eq;
  18 +import static org.mockito.Mockito.when;
  19 +
  20 +public class BpmTaskCandidatePostStrategyTest extends BaseMockitoUnitTest {
  21 +
  22 + @InjectMocks
  23 + private BpmTaskCandidatePostStrategy strategy;
  24 +
  25 + @Mock
  26 + private PostApi postApi;
  27 + @Mock
  28 + private AdminUserApi adminUserApi;
  29 +
  30 + @Test
  31 + public void testCalculateUsers() {
  32 + // 准备参数
  33 + String param = "1,2";
  34 + // mock 方法
  35 + List<AdminUserRespDTO> users = convertList(asSet(11L, 22L),
  36 + id -> new AdminUserRespDTO().setId(id));
  37 + when(adminUserApi.getUserListByPostIds(eq(asSet(1L, 2L)))).thenReturn(users);
  38 +
  39 + // 调用
  40 + Set<Long> results = strategy.calculateUsers(null, param);
  41 + // 断言
  42 + assertEquals(asSet(11L, 22L), results);
  43 + }
  44 +
  45 +}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateRoleStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
  5 +import cn.iocoder.yudao.module.system.api.permission.RoleApi;
  6 +import org.junit.jupiter.api.Test;
  7 +import org.mockito.InjectMocks;
  8 +import org.mockito.Mock;
  9 +
  10 +import java.util.Set;
  11 +
  12 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  13 +import static org.junit.jupiter.api.Assertions.assertEquals;
  14 +import static org.mockito.ArgumentMatchers.eq;
  15 +import static org.mockito.Mockito.when;
  16 +
  17 +public class BpmTaskCandidateRoleStrategyTest extends BaseMockitoUnitTest {
  18 +
  19 + @InjectMocks
  20 + private BpmTaskCandidateRoleStrategy strategy;
  21 +
  22 + @Mock
  23 + private RoleApi roleApi;
  24 + @Mock
  25 + private PermissionApi permissionApi;
  26 +
  27 + @Test
  28 + public void testCalculateUsers() {
  29 + // 准备参数
  30 + String param = "1,2";
  31 + // mock 方法
  32 + when(permissionApi.getUserRoleIdListByRoleIds(eq(asSet(1L, 2L))))
  33 + .thenReturn(asSet(11L, 22L));
  34 +
  35 + // 调用
  36 + Set<Long> results = strategy.calculateUsers(null, param);
  37 + // 断言
  38 + assertEquals(asSet(11L, 22L), results);
  39 + }
  40 +
  41 +}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateUserStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import org.junit.jupiter.api.Test;
  5 +import org.mockito.InjectMocks;
  6 +
  7 +import java.util.Set;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  10 +import static org.junit.jupiter.api.Assertions.assertEquals;
  11 +
  12 +public class BpmTaskCandidateUserStrategyTest extends BaseMockitoUnitTest {
  13 +
  14 + @InjectMocks
  15 + private BpmTaskCandidateUserStrategy strategy;
  16 +
  17 + @Test
  18 + public void testCalculateUsers() {
  19 + // 准备参数
  20 + String param = "1,2";
  21 +
  22 + // 调用
  23 + Set<Long> results = strategy.calculateUsers(null, param);
  24 + // 断言
  25 + assertEquals(asSet(1L, 2L), results);
  26 + }
  27 +
  28 +}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessorChainTest.java deleted
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.BpmTaskCandidateRuleVO;  
8 -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;  
9 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;  
10 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;  
11 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;  
12 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl.BpmTaskAssignLeaderX1Script;  
13 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl.BpmTaskAssignLeaderX2Script;  
14 -import cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor.BpmCandidateScriptApiSourceInfoProcessor;  
15 -import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;  
16 -import cn.iocoder.yudao.module.system.api.dept.DeptApi;  
17 -import cn.iocoder.yudao.module.system.api.dept.PostApi;  
18 -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;  
19 -import cn.iocoder.yudao.module.system.api.dict.DictDataApi;  
20 -import cn.iocoder.yudao.module.system.api.permission.PermissionApi;  
21 -import cn.iocoder.yudao.module.system.api.permission.RoleApi;  
22 -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;  
23 -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;  
24 -import jakarta.annotation.Resource;  
25 -import org.flowable.engine.delegate.DelegateExecution;  
26 -import org.junit.jupiter.api.Disabled;  
27 -import org.junit.jupiter.api.Test;  
28 -import org.springframework.boot.test.mock.mockito.MockBean;  
29 -import org.springframework.context.annotation.Import;  
30 -  
31 -import java.util.Arrays;  
32 -import java.util.List;  
33 -import java.util.Map;  
34 -import java.util.Set;  
35 -  
36 -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;  
37 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;  
38 -import static java.util.Collections.singleton;  
39 -import static org.junit.jupiter.api.Assertions.assertEquals;  
40 -import static org.mockito.ArgumentMatchers.eq;  
41 -import static org.mockito.Mockito.when;  
42 -  
43 -@Disabled // TODO 芋艿:临时禁用,暂时不修复,等重构后解决  
44 -@Import({BpmCandidateSourceInfoProcessorChain.class,  
45 - BpmCandidateScriptApiSourceInfoProcessor.class, BpmTaskAssignLeaderX1Script.class,  
46 - BpmTaskAssignLeaderX2Script.class})  
47 -public class BpmCandidateSourceInfoProcessorChainTest extends BaseDbUnitTest {  
48 - @Resource  
49 - private BpmCandidateSourceInfoProcessorChain processorChain;  
50 -  
51 - @MockBean  
52 - private BpmUserGroupService userGroupService;  
53 - @MockBean  
54 - private DeptApi deptApi;  
55 - @MockBean  
56 - private AdminUserApi adminUserApi;  
57 - @MockBean  
58 - private PermissionApi permissionApi;  
59 - @MockBean  
60 - private RoleApi roleApi;  
61 - @MockBean  
62 - private PostApi postApi;  
63 - @MockBean  
64 - private DictDataApi dictDataApi;  
65 - @Resource  
66 - private BpmCandidateScriptApiSourceInfoProcessor bpmCandidateScriptApiSourceInfoProcessor;  
67 -  
68 - @Test  
69 - public void testCalculateTaskCandidateUsers_Role() {  
70 - // 准备参数  
71 - BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L))  
72 - .setType(BpmTaskAssignRuleTypeEnum.ROLE.getType());  
73 - // mock 方法  
74 - when(permissionApi.getUserRoleIdListByRoleIds(eq(rule.getOptions())))  
75 - .thenReturn(asSet(11L, 22L));  
76 - mockGetUserMap(asSet(11L, 22L));  
77 -  
78 - // 调用  
79 - BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();  
80 - sourceInfo.addRule(rule);  
81 - Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);  
82 - // 断言  
83 - assertEquals(asSet(11L, 22L), results);  
84 - }  
85 -  
86 - @Test  
87 - public void testCalculateTaskCandidateUsers_DeptMember() {  
88 - // 准备参数  
89 - BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L))  
90 - .setType(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType());  
91 - // mock 方法  
92 - List<AdminUserRespDTO> users = CollectionUtils.convertList(asSet(11L, 22L),  
93 - id -> new AdminUserRespDTO().setId(id));  
94 - when(adminUserApi.getUserListByDeptIds(eq(rule.getOptions()))).thenReturn(users);  
95 - mockGetUserMap(asSet(11L, 22L));  
96 -  
97 - // 调用  
98 - BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();  
99 - sourceInfo.addRule(rule);  
100 - Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);  
101 - // 断言  
102 - assertEquals(asSet(11L, 22L), results);  
103 - }  
104 -  
105 - @Test  
106 - public void testCalculateTaskCandidateUsers_DeptLeader() {  
107 - // 准备参数  
108 - BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L))  
109 - .setType(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType());  
110 - // mock 方法  
111 - DeptRespDTO dept1 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(11L));  
112 - DeptRespDTO dept2 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(22L));  
113 - when(deptApi.getDeptList(eq(rule.getOptions()))).thenReturn(Arrays.asList(dept1, dept2));  
114 - mockGetUserMap(asSet(11L, 22L));  
115 -  
116 - // 调用  
117 - BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();  
118 - sourceInfo.addRule(rule);  
119 - Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);  
120 - // 断言  
121 - assertEquals(asSet(11L, 22L), results);  
122 - }  
123 -  
124 - @Test  
125 - public void testCalculateTaskCandidateUsers_Post() {  
126 - // 准备参数  
127 - BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L))  
128 - .setType(BpmTaskAssignRuleTypeEnum.POST.getType());  
129 - // mock 方法  
130 - List<AdminUserRespDTO> users = CollectionUtils.convertList(asSet(11L, 22L),  
131 - id -> new AdminUserRespDTO().setId(id));  
132 - when(adminUserApi.getUserListByPostIds(eq(rule.getOptions()))).thenReturn(users);  
133 - mockGetUserMap(asSet(11L, 22L));  
134 -  
135 - // 调用  
136 - BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();  
137 - sourceInfo.addRule(rule);  
138 - Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);  
139 - // 断言  
140 - assertEquals(asSet(11L, 22L), results);  
141 - }  
142 -  
143 - @Test  
144 - public void testCalculateTaskCandidateUsers_User() {  
145 - // 准备参数  
146 - BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L))  
147 - .setType(BpmTaskAssignRuleTypeEnum.USER.getType());  
148 - // mock 方法  
149 - mockGetUserMap(asSet(1L, 2L));  
150 -  
151 - // 调用  
152 - BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();  
153 - sourceInfo.addRule(rule);  
154 - Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);  
155 - // 断言  
156 - assertEquals(asSet(1L, 2L), results);  
157 - }  
158 -  
159 - @Test  
160 - public void testCalculateTaskCandidateUsers_UserGroup() {  
161 - // 准备参数  
162 - BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L))  
163 - .setType(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType());  
164 - // mock 方法  
165 - BpmUserGroupDO userGroup1 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(11L, 12L)));  
166 - BpmUserGroupDO userGroup2 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(21L, 22L)));  
167 - when(userGroupService.getUserGroupList(eq(rule.getOptions()))).thenReturn(Arrays.asList(userGroup1, userGroup2));  
168 - mockGetUserMap(asSet(11L, 12L, 21L, 22L));  
169 -  
170 - // 调用  
171 - BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();  
172 - sourceInfo.addRule(rule);  
173 - Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);  
174 - // 断言  
175 - assertEquals(asSet(11L, 12L, 21L, 22L), results);  
176 - }  
177 -  
178 - private void mockGetUserMap(Set<Long> assigneeUserIds) {  
179 - Map<Long, AdminUserRespDTO> userMap = CollectionUtils.convertMap(assigneeUserIds, id -> id,  
180 - id -> new AdminUserRespDTO().setId(id).setStatus(CommonStatusEnum.ENABLE.getStatus()));  
181 - when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);  
182 - }  
183 -  
184 - @Test  
185 - public void testCalculateTaskCandidateUsers_Script() {  
186 - // 准备参数  
187 - BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(20L, 21L))  
188 - .setType(BpmTaskAssignRuleTypeEnum.SCRIPT.getType());  
189 - // mock 方法  
190 - BpmTaskAssignScript script1 = new BpmTaskAssignScript() {  
191 -  
192 - @Override  
193 - public Set<Long> calculateTaskCandidateUsers(DelegateExecution task) {  
194 - return singleton(11L);  
195 - }  
196 -  
197 - @Override  
198 - public BpmTaskRuleScriptEnum getEnum() {  
199 - return BpmTaskRuleScriptEnum.LEADER_X1;  
200 - }  
201 - };  
202 - BpmTaskAssignScript script2 = new BpmTaskAssignScript() {  
203 -  
204 - @Override  
205 - public Set<Long> calculateTaskCandidateUsers(DelegateExecution task) {  
206 - return singleton(22L);  
207 - }  
208 -  
209 - @Override  
210 - public BpmTaskRuleScriptEnum getEnum() {  
211 - return BpmTaskRuleScriptEnum.LEADER_X2;  
212 - }  
213 - };  
214 - bpmCandidateScriptApiSourceInfoProcessor.setScripts(Arrays.asList(script1, script2));  
215 - mockGetUserMap(asSet(11L, 22L));  
216 -  
217 - // 调用  
218 - BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();  
219 - sourceInfo.addRule(rule);  
220 - Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);  
221 - // 断言  
222 - assertEquals(asSet(11L, 22L), results);  
223 - }  
224 -  
225 - @Test  
226 - public void testRemoveDisableUsers() {  
227 - // 准备参数. 1L 可以找到;2L 是禁用的;3L 找不到  
228 - Set<Long> assigneeUserIds = asSet(1L, 2L, 3L);  
229 - // mock 方法  
230 - AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)  
231 - .setStatus(CommonStatusEnum.ENABLE.getStatus()));  
232 - AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)  
233 - .setStatus(CommonStatusEnum.DISABLE.getStatus()));  
234 - Map<Long, AdminUserRespDTO> userMap = MapUtil.builder(user1.getId(), user1)  
235 - .put(user2.getId(), user2).build();  
236 - when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);  
237 -  
238 - // 调用  
239 - processorChain.removeDisableUsers(assigneeUserIds);  
240 - // 断言  
241 - assertEquals(asSet(1L), assigneeUserIds);  
242 - }  
243 -  
244 -}  
245 \ No newline at end of file 0 \ No newline at end of file
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImplTest.java deleted
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.enums.definition.BpmTaskAssignRuleTypeEnum;  
10 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;  
11 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;  
12 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl.BpmTaskAssignStartUserScript;  
13 -import cn.iocoder.yudao.module.system.api.dept.DeptApi;  
14 -import cn.iocoder.yudao.module.system.api.dept.PostApi;  
15 -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;  
16 -import cn.iocoder.yudao.module.system.api.dict.DictDataApi;  
17 -import cn.iocoder.yudao.module.system.api.permission.PermissionApi;  
18 -import cn.iocoder.yudao.module.system.api.permission.RoleApi;  
19 -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;  
20 -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;  
21 -import org.flowable.engine.delegate.DelegateExecution;  
22 -import org.junit.jupiter.api.Test;  
23 -import org.springframework.boot.test.mock.mockito.MockBean;  
24 -import org.springframework.context.annotation.Import;  
25 -  
26 -import jakarta.annotation.Resource;  
27 -import java.util.Arrays;  
28 -import java.util.List;  
29 -import java.util.Map;  
30 -import java.util.Set;  
31 -  
32 -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;  
33 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;  
34 -import static java.util.Collections.singleton;  
35 -import static org.junit.jupiter.api.Assertions.assertEquals;  
36 -import static org.mockito.ArgumentMatchers.eq;  
37 -import static org.mockito.Mockito.when;  
38 -  
39 -/**  
40 - * {@link BpmTaskAssignRuleService} 的单元测试  
41 - *  
42 - * @author 芋道源码  
43 - */  
44 -@Import({BpmTaskAssignRuleServiceImpl.class, BpmTaskAssignStartUserScript.class}) // Import 引入 BpmTaskAssignStartUserScript 目的是保证不报错  
45 -public class BpmTaskAssignRuleServiceImplTest extends BaseDbUnitTest {  
46 -  
47 - @Resource  
48 - private BpmTaskAssignRuleServiceImpl bpmTaskRuleService;  
49 -  
50 - @MockBean  
51 - private BpmUserGroupService userGroupService;  
52 - @MockBean  
53 - private DeptApi deptApi;  
54 - @MockBean  
55 - private AdminUserApi adminUserApi;  
56 - @MockBean  
57 - private PermissionApi permissionApi;  
58 - @MockBean  
59 - private RoleApi roleApi;  
60 - @MockBean  
61 - private PostApi postApi;  
62 - @MockBean  
63 - private DictDataApi dictDataApi;  
64 -  
65 - @Test  
66 - public void testCalculateTaskCandidateUsers_Role() {  
67 - // 准备参数  
68 - BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))  
69 - .setType(BpmTaskAssignRuleTypeEnum.ROLE.getType());  
70 - // mock 方法  
71 - when(permissionApi.getUserRoleIdListByRoleIds(eq(rule.getOptions())))  
72 - .thenReturn(asSet(11L, 22L));  
73 - mockGetUserMap(asSet(11L, 22L));  
74 -  
75 - // 调用  
76 - Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);  
77 - // 断言  
78 - assertEquals(asSet(11L, 22L), results);  
79 - }  
80 -  
81 - @Test  
82 - public void testCalculateTaskCandidateUsers_DeptMember() {  
83 - // 准备参数  
84 - BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))  
85 - .setType(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType());  
86 - // mock 方法  
87 - List<AdminUserRespDTO> users = CollectionUtils.convertList(asSet(11L, 22L),  
88 - id -> new AdminUserRespDTO().setId(id));  
89 - when(adminUserApi.getUserListByDeptIds(eq(rule.getOptions()))).thenReturn(users);  
90 - mockGetUserMap(asSet(11L, 22L));  
91 -  
92 - // 调用  
93 - Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);  
94 - // 断言  
95 - assertEquals(asSet(11L, 22L), results);  
96 - }  
97 -  
98 - @Test  
99 - public void testCalculateTaskCandidateUsers_DeptLeader() {  
100 - // 准备参数  
101 - BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))  
102 - .setType(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType());  
103 - // mock 方法  
104 - DeptRespDTO dept1 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(11L));  
105 - DeptRespDTO dept2 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(22L));  
106 - when(deptApi.getDeptList(eq(rule.getOptions()))).thenReturn(Arrays.asList(dept1, dept2));  
107 - mockGetUserMap(asSet(11L, 22L));  
108 -  
109 - // 调用  
110 - Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);  
111 - // 断言  
112 - assertEquals(asSet(11L, 22L), results);  
113 - }  
114 -  
115 - @Test  
116 - public void testCalculateTaskCandidateUsers_Post() {  
117 - // 准备参数  
118 - BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))  
119 - .setType(BpmTaskAssignRuleTypeEnum.POST.getType());  
120 - // mock 方法  
121 - List<AdminUserRespDTO> users = CollectionUtils.convertList(asSet(11L, 22L),  
122 - id -> new AdminUserRespDTO().setId(id));  
123 - when(adminUserApi.getUserListByPostIds(eq(rule.getOptions()))).thenReturn(users);  
124 - mockGetUserMap(asSet(11L, 22L));  
125 -  
126 - // 调用  
127 - Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);  
128 - // 断言  
129 - assertEquals(asSet(11L, 22L), results);  
130 - }  
131 -  
132 - @Test  
133 - public void testCalculateTaskCandidateUsers_User() {  
134 - // 准备参数  
135 - BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))  
136 - .setType(BpmTaskAssignRuleTypeEnum.USER.getType());  
137 - // mock 方法  
138 - mockGetUserMap(asSet(1L, 2L));  
139 -  
140 - // 调用  
141 - Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);  
142 - // 断言  
143 - assertEquals(asSet(1L, 2L), results);  
144 - }  
145 -  
146 - @Test  
147 - public void testCalculateTaskCandidateUsers_UserGroup() {  
148 - // 准备参数  
149 - BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))  
150 - .setType(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType());  
151 - // mock 方法  
152 - BpmUserGroupDO userGroup1 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(11L, 12L)));  
153 - BpmUserGroupDO userGroup2 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(21L, 22L)));  
154 - when(userGroupService.getUserGroupList(eq(rule.getOptions()))).thenReturn(Arrays.asList(userGroup1, userGroup2));  
155 - mockGetUserMap(asSet(11L, 12L, 21L, 22L));  
156 -  
157 - // 调用  
158 - Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);  
159 - // 断言  
160 - assertEquals(asSet(11L, 12L, 21L, 22L), results);  
161 - }  
162 -  
163 - @Test  
164 - public void testCalculateTaskCandidateUsers_Script() {  
165 - // 准备参数  
166 - BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(20L, 21L))  
167 - .setType(BpmTaskAssignRuleTypeEnum.SCRIPT.getType());  
168 - // mock 方法  
169 - BpmTaskAssignScript script1 = new BpmTaskAssignScript() {  
170 -  
171 - @Override  
172 - public Set<Long> calculateTaskCandidateUsers(DelegateExecution task) {  
173 - return singleton(11L);  
174 - }  
175 -  
176 - @Override  
177 - public BpmTaskRuleScriptEnum getEnum() {  
178 - return BpmTaskRuleScriptEnum.LEADER_X1;  
179 - }  
180 - };  
181 - BpmTaskAssignScript script2 = new BpmTaskAssignScript() {  
182 -  
183 - @Override  
184 - public Set<Long> calculateTaskCandidateUsers(DelegateExecution task) {  
185 - return singleton(22L);  
186 - }  
187 -  
188 - @Override  
189 - public BpmTaskRuleScriptEnum getEnum() {  
190 - return BpmTaskRuleScriptEnum.LEADER_X2;  
191 - }  
192 - };  
193 - bpmTaskRuleService.setScripts(Arrays.asList(script1, script2));  
194 - mockGetUserMap(asSet(11L, 22L));  
195 -  
196 - // 调用  
197 - Set<Long> results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);  
198 - // 断言  
199 - assertEquals(asSet(11L, 22L), results);  
200 - }  
201 -  
202 - @Test  
203 - public void testRemoveDisableUsers() {  
204 - // 准备参数. 1L 可以找到;2L 是禁用的;3L 找不到  
205 - Set<Long> assigneeUserIds = asSet(1L, 2L, 3L);  
206 - // mock 方法  
207 - AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)  
208 - .setStatus(CommonStatusEnum.ENABLE.getStatus()));  
209 - AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)  
210 - .setStatus(CommonStatusEnum.DISABLE.getStatus()));  
211 - Map<Long, AdminUserRespDTO> userMap = MapUtil.builder(user1.getId(), user1)  
212 - .put(user2.getId(), user2).build();  
213 - when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);  
214 -  
215 - // 调用  
216 - bpmTaskRuleService.removeDisableUsers(assigneeUserIds);  
217 - // 断言  
218 - assertEquals(asSet(1L), assigneeUserIds);  
219 - }  
220 -  
221 - private void mockGetUserMap(Set<Long> assigneeUserIds) {  
222 - Map<Long, AdminUserRespDTO> userMap = CollectionUtils.convertMap(assigneeUserIds, id -> id,  
223 - id -> new AdminUserRespDTO().setId(id).setStatus(CommonStatusEnum.ENABLE.getStatus()));  
224 - when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);  
225 - }  
226 -  
227 -}  
yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java deleted
1 -package cn.iocoder.yudao.framework.flowable.core;  
yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java deleted
1 -package cn.iocoder.yudao.framework.flowable;