diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java index 36c65ea77..8ef56cbe8 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java @@ -181,7 +181,7 @@ public class FlwTaskController extends BaseController { * @param instanceId 实例id */ @GetMapping("/getBackTaskNode/{instanceId}") - public R> getBackTaskNode(@PathVariable String instanceId) { + public R> getBackTaskNode(@PathVariable Long instanceId) { return R.ok(flwTaskService.getBackTaskNode(instanceId)); } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java index dc027865f..98e002595 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java @@ -103,7 +103,7 @@ public interface IFlwTaskService { * @param instanceId 实例id * @return 结果 */ - List getBackTaskNode(String instanceId); + List getBackTaskNode(Long instanceId); /** * 终止任务 diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java index b1af57ba8..afbbf88b1 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java @@ -198,15 +198,10 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { } String message = bo.getMessage(); BusinessStatusEnum.checkCancelStatus(instance.getFlowStatus()); - //获取已发布的流程节点 - List flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper().eq(FlowNode::getDefinitionId, definition.getId())); - AssertUtil.isTrue(CollUtil.isEmpty(flowNodes), ExceptionCons.NOT_PUBLISH_NODE); - Node startNode = flowNodes.stream().filter(t -> NodeType.isStart(t.getNodeType())).findFirst().orElse(null); - AssertUtil.isNull(startNode, ExceptionCons.LOST_START_NODE); - Node nextNode = nodeService.getNextNode(definition.getId(), startNode.getNodeCode(), null, SkipType.NONE.getKey()); + String applyNodeCode = WorkflowUtils.applyNodeCode(definition.getId()); //撤销 - WorkflowUtils.backTask(message, instance.getId(), nextNode.getNodeCode(), BusinessStatusEnum.CANCEL.getStatus(), BusinessStatusEnum.CANCEL.getStatus()); - //判断申请人节点是否有多个,只保留一个 + WorkflowUtils.backTask(message, instance.getId(), applyNodeCode, BusinessStatusEnum.CANCEL.getStatus(), BusinessStatusEnum.CANCEL.getStatus()); + //判断或签节点是否有多个,只保留一个 List currentTaskList = taskService.list(FlowFactory.newTask().setInstanceId(instance.getId())); if (CollUtil.isNotEmpty(currentTaskList)) { if (currentTaskList.size() > 1) { diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java index 79334214e..c5dbf9b01 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java @@ -31,7 +31,7 @@ import org.dromara.warm.flow.core.service.*; import org.dromara.warm.flow.orm.entity.*; import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper; -import org.dromara.warm.flow.orm.mapper.FlowSkipMapper; +import org.dromara.warm.flow.orm.mapper.FlowNodeMapper; import org.dromara.warm.flow.orm.mapper.FlowTaskMapper; import org.dromara.workflow.common.enums.TaskAssigneeType; import org.dromara.workflow.common.enums.TaskStatusEnum; @@ -70,12 +70,12 @@ public class FlwTaskServiceImpl implements IFlwTaskService { private final UserService userService; private final FlowTaskMapper flowTaskMapper; private final FlowHisTaskMapper flowHisTaskMapper; - private final FlowSkipMapper flowSkipMapper; private final FlowProcessEventHandler flowProcessEventHandler; private final DefService defService; private final HisTaskService hisTaskService; private final IdentifierGenerator identifierGenerator; private final NodeService nodeService; + private final FlowNodeMapper flowNodeMapper; /** * 启动任务 @@ -343,33 +343,68 @@ public class FlwTaskServiceImpl implements IFlwTaskService { * @param bo 参数 */ @Override + @Transactional(rollbackFor = Exception.class) public boolean backProcess(BackProcessBo bo) { try { Long taskId = bo.getTaskId(); String notice = bo.getNotice(); List messageType = bo.getMessageType(); String message = bo.getMessage(); - List flowTasks = flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class).eq(FlowTask::getId, taskId)); - if (CollUtil.isEmpty(flowTasks)) { + FlowTask task = flowTaskMapper.selectById(taskId); + if (ObjectUtil.isNull(task)) { throw new ServiceException("任务不存在!"); } - Instance inst = insService.getById(flowTasks.get(0).getInstanceId()); + List flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper().eq(FlowNode::getDefinitionId, task.getDefinitionId())); + Instance inst = insService.getById(task.getInstanceId()); BusinessStatusEnum.checkBackStatus(inst.getFlowStatus()); - Long definitionId = flowTasks.get(0).getDefinitionId(); + Long definitionId = task.getDefinitionId(); Definition definition = defService.getById(definitionId); - List flowSkips = flowSkipMapper.selectList(new LambdaQueryWrapper<>(FlowSkip.class).eq(FlowSkip::getDefinitionId, definitionId)); - FlowSkip flowSkip = StreamUtils.findFirst(flowSkips, e -> NodeType.START.getKey().equals(e.getNowNodeType())); - //开始节点的下一节点 - assert flowSkip != null; - //申请人节点 - String applyUserNodeCode = flowSkip.getNextNodeCode(); - if (applyUserNodeCode.equals(bo.getNodeCode())) { - WorkflowUtils.backTask(message, inst.getId(), applyUserNodeCode, TaskStatusEnum.BACK.getStatus(), TaskStatusEnum.BACK.getStatus()); + String applyNodeCode = WorkflowUtils.applyNodeCode(definitionId); + FlowNode node = flowNodes.stream().filter(e -> e.getNodeCode().equals(task.getNodeCode())).findFirst().orElse(null); + BigDecimal nodeRatio = node.getNodeRatio(); + //票签 + if (nodeRatio.compareTo(BigDecimal.ZERO) > 0 && nodeRatio.compareTo(new BigDecimal(100)) < 0) { + List userList = this.currentTaskAllUser(task.getId()); + FlowParams flowParams = FlowParams.build(); + flowParams.nodeCode(bo.getNodeCode()); + flowParams.message(message); + flowParams.skipType(SkipType.PASS.getKey()); + if (applyNodeCode.equals(bo.getNodeCode())) { + flowParams.flowStatus(TaskStatusEnum.BACK.getStatus()).hisStatus(TaskStatusEnum.BACK.getStatus()); + } else { + flowParams.flowStatus(TaskStatusEnum.WAITING.getStatus()).hisStatus(TaskStatusEnum.BACK.getStatus()); + } + flowParams.ignore(true); + //解决票签没权限问题 + if (CollUtil.isNotEmpty(userList)) { + flowParams.handler(userList.get(0).getUserId().toString()); + } + taskService.skip(task.getId(), flowParams); } else { - WorkflowUtils.backTask(message, inst.getId(), bo.getNodeCode(), TaskStatusEnum.WAITING.getStatus(), TaskStatusEnum.BACK.getStatus()); + //申请人节点 + if (applyNodeCode.equals(bo.getNodeCode())) { + WorkflowUtils.backTask(message, inst.getId(), applyNodeCode, TaskStatusEnum.BACK.getStatus(), TaskStatusEnum.BACK.getStatus()); + } else { + WorkflowUtils.backTask(message, inst.getId(), bo.getNodeCode(), TaskStatusEnum.WAITING.getStatus(), TaskStatusEnum.BACK.getStatus()); + } } Instance instance = insService.getById(inst.getId()); - this.setHandler(instance, flowTasks.get(0), null); + //判断申请人节点是否有多个,只保留一个 + List currentTaskList = selectByInstId(instance.getId()); + if (CollUtil.isNotEmpty(currentTaskList)) { + List nodeCodes = StreamUtils.toList(currentTaskList, FlowTask::getNodeCode); + List nodeCodeList = StreamUtils.filter(flowNodes, flowNode -> nodeCodes.contains(flowNode.getNodeCode())); + for (Node n : nodeCodeList) { + List flowTasks = currentTaskList.stream().filter(e -> e.getNodeCode().equals(n.getNodeCode()) && n.getNodeRatio().compareTo(BigDecimal.ZERO) == 0).collect(Collectors.toList()); + if (flowTasks.size() > 1) { + flowTasks.remove(0); + List taskIds = StreamUtils.toList(flowTasks, Task::getId); + WorkflowUtils.getFlowUserService().deleteByTaskIds(taskIds); + flowTaskMapper.deleteByIds(taskIds); + } + } + } + this.setHandler(instance, task, null); //消息通知 WorkflowUtils.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice); return true; @@ -385,7 +420,9 @@ public class FlwTaskServiceImpl implements IFlwTaskService { * @param instanceId 实例id */ @Override - public List getBackTaskNode(String instanceId) { + public List getBackTaskNode(Long instanceId) { + //运行中的节点 + List flowTaskList = this.selectByInstId(instanceId); // 创建查询条件,查询历史任务记录 LambdaQueryWrapper lw = new LambdaQueryWrapper<>(FlowHisTask.class) .select(FlowHisTask::getNodeCode, FlowHisTask::getNodeName) @@ -397,12 +434,17 @@ public class FlwTaskServiceImpl implements IFlwTaskService { if (CollUtil.isEmpty(flowHisTasks)) { return Collections.emptyList(); } - return new ArrayList<>(flowHisTasks.stream() + List flowHisTasksList = new ArrayList<>(flowHisTasks.stream() .collect(Collectors.toMap( FlowHisTask::getNodeCode, task -> task, (existing, replacement) -> existing )).values()); + if (CollUtil.isNotEmpty(flowTaskList)) { + List runNode = StreamUtils.toList(flowTaskList, FlowTask::getNodeCode); + return StreamUtils.filter(flowHisTasksList, e -> !runNode.contains(e.getNodeCode())); + } + return flowHisTasksList; } /** diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java index 9d661ad70..3736027a5 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java @@ -2,6 +2,7 @@ package org.dromara.workflow.utils; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.dromara.common.core.domain.dto.UserDTO; @@ -11,15 +12,22 @@ import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mail.utils.MailUtils; import org.dromara.common.sse.dto.SseMessageDto; import org.dromara.common.sse.utils.SseMessageUtils; +import org.dromara.warm.flow.core.constant.ExceptionCons; import org.dromara.warm.flow.core.dto.FlowParams; import org.dromara.warm.flow.core.entity.Instance; +import org.dromara.warm.flow.core.entity.Node; import org.dromara.warm.flow.core.entity.Task; import org.dromara.warm.flow.core.entity.User; +import org.dromara.warm.flow.core.enums.NodeType; import org.dromara.warm.flow.core.enums.SkipType; +import org.dromara.warm.flow.core.service.NodeService; import org.dromara.warm.flow.core.service.TaskService; import org.dromara.warm.flow.core.service.UserService; +import org.dromara.warm.flow.core.utils.AssertUtil; +import org.dromara.warm.flow.orm.entity.FlowNode; import org.dromara.warm.flow.orm.entity.FlowTask; import org.dromara.warm.flow.orm.entity.FlowUser; +import org.dromara.warm.flow.orm.mapper.FlowNodeMapper; import org.dromara.workflow.common.enums.MessageTypeEnum; import org.dromara.workflow.service.IFlwTaskAssigneeService; import org.dromara.workflow.service.IFlwTaskService; @@ -42,6 +50,8 @@ public class WorkflowUtils { private static final IFlwTaskService flwTaskService = SpringUtils.getBean(IFlwTaskService.class); private static final UserService userService = SpringUtils.getBean(UserService.class); private static final TaskService taskService = SpringUtils.getBean(TaskService.class); + private static final FlowNodeMapper FLOW_NODE_MAPPER = SpringUtils.getBean(FlowNodeMapper.class); + private static final NodeService nodeService = SpringUtils.getBean(NodeService.class); /** * 获取工作流用户service @@ -153,14 +163,30 @@ public class WorkflowUtils { flowParams.skipType(SkipType.PASS.getKey()); flowParams.flowStatus(flowStatus).hisStatus(flowHisStatus); flowParams.ignore(true); - //解决会签,或签撤销没权限问题 + //解决会签没权限问题 if (CollUtil.isNotEmpty(userList)) { flowParams.handler(userList.get(0).getUserId().toString()); } taskService.skip(task.getId(), flowParams); } - //解决会签,或签多人审批问题 + //解决会签多人审批问题 backTask(message, instanceId, targetNodeCode, flowStatus, flowHisStatus); } + /** + * 申请人节点编码 + * + * @param definitionId 流程定义id + * @return 申请人节点编码 + */ + public static String applyNodeCode(Long definitionId) { + //获取已发布的流程节点 + List flowNodes = FLOW_NODE_MAPPER.selectList(new LambdaQueryWrapper().eq(FlowNode::getDefinitionId, definitionId)); + AssertUtil.isTrue(CollUtil.isEmpty(flowNodes), ExceptionCons.NOT_PUBLISH_NODE); + Node startNode = flowNodes.stream().filter(t -> NodeType.isStart(t.getNodeType())).findFirst().orElse(null); + AssertUtil.isNull(startNode, ExceptionCons.LOST_START_NODE); + Node nextNode = nodeService.getNextNode(definitionId, startNode.getNodeCode(), null, SkipType.NONE.getKey()); + return nextNode.getNodeCode(); + } + }