sábado, 19 de abril de 2014

Funcionamiento avanzados de los sub Grids

No se si les ha ocurrido, pero por si les ocurre en algún momento, voy a explicar como funciona una funcionalidad de las que mas me gusta de Dynamics CRM 2013.

Es la funcionalidad de poder relacionar rápidamente registros “hijos” desde un formulario.

Añadir un registro existente a uno padre, consiste básicamente en cambiar ese campo “Lookup” del hijo, para relacionarlo con un nuevo registro “padre”.

Básicamente me refiero que teniendo una Cuenta por ejemplo si quiero añadirle ventas, lo que tengo que hacer es lo siguiente:

imageimage

Pero hay veces que al darle al “+” inicial, en vez de abrirnos eso, nos abre directamente el formulario de Creación rápida de la entidad (si lo tiene habilitado) o el formulario de creación principal.

Otra opción para probar es abrir el grid y ver que ocurre allí:

imageimage

Desde allí tengo la misma experiencia. La pregunta es, ¿por qué algunas relaciones se comportan así y otras nos permiten añadir de esta forma mas rápida?

La respuesta es sencilla, y depende del tipo de relación con el hijo. Si el Lookup que define la relación, lo definimos como “Requerido por la empresa”, el comportamiento cambia y esta funcionalidad deja de existir.

image

El botón de “Agregar…” desaparece, y al intentar añadir nuevos registros me abre el formulario de creación rápida:

imageimage

Por lo tanto, en este tipo de relaciones y formularios, al momento de personalizar formularios visualmente hay que tener en cuenta también si el campo es requerido o no.

Espero les sirva esto.

un saludo

domingo, 13 de abril de 2014

Nuevamente MVP y además MAP 2014!

Hola, estas dos últimas semanas, he recibido dos noticias muy motivadoras y que me hacen seguir adelante cada vez más en mis contribuciones a las comunidades de Microsoft.

En primer lugar, Microsoft me ha vuelto a nominar como MVP (Microsoft Most Valuable Professional) para el año 2014, cosa de la que me siento muy muy orgulloso  y agradezco mucho a @Microsoft y al programa @MVPAward.

Esta semana además el equipo MSDN de España, me ha nominado MAP (Microsoft Active Professional) para el año 2014. Esta es una distinción local en España, que premia a los colaboradores de las comunidades de España y otros países.

Aprovecho para comentar que mi visión es que las comunidades de Microsoft y sus colaboradores por todo el mundo ayudan a que los profesionales que utilizan tecnologías de Microsoft puedan trabajar mejor, aprender, hacer networking y mejorar los productos de esta gran empresa.

En mi experiencia personal, el colaborar en las comunidades me ha hecho conocer gente muy interesante y así ampliar mis contactos directos con profesionales que comparten mis mismas inquitudes técnicas. Por otro lado, aprendo muchísimo respondiendo consultas en los foros, publicando artículos técnicos o creando proyectos en CodePlex.

Estos tipos de programas muestran la importancia que da Microsoft a los mismos, y ayudan a que los colaboradores mas activos, fomenten la aparición de nuevos participantes.

Saludos!

Gracias Totales.

viernes, 4 de abril de 2014

Moviendo datos entre entornos diferentes

