gssong
2024-03-25 b5ad057f0697e1bdbb88d26cd5ac72f5f55f7995
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java
@@ -3,7 +3,6 @@
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -20,6 +19,8 @@
import org.dromara.workflow.common.constant.FlowConstant;
import org.dromara.workflow.common.enums.BusinessStatusEnum;
import org.dromara.workflow.common.enums.TaskStatusEnum;
import org.dromara.workflow.domain.ActHiTaskinst;
import org.dromara.workflow.domain.WfTaskBackNode;
import org.dromara.workflow.domain.bo.*;
import org.dromara.workflow.domain.vo.MultiInstanceVo;
import org.dromara.workflow.domain.vo.TaskVo;
@@ -29,8 +30,11 @@
import org.dromara.workflow.flowable.strategy.FlowEventStrategy;
import org.dromara.workflow.flowable.strategy.FlowProcessEventHandler;
import org.dromara.workflow.flowable.strategy.FlowTaskEventHandler;
import org.dromara.workflow.mapper.ActHiTaskinstMapper;
import org.dromara.workflow.mapper.ActTaskMapper;
import org.dromara.workflow.service.IActTaskService;
import org.dromara.workflow.service.IWfTaskBackNodeService;
import org.dromara.workflow.utils.ModelUtils;
import org.dromara.workflow.utils.QueryUtils;
import org.dromara.workflow.utils.WorkflowUtils;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
@@ -42,10 +46,10 @@
import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.flowable.variable.api.persistence.entity.VariableInstance;
import org.springframework.scheduling.annotation.Async;
@@ -73,6 +77,8 @@
    private final ManagementService managementService;
    private final FlowEventStrategy flowEventStrategy;
    private final ActTaskMapper actTaskMapper;
    private final IWfTaskBackNodeService iWfTaskBackNodeService;
    private final ActHiTaskinstMapper actHiTaskinstMapper;
    /**
     * 启动任务
@@ -189,11 +195,14 @@
            //办理意见
            taskService.addComment(completeTaskBo.getTaskId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), StringUtils.isBlank(completeTaskBo.getMessage()) ? "同意" : completeTaskBo.getMessage());
            //办理任务
            taskService.setAssignee(task.getId(), userId);
            if (CollUtil.isNotEmpty(completeTaskBo.getVariables())) {
                taskService.complete(completeTaskBo.getTaskId(), completeTaskBo.getVariables());
            } else {
                taskService.complete(completeTaskBo.getTaskId());
            }
            //记录执行过的流程任务节点
            iWfTaskBackNodeService.recordExecuteNode(task);
            ProcessInstance pi = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult();
            if (pi == null) {
                UpdateBusinessStatusCmd updateBusinessStatusCmd = new UpdateBusinessStatusCmd(task.getProcessInstanceId(), BusinessStatusEnum.FINISH.getStatus());
@@ -203,10 +212,18 @@
                }
            } else {
                List<Task> list = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
                for (Task t : list) {
                    if (ModelUtils.isUserTask(t.getProcessDefinitionId(), t.getTaskDefinitionKey())) {
                        List<HistoricIdentityLink> links = historyService.getHistoricIdentityLinksForTask(t.getId());
                        if (CollUtil.isEmpty(links) && StringUtils.isBlank(t.getAssignee())) {
                            throw new ServiceException("下一节点【" + t.getName() + "】没有办理人!");
                        }
                    }
                }
                if (CollUtil.isNotEmpty(list) && CollUtil.isNotEmpty(completeTaskBo.getWfCopyList())) {
                    TaskEntity newTask = WorkflowUtils.createNewTask(task);
                    taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.COPY.getStatus(),
                        LoginHelper.getLoginUser().getNickname() + "【抄送】给" + String.join(",", StreamUtils.toList(completeTaskBo.getWfCopyList(), WfCopy::getUserName)));
                    taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.COPY.getStatus(), LoginHelper.getLoginUser().getNickname() + "【抄送】给" + String.join(",", StreamUtils.toList(completeTaskBo.getWfCopyList(), WfCopy::getUserName)));
                    taskService.complete(newTask.getId());
                    List<Task> taskList = QueryUtils.taskQuery(task.getProcessInstanceId()).list();
                    WorkflowUtils.createCopyTask(taskList, StreamUtils.toList(completeTaskBo.getWfCopyList(), WfCopy::getUserId));
@@ -245,12 +262,7 @@
        String userId = String.valueOf(LoginHelper.getUserId());
        queryWrapper.eq("t.business_status_", BusinessStatusEnum.WAITING.getStatus());
        queryWrapper.eq(TenantHelper.isEnable(), "t.tenant_id_", TenantHelper.getTenantId());
        queryWrapper.and(w1 ->
            w1.eq("t.assignee_", userId)
                .or(w2 -> w2.isNull("t.assignee_")
                    .apply("exists ( select LINK.ID_ from ACT_RU_IDENTITYLINK LINK where LINK.TASK_ID_ = t.ID_ and LINK.TYPE_ = 'candidate' " +
                        "and (LINK.USER_ID_ = {0} or ( LINK.GROUP_ID_ IN " + getInParam(roleIds) + " ) ))", userId))
        );
        queryWrapper.and(w1 -> w1.eq("t.assignee_", userId).or(w2 -> w2.isNull("t.assignee_").apply("exists ( select LINK.ID_ from ACT_RU_IDENTITYLINK LINK where LINK.TASK_ID_ = t.ID_ and LINK.TYPE_ = 'candidate' " + "and (LINK.USER_ID_ = {0} or ( LINK.GROUP_ID_ IN " + getInParam(roleIds) + " ) ))", userId)));
        if (StringUtils.isNotBlank(taskBo.getName())) {
            queryWrapper.like("t.name_", taskBo.getName());
        }
@@ -263,10 +275,14 @@
        Page<TaskVo> page = actTaskMapper.getTaskWaitByPage(pageQuery.build(), queryWrapper);
        List<TaskVo> taskList = page.getRecords();
        for (TaskVo task : taskList) {
            task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
            task.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId()));
            task.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null);
        if (CollUtil.isNotEmpty(taskList)) {
            for (TaskVo task : taskList) {
                task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
                task.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId()));
                task.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null);
            }
            List<String> processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId);
            WorkflowUtils.setWfFormDefinitionVo(taskList, processDefinitionIds, PROCESS_DEFINITION_ID);
        }
        return new TableDataInfo<>(taskList, page.getTotal());
    }
@@ -317,12 +333,17 @@
                    taskVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(taskVo.getBusinessStatus()));
                    taskVo.setProcessDefinitionKey(e.getProcessDefinitionKey());
                    taskVo.setProcessDefinitionName(e.getProcessDefinitionName());
                    taskVo.setBusinessKey(e.getBusinessKey());
                });
            }
            taskVo.setAssignee(StringUtils.isNotBlank(task.getAssignee()) ? Long.valueOf(task.getAssignee()) : null);
            taskVo.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId()));
            taskVo.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null);
            list.add(taskVo);
        }
        if (CollUtil.isNotEmpty(list)) {
            List<String> processDefinitionIds = StreamUtils.toList(list, TaskVo::getProcessDefinitionId);
            WorkflowUtils.setWfFormDefinitionVo(list, processDefinitionIds, PROCESS_DEFINITION_ID);
        }
        long count = query.count();
        return new TableDataInfo<>(list, count);
@@ -336,39 +357,22 @@
    @Override
    public TableDataInfo<TaskVo> getPageByTaskFinish(TaskBo taskBo, PageQuery pageQuery) {
        String userId = String.valueOf(LoginHelper.getUserId());
        HistoricTaskInstanceQuery query = QueryUtils.hisTaskInstanceQuery();
        query.taskAssignee(userId).finished().orderByHistoricTaskInstanceStartTime().desc();
        if (StringUtils.isNotBlank(taskBo.getName())) {
            query.taskNameLike("%" + taskBo.getName() + "%");
        }
        if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) {
            query.processDefinitionNameLike("%" + taskBo.getProcessDefinitionName() + "%");
        }
        if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) {
            query.processDefinitionKey(taskBo.getProcessDefinitionKey());
        }
        List<HistoricTaskInstance> taskInstanceList = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize());
        List<HistoricProcessInstance> historicProcessInstanceList = null;
        if (CollUtil.isNotEmpty(taskInstanceList)) {
            Set<String> processInstanceIds = StreamUtils.toSet(taskInstanceList, HistoricTaskInstance::getProcessInstanceId);
            historicProcessInstanceList = QueryUtils.hisInstanceQuery(processInstanceIds).list();
        }
        List<TaskVo> list = new ArrayList<>();
        for (HistoricTaskInstance task : taskInstanceList) {
            TaskVo taskVo = BeanUtil.toBean(task, TaskVo.class);
            if (CollUtil.isNotEmpty(historicProcessInstanceList)) {
                historicProcessInstanceList.stream().filter(e -> e.getId().equals(task.getProcessInstanceId())).findFirst().ifPresent(e -> {
                    taskVo.setBusinessStatus(e.getBusinessStatus());
                    taskVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(taskVo.getBusinessStatus()));
                    taskVo.setProcessDefinitionKey(e.getProcessDefinitionKey());
                    taskVo.setProcessDefinitionName(e.getProcessDefinitionName());
                });
        QueryWrapper<TaskVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(taskBo.getName()), "t.name_", taskBo.getName());
        queryWrapper.like(StringUtils.isNotBlank(taskBo.getProcessDefinitionName()), "t.processDefinitionName", taskBo.getProcessDefinitionName());
        queryWrapper.eq(StringUtils.isNotBlank(taskBo.getProcessDefinitionKey()), "t.processDefinitionKey", taskBo.getProcessDefinitionKey());
        queryWrapper.eq("t.assignee_", userId);
        Page<TaskVo> page = actTaskMapper.getTaskFinishByPage(pageQuery.build(), queryWrapper);
        List<TaskVo> taskList = page.getRecords();
        if (CollUtil.isNotEmpty(taskList)) {
            for (TaskVo task : taskList) {
                task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
            }
            taskVo.setAssignee(StringUtils.isNotBlank(task.getAssignee()) ? Long.valueOf(task.getAssignee()) : null);
            list.add(taskVo);
            List<String> processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId);
            WorkflowUtils.setWfFormDefinitionVo(taskList, processDefinitionIds, PROCESS_DEFINITION_ID);
        }
        long count = query.count();
        return new TableDataInfo<>(list, count);
        return new TableDataInfo<>(taskList, page.getTotal());
    }
    /**
@@ -395,7 +399,10 @@
        List<TaskVo> taskList = page.getRecords();
        for (TaskVo task : taskList) {
            task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
            task.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null);
        }
        if (CollUtil.isNotEmpty(taskList)) {
            List<String> processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId);
            WorkflowUtils.setWfFormDefinitionVo(taskList, processDefinitionIds, PROCESS_DEFINITION_ID);
        }
        return new TableDataInfo<>(taskList, page.getTotal());
    }
@@ -407,39 +414,21 @@
     */
    @Override
    public TableDataInfo<TaskVo> getPageByAllTaskFinish(TaskBo taskBo, PageQuery pageQuery) {
        HistoricTaskInstanceQuery query = QueryUtils.hisTaskInstanceQuery();
        query.finished().orderByHistoricTaskInstanceStartTime().desc();
        if (StringUtils.isNotBlank(taskBo.getName())) {
            query.taskNameLike("%" + taskBo.getName() + "%");
        QueryWrapper<TaskVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(taskBo.getName()), "t.name_", taskBo.getName());
        queryWrapper.like(StringUtils.isNotBlank(taskBo.getProcessDefinitionName()), "t.processDefinitionName", taskBo.getProcessDefinitionName());
        queryWrapper.eq(StringUtils.isNotBlank(taskBo.getProcessDefinitionKey()), "t.processDefinitionKey", taskBo.getProcessDefinitionKey());
        Page<TaskVo> page = actTaskMapper.getTaskFinishByPage(pageQuery.build(), queryWrapper);
        List<TaskVo> taskList = page.getRecords();
        for (TaskVo task : taskList) {
            task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
        }
        if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) {
            query.processDefinitionNameLike("%" + taskBo.getProcessDefinitionName() + "%");
        if (CollUtil.isNotEmpty(taskList)) {
            List<String> processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId);
            WorkflowUtils.setWfFormDefinitionVo(taskList, processDefinitionIds, PROCESS_DEFINITION_ID);
        }
        if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) {
            query.processDefinitionKey(taskBo.getProcessDefinitionKey());
        }
        List<HistoricTaskInstance> taskInstanceList = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize());
        List<HistoricProcessInstance> historicProcessInstanceList = null;
        if (CollUtil.isNotEmpty(taskInstanceList)) {
            Set<String> processInstanceIds = StreamUtils.toSet(taskInstanceList, HistoricTaskInstance::getProcessInstanceId);
            historicProcessInstanceList = QueryUtils.hisInstanceQuery(processInstanceIds).list();
        }
        List<TaskVo> list = new ArrayList<>();
        for (HistoricTaskInstance task : taskInstanceList) {
            TaskVo taskVo = BeanUtil.toBean(task, TaskVo.class);
            if (CollUtil.isNotEmpty(historicProcessInstanceList)) {
                historicProcessInstanceList.stream().filter(e -> e.getId().equals(task.getProcessInstanceId())).findFirst().ifPresent(e -> {
                    taskVo.setBusinessStatus(e.getBusinessStatus());
                    taskVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(taskVo.getBusinessStatus()));
                    taskVo.setProcessDefinitionKey(e.getProcessDefinitionKey());
                    taskVo.setProcessDefinitionName(e.getProcessDefinitionName());
                });
            }
            taskVo.setAssignee(Convert.toLong(task.getAssignee()));
            list.add(taskVo);
        }
        long count = query.count();
        return new TableDataInfo<>(list, count);
        return new TableDataInfo<>(taskList, page.getTotal());
    }
    /**
@@ -489,8 +478,7 @@
        if (task.isSuspended()) {
            throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED);
        }
        HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery()
            .processInstanceId(task.getProcessInstanceId()).singleResult();
        HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        BusinessStatusEnum.checkInvalidStatus(historicProcessInstance.getBusinessStatus());
        try {
            if (StringUtils.isBlank(terminationBo.getComment())) {
@@ -525,8 +513,7 @@
     */
    @Override
    public boolean transferTask(TransmitBo transmitBo) {
        Task task = QueryUtils.taskQuery().taskId(transmitBo.getTaskId())
            .taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())).singleResult();
        Task task = QueryUtils.taskQuery().taskId(transmitBo.getTaskId()).taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())).singleResult();
        if (ObjectUtil.isEmpty(task)) {
            throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
        }
