日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

你明白什么是会签?工作流+会签应用

發(fā)布時(shí)間:2023/12/14 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 你明白什么是会签?工作流+会签应用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.什么是會(huì)簽?

?

在流程業(yè)務(wù)管理中,任務(wù)是通常都是由一個(gè)人去處理的,而多個(gè)人同時(shí)處理一個(gè)任務(wù),這種任務(wù)我們稱之為會(huì)簽任務(wù)。這種業(yè)務(wù)需求很常見(jiàn),如一個(gè)請(qǐng)款單,領(lǐng)導(dǎo)審批環(huán)節(jié)中,就需要多個(gè)部門領(lǐng)導(dǎo)簽字。在流程業(yè)務(wù)中,我們可以把每個(gè)領(lǐng)導(dǎo)簽字的環(huán)節(jié)都定義為任務(wù),并且這個(gè)會(huì)簽的人員是不固定的,若固定的我們可以通過(guò)Activiti的并行任務(wù)或串行任務(wù)來(lái)處理。會(huì)簽的引入說(shuō)明,無(wú)非就是為了流程流轉(zhuǎn)至某一環(huán)節(jié)點(diǎn),其審批的人員是動(dòng)態(tài)的,并且需要根據(jù)會(huì)簽審批的結(jié)果實(shí)現(xiàn)流程的不同流轉(zhuǎn)。

2.中國(guó)特色的會(huì)簽需求是什么?

?

