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

miércoles, 5 de febrero de 2014

Error en Workflow Síncrono “Value cannot be null. Parameter name: culture”

Hola, existe una situación que provoca un error en Dynamics CRM 2013.

En esto post intentaré explicar la situación y como resolverlo.

Para reproducirlo hay que seguir estos pasos:

1) creamos una nueva entidad

image

2) Creamos un flujo de trabajo síncrono:

image

3) Hacemos que se dispare antes de una eliminación y definimos una lógica de ejecución:

image

4) Creamos un registro del tipo nuevo creado y lo intentamos eliminar:

image

5) Aparece un error:

image

La descripción del error es la siguiente:

Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: System.Web.HttpUnhandledException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #9BCAE0E7Detail:
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
  <ErrorCode>-2147220970</ErrorCode>
  <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
  <Message>System.Web.HttpUnhandledException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #9BCAE0E7</Message>
  <Timestamp>2014-02-05T20:30:29.5087838Z</Timestamp>
  <InnerFault>
    <ErrorCode>-2147220891</ErrorCode>
    <ErrorDetails xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
    <Message>Value cannot be null.
Parameter name: culture</Message>
    <Timestamp>2014-02-05T20:30:29.5087838Z</Timestamp>
    <InnerFault i:nil="true" />
    <TraceText>

[Microsoft.Crm.ObjectModel: Microsoft.Crm.ObjectModel.SyncWorkflowExecutionPlugin]
[4b68b225-a48e-e311-b0ae-6c3be5be5e68: ]
Starting sync workflow 'test', Id: 4568b225-a48e-e311-b0ae-6c3be5be5e68
Entering ConditionStep1_step:
Sync workflow 'test' terminated with error 'Value cannot be null.
Parameter name: culture'

</TraceText>
  </InnerFault>
  <TraceText i:nil="true" />
</OrganizationServiceFault>

Para solucionar el error tenemos que ir al proceso y modificar como se ejecuta el proceso. Volvemos a activar el mismo y ya todo funciona:

image

Ahora ya me muestra mi mensaje de error personalizado correctamente:

image

Lo curioso es que si vuelvo a poner el valor del proceso como estaba antes, sigue funcionando correctamente:

image

Imagino que esto será resuelto en próximos rollups, de todos modos, con lo explicado aquí, ya se puede continuar trabajando con Dynamics CRM 2013 Sonrisa

he creado también una entrada en connect, por si a alguien le interesa tener un seguimiento de este tema, o votar por el mismo: https://connect.microsoft.com/dynamicssuggestions/feedback/details/816726/mvp-bug-in-sync-workflow-on-before-delete-value-cannot-be-null-parameter-name-culture

Un saludo,

viernes, 17 de enero de 2014

AngularJS en Dynamics CRM 2013

image
Imagino que casi todos ya lo conocen, y muchos ya lo utilizamos hace algún tiempo. AngularJs es un framework de javascript que permite trabajar con modelos MVC (Modelo Vista Controlador) de forma fácil y rápida.
La verdad que el mundo del javascript esta pegando los últimos años unas mejoras y expansión espectacular, y lo bueno de todo esto, es que Dynamics CRM está apoyado en todo esto y nos permite aprovecharnos de todo lo nuevo.
Lo que voy a hacer hoy es una especie de “Hola mundo”, aprovechando lo siguiente:
  • AngularJS (con su NGGrid)
  • jQuery
  • Ejemplos en javascript de la SDK de CRM
La idea funcional es mostrar en un Dashboard de CRM (Panel), un web resource, que recoja datos de CRM y mediante AngularJS, me cree un grid, con funcionalidades como agrupar, ordenar, etc.
Lo que finalmente obtengo es lo siguiente, un grid de Cuentas, con sus ciudades, y la posibilidad de ordenar y agrupar haciendo drag & drop, todo esto en un web resource dentro de un dashboard:
image
image
Como lo hice, es bastante sencillo. Primero empiezo con un web resource de tipo HTML con el siguiente código:
<html ng-app="myApp">  
    <head lang="en">
        <meta charset="utf-8">
        <title>CRM con AngularJS</title>  
        <link rel="stylesheet" type="text/css" href="new_nggrid.min.css" />
        <link rel="stylesheet" type="text/css" href="new_style.css" />
        <script src="ClientGlobalContext.js.aspx" type="text/javascript"></script>
        <script type="text/javascript" src="new_jquery2.0.3.min.js"></script>
        <script type="text/javascript" src="new_jqueryui1.9.1.custom.min.js"></script>
        <script type="text/javascript" src="new_angular.min.js"></script>
        <script type="text/javascript" src="new_nggrid2.0.7.min.js"></script>
        <script type="text/javascript" src="new_SDK.REST.js"></script>
        <script type="text/javascript" src="new_script.js"></script>
    </head>
    <body ng-controller="MyCtrl">    
        <div class="gridStyle" ng-grid="gridOptions"></div>
    </body>
