Dynamic CRM 2013学习笔记(三十五)自定义审批流6 - 审批通过后,再审批 - 二次审批
最近有个特殊的需求,客户想做二次审批,就是审批通过后,再走一次审批流程。最开始一想,这还不简单,审批通过后,直接把状态改成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 - 审批通过后,再审批 - 二次审批的更多相关文章
- Dynamic CRM 2013学习笔记(十五)报表设计:报表入门、开发工具及注意事项
本文是关于CRM 2013报表开发入门介绍,包括开发工具的使用,以及不同于普通Reporting service的相关注意事项. 一.CRM报表简介 报表有两种,SQL-based报表和Fetch-b ...
- Dynamic CRM 2013学习笔记(十二)实现子表合计(汇总,求和)功能的通用插件
上一篇 Dynamic CRM 2013学习笔记(十一)利用Javascript实现子表合计(汇总,求和)功能 , 介绍了如何用js来实现子表合计功能,这种方法要求在各个表单上添加js方法,如果有很多 ...
- Dynamic CRM 2013学习笔记(十四)复制/克隆记录
经常有这样的需求,一个单据上有太多要填写的内容,有时还关联多个子单据,客户不想一个一个地填写,他们想从已有的单据上复制数据,克隆成一条新的记录.本文将介绍如何克隆一条记录,包括它的子单据以生成一条新的 ...
- Dynamic CRM 2013学习笔记(十)客户端几种查询数据方式比较
我们经常要在客户端进行数据查询,下面分别比较常用的几种查询方式:XMLHttpRequest, SDK.JQuery, SDK.Rest. XMLHttpRequest是最基本的调用方式,JQuery ...
- Dynamic CRM 2013学习笔记(十六)用JS控制Tab可见,可用
一个Form里经常会有好几个Tab,有时要根据一些条件设置哪些Tab可用,可见.下面就介绍下如何用JS对Tab进行控制. 1. 控制可见 function setTabVisableByName( ...
- Dynamic CRM 2013学习笔记(十八)根据主表状态用JS控制子表自定义按钮
有时要根据主表的审批状态来控制子表上的按钮要不要显示,比如我们有一个需求审批通过后就不能再上传文件了. 首先打开Visual Ribbon Editor, 如下图,我们可以利用Enable Rules ...
- Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示
CRM的项目,审批流是一个必须品.为了更方便灵活地使用.配置审批流,我们自定义了一整套审批流.首先来看下它的效果: 1. 审批模板 这是一个最简单的审批流,首先指定审批实体,及相关字段,再配置流程节点 ...
- Dynamic CRM 2013学习笔记(二十六)报表设计:Reporting Service报表 动态参数、参数多选全选、动态列、动态显示行字体颜色
上次介绍过CRM里开始报表的一些注意事项:Dynamic CRM 2013学习笔记(十五)报表入门.开发工具及注意事项,本文继续介绍报表里的一些动态效果:动态显示参数,参数是从数据库里查询出来的:参数 ...
- Dynamic CRM 2013学习笔记(二十九)报表设计:reporting service 报表开发常见问题
在报表开发过程中,经常会遇到各种各样的问题,比如The report cannot be displayed. (rsProcessingAborted),一点有意义的提示都没有:再就是分页问题,经常 ...
- Dynamic CRM 2013学习笔记 系列汇总
这里列出所有 Dynamic CRM 2013学习笔记 系列文章,方便大家查阅.有任何建议.意见.需要,欢迎大家提交评论一起讨论. 本文原文地址: Dynamic CRM 2013学习笔记 系列汇总 ...
随机推荐
- 控件的相对位置与绝对位置-UI界面编辑器(SkinStudio)教程
绝对位置: 相对位置: 相对位置配合Anchor属性使用 例如Anchor属性选择left|top(即相对位置的left和top保持不变) 窗口大小改变前: 窗口大小改变后: 可以看到控件相对位置的l ...
- tdd 和 make file,以及cygwin
等我把这本书看完,好好总结一下. 还要把以前的博客文字整理一下
- scala 学习心得
scala 安装步骤 文件下载地址:www.scala-lang.org(Please report bugs at https://issues.scala-lang.org/. We welcom ...
- redis配置认证密码
redis配置密码1.通过配置文件进行配置yum方式安装的redis配置文件通常在/etc/redis.conf中,打开配置文件找到 #requirepass foobared 去掉行前的注释,并修改 ...
- 图表Echarts的使用
Echarts是一个纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表. 本文内容为讲解使用ECharts3.x版本绘制中国地图统计信息. 基本步骤: 1.下载ec ...
- MATLAB - 练习程序,求灰度图像均值、最大、最小数值
clear all; close all; clc img=imread('lena.bmp'); figure; imshow(uint8(img)); [m n]=size(img); img_m ...
- 如何将PHP对象数组转换成普通数组
/** * 对象数组转为普通数组 * * AJAX提交到后台的JSON字串经decode解码后为一个对象数组, * 为此必须转为普通数组后才能进行后续处理, * 此函数支持多维数组处理. * * @p ...
- Scrum Meeting (Oct. 27 2014)
软件工程是一门十分有意思的课程,它不仅锻炼了我们开发软件的能力,更是给了我们结队作业的机会,在团队协作中,我们学会了欣赏别人,学会了品鉴自己,学会了如何集思广益凝聚成一个锐意进取的集体.继单人单词查询 ...
- Linux内核同步机制--转发自蜗窝科技
Linux内核同步机制之(一):原子操作 http://www.wowotech.net/linux_kenrel/atomic.html 一.源由 我们的程序逻辑经常遇到这样的操作序列: 1.读一个 ...
- Android--多线程之Handler(转)
前言 Android的消息传递机制是另外一种形式的“事件处理”,这种机制主要是为了解决Android应用中多线程的问题,在Android中不 允许Activity新启动的线程访问该Activity里的 ...