domingo, 29 de noviembre de 2009

Personalizando el Mapa del sitio (SiteMap)

Microsoft dynamics CRM, nos da la posibilidad de personalizar el Mapa del sitio, de forma que podamos dejarlo de forma que mas nos interese para las necesidades de los clientes, y ademas para "facilitar" la vida a los usuarios para que solo puedan ver lo que necesitan, ocultando según sus roles lo innecesario.
Los enlaces aparecen en "Groups" y "SubAreas" como lo siguiente:






Para poder ocultar una "SubArea", primero voy a explicar como funciona la visibilidad de las mismas. En primer lugar hay que tener en cuenta que solo se mostrarán aquellas SubAreas que tenga permiso el usuario según sus roles de seguridad asignados. Si el usuario puede ver esa entidad, entonces el CRM verifica si hay "Privilegios" adicionales relacionados con la SubArea. Estos privilegios adicionales, nos dan la posibilidad de ocultar o mostrar una SubArea dependendiendo de los permisos que tenga el usuario.
Si quisiésemos ocultar por ejemplo las "Cuentas" para que sólo lo puedan ver los Administradores, un ejemplo sería este (solo les aparecerá a aquellos que puedan crear usuarios):





Por otro lado también hay "Areas", como por ejemplo Area de trabajo, Ventas, Marketing, Configuración, etc.
Estas áreas solo aparecerán si hay SubAreas dentro para mostrar. De esta forma, si quiesiésemos ocultar un Área, simplemente lo que tenemos que hacer es ocultar todas las SubAreas de hay dentro.
Muchas veces necesitamos también crear una nueva Área, con una serie de enlaces dentros (por ejemplo aplicaciones propias para hacer consultas al ERP)
Voy a dejar un ejemplo de como sé haría esto:
















(se deben reemplazar los tags "Titl_e" por "Title" y "Are_a" por "Area")

De esta forma, podríamos ocultar todo lo que nos interese y dejar el mapa del sitio totalmente modificado.

