【工作流Activiti7】Activiti7 会签、或签

内容纲要

多个人同时处理一个任务,这种任务我们称之为会签任务 。Activiti实现会签是基于多实例任务,将节点设置成多实例,主要通过在UserTask节点的属性上配置。

file

会签的种类:

  • 按数量通过: 达到一定数量的通过表决后,会签通过。
  • 按比例通过: 达到一定比例的通过表决后,会签通过。
  • 一票否决: 只要有一个表决时否定的,会签通过。
  • 一票通过: 只要有一个表决通过的,会签通过。

每个实例有以下变量:

  • nrOfInstances: 实例总数
  • nrOfActiveInstances: 当前激活的(未完成的)实例总数。 如果串行执行,则改值永远是1
  • nrOfCompletedInstances: 已完成的实例总数

条件${nrOfInstances == nrOfCompletedInstances}表示所有人员审批完成后会签结束。

条件${ nrOfCompletedInstances == 1}表示一个人完成审批,该会签就结束。

其他条件依次类推,同时这里也可以写自己添加的流程变量。

相关文档如下:

file

file

file

file

下面举个例子:

file

file

<process id="countersign" name="countersign" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <userTask id="usertask1" name="申请" activiti:assignee="zhangsan"></userTask>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <userTask id="usertask2" name="会签审批" activiti:assignee="${approver}">
        <multiInstanceLoopCharacteristics isSequential="false" 
            activiti:collection="${approverList}" activiti:elementVariable="approver">
            <completionCondition>${nrOfCompletedInstances == nrOfInstances}</completionCondition>
        </multiInstanceLoopCharacteristics>
    </userTask>
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
    <userTask id="usertask3" name="备案" activiti:assignee="tianqi"></userTask>
    <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
</process>

编写代码:

//  部署流程定义
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("diagram/countersign.bpmn")
                .name("会签示例")
                .key("countersign")
                .deploy();

//  启动流程实例
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String, Object> variables = new HashMap<>();
variables.put("approverList", Arrays.asList("lisi","wangwu","zhaoliu"));
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("countersign", variables);

//  完成任务
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().processInstanceId("107501").taskAssignee("zhaoliu").singleResult();
if (null != task) {
    taskService.complete(task.getId());
}

流程启动后,首先是zhangsan审批

file

file

zhangsan完成自己的任务后,进入会签环节,于是我们看到当前有3个激活的任务

file

file

当lisi完成任务以后,当前任务剩下2个

file

file

当wangwu和zhaoliu都完成任务了以后,会签任务完成,进入下一个环节

file

file

刚才的例子中没有考虑到审批不通过的情况,接下来我们完善一下,考虑下面的流程

file

file

<process id="countersign" name="countersign" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <userTask id="usertask1" name="申请" activiti:assignee="zhangsan"></userTask>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <userTask id="usertask2" name="会签审批" activiti:assignee="${approver}">
        <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="${approverList}" activiti:elementVariable="approver">
            <completionCondition>${nrOfCompletedInstances / nrOfInstances == 1 || pass == false}</completionCondition>
        </multiInstanceLoopCharacteristics>
    </userTask>
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
    <userTask id="usertask3" name="备案" activiti:assignee="tianqi"></userTask>
    <exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway>
    <sequenceFlow id="flow5" sourceRef="usertask2" targetRef="exclusivegateway1"></sequenceFlow>
    <sequenceFlow id="flow6" name="通过" sourceRef="exclusivegateway1" targetRef="usertask3">
        <conditionExpression xsi:type="tFormalExpression"><![CDATA[${pass == true}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow7" name="拒绝" sourceRef="exclusivegateway1" targetRef="usertask1">
        <conditionExpression xsi:type="tFormalExpression"><![CDATA[${pass == false}]]></conditionExpression>
    </sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow8" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
</process>

在会签审批完成任务时就要加上流程变量pass了

RuntimeService runtimeService = processEngine.getRuntimeService();
TaskService taskService = processEngine.getTaskService();

Task task = taskService.createTaskQuery().processInstanceId("152501").taskAssignee("lisi").singleResult();
if (null != task) {
    Map<String, Object> variables = new HashMap<>();
    variables.put("pass", true);
//            variables.put("pass", false);
    taskService.complete(task.getId(), variables);

    runtimeService.getVariable(task.getExecutionId(), "nrOfCompletedInstances");
}

zhaoliu审批的时候pass传的false,于是流程又走到zhangsan那里,流程重新又走了一遍才全部完成

file

file

标签

发表评论