Commit e01acfb18e12915523b293c81e386a1cb87c6242

Authored by jason
1 parent 41e4283f

工作流 Flowable 任务自定义 Script 脚本 相关实现

Showing 13 changed files with 307 additions and 54 deletions
yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java
1 1 package cn.iocoder.yudao.framework.flowable.core.util;
2 2  
  3 +import org.flowable.bpmn.converter.BpmnXMLConverter;
  4 +import org.flowable.bpmn.model.BpmnModel;
  5 +import org.flowable.bpmn.model.FlowElement;
3 6 import org.flowable.common.engine.impl.identity.Authentication;
4 7  
  8 +import java.util.ArrayList;
  9 +import java.util.Arrays;
  10 +import java.util.List;
  11 +
5 12 public class FlowableUtils {
6 13  
7 14 public static void setAuthenticatedUserId(Long userId) {
... ... @@ -11,4 +18,45 @@ public class FlowableUtils {
11 18 public static void clearAuthenticatedUserId() {
12 19 Authentication.setAuthenticatedUserId(null);
13 20 }
  21 +
  22 + /**
  23 + * 获得 BPMN 流程中,指定的元素们
  24 + *
  25 + * @param model
  26 + * @param clazz 指定元素。例如说,{@link org.flowable.bpmn.model.UserTask}、{@link org.flowable.bpmn.model.Gateway} 等等
  27 + * @return 元素们
  28 + */
  29 + public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {
  30 + List<T> result = new ArrayList<>();
  31 + model.getProcesses().forEach(process -> {
  32 + process.getFlowElements().forEach(flowElement -> {
  33 + if (flowElement.getClass().isAssignableFrom(clazz)) {
  34 + result.add((T) flowElement);
  35 + }
  36 + });
  37 + });
  38 + return result;
  39 + }
  40 +
  41 + /**
  42 + * 比较 两个bpmnModel 是否相同
  43 + * @param oldModel 老的bpmn model
  44 + * @param newModel 新的bpmn model
  45 + */
  46 + public static boolean equals(BpmnModel oldModel, BpmnModel newModel) {
  47 + // 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
  48 + return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
  49 + }
  50 +
  51 + /**
  52 + * 把 bpmnModel 转换成 byte[]
  53 + * @param model bpmnModel
  54 + */
  55 + public static byte[] getBpmnBytes(BpmnModel model) {
  56 + if (model == null) {
  57 + return new byte[0];
  58 + }
  59 + BpmnXMLConverter converter = new BpmnXMLConverter();
  60 + return converter.convertToXML(model);
  61 + }
14 62 }
... ...
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java
1 1 package cn.iocoder.yudao.module.bpm.framework.flowable.config;
2 2  
3 3 import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.BpmActivityBehaviorFactory;
  4 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
4 5 import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmProcessInstanceEventListener;
5 6 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
6 7 import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
... ... @@ -27,8 +28,9 @@ import java.util.List;
27 28 public class BpmFlowableConfiguration {
28 29  
29 30 /**
30   - * 将自定义 listener 加入全局listener
  31 + * Flowable engines 自定义的配置
31 32 * @param listeners 自定义 listener
  33 + * @param bpmActivityBehaviorFactory 自定义的 ActivityBehaviorFactory 实现
32 34 */
33 35 @Bean
34 36 public EngineConfigurationConfigurer<SpringProcessEngineConfiguration> addCustomerListenerConfigurer (ObjectProvider<FlowableEventListener> listeners,
... ... @@ -51,14 +53,15 @@ public class BpmFlowableConfiguration {
51 53 BpmUserGroupService userGroupService,
52 54 PermissionApi permissionApi,
53 55 DeptApi deptApi,
54   - AdminUserApi adminUserApi) {
  56 + AdminUserApi adminUserApi,
  57 + List<BpmTaskAssignScript> scripts) {
55 58 BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory();
56 59 bpmActivityBehaviorFactory.setBpmTaskRuleService(taskRuleService);
57 60 bpmActivityBehaviorFactory.setUserGroupService(userGroupService);
58 61 bpmActivityBehaviorFactory.setAdminUserApi(adminUserApi);
59 62 bpmActivityBehaviorFactory.setPermissionApi(permissionApi);
60 63 bpmActivityBehaviorFactory.setDeptApi(deptApi);
61   -// bpmActivityBehaviorFactory.setScripts(scripts);
  64 + bpmActivityBehaviorFactory.setScripts(scripts);
62 65 return bpmActivityBehaviorFactory;
63 66 }
64 67 }
... ...
yudao-module-bpm/yudao-module-bpm-impl-flowable/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.framework.flowable.core.behavior.script.BpmTaskAssignScript;
3 4 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
4 5 import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
5 6 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
... ... @@ -13,6 +14,8 @@ import org.flowable.bpmn.model.UserTask;
13 14 import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
14 15 import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;
15 16  
  17 +import java.util.List;
  18 +
16 19 /**
17 20 * 自定义的 ActivityBehaviorFactory 实现类,目的如下:
18 21 * 1. 自定义 {@link #createUserTaskActivityBehavior(UserTask)}:实现自定义的流程任务的 assignee 负责人的分配
... ... @@ -35,6 +38,8 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
35 38 private DeptApi deptApi;
36 39 @Setter
37 40 private AdminUserApi adminUserApi;
  41 + @Setter
  42 + private List<BpmTaskAssignScript> scripts;
38 43  
39 44 @Override
40 45 public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) {
... ... @@ -44,8 +49,7 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
44 49 userTaskActivityBehavior.setDeptApi(deptApi);
45 50 userTaskActivityBehavior.setUserGroupService(userGroupService);
46 51 userTaskActivityBehavior.setAdminUserApi(adminUserApi);
47   - //TODO
48   - //userTaskActivityBehavior.setScripts(scripts);
  52 + userTaskActivityBehavior.setScripts(scripts);
49 53 return userTaskActivityBehavior;
50 54 }
51 55 }
... ...
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
... ... @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 7 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
8 8 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
9 9 import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
  10 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
10 11 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
11 12 import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
12 13 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
... ... @@ -30,8 +31,10 @@ import org.flowable.task.service.impl.persistence.entity.TaskEntity;
30 31 import java.util.*;
31 32  
32 33 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  34 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
33 35 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
34 36 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
  37 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS;
35 38 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER;
36 39  
37 40 /**
... ... @@ -56,9 +59,17 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
56 59 @Setter
57 60 private PermissionApi permissionApi;
58 61  
  62 + /**
  63 + * 任务分配脚本
  64 + */
  65 + private Map<Long, BpmTaskAssignScript> scriptMap = Collections.emptyMap();
  66 +
59 67 public BpmUserTaskActivityBehavior(UserTask userTask) {
60 68 super(userTask);
61 69 }
  70 + public void setScripts(List<BpmTaskAssignScript> scripts) {
  71 + this.scriptMap = convertMap(scripts, script -> script.getEnum().getId());
  72 + }
62 73  
63 74 @Override
64 75 protected void handleAssignments(TaskService taskService, String assignee, String owner, List<String> candidateUsers, List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager, DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) {
... ... @@ -100,10 +111,9 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
100 111 assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule);
101 112 } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) {
102 113 assigneeUserIds = calculateTaskCandidateUsersByUserGroup(task, rule);
  114 + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) {
  115 + assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule);
103 116 }
104   -// else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) {
105   -// assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule);
106   -// }
107 117  
108 118 // 移除被禁用的用户
109 119 removeDisableUsers(assigneeUserIds);
... ... @@ -146,6 +156,22 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
146 156 return userIds;
147 157 }
148 158  
  159 + private Set<Long> calculateTaskCandidateUsersByScript(TaskEntity task, BpmTaskAssignRuleDO rule) {
  160 + // 获得对应的脚本
  161 + List<BpmTaskAssignScript> scripts = new ArrayList<>(rule.getOptions().size());
  162 + rule.getOptions().forEach(id -> {
  163 + BpmTaskAssignScript script = scriptMap.get(id);
  164 + if (script == null) {
  165 + throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, id);
  166 + }
  167 + scripts.add(script);
  168 + });
  169 + // 逐个计算任务
  170 + Set<Long> userIds = new HashSet<>();
  171 + scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(task)));
  172 + return userIds;
  173 + }
  174 +
