Commit 0a7f94dd5fe94b72fd14d362efa8fd7e3441dc20

Authored by YunaiV
1 parent bc4427ac

BPM:完善 task 在通过、不通过、取消等情况下的 reason 和 comment 逻辑

yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmCommentTypeEnum.java
@@ -13,10 +13,10 @@ import lombok.Getter; @@ -13,10 +13,10 @@ import lombok.Getter;
13 @AllArgsConstructor 13 @AllArgsConstructor
14 public enum BpmCommentTypeEnum { 14 public enum BpmCommentTypeEnum {
15 15
16 - APPROVE("1", "审批通过", ""), // 理由:直接使用用户的评论  
17 - REJECT("2", "不通过", ""),  
18 - CANCEL("3", "已取消", ""),  
19 - BACK("4", "退回", "{}"), // 直接使用用户填写的原因 16 + APPROVE("1", "审批通过", "审批通过,原因是:{}"),
  17 + REJECT("2", "不通过", "审批不通过:原因是:{}"),
  18 + CANCEL("3", "已取消", "系统自动取消,原因是:{}"),
  19 + RETURN("4", "退回", "任务被退回,原因是:{}"),
20 DELEGATE_START("5", "委派发起", "[{}]将任务委派给[{}],委派理由为:{}"), 20 DELEGATE_START("5", "委派发起", "[{}]将任务委派给[{}],委派理由为:{}"),
21 DELEGATE_END("6", "委派完成", "[{}]完成委派任务,任务重新回到[{}]手中,审批建议为:{}"), 21 DELEGATE_END("6", "委派完成", "[{}]完成委派任务,任务重新回到[{}]手中,审批建议为:{}"),
22 TRANSFER("7", "转派", "[{}]将任务转派给[{}],转派理由为:{}"), 22 TRANSFER("7", "转派", "[{}]将任务转派给[{}],转派理由为:{}"),
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceDeleteReasonEnum.java renamed to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmDeleteReasonEnum.java
@@ -5,20 +5,22 @@ import lombok.AllArgsConstructor; @@ -5,20 +5,22 @@ import lombok.AllArgsConstructor;
5 import lombok.Getter; 5 import lombok.Getter;
6 6
7 /** 7 /**
8 - * 流程实例的删除原因 8 + * 流程实例/任务的删除原因枚举
9 * 9 *
10 * @author 芋道源码 10 * @author 芋道源码
11 */ 11 */
12 @Getter 12 @Getter
13 @AllArgsConstructor 13 @AllArgsConstructor
14 -public enum BpmProcessInstanceDeleteReasonEnum { 14 +public enum BpmDeleteReasonEnum {
15 15
16 - REJECT_TASK("不通过任务,原因:{}"), // 修改文案时,需要注意 isRejectReason 方法  
17 - CANCEL_TASK("主动取消任务,原因:{}"), 16 + // ========== 流程实例的独有原因 ==========
  17 +
  18 + REJECT_TASK("审批不通过任务,原因:{}"), // 场景:用户审批不通过任务。修改文案时,需要注意 isRejectReason 方法
  19 + CANCEL_PROCESS_INSTANCE("用户主动取消流程,原因:{}"), // 场景:用户主动取消流程
18 20
19 // ========== 流程任务的独有原因 ========== 21 // ========== 流程任务的独有原因 ==========
20 - MULTI_TASK_END("系统自动取消,原因:多任务审批已经满足条件,无需审批该任务"), // 多实例满足 condition 而结束时,其它任务实例任务会被取消,对应的删除原因是 MI_END  
21 22
  23 + CANCEL_SYSTEM("系统自动取消"), // 场景:非常多,比如说:1)多任务审批已经满足条件,无需审批该任务;2)流程实例被取消,无需审批该任务;等等
22 ; 24 ;
23 25
24 private final String reason; 26 private final String reason;
@@ -36,23 +38,7 @@ public enum BpmProcessInstanceDeleteReasonEnum { @@ -36,23 +38,7 @@ public enum BpmProcessInstanceDeleteReasonEnum {
36 // ========== 逻辑 ========== 38 // ========== 逻辑 ==========
37 39
38 public static boolean isRejectReason(String reason) { 40 public static boolean isRejectReason(String reason) {
39 - return StrUtil.startWith(reason, "不通过任务,原因:");  
40 - }  
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 - } 41 + return StrUtil.startWith(reason, "审批不通过任务,原因:");
56 } 42 }
57 43
58 } 44 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java
@@ -36,12 +36,12 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent @@ -36,12 +36,12 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent
36 36
37 @Override 37 @Override
38 protected void processCancelled(FlowableCancelledEvent event) { 38 protected void processCancelled(FlowableCancelledEvent event) {
39 - processInstanceService.updateProcessInstanceExtCancel(event); 39 + processInstanceService.updateProcessInstanceWhenCancel(event);
40 } 40 }
41 41
42 @Override 42 @Override
43 protected void processCompleted(FlowableEngineEntityEvent event) { 43 protected void processCompleted(FlowableEngineEntityEvent event) {
44 - processInstanceService.updateProcessInstanceExtComplete((ProcessInstance)event.getEntity()); 44 + processInstanceService.updateProcessInstanceWhenApprove((ProcessInstance)event.getEntity());
45 } 45 }
46 46
47 } 47 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java
@@ -31,7 +31,6 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { @@ -31,7 +31,6 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
31 @Resource 31 @Resource
32 @Lazy // 解决循环依赖 32 @Lazy // 解决循环依赖
33 private BpmTaskService taskService; 33 private BpmTaskService taskService;
34 -  
35 @Resource 34 @Resource
36 @Lazy // 解决循环依赖 35 @Lazy // 解决循环依赖
37 private BpmActivityService activityService; 36 private BpmActivityService activityService;
@@ -39,7 +38,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { @@ -39,7 +38,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
39 public static final Set<FlowableEngineEventType> TASK_EVENTS = ImmutableSet.<FlowableEngineEventType>builder() 38 public static final Set<FlowableEngineEventType> TASK_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
40 .add(FlowableEngineEventType.TASK_CREATED) 39 .add(FlowableEngineEventType.TASK_CREATED)
41 .add(FlowableEngineEventType.TASK_ASSIGNED) 40 .add(FlowableEngineEventType.TASK_ASSIGNED)
42 - .add(FlowableEngineEventType.TASK_COMPLETED) 41 +// .add(FlowableEngineEventType.TASK_COMPLETED) // 由于审批通过时,已经记录了 task 的 status 为通过,所以不需要监听了。
43 .add(FlowableEngineEventType.ACTIVITY_CANCELLED) 42 .add(FlowableEngineEventType.ACTIVITY_CANCELLED)
44 .build(); 43 .build();
45 44
@@ -49,12 +48,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { @@ -49,12 +48,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
49 48
50 @Override 49 @Override
51 protected void taskCreated(FlowableEngineEntityEvent event) { 50 protected void taskCreated(FlowableEngineEntityEvent event) {
52 - taskService.createTaskExt((Task) event.getEntity());  
53 - }  
54 -  
55 - @Override  
56 - protected void taskCompleted(FlowableEngineEntityEvent event) {  
57 - taskService.updateTaskExtComplete((Task)event.getEntity()); 51 + taskService.updateTaskStatusWhenCreated((Task) event.getEntity());
58 } 52 }
59 53
60 @Override 54 @Override
@@ -74,7 +68,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { @@ -74,7 +68,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
74 if (StrUtil.isEmpty(activity.getTaskId())) { 68 if (StrUtil.isEmpty(activity.getTaskId())) {
75 return; 69 return;
76 } 70 }
77 - taskService.updateTaskExtCancel(activity.getTaskId()); 71 + taskService.updateTaskStatusWhenCanceled(activity.getTaskId());
78 }); 72 });
79 } 73 }
80 74
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
@@ -136,14 +136,14 @@ public interface BpmProcessInstanceService { @@ -136,14 +136,14 @@ public interface BpmProcessInstanceService {
136 * 136 *
137 * @param event 流程取消事件 137 * @param event 流程取消事件
138 */ 138 */
139 - void updateProcessInstanceExtCancel(FlowableCancelledEvent event); 139 + void updateProcessInstanceWhenCancel(FlowableCancelledEvent event);
140 140
141 /** 141 /**
142 * 更新 ProcessInstance 拓展记录为完成 142 * 更新 ProcessInstance 拓展记录为完成
143 * 143 *
144 * @param instance 流程任务 144 * @param instance 流程任务
145 */ 145 */
146 - void updateProcessInstanceExtComplete(ProcessInstance instance); 146 + void updateProcessInstanceWhenApprove(ProcessInstance instance);
147 147
148 /** 148 /**
149 * 更新 ProcessInstance 拓展记录为不通过 149 * 更新 ProcessInstance 拓展记录为不通过
@@ -151,7 +151,7 @@ public interface BpmProcessInstanceService { @@ -151,7 +151,7 @@ public interface BpmProcessInstanceService {
151 * @param id 流程编号 151 * @param id 流程编号
152 * @param reason 理由。例如说,审批不通过时,需要传递该值 152 * @param reason 理由。例如说,审批不通过时,需要传递该值
153 */ 153 */
154 - void updateProcessInstanceExtReject(String id, String reason); 154 + void updateProcessInstanceReject(String id, String reason);
155 155
156 // TODO @hai:改成 getProcessInstanceAssigneesByTaskDefinitionKey(String id, String taskDefinitionKey) 156 // TODO @hai:改成 getProcessInstanceAssigneesByTaskDefinitionKey(String id, String taskDefinitionKey)
157 /** 157 /**
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; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils; import cn.iocoder.yudao.framework.flowable.core.context.FlowableContextHolder; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCancelReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceMyPageReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO; 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.enums.task.BpmProcessInstanceDeleteReasonEnum; 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.framework.flowable.core.enums.BpmConstants; 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 jakarta.annotation.Resource; import jakarta.validation.Valid; 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.history.HistoricProcessInstanceQuery; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 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 HistoryService historyService; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private BpmMessageService messageService; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery() .includeProcessVariables() .processInstanceId(id) .singleResult(); } @Override public List<ProcessInstance> getProcessInstances(Set<String> ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).includeProcessVariables().singleResult(); } @Override public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult<HistoricProcessInstance> getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 HistoricProcessInstanceQuery processInstanceQuery = historyService.createHistoricProcessInstanceQuery().includeProcessVariables() .startedBy(String.valueOf(userId)) .orderByProcessInstanceStartTime().desc(); if (StrUtil.isNotEmpty(pageReqVO.getName())) { processInstanceQuery.processInstanceNameLike("%" + pageReqVO.getName() + "%"); } if (StrUtil.isNotEmpty(pageReqVO.getProcessDefinitionId())) { processInstanceQuery.processDefinitionId("%" + pageReqVO.getProcessDefinitionId() + "%"); } if (StrUtil.isNotEmpty(pageReqVO.getCategory())) { processInstanceQuery.processDefinitionCategory(pageReqVO.getCategory()); } if (pageReqVO.getStatus() != null) { processInstanceQuery.variableValueEquals(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, pageReqVO.getStatus()); } if (ArrayUtil.isNotEmpty(pageReqVO.getCreateTime())) { processInstanceQuery.startedAfter(DateUtils.of(pageReqVO.getCreateTime()[0])); processInstanceQuery.startedBefore(DateUtils.of(pageReqVO.getCreateTime()[1])); } // 查询数量 long processInstanceCount = processInstanceQuery.count(); if (processInstanceCount == 0) { return PageResult.empty(processInstanceCount); } // 查询列表 List<HistoricProcessInstance> processInstanceList = processInstanceQuery.listPage(PageUtils.getStart(pageReqVO), pageReqVO.getPageSize()); return new PageResult<>(processInstanceList, processInstanceCount); } @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, createReqVO.getAssignee()); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey(), createReqDTO.getAssignee()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } // 获得流程定义 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, 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())); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String) event.getCause())) { return; } // 更新流程实例 status runtimeService.setVariable(event.getProcessInstanceId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, BpmProcessInstanceStatusEnum.CANCEL.getStatus()); // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, BpmProcessInstanceStatusEnum.CANCEL.getStatus())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 更新拓展表 runtimeService.setVariable(instance.getId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, BpmProcessInstanceStatusEnum.APPROVE.getStatus()); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, BpmProcessInstanceStatusEnum.APPROVE.getStatus())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 更新流程实例 status runtimeService.setVariable(id, BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, BpmProcessInstanceStatusEnum.REJECT.getStatus()); // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, BpmProcessInstanceStatusEnum.REJECT.getStatus())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map<String, Object> variables, String businessKey, Map<String, List<Long>> assignee) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 设置上下文信息 // TODO @hai:要不往 variables 存到一个全局固定 key 里,减少对上下文的依赖 FlowableContextHolder.setAssignee(assignee); // 创建流程实例 variables.put(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中 BpmProcessInstanceStatusEnum.RUNNING.getStatus()); ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .start(); return instance.getId(); } @Override public List<Long> getAssigneeByProcessInstanceIdAndTaskDefinitionKey(String processInstanceId, String taskDefinitionKey) { // 1. 先从上下文获取,首次提交数据库中查询不到 List<Long> result = FlowableContextHolder.getAssigneeByTaskDefinitionKey(taskDefinitionKey); if (CollUtil.isNotEmpty(result)) { return result; } // 2. 从数据库中获取 // TODO @芋艿:指定审批人,这里的存储方案有问题,后续优化下 // BpmProcessInstanceExtDO instance = processInstanceExtMapper.selectByProcessInstanceId(processInstanceId); // if (instance == null) { // throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); // } // if (CollUtil.isNotEmpty(instance.getAssignee())) { // return instance.getAssignee().get(taskDefinitionKey); // } return Collections.emptyList(); } }  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +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.ArrayUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils; import cn.iocoder.yudao.framework.flowable.core.context.FlowableContextHolder; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCancelReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceMyPageReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO; 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.enums.task.BpmDeleteReasonEnum; 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.framework.flowable.core.enums.BpmConstants; 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 jakarta.annotation.Resource; import jakarta.validation.Valid; 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.history.HistoricProcessInstanceQuery; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 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 HistoryService historyService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private BpmMessageService messageService; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery() .includeProcessVariables() .processInstanceId(id) .singleResult(); } @Override public List<ProcessInstance> getProcessInstances(Set<String> ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).includeProcessVariables().singleResult(); } @Override public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult<HistoricProcessInstance> getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 HistoricProcessInstanceQuery processInstanceQuery = historyService.createHistoricProcessInstanceQuery().includeProcessVariables() .startedBy(String.valueOf(userId)) .orderByProcessInstanceStartTime().desc(); if (StrUtil.isNotEmpty(pageReqVO.getName())) { processInstanceQuery.processInstanceNameLike("%" + pageReqVO.getName() + "%"); } if (StrUtil.isNotEmpty(pageReqVO.getProcessDefinitionId())) { processInstanceQuery.processDefinitionId("%" + pageReqVO.getProcessDefinitionId() + "%"); } if (StrUtil.isNotEmpty(pageReqVO.getCategory())) { processInstanceQuery.processDefinitionCategory(pageReqVO.getCategory()); } if (pageReqVO.getStatus() != null) { processInstanceQuery.variableValueEquals(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, pageReqVO.getStatus()); } if (ArrayUtil.isNotEmpty(pageReqVO.getCreateTime())) { processInstanceQuery.startedAfter(DateUtils.of(pageReqVO.getCreateTime()[0])); processInstanceQuery.startedBefore(DateUtils.of(pageReqVO.getCreateTime()[1])); } // 查询数量 long processInstanceCount = processInstanceQuery.count(); if (processInstanceCount == 0) { return PageResult.empty(processInstanceCount); } // 查询列表 List<HistoricProcessInstance> processInstanceList = processInstanceQuery.listPage(PageUtils.getStart(pageReqVO), pageReqVO.getPageSize()); return new PageResult<>(processInstanceList, processInstanceCount); } @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, createReqVO.getAssignee()); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey(), createReqDTO.getAssignee()); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map<String, Object> variables, String businessKey, Map<String, List<Long>> assignee) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 设置上下文信息 // TODO @hai:要不往 variables 存到一个全局固定 key 里,减少对上下文的依赖 FlowableContextHolder.setAssignee(assignee); // 创建流程实例 variables.put(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中 BpmProcessInstanceStatusEnum.RUNNING.getStatus()); ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .start(); return instance.getId(); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } // 获得流程定义 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, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 1.1 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 1.2 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 2. 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmDeleteReasonEnum.CANCEL_PROCESS_INSTANCE.format(cancelReqVO.getReason())); // 3. 进一步的处理,交给 updateProcessInstanceCancel 方法 } @Override public void updateProcessInstanceWhenCancel(FlowableCancelledEvent event) { // 1. 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceReject 方法(审批不通过),已经进行更新了 if (BpmDeleteReasonEnum.isRejectReason((String) event.getCause())) { return; } // 2. 更新流程实例 status runtimeService.setVariable(event.getProcessInstanceId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, BpmProcessInstanceStatusEnum.CANCEL.getStatus()); // 3. 发送流程实例的状态事件 // 注意:此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, BpmProcessInstanceStatusEnum.CANCEL.getStatus())); } @Override public void updateProcessInstanceWhenApprove(ProcessInstance instance) { // 1. 更新流程实例 status runtimeService.setVariable(instance.getId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, BpmProcessInstanceStatusEnum.APPROVE.getStatus()); // 2. 发送流程被【通过】的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 3. 发送流程实例的状态事件 // 注意:此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, BpmProcessInstanceStatusEnum.APPROVE.getStatus())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceReject(String id, String reason) { // 1. 更新流程实例 status runtimeService.setVariable(id, BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, BpmProcessInstanceStatusEnum.REJECT.getStatus()); // 2. 删除流程实例,以实现驳回任务时,取消整个审批流程 ProcessInstance processInstance = getProcessInstance(id); deleteProcessInstance(id, StrUtil.format(BpmDeleteReasonEnum.REJECT_TASK.format(reason))); // 3. 发送流程被【不通过】的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 4. 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, BpmProcessInstanceStatusEnum.REJECT.getStatus())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } @Override public List<Long> getAssigneeByProcessInstanceIdAndTaskDefinitionKey(String processInstanceId, String taskDefinitionKey) { // 1. 先从上下文获取,首次提交数据库中查询不到 List<Long> result = FlowableContextHolder.getAssigneeByTaskDefinitionKey(taskDefinitionKey); if (CollUtil.isNotEmpty(result)) { return result; } // 2. 从数据库中获取 // TODO @芋艿:指定审批人,这里的存储方案有问题,后续优化下 // BpmProcessInstanceExtDO instance = processInstanceExtMapper.selectByProcessInstanceId(processInstanceId); // if (instance == null) { // throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); // } // if (CollUtil.isNotEmpty(instance.getAssignee())) { // return instance.getAssignee().get(taskDefinitionKey); // } return Collections.emptyList(); } }
3 \ No newline at end of file 3 \ 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
@@ -90,25 +90,18 @@ public interface BpmTaskService { @@ -90,25 +90,18 @@ public interface BpmTaskService {
90 void transferTask(Long userId, BpmTaskTransferReqVO reqVO); 90 void transferTask(Long userId, BpmTaskTransferReqVO reqVO);
91 91
92 /** 92 /**
93 - * 创建 Task 拓展记录 93 + * 更新 Task 状态,在创建时
94 * 94 *
95 * @param task 任务实体 95 * @param task 任务实体
96 */ 96 */
97 - void createTaskExt(Task task); 97 + void updateTaskStatusWhenCreated(Task task);
98 98
99 /** 99 /**
100 - * 更新 Task 拓展记录为完成  
101 - *  
102 - * @param task 任务实体  
103 - */  
104 - void updateTaskExtComplete(Task task);  
105 -  
106 - /**  
107 - * 更新 Task 拓展记录为已取消 100 + * 更新 Task 状态,在取消时
108 * 101 *
109 * @param taskId 任务的编号 102 * @param taskId 任务的编号
110 */ 103 */
111 - void updateTaskExtCancel(String taskId); 104 + void updateTaskStatusWhenCanceled(String taskId);
112 105
113 /** 106 /**
114 * 更新 Task 拓展记录,并发送通知 107 * 更新 Task 拓展记录,并发送通知
@@ -117,6 +110,12 @@ public interface BpmTaskService { @@ -117,6 +110,12 @@ public interface BpmTaskService {
117 */ 110 */
118 void updateTaskExtAssign(Task task); 111 void updateTaskExtAssign(Task task);
119 112
  113 + /**
  114 + * 获取任务
  115 + *
  116 + * @param id 任务编号
  117 + * @return 任务
  118 + */
120 Task getTask(String id); 119 Task getTask(String id);
121 120
122 /** 121 /**
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
@@ -13,9 +13,7 @@ import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils; @@ -13,9 +13,7 @@ import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
13 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; 13 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
14 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; 14 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
15 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; 15 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
16 -import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum;  
17 -import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatustEnum;  
18 -import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskAddSignTypeEnum; 16 +import cn.iocoder.yudao.module.bpm.enums.task.*;
19 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants; 17 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants;
20 import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; 18 import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
21 import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; 19 import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
@@ -181,8 +179,8 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -181,8 +179,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
181 // 3.1 更新 task 状态、原因 179 // 3.1 更新 task 状态、原因
182 updateTaskStatusAndReason(task.getId(), BpmTaskStatustEnum.APPROVE.getStatus(), reqVO.getReason()); 180 updateTaskStatusAndReason(task.getId(), BpmTaskStatustEnum.APPROVE.getStatus(), reqVO.getReason());
183 // 3.2 添加评论 181 // 3.2 添加评论
184 - taskService.addComment(task.getId(), task.getProcessInstanceId(),  
185 - BpmCommentTypeEnum.APPROVE.getType(), reqVO.getReason()); 182 + taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.APPROVE.getType(),
  183 + BpmCommentTypeEnum.APPROVE.formatComment(reqVO.getReason()));
186 // 3.3 调用 BPM complete 去完成任务 184 // 3.3 调用 BPM complete 去完成任务
187 taskService.complete(task.getId(), instance.getProcessVariables()); 185 taskService.complete(task.getId(), instance.getProcessVariables());
188 186
@@ -300,21 +298,22 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -300,21 +298,22 @@ public class BpmTaskServiceImpl implements BpmTaskService {
300 @Override 298 @Override
301 @Transactional(rollbackFor = Exception.class) 299 @Transactional(rollbackFor = Exception.class)
302 public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) { 300 public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) {
  301 + // 1.1 校验任务存在
303 Task task = validateTask(userId, reqVO.getId()); 302 Task task = validateTask(userId, reqVO.getId());
304 - // 校验流程实例存在 303 + // 1.2 校验流程实例存在
305 ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); 304 ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
306 if (instance == null) { 305 if (instance == null) {
307 throw exception(PROCESS_INSTANCE_NOT_EXISTS); 306 throw exception(PROCESS_INSTANCE_NOT_EXISTS);
308 } 307 }
309 308
310 - // 更新流程实例为不通过  
311 - updateTaskStatus(task.getId(), BpmTaskStatustEnum.REJECT.getStatus());  
312 - processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getReason()); 309 + // 2.1 更新流程实例为不通过
  310 + updateTaskStatusAndReason(task.getId(), BpmTaskStatustEnum.REJECT.getStatus(), reqVO.getReason());
  311 + // 2.2 添加评论
  312 + taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.REJECT.getType(),
  313 + BpmCommentTypeEnum.REJECT.formatComment(reqVO.getReason()));
313 314
314 -// // 更新任务拓展表为不通过  
315 -// taskExtMapper.updateByTaskId(  
316 -// new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.REJECT.getResult())  
317 -// .setEndTime(LocalDateTime.now()).setReason(reqVO.getReason())); 315 + // 3. 更新流程实例,审批不通过!
  316 + processInstanceService.updateProcessInstanceReject(instance.getProcessInstanceId(), reqVO.getReason());
318 } 317 }
319 318
320 /** 319 /**
@@ -354,112 +353,49 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -354,112 +353,49 @@ public class BpmTaskServiceImpl implements BpmTaskService {
354 } 353 }
355 354
356 @Override 355 @Override
357 - public void createTaskExt(Task task) {  
358 -// BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)  
359 -// .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());  
360 -// // 向后加签生成的任务,状态不能为进行中,需要等前面父任务完成  
361 -// if (BpmTaskAddSignTypeEnum.AFTER_CHILDREN_TASK.getType().equals(task.getScopeType())) {  
362 -// taskExtDO.setResult(BpmProcessInstanceResultEnum.WAIT_BEFORE_TASK.getResult());  
363 -// }  
364 -// taskExtMapper.insert(taskExtDO);  
365 -// Integer status = (Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS);  
366 -// if (status != null) {  
367 -// return;  
368 -// }  
369 -//  
370 -// status = BpmProcessInstanceResultEnum.RUNNING.getResult();  
371 - // 向后加签生成的任务,状态不能为进行中,需要等前面父任务完成  
372 -// if (BpmTaskAddSignTypeEnum.AFTER_CHILDREN_TASK.getType().equals(task.getScopeType())) {  
373 -// status = BpmProcessInstanceResultEnum.WAIT_BEFORE_TASK.getResult();  
374 -// } 356 + public void updateTaskStatusWhenCreated(Task task) {
  357 + Integer status = (Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS);
  358 + if (status != null) {
  359 + log.error("[updateTaskStatusWhenCreated][taskId({}) 已经有状态({})]", task.getId(), status);
  360 + return;
  361 + }
375 updateTaskStatus(task.getId(), BpmTaskStatustEnum.RUNNING.getStatus()); 362 updateTaskStatus(task.getId(), BpmTaskStatustEnum.RUNNING.getStatus());
376 } 363 }
377 364
378 @Override 365 @Override
379 - public void updateTaskExtComplete(Task task) {  
380 -// BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)  
381 -// .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()) // 不设置也问题不大,因为 Complete 一般是审核通过,已经设置  
382 -// .setEndTime(LocalDateTime.now());  
383 -// taskExtMapper.updateByTaskId(taskExtDO);  
384 -  
385 - updateTaskStatus(task.getId(), BpmTaskStatustEnum.APPROVE.getStatus());  
386 - }  
387 -  
388 - @Override  
389 - public void updateTaskExtCancel(String taskId) { 366 + public void updateTaskStatusWhenCanceled(String taskId) {
390 Task task = getTask(taskId); 367 Task task = getTask(taskId);
391 - // 可能只是活动,不是任务,所以查询不到 368 + // 1. 可能只是活动,不是任务,所以查询不到
392 if (task == null) { 369 if (task == null) {
393 - log.error("[updateTaskExtCancel][taskId({}) 任务不存在]", taskId); 370 + log.error("[updateTaskStatusWhenCanceled][taskId({}) 任务不存在]", taskId);
394 return; 371 return;
395 } 372 }
396 373
  374 + // 2. 更新 task 状态 + 原因
397 Integer status = (Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS); 375 Integer status = (Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS);
398 if (BpmTaskStatustEnum.isEndStatus(status)) { 376 if (BpmTaskStatustEnum.isEndStatus(status)) {
399 - log.error("[updateTaskExtCancel][taskId({}) 处于结果({}),无需进行更新]", taskId, status);  
400 - return;  
401 - }  
402 - updateTaskStatus(taskId, BpmTaskStatustEnum.CANCEL.getStatus());  
403 -  
404 - if (true) { 377 + log.error("[updateTaskStatusWhenCanceled][taskId({}) 处于结果({}),无需进行更新]", taskId, status);
405 return; 378 return;
406 } 379 }
407 -  
408 - // 需要在事务提交后,才进行查询。不然查询不到历史的原因  
409 - TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {  
410 -  
411 - @Override  
412 - public void afterCommit() {  
413 - // 可能只是活动,不是任务,所以查询不到  
414 - HistoricTaskInstance task = getHistoricTask(taskId);  
415 - if (task == null) {  
416 - return;  
417 - }  
418 -  
419 -// // 如果任务拓展表已经是完成的状态,则跳过  
420 -// BpmTaskExtDO taskExt = taskExtMapper.selectByTaskId(taskId);  
421 -// if (taskExt == null) {  
422 -// log.error("[updateTaskExtCancel][taskId({}) 查找不到对应的记录,可能存在问题]", taskId);  
423 -// return;  
424 -// }  
425 -// // 如果已经是最终的结果,则跳过  
426 -// if (BpmProcessInstanceResultEnum.isEndResult(taskExt.getResult())) {  
427 -// log.error("[updateTaskExtCancel][taskId({}) 处于结果({}),无需进行更新]", taskId, taskExt.getResult());  
428 -// return;  
429 -// }  
430 - Integer status = (Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS);  
431 - if (BpmTaskStatustEnum.isEndStatus(status)) {  
432 - log.error("[updateTaskExtCancel][taskId({}) 处于结果({}),无需进行更新]", taskId, status);  
433 - return;  
434 - }  
435 -  
436 - // 更新任务  
437 -// taskExtMapper.updateById(new BpmTaskExtDO().setId(taskExt.getId()).setResult(BpmProcessInstanceResultEnum.CANCEL.getResult())  
438 -// .setEndTime(LocalDateTime.now()).setReason(BpmProcessInstanceDeleteReasonEnum.translateReason(task.getDeleteReason())));  
439 - updateTaskStatus(taskId, BpmTaskStatustEnum.CANCEL.getStatus());  
440 - }  
441 -  
442 - }); 380 + updateTaskStatusAndReason(taskId, BpmTaskStatustEnum.CANCEL.getStatus(), BpmDeleteReasonEnum.CANCEL_SYSTEM.getReason());
  381 + // 补充说明:由于 Task 被删除成 HistoricTask 后,无法通过 taskService.addComment 添加理由,所以无法存储具体的取消理由
443 } 382 }
444 383
445 @Override 384 @Override
446 public void updateTaskExtAssign(Task task) { 385 public void updateTaskExtAssign(Task task) {
447 -// BpmTaskExtDO taskExtDO =  
448 -// new BpmTaskExtDO().setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setTaskId(task.getId());  
449 -// taskExtMapper.updateByTaskId(taskExtDO);  
450 -  
451 // 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。 386 // 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
452 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { 387 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  388 +
453 @Override 389 @Override
454 public void afterCommit() { 390 public void afterCommit() {
455 if (StrUtil.isNotEmpty(task.getAssignee())) { 391 if (StrUtil.isNotEmpty(task.getAssignee())) {
456 - ProcessInstance processInstance =  
457 - processInstanceService.getProcessInstance(task.getProcessInstanceId());  
458 - AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));  
459 - messageService.sendMessageWhenTaskAssigned(  
460 - BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task)); 392 + return;
461 } 393 }
  394 + ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
  395 + AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
  396 + messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
462 } 397 }
  398 +
463 }); 399 });
464 } 400 }
465 401
@@ -567,8 +503,8 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -567,8 +503,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
567 return; 503 return;
568 } 504 }
569 // 2.1 添加评论 505 // 2.1 添加评论
570 - taskService.addComment(task.getId(), currentTask.getProcessInstanceId(), BpmCommentTypeEnum.BACK.getType(),  
571 - BpmCommentTypeEnum.BACK.formatComment(reqVO.getReason())); 506 + taskService.addComment(task.getId(), currentTask.getProcessInstanceId(), BpmCommentTypeEnum.RETURN.getType(),
  507 + BpmCommentTypeEnum.RETURN.formatComment(reqVO.getReason()));
572 // 2.2 更新 task 状态 + 原因 508 // 2.2 更新 task 状态 + 原因
573 updateTaskStatusAndReason(task.getId(), BpmTaskStatustEnum.RETURN.getStatus(), reqVO.getReason()); 509 updateTaskStatusAndReason(task.getId(), BpmTaskStatustEnum.RETURN.getStatus(), reqVO.getReason());
574 }); 510 });