Commit 5c3f30e60f74f5b54326f89f549fb563b1abf2bc

Authored by YunaiV
1 parent 692daf90

flowable 任务被取消(包括主动取消、会签取消)时,统一进行更新 task 状态。

Showing 36 changed files with 187 additions and 386 deletions
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/definition/BpmModelFormTypeEnum.java renamed to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelFormTypeEnum.java
1 -package cn.iocoder.yudao.module.bpm.domain.enums.definition; 1 +package cn.iocoder.yudao.module.bpm.enums.definition;
2 2
3 import lombok.AllArgsConstructor; 3 import lombok.AllArgsConstructor;
4 import lombok.Getter; 4 import lombok.Getter;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/definition/BpmTaskAssignRuleTypeEnum.java renamed to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java
1 -package cn.iocoder.yudao.module.bpm.domain.enums.definition; 1 +package cn.iocoder.yudao.module.bpm.enums.definition;
2 2
3 import lombok.AllArgsConstructor; 3 import lombok.AllArgsConstructor;
4 import lombok.Getter; 4 import lombok.Getter;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/definition/BpmTaskRuleScriptEnum.java renamed to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java
1 -package cn.iocoder.yudao.module.bpm.domain.enums.definition; 1 +package cn.iocoder.yudao.module.bpm.enums.definition;
2 2
3 import lombok.AllArgsConstructor; 3 import lombok.AllArgsConstructor;
4 import lombok.Getter; 4 import lombok.Getter;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/message/BpmMessageEnum.java renamed to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/message/BpmMessageEnum.java
1 -package cn.iocoder.yudao.module.bpm.domain.enums.message; 1 +package cn.iocoder.yudao.module.bpm.enums.message;
2 2
3 import lombok.AllArgsConstructor; 3 import lombok.AllArgsConstructor;
4 import lombok.Getter; 4 import lombok.Getter;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/task/BpmProcessInstanceDeleteReasonEnum.java renamed to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceDeleteReasonEnum.java
1 -package cn.iocoder.yudao.module.bpm.domain.enums.task; 1 +package cn.iocoder.yudao.module.bpm.enums.task;
2 2
3 import cn.hutool.core.util.StrUtil; 3 import cn.hutool.core.util.StrUtil;
4 import lombok.AllArgsConstructor; 4 import lombok.AllArgsConstructor;
@@ -14,7 +14,12 @@ import lombok.Getter; @@ -14,7 +14,12 @@ import lombok.Getter;
14 public enum BpmProcessInstanceDeleteReasonEnum { 14 public enum BpmProcessInstanceDeleteReasonEnum {
15 15
16 REJECT_TASK("不通过任务,原因:{}"), // 修改文案时,需要注意 isRejectReason 方法 16 REJECT_TASK("不通过任务,原因:{}"), // 修改文案时,需要注意 isRejectReason 方法
17 - CANCEL_TASK("主动取消任务,原因:{}"); 17 + CANCEL_TASK("主动取消任务,原因:{}"),
  18 +
  19 + // ========== 流程任务的独有原因 ==========
  20 + MULTI_TASK_END("系统自动取消,原因:多任务审批已经满足条件,无需审批该任务"), // 多实例满足 condition 而结束时,其它任务实例任务会被取消,对应的删除原因是 MI_END
  21 +
  22 + ;
18 23
19 private final String reason; 24 private final String reason;
20 25
@@ -34,4 +39,20 @@ public enum BpmProcessInstanceDeleteReasonEnum { @@ -34,4 +39,20 @@ public enum BpmProcessInstanceDeleteReasonEnum {
34 return StrUtil.startWith(reason, "不通过任务,原因:"); 39 return StrUtil.startWith(reason, "不通过任务,原因:");
35 } 40 }
36 41
  42 + /**
  43 + * 将 Flowable 的删除原因,翻译成对应的中文原因
  44 + *
  45 + * @param reason 原始原因
  46 + * @return 原因
  47 + */
  48 + public static String translateReason(String reason) {
  49 + if (StrUtil.isEmpty(reason)) {
  50 + return reason;
  51 + }
  52 + switch (reason) {
  53 + case "MI_END": return MULTI_TASK_END.getReason();
  54 + default: return reason;
  55 + }
  56 + }
  57 +
37 } 58 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/task/BpmProcessInstanceResultEnum.java renamed to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceResultEnum.java
1 -package cn.iocoder.yudao.module.bpm.domain.enums.task; 1 +package cn.iocoder.yudao.module.bpm.enums.task;
2 2
  3 +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
3 import lombok.AllArgsConstructor; 4 import lombok.AllArgsConstructor;
4 import lombok.Getter; 5 import lombok.Getter;
5 6
@@ -16,10 +17,15 @@ public enum BpmProcessInstanceResultEnum { @@ -16,10 +17,15 @@ public enum BpmProcessInstanceResultEnum {
16 APPROVE(2, "通过"), 17 APPROVE(2, "通过"),
17 REJECT(3, "不通过"), 18 REJECT(3, "不通过"),
18 CANCEL(4, "已取消"), 19 CANCEL(4, "已取消"),
  20 +
  21 + // ========== 流程任务独有的状态 ==========
  22 +
19 BACK(5, "退回/驳回"); 23 BACK(5, "退回/驳回");
20 24
21 /** 25 /**
22 * 结果 26 * 结果
  27 + *
  28 + * 如果新增时,注意 {@link #isEndResult(Integer)} 是否需要变更
23 */ 29 */
24 private final Integer result; 30 private final Integer result;
25 /** 31 /**
@@ -27,4 +33,16 @@ public enum BpmProcessInstanceResultEnum { @@ -27,4 +33,16 @@ public enum BpmProcessInstanceResultEnum {
27 */ 33 */
28 private final String desc; 34 private final String desc;
29 35
  36 + /**
  37 + * 判断该结果是否已经处于 End 最终结果
  38 + *
  39 + * 主要用于一些结果更新的逻辑,如果已经是最终结果,就不再进行更新
  40 + *
  41 + * @param result 结果
  42 + * @return 是否
  43 + */
  44 + public static boolean isEndResult(Integer result) {
  45 + return ObjectUtils.equalsAny(result, APPROVE.getResult(), REJECT.getResult(), CANCEL.getResult(), BACK.getResult());
  46 + }
  47 +
30 } 48 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/enums/task/BpmProcessInstanceStatusEnum.java renamed to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java
1 -package cn.iocoder.yudao.module.bpm.domain.enums.task; 1 +package cn.iocoder.yudao.module.bpm.enums.task;
2 2
3 import lombok.AllArgsConstructor; 3 import lombok.AllArgsConstructor;
4 import lombok.Getter; 4 import lombok.Getter;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
@@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskDonePage @@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskDonePage
7 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; 7 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
8 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO; 8 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO;
9 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; 9 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
10 -import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum; 10 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
11 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; 11 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
12 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; 12 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
13 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; 13 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
@@ -192,4 +192,4 @@ public interface BpmTaskConvert { @@ -192,4 +192,4 @@ public interface BpmTaskConvert {
192 tmpMap.forEach((key, var) -> result.add(var)); 192 tmpMap.forEach((key, var) -> result.add(var));
193 return result; 193 return result;
194 } 194 }
195 -}  
196 \ No newline at end of file 195 \ No newline at end of file
  196 +}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java
