审批通过后的单据,一般要对其进行控制,不能修改,不能添加,删除等,下面分别介绍下如何实现:

一、 禁止修改:

1. 主表控制,如果页面上审批状态为审批中或审批通过,就把整个页面都disable掉

  1: function controlReadonly() {
  2:     var status = Xrm.Page.data.entity.attributes.get("new_approval_status").getValue();
  3:     if (status == 2 || status == 3)//审批中或者审批通过
  4:     {
  5:         var controls = Xrm.Page.ui.controls.get();
  6:         for (var i in controls) {
  7:             var control = controls[i];
  8:             control.setDisabled(true);
  9:         }
 10:     }
 11: }

2. 子表控制, 如果有子表,也要让其不能修改

首先查找主表的approval status,如果是审批中或审批通过就disable整个子表

  1: function disableSubForm() {
  2:     var marketingPlan = Xrm.Page.getAttribute("new_marketing_planid").getValue();
  3:     if (marketingPlan != null) {
  4:         var filter = "new_marketing_planSet?$select=new_approval_status&$filter=new_marketing_planId eq guid'" + marketingPlan[0].id + "'";
  5:         var status = Query_ent(filter);
  6:         if (status != null && status.new_approval_status != null) {
  7:             if (status.new_approval_status.Value == 3 || status.new_approval_status.Value == 2) {
  8:                 controlReadOnly();
  9:             }
 10:         }
 11:     }
 12: }

二、禁止添加及删除子表记录

通过上面的js控制,页面上的所有字段确实被disable了,但子表的subgrid及子表页面上的添加及删除按钮没有被控制住。所以决定写一个通用的插件来控制添加及删除。
1. 下图显示了如何在主表上注册这个通用插件
 

这里 message为Delete,是对delete的控制;如果是Create,就要设置成post-operation,才能对添加进行控制。

重点是右边的Unsecure Configuration的配置:

  • 传入的条件

<filter type="or">
  <condition attribute="new_approval_status" operator="eq" value="2" />
  <condition attribute="new_approval_status" operator="eq" value="3" />
</filter>

  • 如果满足这个条件就报这个error

<check error="Cannot delete when approval status is approving or approved !">

2. 子表上注册

子表上没有approval status这个字段,这个字段只在主表上有,但又要依赖这个字段来控制子表,怎么办?

这时就要指定进行如下的配置了:

  1: <check error="Cannot delete sub-form when main form is approving or approved!">
  2:  <link-entity name="new_marketing_plan" to="new_marketing_planid">
  3:   <filter type="or">
  4:    <condition attribute="new_approval_status" operator="eq" value="" />
  5:    <condition attribute="new_approval_status" operator="eq" value="" />
  6:   </filter>
  7:  </link-entity>
  8: </check>
简单介绍下这里的配置,跟主表的配置相比,只是多了个link-entity:
<link-entity name="new_marketing_plan" to="new_marketing_planid">   
name指的是主表的实体, to指的是子表中link到主表实体的字段
 

三、 技术实现

1. 通过一个参数的构造函数来读取unsecure configuration里的配置
  1: public EntityCheck(string unsecure)
  2: {
  3:     m_Config = unsecure;
  4: }
Microsoft Dynamics CRM 平台支持可选的插件构造函数,该函数接受一个或两个字符串参数。如果编写此类构造函数,则可以在运行时向插件传递任何信息字符串。
以下示例显示构造函数的格式。在此示例中,插件类名为 SamplePlugin。
public SamplePlugin()
public SamplePlugin(string unsecure)
public SamplePlugin(string unsecure, string secure)

构造函数的第一个字符串参数包含公共(不安全)信息。第二个字符串参数包含非公共(安全)信息。在这里,安全是指加密的值,而不安全是指未加密的值。如果使用带脱机访问功能的 Microsoft Dynamics CRM for Microsoft Office Outlook,则 CRM for Outlook 脱机时安全字符串不会传递到执行的插件。

在这些字符串中传递到插件构造函数的信息是在 Microsoft Dynamics CRM 中注册插件时指定的。使用插件注册工具注册插件时,可以在“注册新步骤”窗体提供的“安全配置”和“不安全配置”字段中输入安全信息和不安全信息。使用 Microsoft Dynamics CRM SDK 以编程方式注册插件时,SdkMessageProcessingStep.Configuration 包含不安全的值,SdkMessageProcessingStep.SecureConfigId 引用包含安全值的 SdkMessageProcessingStepSecureConfig 记录。

 
2. 读取link-entity
  1: XmlNodeList linkEntityNodeList = linkEntityNode.SelectNodes("link-entity");
  2: if (linkEntityNodeList != null)
  3: {
  4:     foreach (XmlNode subLinkEntityNode in linkEntityNodeList)
  5:     {
  6:         LinkEntity subLe = GetLinkEntity(subLinkEntityNode);
  7:         le.LinkEntities.Add(subLe);
  8:     }
  9: }
 
3. 从config里读取filter
  1: XmlNodeList filterNodeList = linkEntityNode.SelectNodes("filter");
  2: if (filterNodeList != null)
  3: {
  4:     foreach (XmlNode filterNode in filterNodeList)
  5:     {
  6:         FilterExpression filter = this.GetFilter(filterNode);
  7:
  8:         le.LinkCriteria.AddFilter(filter);
  9:     }
 10: }
 