會(huì)簽需求主要有以下兩方面:

  • 會(huì)簽的參與人員
  • 會(huì)簽審批的順序
  • 會(huì)簽審批的結(jié)果
  • 動(dòng)態(tài)加簽
  • 以下我們就是圍繞以上的需求進(jìn)行擴(kuò)展實(shí)現(xiàn)的

    3.Activiti對(duì)于會(huì)簽的實(shí)現(xiàn)

    ?

    BPMN2的標(biāo)準(zhǔn)中并沒(méi)有對(duì)以上這種情景提供完善的支持,因此要在Activiti中實(shí)現(xiàn)會(huì)簽審批,我們需要結(jié)合Activiti提供的流程任務(wù)的多實(shí)例特性,進(jìn)行一些必要的擴(kuò)展,以支持我們的中國(guó)特色的會(huì)簽需求。
    會(huì)簽任務(wù)也是一種人工任務(wù),其在activiti的定義中,也是使用UserTask來(lái)定義,但在屬性上我們需要對(duì)這個(gè)定義的類型進(jìn)行特殊的配置,即為多任務(wù)實(shí)例類型(并行或串行)任何一種。另外需要定義會(huì)簽的參與人員,再定義會(huì)簽的完成條件(若不定義,表示其是所有參與人均完成后,流程才往下跳轉(zhuǎn))。

    3.1.多實(shí)例的人工任務(wù)配置

    ?

    通過(guò)在UserTask節(jié)點(diǎn)的屬性上配置,如下所示:

    其生成的BPMN的配置文件如下所示:

    <userTask id=”sid-78A17A9B-1185-48AA-A1CA-611421251D52″ name=”經(jīng)理會(huì)簽”>
    <multiInstanceLoopCharacteristics isSequential=”false” activiti:collection=”${counterSignService.getUsers(execution)}”>
    <completionCondition>${counterSignService.isComplete(execution)}</completionCondition>
    </multiInstanceLoopCharacteristics>
    </userTask>

    【說(shuō)明】:

  • isSequential=”false” 表示這是非串行會(huì)簽,即為并行會(huì)簽,如三個(gè)人參與會(huì)簽,是三個(gè)人同時(shí)收到待辦,任務(wù)實(shí)例是同時(shí)產(chǎn)生的。
  • activiti:collection 表示是會(huì)簽的參與人員集合,用戶可以通過(guò)定義自身的服務(wù)類來(lái)獲取
  • completionCondition ?表示是任務(wù)往下跳轉(zhuǎn)的完成條件,返回true是,表示條件成立,流程會(huì)跳至下一審批環(huán)節(jié)。
  • 我們就是圍繞著這幾點(diǎn)來(lái)實(shí)現(xiàn)中國(guó)式的流程會(huì)簽的

    3.2 會(huì)簽任務(wù)的人員集合計(jì)算處理

    ?

    我們?cè)赟pring容器中定義一個(gè)會(huì)簽服務(wù)類(counterSignService)里面提供兩個(gè)api接口,一個(gè)是獲得任務(wù)的人員集合,另一個(gè)是判斷當(dāng)前任務(wù)是否已經(jīng)完成了會(huì)簽的計(jì)算,其參考代碼如下所示:

    package com.redxun.bpm.core.service.sign;import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Set;import javax.annotation.Resource;import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;import com.redxun.bpm.activiti.util.ProcessHandleHelper; import com.redxun.bpm.core.entity.BpmDestNode; import com.redxun.bpm.core.entity.BpmRuPath; import com.redxun.bpm.core.entity.BpmSignData; import com.redxun.bpm.core.entity.IExecutionCmd; import com.redxun.bpm.core.entity.ProcessMessage; import com.redxun.bpm.core.entity.config.MultiTaskConfig; import com.redxun.bpm.core.entity.config.TaskVotePrivConfig; import com.redxun.bpm.core.entity.config.UserTaskConfig; import com.redxun.bpm.core.identity.service.BpmIdentityCalService; import com.redxun.bpm.core.manager.BpmNodeSetManager; import com.redxun.bpm.core.manager.BpmSignDataManager; import com.redxun.bpm.enums.TaskOptionType; import com.redxun.org.api.model.IdentityInfo; import com.redxun.sys.org.entity.OsGroup; import com.redxun.sys.org.entity.OsRelType; import com.redxun.sys.org.entity.OsUser; import com.redxun.sys.org.manager.OsGroupManager; import com.redxun.sys.org.manager.OsUserManager;/*** 會(huì)簽配置服務(wù)類* @author csx**/ public class CounterSignService { @Resource private BpmSignDataManager bpmSignDataManager; @Resource private BpmNodeSetManager bpmNodeSetManager; @ResourceBpmIdentityCalService bpmIdentityCalService; @Resource private OsGroupManager osGroupManager; @Resource private OsUserManager osUserManager;private Log logger=LogFactory.getLog(CounterSignService.class); /*** 獲得會(huì)簽任務(wù)中的人員計(jì)算集合* @param execution* @return*/ public Set<String> getUsers(ActivityExecution execution){logger.debug("enter the CounterSignService ");Set<String> userIds=new LinkedHashSet<String>();String nodeId=execution.getActivity().getId();//1.回退處理通過(guò)BpmRuPath backRuPath=ProcessHandleHelper.getBackPath();if(backRuPath!=null && "YES".equals(backRuPath.getIsMultiple())){String uIds=backRuPath.getUserIds();userIds.addAll(Arrays.asList(uIds.split("[,]"))); execution.setVariable("signUserIds_"+nodeId,uIds);return userIds;}//2.通過(guò)變量來(lái)判斷是否第一次進(jìn)入該方法String signUserIds=(String)execution.getVariable("signUserIds_"+nodeId);if(StringUtils.isNotEmpty(signUserIds)){String[]uIds=signUserIds.split("[,]");userIds.addAll(Arrays.asList(uIds));return userIds;}//3.從界面中的提交變量取用戶IExecutionCmd nextCmd=ProcessHandleHelper.getProcessCmd();BpmDestNode bpmDestNode=nextCmd.getNodeUserMap().get(nodeId);if(bpmDestNode!=null && StringUtils.isNotEmpty(bpmDestNode.getUserIds())){//加至流程變量中,以使后續(xù)繼續(xù)不需要從線程及數(shù)據(jù)庫(kù)中獲取execution.setVariable("signUserIds_"+nodeId,bpmDestNode.getUserIds());execution.setVariable("priority_"+nodeId,bpmDestNode.getPriority());execution.setVariable("expiretime_"+nodeId, bpmDestNode.getExpireTime());String[]uIds=bpmDestNode.getUserIds().split("[,]");userIds.addAll(Arrays.asList(uIds));return userIds;}//4.從數(shù)據(jù)庫(kù)中讀取節(jié)點(diǎn)人員配置獲得參與人員列表Collection<IdentityInfo> idInfoList=bpmIdentityCalService.calNodeUsersOrGroups(execution.getProcessDefinitionId(), execution.getCurrentActivityId(),execution.getVariables());for(IdentityInfo identityInfo:idInfoList){if(IdentityInfo.IDENTIFY_TYPE_USER.equals(identityInfo.getIdentityType())){userIds.add(identityInfo.getIdentityInfoId());}else{List<OsUser> users= osUserManager.getByGroupIdRelTypeId(identityInfo.getIdentityInfoId(), OsRelType.REL_CAT_GROUP_USER_BELONG_ID);for(OsUser u:users){userIds.add(u.getUserId());}}}if(userIds.size()>0){StringBuffer sb=new StringBuffer();for(String uId:userIds){sb.append(uId).append(",");}if(sb.length()>0){sb.deleteCharAt(sb.length()-1);}execution.setVariable("signUserIds_"+nodeId,sb.toString());}else{String name=(String)execution.getActivity().getProperty("name");ProcessMessage msg=ProcessHandleHelper.getProcessMessage();msg.getErrorMsges().add("會(huì)簽節(jié)點(diǎn)["+name+"]沒(méi)有設(shè)置執(zhí)行人員,請(qǐng)聯(lián)系管理員!");}return userIds; }/*** 會(huì)簽是否計(jì)算完成* @param execution* @return*/ public boolean isComplete(ActivityExecution execution){//完成會(huì)簽的次數(shù)Integer completeCounter=(Integer)execution.getVariable("nrOfCompletedInstances");//總循環(huán)次數(shù)Integer instanceOfNumbers=(Integer)execution.getVariable("nrOfInstances");String solId=(String)execution.getVariable("solId");String nodeId=execution.getActivity().getId();UserTaskConfig taskConfig=bpmNodeSetManager.getTaskConfig(solId, nodeId);//獲得任務(wù)及其多實(shí)例的配置,則任務(wù)不進(jìn)行任何投票的設(shè)置及處理,即需要所有投票完成后來(lái)才跳至下一步。if(taskConfig.getMultiTaskConfig()==null){return completeCounter==instanceOfNumbers;}//獲得會(huì)簽的數(shù)據(jù)List<BpmSignData> bpmSignDatas=bpmSignDataManager.getByInstIdNodeId(execution.getProcessInstanceId(), nodeId);MultiTaskConfig multiTask=taskConfig.getMultiTaskConfig();//通過(guò)票數(shù)int passCount=0;//反對(duì)票數(shù)int refuseCount=0;//棄權(quán)票數(shù)int abstainCount=0;for(BpmSignData data:bpmSignDatas){int calCount=1;//棄權(quán)不作票數(shù)統(tǒng)計(jì)if(TaskOptionType.ABSTAIN.name().equals(data.getVoteStatus())){abstainCount++;continue;}String userId=data.getUserId();//檢查是否有特權(quán)的處理if(multiTask.getVotePrivConfigs().size()>0){//計(jì)算用戶的用戶組List<OsGroup> osGroups=osGroupManager.getBelongGroups(userId);for(TaskVotePrivConfig voteConfig:multiTask.getVotePrivConfigs()){//是否在特權(quán)里boolean isInPriv=false;//為用戶類型if(TaskVotePrivConfig.USER.equals(voteConfig.getIdentityType()) && voteConfig.getIdentityIds().contains(userId)){isInPriv=true;}else{//為用戶組類型for(OsGroup osGroup:osGroups){if(voteConfig.getIdentityIds().contains(osGroup.getGroupId())){isInPriv=true;break;}}}//若找到特權(quán),則計(jì)算其值if(isInPriv){calCount=voteConfig.getVoteNums();break;}}}//統(tǒng)計(jì)同意票數(shù)if(TaskOptionType.AGREE.name().equals(data.getVoteStatus())){passCount+=calCount;}else{//統(tǒng)計(jì)反對(duì)票數(shù)refuseCount+=calCount;}}logger.debug("==============================passCount:"+passCount+" refuseCount:" + refuseCount +" abstainCount:"+abstainCount);//是否可以跳出會(huì)簽boolean isNext=false;String result=null;//按投票通過(guò)數(shù)進(jìn)行計(jì)算if(MultiTaskConfig.VOTE_TYPE_PASS.equals(multiTask.getVoteResultType())){//計(jì)算是否通過(guò)//按投票數(shù)進(jìn)行統(tǒng)計(jì)if(MultiTaskConfig.CAL_TYPE_NUMS.equals(multiTask.getCalType())){//代表通過(guò)if(passCount>=multiTask.getVoteValue()){isNext=true;result="PASS";}}else{//按百分比進(jìn)行計(jì)算int resultPercent=new Double(passCount*100/(passCount+refuseCount+abstainCount)).intValue();//代表通過(guò)if(resultPercent>=multiTask.getVoteValue()){isNext=true;result="PASS";}}}else{//按投票反對(duì)數(shù)進(jìn)行計(jì)算//計(jì)算是否通過(guò)//按投票數(shù)進(jìn)行統(tǒng)計(jì)if(MultiTaskConfig.CAL_TYPE_NUMS.equals(multiTask.getCalType())){//代表通過(guò)if(refuseCount>=multiTask.getVoteValue()){isNext=true;result="REFUSE";}}else{//按百分比進(jìn)行計(jì)算int resultPercent=new Double(refuseCount*100/(passCount+refuseCount+abstainCount)).intValue();//代表通過(guò)if(resultPercent>=multiTask.getVoteValue()){isNext=true;result="REFUSE";}}}if((MultiTaskConfig.HANDLE_TYPE_DIRECT.equals(multiTask.getHandleType())&& isNext)//直接處理|| (MultiTaskConfig.HANDLE_TYPE_WAIT_TO.equals(multiTask.getHandleType()) && completeCounter==instanceOfNumbers)){//等待所有的處理完execution.setVariable("voteResult_"+nodeId, result);//刪除該節(jié)點(diǎn)的會(huì)簽數(shù)據(jù)for(BpmSignData data:bpmSignDatas){bpmSignDataManager.deleteObject(data);}return true;}return false;} }

    ?

    【說(shuō)明】
    以上的代碼的人員計(jì)算有幾個(gè)來(lái)源:

  • 流程回退時(shí)獲得原來(lái)參與的人員
  • 直接從流程變量中獲取
  • 從界面中的提交變量取用戶
  • 從數(shù)據(jù)庫(kù)中讀取節(jié)點(diǎn)人員配置獲得參與人員列表
  • 會(huì)簽的投票處理結(jié)果放至流程變量中去,供后續(xù)的分支條件來(lái)處理,我們把會(huì)簽的配置設(shè)置管理如下:

    我們提供了按票數(shù)、百分比的投票處理,同時(shí)允許有特權(quán)的用戶的投票規(guī)則以支持靈活的會(huì)簽結(jié)果運(yùn)算。

    咨詢了解

    QQ: 1950148199

    手機(jī):18620763495

    電話:020-29026351


    總結(jié)

    以上是生活随笔為你收集整理的你明白什么是会签?工作流+会签应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。