僞彙總審批,就是每一條流程都是獨立的,這些獨立的流程在走到某個節點的時候,這個節點的審批人可以一次性進行多個任務的審批。
開發環境
JDK1.6
Activiti5.13
Eclipse
MYSQL5
簡單起見,這裏沒有做一個web的項目,只是一個Java程序。
業務場景
預算填報員填寫本單位的預算,預算提交到本單位的上級進行審批,上級審批後提交到總公司進行審批。
有多少個預算到了總公司審批人處,就可以對多少的預算同時進行審批,這些流程都是相對獨立的。
業務數據存儲在單獨的報表系統中,節點可以配置打開報表的方式,表單ID,及節點是否彙總審批。
程序模擬
爲方便起見
1)所有單位的預算員,審批人,彙總審批人都用三個人,kermit, fozzie,admin直接配在流程圖中,實際上kermit和fozzie應會是不同的人,可以動態傳入流程啓動流程
2)節點是否需要彙總,可以根據在節點的參數isSum來進行動態的判定,是否執行彙總審批,程序只是展示效果,具體沒有實現動態的,實現起來並不困難。
3)爲了直觀,節點參數都使用了中文,實際開發中肯定是編碼形式
流程參數說明:
流程實例級別的參數有兩個,一個填報期間period一個填報單位fillAccount
節點級別的配置參數有四個,三個固定的報表唯一編碼sheetId,報表打開方式fillType和是否彙總isSum,一個在流程實例中動態生成的,當前節點的操作單位accountCode
1. 繪製流程圖
![]()
總體配置
填寫預算配置
![]()
![]()
審批預算配置
![]()
![]()
彙總審批預算配置
2. 測試程序
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.FormService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.task.Task;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestFormData {
/**
* @param args
*/
public static void main(String[] args) {
// 加載spring配置
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
RuntimeService runtimeService = (RuntimeService) ctx
.getBean("runtimeService");
ProcessEngine processEngine = (ProcessEngine) ctx
.getBean("processEngine");
FormService formService = (FormService) ctx.getBean("formService");
TaskService taskService = (TaskService) ctx.getBean("taskService");
// 發佈流程
RepositoryService repositoryService = processEngine
.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("diagrams/formDataTest.bpmn").deploy();
fill(runtimeService, formService, taskService);
singleCheck(formService, taskService);
sum(taskService, formService);
}
/**
* 填報預算
*
* @param runtimeService
* @param formService
* @param taskService
*/
private static void fill(RuntimeService runtimeService,
FormService formService, TaskService taskService) {
// 流程開始參數,設置填報期間
Map<String, Object> p = new HashMap<String, Object>();
p.put("period", "2013-07");
// 生成3家單位填報
for (int i = 0; i < 3; i++) {
// 開始流程
runtimeService.startProcessInstanceByKey("formDataTest", p);
System.out
.println("=====================kermit開始填報=======================");
// query kermit's tasks;
List<Task> tasks = taskService.createTaskQuery()
.taskAssignee("kermit").list();
for (Task task : tasks) {
if ("fill".equals(task.getTaskDefinitionKey())) {
// 設置填報人單位編碼記錄在節點
taskService.setVariableLocal(task.getId(), "accoutCode",
"A110" + i);
// 設置該流程實例的填報單位
taskService.setVariable(task.getId(), "fillAccount", "A110"
+ i);
Map<String, FormProperty> propMap = createMap(formService
.getTaskFormData(task.getId()).getFormProperties());
// 獲取節點報表打開類型
String fillType = (String) propMap.get("fillType")
.getValue();
// 獲取節點報表表單ID
String sheetId = (String) propMap.get("sheetId").getValue();
// 獲取節點是否需要彙總參數
String isSum = (String) propMap.get("isSum").getValue();
// 獲取節點填報單位編碼
String accoutCode = (String) taskService.getVariableLocal(
task.getId(), "accoutCode");
// 獲取流程填報單位編碼
String fillAccount = (String) taskService.getVariable(
task.getId(), "fillAccount");
// 獲取流程填報期間
String period = (String) taskService.getVariable(
task.getId(), "period");
// 打印填報信息
System.out.println("\t打開報表類型:" + fillType);
System.out.println("\t填報表單:" + sheetId);
System.out.println("\t填報期間:" + period);
System.out.println("\t是否彙總:" + isSum);
System.out.println("\t當前節點賬號:" + accoutCode);
System.out.println("\t提交審批表單填報單位:" + fillAccount);
// 節點任務結束
taskService.complete(task.getId());
System.out
.println("=============kermit填寫預算單任務已完成=====================");
System.out.println();
}
}
}
}
/**
* 單個審覈
*
* @param formService
* @param taskService
*/
private static void singleCheck(FormService formService,
TaskService taskService) {
System.out
.println("=====================fozzie開始單個審覈=======================");
// query fozzie's tasks;
List<Task> tasks2 = taskService.createTaskQuery()
.taskAssignee("fozzie")
.processVariableValueEquals("period", "2013-07")
.processDefinitionKey("formDataTest").list();
int count = 1;
for (Task task : tasks2) {
if ("check".equals(task.getTaskDefinitionKey())) {
System.out.println("\t審覈第" + count + "個");
// 設置節點審批人單位編碼
taskService.setVariableLocal(task.getId(), "accoutCode",
"A1199");
Map<String, FormProperty> propMap = createMap(formService
.getTaskFormData(task.getId()).getFormProperties());
// 獲取節點報表打開類型
String fillType = (String) propMap.get("fillType").getValue();
// 獲取節點報表表單ID
String sheetId = (String) propMap.get("sheetId").getValue();
// 獲取節點是否需要彙總參數
String isSum = (String) propMap.get("isSum").getValue();
// 獲取節點填報單位編碼
String accoutCode = (String) taskService.getVariableLocal(
task.getId(), "accoutCode");
// 獲取流程填報單位編碼
String fillAccount = (String) taskService.getVariable(
task.getId(), "fillAccount");
// 獲取流程填報期間
String period = (String) taskService.getVariable(task.getId(),
"period");
// 打印填報信息
System.out.println("\t報表打開類型:" + fillType);
System.out.println("\t填報表單:" + sheetId);
System.out.println("\t填報期間:" + period);
System.out.println("\t是否彙總:" + isSum);
System.out.println("\t當前節點賬號:" + accoutCode);
System.out.println("\t提交審批表單填報單位:" + fillAccount);
// 節點任務結束
taskService.complete(task.getId());
System.out.println("\t審覈第" + count + "個完成");
System.out.println();
count++;
}
}
System.out
.println("===================fozzie審批預算單任務已完成===================");
System.out.println();
}
/**
* 彙總審覈
*
* @param taskService
* @param formService
*/
private static void sum(TaskService taskService, FormService formService) {
System.out
.println("=======================admin開始彙總審覈=====================");
List<Task> tasks3 = taskService.createTaskQuery()
.taskAssignee("admin")
.processVariableValueEquals("period", "2013-07")
.processDefinitionKey("formDataTest").list();
// 批量審批列表
List<String> completeTaskIdList = new ArrayList<String>();
// 獲取節點報表打開類型
String fillType = "";
// 獲取節點報表表單ID
String sheetId = "";
// 獲取節點是否需要彙總參數
String isSum = "";
// 獲取流程填報期間
String period = "";
for (Task task : tasks3) {
if ("sum".equals(task.getTaskDefinitionKey())) {
// 設置節點審批人單位編碼
taskService.setVariableLocal(task.getId(), "accoutCode",
"A1199");
// 獲取流程填報單位編碼
String fillAccount = (String) taskService.getVariable(
task.getId(), "fillAccount");
Map<String, FormProperty> propMap = createMap(formService
.getTaskFormData(task.getId()).getFormProperties());
// 獲取節點報表打開類型
fillType = (String) propMap.get("fillType").getValue();
// 獲取節點報表表單ID
sheetId = (String) propMap.get("sheetId").getValue();
// 獲取節點是否需要彙總參數
isSum = (String) propMap.get("isSum").getValue();
// 獲取流程填報期間
period = (String) taskService.getVariable(task.getId(),
"period");
// 打印填報信息
System.out.println("\t提交匯總審批表單填報單位:" + fillAccount);
// 加入批量審批列表
completeTaskIdList.add(task.getId());
}
}
System.out.println("\t報表打開類型:" + fillType);
System.out.println("\t填報表單:" + sheetId);
System.out.println("\t填報期間:" + period);
System.out.println("\t是否彙總:" + isSum);
System.out.println("\t全部審批通過");
for (String t : completeTaskIdList) {
taskService.complete(t);
}
System.out.println("=========admin彙總預算單任務已完成,彙總審批"
+ completeTaskIdList.size() + "個單位=======");
}
private static Map<String, FormProperty> createMap(List<FormProperty> props) {
Map<String, FormProperty> re = new HashMap<String, FormProperty>();
for (FormProperty p : props) {
re.put(p.getId(), p);
}
return re;
}
}
3. 運行結果
=====================kermit開始填報=======================
打開報表類型:普通填報
填報表單:1
填報期間:2013-07
是否彙總:不彙總
當前節點賬號:A1100
提交審批表單填報單位:A1100
=============kermit填寫預算單任務已完成=====================
=====================kermit開始填報=======================
打開報表類型:普通填報
填報表單:1
填報期間:2013-07
是否彙總:不彙總
當前節點賬號:A1101
提交審批表單填報單位:A1101
=============kermit填寫預算單任務已完成=====================
=====================kermit開始填報=======================
打開報表類型:普通填報
填報表單:1
填報期間:2013-07
是否彙總:不彙總
當前節點賬號:A1102
提交審批表單填報單位:A1102
=============kermit填寫預算單任務已完成=====================
=====================fozzie開始單個審覈=======================
審覈第1個
報表打開類型:普通打開
填報表單:2
填報期間:2013-07
是否彙總:不彙總
當前節點賬號:A1199
提交審批表單填報單位:A1100
審覈第1個完成
審覈第2個
報表打開類型:普通打開
填報表單:2
填報期間:2013-07
是否彙總:不彙總
當前節點賬號:A1199
提交審批表單填報單位:A1101
審覈第2個完成
審覈第3個
報表打開類型:普通打開
填報表單:2
填報期間:2013-07
是否彙總:不彙總
當前節點賬號:A1199
提交審批表單填報單位:A1102
審覈第3個完成
===================fozzie審批預算單任務已完成===================
=======================admin開始彙總審覈=====================
提交匯總審批表單填報單位:A1100
提交匯總審批表單填報單位:A1101
提交匯總審批表單填報單位:A1102
報表打開類型:彙總到一張表打開
填報表單:3
填報期間:2013-07
是否彙總:彙總
全部審批通過
=========admin彙總預算單任務已完成,彙總審批3個單位=======
附applicationContext.xml,數據庫使用MYSQL5
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/test_activiti" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Activiti begin -->
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="jobExecutorActivate" value="false" />
<property name="history" value="full" />
<property name="processDefinitionCacheLimit" value="10" />
</bean>
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<bean id="repositoryService" factory-bean="processEngine"
factory-method="getRepositoryService" />
<bean id="runtimeService" factory-bean="processEngine"
factory-method="getRuntimeService" />
<bean id="formService" factory-bean="processEngine"
factory-method="getFormService" />
<bean id="identityService" factory-bean="processEngine"
factory-method="getIdentityService" />
<bean id="taskService" factory-bean="processEngine"
factory-method="getTaskService" />
<bean id="historyService" factory-bean="processEngine"
factory-method="getHistoryService" />
<bean id="managementService" factory-bean="processEngine"
factory-method="getManagementService" />
<!-- Activiti end -->
</beans>
項目引用jar包就是activiti-explorer裏用的所有jar包+mysql的驅動
END