Commit 007639d61aeed2b1530b6d32555ac85980566c86

Authored by jason
1 parent d2750f08

仿钉钉流程设计- 简化审批节点拒绝处理

yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
@@ -51,6 +51,7 @@ public interface ErrorCodeConstants { @@ -51,6 +51,7 @@ public interface ErrorCodeConstants {
51 ErrorCode TASK_SIGN_DELETE_NO_PARENT = new ErrorCode(1_009_005_012, "任务减签失败,被减签的任务必须是通过加签生成的任务"); 51 ErrorCode TASK_SIGN_DELETE_NO_PARENT = new ErrorCode(1_009_005_012, "任务减签失败,被减签的任务必须是通过加签生成的任务");
52 ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人"); 52 ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人");
53 ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在"); 53 ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在");
  54 + ErrorCode TASK_RETURN_NOT_ASSIGN_TARGET_TASK_ID = new ErrorCode(1_009_005_015, "回退任务未指定目标任务编号");
54 ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!"); 55 ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
55 56
56 // ========== 动态表单模块 1-009-010-000 ========== 57 // ========== 动态表单模块 1-009-010-000 ==========
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskRejectHandlerType.java
@@ -14,7 +14,7 @@ import lombok.Getter; @@ -14,7 +14,7 @@ import lombok.Getter;
14 public enum BpmUserTaskRejectHandlerType { 14 public enum BpmUserTaskRejectHandlerType {
15 15
16 TERMINATION(1, "终止流程"), 16 TERMINATION(1, "终止流程"),
17 - RETURN_PRE_USER_TASK(2, "驳回到用户任务"); 17 + RETURN_PRE_USER_TASK(2, "驳回到指定任务节点");
18 18
19 private final Integer type; 19 private final Integer type;
20 private final String name; 20 private final String name;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java
@@ -2,41 +2,23 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener; @@ -2,41 +2,23 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
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.framework.common.util.number.NumberUtils;  
6 -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskReturnReqVO;  
7 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskRejectHandlerType;  
8 -import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;  
9 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;  
10 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;  
11 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;  
12 -import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;  
13 import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService; 5 import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService;
14 -import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;  
15 import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; 6 import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
16 import com.google.common.collect.ImmutableSet; 7 import com.google.common.collect.ImmutableSet;
17 import jakarta.annotation.Resource; 8 import jakarta.annotation.Resource;
18 import lombok.extern.slf4j.Slf4j; 9 import lombok.extern.slf4j.Slf4j;
19 -import org.flowable.bpmn.model.BoundaryEvent;  
20 -import org.flowable.bpmn.model.BpmnModel;  
21 -import org.flowable.bpmn.model.FlowElement;  
22 import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent; 10 import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
23 import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType; 11 import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
24 import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener; 12 import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
25 import org.flowable.engine.delegate.event.FlowableActivityCancelledEvent; 13 import org.flowable.engine.delegate.event.FlowableActivityCancelledEvent;
26 -import org.flowable.engine.delegate.event.FlowableMessageEvent;  
27 import org.flowable.engine.history.HistoricActivityInstance; 14 import org.flowable.engine.history.HistoricActivityInstance;
28 import org.flowable.task.api.Task; 15 import org.flowable.task.api.Task;
29 import org.springframework.context.annotation.Lazy; 16 import org.springframework.context.annotation.Lazy;
30 import org.springframework.stereotype.Component; 17 import org.springframework.stereotype.Component;
31 18
32 import java.util.List; 19 import java.util.List;
33 -import java.util.Objects;  
34 import java.util.Set; 20 import java.util.Set;
35 21
36 -import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;  
37 -import static cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType.USER_TASK_REJECT_POST_PROCESS;  
38 -import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseBoundaryEventExtensionElement;  
39 -  
40 /** 22 /**
41 * 监听 {@link Task} 的开始与完成 23 * 监听 {@link Task} 的开始与完成
42 * 24 *
@@ -52,18 +34,12 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { @@ -52,18 +34,12 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
52 @Resource 34 @Resource
53 @Lazy // 解决循环依赖 35 @Lazy // 解决循环依赖
54 private BpmActivityService activityService; 36 private BpmActivityService activityService;
55 - @Resource  
56 - @Lazy // 解决循环依赖  
57 - private BpmProcessInstanceService processInstanceService;  
58 - @Resource  
59 - @Lazy // 延迟加载,避免循环依赖  
60 - private BpmModelService bpmModelService;  
61 37
62 public static final Set<FlowableEngineEventType> TASK_EVENTS = ImmutableSet.<FlowableEngineEventType>builder() 38 public static final Set<FlowableEngineEventType> TASK_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
63 .add(FlowableEngineEventType.TASK_CREATED) 39 .add(FlowableEngineEventType.TASK_CREATED)
64 .add(FlowableEngineEventType.TASK_ASSIGNED) 40 .add(FlowableEngineEventType.TASK_ASSIGNED)
65 //.add(FlowableEngineEventType.TASK_COMPLETED) // 由于审批通过时,已经记录了 task 的 status 为通过,所以不需要监听了。 41 //.add(FlowableEngineEventType.TASK_COMPLETED) // 由于审批通过时,已经记录了 task 的 status 为通过,所以不需要监听了。
66 - .add(FlowableEngineEventType.ACTIVITY_MESSAGE_RECEIVED) 42 +// .add(FlowableEngineEventType.ACTIVITY_MESSAGE_RECEIVED)
67 .add(FlowableEngineEventType.ACTIVITY_CANCELLED) 43 .add(FlowableEngineEventType.ACTIVITY_CANCELLED)
68 .build(); 44 .build();
69 45
@@ -97,47 +73,47 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { @@ -97,47 +73,47 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
97 }); 73 });
98 } 74 }
99 75
100 - @Override  
101 - protected void activityMessageReceived(FlowableMessageEvent event) {  
102 - BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(event.getProcessDefinitionId());  
103 - FlowElement element = BpmnModelUtils.getFlowElementById(bpmnModel, event.getActivityId());  
104 - if (element instanceof BoundaryEvent) {  
105 - BoundaryEvent boundaryEvent = (BoundaryEvent) element;  
106 - String boundaryEventType = parseBoundaryEventExtensionElement(boundaryEvent, BpmnModelConstants.BOUNDARY_EVENT_TYPE);  
107 - // 如果自定义类型为拒绝后处理,进行拒绝处理  
108 - if (Objects.equals(USER_TASK_REJECT_POST_PROCESS.getType(), NumberUtils.parseInt(boundaryEventType))) {  
109 - String rejectHandlerType = parseBoundaryEventExtensionElement((BoundaryEvent) element, BpmnModelConstants.USER_TASK_REJECT_HANDLER_TYPE);  
110 - rejectHandler(boundaryEvent, event.getProcessInstanceId(), boundaryEvent.getAttachedToRefId(), NumberUtils.parseInt(rejectHandlerType));  
111 - }  
112 - }  
113 - }  
114 -  
115 - private void rejectHandler(BoundaryEvent boundaryEvent, String processInstanceId, String taskDefineKey, Integer rejectHandlerType) {  
116 - BpmUserTaskRejectHandlerType userTaskRejectHandlerType = BpmUserTaskRejectHandlerType.typeOf(rejectHandlerType);  
117 - if (userTaskRejectHandlerType != null) {  
118 - List<Task> taskList = taskService.getAssignedTaskListByConditions(processInstanceId, null, taskDefineKey);  
119 - taskList.forEach(task -> {  
120 - Integer taskStatus = FlowableUtils.getTaskStatus(task);  
121 - // 只有处于拒绝状态下才处理  
122 - if (Objects.equals(BpmTaskStatusEnum.REJECT.getStatus(), taskStatus)) {  
123 - // 终止流程  
124 - if (userTaskRejectHandlerType == BpmUserTaskRejectHandlerType.TERMINATION) {  
125 - processInstanceService.updateProcessInstanceReject(task.getProcessInstanceId(), FlowableUtils.getTaskReason(task));  
126 - return;  
127 - }  
128 - // 驳回  
129 - if (userTaskRejectHandlerType == BpmUserTaskRejectHandlerType.RETURN_PRE_USER_TASK) {  
130 - String returnTaskId = parseBoundaryEventExtensionElement(boundaryEvent, BpmnModelConstants.USER_TASK_REJECT_RETURN_TASK_ID);  
131 - if (returnTaskId != null) {  
132 - BpmTaskReturnReqVO reqVO = new BpmTaskReturnReqVO().setId(task.getId())  
133 - .setTargetTaskDefinitionKey(returnTaskId)  
134 - .setReason("任务拒绝回退");  
135 - taskService.returnTask(getLoginUserId(), reqVO);  
136 - }  
137 - }  
138 - }  
139 - });  
140 - }  
141 - } 76 +// @Override
  77 +// protected void activityMessageReceived(FlowableMessageEvent event) {
  78 +// BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(event.getProcessDefinitionId());
  79 +// FlowElement element = BpmnModelUtils.getFlowElementById(bpmnModel, event.getActivityId());
  80 +// if (element instanceof BoundaryEvent) {
  81 +// BoundaryEvent boundaryEvent = (BoundaryEvent) element;
  82 +// String boundaryEventType = parseBoundaryEventExtensionElement(boundaryEvent, BpmnModelConstants.BOUNDARY_EVENT_TYPE);
  83 +// // 如果自定义类型为拒绝后处理,进行拒绝处理
  84 +// if (Objects.equals(USER_TASK_REJECT_POST_PROCESS.getType(), NumberUtils.parseInt(boundaryEventType))) {
  85 +// String rejectHandlerType = parseBoundaryEventExtensionElement((BoundaryEvent) element, BpmnModelConstants.USER_TASK_REJECT_HANDLER_TYPE);
  86 +// rejectHandler(boundaryEvent, event.getProcessInstanceId(), boundaryEvent.getAttachedToRefId(), NumberUtils.parseInt(rejectHandlerType));
  87 +// }
  88 +// }
  89 +// }
  90 +//
  91 +// private void rejectHandler(BoundaryEvent boundaryEvent, String processInstanceId, String taskDefineKey, Integer rejectHandlerType) {
  92 +// BpmUserTaskRejectHandlerType userTaskRejectHandlerType = BpmUserTaskRejectHandlerType.typeOf(rejectHandlerType);
  93 +// if (userTaskRejectHandlerType != null) {
  94 +// List<Task> taskList = taskService.getAssignedTaskListByConditions(processInstanceId, null, taskDefineKey);
  95 +// taskList.forEach(task -> {
  96 +// Integer taskStatus = FlowableUtils.getTaskStatus(task);
  97 +// // 只有处于拒绝状态下才处理
  98 +// if (Objects.equals(BpmTaskStatusEnum.REJECT.getStatus(), taskStatus)) {
  99 +// // 终止流程
  100 +// if (userTaskRejectHandlerType == BpmUserTaskRejectHandlerType.TERMINATION) {
  101 +// processInstanceService.updateProcessInstanceReject(task.getProcessInstanceId(), FlowableUtils.getTaskReason(task));
  102 +// return;
  103 +// }
  104 +// // 驳回
  105 +// if (userTaskRejectHandlerType == BpmUserTaskRejectHandlerType.RETURN_PRE_USER_TASK) {
  106 +// String returnTaskId = parseBoundaryEventExtensionElement(boundaryEvent, BpmnModelConstants.USER_TASK_REJECT_RETURN_TASK_ID);
  107 +// if (returnTaskId != null) {
  108 +// BpmTaskReturnReqVO reqVO = new BpmTaskReturnReqVO().setId(task.getId())
  109 +// .setTargetTaskDefinitionKey(returnTaskId)
  110 +// .setReason("任务拒绝回退");
  111 +// taskService.returnTask(getLoginUserId(), reqVO);
  112 +// }
  113 +// }
  114 +// }
  115 +// });
  116 +// }
  117 +// }
142 118
143 } 119 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
@@ -5,7 +5,6 @@ import cn.hutool.core.map.MapUtil; @@ -5,7 +5,6 @@ import cn.hutool.core.map.MapUtil;
5 import cn.hutool.core.util.ArrayUtil; 5 import cn.hutool.core.util.ArrayUtil;
6 import cn.hutool.core.util.StrUtil; 6 import cn.hutool.core.util.StrUtil;
7 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 7 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
8 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType;  
9 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; 8 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
10 import org.flowable.bpmn.converter.BpmnXMLConverter; 9 import org.flowable.bpmn.converter.BpmnXMLConverter;
11 import org.flowable.bpmn.model.Process; 10 import org.flowable.bpmn.model.Process;
@@ -43,6 +42,14 @@ public class BpmnModelUtils { @@ -43,6 +42,14 @@ public class BpmnModelUtils {
43 return candidateParam; 42 return candidateParam;
44 } 43 }
45 44
  45 + public static String parseExtensionElement(FlowElement flowElement, String elementName) {
  46 + if (flowElement == null) {
  47 + return null;
  48 + }
  49 + ExtensionElement element = CollUtil.getFirst(flowElement.getExtensionElements().get(elementName));
  50 + return Optional.ofNullable(element).map(ExtensionElement::getElementText).orElse(null);
  51 + }
  52 +
46 // TODO @jason:貌似这个没地方调用??? @芋艿 在 BpmTaskConvert里面。暂时注释掉了。 53 // TODO @jason:貌似这个没地方调用??? @芋艿 在 BpmTaskConvert里面。暂时注释掉了。
47 public static Map<String, Integer> parseFormFieldsPermission(BpmnModel bpmnModel, String flowElementId) { 54 public static Map<String, Integer> parseFormFieldsPermission(BpmnModel bpmnModel, String flowElementId) {
48 FlowElement flowElement = getFlowElementById(bpmnModel, flowElementId); 55 FlowElement flowElement = getFlowElementById(bpmnModel, flowElementId);
@@ -361,27 +368,6 @@ public class BpmnModelUtils { @@ -361,27 +368,6 @@ public class BpmnModelUtils {
361 return userTaskList; 368 return userTaskList;
362 } 369 }
363 370
364 - /**  
365 - * 在用户任务中查找自定义的边界事件  
366 - *  
367 - * @param userTask 用户任务  
368 - * @param bpmBoundaryEventType 自定义的边界事件类型  
369 - */  
370 - public static BoundaryEvent findCustomBoundaryEventOfUserTask(UserTask userTask, BpmBoundaryEventType bpmBoundaryEventType) {  
371 - if (userTask == null) {  
372 - return null;  
373 - }  
374 - BoundaryEvent result = null;  
375 - for (BoundaryEvent item : userTask.getBoundaryEvents()) {  
376 - String boundaryEventType = parseBoundaryEventExtensionElement(item, BpmnModelConstants.BOUNDARY_EVENT_TYPE);  
377 - if (Objects.equals(bpmBoundaryEventType.getType(), NumberUtils.parseInt(boundaryEventType))) {  
378 - result = item;  
379 - break;  
380 - }  
381 - }  
382 - return result;  
383 - }  
384 -  
385 public static String parseBoundaryEventExtensionElement(BoundaryEvent boundaryEvent, String customElement) { 371 public static String parseBoundaryEventExtensionElement(BoundaryEvent boundaryEvent, String customElement) {
386 if (boundaryEvent == null) { 372 if (boundaryEvent == null) {
387 return null; 373 return null;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
@@ -23,10 +23,8 @@ import java.util.List; @@ -23,10 +23,8 @@ import java.util.List;
23 import java.util.Map; 23 import java.util.Map;
24 import java.util.Objects; 24 import java.util.Objects;
25 25
26 -import static cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType.USER_TASK_REJECT_POST_PROCESS;  
27 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType.USER_TASK_TIMEOUT; 26 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType.USER_TASK_TIMEOUT;
28 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.END_EVENT; 27 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.END_EVENT;
29 -import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskRejectHandlerType.RETURN_PRE_USER_TASK;  
30 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutActionEnum.AUTO_REMINDER; 28 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutActionEnum.AUTO_REMINDER;
31 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; 29 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*;
32 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants.*; 30 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants.*;
@@ -222,12 +220,6 @@ public class SimpleModelUtils { @@ -222,12 +220,6 @@ public class SimpleModelUtils {
222 BoundaryEvent boundaryEvent = buildUserTaskTimerBoundaryEvent(userTask, userTaskConfig.getTimeoutHandler()); 220 BoundaryEvent boundaryEvent = buildUserTaskTimerBoundaryEvent(userTask, userTaskConfig.getTimeoutHandler());
223 mainProcess.addFlowElement(boundaryEvent); 221 mainProcess.addFlowElement(boundaryEvent);
224 } 222 }
225 - if (userTaskConfig.getRejectHandler() != null) {  
226 - // 添加用户任务拒绝 Message Boundary Event, 用于任务的拒绝处理  
227 - BoundaryEvent boundaryEvent = buildUserTaskRejectBoundaryEvent(userTask, userTaskConfig.getRejectHandler());  
228 - mainProcess.addFlowElement(boundaryEvent);  
229 - }  
230 -  
231 break; 223 break;
232 } 224 }
233 case COPY_TASK: { 225 case COPY_TASK: {
@@ -284,23 +276,6 @@ public class SimpleModelUtils { @@ -284,23 +276,6 @@ public class SimpleModelUtils {
284 } 276 }
285 } 277 }
286 278
287 - private static BoundaryEvent buildUserTaskRejectBoundaryEvent(UserTask userTask, RejectHandler rejectHandler) {  
288 - BoundaryEvent messageBoundaryEvent = new BoundaryEvent();  
289 - messageBoundaryEvent.setId("Event-" + IdUtil.fastUUID());  
290 - // 设置关联的任务为不会被中断  
291 - messageBoundaryEvent.setCancelActivity(false);  
292 - messageBoundaryEvent.setAttachedToRef(userTask);  
293 - MessageEventDefinition messageEventDefinition = new MessageEventDefinition();  
294 - messageEventDefinition.setMessageRef(REJECT_POST_PROCESS_MESSAGE_NAME);  
295 - messageBoundaryEvent.addEventDefinition(messageEventDefinition);  
296 - addExtensionElement(messageBoundaryEvent, BOUNDARY_EVENT_TYPE, USER_TASK_REJECT_POST_PROCESS.getType().toString());  
297 - addExtensionElement(messageBoundaryEvent, USER_TASK_REJECT_HANDLER_TYPE, StrUtil.toStringOrNull(rejectHandler.getType()));  
298 - if (Objects.equals(rejectHandler.getType(), RETURN_PRE_USER_TASK.getType())) {  
299 - addExtensionElement(messageBoundaryEvent, USER_TASK_REJECT_RETURN_TASK_ID, rejectHandler.getReturnNodeId());  
300 - }  
301 - return messageBoundaryEvent;  
302 - }  
303 -  
304 private static BoundaryEvent buildUserTaskTimerBoundaryEvent(UserTask userTask, SimpleModelUserTaskConfig.TimeoutHandler timeoutHandler) { 279 private static BoundaryEvent buildUserTaskTimerBoundaryEvent(UserTask userTask, SimpleModelUserTaskConfig.TimeoutHandler timeoutHandler) {
305 // 定时器边界事件 280 // 定时器边界事件
306 BoundaryEvent boundaryEvent = new BoundaryEvent(); 281 BoundaryEvent boundaryEvent = new BoundaryEvent();
@@ -406,9 +381,19 @@ public class SimpleModelUtils { @@ -406,9 +381,19 @@ public class SimpleModelUtils {
406 addFormFieldsPermission(userTaskConfig.getFieldsPermission(), userTask); 381 addFormFieldsPermission(userTaskConfig.getFieldsPermission(), userTask);
407 // 处理多实例 382 // 处理多实例
408 processMultiInstanceLoopCharacteristics(userTaskConfig.getApproveMethod(), userTask); 383 processMultiInstanceLoopCharacteristics(userTaskConfig.getApproveMethod(), userTask);
  384 + // 添加任务被拒绝的处理元素
  385 + addTaskRejectElements(userTaskConfig.getRejectHandler(), userTask);
409 return userTask; 386 return userTask;
410 } 387 }
411 388
  389 + private static void addTaskRejectElements(RejectHandler rejectHandler, UserTask userTask) {
  390 + if (rejectHandler == null) {
  391 + return;
  392 + }
  393 + addExtensionElement(userTask, USER_TASK_REJECT_HANDLER_TYPE, StrUtil.toStringOrNull(rejectHandler.getType()));
  394 + addExtensionElement(userTask, USER_TASK_REJECT_RETURN_TASK_ID, rejectHandler.getReturnNodeId());
  395 + }
  396 +
412 private static void processMultiInstanceLoopCharacteristics(Integer approveMethod, UserTask userTask) { 397 private static void processMultiInstanceLoopCharacteristics(Integer approveMethod, UserTask userTask) {
413 BpmApproveMethodEnum bpmApproveMethodEnum = BpmApproveMethodEnum.valueOf(approveMethod); 398 BpmApproveMethodEnum bpmApproveMethodEnum = BpmApproveMethodEnum.valueOf(approveMethod);
414 if (bpmApproveMethodEnum == null || bpmApproveMethodEnum == BpmApproveMethodEnum.SINGLE_PERSON_APPROVE) { 399 if (bpmApproveMethodEnum == null || bpmApproveMethodEnum == BpmApproveMethodEnum.SINGLE_PERSON_APPROVE) {
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
@@ -12,13 +12,12 @@ import cn.iocoder.yudao.framework.common.util.object.PageUtils; @@ -12,13 +12,12 @@ import cn.iocoder.yudao.framework.common.util.object.PageUtils;
12 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; 12 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
13 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; 13 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
14 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; 14 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
15 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType; 15 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskRejectHandlerType;
16 import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum; 16 import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum;
17 import cn.iocoder.yudao.module.bpm.enums.task.BpmDeleteReasonEnum; 17 import cn.iocoder.yudao.module.bpm.enums.task.BpmDeleteReasonEnum;
18 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum; 18 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum;
19 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum; 19 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
20 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants; 20 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants;
21 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;  
22 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; 21 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
23 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; 22 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
24 import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; 23 import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
@@ -28,7 +27,6 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; @@ -28,7 +27,6 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
28 import jakarta.annotation.Resource; 27 import jakarta.annotation.Resource;
29 import jakarta.validation.Valid; 28 import jakarta.validation.Valid;
30 import lombok.extern.slf4j.Slf4j; 29 import lombok.extern.slf4j.Slf4j;
31 -import org.flowable.bpmn.model.BoundaryEvent;  
32 import org.flowable.bpmn.model.BpmnModel; 30 import org.flowable.bpmn.model.BpmnModel;
33 import org.flowable.bpmn.model.FlowElement; 31 import org.flowable.bpmn.model.FlowElement;
34 import org.flowable.bpmn.model.UserTask; 32 import org.flowable.bpmn.model.UserTask;
@@ -36,7 +34,6 @@ import org.flowable.engine.HistoryService; @@ -36,7 +34,6 @@ import org.flowable.engine.HistoryService;
36 import org.flowable.engine.ManagementService; 34 import org.flowable.engine.ManagementService;
37 import org.flowable.engine.RuntimeService; 35 import org.flowable.engine.RuntimeService;
38 import org.flowable.engine.TaskService; 36 import org.flowable.engine.TaskService;
39 -import org.flowable.engine.runtime.Execution;  
40 import org.flowable.engine.runtime.ProcessInstance; 37 import org.flowable.engine.runtime.ProcessInstance;
41 import org.flowable.task.api.DelegationState; 38 import org.flowable.task.api.DelegationState;
42 import org.flowable.task.api.Task; 39 import org.flowable.task.api.Task;
@@ -57,6 +54,8 @@ import java.util.stream.Stream; @@ -57,6 +54,8 @@ import java.util.stream.Stream;
57 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 54 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
58 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 55 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
59 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; 56 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
  57 +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_REJECT_HANDLER_TYPE;
  58 +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_REJECT_RETURN_TASK_ID;
60 59
61 /** 60 /**
62 * 流程任务实例 Service 实现类 61 * 流程任务实例 Service 实现类
@@ -336,23 +335,23 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -336,23 +335,23 @@ public class BpmTaskServiceImpl implements BpmTaskService {
336 // 2.2 添加评论 335 // 2.2 添加评论
337 taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.REJECT.getType(), 336 taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.REJECT.getType(),
338 BpmCommentTypeEnum.REJECT.formatComment(reqVO.getReason())); 337 BpmCommentTypeEnum.REJECT.formatComment(reqVO.getReason()));
339 - 338 + // 3.1 解析用户任务的拒绝处理类型
340 BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId()); 339 BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
341 FlowElement flowElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); 340 FlowElement flowElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
342 - // 寻找用户任务的自定义拒绝后处理边界事件  
343 - BoundaryEvent rejectBoundaryEvent = BpmnModelUtils.findCustomBoundaryEventOfUserTask((UserTask) flowElement,  
344 - BpmBoundaryEventType.USER_TASK_REJECT_POST_PROCESS);  
345 -  
346 - if (rejectBoundaryEvent != null) {  
347 - Execution execution = runtimeService.createExecutionQuery().processInstanceId(task.getProcessInstanceId())  
348 - .activityId(rejectBoundaryEvent.getId()).singleResult();  
349 - if (execution != null) {  
350 - // 3.1 触发消息边界事件. 进一步的处理交给 BpmTaskEventListener  
351 - runtimeService.messageEventReceived(BpmnModelConstants.REJECT_POST_PROCESS_MESSAGE_NAME, execution.getId());  
352 - return; 341 + Integer rejectHandlerType = NumberUtils.parseInt(BpmnModelUtils.parseExtensionElement(flowElement, USER_TASK_REJECT_HANDLER_TYPE));
  342 + BpmUserTaskRejectHandlerType userTaskRejectHandlerType = BpmUserTaskRejectHandlerType.typeOf(rejectHandlerType);
  343 + // 3.2 类型为驳回到指定的任务节点
  344 + if (userTaskRejectHandlerType == BpmUserTaskRejectHandlerType.RETURN_PRE_USER_TASK) {
  345 + String returnTaskId = BpmnModelUtils.parseExtensionElement(flowElement, USER_TASK_REJECT_RETURN_TASK_ID);
  346 + if (returnTaskId == null) {
  347 + throw exception(TASK_RETURN_NOT_ASSIGN_TARGET_TASK_ID);
353 } 348 }
  349 + BpmTaskReturnReqVO returnReq = new BpmTaskReturnReqVO().setId(task.getId()).setTargetTaskDefinitionKey(returnTaskId)
  350 + .setReason(reqVO.getReason());
  351 + returnTask(userId, returnReq);
  352 + return;
354 } 353 }
355 - // 3.2 没有找到拒绝后处理边界事件, 更新流程实例,审批不通过! 354 + // 3.3 其他情况 终止流程。 TODO 后续可能会增加处理类型
356 processInstanceService.updateProcessInstanceReject(instance.getProcessInstanceId(), reqVO.getReason()); 355 processInstanceService.updateProcessInstanceReject(instance.getProcessInstanceId(), reqVO.getReason());
357 } 356 }
358 357