审批过程中,经常要求自动发邮件:审批中要通知下一个审批人进行审批;审批完通知申请人已审批完;被拒绝后,要通知已批准的人和申请人。下面详细介绍如何实现一个自动发邮件的插件:

 

1. 根据审批状态来确定要通知哪个人或哪个角色

  • 状态为2 - 审批中时,查找下一个审批人
/// <summary>
/// 下一个审批人
/// </summary>
/// <returns></returns>
private List<Guid> GetNextStepPerson()
{
//收件人
List<Guid> mailToList = new List<Guid>();
string fetchQuery = @"
<fetch mapping='logical' distinct='false'>
<entity name='crm_approve_activity'>
<attribute name='ownerid' />
<order attribute='createdon' descending='true' />
<filter type='and'>
<condition attribute='regardingobjectid' operator='eq' uitype='' value='{0}' />
<condition attribute='crm_approve_state' operator='eq' value='2' />
</filter>
</entity>
</fetch>"; FetchExpression fetchExp = new FetchExpression(string.Format(fetchQuery, entity.Id));
EntityCollection result = service.RetrieveMultiple(fetchExp);
if (result.Entities.Count == 0) return null;
foreach (Entity activity in result.Entities)
{
Guid ownerid = activity.GetAttributeValue<EntityReference>("ownerid").Id;
if (!mailToList.Contains(ownerid)) mailToList.Add(ownerid);
}
return mailToList;
}

 

  • 状态为3 - 审批通过时,查找申请人
/// <summary>
/// 获得提交人
/// </summary>
/// <returns></returns>
private List<Guid> GetSubmitPerson()
{
//收件人
List<Guid> mailToList = new List<Guid>();
string fetchQuery = @"
<fetch count='1' mapping='logical'>
<entity name='crm_approve_activity'>
<attribute name='ownerid' />
<order attribute='createdon' />
<filter type='and'>
<condition attribute='regardingobjectid' operator='eq' uitype='' value='{0}' />
<condition attribute='crm_approve_state' operator='eq' value='1' />
</filter>
</entity>
</fetch>"; FetchExpression fetchExp = new FetchExpression(string.Format(fetchQuery, entity.Id));
EntityCollection result = service.RetrieveMultiple(fetchExp);
if (result.Entities.Count == 0) return null;
foreach (Entity activity in result.Entities)
{
Guid ownerid = activity.GetAttributeValue<EntityReference>("ownerid").Id;
if (!mailToList.Contains(ownerid)) mailToList.Add(ownerid);
}
return mailToList;
}

 

 

  • 状态为4 - 审批拒绝时,查找审批过的人,以及申请人
/// <summary>
/// reject 后获得审批过的和单据创始人
/// </summary>
/// <returns></returns>
private List<Guid> GetApprovedPerson()
{
//收件人
List<Guid> mailToList = new List<Guid>();
string fetchQuery = @"
<fetch mapping='logical' distinct='false'>
<entity name='crm_approve_activity'>
<attribute name='ownerid' />
<order attribute='createdon' descending='true' />
<filter type='and'>
<condition attribute='regardingobjectid' operator='eq' uitype='' value='{0}' />
<condition attribute='crm_approve_state' operator='eq' value='1' />
</filter>
</entity>
</fetch>"; FetchExpression fetchExp = new FetchExpression(string.Format(fetchQuery, entity.Id));
EntityCollection result = service.RetrieveMultiple(fetchExp);
if (result.Entities.Count == 0) return null;
foreach (Entity activity in result.Entities)
{
Guid ownerid = activity.GetAttributeValue<EntityReference>("ownerid").Id;
if (!mailToList.Contains(ownerid)) mailToList.Add(ownerid);
}
return mailToList;
}

 

2. 定义邮件模板