@@ -652,7 +639,8 @@
    @Transactional(rollbackFor = Exception.class)
    public String backProcess(BackProcessBo backProcessBo) {
        TaskQuery query = QueryUtils.taskQuery();
        Task task = query.taskId(backProcessBo.getTaskId()).taskAssignee(String.valueOf(LoginHelper.getUserId())).singleResult();
        String userId = String.valueOf(LoginHelper.getUserId());
        Task task = query.taskId(backProcessBo.getTaskId()).taskCandidateOrAssigned(userId).singleResult();
        if (ObjectUtil.isEmpty(task)) {
            throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL);
        }
@@ -669,20 +657,33 @@
            BusinessStatusEnum.checkBackStatus(processInstance.getBusinessStatus());
            //判断是否有多个任务
            List<Task> taskList = QueryUtils.taskQuery(processInstanceId).list();
            //申请人节点
            HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().asc().list().get(0);
            String backTaskDefinitionKey = historicTaskInstance.getTaskDefinitionKey();
            String backTaskDefinitionKey = backProcessBo.getTargetActivityId();
            taskService.addComment(task.getId(), processInstanceId, TaskStatusEnum.BACK.getStatus(), StringUtils.isNotBlank(backProcessBo.getMessage()) ? backProcessBo.getMessage() : "退回");
            if (taskList.size() > 1) {
                //当前多个任务驳回到单个节点
                runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveActivityIdsToSingleActivityId(taskList.stream().map(Task::getTaskDefinitionKey).distinct().collect(Collectors.toList()), backTaskDefinitionKey).changeState();
                ActHiTaskinst actHiTaskinst = new ActHiTaskinst();
                actHiTaskinst.setAssignee(userId);
                actHiTaskinst.setId(task.getId());
                actHiTaskinstMapper.updateById(actHiTaskinst);
            } else {
                //当前单个节点驳回单个节点
                runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveActivityIdTo(task.getTaskDefinitionKey(), backTaskDefinitionKey).changeState();
            }
            //删除并行环节未办理记录
            MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
            if (multiInstance == null && taskList.size() > 1) {
                List<Task> tasks = StreamUtils.filter(taskList, e -> !e.getTaskDefinitionKey().equals(task.getTaskDefinitionKey()));
                actHiTaskinstMapper.deleteBatchIds(StreamUtils.toList(tasks, Task::getId));
            }
            List<HistoricTaskInstance> instanceList = QueryUtils.hisTaskInstanceQuery(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().desc().list();
            List<Task> list = QueryUtils.taskQuery(processInstanceId).list();
            for (Task t : list) {
                taskService.setAssignee(t.getId(), historicTaskInstance.getAssignee());
                instanceList.stream().filter(e -> e.getTaskDefinitionKey().equals(t.getTaskDefinitionKey())).findFirst().ifPresent(e -> {
                    taskService.setAssignee(t.getId(), e.getAssignee());
                });
            }
            //发送消息
            String message = "您的【" + processInstance.getName() + "】单据已经被驳回,请您注意查收。";
@@ -692,11 +693,17 @@
                DeleteExecutionCmd deleteExecutionCmd = new DeleteExecutionCmd(executionEntity.getId());
                managementService.executeCommand(deleteExecutionCmd);
            }
            runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.BACK.getStatus());
            FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(processInstance.getProcessDefinitionKey());
            if (processHandler != null) {
                processHandler.handleProcess(processInstance.getBusinessKey(), BusinessStatusEnum.BACK.getStatus(), false);
            WfTaskBackNode wfTaskBackNode = iWfTaskBackNodeService.getListByInstanceIdAndNodeId(task.getProcessInstanceId(), backProcessBo.getTargetActivityId());
            if (ObjectUtil.isNotNull(wfTaskBackNode) && wfTaskBackNode.getOrderNo() == 0) {
                runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.BACK.getStatus());
                FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(processInstance.getProcessDefinitionKey());
                if (processHandler != null) {
                    processHandler.handleProcess(processInstance.getBusinessKey(), BusinessStatusEnum.BACK.getStatus(), false);
                }
            }
            //删除驳回后的流程节点
            iWfTaskBackNodeService.deleteBackTaskNode(processInstanceId, backProcessBo.getTargetActivityId());
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }