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);
}
}
[置顶]Dynamic CRM 2013学习笔记 系列汇总 -- 持续更新中
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?