149 175 private Long chooseTaskAssignee(Set<Long> candidateUserIds) {
150 176 // TODO 芋艿:未来可以优化下,改成轮询的策略
151 177 int index = RandomUtil.randomInt(candidateUserIds.size());
... ...
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java 0 → 100644
  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.task.service.impl.persistence.entity.TaskEntity;
  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 +public interface BpmTaskAssignScript {
  18 +
  19 + /**
  20 + * 基于流程任务,获得任务的候选用户们
  21 + *
  22 + * @param task 任务
  23 + * @return 候选人用户的编号数组
  24 + */
  25 + Set<Long> calculateTaskCandidateUsers(TaskEntity task);
  26 +
  27 + /**
  28 + * 获得枚举值
  29 + *
  30 + * @return 枚举值
  31 + */
  32 + BpmTaskRuleScriptEnum getEnum();
  33 +}
  34 +
... ...
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  4 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
  5 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  6 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  7 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  8 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  9 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  10 +
  11 +import org.flowable.engine.runtime.ProcessInstance;
  12 +import org.flowable.task.service.impl.persistence.entity.TaskEntity;
  13 +import org.springframework.context.annotation.Lazy;
  14 +import org.springframework.util.Assert;
  15 +
  16 +import javax.annotation.Resource;
  17 +import java.util.Set;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  20 +import static java.util.Collections.emptySet;
  21 +
  22 +/**
  23 + * 分配给发起人的 Leader 审批的 Script 实现类
  24 + * 目前 Leader 的定义是,
  25 + *
  26 + * @author 芋道源码
  27 + */
  28 +public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript {
  29 +
  30 + @Resource
  31 + private AdminUserApi adminUserApi;
  32 + @Resource
  33 + private DeptApi deptApi;
  34 + @Resource
  35 + @Lazy // 解决循环依赖
  36 + private BpmProcessInstanceService bpmProcessInstanceService;
  37 +
  38 + protected Set<Long> calculateTaskCandidateUsers(TaskEntity task, int level) {
  39 + Assert.isTrue(level > 0, "level 必须大于 0");
  40 + // 获得发起人
  41 + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId());
  42 + Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
  43 + // 获得对应 leve 的部门
  44 + DeptRespDTO dept = null;
  45 + for (int i = 0; i < level; i++) {
  46 + // 获得 level 对应的部门
  47 + if (dept == null) {
  48 + dept = getStartUserDept(startUserId);
  49 + if (dept == null) { // 找不到发起人的部门,所以无法使用该规则
  50 + return emptySet();
  51 + }
  52 + } else {
  53 + DeptRespDTO parentDept = deptApi.getDept(dept.getParentId());
  54 + if (parentDept == null) { // 找不到父级部门,所以只好结束寻找。原因是:例如说,级别比较高的人,所在部门层级比较少
  55 + break;
  56 + }
  57 + dept = parentDept;
  58 + }
  59 + }
  60 + return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet();
  61 + }
  62 +
  63 + private DeptRespDTO getStartUserDept(Long startUserId) {
  64 + AdminUserRespDTO startUser = adminUserApi.getUser(startUserId);
  65 + if (startUser.getDeptId() == null) { // 找不到部门,所以无法使用该规则
  66 + return null;
  67 + }
  68 + return deptApi.getDept(startUser.getDeptId());
  69 + }
  70 +
  71 +}