Algo que se usa mucho, y de hecho se hace en casi todos los proyectos de CRM, es que una vez que he terminado de desarrollar todo y voy a hacer la subida a los entornos de PRE, UAT, PRO, etc. hace falta también la creación de datos.
Esta creación de datos, puede provenir en general por registros de configuración que ya están creados en DES y deben ser subidos a PRO, o incluso por el simple interés de mover estos datos.
Además a veces incluso queremos que los GUIDs de los registros sean los mismos, ya que se los creo manualmente los GUIDs internos de los registros se asignan automáticamente a nuevos valores.
Esta información además debe estar sincronizada, ya que si modifico datos en el entorno de origen, luego quiero ver ese dato actualizado en el resto.
Normalmente mucha gente mueve estos datos de forma manual exportando e importando desde ficheros Excel, pero es complicado mantenerlo sincronizado y además no se puede automatizar.
Para esto, hoy he preparado una solución MUY SENCILLA que mueve los datos entre entornos.
La idea es la siguiente:
image
El código .NET no puede ser mas simple, en la llamada lo único que quiero pasar es el código son los dos accesos (origen/destino), la entidad y los campos a sincronizar:
static OrganizationService service = GetCrmService(); 
static OrganizationService service2 = GetCrmService2();
MoveData(service, service2, "account", "name,emailaddress1,telephone1");
Y el método lo he llamado “MoveData()”:


         static void MoveData(OrganizationService sourceConnection, OrganizationService destConnection,
           
string entityName, string attributeNames)
        {
           
//1) consulto todo en origen
           
string[] attributes=attributeNames.Split(",".ToCharArray());  
           
QueryExpression consulta1 = new QueryExpression(entityName);  
            consulta1.ColumnSet =
new ColumnSet(attributes);  
           
EntityCollection registros = sourceConnection.RetrieveMultiple(consulta1);  
           
foreach (Entity ent in registros.Entities)  
            {  
               
//2) Consulto si ya existe el registro en destino  
               
Entity dest = null;  
               
try 
               
{  
                    dest = destConnection.Retrieve(entityName, ent.Id,
new ColumnSet(attributes));  
                }  
               
catch (SystemException ex)  
                {  
                    dest =
null;  
                }  
               
bool existe = (dest == null) ? false : true;
  
               
if (!existe)  
                {  
                   
//3) Creacion en destino  
                   
destConnection.Create(ent);  
                   
Console.WriteLine("Registro Creado");  
                }  
               
else  
               
{  
                   
//4) Update en destino  
                   
destConnection.Update(ent);  
                   
Console.WriteLine("Registro Actualizado");  
                }  
            }  
           
Console.ReadLine();  
        }



Finalmente si lo ejecuto me da el resultado:


image

Creo que esta solución es súper fácil pero a la vez útil, para mover datos de un entorno a otro, simplemente pasando las conexiones, y los nombres de entidades y campos.

Pensar cuanto tiempo tardarías en mover 10 entidades de configuración con sus registros manualmente con Excel desde un entorno de DES a PRE, UAT y PRO, y luego intentar pensar cuanto tardarías con algo así…

Happy Developing!

Espero les sirva…

abrazo!

domingo, 16 de marzo de 2014

Consultando la auditoría de Dynamics CRM

