Requirement :
Prevent Users to Mark Complete or Close the Task if "Owner" of the
Task is not the "Created by" of the Task using Plug-in in Dynamics CRM
2011.
On
Click of Mark Complete on Ribbon button from anywhere in CRM Webpage
(Form, Subgrid, HomeGrid), if the Task "Owner" is not Same as Task
"Created By" then Owner should be prevented from Mark the Task Complete
or Close with a User Friendly Message and and also a custom field on
Task form called "Able to Mark complete" if the value of the Check box
is true (Yes) then to override this requirement, i mean user can Mark
Complete or Close.
Implementation:
First
Create a Javascript to control the enabling and disabling of "Able to
Mark complete" field on the Update form of Task. This field will be
enabled for Creator of the Task on Create or Update form, but if the
Owner of the Task is not the Creator of the Task then this field should
be prevented to update on Update form of Task entity. Here is the
JavaScript code to do so (I am avoiding the step to Add the JavaScript
as web-resource and Attaching the code to Task form).
function DisableAbleToCompleteField()
{
var formType = Xrm.Page.ui.getFormType();
if (formType == 2)
{
var userid = Xrm.Page.context.getUserId();
var creatorlookup = Xrm.Page.getAttribute(" createdby");
if (creatorlookup!= null)
{
var creatorlookupvalue = creatorlookup .getValue();
if (creatorlookupvalue != null)
{
var creatorid = creatorlookupvalue[0].id;
}
}
if (userid == creatorid)
Xrm.Page.getControl("new_ abletomarkcomplete"). setDisabled(false);
else
Xrm.Page.getControl("new_ abletomarkcomplete"). setDisabled(true);
} else
Xrm.Page.getControl("new_ abletomarkcomplete"). setDisabled(false);
}
The Complete Code for the Plug-in to prevent an Owner to Mark Complete or Close the Task:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Diagnostics;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.CSharp;
using System.Data;
using System.Runtime.Serialization;
using Microsoft.Crm.Sdk.Messages;
namespace TaskClosurePermissionPlugin
{
public class TaskClosure : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
if (context.PrimaryEntityName == "task")
{
if (context.InputParameters.Contains("EntityMoniker") && context.InputParameters["EntityMoniker"] is EntityReference && context.Depth < 2)
{
if (context.PreEntityImages.Contains("PreImage"))
{
Entity taskentity = (Entity)context.PreEntityImages["PreImage"];
EntityReference owneridLookup = (EntityReference)taskentity.Attributes["ownerid"];
EntityReference createdbyLookup = (EntityReference)taskentity.Attributes["createdby"];
if (owneridLookup.Id != createdbyLookup.Id)
{
if (taskentity.Contains("new_abletomarkcomplete") && !taskentity.GetAttributeValue<bool>("new_abletomarkcomplete"))
{
throw new InvalidPluginExecutionException("This Task is Created by : "+createdbyLookup.Name+" , User : "+owneridLookup.Name +" is not allowed to Mark Complete or Close the Task.");
}
}
}
}
else
{
throw new InvalidPluginExecutionException("Activity should be Task.");
}
}
}
}
}
The Plugin has to use Pre-Image to compare the values of the fields before transaction happens in the Database.
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Diagnostics;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.CSharp;
using System.Data;
using System.Runtime.Serialization;
using Microsoft.Crm.Sdk.Messages;
namespace TaskClosurePermissionPlugin
{
public class TaskClosure : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
if (context.PrimaryEntityName == "task")
{
if (context.InputParameters.Contains("EntityMoniker") && context.InputParameters["EntityMoniker"] is EntityReference && context.Depth < 2)
{
if (context.PreEntityImages.Contains("PreImage"))
{
Entity taskentity = (Entity)context.PreEntityImages["PreImage"];
EntityReference owneridLookup = (EntityReference)taskentity.Attributes["ownerid"];
EntityReference createdbyLookup = (EntityReference)taskentity.Attributes["createdby"];
if (owneridLookup.Id != createdbyLookup.Id)
{
if (taskentity.Contains("new_abletomarkcomplete") && !taskentity.GetAttributeValue<bool>("new_abletomarkcomplete"))
{
throw new InvalidPluginExecutionException("This Task is Created by : "+createdbyLookup.Name+" , User : "+owneridLookup.Name +" is not allowed to Mark Complete or Close the Task.");
}
}
}
}
else
{
throw new InvalidPluginExecutionException("Activity should be Task.");
}
}
}
}
}
The Plugin has to use Pre-Image to compare the values of the fields before transaction happens in the Database.
Now the Registration Process of Plug-in:
Open the Plugin registration Tool, Select your Organization, Log as Admin user (Or if any user has granted permission).
1. Register New Assembly by browsing your dll.
2. You have to Register steps for the plugin on SetState and SetStateDynamicEntity both steps.
3. Register Pre-Image for both Steps.
Once done, you are now Ok to test your business scenario,
Following
are the screen shots, on Single Task and Multiple Tasks Closure Process
from the CRM Landing Page (In My case Dashboard):
Single Task Selected:
Once done, you are now Ok to test your business scenario,
Following
are the screen shots, on Single Task and Multiple Tasks Closure Process
from the CRM Landing Page (In My case Dashboard):
Single Task Selected:
Once done, you are now Ok to test your business scenario,
Following
are the screen shots, on Single Task and Multiple Tasks Closure Process
from the CRM Landing Page (In My case Dashboard):
Single Task Selected: