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