前面介绍过自定义审批流:

Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示

Dynamic CRM 2013学习笔记(二十一)自定义审批流2 - 配置按钮

Dynamic CRM 2013学习笔记(三十二)自定义审批流3 - 节点及实体配置

Dynamic CRM 2013学习笔记(三十三)自定义审批流4 - 规则节点 -有分支的流程处理

Dynamic CRM 2013学习笔记(三十四)自定义审批流5 - 自动邮件通知

Dynamic CRM 2013学习笔记(三十五)自定义审批流6 - 审批通过后,再审批 - 二次审批

Dynamic CRM 2013学习笔记(三十七)自定义审批流7 - 初始化(整套审批流下载、安装)

虽然灵活,功能强大,不用修改代码,完全用配置就可以搞定。

最近客户需要实现一个很简单的审批流,就有了这篇简单审批流的实现。

首先根据需求文档分析流程:

审批流 会签 或签 Java 审批流实现_审批流 会签 或签 Java

功能实现如下:

一、 添加字段

一个是让用户修改的审批状态,如果当前用户是审批人,放开审批状态字段,让用户审批或拒绝;值为 Pending, Approved, Rejected

一个是实体的状态,用户审批后根据业务逻辑来判断实体的状态;值为 Pending, Approved, Rejected

一个审批人字段,提交或用户修改了审批状态后,设置下一个审批人

另外可以设置几个隐藏审批人的字段,方便在插件里一次得出,js里就方便设置了(尽量避免在js里运行大量逻辑),如上图主要是把 sales director, gm 存下来

 

二. JS控制提交按钮和审批状态字段

1. 提交控制

AllowSubmit: function () {

 
    
var currentUserId = Xrm.Page.context.getUserId();
 
    var userHasRole = HP.QuoteRibbon.UserHasRole(["Reginal Sales"], currentUserId);var Approver = Xrm.Page.getAttribute("tm_approver").getValue();var AccountTypeValue = Xrm.Page.getAttribute("wf_accounttype").getValue();var QuoteTypeValue = Xrm.Page.getAttribute("tm_quote_type").getValue();var TotalAmount = Xrm.Page.getAttribute("tm_total_amount").getValue() / 1000; 
    
 
 
    
var AccountType = {};
 
    
AccountType.House = 3;
 
    
 
 
    
var QuoteType = {};
 
    
QuoteType.Standard = 1;
 
    
QuoteType.Custom = 2;
 
    
 
 
    if (userHasRole && Approver == null) {if (TotalAmount < 100 && QuoteTypeValue == QuoteType.Custom && AccountTypeValue != AccountType.House) {return false; 
    
}
 
    
 
 
    return true; 
    
}
 
    else {return false; 
    
}
 
    
},
 
    
 
 
    
