背景

经常有某个汇总子表的数量到主表的总数量,或者汇总子表的总价到主表的总价这种需求。

传统的做法:

1、就是为每个子表实体单独写成一个插件,但是这样不好复用。

2、主表的汇总字段是汇总货币类型,但是不能实时计算,得手动在页面上重新计算,如下图,点刷新才会触发计算

这里有幸阅读了网上一位前辈【疯吻IT】4年前写的文章,继承了他的思路实现了增删改重新触发汇总子表的某个字段到主表某个字段上。

效果图:

话不多说,上代码。

#region << 版 本 注 释 >>
/*----------------------------------------------------------------
* 项目名称 :Vyung.CRM.Plugins.Plugin
* 项目描述 :
* 类 名 称 :SumSub2Head
* 类 描 述 :将子表的字段合计到头表的某个字段
* 增删改实时触发头表汇总字段更新
* 所在的域 :cangfeng-PC
* 命名空间 :Vyung.CRM.Plugins.Plugin
* 机器名称 :CANGFENG-PC
* CLR 版本 :4.0.30319.42000
* 作 者 :cangfeng
* 创建时间 :2018/11/28 13:23:28
* 更新时间 :2018/11/28 13:23:28
* 版 本 号 :v1.0.0.0
*******************************************************************
* Copyright @ cangfeng 2018. All rights reserved.
*******************************************************************
//----------------------------------------------------------------*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Vyung.CRM.Plugins.Common; namespace Vyung.CRM.Plugins.Plugin
{ public class SumSub2Head : IPlugin
{
//第一个参数是要被合计的子表字段,第二个参数是主表的主健,第三个参数是主表实体名,第四个参数是主表上显示合计值的字段。
//new_amounts,new_originalorderid,new_originalorder,new_totalamount
public static string unsecure = "";
public SumSub2Head(string unsecureConfig, string secureConfig)
{
if (String.IsNullOrWhiteSpace(unsecureConfig) ||
String.IsNullOrWhiteSpace(unsecureConfig))
{
throw new InvalidPluginExecutionException("Unsecure and secure strings are required for this plugin to execute.");
} unsecure = unsecureConfig;
}
public void Execute(IServiceProvider serviceProvider)
{
#region 上下文实体信息初始化
ITracingService tracingservice = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
IOrganizationService serviceAdmin = serviceFactory.CreateOrganizationService(null);
bool isCreate = context.MessageName == "Create";
bool isUpdate = context.MessageName == "Update";
bool isDelete = context.MessageName == "Delete";
Entity target = null;
EntityReference targetref = null; //当前的实体
Entity m_CurrentEntity = null; if (context.InputParameters.Contains("Target"))
{
if (context.InputParameters["Target"] is Entity)
target = (Entity)context.InputParameters["Target"];
else if (context.InputParameters["Target"] is EntityReference)
targetref = (EntityReference)context.InputParameters["Target"];
}
Guid entityId;
string logicalName;
if (target == null)
{
entityId = targetref.Id;
logicalName = targetref.LogicalName;
}
else
{
entityId = target.Id;
logicalName = target.LogicalName;
}
#endregion #region 基本实体信息初始化
Entity preEntity = null;
Entity postEntity = null; if (context.PreEntityImages.Contains("PreImage") && context.PreEntityImages["PreImage"] != null)
{
preEntity = context.PreEntityImages["PreImage"];
}
if (context.PostEntityImages.Contains("PostImage") && context.PostEntityImages["PostImage"] != null)
{
postEntity = context.PostEntityImages["PostImage"];
}
int intStage = context.Stage;
#endregion try
{
//第一个参数是要被合计的子表字段,第二个参数是主表的主健,第三个参数是主表实体名,第四个参数是主表上显示合计值的字段。
//new_amounts,new_originalorderid,new_originalorder,new_totalamount
var param = unsecure.Split(','); #region 前期事件
if (intStage == 10 || intStage == 20)
{
#region 创建事件
if (isCreate)
{ }
#endregion #region 更新事件
if (isUpdate)
{ }
#endregion #region 删除事件
if (isDelete)
{ }
#endregion }
#endregion #region 后期事件给m_CurrentEntity赋值
else
{
#region 创建事件
if (isCreate)
{
m_CurrentEntity = target;
}
#endregion #region 更新事件
if (isUpdate)
{ //m_CurrentEntity = (Entity)context.InputParameters["Target"];
m_CurrentEntity = target;
m_CurrentEntity[param[1]] = preEntity[param[1]]; }
#endregion #region 删除事件
if (isDelete)
{
//我擦,删除居然不是entity类型,坑人targetref
//EntityReference er = context.InputParameters["Target"] as EntityReference;
//m_CurrentEntity = new Entity(er.LogicalName);
//m_CurrentEntity.Id = er.Id;
//m_CurrentEntity[param[1]] = preEntity[param[1]]; m_CurrentEntity = new Entity(targetref.LogicalName);
m_CurrentEntity.Id = targetref.Id;
m_CurrentEntity[param[1]] = preEntity[param[1]];
}
#endregion
}
#endregion //获取当前记录的主表id,根据主表id使用Linq获取对应的其他明细记录的需要统计的字段。如:amount
OrganizationServiceContext svcContext = new OrganizationServiceContext(serviceAdmin);
var ents = svcContext.CreateQuery(m_CurrentEntity.LogicalName).Where(e => e[param[1]] == m_CurrentEntity[param[1]] && e[param[0]] != null).Select(e => e[param[0]]);
decimal amount = 0;
foreach (var ent in ents)
{
amount += Convert.ToDecimal(((Money)ent).Value);
} //根据当前记录的主表id,查出首条头记录
var primaryEnt = svcContext.CreateQuery(param[2]).Where(e => e[param[1]] == m_CurrentEntity[param[1]]).FirstOrDefault(); //给头的汇总字段赋值
if (primaryEnt != null)
{
primaryEnt[param[3]] = new Money(amount); //linq更新实体
svcContext.UpdateObject(primaryEnt);
svcContext.SaveChanges();
}
}
catch (Exception e)
{
throw new InvalidPluginExecutionException("错误:" + e.Message + "[" + this.GetType().ToString() + "]");
}
}
}
}

使用步骤:

1、准备好unsecureConfig字段,如下

//第一个参数是要被合计的子表字段,第二个参数是主表的主健,第三个参数是主表实体名,第四个参数是主表上显示合计值的字段。
//new_amounts,new_originalorderid,new_originalorder,new_totalamount

2、注册插件

3、注册步骤

create:

update:

update 的前镜像

delete:

delete的前镜像

Ok,插件写好之后,以后就只需要注册,并且在unsecureConfig配置好对应的汇总字段和表就OK了。

如果本文有帮助到你,就给个推荐吧O(∩_∩)O~

Microsoft Dynamics CRM 增删改子表汇总子表的某个字段到主表的某个字段(通用插件)的更多相关文章

  1. Microsoft Dynamics CRM 2011 当您在 大型数据集上执行 RetrieveMultiple 查询很慢的解决方法

    症状 当您在 Microsoft Dynamics CRM 2011 年大型数据集上执行 RetrieveMultiple 查询时,您会比较慢. 原因 发生此问题是因为大型数据集缓存 Retrieve ...

  2. Microsoft Dynamics CRM 2013 --选项集的多选

    由于从Microsoft Dynamics CRM 2011到Microsoft Dynamics CRM 2013,界面的风格发生了很大的变化 故原先在2011上开发的选项集多选在2013上面已经不 ...

  3. Microsoft Dynamics CRM 常用JS语法(已转成vs2017语法提示)

    背景 最近接触到Microsoft Dynamics CRM的开发.前端js是必不可少的部分,奈何没有一个语法提示,点不出来后续的语句. 在vscode上面搜索插件的时候发现,有一个大神写的插件htt ...

  4. Microsoft Dynamics CRM 分销行业解决方案

    Microsoft Dynamics CRM 分销行业解决方案 方案亮点 360度动态渠道信息管理 充分的客户细分 全面的业务代表考核指标 业务代表管理和能力建设 业务代表过程管理 业务代表费用管理 ...

  5. K2 BPM+Microsoft Dynamics CRM,妥妥的~

    啊~~~~七夕 ▼ 你比巴西少一xi 你比山西多四xi 对有情人来说今天就是情人节,对单身汪来说,今天就是个星期四. but,软件也是要秀恩爱的! ♥ 晒晒我家亲爱的CRM,它的全名叫Microsof ...

  6. 利用K2和Microsoft Dynamics CRM构建业务App的5大理由

    Microsoft Dynamics CRM提供了一个绝佳的客户关系管理平台,使您能够创建各种以客户为中心的解决方案.然而,通过将K2的企业业务流程功能与Microsoft Dynamics CRM相 ...

  7. 一、Microsoft Dynamics CRM 4.0 SDK概述

    Chapter 1. Microsoft Dynamics CRM 4.0 SDK Overview(SDK概述) You are probably reading this book because ...

  8. Dynamic CRM 2015学习笔记(6)没有足够的权限 - 您没有访问这些记录的权限。请联系 Microsoft Dynamics CRM 管理员

    我们经常遇到下面这种问题:没有足够的权限 - 您没有访问这些记录的权限.请联系 Microsoft Dynamics CRM 管理员.  下面将详细介绍下如何解决这种问题:进不了CRM系统:进了CRM ...

  9. Microsoft Dynamics CRM4.0 JScript 过滤lookup 出现 Microsoft Dynamics CRM 窗口无法打开,可能已被弹出窗口阻止程序所阻止。

    一.现象:JScript过滤lookup字段,选择lookup字段出现下图的情况: 出现:Microsoft Dynamics CRM 窗口无法打开,可能已被弹出窗口阻止程序所阻止.请将这台Micro ...

随机推荐

  1. Oracle中,时间的相关操作方法

    无论是DATE还是timestamp都可以进行加减操作.可以对当前日期加年.月.日.时.分.秒,操作不同的时间类型,有三种方法: 1 使用内置函数numtodsinterval增加小时,分钟和秒2 加 ...

  2. ngrep命令用法

    ngrep 是grep(在文本中搜索字符串的工具)的网络版,他力求更多的grep特征,用于搜寻指定的数据包.正由于安装ngrep需用到libpcap库, 所以支持大量的操作系统和网络协议.能识别TCP ...

  3. 【爬坑】Python 3.6 在 Socket 编程时出现类型错误 TypeError: a bytes-like object is required, not 'str'

    1. 问题描述 Python 3.6 在 Socket 编程时出现错误如下 Traceback (most recent call last): File "F:/share/IdeaPro ...

  4. DLL导出类避免地狱问题的完美解决方案

    DLL动态链接库是程序复用的重要方式,DLL可以导出函数,使函数被多个程序复用,DLL中的函数实现可以被修改而无需重新编译和连接使用该DLL的应用程序.作为一名面向对象的程序员,希望DLL可以导出类, ...

  5. 百度地图Key的设置方法

    一.为什么要设置百度Key 万能地图下载器提供了百度POI的下载功能,但由于本软件用户群极大,会导致一天之内访问量超出300万次以上而无法继续下载. 因此,当POI下载不成功能,用户可以自己申请百度地 ...

  6. NOIP模拟赛-2018.10.22

    模拟赛 今天第一节课是历史,当然是不可能上的,一来到机房发现今天高二考试... 老师说以后可能还要给高一考...那还不如现在跟着做好了,毕竟在学长学姐中垫底显得没那么丢人 这套题风格挺奇怪的...为什 ...

  7. Java POI单元格使用心得

    1: /** * Created by liuguangxin on 2018/5/16. * <p> * MergeRegion:表示excel中cell的信息,startRow与end ...

  8. PHP错误提示的关闭方法详解

    关闭PHP错误脚本提示是程序上线了必须做的一件事情,就是不管程序怎么报错我们都不能让错误日志在服务器上给大家看到,下面我来总结两种关闭PHP错误脚本提示的具体方法     最简单的办法就是直接在php ...

  9. git回答整理

    1.git常用命令 首先明确:git有工作区.暂存区.版本库,工作区是电脑里能看到的目录 创建仓库: git init newrepo,使用我们指定目录作为Git仓库(初始化后,会在newrepo目录 ...

  10. leetcode242—Valid Anagram

    Given two strings s and t , write a function to determine if t is an anagram of s. Example 1: Input: ...