最近有个特殊的需求,客户想做二次审批,就是审批通过后,再走一次审批流程。最开始一想,这还不简单,审批通过后,直接把状态改成draft就完了,后来一试,发现一堆问题,比如第一次审批完后,界面是不允许修改的,直接改成draft就又可以修改了;再比如审批活动记录的查找以及死循环的问题等等。于是自己动手单独写了一个公用的再审批插件,下面介绍详细的实现步骤:

 

一、添加字段以控制再审批的次数

添加一个字段 new_approval_count, 再审批一次就把它加1。如果只要再审批一次,那么大于1就退出。

 

二、获取模板
                    ApproveTempleteHelper templetehelper = new ApproveTempleteHelper();
                    Entity approveTempleteEntity = templetehelper.GetApproveTemplete(service, importCurrentEntity.LogicalName);

/// <summary>
/// 获取审批模板
/// </summary>
/// <param name="service"></param>
/// <param name="entityName"></param>
/// <returns></returns>
public Entity GetApproveTemplete(IOrganizationService service, string entityName)
{
try
{
QueryExpression query = new QueryExpression(); query.EntityName = ApproveTempleteSchemaName;
query.ColumnSet.AllColumns = true; query.Criteria = new FilterExpression();
query.Criteria.FilterOperator = LogicalOperator.And; ConditionExpression condition1 = new ConditionExpression();
condition1.AttributeName = ApproveTempleteEntityNameSchemaName;
condition1.Operator = ConditionOperator.Equal;
condition1.Values.Add(entityName);
query.Criteria.AddCondition(condition1); ConditionExpression condition2 = new ConditionExpression();
condition2.AttributeName = StateCodeSchemaName;
condition2.Operator = ConditionOperator.Equal;
condition2.Values.Add(0);
query.Criteria.AddCondition(condition2); ConditionExpression condition3 = new ConditionExpression();
condition3.AttributeName = ApproveTempleteDefaultFlagSchemaName;
condition3.Operator = ConditionOperator.Equal;
condition3.Values.Add(true);
query.Criteria.AddCondition(condition3); EntityCollection results = service.RetrieveMultiple(query);
if (results.Entities.Count > 0)
{
return results.Entities[0];
}
else
{
//throw new Exception("没有为该实体定义默认的审批工作流。");
throw new Exception("No custom default approval workflow for current entity");
}
}
catch (Exception ex)
{
throw new Exception(MethodBase.GetCurrentMethod().Name + " " + ex.Message);
}
}

 

三、获取节点

                   ApproveTempleteNodeHelper nodehelper = new ApproveTempleteNodeHelper();

                    Entity approveNode = nodehelper.GetBeginNodeEntity(service, (Guid)approveTempleteEntity["crm_approve_templeteid"]);

/// <summary>
/// 获取开始节点
/// </summary>
/// <param name="service"></param>
/// <returns></returns>
public Entity GetBeginNodeEntity(IOrganizationService service, Guid templeteId)
{
try
{
QueryExpression query = new QueryExpression(); query.EntityName = TempleteNodeSchemaName;
query.ColumnSet.AllColumns = true; query.Criteria = new FilterExpression();
query.Criteria.FilterOperator = LogicalOperator.And; ConditionExpression condition1 = new ConditionExpression();
condition1.AttributeName = TempleteNodeClassSchemaName;
condition1.Operator = ConditionOperator.Equal;
condition1.Values.Add(0);
query.Criteria.AddCondition(condition1); ConditionExpression condition2 = new ConditionExpression();
condition2.AttributeName = StateCodeSchemaName;
condition2.Operator = ConditionOperator.Equal;
condition2.Values.Add(0);
query.Criteria.AddCondition(condition2); ConditionExpression condition3 = new ConditionExpression();
condition3.AttributeName = TempleteIDSchemaName;
condition3.Operator = ConditionOperator.Equal;
condition3.Values.Add(templeteId);
query.Criteria.AddCondition(condition3); EntityCollection results = service.RetrieveMultiple(query); if (results.Entities.Count > 0)
{
return results.Entities[0];
}
else
{
//throw new Exception("没有未改实体定义开始节点。");
throw new Exception("No begin activity");
}
}
catch (Exception ex)
{
throw new Exception(MethodBase.GetCurrentMethod().Name + " " + ex.Message);
}
}

 