... ...
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java 0 → 100644
  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.task.service.impl.persistence.entity.TaskEntity;
  5 +import org.springframework.stereotype.Component;
  6 +
  7 +import java.util.Set;
  8 +
  9 +/**
  10 + * 分配给发起人的一级 Leader 审批的 Script 实现类
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Component
  15 +public class BpmTaskAssignLeaderX1Script extends BpmTaskAssignLeaderAbstractScript {
  16 +
  17 + @Override
  18 + public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
  19 + return calculateTaskCandidateUsers(task, 1);
  20 + }
  21 +
  22 + @Override
  23 + public BpmTaskRuleScriptEnum getEnum() {
  24 + return BpmTaskRuleScriptEnum.LEADER_X1;
  25 + }
  26 +
  27 +}
... ...
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java 0 → 100644
  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.task.service.impl.persistence.entity.TaskEntity;
  5 +import org.springframework.stereotype.Component;
  6 +
  7 +import java.util.Set;
  8 +
  9 +/**
  10 + * 分配给发起人的二级 Leader 审批的 Script 实现类
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Component
  15 +public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript {
  16 +
  17 + @Override
  18 + public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
  19 + return calculateTaskCandidateUsers(task, 2);
  20 + }
  21 +
  22 + @Override
  23 + public BpmTaskRuleScriptEnum getEnum() {
  24 + return BpmTaskRuleScriptEnum.LEADER_X2;
  25 + }
  26 +
  27 +}
... ...
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
  4 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  5 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
  6 +
  7 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
  8 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  9 +import org.flowable.engine.runtime.ProcessInstance;
  10 +import org.flowable.task.service.impl.persistence.entity.TaskEntity;
  11 +import org.springframework.context.annotation.Lazy;
  12 +import org.springframework.stereotype.Component;
  13 +
  14 +import javax.annotation.Resource;
  15 +import java.util.Set;
  16 +
  17 +/**
  18 + * 分配给发起人审批的 Script 实现类
  19 + *
  20 + * @author 芋道源码
  21 + */
  22 +@Component
  23 +public class BpmTaskAssignStartUserScript implements BpmTaskAssignScript {
  24 +
  25 + @Resource
  26 + @Lazy // 解决循环依赖
  27 + private BpmProcessInstanceService bpmProcessInstanceService;
  28 +
  29 + @Override
  30 + public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
  31 + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId());
  32 + Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
  33 + return SetUtils.asSet(startUserId);
  34 + }
  35 +
  36 + @Override
  37 + public BpmTaskRuleScriptEnum getEnum() {
  38 + return BpmTaskRuleScriptEnum.START_USER;
  39 + }
  40 +
  41 +}