Hoy me propongo la consulta del registro de Auditoría. La auditoría en Dynamics CRM 2013, se almacena en una especie de entidad, pero con limitaciones, y que no puede ser accesible por las búsquedas avanzadas estándar.
Solamente pueden consultarse en los propios registros o de forma general en Configuración->Auditoría->Vista resumen de auditoría:
image
image
Si necesitamos consultas algo mas avanzadas, sólo nos queda ir por los oscuros caminos de lo no soportado (atacando directamente al SQL Server), que no lo recomiendo, o sino utilizar la SDK.
En este caso, vamos a ver un ejemplo donde recojo todos los registros de auditorías de los últimos 30 días, y en caso de ser un Update o Create, además muestro el detalle de cambios actualizados.
El ejemplo de código es el siguiente:
static void GetAudit()
{
    //1) Consulta con Filtro de 30 días
    ConditionExpression cond = new ConditionExpression("createdon", ConditionOperator.LastXDays, 30);
    FilterExpression filter1 = new FilterExpression();
    filter1.AddCondition(cond);
    RetrieveMultipleRequest req = new RetrieveMultipleRequest();
    QueryExpression query = new QueryExpression("audit");
    query.ColumnSet = new ColumnSet(true); 
    query.Criteria.AddFilter(filter1);
    req.Query = query;
    RetrieveMultipleResponse res =(RetrieveMultipleResponse)service.Execute(req);

    //2) Recorremos la Auditoria devuelta
    foreach (Entity ent in res.EntityCollection.Entities)
    {
        //3) Leemos los datos del registro
        Audit record = (Audit)ent;
        string fecha = String.Format("Fecha:{0}", record.CreatedOn.Value.ToString());
        string usuario = String.Format("Usuario:{0}", record.UserId.Name);
        string accion = String.Format("Action:{0}", record.FormattedValues["action"]);
        string operacion = String.Format("Operación:{0}", record.FormattedValues["operation"]);
        string registro = String.Format("Tipo:{0} Name:{1} Guid:{2}", record.ObjectId.LogicalName, 
                record.ObjectId.Name, record.ObjectId.Id.ToString());
                
        //4) Escribimos un log de los datos
        Console.WriteLine(fecha);
        Console.WriteLine(usuario);
        Console.WriteLine(accion);
        Console.WriteLine(operacion);
        Console.WriteLine(registro);

        //5) Si es Create o Update 
        if (record.Action.Value == 1 || record.Action.Value == 2)
        {
            //6) Consultamos el detalle
            RetrieveRecordChangeHistoryRequest changeRequest = 
                new RetrieveRecordChangeHistoryRequest();
            changeRequest.Target = new EntityReference(record.ObjectId.LogicalName, 
                record.ObjectId.Id);
            RetrieveRecordChangeHistoryResponse changeResponse =
                (RetrieveRecordChangeHistoryResponse)service.Execute(changeRequest);
            AuditDetailCollection details = changeResponse.AuditDetailCollection;

            foreach (var detail in details.AuditDetails)
            {
                //7) Por cada detalle devuelto, pintamos valor anterior y actual
                Audit detail_record = (Audit)detail.AuditRecord;
                var detailType = detail.GetType();
                if (detailType == typeof(AttributeAuditDetail))
                {
                    var attributeDetail = (AttributeAuditDetail)detail;
                    foreach (KeyValuePair<String, object> attribute in 
                        attributeDetail.NewValue.Attributes)
                    {
                        String oldValue = "(no value)", newValue = "(no value)";
                        if (attributeDetail.OldValue.Contains(attribute.Key))
                            oldValue = attributeDetail.OldValue[attribute.Key].ToString();
                        newValue = attributeDetail.NewValue[attribute.Key].ToString();
                        Console.WriteLine("Attribute: {0}, old value: {1}, new value: {2}",
                            attribute.Key, oldValue, newValue);
                    }

                    foreach (KeyValuePair<String, object> attribute in 
                        attributeDetail.OldValue.Attributes)
                    {
                        if (!attributeDetail.NewValue.Contains(attribute.Key))
                        {
                            String newValue = "(no value)";
                            String oldValue = attributeDetail.OldValue[attribute.Key].ToString();
                            Console.WriteLine("Attribute: {0}, old value: {1}, new value: {2}",
                                attribute.Key, oldValue, newValue);
                        }
                    }
                }
            }
        }
        Console.WriteLine("---------------");
    }
    Console.ReadLine();
}

En resumen, utilizo el mensaje ExecuteMultiple para la consulta general y luego para el detalle utilizo el mensaje RetrieveRecordChangeHistory.

El resultado obtenido en mi caso es el siguiente:

image

Como puede verse, tengo toda mi auditoría en un resultado ordenado, por fecha, usuario entidad y tipo de acción.

Este ejemplo es 100% funcional, tengo idea de hacer algún tipo de herramienta a futuro, que ayudarnos con los datos que hay en los registros de auditoría, para que sea mas sencillo su explotación.

Espero les sea útil este ejemplo, a mí me ha servido.

domingo, 9 de marzo de 2014

Compartir registros con el propietario antes de reasignar

En Dynamics CRM, tenemos la posibilidad de antes de reasignar un registro, este quede compartido con el propietario original.