四、创建Instance

                    ApproveInstanceHelper instanceHelper = new ApproveInstanceHelper();

                    Guid instanceId = instanceHelper.CreateApproveInstance(service, approveTempleteEntity, billEntityReference);

                    EntityReference instanceReference = new EntityReference(ApproveInstanceSchemaName, instanceId);

/// <summary>
/// 创建流程实例
/// </summary>
/// <param name="service"></param>
/// <param name="templeteEntity"></param>
/// <param name="subject"></param>
/// <param name="billEntity"></param>
/// <returns></returns>
public Guid CreateApproveInstance(IOrganizationService service, Entity templeteEntity, EntityReference billEntityReference)
{
try
{
Entity instance = new Entity(ApproveInstanceSchemaName); instance[ApproveInstanceTempleteIdSchemaName] = new EntityReference(templeteEntity.LogicalName, (Guid)templeteEntity[templeteEntity.LogicalName + "id"]);
instance[ApproveInstanceEntityNameSchemaName] = billEntityReference.LogicalName;
//EntityReference ef = new EntityReference(billEntity.LogicalName, (Guid)templeteEntity[billEntity.LogicalName + "id"]);
instance[ApproveInstanceBillObjectSchemaName] = billEntityReference;
instance[ApproveInstancecrmSubjectSchemaName] = DateTime.Now.ToString() + "流程实例";
instance[ApproveInstanceSubjectSchemaName] = DateTime.Now.ToString() + "流程实例";
return service.Create(instance);
}
catch (Exception ex)
{
throw new Exception(MethodBase.GetCurrentMethod().Name + " " + ex.Message);
}
}

 

五、更新业务表Instance

                    BillHelper billHelper = new BillHelper();

                    billHelper.SetBillWFInstance(service, importCurrentEntity, instanceReference, (string)approveTempleteEntity["crm_wf_instanceid_field"], "new_approval_count", iCount);

/// <summary>
/// 修改业务单据状态
/// </summary>
/// <param name="service"></param>
/// <param name="billEntity"></param>
/// <param name="instanceRefence"></param>
/// <param name="instanceField"></param>
public void SetBillWFInstance(IOrganizationService service, Entity billEntity, EntityReference instanceRefence, string instanceField, string sField, int sValue)
{
try
{
billEntity[sField] = Convert.ToDecimal(sValue); //审批计数
billEntity[instanceField] = instanceRefence;
service.Update(billEntity);
}
catch (Exception ex)
{
throw new Exception(MethodBase.GetCurrentMethod().Name + " " + ex.Message);
}
}

 

六、创建审批活动

                    CreateApproveActivityHelper helper = new CreateApproveActivityHelper();

                    helper.CreateBeginApproveActivity(service, approveTempleteEntity, approveNode, currentEntity, instanceReference, context.UserId, owner);

/// <summary>
/// 创建第一个审批活动
/// </summary>
/// <param name="service"></param>
/// <param name="approveTemplete"></param>
/// <param name="approveNode"></param>
/// <param name="billEntity"></param>
public void CreateBeginApproveActivity(IOrganizationService service, Entity approveTemplete, Entity approveNode, Entity billEntity, EntityReference instanceReference, Guid userid, EntityReference owner)
{
try
{
//获取下一个审批节点
ApproveTempleteNodeHelper nodeHelper = new ApproveTempleteNodeHelper();
ApproveNode BeginApproveNode = nodeHelper.GetApproveNode(approveNode);
BeginApproveNode.CallBackValue = 3; //change to draft awen
EntityReference billEntityReference = new EntityReference(billEntity.LogicalName, (Guid)billEntity[billEntity.LogicalName + "id"]);
BeginApproveNode.BillEntityReference = billEntityReference;
EntityReference approveNodeReference = new EntityReference(approveNode.LogicalName, (Guid)approveNode[approveNode.LogicalName + "id"]);
EntityReference approveTempleteReference = new EntityReference(approveTemplete.LogicalName, (Guid)approveTemplete[approveTemplete.LogicalName + "id"]); //更改业务单据中的状态
nodeHelper.ChangeBillStatus(service, BeginApproveNode, billEntity); string subjectField = "";
if (approveTemplete.Attributes.Keys.Contains(ApproveTempleteSubjectFieldSchemaName))
{
subjectField = (string)approveTemplete[ApproveTempleteSubjectFieldSchemaName];
} //主题
string subject = GetApproveActivitySuject(service, billEntityReference.LogicalName, subjectField, billEntityReference.Id); EntityReference userReference = new EntityReference("systemuser", userid); CreateApproveActivity(service, subject, billEntityReference, userReference, approveNodeReference, approveTempleteReference, instanceReference, 3, true, owner); }
catch (Exception ex)
{
throw new Exception(MethodBase.GetCurrentMethod().Name + " " + ex.Message);
}
}

 