</html>

En este HTML, lo importante es como llamo a mi aplicación “myApp” con el parámetro ng-app y luego el control “MyCtrl” con el parámetros ng-controller, que utilizaré luego.

Fácil, el tema es que hay que añadirle muchas librerías de javascript. Para esto, las añado como web resources en mi solución:

image

Todos esos javascript son librerías genéricas (angular, jquery, etc.) salvo una que llamé “script.js”. En este fichero voy a añadir la lógica de mi formulario:

var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function($scope, $http) {    $scope.totalServerItems = 0;
    $scope.pagingOptions = {
        pageSizes: [250, 500, 1000],
        pageSize: 250,
        currentPage: 1
    };    
     $scope.setPagingData = function(data, page, pageSize){    
        var pagedData = data.slice((page - 1) * pageSize, page * pageSize);
        $scope.myData = pagedData;
        $scope.totalServerItems = data.length;
        if (!$scope.$$phase) {
            $scope.$apply();
        }
    };
    $scope.getPagedDataAsync = function (pageSize, page, searchText) {
        setTimeout(function () {
            var number = 50;
             var options = "$select=Name,Telephone1,Address1_City&$top=" + number ;
             
            SDK.REST.retrieveMultipleRecords("Account", options, function (retrievedAccounts){
                
                $scope.setPagingData(retrievedAccounts,page,pageSize);
                }, function (error) { alert(error.message); }, function (res){var aux=1;});
         }, 100);
    };        
    $scope.gridOptions = {
        data: 'myData',
        enablePaging: false,
        showFooter: false,
        totalServerItems: 'totalServerItems',
        pagingOptions: $scope.pagingOptions,
        filterOptions: $scope.filterOptions, 
        
        columnDefs: [{field:'Name', displayName:'Name'}, {field:'Telephone1', displayName:'Telephone1'}, {field:'Address1_City', displayName:'Address1_City'}], 
        showGroupPanel: true, 
        jqueryUIDraggable: true, 
        enableCellSelection: true,
        enableRowSelection: false,
        enableCellEdit: true,
    };
});    
Este código consulta a CRM al punto oData, y el resultado que es un objeto jSON, lo meto en gridoptions con sus columnas definidas en “columnDefs”. Además en gridOptions se pueden añadir o quitar parámetros de comportamientos del grid, como paginaciones, ediciones, selección de líneas o celdas, etc.