Submit: function () {

 
    var AccountTypeValue = Xrm.Page.getAttribute("wf_accounttype").getValue();var QuoteTypeValue = Xrm.Page.getAttribute("tm_quote_type").getValue();var TotalAmount = Xrm.Page.getAttribute("tm_total_amount").getValue() / 1000;var ApproverAttribute = Xrm.Page.getAttribute("tm_approver"); 
    
var Approver = ApproverAttribute.getValue();
 
    var QuoteStatusAttribute = Xrm.Page.getAttribute("tm_quote_status");var ApprovalResultAttribute = Xrm.Page.getAttribute("tm_approval_result");var CentralizedValue = Xrm.Page.getAttribute("tm_centralized").getValue();var SubmitAttribute = Xrm.Page.getAttribute("tm_submit");SubmitAttribute.setSubmitMode("always");QuoteStatusAttribute.setSubmitMode("always");ApprovalResultAttribute.setSubmitMode("always"); 
    
var AccountType = {};
 
    
AccountType.House = 3;
 
    
 
 
    
var QuoteType = {};
 
    
QuoteType.Standard = 1;
 
    
QuoteType.Custom = 2;
 
    
 
 
    
var QuoteStatus = {};
 
    
QuoteStatus.Pending = 1;
 
    
QuoteStatus.Approved = 2;
 
    
QuoteStatus.Rejected = 3;
 
    
 
 
    
var ApprovalStatus = {};
 
    
ApprovalStatus.Pending = 1;
 
    
ApprovalStatus.Approved = 2;
 
    
ApprovalStatus.Rejected = 3;
 
    
 
 
    if (QuoteTypeValue == QuoteType.Standard) {if (TotalAmount <= 500) { 
    
QuoteStatusAttribute.setValue(QuoteStatus.Approved);
 
    
ApprovalResultAttribute.setValue(ApprovalStatus.Approved);
 
    
}
 
    else {//var sd = HP.QuoteRibbon.GetSalesDirector();//var user = [{ "id": sd.guid, "name": sd.name, "entityType": sd.logicalName }];//ApproverAttribute.setValue(user); 
    
QuoteStatusAttribute.setValue(QuoteStatus.Pending);
 
    
ApprovalResultAttribute.setValue(ApprovalStatus.Pending);
 
    
}
 
    
}
 
    else {if (AccountTypeValue == AccountType.House) {if (TotalAmount < 500) { 
    
ApproverAttribute.setValue(CentralizedValue);
 
    
QuoteStatusAttribute.setValue(QuoteStatus.Pending);
 
    
ApprovalResultAttribute.setValue(ApprovalStatus.Pending);
 
    
}
 
    else if (TotalAmount >= 500) {//var sd = HP.QuoteRibbon.GetSalesDirector();//var user = [{ "id": sd.guid, "name": sd.name, "entityType": sd.logicalName }];//ApproverAttribute.setValue(user); 
    
QuoteStatusAttribute.setValue(QuoteStatus.Pending);
 
    
ApprovalResultAttribute.setValue(ApprovalStatus.Pending);
 
    
}
 
    
}
 
    else {if (TotalAmount >= 100 && TotalAmount < 500) { 
    
ApproverAttribute.setValue(CentralizedValue);
 
    
QuoteStatusAttribute.setValue(QuoteStatus.Pending);
 
    
ApprovalResultAttribute.setValue(ApprovalStatus.Pending);
 
    
}
 
    else if (TotalAmount >= 500) {//var sd = HP.QuoteRibbon.GetSalesDirector();//var user = [{ "id": sd.guid, "name": sd.name, "entityType": sd.logicalName }];//ApproverAttribute.setValue(user); 
    
QuoteStatusAttribute.setValue(QuoteStatus.Pending);
 
    
ApprovalResultAttribute.setValue(ApprovalStatus.Pending);
 
    
}
 
    
}
 
    
}
 
    SubmitAttribute.setValue("Submit_" + new Date()); 
    
Xrm.Page.data.entity.save();
 
    
},

 

2. 审批状态修改事件