1 package cn.iocoder.yudao.module.bpm.dal.dataobject.definition; 1 package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum; 4 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
5 import com.baomidou.mybatisplus.annotation.TableField; 5 import com.baomidou.mybatisplus.annotation.TableField;
6 import com.baomidou.mybatisplus.annotation.TableId; 6 import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 7 import com.baomidou.mybatisplus.annotation.TableName;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmTaskAssignRuleDO.java
@@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.definition; @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; 4 import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
5 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;  
6 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum; 5 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
  6 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
7 import com.baomidou.mybatisplus.annotation.TableField; 7 import com.baomidou.mybatisplus.annotation.TableField;
8 import com.baomidou.mybatisplus.annotation.TableId; 8 import com.baomidou.mybatisplus.annotation.TableId;
9 import com.baomidou.mybatisplus.annotation.TableName; 9 import com.baomidou.mybatisplus.annotation.TableName;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java
1 package cn.iocoder.yudao.module.bpm.dal.dataobject.oa; 1 package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
2 2
3 -import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum; 3 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
4 import lombok.*; 4 import lombok.*;
5 import java.util.*; 5 import java.util.*;
6 import com.baomidou.mybatisplus.annotation.*; 6 import com.baomidou.mybatisplus.annotation.*;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java
1 package cn.iocoder.yudao.module.bpm.dal.dataobject.task; 1 package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 -import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;  
5 -import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceStatusEnum; 4 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
  5 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
6 import com.baomidou.mybatisplus.annotation.TableField; 6 import com.baomidou.mybatisplus.annotation.TableField;
7 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
8 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java
1 package cn.iocoder.yudao.module.bpm.dal.dataobject.task; 1 package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 -import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum; 4 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
5 import com.baomidou.mybatisplus.annotation.TableId; 5 import com.baomidou.mybatisplus.annotation.TableId;
6 import com.baomidou.mybatisplus.annotation.TableName; 6 import com.baomidou.mybatisplus.annotation.TableName;
7 import lombok.Data; 7 import lombok.Data;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java
@@ -20,18 +20,15 @@ public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> { @@ -20,18 +20,15 @@ public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> {
20 return selectList(BpmTaskExtDO::getTaskId, taskIds); 20 return selectList(BpmTaskExtDO::getTaskId, taskIds);
21 } 21 }
22 22
  23 + default BpmTaskExtDO selectByTaskId(String taskId) {
  24 + return selectOne(BpmTaskExtDO::getTaskId, taskId);
  25 + }
  26 +
