`
fyjjack
  • 浏览: 33747 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Activiti 工作流会签开发设计思路

阅读更多

Activiti 工作流会签开发设计思路

 

在流程业务管理中,任务是通常都是由一个人去处理的,而多个人同时处理一个任务,这种任务我们称之为会签任务。这种业务需求也很常见,如一个请款单,领导审批环节中,就需要多个部门领导签字。在流程业务中,我们可以把每个领导签字的环节都定义为任务,但若这样,这个流程业务有一点是固定的,就是签批人是固定的。而任务是由一个领导签完再到另一领导,当然也可以由多个领导同时签字。

传统的用流程业务来解决可以采用以下的做法:


串行会签
串行会签

并行会签


 

前者在流程业务中,叫串行会签,也即是由一个领导签完再至另一领导签。后者我们称之为并行会签,表示几个领导同时进行签发,而不清楚最终是谁先签。


以上的解决方式有两大业务需求下是不能满足的,若会签的领导不是固定的,即可以由上一任务审批人提交前随意进行选择,另一种是对于会签业务中,要求若其中一部分领导审批通过,即直接往下走,不需要全部领导进行审批。另外,对于这种情况下,统计最终领导会签的结果也是比较困难的,即对审批单的意见是同意还是否决没有办法清楚。以上两种业务需求也是很常见的日常需求,但我们若采用了固定的流程节点,则不能实现。在这里,可以采用Activiti的节点多实例来处理,以上流程则可以简化为下:


activiti会签流程设计

何谓多任务实例节点?在Activiti5上的解析则为动态的多任务节点,可以根据传入的动态人员数进行动态生成任务。生成的任务数则不固定,可以进行并行会签,也可以进行串行会签。会签任务最终是否需要往下执行,由会签设置的规则来进行约束。如我们可以常规去设置“一票通过”、“一票否决”、“少数服务多数”等会签规则。因此,我们需要在会签节点上绑定我们的设计规则。会签规则设置界面如下:

会签规则设计

通过会签设计规则,可以清楚最终会签人员的投票结果。其数据结构如下所示:
会签规则表

会签任务的定义本身已经由Activiti来实现了,但需要动态传入动态的人员数

Java代码 复制代码 收藏代码
  1. <userTask activiti:assignee="${assignee}" id="SignTask1" name="领导会签">   
  2. <extensionElements>   
  3. <activiti:taskListener class="com.hotent.platform.service.bpm.listener.TaskSignCreateListener" event="create"/>   
  4. <activiti:taskListener class="com.hotent.platform.service.bpm.listener.TaskAssignListener" event="assignment"/>   
  5. <activiti:taskListener class="com.hotent.platform.service.bpm.listener.TaskCompleteListener" event="complete"/>   
  6. </extensionElements>   
  7. <multiInstanceLoopCharacteristics activiti:elementVariable="assignee" isSequential="false" activiti:collection="${taskUserAssignService.getSignUser(execution)}">   
  8. <completionCondition>${signComplete.isComplete(execution)}</completionCondition>   
  9. </multiInstanceLoopCharacteristics>   
  10. </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)。其获取会签的用户值来自两个方面,一个在界面中指定的会签人员,另一个在后台会签节点上配置的人员。

会签人员设置
后台会签节点人员设置

会签人员设置2
任务审批面上选择下一任务会签人员

<completeCondition>为完成会签的条件signComplete.isComplete(execution),可以在这里根据我们的会签规则及目前的会签情况,决定会签是否完成。其实现如下所示:

最终实现逻辑:
Java代码 复制代码 收藏代码
  1. @Override  
  2. public boolean isComplete(ActivityExecution execution) {   
  3.        
  4.     logger.debug("entert the SignComplete isComplete method...");   
  5.        
  6.     String nodeId=execution.getActivity().getId();   
  7.     String actInstId=execution.getProcessInstanceId();   
  8.        
  9.     ProcessDefinition processDefinition=bpmService.getProcessDefinitionByProcessInanceId(actInstId);   
  10.     //取得会签设置的规则   
  11.     BpmNodeSign bpmNodeSign=bpmNodeSignService.getByDefIdAndNodeId(processDefinition.getId(), nodeId);   
  12.     //完成会签的次数   
  13.     Integer completeCounter=(Integer)execution.getVariable("nrOfCompletedInstances");   
  14.     //总循环次数   
  15.     Integer instanceOfNumbers=(Integer)execution.getVariable("nrOfInstances");   
  16.     //计算投票结果。   
  17.     VoteResult voteResult=calcResult(bpmNodeSign, actInstId, nodeId, completeCounter,instanceOfNumbers);   
  18.        
  19.     String signResult=voteResult.getSignResult();   
  20.     boolean isCompleted=voteResult.getIsComplete();   
  21.        
  22.     /**  
  23.     * 会签完成做的动作。  
  24.     * 1.删除会签的流程变量。  
  25.     * 2.将会签数据更新为完成。  
  26.     * 3.设置会签结果变量。  
  27.     * 4.更新会签节点结果。  
  28.     * 5.清除会签用户。  
  29.     */  
  30.     if(isCompleted){   
  31.         //删除会签的变量。   
  32.         //删除 assignee,loopCounter变量。   
  33.         bpmService.delLoopAssigneeVars(execution.getId());   
  34.         logger.debug("set the sign result + " + signResult);   
  35.         //将会签数据更新为完成。   
  36.         taskSignDataService.batchUpdateCompleted(actInstId, nodeId);   
  37.         //设置会签的结果   
  38.         execution.setVariable("signResult_" + nodeId , signResult);   
  39.         //更新会签节点的状态。   
  40.         Short status=TaskOpinion.STATUS_PASSED;   
  41.         if(signResult.equals(SIGN_RESULT_REFUSE)){   
  42.             status=TaskOpinion.STATUS_NOT_PASSED;   
  43.         }   
  44.         //更新会签节点的状态。   
  45.         bpmProStatusDao.updStatus(actInstId, nodeId,status);   
  46.         //清除会签用户。   
  47.         taskUserAssignService.clearSignUser();   
  48.     }   
  49.        
  50.     return isCompleted;   
  51. }   
  52.   
  53. **   
  54.  * 根据会签规则计算投票结果。   
  55.  * <pre>   
  56.  * 1.如果会签规则为空,那么需要所有的人同意通过会签,否则不通过。   
  57.  * 2.否则按照规则计算投票结果。   
  58.  * </pre>   
  59.  * @param bpmNodeSign       会签规则   
  60.  * @param actInstId         流程实例ID   
  61.  * @param nodeId            节点id名称   
  62.  * @param completeCounter       循环次数   
  63.  * @param instanceOfNumbers     总的会签次数。   
  64.  * @return  
  65.  */   
  66. private VoteResult calcResult(BpmNodeSign bpmNodeSign,String actInstId,String nodeId,Integer completeCounter,Integer instanceOfNumbers){   
  67.     VoteResult voteResult=new VoteResult();   
  68.     //没有会签实例   
  69.     if(instanceOfNumbers==0){   
  70.         return voteResult;   
  71.     }   
  72.     //投同意票数   
  73.     Integer agreeVotesCounts=taskSignDataService.getAgreeVoteCount(actInstId, nodeId);   
  74.     //没有设置会签规则   
  75.     //(那么得全部会签通过才通过,否则不通过)   
  76.     if(bpmNodeSign==null){   
  77.         //还没有完成可以退出。   
  78.         if(completeCounter<instanceOfNumbers){   
  79.             return voteResult;   
  80.         }   
  81.         else{   
  82.             //完成了 (全部同意才通过)   
  83.             if(agreeVotesCounts.equals(instanceOfNumbers)){   
  84.                 return new VoteResult(SIGN_RESULT_PASS,true);   
  85.             }   
  86.             else{   
  87.                 return new VoteResult(SIGN_RESULT_REFUSE,true);   
  88.             }   
  89.         }   
  90.     }   
  91.        
  92.     //投反对票数   
  93.     Integer refuseVotesCounts=taskSignDataService.getRefuseVoteCount(actInstId, nodeId);   
  94.        
  95.     //检查投票是否完成   
  96.     if(BpmNodeSign.VOTE_TYPE_PERCENT.equals(bpmNodeSign.getVoteType())){   
  97.         float percents=0;   
  98.         //按同意票数进行决定   
  99.         if(BpmNodeSign.DECIDE_TYPE_PASS.equals(bpmNodeSign.getDecideType())){   
  100.             percents=agreeVotesCounts/instanceOfNumbers;   
  101.             //投票同意票符合条件   
  102.             if(percents>=bpmNodeSign.getVoteAmount()){   
  103.                 voteResult=new VoteResult(SIGN_RESULT_PASS, true);   
  104.             }   
  105.             //投票已经全部完成   
  106.             else if(completeCounter.equals(instanceOfNumbers)){   
  107.                 voteResult=new VoteResult(SIGN_RESULT_REFUSE, true);   
  108.             }   
  109.         }   
  110.         //按反对票数进行决定   
  111.         else{   
  112.             percents=refuseVotesCounts/instanceOfNumbers;   
  113.             //投票   
  114.             if(percents>=bpmNodeSign.getVoteAmount()){   
  115.                 voteResult=new VoteResult(SIGN_RESULT_REFUSE, true);   
  116.             }   
  117.             //投票已经全部完成   
  118.             else if(completeCounter.equals(instanceOfNumbers)){   
  119.                 voteResult=new VoteResult(SIGN_RESULT_PASS, true);   
  120.             }   
  121.         }   
  122.     }   
  123.     //按绝对票数投票   
  124.     else{   
  125.         //按同意票数进行决定   
  126.         if(BpmNodeSign.DECIDE_TYPE_PASS.equals(bpmNodeSign.getDecideType())){   
  127.             //投票同意票符合条件   
  128.             if(agreeVotesCounts>=bpmNodeSign.getVoteAmount()){   
  129.                 voteResult=new VoteResult(SIGN_RESULT_PASS, true);   
  130.             }   
  131.             //投票已经全部完成   
  132.             else if(completeCounter.equals(instanceOfNumbers)){   
  133.                 voteResult=new VoteResult(SIGN_RESULT_REFUSE, true);   
  134.             }   
  135.         }   
  136.         //按反对票数进行决定   
  137.         else{   
  138.             //投票   
  139.             if(refuseVotesCounts>=bpmNodeSign.getVoteAmount()){   
  140.                 voteResult=new VoteResult(SIGN_RESULT_REFUSE, true);   
  141.             }   
  142.             //投票已经全部完成   
  143.             else if(completeCounter.equals(instanceOfNumbers)){   
  144.                 voteResult=new VoteResult(SIGN_RESULT_PASS, true);   
  145.             }   
  146.         }   
  147.     }   
  148.     return voteResult;   
  149. }  
	@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
可以通过访问流程管理体验效果
最终展示视频可以看以下链接:
7
8
分享到:
评论

相关推荐

    activiti取会签人员

    在用activiti的时候经常遇到取会签人员的问题,这个文档解决怎么获取会签人员。

    activiti 会签投票统计

    Activiti 是一个开源的工作流和业务自动化引擎,广泛应用于企业级流程管理。在这个主题中,"activiti 会签投票统计" 涉及到 Activiti 的特定功能,特别是会签(Parallel Multi-instance)和自定义事件监听器,用于...

    activiti工作流(超详细)

    activiti工作流文档,超详细,从0基础开始入门,包括数据库介绍、核心api等介绍,满足日常开发所需

    Activiti工作流面试相关知识

    Activiti工作流引擎是一款开源的企业级业务流程管理(BPM)和工作流系统,它为组织提供了一种灵活、可扩展的方式来设计、执行和管理业务流程。在面试中,了解Activiti的核心服务对于理解其工作原理和实际应用至关...

    Activiti工作流整合Web流程设计器整合

    在这个“Activiti工作流整合Web流程设计器整合”主题中,我们将深入探讨如何将Activiti与Web流程设计器集成,以实现直观、高效的流程设计和管理。 首先,我们要理解什么是Activiti。Activiti是由Alfresco开发的一款...

    Activiti工作流教程

    Activiti工作流课程Activiti工作流课程Activiti工作流课程Activiti工作流课程Activiti工作流课程Activiti工作流课程

    Activiti-5.4中实现会签

    在 Activiti-5.4 版本中,会签(Concurrent Signatures)是流程设计中的一个重要特性,允许多个参与者同时对同一任务进行处理,提高了工作效率。下面我们将详细探讨如何在Activiti-5.4中实现会签以及相关的技术细节...

    Activiti工作流课程.pdf

    Activiti工作流课程.pdf为读者提供了一个系统的Activiti工作流知识框架,涵盖了工作流的概念、Activiti的介绍、工作流引擎、BPMN业务流程建模与标注、数据库支持等方面的知识点,是学习Activiti工作流的不二之选。

    Activiti工作流数据库表结构.pdf

    Activiti 是一个轻量级的工作流和业务流程管理系统(BPMN),它是基于Java语言开发并遵循Apache许可证的开源项目。Activiti提供了一套完整的工作流和BPM解决方案,用于业务流程的建模、部署、管理和自动化。其工作流...

    activiti工作流中文说明文档

    Activiti工作流中文说明文档 Activiti是一个基于Apache V2协议发布的开源工作流引擎,旨在帮助开发者快速构建业务流程管理系统。本文档将对Activiti的安装、配置、使用等方面进行详细介绍,以帮助开发者快速上手...

    Activiti工作流示例Activiti Demo(带完整源码)非常实用

    Activiti是一款开源的工作流引擎,它基于模型驱动的架构(MDA),专为现代企业应用程序设计,用于处理业务流程自动化。这个"Activiti工作流示例Activiti Demo"提供了完整的源代码,帮助开发者深入理解并实际操作...

    activiti工作流课程

    ### Activiti工作流知识点概述 #### 一、工作流概念及其执行过程 1. **工作流定义**: - 工作流是指“业务过程的部分或整体在计算机应用环境下的自动化”。具体而言,它旨在通过预定义的规则来自动处理文档、信息...

    Activiti工作流使用手册操作文档

    Activiti工作流是一款开源的工作流程管理系统,主要用于企业的业务流程自动化。它基于模型驱动的设计理念,提供了丰富的API和图形化设计工具,使得开发者可以方便地创建、部署和管理工作流程。本操作手册旨在帮助...

    Activiti工作流引擎入门

    Activiti工作流引擎是Java平台上的一个开源工作流管理系统,专为简化业务流程自动化而设计。它使用BPMN(Business Process Model and Notation)2.0标准进行流程建模,使得非技术人员也能理解并创建复杂的业务流程。...

    Activiti工作流视频(企业开发实例讲解)

    传智播客_Activiti工作流视频(企业开发实例讲解)传智播客_Activiti工作流视频(企业开发实例讲解)传智播客_Activiti工作流视频(企业开发实例讲解)

    activiti工作流项目

    【标题】"activiti工作流项目"是一个基于Java技术栈实现的工作流管理系统示例,它集成了SpringMVC、Hibernate和Activiti等关键组件。这个项目旨在演示如何在实际应用中利用Activiti来构建动态表单和处理各种流程审批...

    Activiti工作流引擎简介

    Activiti工作流引擎简介 1.俯瞰Activiti 2.Activiti开发之旅 3.Why Activiti? 4.Activiti的现状与未来

    Activiti多实例任务实现会签

    【标题】"Activiti多实例任务实现会签"是指在Activiti工作流引擎中,如何配置和使用多实例任务来实现会签功能。在企业级应用中,会签常常用于决策过程,要求多个参与者共同审批,只有当所有参与者都完成审批后,流程...

    前后端分离项目中引入activiti工作流引擎

    ### 前后端分离项目中引入Activiti工作流引擎 #### 一、概述 在当前的软件开发中,前后端分离已经成为了一种常见的架构模式。这种模式将前端的用户界面与后端的数据处理逻辑分开,提高了开发效率,同时也使得系统...

    activiti工作流PPT

    Activiti作为一个工作流引擎,允许开发者通过编程或使用图形化工具定义、执行和管理这些流程。 在Activiti中,流程定义是用BPMN 2.0(Business Process Model and Notation)语言编写的,这是一种国际标准,用于...

Global site tag (gtag.js) - Google Analytics