ApprovalResultChanged: function () {

 
    
 
 
    
var ApprovalStatus = {};
 
    
ApprovalStatus.Pending = 1;
 
    
ApprovalStatus.Approved = 2;
 
    
ApprovalStatus.Rejected = 3;
 
    
 
 
    
var QuoteType = {};
 
    
QuoteType.Standard = 1;
 
    
QuoteType.Custom = 2;
 
    
 
 
    
var QuoteStatus = {};
 
    
QuoteStatus.Pending = 1;
 
    
QuoteStatus.Approved = 2;
 
    
QuoteStatus.Rejected = 3;
 
    
 
 
    var ApproverAttribute = Xrm.Page.getAttribute("tm_approver");var CentralizedValue = Xrm.Page.getAttribute("tm_centralized").getValue();var approvalResultValue = Xrm.Page.getAttribute("tm_approval_result").getValue();var QuoteStatusAttribute = Xrm.Page.getAttribute("tm_quote_status");var ApprovalResultAttribute = Xrm.Page.getAttribute("tm_approval_result");var GMValue = Xrm.Page.getAttribute("tm_gmid").getValue(); 
    
 
 
    var AccountTypeValue = Xrm.Page.getAttribute("wf_accounttype").getValue();var QuoteTypeValue = Xrm.Page.getAttribute("tm_quote_type").getValue();var TotalAmount = Xrm.Page.getAttribute("tm_total_amount").getValue() / 1000;QuoteStatusAttribute.setSubmitMode("always");ApproverAttribute.setSubmitMode("always"); 
    
 
 
    if (approvalResultValue == ApprovalStatus.Approved) {if (QuoteTypeValue == QuoteType.Standard) {if (TotalAmount >= 500 && TotalAmount < 1000) { 
    
QuoteStatusAttribute.setValue(QuoteStatus.Approved);
 
    //ApprovalResultAttribute.setValue(ApprovalStatus.Approved); 
    
}
 
    else if (TotalAmount >= 1000) {if (HP.QuoteForm.UserHasRole(["General Manager"]) == true) { 
    
QuoteStatusAttribute.setValue(QuoteStatus.Approved);
 
    //ApprovalResultAttribute.setValue(ApprovalStatus.Approved); 
    
}
 
    else {if (CentralizedValue && HP.QuoteForm.GuidsisEqual(Xrm.Page.context.getUserId(), CentralizedValue[0].id)) { 
    
HP.QuoteForm.SetLookupValue(ApproverAttribute, GMValue);
 
    
}
 
    else { 
    
HP.QuoteForm.SetLookupValue(ApproverAttribute, CentralizedValue);
 
    
}
 
    
QuoteStatusAttribute.setValue(QuoteStatus.Pending);
 
    
ApprovalResultAttribute.setValue(ApprovalStatus.Pending);
 
    
}
 
    
}
 
    
}
 
    else {if (TotalAmount < 1000) { 
    
QuoteStatusAttribute.setValue(QuoteStatus.Approved);
 
    //ApprovalResultAttribute.setValue(ApprovalStatus.Approved); 
    
}
 
    else if (TotalAmount >= 1000) {if (CentralizedValue && HP.QuoteForm.GuidsisEqual(Xrm.Page.context.getUserId(), CentralizedValue[0].id)) { 
    
QuoteStatusAttribute.setValue(QuoteStatus.Approved);
 
    //ApprovalResultAttribute.setValue(ApprovalStatus.Approved); 
    
}
 
    else {if (HP.QuoteForm.UserHasRole(["General Manager"]) == true) { 
    
HP.QuoteForm.SetLookupValue(ApproverAttribute, CentralizedValue);
 
    
}
 
    else { 
    
HP.QuoteForm.SetLookupValue(ApproverAttribute, GMValue);
 
    
}
 
    
QuoteStatusAttribute.setValue(QuoteStatus.Pending);
 
    
ApprovalResultAttribute.setValue(ApprovalStatus.Pending);
 
    
}
 
    
}
 
    
}
 
    
}
 
    else if (approvalResultValue == ApprovalStatus.Rejected) {ApproverAttribute.setValue(null); 
    
QuoteStatusAttribute.setValue(QuoteStatus.Rejected);
 
    //ApprovalResultAttribute.setValue(ApprovalStatus.Rejected); 
    
}
 
    
},


 

三、插件设置审批人

为了在js里快速方便地设置下一个审批人,可以通过插件在后台来设置。当提交后,触发插件把下几个审批人放到隐藏字段里以供js快速赋值


if (entity.Contains("tm_submit")) 
   