23 default List<BpmTaskExtDO> selectListByProcessInstanceId(String processInstanceId) { 27 default List<BpmTaskExtDO> selectListByProcessInstanceId(String processInstanceId) {
24 return selectList(BpmTaskExtDO::getProcessInstanceId, processInstanceId); 28 return selectList(BpmTaskExtDO::getProcessInstanceId, processInstanceId);
25 } 29 }
26 30
27 /** 31 /**
28 - * 删除非当前相同taskDefKey非进行中的任务  
29 - *  
30 - * @param entity 任务信息  
31 - */  
32 - void delTaskByProcInstIdAndTaskIdAndTaskDefKey(@Param("entity") BpmTaskExtDO entity);  
33 -  
34 - /**  
35 * 任务驳回 32 * 任务驳回
36 * 33 *
37 * @param taskId 任务列表 34 * @param taskId 任务列表
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/domain/vo/ApproveProcInstVO.java
@@ -15,6 +15,7 @@ import java.time.LocalDate; @@ -15,6 +15,7 @@ import java.time.LocalDate;
15 @Data 15 @Data
16 @AllArgsConstructor 16 @AllArgsConstructor
17 @NoArgsConstructor 17 @NoArgsConstructor
  18 +// TODO @ke:这个类是不是没用呀
18 public class ApproveProcInstVO { 19 public class ApproveProcInstVO {
19 20
20 @ApiModelProperty("任务id") 21 @ApiModelProperty("任务id")
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
@@ -57,7 +57,8 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { @@ -57,7 +57,8 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
57 Set<Long> candidateUserIds = bpmTaskRuleService.calculateTaskCandidateUsers(execution); 57 Set<Long> candidateUserIds = bpmTaskRuleService.calculateTaskCandidateUsers(execution);
58 // 第二步,后随机选择一个任务的处理人 58 // 第二步,后随机选择一个任务的处理人
59 // 疑问:为什么一定要选择一个任务处理人? 59 // 疑问:为什么一定要选择一个任务处理人?
60 - // 解答:项目对 bpm 的任务是责任到人,所以每个任务有且仅有一个处理人。如果希望一个任务可以同时被多个人处理,可以考虑使用 BpmParallelMultiInstanceBehavior 实现的会签 or 或签。 60 + // 解答:项目对 bpm 的任务是责任到人,所以每个任务有且仅有一个处理人。
  61 + // 如果希望一个任务可以同时被多个人处理,可以考虑使用 BpmParallelMultiInstanceBehavior 实现的会签 or 或签。
61 int index = RandomUtil.randomInt(candidateUserIds.size()); 62 int index = RandomUtil.randomInt(candidateUserIds.size());
62 return CollUtil.get(candidateUserIds, index); 63 return CollUtil.get(candidateUserIds, index);
63 } 64 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java
1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script; 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script;
2 2
3 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum; 3 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
4 import org.flowable.engine.delegate.DelegateExecution; 4 import org.flowable.engine.delegate.DelegateExecution;
5 5
6 import java.util.Set; 6 import java.util.Set;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
2 2
3 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum; 3 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
4 import org.flowable.engine.delegate.DelegateExecution; 4 import org.flowable.engine.delegate.DelegateExecution;
5 import org.springframework.stereotype.Component; 5 import org.springframework.stereotype.Component;
6 6
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
2 2
3 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum; 3 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
4 import org.flowable.engine.delegate.DelegateExecution; 4 import org.flowable.engine.delegate.DelegateExecution;
5 import org.springframework.stereotype.Component; 5 import org.springframework.stereotype.Component;
6 6
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl
2 2
3 import cn.iocoder.yudao.framework.common.util.collection.SetUtils; 3 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
4 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 4 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
5 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum; 5 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
6 import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; 6 import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
7 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; 7 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
8 import org.flowable.engine.delegate.DelegateExecution; 8 import org.flowable.engine.delegate.DelegateExecution;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java
1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener; 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
2 2
  3 +import cn.hutool.core.util.StrUtil;
3 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; 4 import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
  5 +import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService;
4 import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; 6 import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
5 import com.google.common.collect.ImmutableSet; 7 import com.google.common.collect.ImmutableSet;
  8 +import lombok.extern.slf4j.Slf4j;
6 import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent; 9 import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
7 import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType; 10 import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
8 import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener; 11 import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
  12 +import org.flowable.engine.delegate.event.FlowableActivityCancelledEvent;
  13 +import org.flowable.engine.history.HistoricActivityInstance;
9 import org.flowable.task.api.Task; 14 import org.flowable.task.api.Task;
10 import org.springframework.context.annotation.Lazy; 15 import org.springframework.context.annotation.Lazy;
11 import org.springframework.stereotype.Component; 16 import org.springframework.stereotype.Component;
@@ -19,16 +24,22 @@ import java.util.Set; @@ -19,16 +24,22 @@ import java.util.Set;
19 * @author jason 24 * @author jason
20 */ 25 */
21 @Component 26 @Component
  27 +@Slf4j
