瀏覽代碼

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

jason 3 年之前
父節點
當前提交
e01acfb18e
共有 13 個文件被更改,包括 307 次插入54 次删除
  1. 48 0
      yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java
  2. 6 3
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java
  3. 6 2
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java
  4. 29 3
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
  5. 34 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java
  6. 71 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java
  7. 27 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
  8. 27 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
  9. 41 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java
  10. 4 14
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
  11. 2 23
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
  12. 1 0
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
  13. 11 9
      yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java

+ 48 - 0
yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java

@@ -1,7 +1,14 @@
 package cn.iocoder.yudao.framework.flowable.core.util;
 
+import org.flowable.bpmn.converter.BpmnXMLConverter;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.bpmn.model.FlowElement;
 import org.flowable.common.engine.impl.identity.Authentication;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
 public class FlowableUtils {
 
     public static void setAuthenticatedUserId(Long userId) {
@@ -11,4 +18,45 @@ public class FlowableUtils {
     public static void clearAuthenticatedUserId() {
         Authentication.setAuthenticatedUserId(null);
     }
+
+    /**
+     * 获得 BPMN 流程中,指定的元素们
+     *
+     * @param model
+     * @param clazz 指定元素。例如说,{@link org.flowable.bpmn.model.UserTask}、{@link org.flowable.bpmn.model.Gateway} 等等
+     * @return 元素们
+     */
+    public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {
+        List<T> result = new ArrayList<>();
+        model.getProcesses().forEach(process -> {
+            process.getFlowElements().forEach(flowElement -> {
+                if (flowElement.getClass().isAssignableFrom(clazz)) {
+                    result.add((T) flowElement);
+                }
+            });
+        });
+        return result;
+    }
+
+    /**
+     * 比较 两个bpmnModel 是否相同
+     * @param oldModel  老的bpmn model
+     * @param newModel 新的bpmn model
+     */
+    public static boolean equals(BpmnModel oldModel, BpmnModel newModel) {
+        // 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
+        return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
+    }
+
+    /**
+     * 把 bpmnModel 转换成 byte[]
+     * @param model  bpmnModel
+     */
+    public  static byte[] getBpmnBytes(BpmnModel model) {
+        if (model == null) {
+            return new byte[0];
+        }
+        BpmnXMLConverter converter = new BpmnXMLConverter();
+        return converter.convertToXML(model);
+    }
 }

+ 6 - 3
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.bpm.framework.flowable.config;
 
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.BpmActivityBehaviorFactory;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmProcessInstanceEventListener;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
@@ -27,8 +28,9 @@ import java.util.List;
 public class BpmFlowableConfiguration {
 
     /**
-     * 将自定义 listener 加入全局listener
+     * Flowable engines 自定义的配置
      * @param  listeners 自定义 listener
+     * @param  bpmActivityBehaviorFactory 自定义的 ActivityBehaviorFactory 实现
      */
     @Bean
     public EngineConfigurationConfigurer<SpringProcessEngineConfiguration> addCustomerListenerConfigurer (ObjectProvider<FlowableEventListener> listeners,
@@ -51,14 +53,15 @@ public class BpmFlowableConfiguration {
                                                                  BpmUserGroupService userGroupService,
                                                                  PermissionApi permissionApi,
                                                                  DeptApi deptApi,
-                                                                 AdminUserApi adminUserApi) {
+                                                                 AdminUserApi adminUserApi,
+                                                                 List<BpmTaskAssignScript> scripts) {
         BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory();
         bpmActivityBehaviorFactory.setBpmTaskRuleService(taskRuleService);
         bpmActivityBehaviorFactory.setUserGroupService(userGroupService);
         bpmActivityBehaviorFactory.setAdminUserApi(adminUserApi);
         bpmActivityBehaviorFactory.setPermissionApi(permissionApi);
         bpmActivityBehaviorFactory.setDeptApi(deptApi);
-//        bpmActivityBehaviorFactory.setScripts(scripts);
+        bpmActivityBehaviorFactory.setScripts(scripts);
         return bpmActivityBehaviorFactory;
     }
 }

+ 6 - 2
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
 
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
@@ -13,6 +14,8 @@ import org.flowable.bpmn.model.UserTask;
 import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
 import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;
 
+import java.util.List;
+
 /**
  * 自定义的 ActivityBehaviorFactory 实现类,目的如下:
  * 1. 自定义 {@link #createUserTaskActivityBehavior(UserTask)}:实现自定义的流程任务的 assignee 负责人的分配
@@ -35,6 +38,8 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
     private DeptApi deptApi;
     @Setter
     private AdminUserApi adminUserApi;
+    @Setter
+    private List<BpmTaskAssignScript> scripts;
 
     @Override
     public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) {
@@ -44,8 +49,7 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
         userTaskActivityBehavior.setDeptApi(deptApi);
         userTaskActivityBehavior.setUserGroupService(userGroupService);
         userTaskActivityBehavior.setAdminUserApi(adminUserApi);
-        //TODO
-        //userTaskActivityBehavior.setScripts(scripts);
+        userTaskActivityBehavior.setScripts(scripts);
         return userTaskActivityBehavior;
     }
 }

+ 29 - 3
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;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
 import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
@@ -30,8 +31,10 @@ import org.flowable.task.service.impl.persistence.entity.TaskEntity;
 import java.util.*;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS;
 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER;
 
 /**
@@ -56,9 +59,17 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
     @Setter
     private PermissionApi permissionApi;
 
+    /**
+     * 任务分配脚本
+     */
+    private Map<Long, BpmTaskAssignScript> scriptMap = Collections.emptyMap();
+
     public BpmUserTaskActivityBehavior(UserTask userTask) {
         super(userTask);
     }
+    public void setScripts(List<BpmTaskAssignScript> scripts) {
+        this.scriptMap = convertMap(scripts, script -> script.getEnum().getId());
+    }
 
     @Override
     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 {
             assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule);
         } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) {
             assigneeUserIds = calculateTaskCandidateUsersByUserGroup(task, rule);
+        } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) {
+            assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule);
         }