4. 从config里读取condition
  1: XmlNodeList conditionNodeList = linkEntityNode.SelectNodes("condition");
  2: if (conditionNodeList != null)
  3: {
  4:     foreach (XmlNode conditionNode in conditionNodeList)
  5:     {
  6:         ConditionExpression condition = this.GetCondition(conditionNode);
  7:
  8:         le.LinkCriteria.AddCondition(condition);
  9:     }
 10: }
 
5. 最后合成一个QueryExpression对象,传入到RetrieveMultiple方法,进行查询,如果有记录存在,就抛出error:
  1: EntityCollection ec = AdminService.RetrieveMultiple(config.Query);
  2: if (ec != null && ec.Entities.Count > 0)
  3: {
  4:     throw new InvalidPluginExecutionException(config.Error);
  5: }

Dynamic CRM 2013学习笔记 系列汇总

Dynamic CRM 2013学习笔记(五)禁止修改、删除审批通过后的单据的更多相关文章

  1. Dynamic CRM 2013学习笔记(四十五)修改实体及字段的前缀(不用new_开头)

    最近做一个升级的CRM项目,为了区分哪些是新增的,所以决定用一个新的前缀来定义实体及新加的字段.之前用的是new_开头,现在改成tm_开头.   原来只要是新建实体或字段都是new_开头:   1. ...

  2. Dynamic CRM 2013学习笔记(三十五)自定义审批流6 - 审批通过后,再审批 - 二次审批

    最近有个特殊的需求,客户想做二次审批,就是审批通过后,再走一次审批流程.最开始一想,这还不简单,审批通过后,直接把状态改成draft就完了,后来一试,发现一堆问题,比如第一次审批完后,界面是不允许修改 ...

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

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

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

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

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

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

  6. Dynamic CRM 2013学习笔记(四十六)简单审批流的实现

    前面介绍过自定义审批流: Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示 Dynamic CRM 2013学习笔记(二十一)自定义审批流2 - 配置按钮 Dynamic ...

  7. Dynamic CRM 2013学习笔记(二)插件基本用法及调试

      插件是可与 Microsoft Dynamics CRM 2013 和 Microsoft Dynamics CRM Online 集成的自定义业务逻辑(代码),用于修改或增加平台的标准行为.也可 ...

  8. Dynamic CRM 2013学习笔记(十一)利用Javascript实现子表合计(汇总,求和)功能

    我们经常有这样一种需求,子表里新加或修改一数值后,要马上在主表里把它们的和显示在主表上.如果用插件来实现,可以实现求和,但页面上还要刷新一下才能显示正确.这时就考虑到用JS来实现这一功能,并自动刷新页 ...

  9. Dynamic CRM 2013学习笔记(二十六)报表设计:Reporting Service报表 动态参数、参数多选全选、动态列、动态显示行字体颜色

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

随机推荐

  1. 使用VisualVM监控远程服务器JVM

    VisualVM是JDK自带的一款全能型性能监控和故障分析工具,包括对CPU使用.JVM堆内存消耗.线程.类加载的实时监控,内存dump文件分析,垃圾回收运行情况的可视化分析等,对故障排查和性能调优很 ...

  2. 在本地机器上能访问tomcat,远程机器访问不了的解决方法

    问题描述:在测试服务器上搭建了一个tomcat,在测试服务器上能用ip打开tomcat.我用自己的机器能远程桌面能登录到测试服务器上,但在自己的机器上无法通过ip来访问测试服务器上的tomcat. 解 ...

  3. 移动端调试工具-Weinre

    java版本安装和调试 首先需要下载 weinre, weinre目前支持Windows与MacOS, 本文中以Windows版为例. 下载地址:http://people.apache.org/~p ...

  4. Android_layout 布局(一)

    今天主要学习了Android 的layout布局. Android layout 布局一般分为五种: LinearLayout (线性布局) :子组件按照垂直或者水平方向来布局. RelativeLa ...

  5. 在Eclipse上操作Hive-0.13.1-JDBC端口

    fesh个人实践,欢迎经验交流!本文Blog地址:http://www.cnblogs.com/fesh/p/3877740.html 完成<在Hadoop-2.2.0集群上安装 Hive-0. ...

  6. css3实现边框圆角样式

      基本语法: border-radius: 5px; 兼容大多数浏览器: /*兼容Mozilla(Firefox, Flock等浏览器)*/ -moz-border-radius-topleft: ...

  7. iOS 发送Email

    第一步:在程序中添加MessageUi.framework框架 第二步:引入#import <MessageUI/MessageUI.h>头文件 第三步:代码实现 3.1判断是否可以发送邮 ...

  8. UVA 11624 Fire!(广度优先搜索)

    题目大意:在一个N*M的迷宫内,J代表某人(只有一个),F代表火(可能不只一个),#代表墙,火每分钟会向四周除了墙以外的地方扩散一层,问人能否在没被火烧到 之前逃出迷宫,若能逃出输出最短时间.很明显的 ...

  9. java核心知识点学习----重点学习线程池ThreadPool

    线程池是多线程学习中需要重点掌握的. 系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互.在这种情形下,使用线程池可以很好的提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考 ...

  10. 最近写了一个红包雨的小功能,但感觉自己的js还有很多地方可以提高,望大神们可以帮忙指点一二

    js部分 'use strict'; function RedEnvelope(options){ if(this === window){ return new RedEnvelope(option ...