activiti流程駁回

項目地址:activiti-workflow

在通用審批流中都會有駁回的功能,activiti提供的接口並沒有駁回。本文通過對activiti提供接口的擴展實現流程駁回功能,主要代碼如下

		String processInstanceId = taskCurrent.getProcessInstanceId();
        FlowElement targetFlowElement = null;
        if (StringUtil.isNotEmpty(processRejectParam.getTargetNodeId())) {
            //找到目標節點元素
            targetFlowElement = bpmnModel.getMainProcess().getFlowElement(processRejectParam.getTargetNodeId());
        } else {
        	//開始節點的下一個節點
            targetFlowElement = BpmnUtil.startEventNextTaskId(bpmnModel);
        }
        //當前待審批節點定義Id集合
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();

        if (CollectionUtil.isNotEmpty(taskList)) {
            BpmnModel newBpmnModel = bpmnModel;
            Map<String, List<SequenceFlow>> stringListMap = BpmnUtil.invokeSequenceFlows(newBpmnModel, taskList, targetFlowElement);

            for (Task task : taskList) {
                //記錄原活動方向
                List<SequenceFlow> oriSequenceFlows = new ArrayList<>();
                //當前節點
                oriSequenceFlows.addAll(stringListMap.get(task.getTaskDefinitionKey()));
                FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());
                try {
                    Map<String, Object> variables = new HashMap<>();
                    //當前操作節點
                    if(task.getId().equals(taskCurrent.getId())){
                        //設置當前審批人爲提交人
                        taskService.setAssignee(task.getId(), userId);
                        // 保存任務評價
                        if (StringUtil.isNotEmpty(rejectComment)) {
                            taskService.addComment(task.getId(), task.getProcessInstanceId(), rejectComment);
                        }
                        //設置節點狀態
                        taskService.setVariablesLocal(task.getId(), variables);
                        //完成
                        taskService.complete(task.getId());
                    }else{
                        //完成
                        taskService.complete(task.getId());
                        //刪除任務
                        historyService.deleteHistoricTaskInstance(task.getId());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new ProcessException("流程撤回異常,異常原因:" + e.getMessage());
                } finally {
                    //恢復原方向
                    currentFlowNode.setOutgoingFlows(oriSequenceFlows);
                }
            }
        }

invokeSequenceFlows方法,具體代碼在項目中查看。



    /**
     * 處理撤回連線 可能存在分支
     * @param bpmnModel
     * @param taskList
     * @param targetFlowElement
     * @return
     */
    public static Map<String,List<SequenceFlow>> invokeSequenceFlows(BpmnModel bpmnModel , List<Task> taskList, FlowElement targetFlowElement) {
        Map<String,List<SequenceFlow>> flowElements = new HashMap<>(2);
        //並行網關
        ParallelGateway parallelGateway = new ParallelGateway();
        parallelGateway.setId("parallelGateway" + targetFlowElement.getId());
        parallelGateway.setBehavior(new ParallelGatewayActivityBehavior());
        List<SequenceFlow> parallelSequenceFlowInCome = new ArrayList<>();
        for (Task task : taskList) {
            //當前節點
            FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());
            flowElements.put(currentFlowNode.getId(),currentFlowNode.getOutgoingFlows());

            //重新繪製流程圖,從當前節點到到並行網關
            List<SequenceFlow> parallelSequenceFlowList = new ArrayList<>();
            SequenceFlow parallelSequenceFlow = new SequenceFlow();
            parallelSequenceFlow.setId("newSequenceFlowId" + System.currentTimeMillis());
            parallelSequenceFlow.setSourceFlowElement(currentFlowNode);
            parallelSequenceFlow.setTargetFlowElement(parallelGateway);
            parallelSequenceFlowList.add(parallelSequenceFlow);
            parallelSequenceFlowInCome.add(parallelSequenceFlow);
            currentFlowNode.setOutgoingFlows(parallelSequenceFlowList);
        }
        //重新繪製流程圖,從並行網關到開始節點
        List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
        //繪製連線,加入流程信息,並組裝到流程圖
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newSequenceFlowId" + targetFlowElement.getId());
        newSequenceFlow.setSourceFlowElement(parallelGateway);
        newSequenceFlow.setTargetFlowElement(targetFlowElement);
        newSequenceFlowList.add(newSequenceFlow);
        parallelGateway.setIncomingFlows(parallelSequenceFlowInCome);
        parallelGateway.setOutgoingFlows(newSequenceFlowList);

        return flowElements;
    }

整理一些思路,駁回可選擇傳入目標節點的定義ID,如果沒有就默認選擇開始節點的下一個節點。如果當前存在多個審批任務此次執行的任務完成不做其他操作,其他任務完成後刪除(不留下審批痕跡)。

invokeSequenceFlows主要處理的當前審批可能存在多個任務,處理方式爲,在當前節點前面任務增加一個並行網關,將當前審批節點連線到網關,網關連線到目標節點。這樣處理,不管當前有多少審批任務,由於並行網關是等待前面所有節點全部之下完成纔會繼續後續節點,保證當前審批任務全執行完成。

大概過程是這樣

在這裏插入圖片描述
該方法也使用於撤回(發起人操作),可能存在問題,還需大量測試。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章