-//        else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) {
-//            assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule);
-//        }
 
         // 移除被禁用的用户
         removeDisableUsers(assigneeUserIds);
@@ -146,6 +156,22 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
         return userIds;
     }
 
+    private Set<Long> calculateTaskCandidateUsersByScript(TaskEntity task, BpmTaskAssignRuleDO rule) {
+        // 获得对应的脚本
+        List<BpmTaskAssignScript> scripts = new ArrayList<>(rule.getOptions().size());
+        rule.getOptions().forEach(id -> {
+            BpmTaskAssignScript script = scriptMap.get(id);
+            if (script == null) {
+                throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, id);
+            }
+            scripts.add(script);
+        });
+        // 逐个计算任务
+        Set<Long> userIds = new HashSet<>();
+        scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(task)));
+        return userIds;
+    }
+
     private Long chooseTaskAssignee(Set<Long> candidateUserIds) {
         // TODO 芋艿:未来可以优化下,改成轮询的策略
         int index = RandomUtil.randomInt(candidateUserIds.size());

+ 34 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script;
+
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+import org.flowable.task.service.impl.persistence.entity.TaskEntity;
+
+import java.util.Set;
+
+/**
+ * Bpm 任务分配的自定义 Script 脚本
+ * 使用场景:
+ * 1. 设置审批人为发起人
+ * 2. 设置审批人为发起人的 Leader
+ * 3. 甚至审批人为发起人的 Leader 的 Leader
+ *
+ * @author 芋道源码
+ */
+public interface BpmTaskAssignScript {
+
+    /**
+     * 基于流程任务,获得任务的候选用户们
+     *
+     * @param task 任务
+     * @return 候选人用户的编号数组
+     */
+    Set<Long> calculateTaskCandidateUsers(TaskEntity task);
+
+    /**
+     * 获得枚举值
+     *
+     * @return 枚举值
+     */
+    BpmTaskRuleScriptEnum getEnum();
+}
+

+ 71 - 0
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,0 +1,71 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
+
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
+import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.service.impl.persistence.entity.TaskEntity;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.util.Assert;
+
+import javax.annotation.Resource;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
+import static java.util.Collections.emptySet;
+
+/**
+ * 分配给发起人的 Leader 审批的 Script 实现类
+ * 目前 Leader 的定义是,
+ *
+ * @author 芋道源码
+ */
+public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript {
+
+    @Resource
+    private AdminUserApi adminUserApi;
+    @Resource
+    private DeptApi deptApi;
+    @Resource
+    @Lazy // 解决循环依赖
+    private BpmProcessInstanceService bpmProcessInstanceService;
+
+    protected Set<Long> calculateTaskCandidateUsers(TaskEntity task, int level) {
+        Assert.isTrue(level > 0, "level 必须大于 0");
+        // 获得发起人
+        ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId());
+        Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
+        // 获得对应 leve 的部门
+        DeptRespDTO dept = null;
+        for (int i = 0; i < level; i++) {
+            // 获得 level 对应的部门
+            if (dept == null) {
+                dept = getStartUserDept(startUserId);
+                if (dept == null) { // 找不到发起人的部门,所以无法使用该规则
+                    return emptySet();
+                }
+            } else {
+                DeptRespDTO parentDept = deptApi.getDept(dept.getParentId());
+                if (parentDept == null) { // 找不到父级部门,所以只好结束寻找。原因是:例如说,级别比较高的人,所在部门层级比较少
+                    break;
+                }
+                dept = parentDept;
+            }
+        }
+        return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet();
+    }
+
+    private DeptRespDTO getStartUserDept(Long startUserId) {
+        AdminUserRespDTO startUser = adminUserApi.getUser(startUserId);
+        if (startUser.getDeptId() == null) { // 找不到部门,所以无法使用该规则
+            return null;
+        }
+        return deptApi.getDept(startUser.getDeptId());
+    }
+
+}

