sábado, 24 de enero de 2015

Como hacer campos consolidados síncronos (Sync Rollups)

Buenas, como muchos ya conocen y (espero) estén utilizando ya, en Dynamics CRM 2015 tenemos la posibilidad de utilizar campos de tipo “Consolidados” o de tipo “Rollup” (a veces las traducciones no me suenan muy bien y prefiero hablar con conceptos en inglés).
Bien, este tipo de campos tiene la particularidad que se calculan de forma asíncrona, es decir que es posible que el dato que estemos consultando o viendo, no sea esté actualizado. Esto se puede minimizar, bajando los tiempos de cálculo hasta un mínimo de una hora, pero aún así, en algunos escenarios esto no alcanza y es requerido que los cálculos sean totalmente online.
Hoy les voy a enseñar como convertir un campo de tipo Rollup (asíncrono por naturaleza), a un campo de Rollup 100% síncrono.
Me he inventado un escenario donde tengo Cuentas y Contactos (muy original por cierto) y quiero un campo en las Cuentas que me muestre el total de Contactos relacionados que dispone.
El campo de Rollup en Cuenta tiene la siguiente definición:
image
image
Bien, solamente con esto ya dispongo del campo que me calcula el total de contactos relacionados con una Cuenta. Pero esto se calcula de forma asíncrona nomás, o síncrona de forma manual desde el mismo formulario.
Para convertirlo en totalmente síncrono, debemos crear un Plugin y hacer una llamada a un nuevo mensaje llamado “CalculateRollupFieldRequest” que permite disparar el cálculo de un campo de tipo Rollup.
El código completo del Plugin está aquí:
using Microsoft.Crm.Sdk.Messages;using Microsoft.Xrm.Sdk;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Web;
namespace Plugin_Recalculate_Rollup
{
    public class Recalculate_Rollup  :IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)    
        {
            ITracingService tracingService =(ITracingService)serviceProvider.GetService(typeof(ITracingService));        
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));        
            if (context.InputParameters.Contains("Target") &&            context.InputParameters["Target"] is Entity)        
            {
                Entity entity = (Entity)context.InputParameters["Target"];
                if (entity.LogicalName != "contact")
                    return;
                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
                try
                {
                    Entity contact=(Entity)context.PostEntityImages["Imagen"];
                    CalculateRollupFieldRequest calculateRollup = new CalculateRollupFieldRequest();
                    calculateRollup.FieldName = "new_totaldecontactos";
                    calculateRollup.Target = new EntityReference("account", ((EntityReference)contact.Attributes["parentcustomerid"]).Id);
                    CalculateRollupFieldResponse resp = (CalculateRollupFieldResponse)service.Execute(calculateRollup);
                }
                catch (Exception ex)
                {
                    tracingService.Trace("MyPlugin: {0}", ex.ToString());
                    throw;
                }     
            }
        }
    }
}

En la llamada al “CalculateRollupFieldRequest”, solamente hay que pasarle los siguientes parámetros:
  • FieldName: con el nombre del campo Rollup en Cuenta
  • Target: que debe ser un EntityReference al registro “padre”
Este plugin, lo complilamos y lo registramos con el PluginRegistrationTool como siempre.

NOTA: para registrar plugins a mí el PluginRegistrationTool de la versión 7.0.0 (CRM 2015) no me funciona, ya que se me queda la pantalla en blanco al conectar. Para este ejemplo he utilizado el PluginRegistrationTool que viene en la SDK de CRM 2013 SP1 (6.1.0).

image

Adicionalmente he credo una Imagen Post para recoger el “ParenCustomerId” del contacto:

image

Ahora cada vez que crea un Contacto nuevo relacionado con una Cuenta, se recalcula el campo de tipo Rollup:

image

Advertencia!: los campos de tipo Rollup síncronos pueden penalizar (y mucho) el rendimiento del CRM, por esto, si bien una práctica 100% soportada, utilizarlos con cuidado.

8 comentarios:

  1. Hola Demian, el uso de los plug-in como el que acabas de hacer solo aplica para CRM On-premise?? o ya podemos hacerlo en CRM Online

    Saludos

    ResponderEliminar
  2. Hola juan Carlos, aplica a los dos, con casi lo única diferencia que ennonlinensolamento los puedes registrar en el sandbox.
    Un saludo

    ResponderEliminar
  3. Gracias Demian, estaba pensando en hacer algo dentro de CRM Online: pensaba en crear un script o plug in que se ejecutara una acción cuando un usuario se loguie en CRM, tengo un requerimiento donde necesito hacer que CRM me este recordando cuando vence un contrato o las actividades dentro del contrato; estoy metiendo esta duda en el foro de la comunidad con mas detalle, seria bueno tener tu punto de vista.

    Entonces ni pensarlo que se pudiera crear un plug in con crm online en un ambiente productivo?? esto es por que Microsoft no lo soporta?

    Una pregunta, pero si puedo utilizar codigos con javascript para ejecutar una accion automaticamente cada cierto tiempo en CRM??

    ResponderEliminar
  4. Hola Juan Carlos, me estas haciendo varias preguntas en una sola, y con ideas diferentes.
    Primero: Sí que puedes crear plugins en crm online y puedes hacer casi lo mismo que en onprem. La única limitación es que debes registrarlos en sandbox, nada mas.
    Segundo: Lo que necesitas lo podrías hacer con un JavaScript con un settimeout, dentro del ribbon del crm. Este js haría la consulta y te notificaría. Te lo adelanto, no es fácil.

    Un saludo

    ResponderEliminar
  5. Sorry Demian por tantas ideas en varias preguntas :)

    ok creo que ya me esta quedando claro, entonces registro el plug in en mi ambiente sandbox para poderlo utilizar en mi crm productivo??

    Por cierto Demian, das asesoria en temas de desarrollo en CRM??

    Saludos

    ResponderEliminar
  6. Hola Juan Carlos, me acabo de dar cuenta de que me expliqué mal y me estabas entendiendo mal.
    Cuando hablo de "Sandbox", me refiero al contexto donde se registran los plugins.
    Me explico: por un lado estan los entornos de CRM Online, que pueden ser de producción o de no producción (o sandbox). esto es otra cosa.
    Los plugins pueden ser registrados en sandbox que es un servicio interno que tiene el server aislado del IIS de CRM donde se ejecutan los plugins. Si estuvieses en Onprem, puedes registrarlo fuera de este sandbox, lo que te permite por ejemplo acceder al dico duro del servidor, a base de datos SQL Server, etc.. en online, solamente puedes regitrar los plugins en este servicio de sandbox (independientemente si el entorno de CRM es una organizacion de produccion o de no produccion).

    Yo doy asesorías de desarrollo de CRM, formaciones, etc... pero trabajo en la actualidad en una empresa en Madrid, que se llama Infoavan Soluciones.

    ResponderEliminar
  7. Hola Demian si estas muy lejos, en tus próximas vacaciones contempla Guadalajara, Mexico :)

    Gracias por la paciencia y explicarme; ya me quedo claro el concepto. Entonces para tener acceso a este sandbox se requiere algo en especial?

    Saludos

    ResponderEliminar
  8. Apunto Guadalajara..jaja seguro esta muy bien .
    Cuando registres el plugin usando el plugin registration tool de la sdk, veras la opción allí.

    Un saludo

    ResponderEliminar