`
0101tracy
  • 浏览: 2102 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Activity工作流会签开发设计思想

 
阅读更多
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> 

其中,isSequential为true则为串行会签,若为false则为并行会签,而activiti:collection可以来自我们Spring容器中的接口及方法,表示获取会签用户集合,taskUserAssignService.getSignUser(execution)。其获取会签的用户值来自两个方面,一个在界面中指定的会签人员,另一个在后台会签节点上配置的人员。






后台会签节点人员设置






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




<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.} 
  



最终实现效果,可以在线访问

http://www.jee-soft.cn:10080/bpm3/login.jsp

csx/1

可以通过访问流程管理体验效果

最终展示视频可以看以下链接:

http://www.jee-soft.cn/htsite/html/cpjfw/zxjc/bpmx3/index.html
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics