因爲Salesforce只支持根據條件動態選擇審批分支,若是咱們想進一步支持動態根據頁面的某種條件選擇審批人,Salesforce是不支持的。所以咱們只能經過override salesforce審批類來實現,具體步驟以下:javascript
0,以管理員身份新創建一個審批流爲Opportunity(審批流名稱和每一個節點的名稱咱們從寫時候時候須要用到)前端
1,添加一個名稱爲Submit for Approval By Neo 自定義按鈕給Opportunity(因爲咱們要重寫的是Opportunity的審批流)在Opportunity Object 中的 ‘Buttons, Links, and Actions’ 以下:java
填完後填寫js代碼,因爲咱們想經過點擊直接啓動工做流,因此咱們須要在這裏經過js 調用webservice 類啓動。代碼以下:web
1 <!--參數名區分大小寫,對於跨層object直接在Object名後直接加參字段名便可--> 2 {!REQUIRESCRIPT("/soap/ajax/30.0/connection.js")} 3 {!REQUIRESCRIPT("/soap/ajax/30.0/apex.js")} 4 5 var OppID='{!Opportunity.Id}' 6 var Comments = 'submited' 7 var OppSubmitter = '{!$User.Id}' 8 var result = sforce.apex.execute("OppApprovalProcess", "SubmitforApproval", {oppID:OppID,Comments:Comments,userID:OppSubmitter }); 9 window.location.reload()
2,在這裏咱們看到咱們須要調用OppApprovalProcess類下SubmitforApproval方法實現審批的提交,下面就是調用提交的代碼:(裏面還還涉及動態選擇審批人的問題,咱們後邊會講到)ajax
1 global class OppApprovalProcess { 2 3 //submit 4 webservice static boolean SubmitforApproval(string oppID, string Comments, string userID) 5 { 6 try 7 { 8 system.debug('oppID:'+oppID); 9 User nextapprover = getApprover(oppID);; 10 Approval.ProcessSubmitRequest subReq = new Approval.ProcessSubmitRequest(); 11 subReq.setComments(Comments); 12 subReq.setObjectId(oppID); 13 subReq.setSubmitterId(userID); 14 subReq.setNextApproverIds(new Id[]{nextapprover.Id}); 15 subReq.setProcessDefinitionNameOrId('Opportunity_Discount'); 16 Approval.ProcessResult submitResult = Approval.process(subReq); 17 18 return submitResult.isSuccess(); 19 } 20 catch(Exception ex) 21 { 22 system.debug('ex:'+ex.getMessage()); 23 return false; 24 } 25 } 26 }
3,建立完按鈕後,咱們須要把這個自定義按鈕添加到page layout中,咱們的最終目的是在添加完成後替換原有默認的提交按鈕,因此咱們要重寫原有的Opportunity的Detail頁面經過Jquery進行代碼注入,因此咱們要新建一個vistualforce 頁面代碼以下:app
1 <apex:page sidebar="true" standardController="Opportunity"> 2 <!-- <apex:relatedList list="ProcessSteps" ></apex:relatedList>--> 3 <apex:includescript value="{!$Resource.JQuery}"/> 4 <script type="text/javascript"> 5 $(function(){ 6 7 //添加新按鈕隱藏老按鈕 8 // alert($('input[name="piSubmit"]').val()); 9 if($('input[name="piSubmit"]').val()=='Submit for Approval') 10 { 11 ($('input[name="piSubmit"]').hide()).parent().append($('input[name="submit_for_approval"]')); 12 $('input[name="piSubmit"]').next().hide(); 13 } 14 else 15 { 16 //alert($('input[name="piSubmit"]').val()); 17 $('input[name="submit_for_approval"]').hide(); 18 //替換HistoryList中的審批連接 19 var OppId = ('{!Opportunity.Id}').substring(0,15); 20 var ApprovalListID = OppId + '_RelatedProcessHistoryList_body'; 21 //alert(ApprovalListID); 22 var Approvalprocessdiv=document.getElementById(ApprovalListID); 23 //alert(Approvalprocessdiv.getAttribute('class')); 24 if(Approvalprocessdiv!=null) 25 { 26 var originalHTML=Approvalprocessdiv.innerHTML; 27 var newHtml=originalHTML.replace('/p/process/ProcessInstanceWorkitemWizardStageManager?','/apex/ProcessInstance?OppId='+OppId+'&'); 28 Approvalprocessdiv.innerHTML=newHtml; 29 } 30 } 31 }); 32 </script> 33 <apex:detail relatedList="true" title="true"/> 34 </apex:page>
添加完成後效果以下:submit for approval by Neo 就是咱們的自定義按鈕 ide
4,添加提交按鈕後,咱們同時要替換審批頁面的贊成和拒絕按鈕,可是因爲salesforce不支持重寫這個頁面,因此咱們本身建立一個審批頁面來替換salesforce默認的審批頁面,前端代碼以下:this
1 <apex:page controller="ProcessInstanceController" tabStyle="Opportunity"> 2 <apex:form > 3 <apex:sectionHeader title="Opportunity" subtitle="{!objOpp.Name}"/> 4 <apex:pageBlock title="Approve/Reject Approval Request"> 5 <apex:pageBlockButtons location="bottom"> 6 <apex:commandButton value="Approve" action="{!Approval}" reRender="block"> 7 <apex:param name="approve" value="Approve" assignTo="{!ApprovalAction}"/> 8 </apex:commandButton> 9 <apex:commandButton value="Reject" action="{!Approval}" reRender="block"> 10 <apex:param name="reject" value="Reject" assignTo="{!ApprovalAction}"/> 11 </apex:commandButton> 12 <apex:commandButton value="Cancel" action="{!Approval}" reRender="block"> 13 <apex:param name="cancel" value="Cancel" assignTo="{!ApprovalAction}"/> 14 </apex:commandButton> 15 </apex:pageBlockButtons> 16 <apex:pageBlockSection columns="1"> 17 <apex:pageBlockSectionItem > 18 Name <apex:outputField value="{!objOpp.Name}"/> 19 </apex:pageBlockSectionItem> 20 <apex:pageBlockSectionItem > 21 Lead Owner <apex:outputField value="{!objOpp.Owner.Name}"/> 22 </apex:pageBlockSectionItem> 23 <apex:pageBlockSectionItem > 24 Rejection Reason <font color="red">(Mandatory while Rejection)</font><apex:inputField value="{!objOpp.Rejection_Reason__c}"/> 25 </apex:pageBlockSectionItem> 26 <apex:pageBlockSectionItem > 27 Comments <font color="red">(Mandatory while Rejection)</font> <apex:inputTextArea value="{!objOpp.Comments__c}" rows="5" cols="100"/> 28 </apex:pageBlockSectionItem> 29 </apex:pageBlockSection> 30 </apex:pageBlock> 31 </apex:form> 32 </apex:page>
5,同時在後臺類中重寫Apprve 和 Reject 類,代碼以下:spa
1 public class ProcessInstanceController { 2 public String processId; 3 public String OppId; 4 public ProcessInstance objProcessInstance; 5 public Opportunity objOpp {get; set;} 6 public string ApprovalAction {get;set;} 7 public PageReference redirectPage; 8 //初始化 9 public ProcessInstanceController() 10 { 11 processId = ApexPages.currentPage().getParameters().get('id'); //獲取當前的工做流ID 12 OppId = ApexPages.currentPage().getParameters().get('OppId'); //獲取當前case ID 13 objOpp = [select Name,Owner.Name,Rejection_Reason__c,Comments__c from Opportunity where id =:OppId]; //獲取當前Opp對象爲了後面更新comments和Reson 14 redirectPage = new PageReference('/'+OppId); 15 } 16 //審批 17 public PageReference Approval(){ 18 try 19 { 20 if(ApprovalAction == 'Approve' || ApprovalAction == 'Reject') 21 { 22 //system.debug('ApprovalAction:'+this.ApprovalAction); 23 User nextapprover =[select Id from User where username = 'yinghai_guo_neo@sina.com'];//新創建一個object 並mapping關係 24 Approval.ProcessWorkitemRequest approvalNode = new Approval.ProcessWorkitemRequest(); 25 // system.debug('comments:'+objOpp.Comments__c); 26 approvalNode.setComments(objOpp.Comments__c); 27 approvalNode.setAction(ApprovalAction); 28 approvalNode.setNextApproverIds(new Id[]{nextapprover.Id}); 29 approvalNode.setWorkitemId(processId); 30 //system.debug('processID'+processId); 31 Approval.ProcessResult result = Approval.process(approvalNode); 32 //system.debug('result:'+result.isSuccess()); 33 update objOpp; 34 //system.debug('update objOpp'); 35 } 36 else 37 { 38 //system.debug('ApprovalAction:'+this.ApprovalAction); 39 } 40 } 41 catch(Exception ex) 42 { 43 system.debug('Ex:'+ex.getMessage()); 44 } 45 return redirectPage; 46 } 47 }
最後生成的審批頁面效果以下:debug
6, 最後咱們要作的事情就是在動態查找審批人的方法,咱們經過判斷審批的每一個節點等條件賽選出最終審批人
1 //get approver 2 private static User getApprover(string OppID) 3 { 4 string ProcessNodeName = 'Sumbit'; 5 //獲取當前須要審批節點名稱 6 for (ProcessInstance piw:[select Id,(SELECT ProcessNode.Name FROM StepsAndWorkitems) 7 FROM ProcessInstance where TargetObjectId = :OppID order by CreatedDate]) 8 { 9 for(ProcessInstanceHistory PIH : piw.StepsAndWorkitems) 10 { 11 ProcessNodeName=PIH.ProcessNode.Name; 12 break; 13 } 14 } 15 User nextApprover = null; 16 if(ProcessNodeName == 'Submit') 17 { 18 //do sth 19 } 20 else if(ProcessNodeName == 'Director Approval') 21 { 22 //do sth 23 } 24 else if(ProcessNodeName == 'CEO Approval') 25 { 26 //do sth 27 } 28 29 return nextApprover; 30 }
7,因爲咱們的opportunity 的頁面是咱們自定義的,因此咱們要在系統中替換Opportunity list View按鈕中的連接子頁面,咱們直接在Buttons, Links, and Actions修改,截圖以下:
至此,咱們實現審批人的動態審批,有任何問題,留言討論,謝謝!!!