De esta manera podemos permitir que personas que fueron propietarios de un registro, puedan seguir teniendo permisos sobre el mismo, a la vez que consultar sus registros relacionados (si es que la relación esta definida para que se comparte en cascada).

Imaginemos algún escenario real:

Una operadora de atención al cliente, recibe una incidencia de un Cliente nuevo, que mas tarde un jefe de ventas asigna a un delegado comercial. Si la operadora de atención al cliente tiene privilegios de solo ver sus cuentas (de las que es propietaria), dejaría de ver esa cuenta que ha creado ella.

Lo ideal sería que al asignarlo a un delegado comercial, esta Cuenta (y sus relaciones hijas), se compartan con el la operadora que inicialmente la ha creado.

Para que funcione de esta manera, existe una opción en la configuración principal, con el nombre “Compartir registros reasignados con el propietario original”:

image

Pero, ¿como se comporta esto? la idea es bastante sencilla, imaginemos que tenemos una cuenta asignada a Demian:

image

La asignamos al usuario Test User:

image

Si vamos al menú de Compartir:

image

Podemos ver como el registro se ha compartido al usuario propietario inicial (Demian):

image

Excelente solución, solo tienen que tener cuidado con una cosa:

  • Esto se aplica para todos los registros, de todas las entidades, por lo tanto hay que tener cuidado de si se desea este comportamiento de forma “global” para todo el sistema.

Esta opción de configuración es una opción que prácticamente no he utilizado, ni he encontrado que mucha gente la utilice, aunque creo que es una idea muy buena.

un saludo y espero les sirva!

miércoles, 5 de marzo de 2014

Dynamics CRM como plataforma de desarrollo

Como todos conocen, Dynamics CRM es la mejor solución del mercado para todas las gestiones típicas de CRM como de ventas, marketing, servicio, etc. (Winking smile).

Pero cada día que pasa, veo mas a Dynamics CRM también como una excelente plataforma para implementar cualquier tipo de procesos de negocio. Esto nos permite diseñar, desarrollar, implementar y poner en marcha procesos de negocio en tiempo record, en un entorno controlado, amable y moderno, que además evoluciona y mejora por parte del fabricante (Microsoft).

Obviamente, este planteamiento no puede ser aplicado para cualquier tipo de desarrollo (aunque personalmente suelo ser bastante extremista con esto), pero si para una gran parte.

Bien, pero hablemos sobre un ejemplo en concreto para ver que ventajas podemos encontrar. Imaginemos que en una empresa, el departamento de recursos humanos, nos plantea la necesidad de una solución para gestionar las solicitudes de cursos de formación de sus empleados. Actualmente lo hacen por email y Excel, pero es un proceso manual muy lento y se producen errores. En este caso, si se plantea un desarrollo web por ejemplo, deberíamos pensar en un modelo de gestión de usuarios y seguridad, un modelo de datos, implementar un proceso de aprobación, temas técnicos o de sistemas acerca de las tecnologías a utilizar, y otros. Obviamente es un proyecto bastante sencillo, que empezando desde cero su desarrollo podríamos tenerlo listo en aproximadamente un par de meses (aproximación mía). Una vez montado, que pasa si nos piden accesos desde móviles, cambios en la funcionalidad, nuevas validaciones o cambios en el modelo de seguridad?, seguramente nos toque desarrollar nuevamente para realizar todos estos cambios (costo alto).

Todo esto esta muy bien, yo soy desarrollador también y me gustan los retos técnicos y me gusta desarrollar, pero a veces las visiones deben de estos temas deben tener una perspectiva mas a nivel empresarial y no solamente técnica.

Si implementamos soluciones de negocio en Dynamics CRM, ya tenemos disponible un servicio de autenticación y gestión de usuarios, un modelo de seguridad, una herramienta de modelado de datos y millones de funcionalidades “out of the box” como trabajos con Excel, importaciones, auditoría, automatismos, validaciones, workflows y un largo largo etc. No hay que olvidar que todo esto esta apoyado en una solución estándar de mercado, que Microsoft se encarga de mantener y evolucionar (muy rápido últimamente).

