Преглед изворни кода

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

jason пре 1 година
родитељ
комит
007639d61a

+ 1 - 0
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 {
     ErrorCode TASK_SIGN_DELETE_NO_PARENT = new ErrorCode(1_009_005_012, "任务减签失败,被减签的任务必须是通过加签生成的任务");
     ErrorCode TASK_SIGN_DELETE_NO_PARENT = new ErrorCode(1_009_005_012, "任务减签失败,被减签的任务必须是通过加签生成的任务");
     ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人");
     ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人");
     ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在");
     ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在");
+    ErrorCode TASK_RETURN_NOT_ASSIGN_TARGET_TASK_ID = new ErrorCode(1_009_005_015, "回退任务未指定目标任务编号");
     ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
     ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
 
 
     // ========== 动态表单模块 1-009-010-000 ==========
     // ========== 动态表单模块 1-009-010-000 ==========

+ 1 - 1
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;
 public enum BpmUserTaskRejectHandlerType {
 public enum BpmUserTaskRejectHandlerType {
 
 
     TERMINATION(1, "终止流程"),
     TERMINATION(1, "终止流程"),
-    RETURN_PRE_USER_TASK(2, "驳回到用户任务");
+    RETURN_PRE_USER_TASK(2, "驳回到指定任务节点");
 
 
     private final Integer type;
     private final Integer type;
     private final String name;
     private final String name;

+ 43 - 67
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;
 
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
-import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskReturnReqVO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskRejectHandlerType;
-import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
-import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
 import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService;
 import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService;
-import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
 import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
 import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSet;
 import jakarta.annotation.Resource;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.flowable.bpmn.model.BoundaryEvent;
-import org.flowable.bpmn.model.BpmnModel;
-import org.flowable.bpmn.model.FlowElement;
 import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
 import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
 import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
 import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
 import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
 import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
 import org.flowable.engine.delegate.event.FlowableActivityCancelledEvent;
 import org.flowable.engine.delegate.event.FlowableActivityCancelledEvent;
-import org.flowable.engine.delegate.event.FlowableMessageEvent;
 import org.flowable.engine.history.HistoricActivityInstance;
 import org.flowable.engine.history.HistoricActivityInstance;
 import org.flowable.task.api.Task;
 import org.flowable.task.api.Task;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 import java.util.List;
 import java.util.List;
-import java.util.Objects;
 import java.util.Set;
 import java.util.Set;
 
 
-import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
-import static cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType.USER_TASK_REJECT_POST_PROCESS;
-import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseBoundaryEventExtensionElement;
-
 /**
 /**
  * 监听 {@link Task} 的开始与完成
  * 监听 {@link Task} 的开始与完成
  *
  *
@@ -52,18 +34,12 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
     @Resource
     @Resource
     @Lazy // 解决循环依赖
     @Lazy // 解决循环依赖
     private BpmActivityService activityService;
     private BpmActivityService activityService;
-    @Resource
-    @Lazy // 解决循环依赖
-    private BpmProcessInstanceService processInstanceService;
-    @Resource
-    @Lazy // 延迟加载,避免循环依赖
-    private BpmModelService bpmModelService;
 
 
     public static final Set<FlowableEngineEventType> TASK_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
     public static final Set<FlowableEngineEventType> TASK_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
             .add(FlowableEngineEventType.TASK_CREATED)
             .add(FlowableEngineEventType.TASK_CREATED)
             .add(FlowableEngineEventType.TASK_ASSIGNED)
             .add(FlowableEngineEventType.TASK_ASSIGNED)
             //.add(FlowableEngineEventType.TASK_COMPLETED) // 由于审批通过时,已经记录了 task 的 status 为通过,所以不需要监听了。
             //.add(FlowableEngineEventType.TASK_COMPLETED) // 由于审批通过时,已经记录了 task 的 status 为通过,所以不需要监听了。
-            .add(FlowableEngineEventType.ACTIVITY_MESSAGE_RECEIVED)
+//            .add(FlowableEngineEventType.ACTIVITY_MESSAGE_RECEIVED)
             .add(FlowableEngineEventType.ACTIVITY_CANCELLED)
             .add(FlowableEngineEventType.ACTIVITY_CANCELLED)
             .build();
             .build();
 
 
@@ -97,47 +73,47 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
         });
         });
     }
     }
 
 
-    @Override
-    protected void activityMessageReceived(FlowableMessageEvent event) {
-        BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(event.getProcessDefinitionId());
-        FlowElement element = BpmnModelUtils.getFlowElementById(bpmnModel, event.getActivityId());
-        if (element instanceof BoundaryEvent) {
-            BoundaryEvent boundaryEvent = (BoundaryEvent) element;
-            String boundaryEventType = parseBoundaryEventExtensionElement(boundaryEvent, BpmnModelConstants.BOUNDARY_EVENT_TYPE);
-            // 如果自定义类型为拒绝后处理,进行拒绝处理
-            if (Objects.equals(USER_TASK_REJECT_POST_PROCESS.getType(), NumberUtils.parseInt(boundaryEventType))) {
-                String rejectHandlerType = parseBoundaryEventExtensionElement((BoundaryEvent) element, BpmnModelConstants.USER_TASK_REJECT_HANDLER_TYPE);
-                rejectHandler(boundaryEvent, event.getProcessInstanceId(), boundaryEvent.getAttachedToRefId(), NumberUtils.parseInt(rejectHandlerType));
-            }
-        }
-    }
-
-    private void rejectHandler(BoundaryEvent boundaryEvent, String processInstanceId, String taskDefineKey, Integer rejectHandlerType) {
-        BpmUserTaskRejectHandlerType userTaskRejectHandlerType = BpmUserTaskRejectHandlerType.typeOf(rejectHandlerType);
-        if (userTaskRejectHandlerType != null) {
-            List<Task> taskList = taskService.getAssignedTaskListByConditions(processInstanceId, null, taskDefineKey);
-            taskList.forEach(task -> {
-                Integer taskStatus = FlowableUtils.getTaskStatus(task);
-                // 只有处于拒绝状态下才处理
-                if (Objects.equals(BpmTaskStatusEnum.REJECT.getStatus(), taskStatus)) {
-                    // 终止流程
-                    if (userTaskRejectHandlerType == BpmUserTaskRejectHandlerType.TERMINATION) {
-                        processInstanceService.updateProcessInstanceReject(task.getProcessInstanceId(), FlowableUtils.getTaskReason(task));
-                        return;
-                    }
-                    // 驳回
-                    if (userTaskRejectHandlerType == BpmUserTaskRejectHandlerType.RETURN_PRE_USER_TASK) {
-                        String returnTaskId = parseBoundaryEventExtensionElement(boundaryEvent, BpmnModelConstants.USER_TASK_REJECT_RETURN_TASK_ID);
-                        if (returnTaskId != null) {
-                            BpmTaskReturnReqVO reqVO = new BpmTaskReturnReqVO().setId(task.getId())
-                                    .setTargetTaskDefinitionKey(returnTaskId)
-                                    .setReason("任务拒绝回退");
-                            taskService.returnTask(getLoginUserId(), reqVO);
-                        }
-                    }
-                }
-            });
-        }
-    }
+//    @Override
+//    protected void activityMessageReceived(FlowableMessageEvent event) {
+//        BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(event.getProcessDefinitionId());
+//        FlowElement element = BpmnModelUtils.getFlowElementById(bpmnModel, event.getActivityId());
+//        if (element instanceof BoundaryEvent) {
+//            BoundaryEvent boundaryEvent = (BoundaryEvent) element;
+//            String boundaryEventType = parseBoundaryEventExtensionElement(boundaryEvent, BpmnModelConstants.BOUNDARY_EVENT_TYPE);
+//            // 如果自定义类型为拒绝后处理,进行拒绝处理
+//            if (Objects.equals(USER_TASK_REJECT_POST_PROCESS.getType(), NumberUtils.parseInt(boundaryEventType))) {
+//                String rejectHandlerType = parseBoundaryEventExtensionElement((BoundaryEvent) element, BpmnModelConstants.USER_TASK_REJECT_HANDLER_TYPE);
+//                rejectHandler(boundaryEvent, event.getProcessInstanceId(), boundaryEvent.getAttachedToRefId(), NumberUtils.parseInt(rejectHandlerType));
+//            }
+//        }
+//    }
+//
+//    private void rejectHandler(BoundaryEvent boundaryEvent, String processInstanceId, String taskDefineKey, Integer rejectHandlerType) {
+//        BpmUserTaskRejectHandlerType userTaskRejectHandlerType = BpmUserTaskRejectHandlerType.typeOf(rejectHandlerType);
+//        if (userTaskRejectHandlerType != null) {
+//            List<Task> taskList = taskService.getAssignedTaskListByConditions(processInstanceId, null, taskDefineKey);
+//            taskList.forEach(task -> {
+//                Integer taskStatus = FlowableUtils.getTaskStatus(task);
+//                // 只有处于拒绝状态下才处理
+//                if (Objects.equals(BpmTaskStatusEnum.REJECT.getStatus(), taskStatus)) {
+//                    // 终止流程
+//                    if (userTaskRejectHandlerType == BpmUserTaskRejectHandlerType.TERMINATION) {
+//                        processInstanceService.updateProcessInstanceReject(task.getProcessInstanceId(), FlowableUtils.getTaskReason(task));
+//                        return;
+//                    }
+//                    // 驳回
+//                    if (userTaskRejectHandlerType == BpmUserTaskRejectHandlerType.RETURN_PRE_USER_TASK) {
+//                        String returnTaskId = parseBoundaryEventExtensionElement(boundaryEvent, BpmnModelConstants.USER_TASK_REJECT_RETURN_TASK_ID);
+//                        if (returnTaskId != null) {
+//                            BpmTaskReturnReqVO reqVO = new BpmTaskReturnReqVO().setId(task.getId())
+//                                    .setTargetTaskDefinitionKey(returnTaskId)
+//                                    .setReason("任务拒绝回退");
+//                            taskService.returnTask(getLoginUserId(), reqVO);
+//                        }
+//                    }
+//                }
+//            });
+//        }
+//    }
 
 
 }
 }

+ 8 - 22
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;
 import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
 import org.flowable.bpmn.converter.BpmnXMLConverter;
 import org.flowable.bpmn.converter.BpmnXMLConverter;
 import org.flowable.bpmn.model.Process;
 import org.flowable.bpmn.model.Process;
@@ -43,6 +42,14 @@ public class BpmnModelUtils {
         return candidateParam;
         return candidateParam;
     }
     }
 
 
+    public static String parseExtensionElement(FlowElement flowElement, String elementName) {
+        if (flowElement == null) {
+            return null;
+        }
+        ExtensionElement element = CollUtil.getFirst(flowElement.getExtensionElements().get(elementName));
+        return Optional.ofNullable(element).map(ExtensionElement::getElementText).orElse(null);
+    }
+
     // TODO @jason:貌似这个没地方调用???  @芋艿 在 BpmTaskConvert里面。暂时注释掉了。
     // TODO @jason:貌似这个没地方调用???  @芋艿 在 BpmTaskConvert里面。暂时注释掉了。
     public static Map<String, Integer> parseFormFieldsPermission(BpmnModel bpmnModel, String flowElementId) {
     public static Map<String, Integer> parseFormFieldsPermission(BpmnModel bpmnModel, String flowElementId) {
         FlowElement flowElement = getFlowElementById(bpmnModel, flowElementId);
         FlowElement flowElement = getFlowElementById(bpmnModel, flowElementId);
@@ -361,27 +368,6 @@ public class BpmnModelUtils {
         return userTaskList;
         return userTaskList;
     }
     }
 
 
-    /**
-     * 在用户任务中查找自定义的边界事件
-     *
-     * @param userTask 用户任务
-     * @param bpmBoundaryEventType 自定义的边界事件类型
-     */
-    public static BoundaryEvent findCustomBoundaryEventOfUserTask(UserTask userTask, BpmBoundaryEventType bpmBoundaryEventType) {
-        if (userTask == null) {
-            return null;
-        }
-        BoundaryEvent result = null;
-        for (BoundaryEvent item : userTask.getBoundaryEvents()) {
-            String boundaryEventType = parseBoundaryEventExtensionElement(item, BpmnModelConstants.BOUNDARY_EVENT_TYPE);
-            if (Objects.equals(bpmBoundaryEventType.getType(), NumberUtils.parseInt(boundaryEventType))) {
-                result = item;
-                break;
-            }
-        }
-        return result;
-    }
-
     public static String parseBoundaryEventExtensionElement(BoundaryEvent boundaryEvent, String customElement) {
     public static String parseBoundaryEventExtensionElement(BoundaryEvent boundaryEvent, String customElement) {
         if (boundaryEvent == null) {
         if (boundaryEvent == null) {
             return null;
             return null;

+ 10 - 25
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;
 import java.util.Map;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Objects;
 
 
-import static cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType.USER_TASK_REJECT_POST_PROCESS;
 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType.USER_TASK_TIMEOUT;
 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType.USER_TASK_TIMEOUT;
 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.END_EVENT;
 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.END_EVENT;
-import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskRejectHandlerType.RETURN_PRE_USER_TASK;
 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutActionEnum.AUTO_REMINDER;
 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutActionEnum.AUTO_REMINDER;
 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*;
 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*;
 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants.*;
 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants.*;
@@ -222,12 +220,6 @@ public class SimpleModelUtils {
                     BoundaryEvent boundaryEvent = buildUserTaskTimerBoundaryEvent(userTask, userTaskConfig.getTimeoutHandler());
                     BoundaryEvent boundaryEvent = buildUserTaskTimerBoundaryEvent(userTask, userTaskConfig.getTimeoutHandler());
                     mainProcess.addFlowElement(boundaryEvent);
                     mainProcess.addFlowElement(boundaryEvent);
                 }
                 }
-                if (userTaskConfig.getRejectHandler() != null) {
-                    // 添加用户任务拒绝 Message Boundary Event, 用于任务的拒绝处理
-                    BoundaryEvent boundaryEvent = buildUserTaskRejectBoundaryEvent(userTask, userTaskConfig.getRejectHandler());
-                    mainProcess.addFlowElement(boundaryEvent);
-                }
-
                 break;
                 break;
             }
             }
             case COPY_TASK: {
             case COPY_TASK: {
@@ -284,23 +276,6 @@ public class SimpleModelUtils {
         }
         }
     }
     }
 
 
-    private static BoundaryEvent buildUserTaskRejectBoundaryEvent(UserTask userTask, RejectHandler rejectHandler) {
-        BoundaryEvent messageBoundaryEvent = new BoundaryEvent();
-        messageBoundaryEvent.setId("Event-" + IdUtil.fastUUID());
-        // 设置关联的任务为不会被中断
-        messageBoundaryEvent.setCancelActivity(false);
-        messageBoundaryEvent.setAttachedToRef(userTask);
-        MessageEventDefinition messageEventDefinition = new MessageEventDefinition();
-        messageEventDefinition.setMessageRef(REJECT_POST_PROCESS_MESSAGE_NAME);
-        messageBoundaryEvent.addEventDefinition(messageEventDefinition);
-        addExtensionElement(messageBoundaryEvent, BOUNDARY_EVENT_TYPE, USER_TASK_REJECT_POST_PROCESS.getType().toString());
-        addExtensionElement(messageBoundaryEvent, USER_TASK_REJECT_HANDLER_TYPE, StrUtil.toStringOrNull(rejectHandler.getType()));
-        if (Objects.equals(rejectHandler.getType(), RETURN_PRE_USER_TASK.getType())) {
-            addExtensionElement(messageBoundaryEvent, USER_TASK_REJECT_RETURN_TASK_ID, rejectHandler.getReturnNodeId());
-        }
-        return messageBoundaryEvent;
-    }
-
     private static BoundaryEvent buildUserTaskTimerBoundaryEvent(UserTask userTask, SimpleModelUserTaskConfig.TimeoutHandler timeoutHandler) {
     private static BoundaryEvent buildUserTaskTimerBoundaryEvent(UserTask userTask, SimpleModelUserTaskConfig.TimeoutHandler timeoutHandler) {
         // 定时器边界事件
         // 定时器边界事件
         BoundaryEvent boundaryEvent = new BoundaryEvent();
         BoundaryEvent boundaryEvent = new BoundaryEvent();
@@ -406,9 +381,19 @@ public class SimpleModelUtils {
         addFormFieldsPermission(userTaskConfig.getFieldsPermission(), userTask);
         addFormFieldsPermission(userTaskConfig.getFieldsPermission(), userTask);
         // 处理多实例
         // 处理多实例
         processMultiInstanceLoopCharacteristics(userTaskConfig.getApproveMethod(), userTask);
         processMultiInstanceLoopCharacteristics(userTaskConfig.getApproveMethod(), userTask);
+        // 添加任务被拒绝的处理元素
+        addTaskRejectElements(userTaskConfig.getRejectHandler(), userTask);
         return userTask;
         return userTask;
     }
     }
 
 
+    private static void addTaskRejectElements(RejectHandler rejectHandler, UserTask userTask) {
+        if (rejectHandler == null) {
+            return;
+        }
+        addExtensionElement(userTask, USER_TASK_REJECT_HANDLER_TYPE, StrUtil.toStringOrNull(rejectHandler.getType()));
+        addExtensionElement(userTask, USER_TASK_REJECT_RETURN_TASK_ID, rejectHandler.getReturnNodeId());
+    }
+
     private static void processMultiInstanceLoopCharacteristics(Integer approveMethod, UserTask userTask) {
     private static void processMultiInstanceLoopCharacteristics(Integer approveMethod, UserTask userTask) {
         BpmApproveMethodEnum bpmApproveMethodEnum = BpmApproveMethodEnum.valueOf(approveMethod);
         BpmApproveMethodEnum bpmApproveMethodEnum = BpmApproveMethodEnum.valueOf(approveMethod);
         if (bpmApproveMethodEnum == null || bpmApproveMethodEnum == BpmApproveMethodEnum.SINGLE_PERSON_APPROVE) {
         if (bpmApproveMethodEnum == null || bpmApproveMethodEnum == BpmApproveMethodEnum.SINGLE_PERSON_APPROVE) {

+ 16 - 17
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;
 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskRejectHandlerType;
 import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum;
 import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum;
 import cn.iocoder.yudao.module.bpm.enums.task.BpmDeleteReasonEnum;
 import cn.iocoder.yudao.module.bpm.enums.task.BpmDeleteReasonEnum;
 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum;
 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum;
 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants;
-import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
 import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
@@ -28,7 +27,6 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import jakarta.annotation.Resource;
 import jakarta.annotation.Resource;
 import jakarta.validation.Valid;
 import jakarta.validation.Valid;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.flowable.bpmn.model.BoundaryEvent;
 import org.flowable.bpmn.model.BpmnModel;
 import org.flowable.bpmn.model.BpmnModel;
 import org.flowable.bpmn.model.FlowElement;
 import org.flowable.bpmn.model.FlowElement;
 import org.flowable.bpmn.model.UserTask;
 import org.flowable.bpmn.model.UserTask;
@@ -36,7 +34,6 @@ import org.flowable.engine.HistoryService;
 import org.flowable.engine.ManagementService;
 import org.flowable.engine.ManagementService;
 import org.flowable.engine.RuntimeService;
 import org.flowable.engine.RuntimeService;
 import org.flowable.engine.TaskService;
 import org.flowable.engine.TaskService;
-import org.flowable.engine.runtime.Execution;
 import org.flowable.engine.runtime.ProcessInstance;
 import org.flowable.engine.runtime.ProcessInstance;
 import org.flowable.task.api.DelegationState;
 import org.flowable.task.api.DelegationState;
 import org.flowable.task.api.Task;
 import org.flowable.task.api.Task;
@@ -57,6 +54,8 @@ import java.util.stream.Stream;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_REJECT_HANDLER_TYPE;
+import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_REJECT_RETURN_TASK_ID;
 
 
 /**
 /**
  * 流程任务实例 Service 实现类
  * 流程任务实例 Service 实现类
@@ -336,23 +335,23 @@ public class BpmTaskServiceImpl implements BpmTaskService {
         // 2.2 添加评论
         // 2.2 添加评论
         taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.REJECT.getType(),
         taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.REJECT.getType(),
                 BpmCommentTypeEnum.REJECT.formatComment(reqVO.getReason()));
                 BpmCommentTypeEnum.REJECT.formatComment(reqVO.getReason()));
-
+        // 3.1 解析用户任务的拒绝处理类型
         BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
         BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
         FlowElement flowElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
         FlowElement flowElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
-        // 寻找用户任务的自定义拒绝后处理边界事件
-        BoundaryEvent rejectBoundaryEvent = BpmnModelUtils.findCustomBoundaryEventOfUserTask((UserTask) flowElement,
-                BpmBoundaryEventType.USER_TASK_REJECT_POST_PROCESS);
-
-        if (rejectBoundaryEvent != null) {
-            Execution execution = runtimeService.createExecutionQuery().processInstanceId(task.getProcessInstanceId())
-                    .activityId(rejectBoundaryEvent.getId()).singleResult();
-            if (execution != null) {
-                // 3.1 触发消息边界事件. 进一步的处理交给 BpmTaskEventListener
-                runtimeService.messageEventReceived(BpmnModelConstants.REJECT_POST_PROCESS_MESSAGE_NAME, execution.getId());
-                return;
+        Integer rejectHandlerType = NumberUtils.parseInt(BpmnModelUtils.parseExtensionElement(flowElement, USER_TASK_REJECT_HANDLER_TYPE));
+        BpmUserTaskRejectHandlerType userTaskRejectHandlerType = BpmUserTaskRejectHandlerType.typeOf(rejectHandlerType);
+        // 3.2 类型为驳回到指定的任务节点
+        if (userTaskRejectHandlerType == BpmUserTaskRejectHandlerType.RETURN_PRE_USER_TASK) {
+            String returnTaskId = BpmnModelUtils.parseExtensionElement(flowElement, USER_TASK_REJECT_RETURN_TASK_ID);
+            if (returnTaskId == null) {
+                throw exception(TASK_RETURN_NOT_ASSIGN_TARGET_TASK_ID);
             }
             }
+            BpmTaskReturnReqVO returnReq = new BpmTaskReturnReqVO().setId(task.getId()).setTargetTaskDefinitionKey(returnTaskId)
+                    .setReason(reqVO.getReason());
+            returnTask(userId, returnReq);
+            return;
         }
         }
-        // 3.2 没有找到拒绝后处理边界事件, 更新流程实例,审批不通过!
+        // 3.3 其他情况 终止流程。 TODO 后续可能会增加处理类型
         processInstanceService.updateProcessInstanceReject(instance.getProcessInstanceId(), reqVO.getReason());
         processInstanceService.updateProcessInstanceReject(instance.getProcessInstanceId(), reqVO.getReason());
     }
     }