Para mas información, recomiendo estudiarse a fondo este framework, a mí sinceramente me encante porque soy un amante del Javascript (http://angularjs.org/). Mirar también algo específico de ngGrid (Grid de AngularJS utilizado en este ejemplo).

Por último, como siempre, les dejo toda la solución no administrada para que podáis jugar: angulasJS_1_0_0_0.zip

Un saludo!

miércoles, 15 de enero de 2014

Completado el curso de Desarrollo con Dynamics CRM 2011

Academia de la Comunidad CRM
Finalmente se ha terminado de publicar el curso completo de desarrollo con Dynamics CRM 2011 que he realizado y publicado en Comunidad CRM (www.comunidadCRM.com).
Son mas de 3 horas de grabación, que abarca todos los aspectos del desarrollo con Dynamics CRM, buenas prácticas, consejos, ideas y ejemplos reales desde cero y explicados con el Visual Studio.
Espero pueda servirle a la comunidad como introducción a este apasionante mundo del CRM. Por mi parte me siento muy orgulloso de haberlo hecho y agradezco todos los mensajes de agradecimiento que he recibido en estas semanas, y a Comunidad CRM por haber fomentado y organizado. Todo esto me motiva a seguir adelante apoyando y publicando mas y compartiendo conocimiento.
Si alguien quiere hacer el curso completo aquí les dejo el listado de enlaces con todos los capítulos publicados:
Mi consejo final: compartir conocimiento es la mejor manera de seguir aprendiendo siempre.

domingo, 12 de enero de 2014

Workflows síncronos para auto numeración

Hola a todos, antes que nada….FELIZ 2014!
Imagino que todos están al día de que CRM 2013, tenemos la posibilidad de ejecutar los workflows de forma síncrona, sino ver por favor aquí: http://www.demianrasko.com/2013/10/workflows-sincronos-en-crm-2013.html
Los workflows de ejecución síncrona, nos abren una nueva ventana de posibilidades, que hasta ahora solamente eran posibles por medio de plugins, por ejemplo:
  • Auto numeraciones
  • Concatenaciones de campos
  • Validaciones
  • Cálculos
  • etc.
Uno de los plugins mas comunes que casi todos los implementadores han creado, es un plugin para gestionar auto numeraciones. Si bien Dynamics CRM contiene auto numeraciones para determinadas entidades como pedidos, casos, etc., esta numeración no es muy personalizable, y como parte de este código, el número que se incrementa no es 100% seguro que será único.
Ahora mismo hay varias publicaciones, que nos aportan ideas de como crear un workflow síncrono para aplicar auto numeraciones, en particular destaco los posts de dos colegas MVPs:
Por un lado, Shan nos proporciona una solución basada en dos entidades y un workflow síncrono, que nos permite de forma sencilla y sin tirar ni una sola línea de código, de disponer de un autonumerador basado en estos workflows síncronos.
Por otro lado, Jukka plantea la diferencia de realizar algo así con un workflow síncrono y otro igual pero asíncrono, explicando que si es asíncrono, nos generaría códigos duplicados ya que los procesos asíncronos se ejecutan de forma paralela (threads) y no podemos controlar el orden en que se ejecutan.
Recomiendo si les interesa el tema, leer estos dos posts, muy interesantes y rápidos de leer.
De todos, a mi me gusta ir un paso mas. He intentado confirmar si una solución de este tipo puede funcionar en un entorno real, o planteando que limitaciones podemos encontrar.
Me basé en la solución creada por Shan, en donde voy a numerar en el campo “Fax”, las cuentas que voy creando. Lo he realizado, y creando algunos registros de forma manual, funciona perfectamente:
image
Ahora bien, que pasa si creamos de forma masiva miles de registros? influye en algo la forma de crearlos? si los creamos como registros relacionados o “related” o utilizando ExecuteMultiple?
Bien, he creado un ejemplo de creación de miles de registros uno a uno llamando al CreateRequest, luego hice ejemplos con registros “related” (si alguién quiere mas información sobre esto, ir a la sdk: http://msdn.microsoft.com/en-us/library/gg309282.aspx) y por último con el ExecuteRequest.
Mis resultados no podían ser mejores y podía ver como a pesar de haber creado varios miles de registros, no encontraba duplicados:
image
De todos modos, esto no era un ejemplo de todo “estresado” y estaba seguro que si ejecutaba esos mismos códigos en paralelo en diferentes “Threads”, me crearía duplicados.
Entonces, me lancé la creación de estos registros con hasta tres hilos de ejecución:
image
Y encontré que efectivamente me generaba números repetidos hasta tres veces:
image
Está bien, esto tiene sentido, los workflows son síncronos, pero es posible que se intenten crear unos registros exactamente al mismo tiempo, y por lo tanto los numera iguales, no los ejecuta en orden sino en paralelo.
Por lo tanto, he de dar algunas conclusiones como finalización de mi estudio de este tema:
  1. Es una forma sencilla, rápida y sin tirar ni una sola línea de código para auto numerar registros con Dynamics CRM.
  2. Esta forma funciona correctamente (100% seguro) para cargas de datos automáticas que se ejecuten en un solo hilo o thread. No generando duplicados nunca.
  3. En caso de los registros a numerar se creen de forma manual, este tipo de soluciones es prácticamente al 99% seguro de que no habrá duplicados. Reproducir un ejemplo en el cual dos usuarios creen el mismo tipo de registros en el mismo milisegundo, es posible pero casi improbable. Ojo, tener en cuenta que puede ocurrir, en especial en entornos con muchos usuarios.
  4. Si hay procesos por ejemplos de cargas, que se ejecuten en varios hilos de ejecución, esta solución no es viable, ya que los códigos auto numéricos se duplicarán.
Por favor tener en cuenta estos temas, espero que les sirva.
un abrazo