会签任务是工作流里一个比较觉见的任务方式,意思是一个处理任务需要多个人同时处理,然后汇总多个人的意见,决定流程下一步该如何执行。在JBPM4里,并没有会签这个概念,其只有并行任务的处理方式,如下所示:
这种方式会签的任务数量是固定的,并且任务名称也不一样,不能由用户来动态决定有多少人参与会签的任务。当然我们可以让中间那部分只有一个节点,然后根据用户在后台设置了多少人参与或在流程运行过程中,动态知道有多少人参与这个任务,动态创建并发的任务(不过这样实现上有一点困难,需要扩展jbpm的api相对多一些)
而另一种相对比较完善的解决方案是可以用一个任务来代表会签任务,而在流程运行至该任务节点的时候,根据当前有多少人参与这流程,动态生成该任务下的会签子任务,这样可以使得每个会签的参与人都可以在待办事项中看到该任务。这种办法实现上相对容易得多,因为jbpm4本身对子任务的动态创建支持得比较好。
joffice2就是基于这种方式来解决会签的配置及处理。那么,如何汇总会签任务的投票意见呢?我们知道,日常的会签常见的方式有:一票否决,一票通过,全票通过,半数通过等。其实现无非是分为两种,按投票数的绝对票数,另一种是按投票占的百份比数,投票决策又分为两种:通过或拒绝(反对),投票过程中会有通过,反对或弃权的动作。因此,在后台上我们设置某个节点若为会签时,其会签的投票决策方式信息包括如下:
并且我们希望在执行会签任务的时候,会签的参与人员均可以填写意见及选择投票的类型(如同意,反对,弃权),如:
那么投票的情况如何处理,以下为投票的决策处理方式:
为什么要在后面加上流程变量decisionType呢,这里就是为了下一任务可以根据上一任务的会签结果来决定如何往下执行的,我们可以在后续的任务或条件结点中,通过这个变量的值,来决定其如何往下执行。若该变量的值为“pass"表示上一步会签的结果是同意,否则为反对。
如我们有一流程:
那么在分支节点上,我们插入我们需要流程执行的分支决定代码,并且根据这个分支决定代码决定往下一步时执行的路径。于是我们在分支上加上干预的代码如下所示:
根据上面的逻辑判断,我们把完成会签任务的代码展示部分如下:
- /**
- * 完成会签子任务
- * @param parentTask 父任务
- * @param subTask 子任务
- * @param variables 任务中的流程变量
- */
- private void completeSignSubTask(TaskImpl parentTask,TaskImpl subTask,String signalName,Map variables){
- //看目前还有多少子任务
- int subTasksSize=parentTask.getSubTasks().size();
- //检查会签的配置情况
- ProcessInstance pi=((TaskImpl)parentTask).getProcessInstance();
- ProcessDefinition pd=repositoryService.createProcessDefinitionQuery().processDefinitionId(pi.getProcessDefinitionId()).uniqueResult();
- //取得该任务的后台人员配置
- ProUserAssign assignSetting=proUserAssignService.getByDeployIdActivityName(pd.getDeploymentId(), parentTask.getActivityName());
- evict(subTask);
- evict(parentTask);
- if(assignSetting!=null){
- //取得会签配置
- TaskSign taskSign=taskSignService.findByAssignId(assignSetting.getAssignId());
- if(taskSign!=null){//按照配置执行任务跳转
- //是否完成父任务
- boolean isFinishSupTask=false;
- //查看用户投的是哪一种票(同意还是不同意还是弃权)
- Short isAgree=(Short)variables.get(FlowConstants.SIGN_VOTE_TYPE);
- if(isAgree==null){//若为空,则认为是投通过票
- isAgree=TaskSign.DECIDE_TYPE_PASS;
- }
- //1.保存投票信息
- taskSignDataService.addVote(parentTask.getId(),isAgree);
- //加上子任务的流程变量
- taskService.setVariables(subTask.getId(),variables);
- //2.完成子任务
- taskService.completeTask(subTask.getId());
- //3.检查其投票数是否已满足后台会签配置条件
- //3.1根据后台配置的投票类型,取得投票的总数
- Long voteCounts=taskSignDataService.getVoteCounts(parentTask.getId(),taskSign.getDecideType());
- if(taskSign.getVoteCounts()!=null){//按绝对投票数来进行
- if(voteCounts>=taskSign.getVoteCounts()){
- isFinishSupTask=true;
- }
- }else if(taskSign.getVotePercents()!=null){//按投票百分比来进行
- //取到动态有多少子任务
- Integer taskSignCounts=(Integer)taskService.getVariable(parentTask.getId(), "taskSignCounts");
- if(taskSignCounts==null || taskSignCounts==0){
- taskSignCounts=1;
- }
- BigDecimal totalSubTasks=new BigDecimal(taskSignCounts);
- //当前投票后占的百分比
- BigDecimal tempPercent=new BigDecimal(voteCounts).divide(totalSubTasks);
- Integer curPercent=new Integer(tempPercent.multiply(new BigDecimal(100)).intValue());
- if(curPercent>=taskSign.getVotePercents()){
- isFinishSupTask=true;
- }
- }
- //若投票完成后,把投票结果存在decisionType变量里,方便在后台通过脚本根据投票的结果进行跳转
- Map varsMap=new HashMap();
- //当前会签子任务完成后,若投票的情况已经满足后台的会签设置条件
- //或没有满足会签设置的情况,并且会签所有子任务均已经完成
- if(isFinishSupTask || (!isFinishSupTask && subTasksSize==1) ){
- String passRefuse=null;
- if(isFinishSupTask){//所有子任务完成,满足会签条件设置
- passRefuse=TaskSign.DECIDE_TYPE_PASS==taskSign.getDecideType()?"pass":"refuse";
- }else{//所有子任务完成,不满足会签条件设置
- passRefuse=taskSign.getDecideType()==TaskSign.DECIDE_TYPE_PASS?"refuse":"pass";
- }
- logger.debug("会签投票结果:"+ passRefuse);
- varsMap.put("decisionType",passRefuse);
- taskService.setVariables(parentTask.getId(),varsMap);
- //完成父任务
- taskService.completeTask(parentTask.getId(),signalName);
- }
- }else{//没有设置对应的会签配置,则认为会签是全部完成后才能往下执行
- logger.error("Task "+parentTask.getActivityName()+" is not config right sign config in process admin console.");
- if(((TaskImpl)parentTask).getSubTasks().size()==1){//若只有当前子任务,则表示可以结束目前这个任务
- taskService.setVariables(subTask.getId(),variables);
- //完成子任务
- taskService.completeTask(subTask.getId());
- //完成父任务
- taskService.completeTask(parentTask.getId(),signalName);
- }else{
- taskService.setVariables(subTask.getId(), variables);
- //完成子任务后,直接返回则可
- taskService.completeTask(subTask.getId());
- return ;
- }
- }
- }else{
- //TODO
- logger.error("Task "+parentTask.getActivityName()+"is not config the setting in process admin console.");
- }
- }
/** * 完成会签子任务 * @param parentTask 父任务 * @param subTask 子任务 * @param variables 任务中的流程变量 */ private void completeSignSubTask(TaskImpl parentTask,TaskImpl subTask,String signalName,Map variables){ //看目前还有多少子任务 int subTasksSize=parentTask.getSubTasks().size(); //检查会签的配置情况 ProcessInstance pi=((TaskImpl)parentTask).getProcessInstance(); ProcessDefinition pd=repositoryService.createProcessDefinitionQuery().processDefinitionId(pi.getProcessDefinitionId()).uniqueResult(); //取得该任务的后台人员配置 ProUserAssign assignSetting=proUserAssignService.getByDeployIdActivityName(pd.getDeploymentId(), parentTask.getActivityName()); evict(subTask); evict(parentTask); if(assignSetting!=null){ //取得会签配置 TaskSign taskSign=taskSignService.findByAssignId(assignSetting.getAssignId()); if(taskSign!=null){//按照配置执行任务跳转 //是否完成父任务 boolean isFinishSupTask=false; //查看用户投的是哪一种票(同意还是不同意还是弃权) Short isAgree=(Short)variables.get(FlowConstants.SIGN_VOTE_TYPE); if(isAgree==null){//若为空,则认为是投通过票 isAgree=TaskSign.DECIDE_TYPE_PASS; } //1.保存投票信息 taskSignDataService.addVote(parentTask.getId(),isAgree); //加上子任务的流程变量 taskService.setVariables(subTask.getId(),variables); //2.完成子任务 taskService.completeTask(subTask.getId()); //3.检查其投票数是否已满足后台会签配置条件 //3.1根据后台配置的投票类型,取得投票的总数 Long voteCounts=taskSignDataService.getVoteCounts(parentTask.getId(),taskSign.getDecideType()); if(taskSign.getVoteCounts()!=null){//按绝对投票数来进行 if(voteCounts>=taskSign.getVoteCounts()){ isFinishSupTask=true; } }else if(taskSign.getVotePercents()!=null){//按投票百分比来进行 //取到动态有多少子任务 Integer taskSignCounts=(Integer)taskService.getVariable(parentTask.getId(), "taskSignCounts"); if(taskSignCounts==null || taskSignCounts==0){ taskSignCounts=1; } BigDecimal totalSubTasks=new BigDecimal(taskSignCounts); //当前投票后占的百分比 BigDecimal tempPercent=new BigDecimal(voteCounts).divide(totalSubTasks); Integer curPercent=new Integer(tempPercent.multiply(new BigDecimal(100)).intValue()); if(curPercent>=taskSign.getVotePercents()){ isFinishSupTask=true; } } //若投票完成后,把投票结果存在decisionType变量里,方便在后台通过脚本根据投票的结果进行跳转 Map varsMap=new HashMap(); //当前会签子任务完成后,若投票的情况已经满足后台的会签设置条件 //或没有满足会签设置的情况,并且会签所有子任务均已经完成 if(isFinishSupTask || (!isFinishSupTask && subTasksSize==1) ){ String passRefuse=null; if(isFinishSupTask){//所有子任务完成,满足会签条件设置 passRefuse=TaskSign.DECIDE_TYPE_PASS==taskSign.getDecideType()?"pass":"refuse"; }else{//所有子任务完成,不满足会签条件设置 passRefuse=taskSign.getDecideType()==TaskSign.DECIDE_TYPE_PASS?"refuse":"pass"; } logger.debug("会签投票结果:"+ passRefuse); varsMap.put("decisionType",passRefuse); taskService.setVariables(parentTask.getId(),varsMap); //完成父任务 taskService.completeTask(parentTask.getId(),signalName); } }else{//没有设置对应的会签配置,则认为会签是全部完成后才能往下执行 logger.error("Task "+parentTask.getActivityName()+" is not config right sign config in process admin console."); if(((TaskImpl)parentTask).getSubTasks().size()==1){//若只有当前子任务,则表示可以结束目前这个任务 taskService.setVariables(subTask.getId(),variables); //完成子任务 taskService.completeTask(subTask.getId()); //完成父任务 taskService.completeTask(parentTask.getId(),signalName); }else{ taskService.setVariables(subTask.getId(), variables); //完成子任务后,直接返回则可 taskService.completeTask(subTask.getId()); return ; } } }else{ //TODO logger.error("Task "+parentTask.getActivityName()+"is not config the setting in process admin console."); } }
产生会签的任务代码如下:
- /**
- * 创建新的任务
- * @param parentTaskId 父任务 ID
- * @param assignIds 任务执行人IDs
- */
- public void newSubTask(String parentTaskId,Long[]userIds){
- TaskServiceImpl taskServiceImpl=(TaskServiceImpl) taskService;
- Task parentTask=taskServiceImpl.getTask(parentTaskId);
- //为该父任务加上会签的人员数,方便后面对会签的投票进行统计
- Map vars=new HashMap();
- vars.put("taskSignCounts", new Integer(userIds.length));
- taskServiceImpl.setVariables(parentTaskId, vars);
- for(int i=0;i<userIds.length;i++){
- String userId=userIds[i].toString();
- TaskImpl task=(TaskImpl)taskServiceImpl.newTask(parentTaskId);
- task.setAssignee(userId);
- task.setName(parentTask.getName() + "-" + (i+1));
- task.setActivityName(parentTask.getName() );
- task.setDescription(parentTask.getDescription());
- //保存
- taskServiceImpl.saveTask(task);
- }
- }
/** * 创建新的任务 * @param parentTaskId 父任务 ID * @param assignIds 任务执行人IDs */ public void newSubTask(String parentTaskId,Long[]userIds){ TaskServiceImpl taskServiceImpl=(TaskServiceImpl) taskService; Task parentTask=taskServiceImpl.getTask(parentTaskId); //为该父任务加上会签的人员数,方便后面对会签的投票进行统计 Map vars=new HashMap(); vars.put("taskSignCounts", new Integer(userIds.length)); taskServiceImpl.setVariables(parentTaskId, vars); for(int i=0;i<userIds.length;i++){ String userId=userIds[i].toString(); TaskImpl task=(TaskImpl)taskServiceImpl.newTask(parentTaskId); task.setAssignee(userId); task.setName(parentTask.getName() + "-" + (i+1)); task.setActivityName(parentTask.getName() ); task.setDescription(parentTask.getDescription()); //保存 taskServiceImpl.saveTask(task); } }
其最终的实现效果如下flash演示。
http://bbs.jee-soft.cn/swf/signTask.html
或
http://bbs.jee-soft.cn/posts/list/288.page
关于我
qq:1848175569
电话:13672461598
相关推荐
【jbpm4.3 会签的实现】 在企业级工作流管理系统中,会签...在实际项目中,结合测试(如压缩包中的"test"目录中的测试用例)和持续学习(如"sofocus"可能包含的相关文档或讨论),将进一步加深对jbpm会签机制的理解。
在本篇中,我们将深入探讨如何在jBPM4.4中实现自定义会签功能,同时包含加签和减签功能。 首先,我们需要了解什么是会签。会签是指在流程中涉及多个审批人的场景,每个审批人都需要对流程中的某个任务进行操作,...
通过学习"CountersignDemo"这个实例,你可以深入了解JBPM4.4的会签实现,包括如何设计流程、创建自定义活动、编写工具类以及如何在实际应用中部署和使用。这将有助于提升你对业务流程管理的理解,使你能更好地为企业...
在这个实例中,我们将探讨如何在JBPM4.3中实现基于Spring的会签功能。会签是一种常见的业务流程操作,需要多个参与者依次或同时对同一文档或任务进行审批,所有参与者的签名都得到确认后,流程才能继续进行。这通常...
本文将深入探讨如何在jbPM中实现会签以及加签、减签功能,并提供相关实践指导。 1. **会签概念与实现** 会签是指在流程中设置一个环节,需要多个参与者依次或同时进行审批。jbPM通过定义工作流模型,利用task节点...
在jbpm中,"fork & join"机制是实现并行处理和流程控制的关键概念,尤其在处理会签(多个审批人同时参与审批)等场景时显得尤为重要。 "fork"在jbpm中指的是流程分支,当流程到达一个fork节点时,流程会分裂为多个...
在本教程中,我们将深入探讨jbpm中的会签和串签功能,以及如何进行流程部署、启动流程、任务提交、查询已办和待办任务。 首先,让我们了解流程部署的概念。在jbpm中,流程部署是将一个流程定义文件(通常是.bpmn或....
在阅读《jBPM4工作流应用开发指南.pdf》这本书时,你可以学习到如何使用jbpm4的API进行流程设计、部署和执行,以及如何进行流程实例的查询和管理。书中可能还会涉及如何处理异常、分支和合并逻辑,以及如何进行流程...
在jbpm中实现会签,主要涉及到以下几个关键知识点: 1. **工作流模型**:jbpm使用BPMN(Business Process Model and Notation)标准来定义流程模型。BPMN提供了一套图形化的符号,用于描绘业务流程,其中包括并行...
- **Eclipse IDE**:推荐使用Eclipse IDE,因为它有jBPM4的插件支持,可以方便地进行流程设计和调试。 ### 3. 下载与导入jBPM4 访问jBPM官方网站或GitHub仓库下载jBPM4的最新发行版。解压后,将`jbpm-installer`...
在jbpm4中,会签可以通过工作流定义(即流程模型)和工作项处理来实现。 首先,我们需要理解jbpm4的核心组件。jbpm4提供了一个流程建模工具,如jBPM Process Designer,用于创建BPMN 2.0兼容的流程图。这些流程图...
包括jBPM4扩展研发先决条件、深入jPDL和jBPM Service API、升级jBPM3到jBPM4、流程虚拟机原理、jBPM4的设计思想、随需而配jBPM4、异步工作执行器、深入jBPM4电子邮件支持、系统日志、jBPM4与Spring框架集成、jBPM4与...
流程图的设计完成后,可以编译成jpdl文件,然后在jbpm引擎中部署,以便执行和跟踪。 流程图的每个组成部分都有其特定的意义: 1. **开始事件**:流程的起点,标记流程的启动。 2. **任务**:代表业务操作,可以是...
综上,"jbpm4.4简单请假流程"项目展示了如何利用jbpm4.4的特性设计和实现一个典型的业务流程,涵盖了流程定义、任务处理、决策逻辑以及系统集成等方面,为企业级流程管理提供了实用范例。通过对这个项目的理解和实践...
本主题聚焦于"工作流开发会签两套方案(Java源代码实现)",我们将深入探讨两种Java实现会签功能的方法,并结合JBPM(Java Business Process Management)框架,为你揭示如何高效地构建这样的系统。 首先,我们需要...
JBPM与Activiti作为当前市场上主流的工作流引擎,因其开源特性及强大的功能受到了广泛的关注与应用。本文将对JBPM和Activiti进行深入的分析,并与国内的工作流引擎FixFlow进行对比。 #### 二、JBPM与Activiti对比...