activiti节点撤回

activiti节点撤回

最近项目的需求是对已审批的节点进行撤回操作,核心的思路是:

  1. 校验任务和流程信息
  2. 处理已经完成审批的节点信息,做删除操作
  3. 处理下一节点未审批信息,做删除操作
public Boolean processWithdraw(ProcessWithdrawParam processWithdrawParam) {

        String taskId = processWithdrawParam.getTaskId();
        String userId = processWithdrawParam.getUserId();

        HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).taskAssignee(userId).singleResult();
        if (null == task) {
            throw new ApplicationException("撤回失败,失败原因:未查到任务信息或者你没有权限撤回该任务");
        }

        //获取流程模型
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        if (null == bpmnModel) {
            throw new ApplicationException("撤回失败,失败原因:未查到流程信息!");
        }

        String processInstanceId = task.getProcessInstanceId();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (null == processInstance) {
            throw new ApplicationException("撤回失败,失败原因:流程已经结束,或者最后节点已经审批过,不支持撤回!");
        }

        if (processInstance.isSuspended()) {
            throw new ApplicationException("撤回失败,失败原因:流程已经被禁用,不支持撤回!");
        }

        UserTask currentUserTask = (UserTask)bpmnModel.getFlowElement(task.getTaskDefinitionKey());

        if(currentUserTask == null){
            throw new ApplicationException("撤回失败,失败原因:当前节点不存在,不支持撤回!");
        }

        List tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).listPage(0, 500);
        if(CollectionUtil.isNotEmpty(tasks)){
            identityService.setAuthenticatedUserId(userId);
            for (Task t : tasks) {
                taskService.addComment(t.getId(), processInstanceId, "WITHDRAW", processWithdrawParam.getWithdrawComment());
            }
        }

        //执行命令,撤回审批
        processEngine.getManagementService().executeCommand(new WithdrawApproveCmd(processInstanceId, currentUserTask, processWithdrawParam.getTenantId()));

        return Boolean.TRUE;
    }
/**
 * 任务撤回命令类
 *
 * @author zhougl
 * @version v1.0.0
 * @since 2020/9/21 16:49
 */
public class WithdrawApproveCmd implements Command {
    private static final String TASK_NOT_EXECUTE = "TASK_NOT_EXECUTE";
    private static final String TASK_WITHDRAW = "TASK_WITHDRAW";
    /**
     * 流程实例Id
     */
    private final String processInstanceId;
    private final String tenantId;
    private final UserTask userTask;
    /**
     * 所有后续流转任务节点
     */
    private Set userTasks = new ConcurrentHashSet<>();

    /**
     * 保存撤回节点的变量map
     */
    private Map> varMap = new ConcurrentHashMap<>();

    public WithdrawApproveCmd(String processInstanceId, UserTask userTask, String tenantId) {
        this.processInstanceId = processInstanceId;
        this.tenantId = tenantId;
        this.userTask = userTask;
        takeFlowUserTask(userTask);
        // 把当前任务节点也加到未完成节点(多实例的情况-存在未审批的其他实例,也需要删除)
        userTasks.add(userTask);
    }

    @Override
    public Void execute(CommandContext commandContext) {
        ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
        // 处理已经完成的任务
        handleCompletedTask(commandContext);
        // 删除任务
        handleFollowTask(userTasks, commandContext);
        // 创建子执行流,开启任务
        ExecutionEntity processExecution = executionEntityManager.findById(processInstanceId);
        ExecutionEntity childExecution = executionEntityManager.createChildExecution(processExecution);
        childExecution.setCurrentFlowElement(userTask);

        // 设置执行变量
        VariableInstanceEntityManager variableManager = commandContext.getVariableInstanceEntityManager();
        List variableInstanceEntities = varMap.get(userTask.getId());
        if(CollectionUtil.isNotEmpty(variableInstanceEntities)){
            variableInstanceEntities.forEach(var -> {
                var.setExecution(childExecution);
                variableManager.insert(var);
            });
        }

        commandContext.getExecutionEntityManager().insert(childExecution);
        // 交给activiti流转
        commandContext.getAgenda().planContinueProcessOperation(childExecution);
        return null;
    }

    private void handleCompletedTask(CommandContext commandContext) {
        HistoricTaskInstanceEntityManager historicTaskManager = commandContext.getHistoricTaskInstanceEntityManager();
        HistoricActivityInstanceQueryImpl query =
                new HistoricActivityInstanceQueryImpl().activityId(userTask.getId()).processInstanceId(processInstanceId).activityTenantId(tenantId).finished();
        List activityInstances =
                commandContext.getHistoricActivityInstanceEntityManager().findHistoricActivityInstancesByQueryCriteria(query, new Page(0, Integer.MAX_VALUE));
        for (HistoricActivityInstance activity : activityInstances) {
            HistoricActivityInstanceEntity activityEntity = (HistoricActivityInstanceEntity) activity;
            activityEntity.setDeleted(true);
            activityEntity.setDeleteReason(TASK_WITHDRAW);
            commandContext.getHistoricActivityInstanceEntityManager().update(activityEntity);
            historicTaskManager.delete(activity.getTaskId());
        }

    }

    private void handleFollowTask(Set userTasks, CommandContext commandContext) {
        ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
        HistoricTaskInstanceEntityManager historicTaskManager = commandContext.getHistoricTaskInstanceEntityManager();
        for (UserTask userTask : userTasks) {
            String taskDefId = userTask.getId();
            List executionEntities =
                    new ArrayList<>(executionEntityManager.findInactiveExecutionsByActivityIdAndProcessInstanceId(taskDefId, processInstanceId));
            for (ExecutionEntity parentExecution : executionEntities) {
                //关闭未完成的任务执行流
                List childExecutions =
                        executionEntityManager.findChildExecutionsByParentExecutionId(parentExecution.getId());
                for (ExecutionEntity childExecution : childExecutions) {
                    executionEntityManager.deleteExecutionAndRelatedData(childExecution, TASK_NOT_EXECUTE, false);
                    // 删除历史实例
                    HistoricTaskInstanceQueryImpl query = new HistoricTaskInstanceQueryImpl().executionId(childExecution.getId()).processInstanceId(processInstanceId);
                    List historicTaskInstancesByQueryCriteria =
                            historicTaskManager.findHistoricTaskInstancesByQueryCriteria(query);
                    if (CollectionUtil.isNotEmpty(historicTaskInstancesByQueryCriteria)) {
                        for (HistoricTaskInstance historicTaskInstancesByQueryCriterion :
                                historicTaskInstancesByQueryCriteria) {
                            commandContext.getHistoricTaskInstanceEntityManager().delete(historicTaskInstancesByQueryCriterion.getId());
                        }
                    }
                }

                //父执行流关闭
                VariableInstanceEntityManager variableManager = commandContext.getVariableInstanceEntityManager();
                List variableInstances =
                        variableManager.findVariableInstancesByExecutionId(parentExecution.getId());
                varMap.put(parentExecution.getActivityId(),variableInstances);
                variableInstances.forEach(variableManager::delete);
                executionEntityManager.deleteExecutionAndRelatedData(parentExecution, TASK_NOT_EXECUTE, false);
            }
        }


    }

    private void takeFlowUserTask(FlowNode flowNode) {
        List targetElement =
                flowNode.getOutgoingFlows().stream().map(SequenceFlow::getTargetFlowElement).collect(Collectors.toList());
        targetElement.forEach(flowElement -> {
            if (flowElement instanceof UserTask) {
                userTasks.add((UserTask) flowElement);
            } else {
                List collect =
                        ((FlowNode) flowElement).getOutgoingFlows().stream().map(SequenceFlow::getTargetFlowElement).collect(Collectors.toList());
                collect.forEach(childElement -> takeFlowUserTask((FlowNode) childElement));
            }
        });

    }

}

注意事项:

在删除下一节点流程变量时,需要把下一节点的变量暂存起来,在重新创建执行流时,设置这些变量,因为多实例的创建需要依赖这些变量。

你可能感兴趣的:(流程引擎activiti,activiti,java)