最后记得注册这个插件时,要在step里加上一个image:

 

 

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

Dynamic CRM 2013学习笔记(三十五)自定义审批流6 - 审批通过后,再审批 - 二次审批的更多相关文章

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

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

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

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

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

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

  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学习笔记(二十六)报表设计:Reporting Service报表 动态参数、参数多选全选、动态列、动态显示行字体颜色

    上次介绍过CRM里开始报表的一些注意事项:Dynamic CRM 2013学习笔记(十五)报表入门.开发工具及注意事项,本文继续介绍报表里的一些动态效果:动态显示参数,参数是从数据库里查询出来的:参数 ...

  9. Dynamic CRM 2013学习笔记(二十九)报表设计:reporting service 报表开发常见问题

    在报表开发过程中,经常会遇到各种各样的问题,比如The report cannot be displayed. (rsProcessingAborted),一点有意义的提示都没有:再就是分页问题,经常 ...

  10. Dynamic CRM 2013学习笔记 系列汇总

    这里列出所有 Dynamic CRM 2013学习笔记 系列文章,方便大家查阅.有任何建议.意见.需要,欢迎大家提交评论一起讨论. 本文原文地址: Dynamic CRM 2013学习笔记 系列汇总 ...

随机推荐

  1. PLSQL在64位系统连接不上32位的服务器

    1 主要是因为PLSQL只能接纳32位的客户端 2 下载oracle32位客户端 http://www.oracle.com/technetwork/topics/winsoft-085727.htm ...

  2. Egret Wing3 FTP使用方法

    FTP 挺实用的,不用自己去申请sinasea什么的免费空间来测试项目了. 添加FTP服务器配置 默认就行. 指定目录上传至FTP服务器 选择免费云测试空间.然后选择bin-release/web目录 ...

  3. Android之使用Android-AQuery异步加载图片(一)

    第一节:转载地址(http://www.cnblogs.com/lee0oo0/archive/2012/10/25/2738299.html) // 必须实现AQuery这个类 AQuery aq ...

  4. ORA-01720: grant option does not exist for 'xxx.xxxx' (ORA-01720 ‘XXX’ 不存在授权选项)

    原因:用户A将表tab的SELECT权限授予了用户B,而用户B将视图v_tab的查询权限授予C时,也试图将表tab授予用户C,但用户B并没有这个权限(将表tab授予用户C),而引起的 用户B没有授权选 ...

  5. git push throws error: RPC failed; result=22, HTTP code = 411的解决办法

    原因:默认 Git 设置 http post 的缓存为 1MB,将其设置为 500MB 解决办法如下: git config http.postBuffer 524288000

  6. setTimeout注意事项

    <script type="text/javascript">     function  show(v){        alert(v);    }    func ...

  7. Java NIO教程 前言

    阅读本文前,建议你先了解 旧I/O NIO 是 New I/O 的缩写,要了解它真正的内涵,需要掌握的知识还是比较多的.我努力在这几篇笔记里,勾勒出整个io的面貌.为大家的深入学习铺路. I/O简史 ...

  8. Java NIO教程 Channel

    Channel是一个连接到数据源的通道.程序不能直接用Channel中的数据,必须让Channel与BtyeBuffer交互数据,才能使用Buffer中的数据. 我们用FileChannel作为引子, ...

  9. PLSQL数据导入导出问题解决(空表、大字段表、表空间错误等)

    PLSQL使用方法简单,平常使用较多,但在平常使用过程中,遇到一些问题,下面简单罗列并进行解决.这些解决方法大多通过网络查找获得,这里只是进行简单整理. 使用的数据库版本为:Oracle11g. 通用 ...

  10. 包含min函数的栈

    题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数 解法一: 思路:采用java中自带的迭代函数进行处理. public class Solution{ /** * @pa ...