{

 
   
Entity preImageEntity = (Entity)context.PreEntityImages["PreImage"];if (preImageEntity.Contains("tm_approval_result") && ((OptionSetValue)preImageEntity["tm_approval_result"]).Value == 2)return; 
   
 
 
   
CRMConfigHelper.CRMConfig crmConfig = CRMConfigHelper.InitialCRMConfig(context.OrganizationName);
 
   
string sql = string.Format(@"select top 1  op.new_product_line 
   
from Quote q join Opportunity o on q.OpportunityId = o.OpportunityId
 
   
join wf_opportunityproduct op on o.OpportunityId = op.wf_OpportunityId
 
   
where op.wf_IncludeinForecast = 1 and q.QuoteId = '{0}'", entity.Id);
 
   
 
 
   
var dtPL = SqlHelper.SQLExecuteQuery(crmConfig.CRMSqlConnStr, sql).Tables[0];
 
   
if (dtPL.Rows.Count == 1 && dtPL.Rows[0]["new_product_line"] != null) 
   
{

 
   
string productLine = dtPL.Rows[0]["new_product_line"].ToString(); 
   
 
 
   
sql = string.Format(@"select top 1 bu.new_nlt_sales_director 'NLTSD', bu.new_tm_sales_director 'TMSD' 
   
from BusinessUnit bu
 
   
join SystemUser u on bu.BusinessUnitId = u.BusinessUnitId
 
   
where u.SystemUserId = '{0}'", context.UserId);
 
   
 
 
   
var dtSD = SqlHelper.SQLExecuteQuery(crmConfig.CRMSqlConnStr, sql).Tables[0];
 
   
if (dtSD.Rows.Count == 1) 
   
{

 
   
if (productLine == "1") //TM 
   
{

 
   
entity["tm_sales_directorid"] = new EntityReference("systemuser", Guid.Parse(dtSD.Rows[0]["TMSD"].ToString())); 
   
}
 
   
else if (productLine == "2") //NLT 
   
{

 
   
entity["tm_sales_directorid"] = new EntityReference("systemuser", Guid.Parse(dtSD.Rows[0]["NLTSD"].ToString())); 
   
}
 
   
 
 
   
//if (preImageEntity["tm_approver"] == null ) 
   
{

 
   
entity["tm_approver"] = entity["tm_sales_directorid"]; 
   
}
 
   
}
 
   
}
 
   
 
 
   
//if (preImageEntity.Contains("tm_gmid") && preImageEntity["tm_gmid"] != null)//    return; 
   
 
 
   
sql = @"select top 1 u.SystemUserId 'GM' 
   
from SystemUser u
 
   
join SystemUserRoles ur on u.SystemUserId = ur.SystemUserId
 
   
join role r on r.RoleId = ur.RoleId
 
   
where r.Name = 'General Manager'";
 
   
 
 
   
var dtGM = SqlHelper.SQLExecuteQuery(crmConfig.CRMSqlConnStr, sql).Tables[0];
 
   
if (dtGM.Rows.Count == 1 && dtGM.Rows[0]["GM"] != null) 
   
{

 
   
entity["tm_gmid"] = new EntityReference("systemuser", Guid.Parse(dtGM.Rows[0]["GM"].ToString())); 
   
}
 
   
}


 

四、公用JS方法

1. 设置Lookup值 


SetLookupValue: function (LookupAttribute, LookupValue) {

 
   
var lookupReference = [];
 
   
lookupReference[0] = {};
 
   
lookupReference[0].id = LookupValue[0].id;
 
   
lookupReference[0].entityType = LookupValue[0].entityType;
 
   
lookupReference[0].name = LookupValue[0].name;
 
   
LookupAttribute.setValue(lookupReference);
 
   
},



  

2. OData查询   


ODataRetrieve: function (oDataString) {

 
   
var retrieveReq = new XMLHttpRequest();retrieveReq.open("GET", encodeURI(Xrm.Page.context.getClientUrl() + "/XRMServices/2011/OrganizationData.svc/" + oDataString), false);retrieveReq.setRequestHeader("Accept", "application/json");retrieveReq.setRequestHeader("Content-Type", "application/json;charset=utf-8"); 
   
retrieveReq.send();
 
   
return JSON.parse(retrieveReq.responseText).d; 
   
},



 

3. 当前用户是否有指定的角色   


UserHasRole: function (roleNames) {

 
   
var ODataResult = HP.QuoteForm.ODataRetrieve("SystemUserSet?$select=systemuserroles_association/Name&$expand=systemuserroles_association&$filter=SystemUserId eq guid'" + Xrm.Page.context.getUserId() + "'");if (ODataResult != null && ODataResult.results.length == 1 && ODataResult.results[0].systemuserroles_association.results.length > 0) { 
   
var oDataRoles = ODataResult.results[0].systemuserroles_association.results;
 
   
for (var i = 0; i < oDataRoles.length; i++) {for (var j = 0; j < roleNames.length; j++) {if (oDataRoles[i].Name == roleNames[j]) {return true; 
   
}
 
   
}
 
   
}
 
   
}
 
   
return false; 
   
},



 

4. 判断两个GUID是相同 


GuidsisEqual: function (guid1, guid2) {

 
   
var isEqual = false;if (guid1 != null && guid2 != null) {isEqual = guid1.replace(/[{}]/g, "").toLowerCase() == guid2.replace(/[{}]/g, "").toLowerCase(); 
   
}
 
   
return isEqual; 
   
},



 

 

 

Dynamic CRM 2013学习笔记 系列汇总