Salesforce 动态审批
由于Salesforce只支持根据条件动态选择审批分支,如果我们想进一步支持动态根据页面的某种条件选择审批人,Salesforce是不支持的。因此我们只能通过override salesforce审批类来实现,具体步骤如下:
0,以管理员身份新建立一个审批流为Opportunity(审批流名称和每个节点的名称我们从写时候时候需要用到)
1,添加一个名称为Submit for Approval By Neo 自定义按钮给Opportunity(由于我们要重写的是Opportunity的审批流)在Opportunity Object 中的 ‘Buttons, Links, and Actions’ 如下:
填完后填写js代码,由于我们想通过点击直接启动工作流,所以我们需要在这里通过js 调用webservice 类启动。代码如下:
<!--参数名区分大小写,对于跨层object直接在Object名后直接加参字段名即可-->
{!REQUIRESCRIPT("/soap/ajax/30.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/30.0/apex.js")} var OppID='{!Opportunity.Id}'
var Comments = 'submited'
var OppSubmitter = '{!$User.Id}'
var result = sforce.apex.execute("OppApprovalProcess", "SubmitforApproval", {oppID:OppID,Comments:Comments,userID:OppSubmitter });
window.location.reload()
2,在这里我们看到我们需要调用OppApprovalProcess类下SubmitforApproval方法实现审批的提交,下面就是调用提交的代码:(里面还还涉及动态选择审批人的问题,我们后边会讲到)
global class OppApprovalProcess { //submit
webservice static boolean SubmitforApproval(string oppID, string Comments, string userID)
{
try
{
system.debug('oppID:'+oppID);
User nextapprover = getApprover(oppID);;
Approval.ProcessSubmitRequest subReq = new Approval.ProcessSubmitRequest();
subReq.setComments(Comments);
subReq.setObjectId(oppID);
subReq.setSubmitterId(userID);
subReq.setNextApproverIds(new Id[]{nextapprover.Id});
subReq.setProcessDefinitionNameOrId('Opportunity_Discount');
Approval.ProcessResult submitResult = Approval.process(subReq); return submitResult.isSuccess();
}
catch(Exception ex)
{
system.debug('ex:'+ex.getMessage());
return false;
}
}
}
3,创建完按钮后,我们需要把这个自定义按钮添加到page layout中,我们的最终目的是在添加完成后替换原有默认的提交按钮,所以我们要重写原有的Opportunity的Detail页面通过Jquery进行代码注入,所以我们要新建一个vistualforce 页面代码如下:
<apex:page sidebar="true" standardController="Opportunity">
<!-- <apex:relatedList list="ProcessSteps" ></apex:relatedList>-->
<apex:includescript value="{!$Resource.JQuery}"/>
<script type="text/javascript">
$(function(){ //添加新按钮隐藏老按钮
// alert($('input[name="piSubmit"]').val());
if($('input[name="piSubmit"]').val()=='Submit for Approval')
{
($('input[name="piSubmit"]').hide()).parent().append($('input[name="submit_for_approval"]'));
$('input[name="piSubmit"]').next().hide();
}
else
{
//alert($('input[name="piSubmit"]').val());
$('input[name="submit_for_approval"]').hide();
//替换HistoryList中的审批链接
var OppId = ('{!Opportunity.Id}').substring(0,15);
var ApprovalListID = OppId + '_RelatedProcessHistoryList_body';
//alert(ApprovalListID);
var Approvalprocessdiv=document.getElementById(ApprovalListID);
//alert(Approvalprocessdiv.getAttribute('class'));
if(Approvalprocessdiv!=null)
{
var originalHTML=Approvalprocessdiv.innerHTML;
var newHtml=originalHTML.replace('/p/process/ProcessInstanceWorkitemWizardStageManager?','/apex/ProcessInstance?OppId='+OppId+'&');
Approvalprocessdiv.innerHTML=newHtml;
}
}
});
</script>
<apex:detail relatedList="true" title="true"/>
</apex:page>
添加完成后效果如下:submit for approval by Neo 就是我们的自定义按钮
4,添加提交按钮后,我们同时要替换审批页面的同意和拒绝按钮,但是由于salesforce不支持重写这个页面,所以我们自己创建一个审批页面来替换salesforce默认的审批页面,前端代码如下:
<apex:page controller="ProcessInstanceController" tabStyle="Opportunity">
<apex:form >
<apex:sectionHeader title="Opportunity" subtitle="{!objOpp.Name}"/>
<apex:pageBlock title="Approve/Reject Approval Request">
<apex:pageBlockButtons location="bottom">
<apex:commandButton value="Approve" action="{!Approval}" reRender="block">
<apex:param name="approve" value="Approve" assignTo="{!ApprovalAction}"/>
</apex:commandButton>
<apex:commandButton value="Reject" action="{!Approval}" reRender="block">
<apex:param name="reject" value="Reject" assignTo="{!ApprovalAction}"/>
</apex:commandButton>
<apex:commandButton value="Cancel" action="{!Approval}" reRender="block">
<apex:param name="cancel" value="Cancel" assignTo="{!ApprovalAction}"/>
</apex:commandButton>
</apex:pageBlockButtons>
<apex:pageBlockSection columns="1">
<apex:pageBlockSectionItem >
Name <apex:outputField value="{!objOpp.Name}"/>
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem >
Lead Owner <apex:outputField value="{!objOpp.Owner.Name}"/>
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem >
Rejection Reason <font color="red">(Mandatory while Rejection)</font><apex:inputField value="{!objOpp.Rejection_Reason__c}"/>
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem >
Comments <font color="red">(Mandatory while Rejection)</font> <apex:inputTextArea value="{!objOpp.Comments__c}" rows="5" cols="100"/>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>
5,同时在后台类中重写Apprve 和 Reject 类,代码如下:
public class ProcessInstanceController {
public String processId;
public String OppId;
public ProcessInstance objProcessInstance;
public Opportunity objOpp {get; set;}
public string ApprovalAction {get;set;}
public PageReference redirectPage;
//初始化
public ProcessInstanceController()
{
processId = ApexPages.currentPage().getParameters().get('id'); //获取当前的工作流ID
OppId = ApexPages.currentPage().getParameters().get('OppId'); //获取当前case ID
objOpp = [select Name,Owner.Name,Rejection_Reason__c,Comments__c from Opportunity where id =:OppId]; //获取当前Opp对象为了后面更新comments和Reson
redirectPage = new PageReference('/'+OppId);
}
//审批
public PageReference Approval(){
try
{
if(ApprovalAction == 'Approve' || ApprovalAction == 'Reject')
{
//system.debug('ApprovalAction:'+this.ApprovalAction);
User nextapprover =[select Id from User where username = 'yinghai_guo_neo@sina.com'];//新建立一个object 并mapping关系
Approval.ProcessWorkitemRequest approvalNode = new Approval.ProcessWorkitemRequest();
// system.debug('comments:'+objOpp.Comments__c);
approvalNode.setComments(objOpp.Comments__c);
approvalNode.setAction(ApprovalAction);
approvalNode.setNextApproverIds(new Id[]{nextapprover.Id});
approvalNode.setWorkitemId(processId);
//system.debug('processID'+processId);
Approval.ProcessResult result = Approval.process(approvalNode);
//system.debug('result:'+result.isSuccess());
update objOpp;
//system.debug('update objOpp');
}
else
{
//system.debug('ApprovalAction:'+this.ApprovalAction);
}
}
catch(Exception ex)
{
system.debug('Ex:'+ex.getMessage());
}
return redirectPage;
}
}
最后生成的审批页面效果如下:
6, 最后我们要做的事情就是在动态查找审批人的方法,我们通过判断审批的每个节点等条件赛选出最终审批人
//get approver
private static User getApprover(string OppID)
{
string ProcessNodeName = 'Sumbit';
//获取当前需要审批节点名称
for (ProcessInstance piw:[select Id,(SELECT ProcessNode.Name FROM StepsAndWorkitems)
FROM ProcessInstance where TargetObjectId = :OppID order by CreatedDate])
{
for(ProcessInstanceHistory PIH : piw.StepsAndWorkitems)
{
ProcessNodeName=PIH.ProcessNode.Name;
break;
}
}
User nextApprover = null;
if(ProcessNodeName == 'Submit')
{
//do sth
}
else if(ProcessNodeName == 'Director Approval')
{
//do sth
}
else if(ProcessNodeName == 'CEO Approval')
{
//do sth
} return nextApprover;
}
7,由于我们的opportunity 的页面是我们自定义的,所以我们要在系统中替换Opportunity list View按钮中的链接子页面,我们直接在Buttons, Links, and Actions修改,截图如下:
至此,我们实现审批人的动态审批,有任何问题,留言讨论,谢谢!!!
Salesforce 动态审批的更多相关文章
- salesforce 零基础学习(四十六)动态美观显示列表中记录的审批状态
项目中,申请者申请某些事项以后,常常需要在申请列表中查看当前申请的记录所在的审批状态,动态美观的显示状态可以使UI更符合客户要求,比如下面这样. 以Goods__c表为例,申请者申请的一些采购以前需要 ...
- salesforce零基础学习(八十二)审批邮件获取最终审批人和审批意见
项目中,审批操作无处不在.配置审批流时,我们有时候会用到queue,related user设置当前步骤的审批人,审批人可以一个或者多个.当审批人有多个时,邮件中获取当前记录的审批人和审批意见就不能随 ...
- Salesforce 开发整理(七)配置审批流
salesforce提供了比较强大的可配置审批流功能,在系统中翻译为“批准过程”.所以需要配置审批时,选择创建 ——> 工作流和批准 ——> 批准过程,然后选择管理批准过程,选择需要配置 ...
- salesforce 零基础学习(三十四)动态的Custom Label
custom label在项目中经常用到,常用在apex class或者VF里面用来显示help text或者error message.有的时候我们需要用到的信息是动态变化的,那样就需要动态来显示信 ...
- salesforce 零基础开发入门学习(九)Approval Process 介绍
在阅读此篇文章前,可以先参考阅读一个前辈总结的关于Approval Process的操作.以下为参考的链接: http://www.cnblogs.com/mingmingruyuedlut/p/37 ...
- salesforce 零基础学习(六十七)SingleEmailMessage 那点事
在salesforce开发中,发送邮件是一个很常见的功能.比如在进入审批流以后的通过和拒绝的操作需要发送邮件给记录的owner,和其他系统交互以后更改了某些状态通知相关的User或者Contact等等 ...
- salesforce
salesforce&apex salesforce开发的小心得 salesforce零基础学习(七十七)队列的实现以及应用 摘要: 队列和栈简单的区别为栈是后进先出,队列是先进先出.队列也是 ...
- Salesforce开发者学习笔记之一:基本知识
本文介绍了Salesforce开发平台的基本知识, 包括如下内容: Salesforce平台介绍 Salesforce基本术语 定制和扩展Salesforce平台 创建一个简单的应用程序 Salesf ...
- salesforce 零基础学习(五十四)常见异常友好消息提示
异常或者error code汇总:https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_con ...
随机推荐
- 11.12模拟考T2(GCD)
2.梅花桩 (blossom.pas/c/cpp) [问题描述] 小x在练习一门轻功,这门轻功是在梅花桩上跳来跳去,这门轻功是严格按照直线从一个梅花桩直接跳到另外一个梅花桩上.因为小x有恐高症,所 ...
- kbengine里如何使用git快速下载项目?
项目有两个镜像,github[https://github.com/kbengine/kbengine.git] ,osc开源中国[https://git.oschina.net/likecg/kbe ...
- Python 常用函数
字符串->数字: float(str) int(str) 十六进制字符串转int: 不带0x前缀: x = int('dead',16) 带0x前缀: x = int('0xff', 0) 其中 ...
- css3实现酷炫的3D盒子翻转效果
简介 运用css3先在平面空间组成立方体盒子,再让整个盒子翻转起来,先来张效果图: 步骤 1.先用css将6张图片摆成下图的样子: 下面就是通过css3的3D变换将每个面进行翻转,使之成为一个立体的盒 ...
- delphi 动态更改屏幕分辨率(转)
一.如何动态更改屏幕分辨率 有许多小工具可以在不重新启动Windows的条件下,动态更改屏幕分辨率.你是不是也想自己动手做一个呢?请在interface段中加入下面一句 function Resolu ...
- angularJs ng-model/ng-bind
ng-bind 与ng-model区别ng-bind是从$scope -> view的单向绑定,也就是说ng-bind是相当于{{object.xxx}},是用于展示数据的.ng-modle是$ ...
- webstorm(注册,激活,破解,码,一起支持正版,最新可用)(2016.9.2更新)
webstorm(注册,激活,破解,码,一起支持正版,最新可用)(2016.9.2更新) 来源于:http://blog.csdn.net/xx1710/article/details/51725 ...
- [转载]ARM协处理器CP15寄存器详解
用于系统存储管理的协处理器CP15 原地址:http://blog.csdn.net/gameit/article/details/13169405 MCR{cond} coproc,opc ...
- (error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about t
运行redis过程中,突然报错如下: (error) MISCONF Redis is configured to save RDB snapshots, but is currently not a ...
- 如何用 .Net 开发
1. 使用最新的技术() 2. 模块拆分,(保持单一,不要把所有的功能都在一起) 3.使用轻量级的外部框架 : :TinyMapper MVC6