- 会签场景:
开始 - 填写放假通知单(代理人)- 投票审批(指定多个参与人)- 根据设置的完成条件后,全部参与人必须完成后,自动结束流程- 或签场景:
开始 - 填写放假通知单(代理人)- 投票审批(指定多个参与人)- 根据设置的完成条件后,比例数完成,自动结束流程
代码实现
部署流程
@Test
public void deployProcess() throws IOException {
ClassPathResource classPathResource = new ClassPathResource("/processes/holiday.bpmn20.xml");
Deployment deploy = repositoryService.createDeployment()
.addInputStream(classPathResource.getPath(), classPathResource.getInputStream())
.deploy();
System.out.println("deploy = " + deploy);
}
启动流程
@Test
public void startProcess() {
// 设置流程变量
Map<String, Object> variables = new HashMap<>();
variables.put("applyUserId", APPLY_USER_ID);
variables.put("managerList", CollectionUtil.newArrayList("张三", "李四", "王五"));
// 获取流程定义的Key
String processDefinitionKey = "holiday";
// 定义businessKey
String businessKey = processDefinitionKey + ":" + BUSINESS_ID;
// 启动流程
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
System.out.println("processInstance = " + processInstance);
// 获取流程变量
System.out.println("===================流程变量===================");
runtimeService.getVariables(processInstance.getId()).forEach((key, value) -> System.out.println("key:" + key + ",value:" + value));
// 输出当前任务列表
this.printTaskList(processInstance.getId());
}
填写放假通知任务
将启动流程后的流程实例ID更换到下面
@Test
public void fillOutHolidayNotice() {
// 查询任务
Task task = taskService.createTaskQuery().processInstanceId(PROCESS_INSTANCE_ID).taskAssignee(APPLY_USER_ID).singleResult();
// 增加意见
taskService.addComment(task.getId(), task.getProcessInstanceId(), "我支持放假的");
// 完成任务
Map<String, Object> hashMap = new HashMap<>();
hashMap.put("days", 10);
taskService.complete(task.getId(), hashMap);
// 输出当前任务列表
this.printTaskList(task.getProcessInstanceId());
}
投票审批
将启动流程后的流程实例ID更换到下面
@Test
public void voteAudit() {
// 查询任务(代理人分别查询完成)
Task task = taskService.createTaskQuery().processInstanceId(PROCESS_INSTANCE_ID).taskAssignee("张三").singleResult();
// 增加意见
taskService.addComment(task.getId(), task.getProcessInstanceId(), "同意放假");
// 完成任务
taskService.complete(task.getId());
// 输出当前任务列表
this.printTaskList(task.getProcessInstanceId());
}
xml文件
<?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: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" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef">
<process id="holiday" name="放假审批流程" isExecutable="true">
<documentation>模拟放假审批流程</documentation>
<startEvent id="sid-f8852670-b815-4f97-84b0-eb11d34d9334" name="开始"/>
<userTask id="sid-f4101616-870b-45f6-b710-22978eb27828" name="填写放假通知单" activiti:assignee="${applyUserId}"/>
<userTask id="sid-a6f78e45-6624-4996-869d-ae616b2b78e4" name="投票审批" activiti:assignee="${manager}">
<!-- 多实例会签 -->
<multiInstanceLoopCharacteristics isSequential="false" activiti:collection="${managerList}" activiti:elementVariable="manager">
<!--
isSequential:false表示并行,true串行
activiti:collection:多实例人员集合变量
activiti:elementVariable:人员集合中的元素变量,这里要UserTask中activiti:assignee的值对应
nrOfInstances:总实例数
nrOfCompletedInstances:完成数
completionCondition:完成条件
-->
<!-- <completionCondition><![CDATA[${nrOfCompletedInstances == nrOfInstances}]]></completionCondition>-->
<completionCondition><![CDATA[${nrOfCompletedInstances/nrOfInstances >= 0.6}]]></completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<sequenceFlow id="sid-92f3fd0d-a6ed-45cc-ae12-71adb0d0060b" sourceRef="sid-f8852670-b815-4f97-84b0-eb11d34d9334" targetRef="sid-f4101616-870b-45f6-b710-22978eb27828"/>
<sequenceFlow id="sid-14fabbf8-263a-4b6b-a8b2-60c494ec52ae" sourceRef="sid-f4101616-870b-45f6-b710-22978eb27828" targetRef="sid-a6f78e45-6624-4996-869d-ae616b2b78e4"/>
<endEvent id="sid-b9011d2c-1871-49d2-82bb-b521dbd9dfeb" name="结束"/>
<sequenceFlow id="sid-6aa8c217-001a-43a3-a28b-509edc0100a2" sourceRef="sid-a6f78e45-6624-4996-869d-ae616b2b78e4" targetRef="sid-b9011d2c-1871-49d2-82bb-b521dbd9dfeb"/>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_holiday">
<bpmndi:BPMNPlane bpmnElement="holiday" id="BPMNPlane_holiday">
<bpmndi:BPMNShape id="shape-d078e42c-b1e3-4fa1-86fe-6c8f21f5e62e" bpmnElement="sid-f8852670-b815-4f97-84b0-eb11d34d9334">
<omgdc:Bounds x="-161.5" y="-32.265995" width="30.0" height="30.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape-8f198408-3f86-45b6-ab85-4bcf104a9786" bpmnElement="sid-a6f78e45-6624-4996-869d-ae616b2b78e4">
<omgdc:Bounds x="64.696" y="-57.265995" width="100.0" height="80.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape-6006d1ea-5233-4f69-a21d-c42fb50492aa" bpmnElement="sid-f4101616-870b-45f6-b710-22978eb27828">
<omgdc:Bounds x="-93.65202" y="-57.266" width="100.0" height="80.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="edge-a4f60f49-040d-4cae-82db-3502dd77a1ab" bpmnElement="sid-92f3fd0d-a6ed-45cc-ae12-71adb0d0060b">
<omgdi:waypoint x="-131.5" y="-17.265995"/>
<omgdi:waypoint x="-93.65202" y="-17.265999"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="edge-4b34fd90-434d-491d-b1cc-e10431bad198" bpmnElement="sid-14fabbf8-263a-4b6b-a8b2-60c494ec52ae">
<omgdi:waypoint x="6.3479767" y="-17.265999"/>
<omgdi:waypoint x="64.696" y="-17.265995"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="shape-bdb837a7-defc-466a-bfd5-c89d3fac4951" bpmnElement="sid-b9011d2c-1871-49d2-82bb-b521dbd9dfeb">
<omgdc:Bounds x="218.34798" y="-32.265995" width="30.0" height="30.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="edge-af623160-12e5-40f9-aed5-ee1d597367f3" bpmnElement="sid-6aa8c217-001a-43a3-a28b-509edc0100a2">
<omgdi:waypoint x="164.696" y="-17.265995"/>
<omgdi:waypoint x="218.34798" y="-17.265995"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>