Entity curEntity = service.Retrieve(entity.LogicalName, entity.Id,
new ColumnSet(m_Parameter, "ownerid")); string subjectTxt = string.Empty;
string formNumber = curEntity.GetAttributeValue<string>(m_Parameter);
if (formNumber == null) formNumber = "";
string fName = entityDisplayName + "(" + formNumber + ")"; StringBuilder body = new StringBuilder();
body.AppendLine("<p>Dear {0},</p>");//收件人的 first name
string url = GetCRMServiceUrl() + "main.aspx?etn=" + entity.LogicalName
+ "&pagetype=entityrecord&id=%7B" + entity.Id + "%7D";
if (approvalStatus == 4)
{
subjectTxt = fName + " was rejected";
body.AppendLine(string.Format("For more information, please click on <a href='{0}' target='_blank'>{1}</a></p>", url, fName));
body.AppendLine("<p>Best Regards</p>");
body.AppendLine("<p>CRM</p>");
// txt = "Reject";
}
else if (approvalStatus == 3)
{
subjectTxt = fName + " has been completed";
body.AppendLine(string.Format("<p>{0} has been completed. For more information, please click on <a href='{1}' target='_blank'>{2}</a></p>", fName, url, fName));
body.AppendLine("<p>Best Regards</p>");
body.AppendLine("<p>CRM</p>");
// txt = "Completed";
}
else if (approvalStatus == 2)
{
subjectTxt = "Please review and approve " + fName;
body.AppendLine(string.Format("<p> Please review and approve the {0} on <a href='{1}' target='_blank'>{2}</a></p>", fName, url, fName));
body.AppendLine("<p>Thank you very much!</p>");
body.AppendLine("<p>Best Regards</p>");
body.AppendLine("<p>CRM</p>");
}

 

3. 创建邮件实体

List<ActivityParty> fromList = new List<ActivityParty>();
fromList.Add(new ActivityParty()
{
PartyId = new EntityReference(SystemUser.EntityLogicalName, context.UserId),
ParticipationTypeMask = new OptionSetValue(8)
}); foreach (Guid to in mailToList)
{
// to
List<ActivityParty> toList = new List<ActivityParty>();
toList.Add(new ActivityParty()
{
PartyId = new EntityReference(SystemUser.EntityLogicalName, to),
ParticipationTypeMask = new OptionSetValue(8)
}); Email email = new Email();
email.From = fromList;
email.To = toList;
//email.Cc = cclist;
email.RegardingObjectId = new EntityReference(curEntity.LogicalName, curEntity.Id);
email.ActualDurationMinutes = 30;
email.IsWorkflowCreated = false;
email.Subject = subjectTxt;
SystemUser user = new SystemUser();
user.Attributes = service.Retrieve(SystemUser.EntityLogicalName, to,
new ColumnSet("firstname")).Attributes;
email.Description = string.Format(body.ToString(), user.FirstName);
email.Id = service.Create(email);
SendMail(service, email.Id);
}

 

4. 发送邮件

SendEmailRequest sendEmailreq = new SendEmailRequest();
sendEmailreq.EmailId = mailId;
sendEmailreq.TrackingToken = "";
sendEmailreq.IssueSend = true;
SendEmailResponse sendEmailresp = (SendEmailResponse)service.Execute(sendEmailreq);

 

 

5. 注册插件

 

6. 错误处理

有一次系统重置后,发邮件的插件报了一个错:Cannot open Sql Encryption Symmetric Key because Symmetric Key password does not exist in Config DB

解决方法:

依次打开Settings->Data management –> Data Encryption

然后在上面红框里填上任意一个key即可

 

大功告成!

 

Dynamic CRM 2013学习笔记 系列汇总 -- 持续更新中