22 public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { 28 public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
23 29
24 @Resource 30 @Resource
25 @Lazy // 解决循环依赖 31 @Lazy // 解决循环依赖
26 private BpmTaskService taskService; 32 private BpmTaskService taskService;
27 33
  34 + @Resource
  35 + @Lazy // 解决循环依赖
  36 + private BpmActivityService activityService;
  37 +
28 public static final Set<FlowableEngineEventType> TASK_EVENTS = ImmutableSet.<FlowableEngineEventType>builder() 38 public static final Set<FlowableEngineEventType> TASK_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
29 .add(FlowableEngineEventType.TASK_CREATED) 39 .add(FlowableEngineEventType.TASK_CREATED)
30 .add(FlowableEngineEventType.TASK_ASSIGNED) 40 .add(FlowableEngineEventType.TASK_ASSIGNED)
31 .add(FlowableEngineEventType.TASK_COMPLETED) 41 .add(FlowableEngineEventType.TASK_COMPLETED)
  42 + .add(FlowableEngineEventType.ACTIVITY_CANCELLED)
32 .build(); 43 .build();
33 44
34 public BpmTaskEventListener(){ 45 public BpmTaskEventListener(){
@@ -49,4 +60,18 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { @@ -49,4 +60,18 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
49 protected void taskAssigned(FlowableEngineEntityEvent event) { 60 protected void taskAssigned(FlowableEngineEntityEvent event) {
50 taskService.updateTaskExtAssign((Task)event.getEntity()); 61 taskService.updateTaskExtAssign((Task)event.getEntity());
51 } 62 }
  63 +
  64 + @Override
  65 + protected void activityCancelled(FlowableActivityCancelledEvent event) {
  66 + HistoricActivityInstance activity = activityService.getHistoricActivityByExecutionId(event.getExecutionId());
  67 + if (activity == null) {
  68 + log.error("[activityCancelled][使用 executionId({}) 查找不到对应的活动实例]", event.getExecutionId());
  69 + return;
  70 + }
  71 + if (StrUtil.isEmpty(activity.getTaskId())) {
  72 + return;
  73 + }
  74 + taskService.updateTaskExtCancel(activity.getTaskId());
  75 + }
  76 +
52 } 77 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java
@@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmFormConvert; @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmFormConvert;
9 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; 9 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
10 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper; 10 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper;
11 import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants; 11 import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
12 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum; 12 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
13 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO; 13 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
14 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; 14 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
15 import cn.iocoder.yudao.framework.common.pojo.PageResult; 15 import cn.iocoder.yudao.framework.common.pojo.PageResult;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
@@ -10,7 +10,7 @@ import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; @@ -10,7 +10,7 @@ import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*; 10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
11 import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert; 11 import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
12 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; 12 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
13 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum; 13 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
14 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO; 14 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
15 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; 15 import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
16 import lombok.extern.slf4j.Slf4j; 16 import lombok.extern.slf4j.Slf4j;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
@@ -15,7 +15,7 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert; @@ -15,7 +15,7 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert;
15 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; 15 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
16 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; 16 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
17 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; 17 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
18 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum; 18 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
19 import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants; 19 import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
20 import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; 20 import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
21 import cn.iocoder.yudao.module.system.api.dept.DeptApi; 21 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
@@ -274,7 +274,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { @@ -274,7 +274,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
274 274
275 // 移除被禁用的用户 275 // 移除被禁用的用户
276 removeDisableUsers(assigneeUserIds); 276 removeDisableUsers(assigneeUserIds);
277 - // 如果候选人为空,抛出异常 TODO 芋艿:没候选人的策略选择。1 - 挂起;2 - 直接结束;3 - 强制一个兜底人 277 + // 如果候选人为空,抛出异常
278 if (CollUtil.isEmpty(assigneeUserIds)) { 278 if (CollUtil.isEmpty(assigneeUserIds)) {
279 log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}) 找不到候选人]", execution.getId(), 279 log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}) 找不到候选人]", execution.getId(),
280 execution.getProcessDefinitionId(), execution.getCurrentActivityId(), toJsonString(rule)); 280 execution.getProcessDefinitionId(), execution.getCurrentActivityId(), toJsonString(rule));
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java
1 package cn.iocoder.yudao.module.bpm.service.definition.dto; 1 package cn.iocoder.yudao.module.bpm.service.definition.dto;
2 2
3 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum; 3 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
4 import lombok.Data; 4 import lombok.Data;
5 5
6 /** 6 /**
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.definition.dto; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.definition.dto;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
5 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmModelFormTypeEnum; 5 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
6 import lombok.Data; 6 import lombok.Data;
7 7
8 import javax.validation.constraints.AssertTrue; 8 import javax.validation.constraints.AssertTrue;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.message; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.message;
2 2
3 import cn.iocoder.yudao.framework.web.config.WebProperties; 3 import cn.iocoder.yudao.framework.web.config.WebProperties;
4 import cn.iocoder.yudao.module.bpm.convert.message.BpmMessageConvert; 4 import cn.iocoder.yudao.module.bpm.convert.message.BpmMessageConvert;
5 -import cn.iocoder.yudao.module.bpm.domain.enums.message.BpmMessageEnum; 5 +import cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum;
6 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO; 6 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
7 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO; 7 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
8 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; 8 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java
@@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeavePageReqVO; @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeavePageReqVO;
9 import cn.iocoder.yudao.module.bpm.convert.oa.BpmOALeaveConvert; 9 import cn.iocoder.yudao.module.bpm.convert.oa.BpmOALeaveConvert;
10 import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO; 10 import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO;
11 import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOALeaveMapper; 11 import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOALeaveMapper;
12 -import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum; 12 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
13 import org.springframework.stereotype.Service; 13 import org.springframework.stereotype.Service;
14 import org.springframework.transaction.annotation.Transactional; 14 import org.springframework.transaction.annotation.Transactional;
15 import org.springframework.validation.annotation.Validated; 15 import org.springframework.validation.annotation.Validated;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityService.java
1 package cn.iocoder.yudao.module.bpm.service.task; 1 package cn.iocoder.yudao.module.bpm.service.task;
2 2
3 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO; 3 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
  4 +import org.flowable.engine.history.HistoricActivityInstance;
4 5
5 import java.util.List; 6 import java.util.List;
6 7
@@ -19,4 +20,12 @@ public interface BpmActivityService { @@ -19,4 +20,12 @@ public interface BpmActivityService {
19 */ 20 */
20 List<BpmActivityRespVO> getActivityListByProcessInstanceId(String processInstanceId); 21 List<BpmActivityRespVO> getActivityListByProcessInstanceId(String processInstanceId);
21 22
  23 + /**
  24 + * 获得执行编号对应的活动实例
  25 + *
  26 + * @param executionId 执行编号
  27 + * @return 活动实例
  28 + */
  29 + HistoricActivityInstance getHistoricActivityByExecutionId(String executionId);
  30 +
22 } 31 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper; @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper;
8 import lombok.extern.slf4j.Slf4j; 8 import lombok.extern.slf4j.Slf4j;
9 9
10 import org.flowable.engine.HistoryService; 10 import org.flowable.engine.HistoryService;
  11 +import org.flowable.engine.history.HistoricActivityInstance;
11 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
12 import org.springframework.validation.annotation.Validated; 13 import org.springframework.validation.annotation.Validated;
13 14
@@ -38,4 +39,10 @@ public class BpmActivityServiceImpl implements BpmActivityService { @@ -38,4 +39,10 @@ public class BpmActivityServiceImpl implements BpmActivityService {
38 List<BpmActivityDO> bpmActivityDOList = bpmActivityMapper.listAllByProcInstIdAndDelete(procInstId); 39 List<BpmActivityDO> bpmActivityDOList = bpmActivityMapper.listAllByProcInstIdAndDelete(procInstId);
39 return BpmActivityConvert.INSTANCE.convertList(bpmActivityDOList); 40 return BpmActivityConvert.INSTANCE.convertList(bpmActivityDOList);
40 } 41 }
  42 +
  43 + @Override
  44 + public HistoricActivityInstance getHistoricActivityByExecutionId(String executionId) {
  45 + return historyService.createHistoricActivityInstanceQuery().executionId(executionId).singleResult();
  46 + }
  47 +