Para personalizar el SiteMap, recomiendo utilizar las "Stunnware Tools 4.0" (http://www.stunnware.com/).

un saludo

jueves, 26 de noviembre de 2009

Ha salido una nueva versión de la SDK (4.0.11)

Ahora parece que el equipo del CRM de Microsoft está a tope actualizando la SDK (la versión anterior 4.0.10 salió en octubre).
La nueva versión no parece tener cambios importantes, salvo un par de artículos, pero igual como siempre recomiendo tener la última.

Una cosa interesante de esta nueva SDK es un documento con el nombre "Download an Attachment" con un ejemplo de como descargar un fichero adjunto en una "Nota".

Descárguenla desde aquí: http://www.microsoft.com/downloads/details.aspx?FamilyID=82E632A7-FAF9-41E0-8EC1-A2662AAE9DFB&displaylang=en

Un abrazo!

martes, 24 de noviembre de 2009

Foros técnicos de Microsoft CRM

Hola, este post es para recordar que existen una serie de foros técnicos en castellano en donde se pueden plantear dudas, problemas, incidencias, etc. a la "comunidad" de CRM.
Recomiendo utilizar estos foros, la verdad que mucha gente ve resuelta sus dudas de esta forma.
Yo suelo "pasearme" por ellos a ver que hay, y si puedo, intento participar.
Los foros son:

  • http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=microsoft.public.es.crm&cat=es_ES_4d003c3d-4b24-4d73-9698-e6970c115e19&lang=es&cr=ES


  • http://social.microsoft.com/Forums/es-ES/crmspanish/threads


  • http://social.technet.microsoft.com/forums/es-ES/dynamicses/threads/


  • Un saludo!

    sábado, 21 de noviembre de 2009

    Usuarios en CRM y directorio activo

    En las implantaciones de CRM, a veces surgen problemas relacionados con los usuarios.
    Los usuarios de CRM deben primero estar creados previamente en el directorio activo del dominio donde esté el CRM.
    Los pasos para crear un nuevo usuario serían:
    1) Crear el usuario en el directorio activo.
    2) Dar de alta el usuario en el CRM.
    3) Añadirle los roles de seguridad que se deseen.

    Hay ciertas consideraciones que deben ser tenidas en cuenta a la hora de la gestión de usuarios en CRM:
  • Cuando se crea un nuevo usuario en CRM, el CRM almacena el "id" interno del directorio activo. El "enlace" entre un usuario de CRM y uno de directorio activo, no se realiza a traves del inicio de sesión, sino a través de dicho "id".

  • Al crear un usuario nuevo, para que pueda acceder debe tener en sus roles, el permiso de "modificar" su configuración de usuario. Esto es así porque al acceder al CRM por primera vez, se debe poder modificar su configuración.

  • Nunca eliminar el usuario en el directorio activo, esto provocará que un usuario habilitado en CRM, no pueda acceder al CRM, y ademas quedará "desenlazado" con el directorio activo.

  • En caso de modificar el inicio de sesión en el directorio activo, el usuario podrá seguir accediendo al CRM y funcionando correctamente. Lo único que si que fallaría serían las consultas a las FilteredViews realizadas con ese usuario, ya que ahí si que lo relaciona por el inicio de sesión.

  • En caso de que se haya modificado el inicio del sesión del directorio activo, se puede acceder al formulario de CRM del usuario en cuestión y actualizar el atributo de inicio de sesión, para que se actualice con el nuevo valor. Primero hay que introducir el inicio de sesión de un usuario cualquiera del directorio activo (que no esté en CRM), guardar, y luego introducir en inicio de sesión correcto y guardar.

  • En relación con las bajas de usuarios, lo que recomiendo es que nunca se eliminen los usuarios del directorio activo. En caso de producirse una baja, lo ideal sería deshabilitar el usuario de CRM y luego desactivarlo del directorio activo.


  • un saludo

    miércoles, 18 de noviembre de 2009

    Trabajando con atributos deshabilitados y concatenaciones

    En este artículo intentaré comentar como trabajar con atributos deshabilitados en los formularios de CRM.
    Para esto lo explicaré con un ejemplo práctico que suele ocurrir mucho en la vida de los proyectos en CRM.
    Muchas veces nos vemos en la necesidad de crear entidades para hacer relaciones N-N (entidades intermedias de relación). Un ejemplo sería si tenemos una entidad de "Paises" y queremos relacionar varios paises a las cuentas para determinar el volumen de ventas de cada cliente por paises.
    En esta entidad intermendia "Ventas por paises", hay un atributo que es nombre de la entidad "new_name", dicho nombre realmente no tiene mucho sentido, pero es recomendable rellenarlo con algun valor, por ejemplo "Nombre de la cuenta" - "Pais", para que quede algo descriptivo en el nombre del registro.
    Para hacer esto deberiamos introducir en el evento "OnChange()":

    var oCuenta=crmForm.all.new_accountid.DataValue;
    var oPais=crmForm.all.new_paisid.DataValue;

    var sCuenta="";
    var sPais="";

    if (oCuenta!=null) sCuenta=oCuenta[0].name;
    if (oPais!=null) sPais=oPais[0].name;

    crmForm.all.new_name.DataValue=sCuenta + " - " + sPais;

    Además, para dejarlo mas completo, vamos a añadir en el "OnLoad()" y en el "OnSave()" lo siguiente:

    crmForm.all.new_pais.FireOnChange();

    Adicionalmente, el atributo "new_name" lo vamos a dejar deshabilitado en el formulario.
    Esto funcionaría correctamente en la creación, pero si intentamos actualizar el formulario, el atributo "new_name" no se actualiza mas.
    Esto ocurre porque los atributos del formulario que estan deshabilitados no son enviados al servidor, aunque hayan sido modificados.

    Para solucionar esto, hay que añadir lo siguiente en el evento "OnSave()" del formulario:

    if (crmForm.all.new_name.IsDirty)
    {
    crmForm.all.new_name.ForceSubmit=true;
    }

    Simplemente estamos preguntando si ese atributo ha sido modificado, y si es así, le decimos al formulario de CRM que envíe la modificación al servidor y actualice el registro.
    Mucho cuidado con esto: si ponemos todos los atributos con el ForceSubmit=true, los registros siempre serán actualizados, a pesar de que no haya cambios, lo que provocaría que siempre se disparen los workflows, los plugins relacionados, y actualizaría las fechas de modificación.

    Por lo tanto, utilizar el "ForceSubmit", pero con mucho cuidado.

    Un saludo!

    sábado, 14 de noviembre de 2009

    Como aplicar seguridad a nivel de atributo

    Esta semana Microsoft ha publicado un artículo muy interesante acerca de como aplicar seguridad a nivel de atributo en CRM.
    Como todos sabrán, Microsoft Dynamics CRM 4.0 no incluye dentro de su modelo de seguridad a la seguridad a nivel de atributo. Solo se pude aplicar seguridad a nivel de registro (segun el propietario, su unidad organizativa, etc.).
    A pesar de esto, las posibilidades de extensibilidad que ofrece el CRM, nos permite desarrollarnos nuestro propio modelo de seguridad, de forma que se aplique según las reglas o condiciones que deseemos nosotros.
    El artículo que esta semana ha publicado Microsoft nos puede servir de guia para ese desarrollo y la verdad que recomiendo tambien leerlo para poder comprender mas a fondo como funciona el CRM en sus "tripas".
    Lo que me ha resultado muy interesante es un gráfico donde explica donde son los "puntos de interacción" del CRM, es decir donde podemos recoger los eventos del CRM:

    Recomiendo leerse detenidamente este artículo, no solo para hacer un desarrollo a nivel de seguridad a nivel de atributos, sino para sacar ideas para hacer futuras cosas con el CRM.

    El documento puede descargarse de aquí: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=471f8670-47b3-4525-b25d-c11a6774615c

    un saludo

    jueves, 12 de noviembre de 2009

    Atención con los CustomerAddress utilizando DynamicEntity y FilteredViews

    Lo ideal al desarrollar con aplicaciones para CRM, es utilizar las famosas "DynamicEntity".
    De esta forma podemos realizar cualquier tipo de accion (crear, actualizar, etc.) con cualquier tipo de entidad.
    Para formatear correctamente los valores, podemos acceder primero a los MetaDatos de los atributos de la entidad, para saber de que tipo es el registro, y asi crear dinamicamente los atributos de la entidad "Dinámica".
    El problema surge con la entidad "CustomerAddress" en el atributo "objecttypecode". Este atributo es obligatorio y debe ser rellenado siempre para crear un registro de dirección. Al recoger el tipo del atributo, nos dice el CRM que es de tipo "Picklist", cuando en realidad es de tipo "EntityReference". Si intentamos crear una dirección pasando ese atributo como de tipo "Picklist", el CRM da un error y no nos lo permite.
    Para solucionar esto hay que crear una propiedad de tipo "EntityNameReferenceProperty".
    Para recoger el tipo del atributo hay que hacer:

    RetrieveAttributeRequest atrreq = new RetrieveAttributeRequest();
    atrreq.EntityLogicalName = "customeraddress";
    atrreq.LogicalName = "objecttypecode";
    RetrieveAttributeResponse atrresp = (RetrieveAttributeResponse)meta.Execute(atrreq);

    Y luego verificar el valor de "atrresp.AttributeMetadata.AttributeType".

    Nota adicional sobre la FilteredView: Si hacemos una consulta SQL en la vista "FilteredCustomerAddress", el atributo "parentid" que es la referencia a la Cuenta o Contacto relacionado con la dirección, no tiene el campo "parentidname" que deberia tener por ser un atributo de tipo "Customer".

    Conclusión: mucho cuidado al trabajar con "CustomerAddress", que tiene cosillas que no son del todo "Dinámicas" como en el resto de entidades, y podemos encontrarnos cosas raras.

    un saludo

    miércoles, 11 de noviembre de 2009

    Como controlar los ficheros adjuntos

    Como saben, en CRM se pueden añadir ficheros como adjuntos.
    Estos ficheros se adjuntan como "Notas" o como ficheros adjuntos en los correos electrónicos.
    El CRM no tiene ningun proceso de antivirus que controle los ficheros que se suben al CRM y que son almacenados en la base de datos de SQL Server.
    Muchas veces me preguntan como controlar que tipos de ficheros pueden subirse al CRM y como definir el tamaño máximo de dichos ficheros.
    Para definir esto hay que ir a Configuracion->Administración->Configuración del sistema.


    Allí, en la pestaña "General", se puede definir un listado de extensioens de ficheros "bloquedadas":


    Por último en la pestaña de "Correo electrónico" se puede definir el tamaño máximo de los adjuntos:

    viernes, 6 de noviembre de 2009

    Dejando rastro de los plugins

    Muchas veces necesitamos hacer pruebas y depuraciones para ver como llegan los datos en un plugin, en especial en relacion con los input/output parameters y las imágenes.
    Bueno, he preparado un plugin, que registra en una entidad de CRM, lo que ocurre cuando se dispara el plugin y nos deja el XML de esos parametros que "pasan" por el plugin.
    Para esto los pasos son:
    1) hacer un plugin con el siguiente código:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Crm.Sdk;
    using Microsoft.Crm.SdkTypeProxy;
    using System.Xml;
    using System.Xml.Serialization;
    using System.IO;

    namespace Logger
    {

    public class Log : IPlugin
    {
    public void Execute(IPluginExecutionContext context)
    {

    string sInputParameters = serializar(context.InputParameters);
    string sOutputParameters = serializar(context.OutputParameters);
    string sPreEntityImages = serializar(context.PreEntityImages);
    string sPostEntityImages = serializar(context.PostEntityImages);

    StringProperty strname = new StringProperty("new_name", context.PrimaryEntityName);
    StringProperty strmensaje = new StringProperty("new_mensaje", context.MessageName);
    StringProperty strinputparameter = new StringProperty("new_inputparameter", sInputParameters);
    StringProperty stroutputparameter = new StringProperty("new_outputparameter", sOutputParameters);

    StringProperty strpreimages = new StringProperty("new_preentityimages", sPreEntityImages);
    StringProperty strpostimages = new StringProperty("new_postentityimages", sPostEntityImages);

    DynamicEntity dyn = new DynamicEntity();
    dyn.Name = "new_log";
    dyn.Properties.Add(strname);
    dyn.Properties.Add(strmensaje);
    dyn.Properties.Add(strinputparameter);
    dyn.Properties.Add(stroutputparameter);
    dyn.Properties.Add(strpreimages);
    dyn.Properties.Add(strpostimages);

    ICrmService serv=context.CreateCrmService(true);
    serv.Create(dyn);
    }

    public string serializar(PropertyBag obj)
    {
    string sreturn = "";
    XmlSerializer serializer = new XmlSerializer(typeof(PropertyBag));
    if (obj != null)
    {
    using (MemoryStream xmlInputParameters = new MemoryStream())
    {
    serializer.Serialize(xmlInputParameters, obj);
    byte[] buffer = new Byte[xmlInputParameters.Length];
    xmlInputParameters.Seek(0, 0);
    xmlInputParameters.Read(buffer, 0, Convert.ToInt32(xmlInputParameters.Length));
    sreturn = System.Text.Encoding.ASCII.GetString(buffer, 0, Convert.ToInt32(xmlInputParameters.Length));
    }
    }
    if (sreturn.Length > 100000) //el crm no deja campos ntext mas grandes de 100.000 caracteres
    {
    sreturn = sreturn.Substring(0, 100000);
    }
    return sreturn;
    }
    }
    }
    El código como ven es bastante sencillo, lo único que hace es serializar los objetos a mostrar, y crear un registro de "Log" con la información.

    2) Importar las personalizaciones de la entidad donde se registrarán los datos. Descargar la misma desde aquí. (es una sola entidad, con el nombre "Log")

    3) Registrar la dll y añadirla al mensaje que deseamos "depurar" (se debe registrar en tantos eventos como deseemos):


    Los datos se irán registrando de la siguiente forma (nos deja quien diparó el evento, la entidad, el tipo, la hora y los parametros e imágenes):


    Los recursos para esto pueden ser descargados desde aquí:
  • Personalizaciones entidad Log

  • Fichero Dll


  • Espero pueda servirles en su vida con los "plugins".

    un abrazo

    jueves, 5 de noviembre de 2009

    Como poner una búsqueda avanzada en un formulario

    Para poner una búsqueda avanzada en un iframe en un formulario de CRM, simplemente deberemos copiar la URL de la vista y ponerla como un iframe:

    1) Hacer la vista y guardarla.

    2) Ir a "Vistas guardadas" y copiar la url de la Búsqueda avanzada:


    3) Crear un Iframe pegando la URL:

    martes, 3 de noviembre de 2009

    Ha salido una nueva versión de la SDK (4.0.10)

    Luego de mas de 4 meses, Microsoft ha publicado una nueva versión de la documentación de la SDK de Micrsofot Dynamics CRM 4.0.
    Puede ser descargada desde aquí: Microsoft Dynamics CRM 4.0 Software Development Kit (SDK)

    Hay algunos temas a destacar:
    1) Hacen una aclaración especial que es muy importante: "Important: Using scripts to hide HTML form elements that display fields, sections, or tabs is unsupported and is not upgradeable." . Esto hay que tenerlo en cuenta, ya que posiblemente todos hemos ocultado campos alguna vez, y seguramente no funcione esto con "CRM 5".
    2) En la documentación de las "SubArea" del Mapa del sitio (SiteMap) hay unos nuevos atributos documentados de "GetStartedPanePath", para definir el panel inicial del Area. (Solo para CRM Online)
    3) Mejorada la documentación para los "Pre-filtros" de los informes en Reporting Services.
    4) Se ha añadido la clase "Microsoft.Crm.SdkTypeProxy.XmlSerializers.dll" como assembly "Soportado".
    5) En la carpeta "\stylesheet" hay un HTML de ejemplo con sus imágenes y sus CSS de ejemplo de formularios de CRM.
    6) La herramienta para registro de plugins y Assemblies de workflows (PluginRegistrationTool) ha sido actualizada arreglando algunos "bugs".
    7) Artículo interesante para paginaciones de queries: "Using the Paging Cookie"
    8) Otro artículo interesante para desarrolladores: "Choosing Between the WSDL and Assemblies"

    Un saludo

    lunes, 2 de noviembre de 2009

    Como personalizar todas las vistas del CRM (incluso las ocultas)

    Muchas veces necesitamos personalizar vistas que el propio CRM no nos prmite de forma estándar modificar.
    Esto ocurre por ejemplo con la vista de "Todos los integrantes" de las Listas de marketing, que no nos permiten personalizar las columnas a mostrar. Voy a intentar explicar con un ejemplo práctico como sería la forma de hacer esto.
    No estoy seguro de si es algo soportado, pero como ocurre siempre, si tengo dudas considero que es algo no soportado.
    Los pasos a realizar son los siguientes:
    1) Hacer una consulta SQL en la base de datos:

    Select SavedQueryId from savedquerybase
    where name like '%Todos los integrantes%'
    AND ReturnedTypeCode=2
    Con esta consulta recogeremos el GUID de la vista que necesitamos modificar, buscando por el nombre de la vista y el "ReturnedTypeCode" (en este caso contact -2-).
    Una vez que tenemos el id, solamente tenemos que entrar a una URL pasandole dicho GUID y allí se podrá modificar la vista en cuestión:
    http://servidor/empresa/tools/vieweditor/viewManager.aspx?id={2F0D0EDE-D356-4B1E-83BD-E978F10E3EEB}

    Yo lo he probado con varias vistas y me ha funcionado correctamente, no estoy seguro si funcionará con todas las vistas, pero con este en particular si que va bien.

    Esta idea la he recogido del blog de Gryzzly Villoslado

    Un saludo