首页 > 代码库 > Salesforce 动态审批

Salesforce 动态审批

由于Salesforce只支持根据条件动态选择审批分支,如果我们想进一步支持动态根据页面的某种条件选择审批人,Salesforce是不支持的。因此我们只能通过override salesforce审批类来实现,具体步骤如下:

0,以管理员身份新建立一个审批流为Opportunity(审批流名称和每个节点的名称我们从写时候时候需要用到)

1,添加一个名称为Submit for Approval By Neo 自定义按钮给Opportunity(由于我们要重写的是Opportunity的审批流)在Opportunity Object 中的 ‘Buttons, Links, and Actions’ 如下:

技术分享

填完后填写js代码,由于我们想通过点击直接启动工作流,所以我们需要在这里通过js 调用webservice 类启动。代码如下:

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方法实现审批的提交,下面就是调用提交的代码:(里面还还涉及动态选择审批人的问题,我们后边会讲到)

 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 页面代码如下:

 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             else15             {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 就是我们的自定义按钮 

技术分享

 4,添加提交按钮后,我们同时要替换审批页面的同意和拒绝按钮,但是由于salesforce不支持重写这个页面,所以我们自己创建一个审批页面来替换salesforce默认的审批页面,前端代码如下:

 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 类,代码如下:

 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‘); //获取当前的工作流ID12         OppId = ApexPages.currentPage().getParameters().get(‘OppId‘); //获取当前case ID13         objOpp = [select Name,Owner.Name,Rejection_Reason__c,Comments__c from Opportunity where id =:OppId]; //获取当前Opp对象为了后面更新comments和Reson14         redirectPage = new PageReference(‘/‘+OppId);15      }16     //审批17      public PageReference Approval(){   18       try19         {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             else37             {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 }

最后生成的审批页面效果如下:

 技术分享

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 sth19         }20         else if(ProcessNodeName == ‘Director Approval‘)21         {22             //do sth23         }24         else if(ProcessNodeName == ‘CEO Approval‘)25         {26             //do sth27         }28         29         return nextApprover;30     }

7,由于我们的opportunity 的页面是我们自定义的,所以我们要在系统中替换Opportunity list View按钮中的链接子页面,我们直接在Buttons, Links, and Actions修改,截图如下:

技术分享

至此,我们实现审批人的动态审批,有任何问题,留言讨论,谢谢!!!

Salesforce 动态审批