41 } 48 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
1 -package cn.iocoder.yudao.module.bpm.service.task;  
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.pojo.PageResult;  
7 -import cn.iocoder.yudao.framework.common.util.number.NumberUtils;  
8 -import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;  
9 -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;  
10 -import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;  
11 -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;  
12 -import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;  
13 -import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;  
14 -import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceDeleteReasonEnum;  
15 -import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;  
16 -import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceStatusEnum;  
17 -import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher;  
18 -import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;  
19 -import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;  
20 -import cn.iocoder.yudao.module.system.api.dept.DeptApi;  
21 -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;  
22 -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;  
23 -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;  
24 -import lombok.extern.slf4j.Slf4j;  
25 -import org.flowable.engine.HistoryService;  
26 -import org.flowable.engine.RuntimeService;  
27 -import org.flowable.engine.delegate.event.FlowableCancelledEvent;  
28 -import org.flowable.engine.history.HistoricProcessInstance;  
29 -import org.flowable.engine.repository.ProcessDefinition;  
30 -import org.flowable.engine.runtime.ProcessInstance;  
31 -import org.flowable.task.api.Task;  
32 -import org.springframework.context.annotation.Lazy;  
33 -import org.springframework.scheduling.annotation.Async;  
34 -import org.springframework.stereotype.Service;  
35 -import org.springframework.transaction.annotation.Transactional;  
36 -import org.springframework.validation.annotation.Validated;  
37 -  
38 -import javax.annotation.Resource;  
39 -import javax.validation.Valid;  
40 -import java.util.*;  
41 -  
42 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;  
43 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;  
44 -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;  
45 -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF;  
46 -  
47 -/**  
48 - * 流程实例 Service 实现类  
49 - *  
50 - * ProcessDefinition & ProcessInstance & Execution & Task 的关系:  
51 - * 1. https://blog.csdn.net/bobozai86/article/details/105210414  
52 - *  
53 - * HistoricProcessInstance & ProcessInstance 的关系:  
54 - * 1.https://my.oschina.net/843294669/blog/719024  
55 - * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例  
56 - *  
57 - * @author 芋道源码  
58 - */  
59 -@Service  
60 -@Validated  
61 -@Slf4j  
62 -public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {  
63 -  
64 - @Resource  
65 - private RuntimeService runtimeService;  
66 - @Resource  
67 - private BpmProcessInstanceExtMapper processInstanceExtMapper;  
68 - @Resource  
69 - @Lazy // 解决循环依赖  
70 - private BpmTaskService taskService;  
71 - @Resource  
72 - private BpmProcessDefinitionService processDefinitionService;  
73 - @Resource  
74 - private HistoryService historyService;  
75 - @Resource  
76 - private AdminUserApi adminUserApi;  
77 - @Resource  
78 - private DeptApi deptApi;  
79 - @Resource  
80 - private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher;  
81 - @Resource  
82 - private BpmMessageService messageService;  
83 - @Override  
84 - public ProcessInstance getProcessInstance(String id) {  
85 - return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult();  
86 - }  
87 -  
88 - @Override  
89 - public List<ProcessInstance> getProcessInstances(Set<String> ids) {  
90 - return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();  
91 - }  
92 -  
93 - @Override  
94 - public PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId,  
95 - BpmProcessInstanceMyPageReqVO pageReqVO) {  
96 - // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页  
97 - PageResult<BpmProcessInstanceExtDO> pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO);  
98 - if (CollUtil.isEmpty(pageResult.getList())) {  
99 - return new PageResult<>(pageResult.getTotal());  
100 - }  
101 -  
102 - // 获得流程 Task Map  
103 - List<String> processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId);  
104 - Map<String, List<Task>> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds);  
105 - // 转换返回  
106 - return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap);  
107 - }  
108 -  
109 - @Override  
110 - @Transactional(rollbackFor = Exception.class)  
111 - public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {  
112 - // 获得流程定义  
113 - ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());  
114 - // 发起流程  
115 - return createProcessInstance0(userId, definition, createReqVO.getVariables(), null);  
116 - }  
117 -  
118 - @Override  
119 - public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {  
120 - // 获得流程定义  
121 - ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());  
122 - // 发起流程  
123 - return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey());  
124 - }  
125 -  
126 - @Override  
127 - public BpmProcessInstanceRespVO getProcessInstanceVO(String id) {  
128 - // 获得流程实例  
129 - HistoricProcessInstance processInstance = getHistoricProcessInstance(id);  
130 - if (processInstance == null) {  
131 - return null;  
132 - }  
133 - BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id);  
134 - Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id);  
135 -  
136 - // 获得流程定义  
137 - ProcessDefinition processDefinition = processDefinitionService  
138 - .getProcessDefinition(processInstance.getProcessDefinitionId());  
139 - Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId());  
140 - BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt(  
141 - processInstance.getProcessDefinitionId());  
142 - Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id);  
143 - String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId());  
144 -  
145 - // 获得 User  
146 - AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId()));  
147 - DeptRespDTO dept = null;  
148 - if (startUser != null) {  
149 - dept = deptApi.getDept(startUser.getDeptId());  
150 - }  
151 -  
152 - // 拼接结果  
153 - return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt,  
154 - processDefinition, processDefinitionExt, bpmnXml, startUser, dept);  
155 - }  
156 -  
157 - @Override  
158 - public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {  
159 - // 校验流程实例存在  
160 - ProcessInstance instance = getProcessInstance(cancelReqVO.getId());  
161 - if (instance == null) {  
162 - throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);  
163 - }  
164 - // 只能取消自己的  
165 - if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {  
166 - throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);  
167 - }  
168 -  
169 - // 通过删除流程实例,实现流程实例的取消,  
170 - // 删除流程实例,正则执行任务ACT_RU_TASK. 任务会被删除。通过历史表查询  
171 - deleteProcessInstance(cancelReqVO.getId(),  
172 - BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason()));  
173 - }  
174 -  
175 - /**  
176 - * 获得历史的流程实例  
177 - *  
178 - * @param id 流程实例的编号  
179 - * @return 历史的流程实例  
180 - */  
181 - @Override  
182 - public HistoricProcessInstance getHistoricProcessInstance(String id) {  
183 - return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();  
184 - }  
185 -  
186 - @Override  
187 - public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) {  
188 - return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list();  
189 - }  
190 -  
191 - @Override  
192 - public void createProcessInstanceExt(ProcessInstance instance) {  
193 - // 获得流程定义  
194 - ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId());  
195 - // 插入 BpmProcessInstanceExtDO 对象  
196 - BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()  
197 - .setProcessInstanceId(instance.getId())  
198 - .setProcessDefinitionId(definition.getId())  
199 - .setName(instance.getProcessDefinitionName())  
200 - .setStartUserId(Long.valueOf(instance.getStartUserId()))  
201 - .setCategory(definition.getCategory())  
202 - .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus())  
203 - .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());  
204 -  
205 - processInstanceExtMapper.insert(instanceExtDO);  
206 - }  
207 -  
208 - @Override  
209 - public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) {  
210 - // 判断是否为 Reject 不通过。如果是,则不进行更新  
211 - if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) {  
212 - return;  
213 - }  
214 -  
215 - // 需要主动查询,因为 instance 只有 id 属性  
216 - // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance  
217 - HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId());  
218 - // 更新拓展表  
219 - BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()  
220 - .setProcessInstanceId(event.getProcessInstanceId())  
221 - .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置  
222 - .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())  
223 - .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult());  
224 -  
225 - processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);  
226 -  
227 - // 发送流程实例的状态事件  
228 - processInstanceResultEventPublisher.sendProcessInstanceResultEvent(  
229 - BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));  
230 - }  
231 -  
232 - @Override  
233 - public void updateProcessInstanceExtComplete(ProcessInstance instance) {  
234 - // 需要主动查询,因为 instance 只有 id 属性  
235 - // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance  
236 - HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId());  
237 - // 更新拓展表  
238 - BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()  
239 - .setProcessInstanceId(instance.getProcessInstanceId())  
240 - .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置  
241 - .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())  
242 - .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过  
243 - processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);  
244 -  
245 - // 发送流程被通过的消息  
246 - messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance));  
247 -  
248 - // 发送流程实例的状态事件  
249 - processInstanceResultEventPublisher.sendProcessInstanceResultEvent(  
250 - BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));  
251 - }  
252 -  
253 - @Transactional(rollbackFor = Exception.class)  
254 - public void updateProcessInstanceExtReject(String id, String reason) {  
255 - // 需要主动查询,因为 instance 只有 id 属性  
256 - ProcessInstance processInstance = getProcessInstance(id);  
257 - // 删除流程实例,以实现驳回任务时,取消整个审批流程  
258 - deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason)));  
259 -  
260 - // 更新 status + result  
261 - // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法,  
262 - // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的  
263 - BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id)  
264 - .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())  
265 - .setResult(BpmProcessInstanceResultEnum.REJECT.getResult());  
266 - processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);  
267 -  
268 - // 发送流程被不通过的消息  
269 - messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason));  
270 -  
271 - // 发送流程实例的状态事件  
272 - processInstanceResultEventPublisher.sendProcessInstanceResultEvent(  
273 - BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));  
274 - }  
275 -  
276 - private void deleteProcessInstance(String id, String reason) {  
277 - runtimeService.deleteProcessInstance(id, reason);  
278 - }  
279 -  
280 - private String createProcessInstance0(Long userId, ProcessDefinition definition,  
281 - Map<String, Object> variables, String businessKey) {  
282 - // 校验流程定义  
283 - if (definition == null) {  
284 - throw exception(PROCESS_DEFINITION_NOT_EXISTS);  
285 - }  
286 - if (definition.isSuspended()) {  
287 - throw exception(PROCESS_DEFINITION_IS_SUSPENDED);  
288 - }  
289 -  
290 - // 创建流程实例  
291 - ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables);  
292 - // 设置流程名字  
293 - runtimeService.setProcessInstanceName(instance.getId(), definition.getName());  
294 -  
295 - // 补全流程实例的拓展表  
296 - //TODO startProcessInstance流程里面修改了 BpmProcessInstanceExt,没有提交,和下面的更新 锁持有冲突了,异步更新这个表  
297 -// processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()).setFormVariables(variables));  
298 - BpmProcessInstanceExtDO bpmProcessInstanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()).setFormVariables(variables);  
299 - asyncUpdateProcesInstance(bpmProcessInstanceExtDO);  
300 - return instance.getId();  
301 - }  
302 -  
303 - @Async  
304 - public void asyncUpdateProcesInstance(BpmProcessInstanceExtDO bpmProcessInstanceExtDO){  
305 - log.info("asyncUpdateProcesInstance ,cause MySQL Dead Lock");  
306 - processInstanceExtMapper.updateByProcessInstanceId(bpmProcessInstanceExtDO);  
307 -  
308 - }  
309 -} 1 +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; 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 lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" /> * * HistoricProcessInstance & ProcessInstance 的关系: * 1. <a href=" https://my.oschina.net/843294669/blog/71902" /> * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List<ProcessInstance> getProcessInstances(Set<String> ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult<BpmProcessInstanceExtDO> pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List<String> processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map<String, List<Task>> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map<String, Object> variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 //TODO startProcessInstance流程里面修改了 BpmProcessInstanceExt,没有提交,和下面的更新 锁持有冲突了,异步更新这个表 // processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()).setFormVariables(variables)); BpmProcessInstanceExtDO bpmProcessInstanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()).setFormVariables(variables); asyncUpdateProcesInstance(bpmProcessInstanceExtDO); return instance.getId(); } @Async public void asyncUpdateProcesInstance(BpmProcessInstanceExtDO bpmProcessInstanceExtDO){ log.info("asyncUpdateProcesInstance ,cause MySQL Dead Lock"); processInstanceExtMapper.updateByProcessInstanceId(bpmProcessInstanceExtDO); } }
310 \ No newline at end of file 2 \ No newline at end of file
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
@@ -17,6 +17,7 @@ import java.util.Map; @@ -17,6 +17,7 @@ import java.util.Map;
17 * @author 芋道源码 17 * @author 芋道源码
18 */ 18 */
19 public interface BpmTaskService { 19 public interface BpmTaskService {
  20 +
20 /** 21 /**
21 * 获得待办的流程任务分页 22 * 获得待办的流程任务分页
22 * 23 *
@@ -121,6 +122,13 @@ public interface BpmTaskService { @@ -121,6 +122,13 @@ public interface BpmTaskService {
121 void updateTaskExtComplete(Task task); 122 void updateTaskExtComplete(Task task);
122 123
123 /** 124 /**
  125 + * 更新 Task 拓展记录为已取消
  126 + *
  127 + * @param taskId 任务的编号
  128 + */
  129 + void updateTaskExtCancel(String taskId);
  130 +
  131 + /**
124 * 更新 Task 拓展记录,并发送通知 132 * 更新 Task 拓展记录,并发送通知
125 * 133 *
126 * @param task 任务实体 134 * @param task 任务实体
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
@@ -15,7 +15,8 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; @@ -15,7 +15,8 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
15 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; 15 import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
16 import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper; 16 import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmActivityMapper;
17 import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper; 17 import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper;
18 -import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum; 18 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
  19 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
19 import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; 20 import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
20 import cn.iocoder.yudao.module.business.hi.task.inst.service.HiTaskInstService; 21 import cn.iocoder.yudao.module.business.hi.task.inst.service.HiTaskInstService;
21 import cn.iocoder.yudao.module.system.api.dept.DeptApi; 22 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
@@ -214,14 +215,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -214,14 +215,6 @@ public class BpmTaskServiceImpl implements BpmTaskService {
214 List<BpmTaskAssignRuleDO> bpmTaskAssignRuleList = 215 List<BpmTaskAssignRuleDO> bpmTaskAssignRuleList =
215 taskAssignRuleMapper.selectListByProcessDefinitionId(task.getProcessDefinitionId(), 216 taskAssignRuleMapper.selectListByProcessDefinitionId(task.getProcessDefinitionId(),
216 task.getTaskDefinitionKey()); 217 task.getTaskDefinitionKey());
217 - if (CollUtil.isNotEmpty(bpmTaskAssignRuleList) && bpmTaskAssignRuleList.size() > 0) {  
218 - // edit by 芋艿 TODO  
219 -// if (BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType().equals(bpmTaskAssignRuleList.get(0).getType())) {  
220 -// taskExtMapper.delTaskByProcInstIdAndTaskIdAndTaskDefKey(  
221 -// new BpmTaskExtDO().setTaskId(task.getId()).setTaskDefKey(task.getTaskDefinitionKey())  
222 -// .setProcessInstanceId(task.getProcessInstanceId()));  
223 -// }  
224 - }  
225 } 218 }
226 219
227 @Override 220 @Override
@@ -292,6 +285,23 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -292,6 +285,23 @@ public class BpmTaskServiceImpl implements BpmTaskService {
292 taskService.setAssignee(id, String.valueOf(userId)); 285 taskService.setAssignee(id, String.valueOf(userId));
293 } 286 }
294 287
  288 + /**
  289 + * 校验任务是否存在, 并且是否是分配给自己的任务
  290 + *
  291 + * @param userId 用户 id
  292 + * @param taskId task id
  293 + */
  294 + private Task checkTask(Long userId, String taskId) {
  295 + Task task = getTask(taskId);
  296 + if (task == null) {
  297 + throw exception(TASK_COMPLETE_FAIL_NOT_EXISTS);
  298 + }
  299 + if (!Objects.equals(userId, NumberUtils.parseLong(task.getAssignee()))) {
  300 + throw exception(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF);
  301 + }
  302 + return task;
  303 + }
  304 +
295 @Override 305 @Override
296 public void createTaskExt(Task task) { 306 public void createTaskExt(Task task) {
297 BpmTaskExtDO taskExtDO = 307 BpmTaskExtDO taskExtDO =
@@ -301,11 +311,46 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -301,11 +311,46 @@ public class BpmTaskServiceImpl implements BpmTaskService {
301 311
302 @Override 312 @Override
303 public void updateTaskExtComplete(Task task) { 313 public void updateTaskExtComplete(Task task) {
304 - BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task).setEndTime(new Date()); 314 + BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
  315 + .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()) // 不设置也问题不大,因为 Complete 一般是审核通过,已经设置
  316 + .setEndTime(new Date());
305 taskExtMapper.updateByTaskId(taskExtDO); 317 taskExtMapper.updateByTaskId(taskExtDO);
306 } 318 }
307 319
308 @Override 320 @Override
  321 + public void updateTaskExtCancel(String taskId) {
  322 + // 需要在事务提交后,才进行查询。不然查询不到历史的原因
  323 + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  324 +
  325 + @Override
  326 + public void afterCommit() {
  327 + // 可能只是活动,不是任务,所以查询不到
  328 + HistoricTaskInstance task = getHistoricTask(taskId);
  329 + if (task == null) {
  330 + return;
  331 + }
  332 +
  333 + // 如果任务拓展表已经是完成的状态,则跳过
  334 + BpmTaskExtDO taskExt = taskExtMapper.selectByTaskId(taskId);
  335 + if (taskExt == null) {
  336 + log.error("[updateTaskExtCancel][taskId({}) 查找不到对应的记录,可能存在问题]", taskId);
  337 + return;
  338 + }
  339 + // 如果已经是最终的结果,则跳过
  340 + if (BpmProcessInstanceResultEnum.isEndResult(taskExt.getResult())) {
  341 + log.error("[updateTaskExtCancel][taskId({}) 处于结果({}),无需进行更新]", taskId, taskExt.getResult());
  342 + return;
  343 + }
  344 +
  345 + // 更新任务
  346 + taskExtMapper.updateById(new BpmTaskExtDO().setId(taskExt.getId()).setResult(BpmProcessInstanceResultEnum.CANCEL.getResult())
  347 + .setEndTime(new Date()).setReason(BpmProcessInstanceDeleteReasonEnum.translateReason(task.getDeleteReason())));
  348 + }
  349 +
  350 + });
  351 + }
  352 +
  353 + @Override
309 public void updateTaskExtAssign(Task task) { 354 public void updateTaskExtAssign(Task task) {
310 BpmTaskExtDO taskExtDO = 355 BpmTaskExtDO taskExtDO =
311 new BpmTaskExtDO().setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setTaskId(task.getId()); 356 new BpmTaskExtDO().setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setTaskId(task.getId());
@@ -323,24 +368,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -323,24 +368,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
323 }); 368 });
324 } 369 }
325 370
326 - /**  
327 - * 校验任务是否存在, 并且是否是分配给自己的任务  
328 - *  
329 - * @param userId 用户 id  
330 - * @param taskId task id  
331 - */  
332 - private Task checkTask(Long userId, String taskId) {  
333 - Task task = getTask(taskId);  
334 - if (task == null) {  
335 - throw exception(TASK_COMPLETE_FAIL_NOT_EXISTS);  
336 - }  
337 - if (!Objects.equals(userId, NumberUtils.parseLong(task.getAssignee()))) {  
338 - throw exception(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF);  
339 - }  
340 - return task;  
341 - }  
342 -  
343 private Task getTask(String id) { 371 private Task getTask(String id) {
344 return taskService.createTaskQuery().taskId(id).singleResult(); 372 return taskService.createTaskQuery().taskId(id).singleResult();
345 } 373 }
  374 +
  375 + private HistoricTaskInstance getHistoricTask(String id) {
  376 + return historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult();
  377 + }
  378 +
