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

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‘); //获取当前的工作流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 = ‘[email protected]‘];//新建立一个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 }

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

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修改,截图如下:

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

时间: 2024-10-26 12:07:16

Salesforce 动态审批的相关文章

SF :Salesforce中,关于审批的一些对象

SF中,与审批有关的对象:ProcessInstance, ProcessInstanceHistory, ProcessInstanceStep, ProcessInstanceWorkitem, ProcessNode and TargetObject. ProcessInstanceHistory与ProcessInstanceStep对象中的Fields基本相同 ProcessInstanceHistory:isPending, RemindersSent, TargetObjectId

在BPM动态可配置表单中使用NoSQL技术可行性分析——通用流程化应用审批单设计思路(二)

原业务流程平台审批单使用横向表纵向存储的思路,所有流程所使用的业务表单的数据都存在一张物理表中,表中每条数据记录包含Column定义和Value,Column所对应的字段信息,通过定义表来定义.这种做法就是在实现时,需要使用代码进行数据组装,比较繁琐.当表单较大时,界面展现速度慢.此方案查询统计支持有限. 为了满足可配置动态表单的需求,并解决上述方案的不足,采用NoSQL技术来优化设计,因为NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式.按NoSQL的特性,可以灵活进行s

salesforce零基础学习(八十二)审批邮件获取最终审批人和审批意见

项目中,审批操作无处不在.配置审批流时,我们有时候会用到queue,related user设置当前步骤的审批人,审批人可以一个或者多个.当审批人有多个时,邮件中获取当前记录的审批人和审批意见就不能随便的取一个审批人了,有以下方式针对不同的场景可以获取到当前记录的最终审批人以及审批意见. 邮件内容使用以下几种方式实现: 1.代码里面实现邮件发送 2.email template(text/html/custom) 3.visualforce emailTemplate 对发送邮件方式不清楚的,可

在审批时通过存储过程动态干预操作结果的配置

业务场景: 在领导审批的时候,点击同意时,可以调用预先指定的存储过程,通过返回不同的结果值,来达到对当前单据的特殊控制,显示特定的提示信息,并影响是否可以正常审批的操作. 实施部署步骤: 1.在"表单流程"中,打开特定流程,打开希望控制的特定节点. 2.在"基本属性"页签的"审批前执行"字段中,写入需要执行的存储过程语句,例如: exec p_uf_audit_check 'G_FORM_ID','其他参数' 其中:存储过程名称自定:G_FORM

动态添加table表格内容,填充审批意见。

一,前台 <asp:table id="tblApprove" runat="server" Width="100%"></asp:table> 二.后台 QueryApproveInfo private void SetTable() { TableRow tblRow = new TableRow(); TableCell tblCell = new TableCell(); tblCell.Text = "

salesforce 零基础学习(三十四)动态的Custom Label

custom label在项目中经常用到,常用在apex class或者VF里面用来显示help text或者error message.有的时候我们需要用到的信息是动态变化的,那样就需要动态来显示信息. 步骤如下: 一.创建custom label 我们创建名为Show Message Dynamic的label,value值通过{item}来动态展示信息. 二.使用custom label实现动态显示 为了方便显示,将custom label显示在trigger中处理错误信息. 1 trig

salesforce 零基础开发入门学习(九)Approval Process 介绍

在阅读此篇文章前,可以先参考阅读一个前辈总结的关于Approval Process的操作.以下为参考的链接: http://www.cnblogs.com/mingmingruyuedlut/p/3765777.html Approval Process用于流程审批,Apex主要涉及到的命名空间和类为Approval命名空间以及System命名空间下的Approval类. 其中Approval命名空间下主要的类为: ProcessRequest ProcessSubmitRequest Proc

用MongoDB数据库来管理办公系统中文档型的表单和信息——通用流程化应用审批单设计思路(二,续)

1.办公系统中文档的定义 办公系统中的文档就是指对数据不敏感的业务,例如流程中的审批单.信息专栏.数据上报.信息记录等.而对于这些信息的管理,特别是时效性较强的管理记录,仍采用关系型数据库进行管理. (1)流程中审批单 流程中审批单由功能按钮区.特殊功能区.业务表单区.附件区.审批意见区等区域构成,其中,业务表单区理论上包含附件和意见,但是由于附件和意见的业务特殊性,需要单独进行管理,剩下的业务表单就可以看作文档了. 在一些流程审批业务中,业务信息有的是以Excel或word文件等方式专递,这样

医疗时鲜资讯:关注新医改动态

背景: 中国医疗行业正在面临着重大的变革,时下诸如"多点执业"."全科医生"."家庭医生"."网络医疗"."移动医疗"等词汇越来越受到大众的关注,常常被推送到各大网站的头条,因此本系列博文主要负责摘录相关的资讯,文后或许会有感而发而牢骚几句,谨记:本人仅仅是凑凑热闹而已-- 时鲜资讯: (一)国家政策文件 最近国家卫计委在医疗及相关领域发布的文件可谓不胜枚举,这足以说明新医改的紧迫性,以及政府改革的力度.文