+ 27 - 0
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,0 +1,27 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
+
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+import org.flowable.task.service.impl.persistence.entity.TaskEntity;
+import org.springframework.stereotype.Component;
+
+import java.util.Set;
+
+/**
+ * 分配给发起人的一级 Leader 审批的 Script 实现类
+ *
+ * @author 芋道源码
+ */
+@Component
+public class BpmTaskAssignLeaderX1Script extends BpmTaskAssignLeaderAbstractScript {
+
+    @Override
+    public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
+        return calculateTaskCandidateUsers(task, 1);
+    }
+
+    @Override
+    public BpmTaskRuleScriptEnum getEnum() {
+        return BpmTaskRuleScriptEnum.LEADER_X1;
+    }
+
+}

+ 27 - 0
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,0 +1,27 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
+
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+import org.flowable.task.service.impl.persistence.entity.TaskEntity;
+import org.springframework.stereotype.Component;
+
+import java.util.Set;
+
+/**
+ * 分配给发起人的二级 Leader 审批的 Script 实现类
+ *
+ * @author 芋道源码
+ */
+@Component
+public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript {
+
+    @Override
+    public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
+        return calculateTaskCandidateUsers(task, 2);
+    }
+
+    @Override
+    public BpmTaskRuleScriptEnum getEnum() {
+        return BpmTaskRuleScriptEnum.LEADER_X2;
+    }
+
+}

+ 41 - 0
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,0 +1,41 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
+
+import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
+import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.service.impl.persistence.entity.TaskEntity;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Set;
+
+/**
+ * 分配给发起人审批的 Script 实现类
+ *
+ * @author 芋道源码
+ */
+@Component
+public class BpmTaskAssignStartUserScript implements BpmTaskAssignScript {
+
+    @Resource
+    @Lazy // 解决循环依赖
+    private BpmProcessInstanceService bpmProcessInstanceService;
+
+    @Override
+    public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
+        ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId());
+        Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
+        return SetUtils.asSet(startUserId);
+    }
+
+    @Override
+    public BpmTaskRuleScriptEnum getEnum() {
+        return BpmTaskRuleScriptEnum.START_USER;
+    }
+
+}