346 } 379 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/business/hi/task/inst/service/HiTaskInstService.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.business.hi.task.inst.service; @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.business.hi.task.inst.service;
3 import cn.hutool.core.bean.BeanUtil; 3 import cn.hutool.core.bean.BeanUtil;
4 import cn.hutool.core.collection.CollUtil; 4 import cn.hutool.core.collection.CollUtil;
5 import cn.hutool.core.util.ObjectUtil; 5 import cn.hutool.core.util.ObjectUtil;
6 -import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;  
7 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 6 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
8 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; 7 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
9 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO; 8 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO;
@@ -68,7 +67,6 @@ public class HiTaskInstService { @@ -68,7 +67,6 @@ public class HiTaskInstService {
68 * @return 返回流程信息 67 * @return 返回流程信息
69 */ 68 */
70 @TenantIgnore 69 @TenantIgnore
71 - @DataPermission(enable = false) // TODO 芋艿:先临时去掉  
72 public List<BpmTaskRespVO> taskGetComment(List<BpmTaskExtDO> taskList, Object approved) { 70 public List<BpmTaskRespVO> taskGetComment(List<BpmTaskExtDO> taskList, Object approved) {
73 BpmTaskExtDO task = taskList.get(taskList.size() - 1); 71 BpmTaskExtDO task = taskList.get(taskList.size() - 1);
74 Map<String, BpmTaskExtDO> bpmTaskMap = 72 Map<String, BpmTaskExtDO> bpmTaskMap =
yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmTaskExtMapper.xml
@@ -2,14 +2,6 @@ @@ -2,14 +2,6 @@
2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3 <mapper namespace="cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper"> 3 <mapper namespace="cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper">
4 4
5 -  
6 - <update id="delTaskByProcInstIdAndTaskIdAndTaskDefKey">  
7 - UPDATE bpm_task_ext  
8 - SET deleted=1  
9 - WHERE process_instance_id = #{entity.processInstanceId}  
10 - AND task_def_key = #{entity.taskDefKey}  
11 - AND task_id != #{entity.taskId}  
12 - </update>  
13 <update id="backByTaskId"> 5 <update id="backByTaskId">
14 UPDATE bpm_task_ext 6 UPDATE bpm_task_ext
15 SET result=2, 7 SET result=2,
@@ -26,5 +18,4 @@ @@ -26,5 +18,4 @@
26 </foreach> 18 </foreach>
27 </update> 19 </update>
28 20
29 -  
30 </mapper> 21 </mapper>
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImplTest.java
@@ -6,8 +6,8 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; @@ -6,8 +6,8 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
6 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 6 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
7 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; 7 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
8 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; 8 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
9 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;  
10 -import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum; 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; 11 import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
12 import cn.iocoder.yudao.module.system.api.dept.DeptApi; 12 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
13 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; 13 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;