Activiti6---流程的撤回

1. 说明

场景:以我的案例4基础上加入这样一个中国式需求,例如:申请人提交请假单后发现自己写错了,需要撤回提交的操作,重新填写提交。那么应该怎么解决。这就是流程的撤回,以下是测试流程撤回的操作。

2. 实现流程撤回的思路

1、获取当前任务所在的节点
2、获取所在节点的流出方向
3、记录所在节点的流出方向,并将所在节点的流出方向清空
4、获取目标节点
5、创建新的方向
6、将新的方向set到所在节点的流出方向
7、完成当前任务
8、还原所在节点的流出方向

3. 测试

设计流程图:
在这里插入图片描述
Bpmn文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1597282397003" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
  <process id="withdraw" isClosed="false" isExecutable="true" processType="None">
    <startEvent id="_2" name="开始"/>
    <userTask activiti:assignee="zhangsan" activiti:exclusive="true" id="_3" name="原始任务A"/>
    <userTask activiti:assignee="lisi" activiti:exclusive="true" id="_4" name="原始任务B"/>
    <endEvent id="_5" name="结束"/>
    <sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/>
    <sequenceFlow id="_7" sourceRef="_3" targetRef="_4"/>
    <sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/>
  </process>
  <bpmndi:BPMNDiagram documentation="background=#000000;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
    <bpmndi:BPMNPlane bpmnElement="withdraw">
      <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
        <omgdc:Bounds height="32.0" width="32.0" x="-5.0" y="325.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
        <omgdc:Bounds height="55.0" width="85.0" x="140.0" y="310.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
        <omgdc:Bounds height="55.0" width="85.0" x="350.0" y="310.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
        <omgdc:Bounds height="32.0" width="32.0" x="545.0" y="320.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_2" targetElement="_3">
        <omgdi:waypoint x="27.0" y="341.0"/>
        <omgdi:waypoint x="140.0" y="337.5"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_3" targetElement="_4">
        <omgdi:waypoint x="225.0" y="337.5"/>
        <omgdi:waypoint x="350.0" y="337.5"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_4" targetElement="_5">
        <omgdi:waypoint x="435.0" y="337.5"/>
        <omgdi:waypoint x="545.0" y="336.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

测试类:

package com.yb;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.hibernate.service.spi.ServiceException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * @author [email protected]
 * @version 1.0
 * @date 2020/8/5
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class ActivitiJpaTest08 {
    
    

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private TaskService taskService;
    @Resource
    private HistoryService historyService;

    @Resource
    private HttpServletRequest request;
    /**
     * 部署流程,测试撤回
     */
    @Test
    public void repositoryDeploy(){
    
    
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("processes/BackOff.bpmn")
                .addClasspathResource("processes/BackOff.png")
                .name("测试撤回-1")
                .deploy();
        System.out.println("部署ID:"+deploy.getId());
        System.out.println("部署名称"+deploy.getName());
    }

    /**
     * 发布流程
     */
    @Test
    public void runtimeRelease(){
    
    

        ProcessInstance pi = runtimeService.startProcessInstanceByKey("withdraw");
        System.out.println("流程实例ID:"+pi.getId());
        System.out.println("流程定义ID:"+pi.getProcessDefinitionId());
    }

    /**
     * 查询及完成任务
     */
    @Test
    public void taskQueryComplete(){
    
    
        List<Task> list = taskService.createTaskQuery()
                .taskAssignee("zhangsan")
                .list();
        for (Task task : list) {
    
    
            System.out.println("--------------------------------------------");
            System.out.println("任务ID:" + task.getId());
            System.out.println("任务名称:" + task.getName());
            System.out.println("任务创建时间:" + task.getCreateTime());
            System.out.println("任务委派人:" + task.getAssignee());
            System.out.println("流程实例ID:" + task.getProcessInstanceId());
            System.out.println("--------------------------------------------");
            taskService.complete(task.getId());
        }
    }





    /**
     *撤回上一个节点
     */
    @Test
    public void taskQueryComplete2() throws Exception{
    
    
        //当前任务
        Task task = taskService.createTaskQuery()
                .taskAssignee("lisi")
                .singleResult();
        if(task==null) {
    
    
            throw new ServiceException("流程未启动或已执行完成,无法撤回");
        }
        List<HistoricTaskInstance> htlist = historyService.createHistoricTaskInstanceQuery()
                .processDefinitionId(task.getProcessDefinitionId())
                .list();

        String myTaskId = null;
        HistoricTaskInstance myTask = null;

        for (HistoricTaskInstance hti : htlist) {
    
    
            //回退到zhangsan也就是任务A,业务中这里就是当前登录的用户名
            if(hti.getAssignee().equals("zhangsan")){
    
    
                myTaskId=hti.getId();

                myTask=hti;
                break;
            }
        }

        if(myTask==null){
    
    
            throw new ServiceException("该任务非当前用户提交,无法撤回");
        }

        String processDefinitionId = myTask.getProcessDefinitionId();
        

        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);


        String myActivityId = null;

        List<HistoricActivityInstance> haiList =
                historyService
                        .createHistoricActivityInstanceQuery()
                        .executionId(myTask.getExecutionId())
                        .finished()
                        .list();

        for (HistoricActivityInstance hai : haiList) {
    
    
            if(myTaskId.equals(hai.getTaskId())) {
    
    
                myActivityId = hai.getActivityId();
                break;
            }
        }

        FlowNode myFlowNode =
                (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);

        Execution execution = runtimeService.createExecutionQuery()
                .executionId(task.getExecutionId()).singleResult();

        String activityId = execution.getActivityId();

        System.out.println(activityId);

        FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess()
                .getFlowElement(activityId);

        //记录原活动方向
        List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
        oriSequenceFlows.addAll(flowNode.getOutgoingFlows());

        //清理活动方向
        flowNode.getOutgoingFlows().clear();

        //建立新方向
        List<SequenceFlow> newSequenceFlowList = new ArrayList<SequenceFlow>();
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newSequenceFlowId");
        newSequenceFlow.setSourceFlowElement(flowNode);
        newSequenceFlow.setTargetFlowElement(myFlowNode);
        newSequenceFlowList.add(newSequenceFlow);
        flowNode.setOutgoingFlows(newSequenceFlowList);

        Authentication.setAuthenticatedUserId("zhangsan");
        taskService.addComment(task.getId(), task.getProcessInstanceId(), "撤回");

        //完成任务
        taskService.complete(task.getId());
        //恢复原方向
        flowNode.setOutgoingFlows(oriSequenceFlows);
    }
}

数据库:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Lv_vI/article/details/107997446
今日推荐