... ...
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
... ... @@ -5,6 +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.util.FlowableUtils;
8 9 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
9 10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
10 11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
... ... @@ -198,7 +199,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
198 199 BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes());
199 200 BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
200 201 //TODO 貌似 flowable 不修改这个也不同。需要看看。 sourceSystemId 不同
201   - if (equals(oldModel, newModel)) {
  202 + if (FlowableUtils.equals(oldModel, newModel)) {
202 203 return false;
203 204 }
204 205 // 最终发现都一致,则返回 true
... ... @@ -216,19 +217,8 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
216 217 BpmnXMLConverter converter = new BpmnXMLConverter();
217 218 return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
218 219 }
219   - //TODO 移出去
220   - public boolean equals(BpmnModel oldModel, BpmnModel newModel) {
221   - // 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
222   - return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
223   - }
224   - //TODO 移出去
225   - public byte[] getBpmnBytes(BpmnModel model) {
226   - if (model == null) {
227   - return new byte[0];
228   - }
229   - BpmnXMLConverter converter = new BpmnXMLConverter();
230   - return converter.convertToXML(model);
231   - }
  220 +
  221 +
232 222  
233 223 @Override
234 224 public BpmProcessDefinitionExtDO getProcessDefinitionExt(String id) {
... ...
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
... ... @@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
5 5 import cn.hutool.core.util.StrUtil;
6 6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
7 7 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  8 +import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
8 9 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
9 10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
10 11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
... ... @@ -87,37 +88,15 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService{
87 88 if (model == null) {
88 89 return Collections.emptyList();
89 90 }
90   -
91 91 // 获得用户任务,只有用户任务才可以设置分配规则
92   - List<UserTask> userTasks = getBpmnModelElements(model, UserTask.class);
  92 + List<UserTask> userTasks = FlowableUtils.getBpmnModelElements(model, UserTask.class);
93 93 if (CollUtil.isEmpty(userTasks)) {
94 94 return Collections.emptyList();
95 95 }
96   -
97 96 // 转换数据
98 97 return BpmTaskAssignRuleConvert.INSTANCE.convertList(userTasks, rules);
99 98 }
100 99  
101   - /**
102   - * TODO 需要移出去
103   - * 获得 BPMN 流程中,指定的元素们
104   - *
105   - * @param model
106   - * @param clazz 指定元素。例如说,{@link org.flowable.bpmn.model.UserTask}、{@link org.flowable.bpmn.model.Gateway} 等等
107   - * @return 元素们
108   - */
109   - public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {
110   - List<T> result = new ArrayList<>();
111   - model.getProcesses().forEach(process -> {
112   - process.getFlowElements().forEach(flowElement -> {
113   - if (flowElement.getClass().isAssignableFrom(clazz)) {
114   - result.add((T) flowElement);
115   - }
116   - });
117   - });
118   - return result;
119   - }
120   -
121 100 @Override
122 101 public Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO) {
123 102 // 校验参数
... ...
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
... ... @@ -106,6 +106,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
106 106 }
107 107  
108 108 @Override
  109 + @Transactional(rollbackFor = Exception.class)
