Activiti 工作流会签开发设计思路
在流程业务管理中,任务是通常都是由一个人去处理的,而多个人同时处理一个任务,这种任务我们称之为会签任务。这种业务需求也很常见,如一个请款单,领导审批环节中,就需要多个部门领导签字。在流程业务中,我们可以把每个领导签字的环节都定义为任务,但若这样,这个流程业务有一点是固定的,就是签批人是固定的。而任务是由一个领导签完再到另一领导,当然也可以由多个领导同时签字。
传统的用流程业务来解决可以采用以下的做法:
串行会签
并行会签
前者在流程业务中,叫串行会签,也即是由一个领导签完再至另一领导签。后者我们称之为并行会签,表示几个领导同时进行签发,而不清楚最终是谁先签。
以上的解决方式有两大业务需求下是不能满足的,若会签的领导不是固定的,即可以由上一任务审批人提交前随意进行选择,另一种是对于会签业务中,要求若其中一部分领导审批通过,即直接往下走,不需要全部领导进行审批。另外,对于这种情况下,统计最终领导会签的结果也是比较困难的,即对审批单的意见是同意还是否决没有办法清楚。以上两种业务需求也是很常见的日常需求,但我们若采用了固定的流程节点,则不能实现。在这里,可以采用Activiti的节点多实例来处理,以上流程则可以简化为下:
何谓多任务实例节点?在Activiti5上的解析则为动态的多任务节点,可以根据传入的动态人员数进行动态生成任务。生成的任务数则不固定,可以进行并行会签,也可以进行串行会签。会签任务最终是否需要往下执行,由会签设置的规则来进行约束。如我们可以常规去设置“一票通过”、“一票否决”、“少数服务多数”等会签规则。因此,我们需要在会签节点上绑定我们的设计规则。会签规则设置界面如下:
通过会签设计规则,可以清楚最终会签人员的投票结果。其数据结构如下所示:
会签任务的定义本身已经由Activiti来实现了,但需要动态传入动态的人员数
- <userTask activiti:assignee="${assignee}" id="SignTask1" name="领导会签">
- <extensionElements>
- <activiti:taskListener class="com.hotent.platform.service.bpm.listener.TaskSignCreateListener" event="create"/>
- <activiti:taskListener class="com.hotent.platform.service.bpm.listener.TaskAssignListener" event="assignment"/>
- <activiti:taskListener class="com.hotent.platform.service.bpm.listener.TaskCompleteListener" event="complete"/>
- </extensionElements>
- <multiInstanceLoopCharacteristics activiti:elementVariable="assignee" isSequential="false" activiti:collection="${taskUserAssignService.getSignUser(execution)}">
- <completionCondition>${signComplete.isComplete(execution)}</completionCondition>
- </multiInstanceLoopCharacteristics>
- </userTask>
<userTask activiti:assignee="${assignee}" id="SignTask1" name="领导会签"> <extensionElements> <activiti:taskListener class="com.hotent.platform.service.bpm.listener.TaskSignCreateListener" event="create"/> <activiti:taskListener class="com.hotent.platform.service.bpm.listener.TaskAssignListener" event="assignment"/> <activiti:taskListener class="com.hotent.platform.service.bpm.listener.TaskCompleteListener" event="complete"/> </extensionElements> <multiInstanceLoopCharacteristics activiti:elementVariable="assignee" isSequential="false" activiti:collection="${taskUserAssignService.getSignUser(execution)}"> <completionCondition>${signComplete.isComplete(execution)}</completionCondition> </multiInstanceLoopCharacteristics> </userTask>
其中,isSequential为true则为串行会签,若为false则为并行会签,而activiti:collection可以来自我们Spring容器中的接口及方法,表示获取会签用户集合,taskUserAssignService.getSignUser(execution)。其获取会签的用户值来自两个方面,一个在界面中指定的会签人员,另一个在后台会签节点上配置的人员。
后台会签节点人员设置
任务审批面上选择下一任务会签人员
<completeCondition>为完成会签的条件signComplete.isComplete(execution),可以在这里根据我们的会签规则及目前的会签情况,决定会签是否完成。其实现如下所示:
最终实现逻辑:
- @Override
- public boolean isComplete(ActivityExecution execution) {
- logger.debug("entert the SignComplete isComplete method...");
- String nodeId=execution.getActivity().getId();
- String actInstId=execution.getProcessInstanceId();
- ProcessDefinition processDefinition=bpmService.getProcessDefinitionByProcessInanceId(actInstId);
- //取得会签设置的规则
- BpmNodeSign bpmNodeSign=bpmNodeSignService.getByDefIdAndNodeId(processDefinition.getId(), nodeId);
- //完成会签的次数
- Integer completeCounter=(Integer)execution.getVariable("nrOfCompletedInstances");
- //总循环次数
- Integer instanceOfNumbers=(Integer)execution.getVariable("nrOfInstances");
- //计算投票结果。
- VoteResult voteResult=calcResult(bpmNodeSign, actInstId, nodeId, completeCounter,instanceOfNumbers);
- String signResult=voteResult.getSignResult();
- boolean isCompleted=voteResult.getIsComplete();
- /**
- * 会签完成做的动作。
- * 1.删除会签的流程变量。
- * 2.将会签数据更新为完成。
- * 3.设置会签结果变量。
- * 4.更新会签节点结果。
- * 5.清除会签用户。
- */
- if(isCompleted){
- //删除会签的变量。
- //删除 assignee,loopCounter变量。
- bpmService.delLoopAssigneeVars(execution.getId());
- logger.debug("set the sign result + " + signResult);
- //将会签数据更新为完成。
- taskSignDataService.batchUpdateCompleted(actInstId, nodeId);
- //设置会签的结果
- execution.setVariable("signResult_" + nodeId , signResult);
- //更新会签节点的状态。
- Short status=TaskOpinion.STATUS_PASSED;
- if(signResult.equals(SIGN_RESULT_REFUSE)){
- status=TaskOpinion.STATUS_NOT_PASSED;
- }
- //更新会签节点的状态。
- bpmProStatusDao.updStatus(actInstId, nodeId,status);
- //清除会签用户。
- taskUserAssignService.clearSignUser();
- }
- return isCompleted;
- }
- **
- * 根据会签规则计算投票结果。
- * <pre>
- * 1.如果会签规则为空,那么需要所有的人同意通过会签,否则不通过。
- * 2.否则按照规则计算投票结果。
- * </pre>
- * @param bpmNodeSign 会签规则
- * @param actInstId 流程实例ID
- * @param nodeId 节点id名称
- * @param completeCounter 循环次数
- * @param instanceOfNumbers 总的会签次数。
- * @return
- */
- private VoteResult calcResult(BpmNodeSign bpmNodeSign,String actInstId,String nodeId,Integer completeCounter,Integer instanceOfNumbers){
- VoteResult voteResult=new VoteResult();
- //没有会签实例
- if(instanceOfNumbers==0){
- return voteResult;
- }
- //投同意票数
- Integer agreeVotesCounts=taskSignDataService.getAgreeVoteCount(actInstId, nodeId);
- //没有设置会签规则
- //(那么得全部会签通过才通过,否则不通过)
- if(bpmNodeSign==null){
- //还没有完成可以退出。
- if(completeCounter<instanceOfNumbers){
- return voteResult;
- }
- else{
- //完成了 (全部同意才通过)
- if(agreeVotesCounts.equals(instanceOfNumbers)){
- return new VoteResult(SIGN_RESULT_PASS,true);
- }
- else{
- return new VoteResult(SIGN_RESULT_REFUSE,true);
- }
- }
- }
- //投反对票数
- Integer refuseVotesCounts=taskSignDataService.getRefuseVoteCount(actInstId, nodeId);
- //检查投票是否完成
- if(BpmNodeSign.VOTE_TYPE_PERCENT.equals(bpmNodeSign.getVoteType())){
- float percents=0;
- //按同意票数进行决定
- if(BpmNodeSign.DECIDE_TYPE_PASS.equals(bpmNodeSign.getDecideType())){
- percents=agreeVotesCounts/instanceOfNumbers;
- //投票同意票符合条件
- if(percents>=bpmNodeSign.getVoteAmount()){
- voteResult=new VoteResult(SIGN_RESULT_PASS, true);
- }
- //投票已经全部完成
- else if(completeCounter.equals(instanceOfNumbers)){
- voteResult=new VoteResult(SIGN_RESULT_REFUSE, true);
- }
- }
- //按反对票数进行决定
- else{
- percents=refuseVotesCounts/instanceOfNumbers;
- //投票
- if(percents>=bpmNodeSign.getVoteAmount()){
- voteResult=new VoteResult(SIGN_RESULT_REFUSE, true);
- }
- //投票已经全部完成
- else if(completeCounter.equals(instanceOfNumbers)){
- voteResult=new VoteResult(SIGN_RESULT_PASS, true);
- }
- }
- }
- //按绝对票数投票
- else{
- //按同意票数进行决定
- if(BpmNodeSign.DECIDE_TYPE_PASS.equals(bpmNodeSign.getDecideType())){
- //投票同意票符合条件
- if(agreeVotesCounts>=bpmNodeSign.getVoteAmount()){
- voteResult=new VoteResult(SIGN_RESULT_PASS, true);
- }
- //投票已经全部完成
- else if(completeCounter.equals(instanceOfNumbers)){
- voteResult=new VoteResult(SIGN_RESULT_REFUSE, true);
- }
- }
- //按反对票数进行决定
- else{
- //投票
- if(refuseVotesCounts>=bpmNodeSign.getVoteAmount()){
- voteResult=new VoteResult(SIGN_RESULT_REFUSE, true);
- }
- //投票已经全部完成
- else if(completeCounter.equals(instanceOfNumbers)){
- voteResult=new VoteResult(SIGN_RESULT_PASS, true);
- }
- }
- }
- return voteResult;
- }
@Override public boolean isComplete(ActivityExecution execution) { logger.debug("entert the SignComplete isComplete method..."); String nodeId=execution.getActivity().getId(); String actInstId=execution.getProcessInstanceId(); ProcessDefinition processDefinition=bpmService.getProcessDefinitionByProcessInanceId(actInstId); //取得会签设置的规则 BpmNodeSign bpmNodeSign=bpmNodeSignService.getByDefIdAndNodeId(processDefinition.getId(), nodeId); //完成会签的次数 Integer completeCounter=(Integer)execution.getVariable("nrOfCompletedInstances"); //总循环次数 Integer instanceOfNumbers=(Integer)execution.getVariable("nrOfInstances"); //计算投票结果。 VoteResult voteResult=calcResult(bpmNodeSign, actInstId, nodeId, completeCounter,instanceOfNumbers); String signResult=voteResult.getSignResult(); boolean isCompleted=voteResult.getIsComplete(); /** * 会签完成做的动作。 * 1.删除会签的流程变量。 * 2.将会签数据更新为完成。 * 3.设置会签结果变量。 * 4.更新会签节点结果。 * 5.清除会签用户。 */ if(isCompleted){ //删除会签的变量。 //删除 assignee,loopCounter变量。 bpmService.delLoopAssigneeVars(execution.getId()); logger.debug("set the sign result + " + signResult); //将会签数据更新为完成。 taskSignDataService.batchUpdateCompleted(actInstId, nodeId); //设置会签的结果 execution.setVariable("signResult_" + nodeId , signResult); //更新会签节点的状态。 Short status=TaskOpinion.STATUS_PASSED; if(signResult.equals(SIGN_RESULT_REFUSE)){ status=TaskOpinion.STATUS_NOT_PASSED; } //更新会签节点的状态。 bpmProStatusDao.updStatus(actInstId, nodeId,status); //清除会签用户。 taskUserAssignService.clearSignUser(); } return isCompleted; } /** * 根据会签规则计算投票结果。 * <pre> * 1.如果会签规则为空,那么需要所有的人同意通过会签,否则不通过。 * 2.否则按照规则计算投票结果。 * </pre> * @param bpmNodeSign 会签规则 * @param actInstId 流程实例ID * @param nodeId 节点id名称 * @param completeCounter 循环次数 * @param instanceOfNumbers 总的会签次数。 * @return */ private VoteResult calcResult(BpmNodeSign bpmNodeSign,String actInstId,String nodeId,Integer completeCounter,Integer instanceOfNumbers){ VoteResult voteResult=new VoteResult(); //没有会签实例 if(instanceOfNumbers==0){ return voteResult; } //投同意票数 Integer agreeVotesCounts=taskSignDataService.getAgreeVoteCount(actInstId, nodeId); //没有设置会签规则 //(那么得全部会签通过才通过,否则不通过) if(bpmNodeSign==null){ //还没有完成可以退出。 if(completeCounter<instanceOfNumbers){ return voteResult; } else{ //完成了 (全部同意才通过) if(agreeVotesCounts.equals(instanceOfNumbers)){ return new VoteResult(SIGN_RESULT_PASS,true); } else{ return new VoteResult(SIGN_RESULT_REFUSE,true); } } } //投反对票数 Integer refuseVotesCounts=taskSignDataService.getRefuseVoteCount(actInstId, nodeId); //检查投票是否完成 if(BpmNodeSign.VOTE_TYPE_PERCENT.equals(bpmNodeSign.getVoteType())){ float percents=0; //按同意票数进行决定 if(BpmNodeSign.DECIDE_TYPE_PASS.equals(bpmNodeSign.getDecideType())){ percents=agreeVotesCounts/instanceOfNumbers; //投票同意票符合条件 if(percents>=bpmNodeSign.getVoteAmount()){ voteResult=new VoteResult(SIGN_RESULT_PASS, true); } //投票已经全部完成 else if(completeCounter.equals(instanceOfNumbers)){ voteResult=new VoteResult(SIGN_RESULT_REFUSE, true); } } //按反对票数进行决定 else{ percents=refuseVotesCounts/instanceOfNumbers; //投票 if(percents>=bpmNodeSign.getVoteAmount()){ voteResult=new VoteResult(SIGN_RESULT_REFUSE, true); } //投票已经全部完成 else if(completeCounter.equals(instanceOfNumbers)){ voteResult=new VoteResult(SIGN_RESULT_PASS, true); } } } //按绝对票数投票 else{ //按同意票数进行决定 if(BpmNodeSign.DECIDE_TYPE_PASS.equals(bpmNodeSign.getDecideType())){ //投票同意票符合条件 if(agreeVotesCounts>=bpmNodeSign.getVoteAmount()){ voteResult=new VoteResult(SIGN_RESULT_PASS, true); } //投票已经全部完成 else if(completeCounter.equals(instanceOfNumbers)){ voteResult=new VoteResult(SIGN_RESULT_REFUSE, true); } } //按反对票数进行决定 else{ //投票 if(refuseVotesCounts>=bpmNodeSign.getVoteAmount()){ voteResult=new VoteResult(SIGN_RESULT_REFUSE, true); } //投票已经全部完成 else if(completeCounter.equals(instanceOfNumbers)){ voteResult=new VoteResult(SIGN_RESULT_PASS, true); } } } return voteResult; }
最终实现效果,可以在线访问
csx/1
可以通过访问流程管理体验效果
最终展示视频可以看以下链接:
发表评论
-
前后端分离+微服务架构的BPM快速开发平台
2019-10-30 19:04 6581 概述 EIP(Enterprise Inf ... -
基于开源流程引擎Activiti5的工作流开发平台 BPMX3
2012-07-26 14:35 4178BPMX3平台是宏天软件在ESTBPM2的基础上,追随开源工作 ... -
基于开源流程引擎Activiti5的工作流开发平台BPM X3
2012-06-11 09:17 13BPMX3平台是宏天软件在ESTBPM2的基础上,追随开源工作 ... -
BPM X3--activiti 5在线流程设计器开发
2012-06-11 09:12 7jbpm4的开发成员tom离开 ... -
宏天J.Office 性能优化--EXTJS按模板下载js
2011-12-19 18:05 1436宏天对EXTJS的性能调整: 1.打开Tomcat或Appa ... -
J.Office中的公文签名及签章
2011-08-12 13:58 1716政府的很多系统都有涉及到电子签名及签章的管理功能,在jof ... -
JOffice2中WebService的使用(CXF)
2011-08-12 13:54 15641. WebService基本概念 WSDL: ... -
JOffice2 发布了开源的开发者体验版本
2011-08-12 13:48 1118JOffice的爱好者有福音了,经公司决定,现在 ... -
关于 JOffice 的业务表单与流程的整合问题
2011-08-01 17:05 1569关于 JOffice 的业务表单 ... -
JBPM4的子流程与父流程的设计及开发
2011-07-14 12:02 1427【JBPM4的子流程与父流 ... -
JOffice的EXT性能优化方法
2011-07-11 10:39 1630JOffice由于用了Ext,所以在客户端的性能表现总是平平, ... -
代码生成器EST-BPM
2011-05-30 14:30 1770一、代码加速器的介绍 代码加速器是基于Velo ... -
Jbpm4中的会签设计及实现
2011-05-12 14:44 1760jbpm4.4提供了三种比较方便的分支跳转方式,如下所示: ... -
宏天工作流平台Jbpm4中的会签设计及实现
2011-05-12 12:11 2140会签任务是工作流里一个比较觉见的任务方式,意思是一个处理任务需 ... -
选用ibatis和hibernate的区别
2011-05-05 09:22 814选用ibatis和hibernate的区别 http://w ... -
JOffice2升级智能化表单设计及可视化流程设计(JBPM4.4) 100%开放源代码
2011-03-23 15:54 1003JOffice2升级智能化表单 ...
相关推荐
在用activiti的时候经常遇到取会签人员的问题,这个文档解决怎么获取会签人员。
Activiti 是一个开源的工作流和业务自动化引擎,广泛应用于企业级流程管理。在这个主题中,"activiti 会签投票统计" 涉及到 Activiti 的特定功能,特别是会签(Parallel Multi-instance)和自定义事件监听器,用于...
activiti工作流文档,超详细,从0基础开始入门,包括数据库介绍、核心api等介绍,满足日常开发所需
Activiti工作流引擎是一款开源的企业级业务流程管理(BPM)和工作流系统,它为组织提供了一种灵活、可扩展的方式来设计、执行和管理业务流程。在面试中,了解Activiti的核心服务对于理解其工作原理和实际应用至关...
在这个“Activiti工作流整合Web流程设计器整合”主题中,我们将深入探讨如何将Activiti与Web流程设计器集成,以实现直观、高效的流程设计和管理。 首先,我们要理解什么是Activiti。Activiti是由Alfresco开发的一款...
Activiti工作流课程Activiti工作流课程Activiti工作流课程Activiti工作流课程Activiti工作流课程Activiti工作流课程
在 Activiti-5.4 版本中,会签(Concurrent Signatures)是流程设计中的一个重要特性,允许多个参与者同时对同一任务进行处理,提高了工作效率。下面我们将详细探讨如何在Activiti-5.4中实现会签以及相关的技术细节...
Activiti是一款开源的工作流引擎,它基于模型驱动的架构(MDA),专为现代企业应用程序设计,用于处理业务流程自动化。这个"Activiti工作流示例Activiti Demo"提供了完整的源代码,帮助开发者深入理解并实际操作...
### Activiti工作流知识点概述 #### 一、工作流概念及其执行过程 1. **工作流定义**: - 工作流是指“业务过程的部分或整体在计算机应用环境下的自动化”。具体而言,它旨在通过预定义的规则来自动处理文档、信息...
Activiti工作流是一款开源的工作流程管理系统,主要用于企业的业务流程自动化。它基于模型驱动的设计理念,提供了丰富的API和图形化设计工具,使得开发者可以方便地创建、部署和管理工作流程。本操作手册旨在帮助...
Activiti工作流引擎是Java平台上的一个开源工作流管理系统,专为简化业务流程自动化而设计。它使用BPMN(Business Process Model and Notation)2.0标准进行流程建模,使得非技术人员也能理解并创建复杂的业务流程。...
传智播客_Activiti工作流视频(企业开发实例讲解)传智播客_Activiti工作流视频(企业开发实例讲解)传智播客_Activiti工作流视频(企业开发实例讲解)
【标题】"activiti工作流项目"是一个基于Java技术栈实现的工作流管理系统示例,它集成了SpringMVC、Hibernate和Activiti等关键组件。这个项目旨在演示如何在实际应用中利用Activiti来构建动态表单和处理各种流程审批...
Activiti工作流引擎简介 1.俯瞰Activiti 2.Activiti开发之旅 3.Why Activiti? 4.Activiti的现状与未来
### 前后端分离项目中引入Activiti工作流引擎 #### 一、概述 在当前的软件开发中,前后端分离已经成为了一种常见的架构模式。这种模式将前端的用户界面与后端的数据处理逻辑分开,提高了开发效率,同时也使得系统...
Activiti作为一个工作流引擎,允许开发者通过编程或使用图形化工具定义、执行和管理这些流程。 在Activiti中,流程定义是用BPMN 2.0(Business Process Model and Notation)语言编写的,这是一种国际标准,用于...
Activiti工作流中文说明文档 Activiti是一个基于Apache V2协议发布的开源工作流引擎,旨在帮助开发者快速构建业务流程管理系统。本文档将对Activiti的安装、配置、使用等方面进行详细介绍,以帮助开发者快速上手...
通过这个"activiti工作流案例",你可以动手操作,实践每个环节,从流程设计、部署到执行,从而更好地理解和掌握Activiti工作流引擎的使用。同时,这也有助于你深入理解BPMN 2.0标准和业务流程自动化的核心概念。在...
【标题】"Activiti多实例任务实现会签"是指在Activiti工作流引擎中,如何配置和使用多实例任务来实现会签功能。在企业级应用中,会签常常用于决策过程,要求多个参与者共同审批,只有当所有参与者都完成审批后,流程...