diff --git a/pom.xml b/pom.xml
index 3a66524bc..1b5fc92c1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,7 @@
yudao-module-system
yudao-module-infra
-
+ yudao-module-bpm
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java
index c434b2577..d236d1817 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java
@@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.common.util.string;
+import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
@@ -46,6 +47,10 @@ public class StrUtils {
return Arrays.stream(longs).boxed().collect(Collectors.toList());
}
+ public static Set splitToLongSet(String value) {
+ return splitToLongSet(value, StrPool.COMMA);
+ }
+
public static Set splitToLongSet(String value, CharSequence separator) {
long[] longs = StrUtil.splitToLong(value, separator);
return Arrays.stream(longs).boxed().collect(Collectors.toSet());
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
index 646841b34..bdc3d17ce 100644
--- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
+++ b/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 {
ErrorCode MODEL_NOT_EXISTS = new ErrorCode(1_009_002_001, "流程模型不存在");
ErrorCode MODEL_KEY_VALID = new ErrorCode(1_009_002_002, "流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!");
ErrorCode MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG = new ErrorCode(1_009_002_003, "部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置");
- ErrorCode MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG = new ErrorCode(1_009_002_004, "部署流程失败," +
+ ErrorCode MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG = new ErrorCode(1_009_002_004, "部署流程失败," +
"原因:用户任务({})未配置审批人,请点击【流程设计】按钮,选择该它的【任务(审批人)】进行配置");
ErrorCode MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS = new ErrorCode(1_009_003_005, "流程定义部署失败,原因:信息未发生变化");
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java
deleted file mode 100644
index d220da746..000000000
--- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package cn.iocoder.yudao.module.bpm.enums.definition;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * BPM 任务分配规则的类型枚举
- *
- * @author 芋道源码
- */
-@Getter
-@AllArgsConstructor
-public enum BpmTaskAssignRuleTypeEnum {
-
- ROLE(10, "角色"),
- DEPT_MEMBER(20, "部门的成员"), // 包括负责人
- DEPT_LEADER(21, "部门的负责人"),
- POST(22, "岗位"),
- USER(30, "用户"),
- USER_GROUP(40, "用户组"),
- @Deprecated
- SCRIPT(50, "自定义脚本"), // 例如说,发起人所在部门的领导、发起人所在部门的领导的领导
- EXPRESS(60, "流程表达式"), // 表达式 ExpressionManager
- ;
-
- /**
- * 类型
- */
- private final Integer type;
- /**
- * 描述
- */
- private final String desc;
-
-}
diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java
deleted file mode 100644
index 7fc0e3b8b..000000000
--- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package cn.iocoder.yudao.module.bpm.enums.definition;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * BPM 任务规则的脚本枚举
- * 目前暂时通过 TODO 芋艿:硬编码,未来可以考虑 Groovy 动态脚本的方式
- *
- * @author 芋道源码
- */
-@Getter
-@AllArgsConstructor
-public enum BpmTaskRuleScriptEnum {
-
- START_USER(10L, "流程发起人"),
-
- LEADER_X1(20L, "流程发起人的一级领导"),
- LEADER_X2(21L, "流程发起人的二级领导");
-
- /**
- * 脚本编号
- */
- private final Long id;
- /**
- * 脚本描述
- */
- private final String desc;
-
-}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmCandidateProcessorConfiguration.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmCandidateProcessorConfiguration.java
deleted file mode 100644
index cff03488b..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmCandidateProcessorConfiguration.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package cn.iocoder.yudao.module.bpm.framework.bpm.config;
-
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
-import cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor.*;
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-// TODO @芋艿:Candidate 相关还在完善中,用户可以暂时忽略,仅 yudao 开发的同学需要关注~计划是把 Candidate 和 Assign 融合成一套
-/**
- * BPM 通用的 Configuration 配置类,提供给 Activiti 和 Flowable
- * @author kyle
- */
-@Configuration(proxyBeanMethods = false)
-public class BpmCandidateProcessorConfiguration {
- @Bean
- public BpmCandidateAdminUserApiSourceInfoProcessor bpmCandidateAdminUserApiSourceInfoProcessor() {
- return new BpmCandidateAdminUserApiSourceInfoProcessor();
- }
-
- @Bean
- public BpmCandidateDeptApiSourceInfoProcessor bpmCandidateDeptApiSourceInfoProcessor() {
- return new BpmCandidateDeptApiSourceInfoProcessor();
- }
-
- @Bean
- public BpmCandidatePostApiSourceInfoProcessor bpmCandidatePostApiSourceInfoProcessor() {
- return new BpmCandidatePostApiSourceInfoProcessor();
- }
-
- @Bean
- public BpmCandidateRoleApiSourceInfoProcessor bpmCandidateRoleApiSourceInfoProcessor() {
- return new BpmCandidateRoleApiSourceInfoProcessor();
- }
-
- @Bean
- public BpmCandidateUserGroupApiSourceInfoProcessor bpmCandidateUserGroupApiSourceInfoProcessor() {
- return new BpmCandidateUserGroupApiSourceInfoProcessor();
- }
-
- /**
- * 可以自己定制脚本,然后通过这里设置到处理器里面去
- * @param scriptsOp 脚本包装对象
- * @return
- */
- @Bean
- public BpmCandidateScriptApiSourceInfoProcessor bpmCandidateScriptApiSourceInfoProcessor(ObjectProvider scriptsOp) {
- BpmCandidateScriptApiSourceInfoProcessor bpmCandidateScriptApiSourceInfoProcessor = new BpmCandidateScriptApiSourceInfoProcessor();
- bpmCandidateScriptApiSourceInfoProcessor.setScripts(scriptsOp);
- return bpmCandidateScriptApiSourceInfoProcessor;
- }
-}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java
index c048d9c73..9248da552 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java
+++ b/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;
import cn.hutool.core.collection.ListUtil;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.BpmActivityBehaviorFactory;
-import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
@@ -10,6 +12,8 @@ import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import java.util.List;
+
/**
* BPM 模块的 Flowable 配置类
*
@@ -36,11 +40,20 @@ public class BpmFlowableConfiguration {
};
}
+ // =========== 审批人相关的 Bean ==========
+
@Bean
- public BpmActivityBehaviorFactory bpmActivityBehaviorFactory(BpmTaskAssignRuleService taskRuleService) {
+ public BpmActivityBehaviorFactory bpmActivityBehaviorFactory(BpmTaskCandidateInvoker bpmTaskCandidateInvoker) {
BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory();
- bpmActivityBehaviorFactory.setBpmTaskRuleService(taskRuleService);
+ bpmActivityBehaviorFactory.setTaskCandidateInvoker(bpmTaskCandidateInvoker);
return bpmActivityBehaviorFactory;
}
-}
+ @Bean
+ @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") // adminUserApi 可以注入成功
+ public BpmTaskCandidateInvoker bpmTaskCandidateInvoker(List strategyList,
+ AdminUserApi adminUserApi) {
+ return new BpmTaskCandidateInvoker(strategyList, adminUserApi);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java
index dced1c5bd..e9f1f32d7 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java
@@ -1,10 +1,7 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
-import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
import lombok.Setter;
-import lombok.ToString;
import org.flowable.bpmn.model.Activity;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
@@ -18,25 +15,22 @@ import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFacto
*
* @author 芋道源码
*/
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
+@Setter
public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
- @Setter
- private BpmTaskAssignRuleService bpmTaskRuleService;
+ private BpmTaskCandidateInvoker taskCandidateInvoker;
@Override
public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) {
return new BpmUserTaskActivityBehavior(userTask)
- .setBpmTaskRuleService(bpmTaskRuleService);
+ .setTaskCandidateInvoker(taskCandidateInvoker);
}
@Override
public ParallelMultiInstanceBehavior createParallelMultiInstanceBehavior(Activity activity,
AbstractBpmnActivityBehavior innerActivityBehavior) {
return new BpmParallelMultiInstanceBehavior(activity, innerActivityBehavior)
- .setBpmTaskRuleService(bpmTaskRuleService);
+ .setTaskCandidateInvoker(taskCandidateInvoker);
}
// TODO @ke:SequentialMultiInstanceBehavior 这个抽空也可以看看
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java
index 0b60faa06..ed51b23fa 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java
@@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
-import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.Activity;
@@ -23,7 +23,7 @@ import java.util.Set;
public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehavior {
@Setter
- private BpmTaskAssignRuleService bpmTaskRuleService;
+ private BpmTaskCandidateInvoker taskCandidateInvoker;
public BpmParallelMultiInstanceBehavior(Activity activity,
AbstractBpmnActivityBehavior innerActivityBehavior) {
@@ -50,7 +50,7 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav
super.collectionElementVariable = FlowableUtils.formatCollectionElementVariable(execution.getCurrentActivityId());
// 第二步,获取任务的所有处理人
- Set assigneeUserIds = bpmTaskRuleService.calculateTaskCandidateUsers(execution);
+ Set assigneeUserIds = taskCandidateInvoker.calculateUsers(execution);
execution.setVariable(super.collectionVariable, assigneeUserIds);
return assigneeUserIds.size();
}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
index aeda4d52c..de17502bf 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
+++ b/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;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.RandomUtil;
-import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.UserTask;
@@ -29,7 +29,7 @@ import java.util.Set;
public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
@Setter
- private BpmTaskAssignRuleService bpmTaskRuleService;
+ private BpmTaskCandidateInvoker taskCandidateInvoker;
public BpmUserTaskActivityBehavior(UserTask userTask) {
super(userTask);
@@ -54,7 +54,7 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
// 情况二,如果非多实例的任务,则计算任务处理人
// 第一步,先计算可处理该任务的处理人们
- Set candidateUserIds = bpmTaskRuleService.calculateTaskCandidateUsers(execution);
+ Set candidateUserIds = taskCandidateInvoker.calculateUsers(execution);
// 第二步,后随机选择一个任务的处理人
// 疑问:为什么一定要选择一个任务处理人?
// 解答:项目对 bpm 的任务是责任到人,所以每个任务有且仅有一个处理人。
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java
deleted file mode 100644
index c39059048..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script;
-
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
-import org.flowable.engine.delegate.DelegateExecution;
-
-import java.util.Set;
-
-/**
- * Bpm 任务分配的自定义 Script 脚本
- * 使用场景:
- * 1. 设置审批人为发起人
- * 2. 设置审批人为发起人的 Leader
- * 3. 甚至审批人为发起人的 Leader 的 Leader
- *
- * @author 芋道源码
- */
-@Deprecated
-public interface BpmTaskAssignScript {
-
- /**
- * 基于执行任务,获得任务的候选用户们
- *
- * @param execution 执行任务
- * @return 候选人用户的编号数组
- */
- Set calculateTaskCandidateUsers(DelegateExecution execution);
-
- /**
- * 获得枚举值
- *
- * @return 枚举值
- */
- BpmTaskRuleScriptEnum getEnum();
-
-}
-
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
deleted file mode 100644
index 9c31970f7..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
-
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
-import org.flowable.engine.delegate.DelegateExecution;
-import org.springframework.stereotype.Component;
-
-import java.util.Set;
-
-/**
- * 分配给发起人的一级 Leader 审批的 Script 实现类
- *
- * @author 芋道源码
- */
-@Deprecated
-@Component
-public class BpmTaskAssignLeaderX1Script extends BpmTaskAssignLeaderAbstractScript {
-
- @Override
- public Set calculateTaskCandidateUsers(DelegateExecution execution) {
- return calculateTaskCandidateUsers(execution, 1);
- }
-
- @Override
- public BpmTaskRuleScriptEnum getEnum() {
- return BpmTaskRuleScriptEnum.LEADER_X1;
- }
-
-}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
deleted file mode 100644
index 935545100..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
-
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
-import org.flowable.engine.delegate.DelegateExecution;
-import org.springframework.stereotype.Component;
-
-import java.util.Set;
-
-/**
- * 分配给发起人的二级 Leader 审批的 Script 实现类
- *
- * @author 芋道源码
- */
-@Deprecated
-@Component
-public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript {
-
- @Override
- public Set calculateTaskCandidateUsers(DelegateExecution execution) {
- return calculateTaskCandidateUsers(execution, 2);
- }
-
- @Override
- public BpmTaskRuleScriptEnum getEnum() {
- return BpmTaskRuleScriptEnum.LEADER_X2;
- }
-
-}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java
new file mode 100644
index 000000000..d1ba65df2
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java
@@ -0,0 +1,134 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import com.google.common.annotations.VisibleForTesting;
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.bpmn.model.FlowElement;
+import org.flowable.bpmn.model.UserTask;
+import org.flowable.engine.delegate.DelegateExecution;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER;
+
+/**
+ * {@link BpmTaskCandidateStrategy} 的调用者,用于调用对应的策略,实现任务的候选人的计算
+ *
+ * @author 芋道源码
+ */
+@Slf4j
+public class BpmTaskCandidateInvoker {
+
+ private final Map strategyMap = new HashMap<>();
+
+ private final AdminUserApi adminUserApi;
+
+ public BpmTaskCandidateInvoker(List strategyList,
+ AdminUserApi adminUserApi) {
+ strategyList.forEach(strategy -> {
+ BpmTaskCandidateStrategy oldStrategy = strategyMap.put(strategy.getStrategy(), strategy);
+ Assert.isNull(oldStrategy, "策略(%s) 重复", strategy.getStrategy());
+ });
+ this.adminUserApi = adminUserApi;
+ }
+
+ /**
+ * 校验流程模型的任务分配规则全部都配置了
+ * 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!
+ *
+ * @param bpmnBytes BPMN XML
+ */
+ public void validateBpmnConfig(byte[] bpmnBytes) {
+ BpmnModel bpmnModel = BpmnModelUtils.getBpmnModel(bpmnBytes);
+ assert bpmnModel != null;
+ List userTaskList = BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class);
+ // 遍历所有的 UserTask,校验审批人配置
+ userTaskList.forEach(userTask -> {
+ // 1. 非空校验
+ Integer strategy = parseCandidateStrategy(userTask);
+ String param = parseCandidateParam(userTask);
+ if (strategy == null || StrUtil.isBlank(param)) {
+ throw exception(MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG, userTask.getName());
+ }
+ // 2. 具体策略校验
+ getCandidateStrategy(strategy).validateParam(param);
+ });
+ }
+
+ /**
+ * 计算任务的候选人
+ *
+ * @param execution 执行任务
+ * @return 用户编号集合
+ */
+ public Set calculateUsers(DelegateExecution execution) {
+ // TODO 芋艿:这里需要重构
+// // 1. 先从提前选好的审批人中获取
+// List assignee = processInstanceService.getAssigneeByProcessInstanceIdAndTaskDefinitionKey(
+// execution.getProcessInstanceId(), execution.getCurrentActivityId());
+// if (CollUtil.isNotEmpty(assignee)) {
+// // TODO @hai:new HashSet 即可
+// return convertSet(assignee, Function.identity());
+// }
+ Integer strategy = parseCandidateStrategy(execution.getCurrentFlowElement());
+ String param = parseCandidateParam(execution.getCurrentFlowElement());
+ // 1.1 计算任务的候选人
+ Set userIds = getCandidateStrategy(strategy).calculateUsers(execution, param);
+ // 1.2 移除被禁用的用户
+ removeDisableUsers(userIds);
+
+ // 2. 校验是否有候选人
+ if (CollUtil.isEmpty(userIds)) {
+ log.error("[calculateUsers][流程任务({}/{}/{}) 任务规则({}/{}) 找不到候选人]", execution.getId(),
+ execution.getProcessDefinitionId(), execution.getCurrentActivityId(), strategy, param);
+ throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER);
+ }
+ return userIds;
+ }
+
+ @VisibleForTesting
+ void removeDisableUsers(Set assigneeUserIds) {
+ if (CollUtil.isEmpty(assigneeUserIds)) {
+ return;
+ }
+ Map userMap = adminUserApi.getUserMap(assigneeUserIds);
+ assigneeUserIds.removeIf(id -> {
+ AdminUserRespDTO user = userMap.get(id);
+ return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus());
+ });
+ }
+
+ private static Integer parseCandidateStrategy(FlowElement userTask) {
+ return NumberUtils.parseInt(userTask.getAttributeValue(
+ BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY));
+ }
+
+ private static String parseCandidateParam(FlowElement userTask) {
+ return userTask.getAttributeValue(
+ BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM);
+ }
+
+ private BpmTaskCandidateStrategy getCandidateStrategy(Integer strategy) {
+ BpmTaskCandidateStrategyEnum strategyEnum = BpmTaskCandidateStrategyEnum.valueOf(strategy);
+ Assert.notNull(strategyEnum, "策略(%s) 不存在", strategy);
+ BpmTaskCandidateStrategy strategyObj = strategyMap.get(strategyEnum);
+ Assert.notNull(strategyObj, "策略(%s) 不存在", strategy);
+ return strategyObj;
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateStrategy.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateStrategy.java
new file mode 100644
index 000000000..a5c5c9b4d
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateStrategy.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate;
+
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
+import org.flowable.engine.delegate.DelegateExecution;
+
+import java.util.Set;
+
+/**
+ * BPM 任务的候选人的策略接口
+ *
+ * 例如说:分配审批人
+ *
+ * @author 芋道源码
+ */
+public interface BpmTaskCandidateStrategy {
+
+ /**
+ * 对应策略
+ *
+ * @return 策略
+ */
+ BpmTaskCandidateStrategyEnum getStrategy();
+
+ /**
+ * 校验参数
+ *
+ * @param param 参数
+ */
+ void validateParam(String param);
+
+ /**
+ * 基于执行任务,获得任务的候选用户们
+ *
+ * @param execution 执行任务
+ * @return 用户编号集合
+ */
+ Set calculateUsers(DelegateExecution execution, String param);
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpression.java
similarity index 81%
rename from yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java
rename to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpression.java
index 22ef4cde7..cb5306548 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpression.java
@@ -1,7 +1,6 @@
-package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.expression;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
@@ -9,7 +8,7 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.runtime.ProcessInstance;
-import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import jakarta.annotation.Resource;
@@ -19,23 +18,23 @@ import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static java.util.Collections.emptySet;
/**
- * 分配给发起人的 Leader 审批的 Script 实现类
- * 目前 Leader 的定义是,
+ * 分配给发起人的 Leader 审批的 Expression 流程表达式
+ * 目前 Leader 的定义是,发起人所在部门的 Leader
*
* @author 芋道源码
*/
-@Deprecated
-public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript {
+@Component
+public class BpmTaskAssignLeaderExpression {
@Resource
private AdminUserApi adminUserApi;
@Resource
private DeptApi deptApi;
+
@Resource
- @Lazy // 解决循环依赖
private BpmProcessInstanceService bpmProcessInstanceService;
- protected Set calculateTaskCandidateUsers(DelegateExecution execution, int level) {
+ protected Set calculateUsers(DelegateExecution execution, int level) {
Assert.isTrue(level > 0, "level 必须大于 0");
// 获得发起人
ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId());
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignStartUserExpression.java
similarity index 54%
rename from yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java
rename to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignStartUserExpression.java
index 0329aec6a..c4d8811b4 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignStartUserExpression.java
@@ -1,41 +1,30 @@
-package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.expression;
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
+import jakarta.annotation.Resource;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.runtime.ProcessInstance;
-import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
-import jakarta.annotation.Resource;
import java.util.Set;
/**
- * 分配给发起人审批的 Script 实现类
+ * 分配给发起人审批的 Expression 流程表达式
*
* @author 芋道源码
*/
-@Deprecated
@Component
-public class BpmTaskAssignStartUserScript implements BpmTaskAssignScript {
+public class BpmTaskAssignStartUserExpression {
@Resource
- @Lazy // 解决循环依赖
private BpmProcessInstanceService bpmProcessInstanceService;
- @Override
- public Set calculateTaskCandidateUsers(DelegateExecution execution) {
+ public Set calculateUsers(DelegateExecution execution) {
ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId());
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
return SetUtils.asSet(startUserId);
}
- @Override
- public BpmTaskRuleScriptEnum getEnum() {
- return BpmTaskRuleScriptEnum.START_USER;
- }
-
}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptLeaderStrategy.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptLeaderStrategy.java
new file mode 100644
index 000000000..485552f91
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptLeaderStrategy.java
@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.common.util.string.StrUtils;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import jakarta.annotation.Resource;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+/**
+ * 部门的负责人 {@link BpmTaskCandidateStrategy} 实现类
+ *
+ * @author kyle
+ */
+@Component
+public class BpmTaskCandidateDeptLeaderStrategy implements BpmTaskCandidateStrategy {
+
+ @Resource
+ private DeptApi deptApi;
+
+ @Override
+ public BpmTaskCandidateStrategyEnum getStrategy() {
+ return BpmTaskCandidateStrategyEnum.DEPT_LEADER;
+ }
+
+ @Override
+ public void validateParam(String param) {
+ Set deptIds = StrUtils.splitToLongSet(param);
+ deptApi.validateDeptList(deptIds);
+ }
+
+ @Override
+ public Set calculateUsers(DelegateExecution execution, String param) {
+ Set deptIds = StrUtils.splitToLongSet(param);
+ List depts = deptApi.getDeptList(deptIds);
+ return convertSet(depts, DeptRespDTO::getLeaderUserId);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptMemberStrategy.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptMemberStrategy.java
new file mode 100644
index 000000000..f60b1cc8b
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptMemberStrategy.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.common.util.string.StrUtils;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import jakarta.annotation.Resource;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+/**
+ * 部门的成员 {@link BpmTaskCandidateStrategy} 实现类
+ *
+ * @author kyle
+ */
+@Component
+public class BpmTaskCandidateDeptMemberStrategy implements BpmTaskCandidateStrategy {
+
+ @Resource
+ private DeptApi deptApi;
+ @Resource
+ private AdminUserApi adminUserApi;
+
+ @Override
+ public BpmTaskCandidateStrategyEnum getStrategy() {
+ return BpmTaskCandidateStrategyEnum.DEPT_MEMBER;
+ }
+
+ @Override
+ public void validateParam(String param) {
+ Set deptIds = StrUtils.splitToLongSet(param);
+ deptApi.validateDeptList(deptIds);
+ }
+
+ @Override
+ public Set calculateUsers(DelegateExecution execution, String param) {
+ Set deptIds = StrUtils.splitToLongSet(param);
+ List users = adminUserApi.getUserListByDeptIds(deptIds);
+ return convertSet(users, AdminUserRespDTO::getId);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateExpressionStrategy.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateExpressionStrategy.java
new file mode 100644
index 000000000..f8be5fe3e
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateExpressionStrategy.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
+import org.dromara.hutool.core.convert.Convert;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.springframework.stereotype.Component;
+
+import java.util.Set;
+
+/**
+ * 流程表达式 {@link BpmTaskCandidateStrategy} 实现类
+ *
+ * @author 芋道源码
+ */
+@Component
+public class BpmTaskCandidateExpressionStrategy implements BpmTaskCandidateStrategy {
+
+ @Override
+ public BpmTaskCandidateStrategyEnum getStrategy() {
+ return BpmTaskCandidateStrategyEnum.EXPRESSION;
+ }
+
+ @Override
+ public void validateParam(String param) {
+ // do nothing 因为它基本做不了校验
+ }
+
+ @Override
+ public Set calculateUsers(DelegateExecution execution, String param) {
+ Object result = FlowableUtils.getExpressionValue(execution, param);
+ return Convert.toSet(Long.class, result);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateGroupStrategy.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateGroupStrategy.java
new file mode 100644
index 000000000..b8fa00f84
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateGroupStrategy.java
@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.common.util.string.StrUtils;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
+import jakarta.annotation.Resource;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
+
+/**
+ * 用户组 {@link BpmTaskCandidateStrategy} 实现类
+ *
+ * @author kyle
+ */
+@Component
+public class BpmTaskCandidateGroupStrategy implements BpmTaskCandidateStrategy {
+
+ @Resource
+ private BpmUserGroupService userGroupService;
+
+ @Override
+ public BpmTaskCandidateStrategyEnum getStrategy() {
+ return BpmTaskCandidateStrategyEnum.USER_GROUP;
+ }
+
+ @Override
+ public void validateParam(String param) {
+ Set groupIds = StrUtils.splitToLongSet(param);
+ userGroupService.getUserGroupList(groupIds);
+ }
+
+ @Override
+ public Set calculateUsers(DelegateExecution execution, String param) {
+ Set groupIds = StrUtils.splitToLongSet(param);
+ List groups = userGroupService.getUserGroupList(groupIds);
+ return convertSetByFlatMap(groups, BpmUserGroupDO::getMemberUserIds, Collection::stream);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidatePostStrategy.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidatePostStrategy.java
new file mode 100644
index 000000000..3f2ae58f1
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidatePostStrategy.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.common.util.string.StrUtils;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
+import cn.iocoder.yudao.module.system.api.dept.PostApi;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import jakarta.annotation.Resource;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+/**
+ * 岗位 {@link BpmTaskCandidateStrategy} 实现类
+ *
+ * @author kyle
+ */
+@Component
+public class BpmTaskCandidatePostStrategy implements BpmTaskCandidateStrategy {
+
+ @Resource
+ private PostApi postApi;
+ @Resource
+ private AdminUserApi adminUserApi;
+
+ @Override
+ public BpmTaskCandidateStrategyEnum getStrategy() {
+ return BpmTaskCandidateStrategyEnum.POST;
+ }
+
+ @Override
+ public void validateParam(String param) {
+ Set postIds = StrUtils.splitToLongSet(param);
+ postApi.validPostList(postIds);
+ }
+
+ @Override
+ public Set calculateUsers(DelegateExecution execution, String param) {
+ Set postIds = StrUtils.splitToLongSet(param);
+ List users = adminUserApi.getUserListByPostIds(postIds);
+ return convertSet(users, AdminUserRespDTO::getId);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateRoleStrategy.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateRoleStrategy.java
new file mode 100644
index 000000000..0dd178626
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateRoleStrategy.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.common.util.string.StrUtils;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
+import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
+import cn.iocoder.yudao.module.system.api.permission.RoleApi;
+import jakarta.annotation.Resource;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.springframework.stereotype.Component;
+
+import java.util.Set;
+
+/**
+ * 角色 {@link BpmTaskCandidateStrategy} 实现类
+ *
+ * @author kyle
+ */
+@Component
+public class BpmTaskCandidateRoleStrategy implements BpmTaskCandidateStrategy {
+
+ @Resource
+ private RoleApi roleApi;
+ @Resource
+ private PermissionApi permissionApi;
+
+ @Override
+ public BpmTaskCandidateStrategyEnum getStrategy() {
+ return BpmTaskCandidateStrategyEnum.ROLE;
+ }
+
+ @Override
+ public void validateParam(String param) {
+ Set roleIds = StrUtils.splitToLongSet(param);
+ roleApi.validRoleList(roleIds);
+ }
+
+ @Override
+ public Set calculateUsers(DelegateExecution execution, String param) {
+ Set roleIds = StrUtils.splitToLongSet(param);
+ return permissionApi.getUserRoleIdListByRoleIds(roleIds);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateUserStrategy.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateUserStrategy.java
new file mode 100644
index 000000000..390e4903a
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateUserStrategy.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.common.util.string.StrUtils;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import jakarta.annotation.Resource;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.springframework.stereotype.Component;
+
+import java.util.Set;
+
+/**
+ * 用户 {@link BpmTaskCandidateStrategy} 实现类
+ *
+ * @author kyle
+ */
+@Component
+public class BpmTaskCandidateUserStrategy implements BpmTaskCandidateStrategy {
+
+ @Resource
+ private AdminUserApi adminUserApi;
+
+ @Override
+ public BpmTaskCandidateStrategyEnum getStrategy() {
+ return BpmTaskCandidateStrategyEnum.USER;
+ }
+
+ @Override
+ public void validateParam(String param) {
+ adminUserApi.validateUserList(StrUtils.splitToLongSet(param));
+ }
+
+ @Override
+ public Set calculateUsers(DelegateExecution execution, String param) {
+ return StrUtils.splitToLongSet(param);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmTaskCandidateStrategyEnum.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmTaskCandidateStrategyEnum.java
new file mode 100644
index 000000000..0c3199821
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmTaskCandidateStrategyEnum.java
@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.enums;
+
+import cn.hutool.core.util.ArrayUtil;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * BPM 任务的候选人策略枚举
+ *
+ * 例如说:分配给指定人审批
+ *
+ * @author 芋道源码
+ */
+@Getter
+@AllArgsConstructor
+public enum BpmTaskCandidateStrategyEnum {
+
+ ROLE(10, "角色"),
+ DEPT_MEMBER(20, "部门的成员"), // 包括负责人
+ DEPT_LEADER(21, "部门的负责人"),
+ POST(22, "岗位"),
+ USER(30, "用户"),
+ USER_GROUP(40, "用户组"),
+ EXPRESSION(60, "流程表达式"), // 表达式 ExpressionManager
+ ;
+
+ /**
+ * 类型
+ */
+ private final Integer strategy;
+ /**
+ * 描述
+ */
+ private final String description;
+
+ public static BpmTaskCandidateStrategyEnum valueOf(Integer strategy) {
+ return ArrayUtil.firstMatch(o -> o.getStrategy().equals(strategy), values());
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java
new file mode 100644
index 000000000..c8fefd55b
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.enums;
+
+/**
+ * 流程常量信息
+ */
+public interface BpmnModelConstants {
+
+ String BPMN_FILE_SUFFIX = ".bpmn";
+
+ /**
+ * BPMN 中的命名空间
+ */
+ String NAMESPACE = "http://flowable.org/bpmn";
+
+ /**
+ * BPMN UserTask 的扩展属性,用于标记候选人策略
+ */
+ String USER_TASK_CANDIDATE_STRATEGY = "candidateStrategy";
+ /**
+ * BPMN UserTask 的扩展属性,用于标记候选人参数
+ */
+ String USER_TASK_CANDIDATE_PARAM = "candidateParam";
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java
deleted file mode 100644
index 0c5f099d6..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.candidate;
-
-import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * 获取候选人信息
- */
-@AllArgsConstructor
-@NoArgsConstructor
-@Data
-public class BpmCandidateSourceInfo {
- @Schema(description = "当前任务ID")
- @NotNull
- private String taskId;
- /**
- * 通过这些规则,生成最终需要生成的用户
- */
- @Schema(description = "当前任务预选规则")
- @NotEmpty(message = "不允许空规则")
- private Set rules;
-
- @Schema(description = "发起抄送的用户")
- private String creator;
-
- @Schema(description = "抄送原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "请帮忙审查下!")
- @NotEmpty(message = "抄送原因不能为空")
- private String reason;
-
- public void addRule(BpmTaskCandidateRuleVO vo) {
- assert vo != null;
- if (rules == null) {
- rules = new HashSet<>();
- }
- rules.add(vo);
- }
-}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessor.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessor.java
deleted file mode 100644
index 0fe741c20..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessor.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.candidate;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
-import org.flowable.engine.delegate.DelegateExecution;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-public interface BpmCandidateSourceInfoProcessor {
- /**
- * 获取该处理器支持的类型
- * 来自 {@link BpmTaskAssignRuleTypeEnum}
- *
- * @return
- */
- Set getSupportedTypes();
-
- /**
- * 对规则和人员做校验
- *
- * @param type 规则
- * @param options 人员id
- */
- void validRuleOptions(Integer type, Set options);
-
- /**
- * 默认的处理
- * 如果想去操作所有的规则,则可以覆盖此方法
- *
- * @param request 原始请求
- * @param delegateExecution 审批过程中的对象
- * @return 必须包含的是用户ID,而不是其他的ID
- * @throws Exception
- */
- default Set process(BpmCandidateSourceInfo request, DelegateExecution delegateExecution) throws Exception {
- Set rules = request.getRules();
- Set results = new HashSet<>();
- for (BpmTaskCandidateRuleVO rule : rules) {
- // 每个处理器都有机会处理自己支持的事件
- if (CollUtil.contains(getSupportedTypes(), rule.getType())) {
- results.addAll(doProcess(request, rule, delegateExecution));
- }
- }
- return results;
- }
-
- default Set doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {
- return Collections.emptySet();
- }
-}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessorChain.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessorChain.java
deleted file mode 100644
index dafc0835a..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessorChain.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.candidate;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.collection.ListUtil;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;
-import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
-import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
-import org.flowable.engine.delegate.DelegateExecution;
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.stereotype.Service;
-
-import jakarta.annotation.Resource;
-import java.util.*;
-
-@Service
-public class BpmCandidateSourceInfoProcessorChain {
-
- // 保存处理节点
-
- private List processorList;
- @Resource
- private AdminUserApi adminUserApi;
-
- /**
- * 可添加其他处理器
- *
- * @param processorOp
- * @return
- */
- @Resource
- // 动态扩展处理节点
- public BpmCandidateSourceInfoProcessorChain addProcessor(ObjectProvider processorOp) {
- List processor = ListUtil.toList(processorOp.iterator());
- if (null == processorList) {
- processorList = new ArrayList<>(processor.size());
- }
- processorList.addAll(processor);
- return this;
- }
-
- // 获取处理器处理
- public Set process(BpmCandidateSourceInfo sourceInfo, DelegateExecution execution) throws Exception {
- // Verify our parameters
- if (sourceInfo == null) {
- throw new IllegalArgumentException();
- }
- for (BpmCandidateSourceInfoProcessor processor : processorList) {
- try {
- for (BpmTaskCandidateRuleVO vo : sourceInfo.getRules()) {
- if (CollUtil.contains(processor.getSupportedTypes(), vo.getType())) {
- processor.validRuleOptions(vo.getType(), vo.getOptions());
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- throw e;
- }
- }
- Set saveResult = Collections.emptySet();
- Exception saveException = null;
- for (BpmCandidateSourceInfoProcessor processor : processorList) {
- try {
- saveResult = processor.process(sourceInfo, execution);
- if (CollUtil.isNotEmpty(saveResult)) {
- removeDisableUsers(saveResult);
- break;
- }
- } catch (Exception e) {
- saveException = e;
- break;
- }
- }
- // Return the exception or result state from the last execute()
- if ((saveException != null)) {
- throw saveException;
- } else {
- return (saveResult);
- }
- }
-
- public Set calculateTaskCandidateUsers(DelegateExecution execution, BpmCandidateSourceInfo sourceInfo) {
- Set results = Collections.emptySet();
- try {
- results = process(sourceInfo, execution);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return results;
- }
-
- /**
- * 移除禁用用户
- *
- * @param assigneeUserIds
- */
- public void removeDisableUsers(Set assigneeUserIds) {
- if (CollUtil.isEmpty(assigneeUserIds)) {
- return;
- }
- Map userMap = adminUserApi.getUserMap(assigneeUserIds);
- assigneeUserIds.removeIf(id -> {
- AdminUserRespDTO user = userMap.get(id);
- return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus());
- });
- }
-}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateAdminUserApiSourceInfoProcessor.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateAdminUserApiSourceInfoProcessor.java
deleted file mode 100644
index 536b3eec2..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateAdminUserApiSourceInfoProcessor.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor;
-
-import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
-import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor;
-import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
-import org.flowable.engine.delegate.DelegateExecution;
-
-import jakarta.annotation.Resource;
-import java.util.Set;
-
-public class BpmCandidateAdminUserApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor {
- @Resource
- private AdminUserApi api;
-
- @Override
- public Set getSupportedTypes() {
- return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.USER.getType());
- }
-
- @Override
- public void validRuleOptions(Integer type, Set options) {
- api.validateUserList(options);
- }
-
- @Override
- public Set doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {
- return rule.getOptions();
- }
-}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateDeptApiSourceInfoProcessor.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateDeptApiSourceInfoProcessor.java
deleted file mode 100644
index 6fcfa23fd..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateDeptApiSourceInfoProcessor.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor;
-
-import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
-import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor;
-import cn.iocoder.yudao.module.system.api.dept.DeptApi;
-import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
-import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
-import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
-import org.flowable.engine.delegate.DelegateExecution;
-
-import jakarta.annotation.Resource;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
-
-public class BpmCandidateDeptApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor {
- @Resource
- private DeptApi api;
- @Resource
- private AdminUserApi adminUserApi;
-
- @Override
- public Set getSupportedTypes() {
- return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(),
- BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType());
- }
-
- @Override
- public void validRuleOptions(Integer type, Set options) {
- api.validateDeptList(options);
- }
-
- @Override
- public Set doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {
- if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), rule.getType())) {
- List users = adminUserApi.getUserListByDeptIds(rule.getOptions());
- return convertSet(users, AdminUserRespDTO::getId);
- } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), rule.getType())) {
- List depts = api.getDeptList(rule.getOptions());
- return convertSet(depts, DeptRespDTO::getLeaderUserId);
- }
- return Collections.emptySet();
- }
-}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidatePostApiSourceInfoProcessor.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidatePostApiSourceInfoProcessor.java
deleted file mode 100644
index f924d87ef..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidatePostApiSourceInfoProcessor.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor;
-
-import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
-import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor;
-import cn.iocoder.yudao.module.system.api.dept.PostApi;
-import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
-import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
-import org.flowable.engine.delegate.DelegateExecution;
-
-import jakarta.annotation.Resource;
-import java.util.List;
-import java.util.Set;
-
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
-
-public class BpmCandidatePostApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor {
- @Resource
- private PostApi api;
- @Resource
- private AdminUserApi adminUserApi;
-
- @Override
- public Set getSupportedTypes() {
- return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.POST.getType());
- }
-
- @Override
- public void validRuleOptions(Integer type, Set options) {
- api.validPostList(options);
- }
-
- @Override
- public Set doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {
- List users = adminUserApi.getUserListByPostIds(rule.getOptions());
- return convertSet(users, AdminUserRespDTO::getId);
- }
-}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateRoleApiSourceInfoProcessor.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateRoleApiSourceInfoProcessor.java
deleted file mode 100644
index f3ba5b92b..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateRoleApiSourceInfoProcessor.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor;
-
-import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
-import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor;
-import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
-import cn.iocoder.yudao.module.system.api.permission.RoleApi;
-import org.flowable.engine.delegate.DelegateExecution;
-
-import jakarta.annotation.Resource;
-import java.util.Set;
-
-public class BpmCandidateRoleApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor {
- @Resource
- private RoleApi api;
-
- @Resource
- private PermissionApi permissionApi;
-
- @Override
- public Set getSupportedTypes() {
- return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.ROLE.getType());
- }
-
- @Override
- public void validRuleOptions(Integer type, Set options) {
- api.validRoleList(options);
- }
-
- @Override
- public Set doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {
- return permissionApi.getUserRoleIdListByRoleIds(rule.getOptions());
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateScriptApiSourceInfoProcessor.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateScriptApiSourceInfoProcessor.java
deleted file mode 100644
index 4bf25694d..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateScriptApiSourceInfoProcessor.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
-import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;
-import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor;
-import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
-import org.flowable.engine.delegate.DelegateExecution;
-import org.springframework.beans.factory.ObjectProvider;
-
-import jakarta.annotation.Resource;
-import java.util.*;
-import java.util.stream.Collectors;
-
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
-import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS;
-
-public class BpmCandidateScriptApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor {
- @Resource
- private DictDataApi dictDataApi;
-
- /**
- * 任务分配脚本
- */
- private Map scriptMap = Collections.emptyMap();
-
- public void setScripts(ObjectProvider scriptsOp) {
- List scripts = scriptsOp.orderedStream().collect(Collectors.toList());
- setScripts(scripts);
- }
-
- public void setScripts(List scripts) {
- this.scriptMap = convertMap(scripts, script -> script.getEnum().getId());
- }
-
- @Override
- public Set getSupportedTypes() {
- return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.SCRIPT.getType());
- }
-
- @Override
- public void validRuleOptions(Integer type, Set options) {
- dictDataApi.validateDictDataList(DictTypeConstants.TASK_ASSIGN_SCRIPT,
- CollectionUtils.convertSet(options, String::valueOf));
- }
-
- @Override
- public Set doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {
- return calculateTaskCandidateUsersByScript(delegateExecution, rule.getOptions());
- }
-
- private Set calculateTaskCandidateUsersByScript(DelegateExecution execution, Set options) {
- // 获得对应的脚本
- List scripts = new ArrayList<>(options.size());
- options.forEach(id -> {
- BpmTaskAssignScript script = scriptMap.get(id);
- if (script == null) {
- throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, id);
- }
- scripts.add(script);
- });
- // 逐个计算任务
- Set userIds = new HashSet<>();
- scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(execution)));
- return userIds;
- }
-}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateUserGroupApiSourceInfoProcessor.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateUserGroupApiSourceInfoProcessor.java
deleted file mode 100644
index b0720b0d5..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateUserGroupApiSourceInfoProcessor.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor;
-
-import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
-import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;
-import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor;
-import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
-import org.flowable.engine.delegate.DelegateExecution;
-
-import jakarta.annotation.Resource;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-public class BpmCandidateUserGroupApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor {
- @Resource
- private BpmUserGroupService api;
- @Resource
- private BpmUserGroupService userGroupService;
-
- @Override
- public Set getSupportedTypes() {
- return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType());
- }
-
- @Override
- public void validRuleOptions(Integer type, Set options) {
- api.validUserGroups(options);
- }
-
- @Override
- public Set doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) {
- List userGroups = userGroupService.getUserGroupList(rule.getOptions());
- Set userIds = new HashSet<>();
- userGroups.forEach(group -> userIds.addAll(group.getMemberUserIds()));
- return userIds;
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
index 00ba49de4..729e176b0 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
+++ b/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.*;
import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
import jakarta.annotation.Resource;
@@ -54,8 +55,9 @@ public class BpmModelServiceImpl implements BpmModelService {
private BpmProcessDefinitionService processDefinitionService;
@Resource
private BpmFormService bpmFormService;
+
@Resource
- private BpmTaskAssignRuleService taskAssignRuleService;
+ private BpmTaskCandidateInvoker taskCandidateInvoker;
@Override
public PageResult getModelPage(BpmModelPageReqVO pageVO) {
@@ -166,7 +168,7 @@ public class BpmModelServiceImpl implements BpmModelService {
// 1.3 校验表单已配
BpmFormDO form = checkFormConfig(model.getMetaInfo());
// 1.4 校验任务分配规则已配置
- taskAssignRuleService.checkTaskAssignRuleAllConfig(bpmnBytes);
+ taskCandidateInvoker.validateBpmnConfig(bpmnBytes);
// 1.5 校验模型是否发生修改。如果未修改,则不允许创建
BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form)
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
index dd5f035a9..82f15beec 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
+++ b/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;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
-import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java
deleted file mode 100644
index 012141adf..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.definition;
-
-import org.flowable.engine.delegate.DelegateExecution;
-
-import java.util.Set;
-
-/**
- * BPM 任务分配规则 Service 接口
- *
- * @author 芋道源码
- */
-public interface BpmTaskAssignRuleService {
-
- /**
- * 校验流程模型的任务分配规则全部都配置了
- * 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!
- *
- * @param bpmnBytes BPMN XML
- */
- void checkTaskAssignRuleAllConfig(byte[] bpmnBytes);
-
- /**
- * 计算当前执行任务的处理人
- *
- * @param execution 执行任务
- * @return 处理人的编号数组
- */
- Set calculateTaskCandidateUsers(DelegateExecution execution);
-
-}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
deleted file mode 100644
index a1474afd0..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
+++ /dev/null
@@ -1,254 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.definition;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
-import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
-import cn.iocoder.yudao.framework.common.util.string.StrUtils;
-import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
-import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants;
-import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
-import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
-import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
-import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
-import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
-import cn.iocoder.yudao.module.system.api.dept.DeptApi;
-import cn.iocoder.yudao.module.system.api.dept.PostApi;
-import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
-import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
-import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
-import cn.iocoder.yudao.module.system.api.permission.RoleApi;
-import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
-import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
-import com.google.common.annotations.VisibleForTesting;
-import jakarta.annotation.Resource;
-import lombok.extern.slf4j.Slf4j;
-import org.dromara.hutool.core.convert.Convert;
-import org.flowable.bpmn.model.BpmnModel;
-import org.flowable.bpmn.model.FlowElement;
-import org.flowable.bpmn.model.UserTask;
-import org.flowable.engine.delegate.DelegateExecution;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.*;
-import java.util.function.Function;
-
-import static cn.hutool.core.text.CharSequenceUtil.format;
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
-import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
-
-/**
- * BPM 任务分配规则 Service 实现类
- */
-@Service
-@Validated
-@Slf4j
-public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
-
- @Resource
- private BpmUserGroupService userGroupService;
- @Resource
- @Lazy // 解决循环依赖
- private BpmProcessInstanceService processInstanceService;
-
-// @Resource
-// private ExpressionManager expressionManager;
-
- @Resource
- private RoleApi roleApi;
- @Resource
- private DeptApi deptApi;
- @Resource
- private PostApi postApi;
- @Resource
- private AdminUserApi adminUserApi;
- @Resource
- private DictDataApi dictDataApi;
- @Resource
- private PermissionApi permissionApi;
-
- /**
- * 任务分配脚本
- */
- private Map scriptMap = Collections.emptyMap();
-
- @Resource
- public void setScripts(List scripts) {
- this.scriptMap = convertMap(scripts, script -> script.getEnum().getId());
- }
-
- @Override
- public void checkTaskAssignRuleAllConfig(byte[] bpmnBytes) {
- BpmnModel bpmnModel = BpmnModelUtils.getBpmnModel(bpmnBytes);
- assert bpmnModel != null;
- List userTaskList = BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class);
- // 遍历所有的 UserTask,校验审批人配置
- userTaskList.forEach(userTask -> {
- // TODO 芋艿:assignType/assignOptions/, 枚举
- Integer type = NumberUtils.parseInt(userTask.getAttributeValue(BpmnModelConstants.NAMESPACE, "assignType"));
- String options = userTask.getAttributeValue(BpmnModelConstants.NAMESPACE, "assignOptions");
- if (type == null || StrUtil.isBlank(options)) {
- throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, userTask.getName());
- }
- // TODO 芋艿:校验 options
- if (ObjectUtil.equal(type, BpmTaskAssignRuleTypeEnum.EXPRESS.getType())) {
- return;
- }
- validTaskAssignRuleOptions(type, StrUtils.splitToLong(options, ","));
- });
- }
-
- private void validTaskAssignRuleOptions(Integer type, Collection options) {
- if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) {
- roleApi.validRoleList(options);
- } else if (ObjectUtils.equalsAny(type, BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(),
- BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType())) {
- deptApi.validateDeptList(options);
- } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.POST.getType())) {
- postApi.validPostList(options);
- } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER.getType())) {
- adminUserApi.validateUserList(options);
- } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_GROUP.getType())) {
- userGroupService.validUserGroups(options);
- } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) {
- dictDataApi.validateDictDataList(DictTypeConstants.TASK_ASSIGN_SCRIPT,
- CollectionUtils.convertSet(options, String::valueOf));
- } else {
- throw new IllegalArgumentException(format("未知的规则类型({})", type));
- }
- }
-
- public Long test(DelegateExecution execution) {
- return 1L;
- }
-
- public Long test2(DelegateExecution execution, Long id) {
- return id;
- }
-
- @Override
- @DataPermission(enable = false) // 忽略数据权限,不然分配会存在问题
- public Set calculateTaskCandidateUsers(DelegateExecution execution) {
- // 1. 先从提前选好的审批人中获取
- List assignee = processInstanceService.getAssigneeByProcessInstanceIdAndTaskDefinitionKey(
- execution.getProcessInstanceId(), execution.getCurrentActivityId());
- if (CollUtil.isNotEmpty(assignee)) {
- // TODO @hai:new HashSet 即可
- return convertSet(assignee, Function.identity());
- }
- // 2. 通过分配规则,计算审批人
- return calculateTaskCandidateUsers0(execution);
- }
-
- @VisibleForTesting
- Set calculateTaskCandidateUsers0(DelegateExecution execution) {
- // 获得审批人配置
- // TODO 芋艿:assignType/assignOptions/, 枚举
- FlowElement flowElement = execution.getCurrentFlowElement();
- Integer type = NumberUtils.parseInt(flowElement.getAttributeValue(BpmnModelConstants.NAMESPACE, "assignType"));
- String optionStr = flowElement.getAttributeValue(BpmnModelConstants.NAMESPACE, "assignOptions");
- Set options = null;
- if (ObjectUtil.notEqual(BpmTaskAssignRuleTypeEnum.EXPRESS.getType(), type)) {
- options = StrUtils.splitToLongSet(optionStr, ",");
- }
-
- // 计算审批人
- Set assigneeUserIds = null;
- if (Objects.equals(BpmTaskAssignRuleTypeEnum.ROLE.getType(), type)) {
- assigneeUserIds = calculateTaskCandidateUsersByRole(options);
- } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), type)) {
- assigneeUserIds = calculateTaskCandidateUsersByDeptMember(options);
- } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), type)) {
- assigneeUserIds = calculateTaskCandidateUsersByDeptLeader(options);
- } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.POST.getType(), type)) {
- assigneeUserIds = calculateTaskCandidateUsersByPost(options);
- } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER.getType(), type)) {
- assigneeUserIds = calculateTaskCandidateUsersByUser(options);
- } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), type)) {
- assigneeUserIds = calculateTaskCandidateUsersByUserGroup(options);
- } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), type)) {
- assigneeUserIds = calculateTaskCandidateUsersByScript(execution, options);
- } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.EXPRESS.getType(), type)) {
- Object result = FlowableUtils.getExpressionValue(execution, optionStr);
- assigneeUserIds = Convert.toSet(Long.class, result);
- }
-
- // 移除被禁用的用户
- removeDisableUsers(assigneeUserIds);
- // 如果候选人为空,抛出异常
- if (CollUtil.isEmpty(assigneeUserIds)) {
- log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}/{}) 找不到候选人]", execution.getId(),
- execution.getProcessDefinitionId(), execution.getCurrentActivityId(), type, options);
- throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER);
- }
- return assigneeUserIds;
- }
-
- private Set calculateTaskCandidateUsersByRole(Set roleIds) {
- return permissionApi.getUserRoleIdListByRoleIds(roleIds);
- }
-
- private Set calculateTaskCandidateUsersByDeptMember(Set deptIds) {
- List users = adminUserApi.getUserListByDeptIds(deptIds);
- return convertSet(users, AdminUserRespDTO::getId);
- }
-
- private Set calculateTaskCandidateUsersByDeptLeader(Set deptIds) {
- List depts = deptApi.getDeptList(deptIds);
- return convertSet(depts, DeptRespDTO::getLeaderUserId);
- }
-
- private Set calculateTaskCandidateUsersByPost(Set postIds) {
- List users = adminUserApi.getUserListByPostIds(postIds);
- return convertSet(users, AdminUserRespDTO::getId);
- }
-
- private Set calculateTaskCandidateUsersByUser(Set userIds) {
- return userIds;
- }
-
- private Set calculateTaskCandidateUsersByUserGroup(Set groupIds) {
- List userGroups = userGroupService.getUserGroupList(groupIds);
- Set userIds = new HashSet<>();
- userGroups.forEach(group -> userIds.addAll(group.getMemberUserIds()));
- return userIds;
- }
-
- private Set calculateTaskCandidateUsersByScript(DelegateExecution execution, Set scriptIds) {
- // 获得对应的脚本
- List scripts = new ArrayList<>(scriptIds.size());
- scriptIds.forEach(scriptId -> {
- BpmTaskAssignScript script = scriptMap.get(scriptId);
- if (script == null) {
- throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, scriptId);
- }
- scripts.add(script);
- });
- // 逐个计算任务
- Set userIds = new HashSet<>();
- scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(execution)));
- return userIds;
- }
-
- @VisibleForTesting
- void removeDisableUsers(Set assigneeUserIds) {
- if (CollUtil.isEmpty(assigneeUserIds)) {
- return;
- }
- Map userMap = adminUserApi.getUserMap(assigneeUserIds);
- assigneeUserIds.removeIf(id -> {
- AdminUserRespDTO user = userMap.get(id);
- return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus());
- });
- }
-
-}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java
index 208749a57..4d1db2958 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java
+++ b/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;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo;
/**
* 流程抄送 Service 接口
@@ -13,14 +12,6 @@ import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo;
*/
public interface BpmProcessInstanceCopyService {
- // TODO 芋艿:这块要 review 下;思考下~~
- /**
- * 抄送
- * @param sourceInfo 抄送源信息,方便抄送处理
- * @return
- */
- boolean makeCopy(BpmCandidateSourceInfo sourceInfo);
-
/**
* 流程实例的抄送
*
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java
index 50d042cdc..d800d1932 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java
@@ -1,35 +1,22 @@
package cn.iocoder.yudao.module.bpm.service.task.cc;
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.cc.BpmProcessInstanceCopyMapper;
import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo;
-import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessorChain;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
-import cn.iocoder.yudao.module.bpm.service.task.cc.dto.BpmDelegateExecutionDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
-import org.flowable.engine.RuntimeService;
-import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
/**
@@ -45,12 +32,6 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy
@Resource
private BpmProcessInstanceCopyMapper processInstanceCopyMapper;
- @Resource
- private RuntimeService runtimeService;
-
- @Resource
- private BpmCandidateSourceInfoProcessorChain processorChain;
-
@Resource
@Lazy
private BpmTaskService bpmTaskService;
@@ -58,55 +39,6 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy
@Lazy
private BpmProcessInstanceService bpmProcessInstanceService;
- @Override
- public boolean makeCopy(BpmCandidateSourceInfo sourceInfo) {
- if (null == sourceInfo) {
- return false;
- }
-
- Task task = bpmTaskService.getTask(sourceInfo.getTaskId());
- if (ObjectUtil.isNull(task)) {
- return false;
- }
- String processInstanceId = task.getProcessInstanceId();
- if (StrUtil.isBlank(processInstanceId)) {
- return false;
- }
- DelegateExecution executionEntity = new BpmDelegateExecutionDTO(processInstanceId);
- Set ccCandidates = processorChain.calculateTaskCandidateUsers(executionEntity, sourceInfo);
- if (CollUtil.isEmpty(ccCandidates)) {
- log.warn("相关抄送人不存在 {}", sourceInfo.getTaskId());
- return false;
- } else {
- BpmProcessInstanceCopyDO copyDO = new BpmProcessInstanceCopyDO();
- // 调用
- // 设置任务id
- copyDO.setTaskId(sourceInfo.getTaskId());
- copyDO.setTaskName(task.getName());
- copyDO.setProcessInstanceId(processInstanceId);
- ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
- .processInstanceId(processInstanceId)
- .singleResult();
- if (null == processInstance) {
- log.warn("相关流程实例不存在 {}", sourceInfo.getTaskId());
- return false;
- }
- copyDO.setStartUserId(Long.parseLong(processInstance.getStartUserId()));
- copyDO.setProcessInstanceName(processInstance.getName());
- copyDO.setCategory(processInstance.getProcessDefinitionCategory());
- copyDO.setReason(sourceInfo.getReason());
- copyDO.setCreator(sourceInfo.getCreator());
- copyDO.setCreateTime(LocalDateTime.now());
- List copyList = new ArrayList<>(ccCandidates.size());
- for (Long userId : ccCandidates) {
- BpmProcessInstanceCopyDO copy = BeanUtil.copyProperties(copyDO, BpmProcessInstanceCopyDO.class);
- copy.setUserId(userId);
- copyList.add(copy);
- }
- return processInstanceCopyMapper.insertBatch(copyList);
- }
- }
-
@Override
public void createProcessInstanceCopy(Long userId, BpmProcessInstanceCopyCreateReqVO reqVO) {
// 1.1 校验任务存在
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvokerTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvokerTest.java
new file mode 100644
index 000000000..702dce3f1
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvokerTest.java
@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate;
+
+import cn.hutool.core.map.MapUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.BpmTaskCandidateUserStrategy;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import org.flowable.bpmn.model.UserTask;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * {@link BpmTaskCandidateInvoker} 的单元测试
+ *
+ * @author 芋道源码
+ */
+public class BpmTaskCandidateInvokerTest extends BaseMockitoUnitTest {
+
+ @InjectMocks
+ private BpmTaskCandidateInvoker taskCandidateInvoker;
+
+ @Mock
+ private AdminUserApi adminUserApi;
+ @Spy
+ private BpmTaskCandidateStrategy strategy = new BpmTaskCandidateUserStrategy();
+ @Spy
+ private List strategyList = Collections.singletonList(strategy);
+
+ @Test
+ public void testCalculateUsers() {
+ // 准备参数
+ String param = "1,2";
+ DelegateExecution execution = mock(DelegateExecution.class);
+ // mock 方法(DelegateExecution)
+ UserTask userTask = mock(UserTask.class);
+ when(execution.getCurrentFlowElement()).thenReturn(userTask);
+ when(userTask.getAttributeValue(eq(BpmnModelConstants.NAMESPACE), eq(BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY)))
+ .thenReturn(BpmTaskCandidateStrategyEnum.USER.getStrategy().toString());
+ when(userTask.getAttributeValue(eq(BpmnModelConstants.NAMESPACE), eq(BpmnModelConstants.USER_TASK_CANDIDATE_PARAM)))
+ .thenReturn(param);
+ // mock 方法(adminUserApi)
+ AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)
+ .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+ AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)
+ .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+ Map userMap = MapUtil.builder(user1.getId(), user1)
+ .put(user2.getId(), user2).build();
+ when(adminUserApi.getUserMap(eq(asSet(1L, 2L)))).thenReturn(userMap);
+
+ // 调用
+ Set results = taskCandidateInvoker.calculateUsers(execution);
+ // 断言
+ assertEquals(asSet(1L, 2L), results);
+ }
+
+ @Test
+ public void testRemoveDisableUsers() {
+ // 准备参数. 1L 可以找到;2L 是禁用的;3L 找不到
+ Set assigneeUserIds = asSet(1L, 2L, 3L);
+ // mock 方法
+ AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)
+ .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+ AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)
+ .setStatus(CommonStatusEnum.DISABLE.getStatus()));
+ Map userMap = MapUtil.builder(user1.getId(), user1)
+ .put(user2.getId(), user2).build();
+ when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);
+
+ // 调用
+ taskCandidateInvoker.removeDisableUsers(assigneeUserIds);
+ // 断言
+ assertEquals(asSet(1L), assigneeUserIds);
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpressionTest.java
similarity index 86%
rename from yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java
rename to yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpressionTest.java
index f46278083..b9a77ca79 100644
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpressionTest.java
@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.expression;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
@@ -21,10 +21,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
-public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
+public class BpmTaskAssignLeaderExpressionTest extends BaseMockitoUnitTest {
@InjectMocks
- private BpmTaskAssignLeaderX2Script script;
+ private BpmTaskAssignLeaderExpression expression;
@Mock
private AdminUserApi adminUserApi;
@@ -34,7 +34,7 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
private BpmProcessInstanceService bpmProcessInstanceService;
@Test
- public void testCalculateTaskCandidateUsers_noDept() {
+ public void testCalculateUsers_noDept() {
// 准备参数
DelegateExecution execution = mockDelegateExecution(1L);
// mock 方法(startUser)
@@ -44,13 +44,13 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
when(deptApi.getDept(eq(10L))).thenReturn(null);
// 调用
- Set result = script.calculateTaskCandidateUsers(execution);
+ Set result = expression.calculateUsers(execution, 1);
// 断言
assertEquals(0, result.size());
}
@Test
- public void testCalculateTaskCandidateUsers_noParentDept() {
+ public void testCalculateUsers_noParentDept() {
// 准备参数
DelegateExecution execution = mockDelegateExecution(1L);
// mock 方法(startUser)
@@ -63,13 +63,13 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
when(deptApi.getDept(eq(100L))).thenReturn(null);
// 调用
- Set result = script.calculateTaskCandidateUsers(execution);
+ Set result = expression.calculateUsers(execution, 2);
// 断言
assertEquals(asSet(20L), result);
}
@Test
- public void testCalculateTaskCandidateUsers_existParentDept() {
+ public void testCalculateUsers_existParentDept() {
// 准备参数
DelegateExecution execution = mockDelegateExecution(1L);
// mock 方法(startUser)
@@ -84,7 +84,7 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
when(deptApi.getDept(eq(100L))).thenReturn(parentDept);
// 调用
- Set result = script.calculateTaskCandidateUsers(execution);
+ Set result = expression.calculateUsers(execution, 2);
// 断言
assertEquals(asSet(200L), result);
}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptLeaderStrategyTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptLeaderStrategyTest.java
new file mode 100644
index 000000000..9b89e2bd3
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptLeaderStrategyTest.java
@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
+import static java.util.Arrays.asList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+public class BpmTaskCandidateDeptLeaderStrategyTest extends BaseMockitoUnitTest {
+
+ @InjectMocks
+ private BpmTaskCandidateDeptLeaderStrategy strategy;
+
+ @Mock
+ private DeptApi deptApi;
+
+ @Test
+ public void testCalculateUsers() {
+ // 准备参数
+ String param = "1,2";
+ // mock 方法
+ DeptRespDTO dept1 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(11L));
+ DeptRespDTO dept2 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(22L));
+ when(deptApi.getDeptList(eq(asSet(1L, 2L)))).thenReturn(asList(dept1, dept2));
+
+ // 调用
+ Set results = strategy.calculateUsers(null, param);
+ // 断言
+ assertEquals(asSet(11L, 22L), results);
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptMemberStrategyTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptMemberStrategyTest.java
new file mode 100644
index 000000000..4e72c0281
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptMemberStrategyTest.java
@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import java.util.List;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+public class BpmTaskCandidateDeptMemberStrategyTest extends BaseMockitoUnitTest {
+
+ @InjectMocks
+ private BpmTaskCandidateDeptMemberStrategy strategy;
+
+ @Mock
+ private AdminUserApi adminUserApi;
+
+ @Test
+ public void testCalculateUsers() {
+ // 准备参数
+ String param = "11,22";
+ // mock 方法
+ List users = convertList(asSet(11L, 22L),
+ id -> new AdminUserRespDTO().setId(id));
+ when(adminUserApi.getUserListByDeptIds(eq(asSet(11L, 22L)))).thenReturn(users);
+
+ // 调用
+ Set results = strategy.calculateUsers(null, param);
+ // 断言
+ assertEquals(asSet(11L, 22L), results);
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateExpressionStrategyTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateExpressionStrategyTest.java
new file mode 100644
index 000000000..caa668eac
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateExpressionStrategyTest.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.MockedStatic;
+
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.*;
+
+public class BpmTaskCandidateExpressionStrategyTest extends BaseMockitoUnitTest {
+
+ @InjectMocks
+ private BpmTaskCandidateExpressionStrategy strategy;
+
+ @Test
+ public void testCalculateUsers() {
+ try (MockedStatic flowableUtilMockedStatic = mockStatic(FlowableUtils.class)) {
+ // 准备参数
+ String param = "1,2";
+ DelegateExecution execution = mock(DelegateExecution.class);
+ // mock 方法
+ flowableUtilMockedStatic.when(() -> FlowableUtils.getExpressionValue(same(execution), eq(param)))
+ .thenReturn(asSet(1L, 2L));
+
+ // 调用
+ Set results = strategy.calculateUsers(execution, param);
+ // 断言
+ assertEquals(asSet(1L, 2L), results);
+ }
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateGroupStrategyTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateGroupStrategyTest.java
new file mode 100644
index 000000000..07958a51b
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateGroupStrategyTest.java
@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import java.util.Arrays;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+public class BpmTaskCandidateGroupStrategyTest extends BaseMockitoUnitTest {
+
+ @InjectMocks
+ private BpmTaskCandidateGroupStrategy strategy;
+
+ @Mock
+ private BpmUserGroupService userGroupService;
+
+ @Test
+ public void testCalculateUsers() {
+ // 准备参数
+ String param = "1,2";
+ // mock 方法
+ BpmUserGroupDO userGroup1 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(11L, 12L)));
+ BpmUserGroupDO userGroup2 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(21L, 22L)));
+ when(userGroupService.getUserGroupList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(userGroup1, userGroup2));
+
+ // 调用
+ Set results = strategy.calculateUsers(null, param);
+ // 断言
+ assertEquals(asSet(11L, 12L, 21L, 22L), results);
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidatePostStrategyTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidatePostStrategyTest.java
new file mode 100644
index 000000000..a30ce28eb
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidatePostStrategyTest.java
@@ -0,0 +1,45 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import cn.iocoder.yudao.module.system.api.dept.PostApi;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import java.util.List;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+public class BpmTaskCandidatePostStrategyTest extends BaseMockitoUnitTest {
+
+ @InjectMocks
+ private BpmTaskCandidatePostStrategy strategy;
+
+ @Mock
+ private PostApi postApi;
+ @Mock
+ private AdminUserApi adminUserApi;
+
+ @Test
+ public void testCalculateUsers() {
+ // 准备参数
+ String param = "1,2";
+ // mock 方法
+ List users = convertList(asSet(11L, 22L),
+ id -> new AdminUserRespDTO().setId(id));
+ when(adminUserApi.getUserListByPostIds(eq(asSet(1L, 2L)))).thenReturn(users);
+
+ // 调用
+ Set results = strategy.calculateUsers(null, param);
+ // 断言
+ assertEquals(asSet(11L, 22L), results);
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateRoleStrategyTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateRoleStrategyTest.java
new file mode 100644
index 000000000..7c4247bcd
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateRoleStrategyTest.java
@@ -0,0 +1,41 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
+import cn.iocoder.yudao.module.system.api.permission.RoleApi;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+public class BpmTaskCandidateRoleStrategyTest extends BaseMockitoUnitTest {
+
+ @InjectMocks
+ private BpmTaskCandidateRoleStrategy strategy;
+
+ @Mock
+ private RoleApi roleApi;
+ @Mock
+ private PermissionApi permissionApi;
+
+ @Test
+ public void testCalculateUsers() {
+ // 准备参数
+ String param = "1,2";
+ // mock 方法
+ when(permissionApi.getUserRoleIdListByRoleIds(eq(asSet(1L, 2L))))
+ .thenReturn(asSet(11L, 22L));
+
+ // 调用
+ Set results = strategy.calculateUsers(null, param);
+ // 断言
+ assertEquals(asSet(11L, 22L), results);
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateUserStrategyTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateUserStrategyTest.java
new file mode 100644
index 000000000..d71ccebfd
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateUserStrategyTest.java
@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class BpmTaskCandidateUserStrategyTest extends BaseMockitoUnitTest {
+
+ @InjectMocks
+ private BpmTaskCandidateUserStrategy strategy;
+
+ @Test
+ public void testCalculateUsers() {
+ // 准备参数
+ String param = "1,2";
+
+ // 调用
+ Set results = strategy.calculateUsers(null, param);
+ // 断言
+ assertEquals(asSet(1L, 2L), results);
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessorChainTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessorChainTest.java
deleted file mode 100644
index 29caf9ced..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessorChainTest.java
+++ /dev/null
@@ -1,244 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.candidate;
-
-import cn.hutool.core.map.MapUtil;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO;
-import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl.BpmTaskAssignLeaderX1Script;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl.BpmTaskAssignLeaderX2Script;
-import cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor.BpmCandidateScriptApiSourceInfoProcessor;
-import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
-import cn.iocoder.yudao.module.system.api.dept.DeptApi;
-import cn.iocoder.yudao.module.system.api.dept.PostApi;
-import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
-import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
-import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
-import cn.iocoder.yudao.module.system.api.permission.RoleApi;
-import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
-import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
-import jakarta.annotation.Resource;
-import org.flowable.engine.delegate.DelegateExecution;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
-import static java.util.Collections.singleton;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-@Disabled // TODO 芋艿:临时禁用,暂时不修复,等重构后解决
-@Import({BpmCandidateSourceInfoProcessorChain.class,
- BpmCandidateScriptApiSourceInfoProcessor.class, BpmTaskAssignLeaderX1Script.class,
- BpmTaskAssignLeaderX2Script.class})
-public class BpmCandidateSourceInfoProcessorChainTest extends BaseDbUnitTest {
- @Resource
- private BpmCandidateSourceInfoProcessorChain processorChain;
-
- @MockBean
- private BpmUserGroupService userGroupService;
- @MockBean
- private DeptApi deptApi;
- @MockBean
- private AdminUserApi adminUserApi;
- @MockBean
- private PermissionApi permissionApi;
- @MockBean
- private RoleApi roleApi;
- @MockBean
- private PostApi postApi;
- @MockBean
- private DictDataApi dictDataApi;
- @Resource
- private BpmCandidateScriptApiSourceInfoProcessor bpmCandidateScriptApiSourceInfoProcessor;
-
- @Test
- public void testCalculateTaskCandidateUsers_Role() {
- // 准备参数
- BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L))
- .setType(BpmTaskAssignRuleTypeEnum.ROLE.getType());
- // mock 方法
- when(permissionApi.getUserRoleIdListByRoleIds(eq(rule.getOptions())))
- .thenReturn(asSet(11L, 22L));
- mockGetUserMap(asSet(11L, 22L));
-
- // 调用
- BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();
- sourceInfo.addRule(rule);
- Set results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);
- // 断言
- assertEquals(asSet(11L, 22L), results);
- }
-
- @Test
- public void testCalculateTaskCandidateUsers_DeptMember() {
- // 准备参数
- BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L))
- .setType(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType());
- // mock 方法
- List users = CollectionUtils.convertList(asSet(11L, 22L),
- id -> new AdminUserRespDTO().setId(id));
- when(adminUserApi.getUserListByDeptIds(eq(rule.getOptions()))).thenReturn(users);
- mockGetUserMap(asSet(11L, 22L));
-
- // 调用
- BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();
- sourceInfo.addRule(rule);
- Set results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);
- // 断言
- assertEquals(asSet(11L, 22L), results);
- }
-
- @Test
- public void testCalculateTaskCandidateUsers_DeptLeader() {
- // 准备参数
- BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L))
- .setType(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType());
- // mock 方法
- DeptRespDTO dept1 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(11L));
- DeptRespDTO dept2 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(22L));
- when(deptApi.getDeptList(eq(rule.getOptions()))).thenReturn(Arrays.asList(dept1, dept2));
- mockGetUserMap(asSet(11L, 22L));
-
- // 调用
- BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();
- sourceInfo.addRule(rule);
- Set results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);
- // 断言
- assertEquals(asSet(11L, 22L), results);
- }
-
- @Test
- public void testCalculateTaskCandidateUsers_Post() {
- // 准备参数
- BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L))
- .setType(BpmTaskAssignRuleTypeEnum.POST.getType());
- // mock 方法
- List users = CollectionUtils.convertList(asSet(11L, 22L),
- id -> new AdminUserRespDTO().setId(id));
- when(adminUserApi.getUserListByPostIds(eq(rule.getOptions()))).thenReturn(users);
- mockGetUserMap(asSet(11L, 22L));
-
- // 调用
- BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();
- sourceInfo.addRule(rule);
- Set results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);
- // 断言
- assertEquals(asSet(11L, 22L), results);
- }
-
- @Test
- public void testCalculateTaskCandidateUsers_User() {
- // 准备参数
- BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L))
- .setType(BpmTaskAssignRuleTypeEnum.USER.getType());
- // mock 方法
- mockGetUserMap(asSet(1L, 2L));
-
- // 调用
- BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();
- sourceInfo.addRule(rule);
- Set results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);
- // 断言
- assertEquals(asSet(1L, 2L), results);
- }
-
- @Test
- public void testCalculateTaskCandidateUsers_UserGroup() {
- // 准备参数
- BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L))
- .setType(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType());
- // mock 方法
- BpmUserGroupDO userGroup1 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(11L, 12L)));
- BpmUserGroupDO userGroup2 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(21L, 22L)));
- when(userGroupService.getUserGroupList(eq(rule.getOptions()))).thenReturn(Arrays.asList(userGroup1, userGroup2));
- mockGetUserMap(asSet(11L, 12L, 21L, 22L));
-
- // 调用
- BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();
- sourceInfo.addRule(rule);
- Set results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);
- // 断言
- assertEquals(asSet(11L, 12L, 21L, 22L), results);
- }
-
- private void mockGetUserMap(Set assigneeUserIds) {
- Map userMap = CollectionUtils.convertMap(assigneeUserIds, id -> id,
- id -> new AdminUserRespDTO().setId(id).setStatus(CommonStatusEnum.ENABLE.getStatus()));
- when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);
- }
-
- @Test
- public void testCalculateTaskCandidateUsers_Script() {
- // 准备参数
- BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(20L, 21L))
- .setType(BpmTaskAssignRuleTypeEnum.SCRIPT.getType());
- // mock 方法
- BpmTaskAssignScript script1 = new BpmTaskAssignScript() {
-
- @Override
- public Set calculateTaskCandidateUsers(DelegateExecution task) {
- return singleton(11L);
- }
-
- @Override
- public BpmTaskRuleScriptEnum getEnum() {
- return BpmTaskRuleScriptEnum.LEADER_X1;
- }
- };
- BpmTaskAssignScript script2 = new BpmTaskAssignScript() {
-
- @Override
- public Set calculateTaskCandidateUsers(DelegateExecution task) {
- return singleton(22L);
- }
-
- @Override
- public BpmTaskRuleScriptEnum getEnum() {
- return BpmTaskRuleScriptEnum.LEADER_X2;
- }
- };
- bpmCandidateScriptApiSourceInfoProcessor.setScripts(Arrays.asList(script1, script2));
- mockGetUserMap(asSet(11L, 22L));
-
- // 调用
- BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo();
- sourceInfo.addRule(rule);
- Set results = processorChain.calculateTaskCandidateUsers(null, sourceInfo);
- // 断言
- assertEquals(asSet(11L, 22L), results);
- }
-
- @Test
- public void testRemoveDisableUsers() {
- // 准备参数. 1L 可以找到;2L 是禁用的;3L 找不到
- Set assigneeUserIds = asSet(1L, 2L, 3L);
- // mock 方法
- AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)
- .setStatus(CommonStatusEnum.ENABLE.getStatus()));
- AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)
- .setStatus(CommonStatusEnum.DISABLE.getStatus()));
- Map userMap = MapUtil.builder(user1.getId(), user1)
- .put(user2.getId(), user2).build();
- when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);
-
- // 调用
- processorChain.removeDisableUsers(assigneeUserIds);
- // 断言
- assertEquals(asSet(1L), assigneeUserIds);
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImplTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImplTest.java
deleted file mode 100644
index 2ca2ff914..000000000
--- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImplTest.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package cn.iocoder.yudao.module.bpm.service.definition;
-
-import cn.hutool.core.map.MapUtil;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
-import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl.BpmTaskAssignStartUserScript;
-import cn.iocoder.yudao.module.system.api.dept.DeptApi;
-import cn.iocoder.yudao.module.system.api.dept.PostApi;
-import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
-import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
-import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
-import cn.iocoder.yudao.module.system.api.permission.RoleApi;
-import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
-import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
-import org.flowable.engine.delegate.DelegateExecution;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.context.annotation.Import;
-
-import jakarta.annotation.Resource;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
-import static java.util.Collections.singleton;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-/**
- * {@link BpmTaskAssignRuleService} 的单元测试
- *
- * @author 芋道源码
- */
-@Import({BpmTaskAssignRuleServiceImpl.class, BpmTaskAssignStartUserScript.class}) // Import 引入 BpmTaskAssignStartUserScript 目的是保证不报错
-public class BpmTaskAssignRuleServiceImplTest extends BaseDbUnitTest {
-
- @Resource
- private BpmTaskAssignRuleServiceImpl bpmTaskRuleService;
-
- @MockBean
- private BpmUserGroupService userGroupService;
- @MockBean
- private DeptApi deptApi;
- @MockBean
- private AdminUserApi adminUserApi;
- @MockBean
- private PermissionApi permissionApi;
- @MockBean
- private RoleApi roleApi;
- @MockBean
- private PostApi postApi;
- @MockBean
- private DictDataApi dictDataApi;
-
- @Test
- public void testCalculateTaskCandidateUsers_Role() {
- // 准备参数
- BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
- .setType(BpmTaskAssignRuleTypeEnum.ROLE.getType());
- // mock 方法
- when(permissionApi.getUserRoleIdListByRoleIds(eq(rule.getOptions())))
- .thenReturn(asSet(11L, 22L));
- mockGetUserMap(asSet(11L, 22L));
-
- // 调用
- Set results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
- // 断言
- assertEquals(asSet(11L, 22L), results);
- }
-
- @Test
- public void testCalculateTaskCandidateUsers_DeptMember() {
- // 准备参数
- BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
- .setType(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType());
- // mock 方法
- List users = CollectionUtils.convertList(asSet(11L, 22L),
- id -> new AdminUserRespDTO().setId(id));
- when(adminUserApi.getUserListByDeptIds(eq(rule.getOptions()))).thenReturn(users);
- mockGetUserMap(asSet(11L, 22L));
-
- // 调用
- Set results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
- // 断言
- assertEquals(asSet(11L, 22L), results);
- }
-
- @Test
- public void testCalculateTaskCandidateUsers_DeptLeader() {
- // 准备参数
- BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
- .setType(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType());
- // mock 方法
- DeptRespDTO dept1 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(11L));
- DeptRespDTO dept2 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(22L));
- when(deptApi.getDeptList(eq(rule.getOptions()))).thenReturn(Arrays.asList(dept1, dept2));
- mockGetUserMap(asSet(11L, 22L));
-
- // 调用
- Set results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
- // 断言
- assertEquals(asSet(11L, 22L), results);
- }
-
- @Test
- public void testCalculateTaskCandidateUsers_Post() {
- // 准备参数
- BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
- .setType(BpmTaskAssignRuleTypeEnum.POST.getType());
- // mock 方法
- List users = CollectionUtils.convertList(asSet(11L, 22L),
- id -> new AdminUserRespDTO().setId(id));
- when(adminUserApi.getUserListByPostIds(eq(rule.getOptions()))).thenReturn(users);
- mockGetUserMap(asSet(11L, 22L));
-
- // 调用
- Set results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
- // 断言
- assertEquals(asSet(11L, 22L), results);
- }
-
- @Test
- public void testCalculateTaskCandidateUsers_User() {
- // 准备参数
- BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
- .setType(BpmTaskAssignRuleTypeEnum.USER.getType());
- // mock 方法
- mockGetUserMap(asSet(1L, 2L));
-
- // 调用
- Set results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
- // 断言
- assertEquals(asSet(1L, 2L), results);
- }
-
- @Test
- public void testCalculateTaskCandidateUsers_UserGroup() {
- // 准备参数
- BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
- .setType(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType());
- // mock 方法
- BpmUserGroupDO userGroup1 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(11L, 12L)));
- BpmUserGroupDO userGroup2 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(21L, 22L)));
- when(userGroupService.getUserGroupList(eq(rule.getOptions()))).thenReturn(Arrays.asList(userGroup1, userGroup2));
- mockGetUserMap(asSet(11L, 12L, 21L, 22L));
-
- // 调用
- Set results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
- // 断言
- assertEquals(asSet(11L, 12L, 21L, 22L), results);
- }
-
- @Test
- public void testCalculateTaskCandidateUsers_Script() {
- // 准备参数
- BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(20L, 21L))
- .setType(BpmTaskAssignRuleTypeEnum.SCRIPT.getType());
- // mock 方法
- BpmTaskAssignScript script1 = new BpmTaskAssignScript() {
-
- @Override
- public Set calculateTaskCandidateUsers(DelegateExecution task) {
- return singleton(11L);
- }
-
- @Override
- public BpmTaskRuleScriptEnum getEnum() {
- return BpmTaskRuleScriptEnum.LEADER_X1;
- }
- };
- BpmTaskAssignScript script2 = new BpmTaskAssignScript() {
-
- @Override
- public Set calculateTaskCandidateUsers(DelegateExecution task) {
- return singleton(22L);
- }
-
- @Override
- public BpmTaskRuleScriptEnum getEnum() {
- return BpmTaskRuleScriptEnum.LEADER_X2;
- }
- };
- bpmTaskRuleService.setScripts(Arrays.asList(script1, script2));
- mockGetUserMap(asSet(11L, 22L));
-
- // 调用
- Set results = bpmTaskRuleService.calculateTaskCandidateUsers(null, rule);
- // 断言
- assertEquals(asSet(11L, 22L), results);
- }
-
- @Test
- public void testRemoveDisableUsers() {
- // 准备参数. 1L 可以找到;2L 是禁用的;3L 找不到
- Set assigneeUserIds = asSet(1L, 2L, 3L);
- // mock 方法
- AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)
- .setStatus(CommonStatusEnum.ENABLE.getStatus()));
- AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)
- .setStatus(CommonStatusEnum.DISABLE.getStatus()));
- Map userMap = MapUtil.builder(user1.getId(), user1)
- .put(user2.getId(), user2).build();
- when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);
-
- // 调用
- bpmTaskRuleService.removeDisableUsers(assigneeUserIds);
- // 断言
- assertEquals(asSet(1L), assigneeUserIds);
- }
-
- private void mockGetUserMap(Set assigneeUserIds) {
- Map userMap = CollectionUtils.convertMap(assigneeUserIds, id -> id,
- id -> new AdminUserRespDTO().setId(id).setStatus(CommonStatusEnum.ENABLE.getStatus()));
- when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);
- }
-
-}
diff --git a/yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java b/yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java
deleted file mode 100644
index f279e95df..000000000
--- a/yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package cn.iocoder.yudao.framework.flowable.core.enums;
-
-/**
- * 流程常量信息
- */
-public interface BpmnModelConstants {
-
- String BPMN_FILE_SUFFIX = ".bpmn";
-
- /**
- * BPMN 中的命名空间
- *
- * 这个东西有可能导致无法切换工作流程的实现
- */
- String NAMESPACE = "http://flowable.org/bpmn";
-
-}
diff --git a/yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java b/yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java
deleted file mode 100644
index de8d6279d..000000000
--- a/yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java
+++ /dev/null
@@ -1 +0,0 @@
-package cn.iocoder.yudao.framework.flowable.core;
diff --git a/yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java b/yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java
deleted file mode 100644
index 324d3de0e..000000000
--- a/yudao-module-bpm/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java
+++ /dev/null
@@ -1 +0,0 @@
-package cn.iocoder.yudao.framework.flowable;