109 110 public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
110 111 // 获得流程定义
111 112 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
... ...
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
... ... @@ -25,6 +25,7 @@ import org.flowable.task.api.TaskQuery;
25 25 import org.flowable.task.api.history.HistoricTaskInstance;
26 26 import org.flowable.task.api.history.HistoricTaskInstanceQuery;
27 27 import org.springframework.stereotype.Service;
  28 +import org.springframework.transaction.annotation.Transactional;
28 29 import org.springframework.transaction.support.TransactionSynchronization;
29 30 import org.springframework.transaction.support.TransactionSynchronizationManager;
30 31  
... ... @@ -167,6 +168,7 @@ public class BpmTaskServiceImpl implements BpmTaskService{
167 168 }
168 169  
169 170 @Override
  171 + @Transactional(rollbackFor = Exception.class)
170 172 public void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO) {
171 173 // 校验任务存在
172 174 Task task = checkTask(userId, reqVO.getId());
... ... @@ -184,6 +186,7 @@ public class BpmTaskServiceImpl implements BpmTaskService{
184 186 }
185 187  
186 188 @Override
  189 + @Transactional(rollbackFor = Exception.class)
187 190 public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) {
188 191 Task task = checkTask(userId, reqVO.getId());
189 192 // 校验流程实例存在
... ... @@ -234,16 +237,15 @@ public class BpmTaskServiceImpl implements BpmTaskService{
234 237 .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()))
235 238 .setTaskId(task.getId());
236 239 taskExtMapper.updateByTaskId(taskExtDO);
237   - //TODO 创建任务时候 也会调用 updateTaskExtAssign, processInstance 名称为空 校验不通过
238 240 // 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
239   -// TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
240   -// @Override
241   -// public void afterCommit() {
242   -// ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
243   -// AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
244   -// messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
245   -// }
246   -// });
  241 + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  242 + @Override
  243 + public void afterCommit() {
  244 + ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
  245 + AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
  246 + messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
  247 + }
  248 + });
247 249 }
248 250  
249 251 /**
... ...