Flowable & 多实例任务 会签

7,581 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

什么是会签任务

  会签任务:一个任务需要两个或者两个以上的成员参与进行审批审批条件是多样,并且可配置通过的权重比例。可以理解为投票,但是也有可能 某一个审批者有一票否决权。

会签任务的内置参数

参数 注释
nrOfInstances 一共多少实例
 nrOfCompletedInstances 已经完成审批数量(包含审批结果为通过和拒绝的)
 nrOfActiveInstances 还未完成审批数量

下面我们去画一个 会签任务的流程图

员工会签 + 排他网关 (会签成功) 到经理审批
      排他网关 (会签失败)到人事审批
排他网关 的条件: ${status=="false"} 人事审批 or ${status=="true"} 经理审批 image.png

第一步先选择实例类型

Parallel 并行,指的如果我们配置了3人会签,3人可以同时在待办看到此任务并处理

sequential 串行,指的是如果我们配置了3人会签,则会需要串行执行,前一个人办理了后一个人才能看到 image.png

第二步 填写多实例集合

image.png

第三步 设置基数和元素变量

这里的基数指的是:创建流程任务的数量
变量指的是:集合里的每一个用户

image.png

第四步 设置一个 执行监听器 类型为 start

image.png 监听类 设置初始 同意人数 和 拒绝人数

@Component("applyTaskListener")
@Slf4j
public class ApplyTaskListener implements ExecutionListener {

    @Override
    public void notify(DelegateExecution delegateExecution) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("reject", 0);//拒绝人数
        map.put("agree", 0);//同意人数
        delegateExecution.setVariables(map);
    }
}

第五步 设置完成标准 和分配用户 这里都用表达式

image.png 完成条件 : ${completeTask.compleTaskTo(execution)} 就是下面这个类

@Component("completeTask")
@Slf4j
public boolean compleTaskTo(DelegateExecution execution){
log.info("任务会签总数:"+execution.getVariable("nrOfInstances"));
log.info("待会签任务数量:"+execution.getVariable("nrOfActiveInstances"));
log.info("已完成会签任务数量:"+execution.getVariable("nrOfCompletedInstances"));
//设置权重
    Integer agree = (Integer) execution.getVariable("agree");//同意人数
    if(agree/(Integer) execution.getVariable("nrOfInstances")>0.5){
        log.info("同意人数:"+agree);
        //设置会签结果 排他网关会用到
        execution.setVariable("status","true");
        return  true;
    }else{
        return  false;
    }
}

完成条件也可以直接 : ${nrOfInstances/nrOfCompletedInstances>=0.5} 同意率大于等于 50%
如果不填写的话就是100% 才算通过