Por esto voy a plantear unos cuantos puntos que considero grandes “ventajas” de la utilización de Dynamics CRM como “xRM”:

  • Time to market: el tiempo de implementación de un proceso de negocio con Dynamics CRM es increíblemente rápido
  • Mantenimiento y evolución: al estar basado en una plataforma estándar, no se depende tanto del implementador y esto da mas libertad
  • Soporte: el soporte de Microsoft sobre la solución es imprescindible en determinadas organizaciones que requieren niveles de seguridad altos
  • Una plataforma, N procesos: sobre la misma plataforma, se pueden implementar todos los procesos de negocio que sean requeridos
  • Integración con cualquier otra solución: Como Dynamics CRM está basado en Web services, todo lo que implementemos en esta plataforma es muy fácilmente integrable con cualquier plataforma
  • Escalabilidad: en la parte de sistemas, nos permite que sea facilmente escalable
  • Nube u Onprem: posibilidad de implementarlo en la nube o en mi casa (onpremise)
  • Mantenimiento por usuarios avanzados: muchas veces, este tipo de procesos pueden ser mantenidos, administrados y evolucionados por “power users” sin necesidad de disponer de un equipo completo de desarrollo.
  • Precio: Obviamente Dynamics CRM no es gratis, pero el pago de las licencias muchas veces es mas bajo que si hubiesemos invertido ese dinero en desarrollos a medida, que en algun momento futuro se tirará o se tendrá que evolucionar a un precio muy elevado. Estas evoluciones con Dynamics CRM son muchisimo mas sencillas, rápidas y por supuesto, a precios menores.
  • Etc.
  • Etc.

Creo que el tiempo de ver al “CRM” como un simple sitio donde gestionar relaciones con mis clientes, ha pasado. Ahora Dynamics CRM es mucho mas y ofrece muchas mas posibilidades.

Por todo esto, ante un planteamiento de un nuevo requerimiento empresarial, sea del tipo que sea, por lo menos creo que debería ser analizada la posibilidad de implementarlo en una plataforma estándar como Dynamics CRM.

Un análisis en profundidad punto a punto nos desvelará que muchas veces la utilización de Dynamics CRM como plataforma de desarrollo, no solo nos ayuda a enfocarnos mejor en la solución de negocio, sino que también es una solución con vistas a evolucionar en el futuro de forma mucho mas ordenada, soportada y mantenible.

lunes, 17 de febrero de 2014

ITCAMP CRM Online con Comunidad Office 365

imageimage

El pasado sábado 15 de febrero en La Fundación Tajamar, tuve el placer de participar como ponente en el ITCamp enfocado en Dynamics CRM Online.

Esta serie de ITCamps está organizado por la Comunidad de Office 365. Para este ITCamp hemos colaborado dos comunidades “en español” como son comunidadCRM y comunidad de Office 365.

El ITCAmp ha comenzado con una introducción a Dynamics CRM Online realizada por Rafael Ansino para luego dar lugar a un laboratorio práctico que he preparado. Este laboratorio, en realidad es un “mini” proyecto en si mismo, abarcando elementos introductorios para gente que es nueva en Dynamics CRM.

El laboratorio completo esta online para que podáis paso a paso volver a hacerlo desde donde queráis: Guia IT CAMP CRM Online.docx . Un un tutorial paso a paso, para poder realizar el proyecto completo. Incluye personalizaciones, cargas de datos, configuración y seguridad.

Personalmente ha sido una experiencia excelente y una oportunidad de conocer gente genial y pasar un buen rato compartiendo tecnología. Muchas gracias a todos los asistentes, y espero que pueda haberles sido de utilidad.

Os dejo algunas fotos del evento:

20140215_083728Embedded image permalink

Embedded image permalinkEmbedded image permalink