Dynamic CRM 2013学习笔记(三十四)自定义审批流5 - 自动邮件通知的更多相关文章

  1. Dynamic CRM 2013学习笔记(十四)复制/克隆记录

    经常有这样的需求,一个单据上有太多要填写的内容,有时还关联多个子单据,客户不想一个一个地填写,他们想从已有的单据上复制数据,克隆成一条新的记录.本文将介绍如何克隆一条记录,包括它的子单据以生成一条新的 ...

  2. Dynamic CRM 2013学习笔记(十二)实现子表合计(汇总,求和)功能的通用插件

    上一篇 Dynamic CRM 2013学习笔记(十一)利用Javascript实现子表合计(汇总,求和)功能 , 介绍了如何用js来实现子表合计功能,这种方法要求在各个表单上添加js方法,如果有很多 ...

  3. Dynamic CRM 2013学习笔记(十五)报表设计:报表入门、开发工具及注意事项

    本文是关于CRM 2013报表开发入门介绍,包括开发工具的使用,以及不同于普通Reporting service的相关注意事项. 一.CRM报表简介 报表有两种,SQL-based报表和Fetch-b ...

  4. Dynamic CRM 2013学习笔记(十)客户端几种查询数据方式比较

    我们经常要在客户端进行数据查询,下面分别比较常用的几种查询方式:XMLHttpRequest, SDK.JQuery, SDK.Rest. XMLHttpRequest是最基本的调用方式,JQuery ...

  5. Dynamic CRM 2013学习笔记(十六)用JS控制Tab可见,可用

    一个Form里经常会有好几个Tab,有时要根据一些条件设置哪些Tab可用,可见.下面就介绍下如何用JS对Tab进行控制. 1. 控制可见   function setTabVisableByName( ...

  6. Dynamic CRM 2013学习笔记(十八)根据主表状态用JS控制子表自定义按钮

    有时要根据主表的审批状态来控制子表上的按钮要不要显示,比如我们有一个需求审批通过后就不能再上传文件了. 首先打开Visual Ribbon Editor, 如下图,我们可以利用Enable Rules ...

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

    CRM的项目,审批流是一个必须品.为了更方便灵活地使用.配置审批流,我们自定义了一整套审批流.首先来看下它的效果: 1. 审批模板 这是一个最简单的审批流,首先指定审批实体,及相关字段,再配置流程节点 ...

  8. Dynamic CRM 2013学习笔记(二十)字段改变事件的二种实现方法

    CRM里有二种方式实现字段change事件,一种是在form里,一种完全通过js来实现.本文介绍下二者的用途及区别. 1. Form里用法 这种方式估计其实也是添加一个js的function. 这种方 ...

  9. Dynamic CRM 2013学习笔记(二十五)JS调用web service 实现多条记录复制(克隆)功能

    前面介绍过如何克隆一条当前的记录: Dynamic CRM 2013学习笔记(十四)复制/克隆记录 , 主要是通过界面上加一个字段,单击form上的clone 按钮时,改变这个字段的值以触发插件来实现 ...

随机推荐

  1. MySQL日期数据类型、时间类型使用总结

    MySQL日期数据类型.时间类型使用总结 MySQL日期数据类型.MySQL时间类型使用总结,需要的朋友可以参考下.   MySQL 日期类型:日期格式.所占存储空间.日期范围 比较. 日期类型    ...

  2. fis3安装

    主要安装过程参考官网:http://fis.baidu.com/fis3/docs/beginning/install.html 这里记录安装fis3时遇到的一些问题: 1.npm install - ...

  3. sublime好看的主题webstrom破解

    http://equinusocio.github.io/material-theme/ sublime jsDoc注释 Doc Blockr webstrom破解 http://15.idea.la ...

  4. System.DateTime.Now的内容

    ?System.DateTime.Now{2016/10/09 15:19:12}    Date: {2016/10/09 0:00:00}    dateData: 985948826838121 ...

  5. JavaWeb总结--Servlet 工作原理解析

    从 Servlet 容器说起 要介绍 Servlet 必须要先把 Servlet 容器说清楚,Servlet 与 Servlet 容器的关系有点像枪和子弹的关系,枪是为子弹而生,而子弹又让枪有了杀伤力 ...

  6. VC++ chap12 file

    file operation _______C语言对文件操作的支持 fopen accepts paths that are valid on the file system at the point ...

  7. SQL SERVER 批量插入记录

    --create function insertData(@count as int,@tsn as bigint,@id as int) --as --begin SET IDENTITY_INSE ...

  8. poj 2987 最大权闭合图

    Language: Default Firing Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 8744   Accept ...

  9. computer repair services in Hangzhou

    We provide support for all kinds of Windows based Desktops and Laptops all over Hangzhou,I will be i ...

  10. 第1章 C#类型基础

    1.1值类型和引用类型 1.1.1 值类型 使用值类型之前需要对值类型的所有元素初始化(普通值类型和结构体). 结构还有一个特性:调用结构上的方法前,需要对其所有的字段进行赋值,为了避免对结构体中所有 ...