下面我们去部署这个流程图

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.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" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
  <process id="all_key" name="多人会签006" isExecutable="true">
    <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
    <userTask id="sid-56C2E056-E8B9-469A-AA0A-D3DD233E9685" name="员工投票" flowable:assignee="${person}">
      <extensionElements>
        <flowable:executionListener event="start" class="com.xk.flowable.listeners.ApplyTaskListener"></flowable:executionListener>
        <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
      <multiInstanceLoopCharacteristics isSequential="false" flowable:collection="persons" flowable:elementVariable="person">
        <loopCardinality>3</loopCardinality>
        <completionCondition>${completeTask.compleTaskTo(execution)}</completionCondition>
      </multiInstanceLoopCharacteristics>
    </userTask>
    <sequenceFlow id="sid-42768932-9A32-476A-92F5-544164EE44B3" sourceRef="startEvent1" targetRef="sid-56C2E056-E8B9-469A-AA0A-D3DD233E9685"></sequenceFlow>
    <userTask id="sid-AA0E9C86-CDF4-422C-8C99-43ADAF838B57" name="经理审批" flowable:assignee="xkk" flowable:formFieldValidation="true">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <endEvent id="sid-6F85675E-A489-43FD-82EC-7B148D738939"></endEvent>
    <sequenceFlow id="sid-D6A081B4-66A6-4CCB-92C8-DF27962D1B3A" sourceRef="sid-AA0E9C86-CDF4-422C-8C99-43ADAF838B57" targetRef="sid-6F85675E-A489-43FD-82EC-7B148D738939"></sequenceFlow>
    <exclusiveGateway id="sid-83034BD9-1DEB-4AE8-A85E-2BA46A26818B"></exclusiveGateway>
    <sequenceFlow id="sid-A66FF455-D909-4D99-9551-1855F2930951" sourceRef="sid-56C2E056-E8B9-469A-AA0A-D3DD233E9685" targetRef="sid-83034BD9-1DEB-4AE8-A85E-2BA46A26818B"></sequenceFlow>
    <sequenceFlow id="sid-DA44BC94-243B-48F9-BA10-B7BADB3F5DB8" sourceRef="sid-83034BD9-1DEB-4AE8-A85E-2BA46A26818B" targetRef="sid-AA0E9C86-CDF4-422C-8C99-43ADAF838B57">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${status =="true"}]]></conditionExpression>
    </sequenceFlow>
    <userTask id="sid-88EB8D06-A17A-4869-8610-6C090D7BFB88" name="人事审批" flowable:formFieldValidation="true"></userTask>
    <sequenceFlow id="sid-720EC886-26AF-4406-B282-A7AC30B0936B" sourceRef="sid-83034BD9-1DEB-4AE8-A85E-2BA46A26818B" targetRef="sid-88EB8D06-A17A-4869-8610-6C090D7BFB88">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${status=="false"}]]></conditionExpression>
    </sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_all_key">
    <bpmndi:BPMNPlane bpmnElement="all_key" id="BPMNPlane_all_key">
      <bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
        <omgdc:Bounds height="30.0" width="30.0" x="100.0" y="163.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-56C2E056-E8B9-469A-AA0A-D3DD233E9685" id="BPMNShape_sid-56C2E056-E8B9-469A-AA0A-D3DD233E9685">
        <omgdc:Bounds height="80.0" width="100.0" x="175.0" y="138.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-AA0E9C86-CDF4-422C-8C99-43ADAF838B57" id="BPMNShape_sid-AA0E9C86-CDF4-422C-8C99-43ADAF838B57">
        <omgdc:Bounds height="80.0" width="100.0" x="495.0" y="138.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-6F85675E-A489-43FD-82EC-7B148D738939" id="BPMNShape_sid-6F85675E-A489-43FD-82EC-7B148D738939">
        <omgdc:Bounds height="28.0" width="28.0" x="735.0" y="164.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-83034BD9-1DEB-4AE8-A85E-2BA46A26818B" id="BPMNShape_sid-83034BD9-1DEB-4AE8-A85E-2BA46A26818B">
        <omgdc:Bounds height="40.0" width="40.0" x="345.0" y="158.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-88EB8D06-A17A-4869-8610-6C090D7BFB88" id="BPMNShape_sid-88EB8D06-A17A-4869-8610-6C090D7BFB88">
        <omgdc:Bounds height="80.0" width="100.0" x="315.0" y="285.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="sid-720EC886-26AF-4406-B282-A7AC30B0936B" id="BPMNEdge_sid-720EC886-26AF-4406-B282-A7AC30B0936B">
        <omgdi:waypoint x="365.41121495327104" y="197.5296218487395"></omgdi:waypoint>
        <omgdi:waypoint x="365.00441860465116" y="285.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-DA44BC94-243B-48F9-BA10-B7BADB3F5DB8" id="BPMNEdge_sid-DA44BC94-243B-48F9-BA10-B7BADB3F5DB8">
        <omgdi:waypoint x="384.4976130653267" y="178.44692737430168"></omgdi:waypoint>
        <omgdi:waypoint x="495.0" y="178.1391364902507"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-42768932-9A32-476A-92F5-544164EE44B3" id="BPMNEdge_sid-42768932-9A32-476A-92F5-544164EE44B3">
        <omgdi:waypoint x="129.9499984899576" y="178.0"></omgdi:waypoint>
        <omgdi:waypoint x="174.9999999999917" y="178.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-D6A081B4-66A6-4CCB-92C8-DF27962D1B3A" id="BPMNEdge_sid-D6A081B4-66A6-4CCB-92C8-DF27962D1B3A">
        <omgdi:waypoint x="594.9499999999294" y="178.0"></omgdi:waypoint>
        <omgdi:waypoint x="735.0" y="178.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-A66FF455-D909-4D99-9551-1855F2930951" id="BPMNEdge_sid-A66FF455-D909-4D99-9551-1855F2930951">
        <omgdi:waypoint x="274.95000000000005" y="178.0"></omgdi:waypoint>
        <omgdi:waypoint x="345.0" y="178.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
@Test
public void DeployProcess(){
    Deployment holiday = repositoryService.createDeployment()
            .addClasspathResource("多人会签006.bpmn20.xml")
            .name("多人会签006")
            .deploy();
}

启动流程

@Test
public void StatrProcess(){
    //先查到流程
    ProcessDefinition leave_key = repositoryService.createProcessDefinitionQuery().processDefinitionKey("all_key007").singleResult();
    //启动流程并分配给
    Map<String,Object> map = new HashMap<>();
    //注意这里的值必须大于 设置的基数
    map.put("persons", Arrays.asList("张三","李四","王二狗","赵天"));
    runtimeService.startProcessInstanceById(leave_key.getId(), map);
}

DB ACT_RU_TASK

image.png

下面我们切换账户完成这个会签

@Test
public void comleteProcess(){
    Task task = taskService.createTaskQuery()
            //ACT_RU_TASK 表中 PROC_INST_ID_cdbf8217-de81-11ec-8925-666ee0fc370d
            .processInstanceId("17ebd29d-de85-11ec-b5d7-666ee0fc370d")
            .taskAssignee("李四")
            .singleResult();
    if (task!=null){
        Map<String,Object> map = new HashMap<>();
        Integer reject = (int)taskService.getVariable(task.getId(),"agree");
        map.put("agree",reject+1);
        taskService.complete(task.getId(),map);
    }
}

李四的已经处理为 同意

image.png 接着我们把 张三的 成同意 就会看到会签任务完成 并流转到 经理审批

image.png

如果参与会签的所有人都不同意的话就会被排他网关 流转到 认识审批

image.png 到这里 我们的多人会签任务就完成😁😁😁😁