+ 4 - 14
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;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
+import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
@@ -198,7 +199,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
         BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes());
         BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
         //TODO  貌似 flowable 不修改这个也不同。需要看看。 sourceSystemId 不同
-        if (equals(oldModel, newModel)) {
+        if (FlowableUtils.equals(oldModel, newModel)) {
             return false;
         }
         // 最终发现都一致,则返回 true
@@ -216,19 +217,8 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
         BpmnXMLConverter converter = new BpmnXMLConverter();
         return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
     }
-    //TODO 移出去
-    public  boolean equals(BpmnModel oldModel, BpmnModel newModel) {
-        // 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
-        return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
-    }
-    //TODO 移出去
-    public  byte[] getBpmnBytes(BpmnModel model) {
-        if (model == null) {
-            return new byte[0];
-        }
-        BpmnXMLConverter converter = new BpmnXMLConverter();
-        return converter.convertToXML(model);
-    }
+
+
 
     @Override
     public BpmProcessDefinitionExtDO getProcessDefinitionExt(String id) {

+ 2 - 23
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;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
+import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
@@ -87,37 +88,15 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService{
         if (model == null) {
             return Collections.emptyList();
         }
-
         // 获得用户任务,只有用户任务才可以设置分配规则
-        List<UserTask> userTasks = getBpmnModelElements(model, UserTask.class);
+        List<UserTask> userTasks = FlowableUtils.getBpmnModelElements(model, UserTask.class);
         if (CollUtil.isEmpty(userTasks)) {
             return Collections.emptyList();
         }
-
         // 转换数据
         return BpmTaskAssignRuleConvert.INSTANCE.convertList(userTasks, rules);
     }
 
-    /**
-     * TODO 需要移出去
-     * 获得 BPMN 流程中,指定的元素们
-     *
-     * @param model
-     * @param clazz 指定元素。例如说,{@link org.flowable.bpmn.model.UserTask}、{@link org.flowable.bpmn.model.Gateway} 等等
-     * @return 元素们
-     */
-    public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {
-        List<T> result = new ArrayList<>();
-        model.getProcesses().forEach(process -> {
-            process.getFlowElements().forEach(flowElement -> {
-                if (flowElement.getClass().isAssignableFrom(clazz)) {
-                    result.add((T) flowElement);
-                }
-            });
-        });
-        return result;
-    }
-
     @Override
     public Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO) {
         // 校验参数

+ 1 - 0
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
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
         // 获得流程定义
         ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());

+ 11 - 9
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;
 import org.flowable.task.api.history.HistoricTaskInstance;
 import org.flowable.task.api.history.HistoricTaskInstanceQuery;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.support.TransactionSynchronization;
 import org.springframework.transaction.support.TransactionSynchronizationManager;
 
@@ -167,6 +168,7 @@ public class BpmTaskServiceImpl implements BpmTaskService{
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO) {
         // 校验任务存在
         Task task = checkTask(userId, reqVO.getId());
@@ -184,6 +186,7 @@ public class BpmTaskServiceImpl implements BpmTaskService{
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) {
         Task task = checkTask(userId, reqVO.getId());
         // 校验流程实例存在
@@ -234,16 +237,15 @@ public class BpmTaskServiceImpl implements BpmTaskService{
                 .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()))
                 .setTaskId(task.getId());
         taskExtMapper.updateByTaskId(taskExtDO);
-        //TODO  创建任务时候 也会调用 updateTaskExtAssign, processInstance 名称为空 校验不通过
         // 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
-//        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
-//            @Override
-//            public void afterCommit() {
-//                ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
-//                AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
-//                messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
-//            }
-//        });
+        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+            @Override
+            public void afterCommit() {
+                ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
+                AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
+                messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
+            }
+        });
     }
 
     /**