Activiti6+SpringBoot---会签功能学习-2

文章目录

1. 说明

会签功能学习1基础上的升级。

2. 流程实现

场景:有多个项目经理进行审批,全部通过才能结束,全部不同意就驳回重新申请。
流程图:
在这里插入图片描述
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="m1596608849637" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
  <process id="leave" isClosed="false" isExecutable="true" processType="None">
    <startEvent id="_2" name="开始"/>
    <userTask activiti:assignee="${inputUser}" activiti:exclusive="true" id="_3" name="填写请假单">
      <extensionElements>
        <activiti:taskListener class="com.yb.listener.MyCompeteistener" event="create"/>
      </extensionElements>
    </userTask>
    <exclusiveGateway gatewayDirection="Unspecified" id="_4" name="排他网关"/>
    <userTask activiti:assignee="王大" activiti:exclusive="true" id="_5" name="总经理审批"/>
    <userTask activiti:assignee="${assignee}" activiti:exclusive="true" id="_6" name="项目经理审批">
      <extensionElements>
        <activiti:taskListener class="com.yb.listener.MutiGroupsListener" event="create"/>
      </extensionElements>
      <multiInstanceLoopCharacteristics activiti:collection="${assignees}" activiti:elementVariable="assignee" isSequential="false">
        <completionCondition><![CDATA[${
    
    passCount/totalCount==1}]]></completionCondition>
      </multiInstanceLoopCharacteristics>
    </userTask>
    <endEvent id="_7" name="结束"/>
    <sequenceFlow id="_8" sourceRef="_2" targetRef="_3"/>
    <sequenceFlow id="_9" sourceRef="_3" targetRef="_4"/>
    <sequenceFlow id="_10" name="大于三天" sourceRef="_4" targetRef="_5">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${
    
    day>3}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_11" name="小于三天" sourceRef="_4" targetRef="_6">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${
    
    day<=3}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_12" sourceRef="_5" targetRef="_7"/>
    <sequenceFlow id="_13" name="都同意" sourceRef="_6" targetRef="_7">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${
    
    passCount/totalCount==1}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_14" name="不同意" sourceRef="_5" targetRef="_3">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${
    
    status==0}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="_15" name="都不同意" sourceRef="_6" targetRef="_3">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${
    
    passCount/totalCount==0}]]></conditionExpression>
    </sequenceFlow>
  </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="leave">
      <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
        <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="345.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="90.0" y="335.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" isMarkerVisible="false">
        <omgdc:Bounds height="32.0" width="32.0" x="250.0" y="345.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
        <omgdc:Bounds height="55.0" width="85.0" x="375.0" y="280.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6">
        <omgdc:Bounds height="55.0" width="85.0" x="370.0" y="415.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_7" id="Shape-_7">
        <omgdc:Bounds height="32.0" width="32.0" x="555.0" y="350.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="_13" id="BPMNEdge__13" sourceElement="_6" targetElement="_7">
        <omgdi:waypoint x="455.0" y="442.5"/>
        <omgdi:waypoint x="555.0" y="366.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_5" targetElement="_7">
        <omgdi:waypoint x="460.0" y="307.5"/>
        <omgdi:waypoint x="555.0" y="366.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_15" id="BPMNEdge__15" sourceElement="_6" targetElement="_3">
        <omgdi:waypoint x="412.5" y="470.0"/>
        <omgdi:waypoint x="225.0" y="495.0"/>
        <omgdi:waypoint x="132.5" y="390.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_14" id="BPMNEdge__14" sourceElement="_5" targetElement="_3">
        <omgdi:waypoint x="417.5" y="280.0"/>
        <omgdi:waypoint x="135.0" y="250.0"/>
        <omgdi:waypoint x="135.0" y="335.0"/>
        <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="_2" targetElement="_3">
        <omgdi:waypoint x="32.0" y="361.0"/>
        <omgdi:waypoint x="90.0" y="362.5"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_3" targetElement="_4">
        <omgdi:waypoint x="175.0" y="362.5"/>
        <omgdi:waypoint x="250.0" y="361.0"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_11" id="BPMNEdge__11" sourceElement="_4" targetElement="_6">
        <omgdi:waypoint x="282.0" y="361.0"/>
        <omgdi:waypoint x="370.0" y="442.5"/>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_4" targetElement="_5">
        <omgdi:waypoint x="282.0" y="361.0"/>
        <omgdi:waypoint x="375.0" y="307.5"/>
        <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 com.yb.domain.User;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
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.HashMap;
import java.util.List;

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

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

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

    /**
     * 发布流程
     */
    @Test
    public void runtimeRelease(){
    
    
//        User user = (User) request.getServletContext().getAttribute("user");
//        模拟登录用户,进行指定任务人
        User user = new User(1, "jack", "1234");
        HashMap<String, Object> map = new HashMap<>();
        map.put("inputUser",user.getUsername());
        ProcessInstance pi = runtimeService.startProcessInstanceByKey("leave",map);
        System.out.println("流程实例ID:"+pi.getId());
        System.out.println("流程定义ID:"+pi.getProcessDefinitionId());
    }

    /**
     * 查询及完成任务
     */
    @Test
    public void taskQueryComplete(){
    
    
        //        User user = (User) request.getServletContext().getAttribute("user");
        //        模拟登录用户,获取到任务人,进行任务的查询和提交
        List<Task> list = taskService.createTaskQuery()
                .taskAssignee("jack")
                .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());
            //完成任务,这里测试请假3天触发一个角色多个审批人
            HashMap<String, Object> map = new HashMap<>();
            map.put("day",3);
            taskService.complete(task.getId(),map);
        }
    }

    

    

    /**
     * 查询及完成任务+驳回功能
     */
    @Test
    public void taskQueryComplete2(){
    
    

        Task task = taskService.createTaskQuery()
                .taskAssignee("王一")
                .singleResult();
        List<Task> list = taskService.createTaskQuery()
                .taskName(task.getName())
                .processInstanceId(task.getProcessInstanceId())
                .list();
        int passCount = 0;//审批同意人数

        int noPassCount = 0;//审批不同意人数

        int totalCount = 0;//任务总人数

        String tmpPassCount  = runtimeService.getVariable(task.getProcessInstanceId(),
                task.getTaskDefinitionKey()+"#passCount") + "";

        String tmpNoPassCount = runtimeService.getVariable(task.getProcessInstanceId(),
                task.getTaskDefinitionKey()+"#noPassCount")+"";

        String tmpTotal = runtimeService.getVariable(task.getProcessInstanceId(),
                task.getTaskDefinitionKey()+"#totalCount")+"";



        if(!tmpPassCount.equals("null") && !tmpPassCount.trim().equals("")){
    
    

            passCount = Integer.parseInt(tmpPassCount);

        }



        if(!tmpNoPassCount.equals("null") && !tmpNoPassCount.trim().equals("")){
    
    

            noPassCount = Integer.parseInt(tmpNoPassCount);

        }



        if(tmpTotal.equals("null") || tmpTotal.trim().equals("")){
    
    

            totalCount = list.size();

        } else if(!tmpTotal.equals("null") && !tmpTotal.trim().equals("")){
    
    

            totalCount = Integer.parseInt(tmpTotal);
        }
        String passflag = "同意";
        for (Task tmp : list) {
    
    
            if(passflag.equals("同意")&&tmp.getId().equals(task.getId())){
    
    
                passCount++;
            }
            if(passflag.equals("不同意")&&tmp.getId().equals(task.getId())){
    
    
                noPassCount++;
            }
        }

        HashMap<String, Object> map = new HashMap<>();
        map.put("passCount",passCount);
        map.put("noPassCount", noPassCount);
        map.put("totalCount", totalCount);
        map.put(task.getTaskDefinitionKey()+"#passCount", passCount);

        map.put(task.getTaskDefinitionKey()+"#noPassCount", noPassCount);

        map.put(task.getTaskDefinitionKey()+"#totalCount", totalCount);

        taskService.complete(task.getId(),map);
    }
}

填写请假单时监听器
设置下一个assignees的办理人

package com.yb.listener;

import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;

import java.util.ArrayList;

/**
 * @author [email protected]
 * @version 1.0
 * @date 2020/8/11
 */
public class MyCompeteistener implements TaskListener {
    
    
    @Override
    public void notify(DelegateTask delegateTask) {
    
    
        ArrayList<String> list = new ArrayList<>();
        list.add("王一");
        list.add("王二");
        list.add("王三");

        delegateTask.setVariable("assignees",list);
    }
}

项目经理审批时监听器
在审批时把数据库里的三个变量的值更新为0,方便任务再次办理时的计算。

package com.yb.listener;

import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;

/**
 * @author [email protected]
 * @version 1.0
 * @date 2020/8/11
 */
public class MutiGroupsListener implements TaskListener {
    
    
    @Override
    public void notify(DelegateTask delegateTask) {
    
    
        delegateTask.setVariable("passCount","0");
        delegateTask.setVariable("totalCount", "0");
        delegateTask.setVariable("noPassCount", "0");
        
    }
}

测试流程走向:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Lv_vI/article/details/107938032