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

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

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

串行会签
串行会签
并行会签
并行会签

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

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

流程图
何谓多任务实例节点?在Activiti5上的解析则为动态的多任务节 点,可以根据传入的动态人员数进行动态生成任务。生成的任务数则不固定,可以进行并行会签,也可以进行串行会签。会签任务最终是否需要往下执行,由会签设 置的规则来进行约束。如我们可以常规去设置“一票通过”、“一票否决”、“少数服务多数”等会签规则。因此,我们需要在会签节点上绑定我们的设计规则。会签规则设置界面如下:
会签规则设置界面
通过会签设计规则,可以清楚最终会签人员的投票结果。其数据结构如下所示:
数据结构
会签任务的定义本身已经由Activiti来实现了,但需要动态传入动态的人员数
Java代码
  1. <userTaskactiviti:assignee="${assignee}"id="SignTask1"name="领导会签">
  2. <extensionElements>
  3. <activiti:taskListenerclass="com.hotent.platform.service.bpm.listener.TaskSignCreateListener"event="create"/>
  4. <activiti:taskListenerclass="com.hotent.platform.service.bpm.listener.TaskAssignListener"event="assignment"/>
  5. <activiti:taskListenerclass="com.hotent.platform.service.bpm.listener.TaskCompleteListener"event="complete"/>
  6. </extensionElements>
  7. <multiInstanceLoopCharacteristicsactiviti: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. publicbooleanisComplete(ActivityExecutionexecution){
  3. logger.debug("enterttheSignCompleteisCompletemethod...");
  4. StringnodeId=execution.getActivity().getId();
  5. StringactInstId=execution.getProcessInstanceId();
  6. ProcessDefinitionprocessDefinition=bpmService.getProcessDefinitionByProcessInanceId(actInstId);
  7. //取得会签设置的规则
  8. BpmNodeSignbpmNodeSign=bpmNodeSignService.getByDefIdAndNodeId(processDefinition.getId(),nodeId);
  9. //完成会签的次数
  10. IntegercompleteCounter=(Integer)execution.getVariable("nrOfCompletedInstances");
  11. //总循环次数
  12. IntegerinstanceOfNumbers=(Integer)execution.getVariable("nrOfInstances");
  13. //计算投票结果。
  14. VoteResultvoteResult=calcResult(bpmNodeSign,actInstId,nodeId,completeCounter,instanceOfNumbers);
  15. StringsignResult=voteResult.getSignResult();
  16. booleanisCompleted=voteResult.getIsComplete();
  17. /**
  18. *会签完成做的动作。
  19. *1.删除会签的流程变量。
  20. *2.将会签数据更新为完成。
  21. *3.设置会签结果变量。
  22. *4.更新会签节点结果。
  23. *5.清除会签用户。
  24. */
  25. if(isCompleted){
  26. //删除会签的变量。
  27. //删除assignee,loopCounter变量。
  28. bpmService.delLoopAssigneeVars(execution.getId());
  29. logger.debug("setthesignresult+"+signResult);
  30. //将会签数据更新为完成。
  31. taskSignDataService.batchUpdateCompleted(actInstId,nodeId);
  32. //设置会签的结果
  33. execution.setVariable("signResult_"+nodeId,signResult);
  34. //更新会签节点的状态。
  35. Shortstatus=TaskOpinion.STATUS_PASSED;
  36. if(signResult.equals(SIGN_RESULT_REFUSE)){
  37. status=TaskOpinion.STATUS_NOT_PASSED;
  38. }
  39. //更新会签节点的状态。
  40. bpmProStatusDao.updStatus(actInstId,nodeId,status);
  41. //清除会签用户。
  42. taskUserAssignService.clearSignUser();
  43. }
  44. returnisCompleted;
  45. }
  46. **
  47. *根据会签规则计算投票结果。
  48. *<pre>
  49. *1.如果会签规则为空,那么需要所有的人同意通过会签,否则不通过。
  50. *2.否则按照规则计算投票结果。
  51. *</pre>
  52. *@parambpmNodeSign会签规则
  53. *@paramactInstId流程实例ID
  54. *@paramnodeId节点id名称
  55. *@paramcompleteCounter循环次数
  56. *@paraminstanceOfNumbers总的会签次数。
  57. *@return
  58. */
  59. privateVoteResultcalcResult(BpmNodeSignbpmNodeSign,StringactInstId,StringnodeId,IntegercompleteCounter,IntegerinstanceOfNumbers){
  60. VoteResultvoteResult=newVoteResult();
  61. //没有会签实例
  62. if(instanceOfNumbers==0){
  63. returnvoteResult;
  64. }
  65. //投同意票数
  66. IntegeragreeVotesCounts=taskSignDataService.getAgreeVoteCount(actInstId,nodeId);
  67. //没有设置会签规则
  68. //(那么得全部会签通过才通过,否则不通过)
  69. if(bpmNodeSign==null){
  70. //还没有完成可以退出。
  71. if(completeCounter<instanceOfNumbers){
  72. returnvoteResult;
  73. }
  74. else{
  75. //完成了(全部同意才通过)
  76. if(agreeVotesCounts.equals(instanceOfNumbers)){
  77. returnnewVoteResult(SIGN_RESULT_PASS,true);
  78. }
  79. else{
  80. returnnewVoteResult(SIGN_RESULT_REFUSE,true);
  81. }
  82. }
  83. }
  84. //投反对票数
  85. IntegerrefuseVotesCounts=taskSignDataService.getRefuseVoteCount(actInstId,nodeId);
  86. //检查投票是否完成
  87. if(BpmNodeSign.VOTE_TYPE_PERCENT.equals(bpmNodeSign.getVoteType())){
  88. floatpercents=0;
  89. //按同意票数进行决定
  90. if(BpmNodeSign.DECIDE_TYPE_PASS.equals(bpmNodeSign.getDecideType())){
  91. percents=agreeVotesCounts/instanceOfNumbers;
  92. //投票同意票符合条件
  93. if(percents>=bpmNodeSign.getVoteAmount()){
  94. voteResult=newVoteResult(SIGN_RESULT_PASS,true);
  95. }
  96. //投票已经全部完成
  97. elseif(completeCounter.equals(instanceOfNumbers)){
  98. voteResult=newVoteResult(SIGN_RESULT_REFUSE,true);
  99. }
  100. }
  101. //按反对票数进行决定
  102. else{
  103. percents=refuseVotesCounts/instanceOfNumbers;
  104. //投票
  105. if(percents>=bpmNodeSign.getVoteAmount()){
  106. voteResult=newVoteResult(SIGN_RESULT_REFUSE,true);
  107. }
  108. //投票已经全部完成
  109. elseif(completeCounter.equals(instanceOfNumbers)){
  110. voteResult=newVoteResult(SIGN_RESULT_PASS,true);
  111. }
  112. }
  113. }
  114. //按绝对票数投票
  115. else{
  116. //按同意票数进行决定
  117. if(BpmNodeSign.DECIDE_TYPE_PASS.equals(bpmNodeSign.getDecideType())){
  118. //投票同意票符合条件
  119. if(agreeVotesCounts>=bpmNodeSign.getVoteAmount()){
  120. voteResult=newVoteResult(SIGN_RESULT_PASS,true);
  121. }
  122. //投票已经全部完成
  123. elseif(completeCounter.equals(instanceOfNumbers)){
  124. voteResult=newVoteResult(SIGN_RESULT_REFUSE,true);
  125. }
  126. }
  127. //按反对票数进行决定
  128. else{
  129. //投票
  130. if(refuseVotesCounts>=bpmNodeSign.getVoteAmount()){
  131. voteResult=newVoteResult(SIGN_RESULT_REFUSE,true);
  132. }
  133. //投票已经全部完成
  134. elseif(completeCounter.equals(instanceOfNumbers)){
  135. voteResult=newVoteResult(SIGN_RESULT_PASS,true);
  136. }
  137. }
  138. }
  139. returnvoteResult;
  140. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值