activiti 实现连续驳回功能

在使用流程的时候,总是可能会有表单内容漏填的可能,那么就需要对流程进行驳回,甚至是连续驳回的功能。该文章目前只针对于单个流向的流程进行连续驳回的功能实现。

与自定义流程路径跳转到指定的节点不同的是,在有多个节点的情况下不需要专门对每个节点指定一条驳回的路径,且在驳回时会将上一个节点的代办人指定为上个节点的办理人(针对节点的办理人为候选组)。

最终实现思路:

1.取得所有历史任务按时间降序排序,获取当前节点
2.根据当前节点的模型节点id,查找到上一个节点id,获取上一个节点
    根据上一个节点id 去历史任务中查询上一个节点的历史任务中的最后一个
    根据模型节点的唯一标识 分组 并在组内根据创建时间降序排序
3、获取所在节点的流出方向,、记录所在节点的流出方向,并将所在节点的流出方向清空
4、根据创建新的方向
5、将新的方向set到所在节点的流出方向
6、完成当前任务
7、还原所在节点的流出方向

代码实现

/**
     * 1.取得所有历史任务按时间降序排序,获取当前节点
     * 2.根据当前节点的模型节点id,查找到上一个节点id,获取上一个节点
     *    根据上一个节点id 去历史任务中查询上一个节点的历史任务中的最后一个(根据  模型节点的唯一标识 分组 并在组内根据创建时间降序排序)
     * 3、获取所在节点的流出方向,、记录所在节点的流出方向,并将所在节点的流出方向清空
     * 4、根据创建新的方向
     * 5、将新的方向set到所在节点的流出方向
     * 6、完成当前任务
     * 7、还原所在节点的流出方向
     */
    public String backProcess(String processInstanceId, String taskId) throws Exception {
        // 取得所有历史任务按时间降序排序
        List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId)
                .orderByTaskCreateTime().desc().list();
        Integer size = 2;
        if (StringUtils.isEmpty(htiList) || htiList.size() < size) {
            return "流程实例的首个节点不能驳回";
        }
         //所有历史任务根据  模型节点的唯一标识 分组 并在组内根据创建时间降序排序
        Map<String, List<HistoricTaskInstance>> htiGroup = htiList.stream()
                .collect(Collectors.groupingBy(
                        HistoricTaskInstance::getTaskDefinitionKey,
                        Collectors.collectingAndThen(Collectors.toList(),
                                list -> list.stream()
                                        .sorted(Comparator.comparing(HistoricTaskInstance::getCreateTime))
                                        .collect(Collectors.toList()))
                ));



        // list里第一条代表当前任务
        HistoricTaskInstance curTask = htiList.get(0);
        // 当前节点的executionId:历史任务实例相关联的执行ID
        String curExecutionId = curTask.getExecutionId();
        //根据 历史任务实例所属流程的定义ID 查询 流程模型,ID通常是BPMN模型的ID与其版本号的组合 例如exampleDemo:1:77003
        BpmnModel bpmnModel = repositoryService.getBpmnModel(curTask.getProcessDefinitionId());
        //每个模型节点的唯一标识 例:ddfour
        FlowElement currentElement = bpmnModel.getMainProcess().getFlowElement(curTask.getTaskDefinitionKey());
        String lastTaskDefinitionKey = null;
        if (currentElement != null && currentElement instanceof FlowNode) {
            FlowNode currentNode = (FlowNode) currentElement;
            // 获取入口连线
            List<SequenceFlow> incomingFlows = currentNode.getIncomingFlows();
            if (incomingFlows != null && !incomingFlows.isEmpty()) {
                // 在大多数情况下,一个节点只有一个入口连线。
                // 但是,如果存在多个连线,你需要根据你的需求来决定如何处理它们。
                SequenceFlow incomingFlow = incomingFlows.get(0);
                FlowNode previousNode = (FlowNode) incomingFlow.getSourceFlowElement();
                //流程模型 当前节点的上一个节点的key
                 lastTaskDefinitionKey= previousNode.getId();

            }
        }
        List<HistoricTaskInstance> lastTaskResult = htiGroup.get(lastTaskDefinitionKey);
        //上一个任务
        HistoricTaskInstance lastTask =lastTaskResult.get(lastTaskResult.size() - 1);
        // 上一个任务的taskId
        String lastTaskId = lastTask.getId();
        if (null == lastTaskId) {
            throw new Exception("LAST TASK IS NULL");
        }
        String lastActivityId = null;
        List<HistoricActivityInstance> haiFinishedList = historyService.createHistoricActivityInstanceQuery()
                .executionId(lastTask.getExecutionId()).finished().list();
        for (HistoricActivityInstance hai : haiFinishedList) {
            if (lastTaskId.equals(hai.getTaskId())) {
                // 得到ActivityId,只有HistoricActivityInstance对象里才有此方法
                lastActivityId = hai.getActivityId();
                break;
            }
        }

        // 得到上个节点的信息
        FlowNode lastFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(lastActivityId);
        // 取得当前节点的信息
        Execution execution = runtimeService.createExecutionQuery().executionId(curExecutionId).singleResult();
        String curActivityId = execution.getActivityId();
        FlowNode curFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(curActivityId);

        // 记录当前节点的原活动方向
        List<SequenceFlow> oriSequenceFlows = new ArrayList<>();
        oriSequenceFlows.addAll(curFlowNode.getOutgoingFlows());
        // 清理活动方向
        curFlowNode.getOutgoingFlows().clear();
        // 建立新方向
        List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("flow4");
        newSequenceFlow.setSourceFlowElement(curFlowNode);
        newSequenceFlow.setTargetFlowElement(lastFlowNode);
        newSequenceFlowList.add(newSequenceFlow);
        curFlowNode.setOutgoingFlows(newSequenceFlowList);

        // 完成任务
        taskService.complete(taskId);
        // 恢复原方向
        curFlowNode.setOutgoingFlows(oriSequenceFlows);
        // 设置执行人
        Task nextTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
        if (nextTask != null) {
            taskService.setAssignee(nextTask.getId(), lastTask.getAssignee());
        }
        return "驳回成功";
    }

文章参考:activiti 节点驳回处理_activiti驳回任意节点-CSDN博客

本篇文章在该文章上进行了修改,很感谢该作者为我提供了实现思路!

还有,我讨厌vip文章,CSDN的vip太贵了!!!(无能狂怒(-᷅_-᷄))

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值