Tuesday, August 16, 2011

Sum activities duration Dynamics crm 2011

Sum activities duration Dynamics crm 2011.

This is plugin that sums all completed activites into some custom entity.

Prerequests:
  1. Early binding class. (not a most but makes code writing easier)
    Early binding walkthrough link : http://dynamicslollipops.blogspot.com/2011/07/mscrm-2011-early-binding-plugin.htm

The Plugin code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using Xrm;
using System.ServiceModel;

namespace MSCRM2011Plugins
{
    public class SumActivityPlugin : IPlugin
    {

        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));

            try
            {
                IOrganizationServiceFactory serviceFactory =
                    (IOrganizationServiceFactory)serviceProvider.GetService(
                typeof(IOrganizationServiceFactory));
                IOrganizationService service =
                serviceFactory.CreateOrganizationService(context.UserId);

                XrmServiceContext xrm = new XrmServiceContext(service);
                
                // Extract the tracing service.
                ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
                if (tracingService == null){
                    throw new InvalidPluginExecutionException("Failed to retrieve the tracing service.");
                }
                Entity postEntity = null;
                Entity preEntity = null;
                if (context.PostEntityImages.Contains("MyImage"))
                {
                    postEntity = context.PostEntityImages["MyImage"];
                }
                if (context.PreEntityImages.Contains("MyImage"))
                {
                    preEntity = context.PreEntityImages["MyImage"];
                }
                tracingService.Trace("MeesageName = " + context.MessageName);
                if (context.MessageName.ToLower().Equals("delete"))
                {
                    tracingService.Trace("Completed activity was delete recalc total duration for project");
                    CalcProjectActivities(xrm, tracingService, preEntity);
                }
                else
                {
                    tracingService.Trace("calc project total duration");
                    //change state
                    CalcProjectActivities(xrm, tracingService, postEntity);
                }
            }
            catch (FaultException ex)
            {
                throw new InvalidPluginExecutionException(
                "An error occurred in the plug-in.", ex);
            }

        }

        private void CalcProjectActivities(XrmServiceContext xrm, ITracingService tracingService, Entity reldEntity)
        {
           // tracingService.Trace("Get activity");
           // ActivityPointer activity = xrm.ActivityPointerSet.FirstOrDefault(ac => ac.ActivityId == new Guid(reldEntity["activityid"].ToString()));
            tracingService.Trace("Get all related activities");
            IQueryable activities = xrm.ActivityPointerSet.Where(ac => ac.RegardingObjectId != null && ac.RegardingObjectId.Id == ((EntityReference)reldEntity["regardingobjectid"]).Id && ac.ActualDurationMinutes != null && ac.StateCode.Value == ActivityPointerState.Completed);
            if (activities != null)// && activity != null)
            {
                int totalSum = 0;
                foreach (var a in activities)
                {
                    totalSum += a.ActualDurationMinutes.Value;
                }
                ActivityPointer activity = activities.FirstOrDefault();
                tracingService.Trace("total sum = " + totalSum);
                if (activity != null && activity.RegardingObjectId.LogicalName == new_project.EntityLogicalName)
                {
                    new_project relatedProject = xrm.new_projectSet.FirstOrDefault(proj => proj.new_projectId == activity.RegardingObjectId.Id);
                    if (relatedProject.new_totalhours == null && totalSum != 0)
                    {
                        relatedProject.new_totalhours = totalSum;
                        xrm.UpdateObject(relatedProject);
                        xrm.SaveChanges();
                    }
                    else if (relatedProject.new_totalhours != null && relatedProject.new_totalhours.Value != totalSum)
                    {
                        relatedProject.new_totalhours = totalSum;
                        xrm.UpdateObject(relatedProject);
                        xrm.SaveChanges();
                    }
                }
            }
        }
    }
}

*In this example the new_totalhour (int - duration format) attribute updated in custom entity name new_project, You can update any attribute you want.

General plugin code description:

  1. Get the post / pre image of the activity type entity like fax, email appointment and etc.
    not the activity pointer since you can't register setstate, setstatedynamic or delete to activity pointer.
  2. Get from it the regerdingobjectid and the duration of all the other completed activites releted to the same record.
  3. Update the record with the new duration.

Last step is to register the plugin and the steps.
Entities: All the activites you would like to sum have to be registered.
Messages: setstate, setstatedynamic and delete.
Images:
add post image to setstate and setstatedynamic
add pre image to delete.

Thursday, August 4, 2011

Solution plugins and the holy pluginregistrationtool

Solution plugins and the holy pluginregistrationtool


From now on after registering plugin with pluginregistertiontool, It's no longer needed for moving plugins between environment. Plugins and their steps can be included in solutions.
For best practice register all plugins to the sandbox and database, otherwise you might have problem moving them to other enviroments (ONLINE for example)


The pluginregistretiontool is still important and necessary for the first registretion of the plugins to the MSCRM 2011. It is still imposiable to do it from the CRM web application.