viernes, 31 de agosto de 2012

Error con UR 10: The element 'savedquery' has incomplete content. List of possible elements expected: 'LocalizedNames'.

Hola, como todos saben, recientemente Microsoft ha publicado el último “Update Rollup” (10) de CRM 2011 (http://www.microsoft.com/en-us/download/details.aspx?id=30711)

Como siempre recomiendo, estas actualizaciones son siempre necesarias ya que se solucionan error y se mejora el rendimiento. Pero esto hay que hacerlo SIEMPRE primero en entornos de desarrollo y probar todo bien.

Bien, ahora aparentemente con este Rollup ocurre un problema, que según he probado, solo pasa en entornos OnPremise migrados desde la versión 4.0.

El problema es que al exportar una solución que contenga cualquier entidad, y se desee volver a importar la misma, aparece el siguiente error:

The element 'savedquery' has incomplete content. List of possible elements expected: 'LocalizedNames'.

Investigando, he visto que esto ocurre porque al exportar hay un error, y se añade en el XML de la entidad una nueva vista que no debería estar allí, que no contiene el tag “LocalizedNames”.

Para ver el problema, podemos abrir el ZIP con la solución, y editar el fichero Customizacions.xml

image

Allí se puede ver esa nueva vista (que no aparece en ningún sitio) que no tiene nombres (“LocalizedNames”) y que tiene como columnas “statecode” y “ownerid” (Estado y Propietario).

Para solucionar este error de momento encontré 2 caminos (los dos son no soportados):

1) Añadir un nodo LocalizedNames a esta vista como por ejemplo:

image

2) Eliminar completamente esta vista.

De las dos maneras el error desaparece y parece que funciona correctamente.

De momento parece ser que no hay solución a este problema, les dejo un “hilo” del foro de Microsoft con otra gente que tiene este mismo problema.

http://social.msdn.microsoft.com/Forums/es-AR/crmdeployment/thread/19adc0c0-b888-499d-aa3a-d922e0c691da

Un saludo,

lunes, 20 de agosto de 2012

DynamicForm: Tutorial de implantación

Completando el artículo del otro día, lo que voy a hacer hoy es explicar como implementar paso a paso (“Step by Step”) la librería y como ponerla en funcionamiento.

La primera opción, podría ser el descargarse la solución completa de Codeplex y luego importarla: http://elblogdedynamicscrm.codeplex.com/releases/view/87885

La versión actual es la DynamicForm_2_1_0_0.zip. Importando y publicando la misma, ya podéis ver funcionando todo lo explicado en el formulario de Cuentas. Solo haría falta crearse algunos países en la entidad con el mismo nombre.

Tener en Cuenta que la solución tiene personalizaciones en Cuenta y Países, además de crear algunos web resources y en es “No Administrada”, por lo cual no se podrá desinstalar:

image

Otra opción pasaría por implementarlo poco a poco y a “mano”. La idea es mostrar como implementar la librearía en el caso real con los ejemplos que ya he montado yo. Esto permitirá entender como funciona.

Los pasos serían los siguientes:

1) Creación de WebResource DynamicForm:

image

El código fuente que se debe incluir en el mismo está en codeplex en el fichero DynamicForm_2.1.js: http://elblogdedynamicscrm.codeplex.com/SourceControl/changeset/view/14049#219034

2) Creación Web Resource con jquery:

image

El código fuente que se debe incluir en el mismo está en codeplex en el fichero jquery.js:

http://elblogdedynamicscrm.codeplex.com/SourceControl/changeset/view/14185#227690

3) Creación del Web Resource ReadDataSyncFunctions

image

El código fuente que se debe incluir en el mismo está en codeplex en el fichero ReadDataSyncFunctions.js:

http://elblogdedynamicscrm.codeplex.com/SourceControl/changeset/view/14186#227691

4) Creación del Web Resource con el XML de configuración

image

El código fuente que se debe incluir en el mismo está en codeplex en el fichero new_test_xml.xml:

http://elblogdedynamicscrm.codeplex.com/SourceControl/changeset/view/14187#227692

5) Creación de la entidad de Países:

image

6) En Cuentas se deben crear dos atributos, uno de tipo Lookup a Paises y otro de tipo ntext:

image

7) Personalizaciones en el formulario de Cuenta para añadir funcionalidades

En la siguiente imagen muestro como he dejado el formulario de cuentas, y he marcado los IFRAMES que he creado con sus nombres.

image

La configuración de los 3 IFRAMES es similar y es como lo siguiente:

imageimageimage

La idea es que en el formulario, estén añadidos todos los campos, secciones y pestañas utilizados en el XML anterior. Además es necesario crear los IFRAMES donde se incluirán las funcionalidades de combo, radio y múltiple selección.

8) Añadir los recursos web con el javascript que se utilizará en el formulario:

image

Es importante mantener el orden:

  • jquery
  • ReadDataSyncFunctions.js
  • DynamicForm

9) Añadir las llamadas necesarias en los eventos:

OnLoad y OnSave del formulario:

image

image

Y en los campos utilizados para las funcionalidades de la librería:

image

image

image

image

image

image

image

image

image

image

Espero les sirva este paso a paso a entender como está “montada” la solución y como funciona.

A partir de ahora intentaré ir mejorándola mas poco a poco.

Un abrazo a todos!

Demian.

viernes, 17 de agosto de 2012

Publicado Rollup 10 de CRM 2011

Se ha publicado el nuevo Rollup 10 para CRM 2011.
En este artículo se explica lo mas importante de este Rollup: http://blogs.msdn.com/b/crminthefield/archive/2012/08/13/overview-and-podcast-update-rollup-10.aspx

Lo más importante a tener en cuenta con este Rollup, se incluye en este artículo, relacionado con temas de optimización de CRM: "Optimizing and Maintaining the Performance of a Microsoft Dynamics CRM 2011 Server Infrastructure": "http://www.microsoft.com/en-us/download/details.aspx?id=27139

Para descargarlo: http://www.microsoft.com/en-us/download/details.aspx?id=30711&WT.mc_id=rss_allproducts_dynamics
 Artículo KB completo: http://support.microsoft.com/default.aspx?kbid=2710577

un saludo,

lunes, 13 de agosto de 2012

DynamicForm: Resumen de funcionalidades

Hola, creo que ha llegado el momento de hacer un pequeño (y rápido) resumen, de todas las funcionalidades incluidas hasta hoy en nuestra librería.
El objetivo de esta librería no es solamente ofrecer funcionalidades adicionales que CRM 2011 no tiene, sino también ir explicando como lo voy haciendo, para dejar ideas de como añadir funcionalidades en CRM 2011 diferentes.
Como todos saben, la idea principal de la misma, es que mediante un XML ubicado en un WebResource de Dynamics CRM 2011, se puedan definir comportamientos dinámicos dentro del formulario de CRM.
De esta manera, se puede “jugar” con estas funcionalidades sin necesidad de programar nada en javascript, sino que los comportamientos pueden ser administrados mediante la modificación del XML y alguna personalización.
La idea en resumen es como lo siguiente:
image
Las soluciones completas, códigos fuentes y documentaciones las tenemos incluidas en un sitio común y abierto en CodePlex: http://elblogdedynamicscrm.codeplex.com/documentation
A continuación haré un resumen de cada una de las funcionalidades. Para ver mas en profundidad acerca del funcionamiento de cada una, recomiendo revisar los correspondientes artículos publicados anteriormente.
1) Ocultamiento de campos, secciones, pestañas y nivel de requerimiento de campos dinámico dependiendo de una condición del valor de un campo.
En el siguiente XML, se puede definir un campo de condición, y dependiendo del valor seleccionado de mismo, se pueden ocultar o mostrar campos, secciones y pestañas. Además se puede definir el nivel de requerimiento de los campos (obligatorio, recomendado u opcional).
   1: <attributes>
   2:     <attribute name="accountcategorycode" value="1" 
   3:         showattributes="primarycontactid,accountnumber"hideattributes="" 
   4:         showsections="general/address,general/shipping information" 
   5:         hidesections="" showtabs="notes and activities,administration" hidetabs="" 
   6:         setrequiredlevel="required:fax-address1_city,recommended:address1_name"/>
   7:     <attribute name="accountcategorycode" value="2" showattributes="" 
   8:         hideattributes="primarycontactid,accountnumber" showsections="" 
   9:         hidesections="general/address,general/shipping information" 
  10:         showtabs="" hidetabs="notes and activities,administration"
  11:         setrequiredlevel="none:fax-address1_city-address1_name-websiteurl"/>
  12: </attributes>
image

2) Concatenaciones de campos

Con el siguiente XML, se puede definir una “action” en donde se define un campo destino, y varios campos que serán concatenados. Además se puede definir que valor tendrá el string de concatenación.


   1: <action type="concat" destattribute="description" 
   2:     attributestoconcat="address1_name,address1_line1,address1_line2,address1_line3,
   3:     address1_city,address1_postalcode,address1_stateorprovince,address1_country,
   4:     address1_telephone1"
stringseparator=";"/>

image

3) Validaciones de campos según tipos
La idea de esta funcionalidad es que se puedan definir validaciones de campos dependiendo del contenido de negocio que se le quiere dar a determinados campos. Por ejemplo, validar que solo se introduzcan númericos, campos de tipo dirección de correo electrónico, de tipo dirección ip, de tipo URL, etc.
Esto se define con el siguiente XML, que además contempla que los mensajes de error en las validaciones aparezca en la parte superior de formulario:

   1: <validations>
   2:     <validation attributename="accountnumber" type="number" RegEx=""/>
   3:     <validation attributename="address1_name" type="email" RegEx=""/>
   4:     <validation attributename="address2_line1" type="ipaddress" RegEx=""/>
   5:     <validation attributename="address2_line2" type="url" RegEx=""/>
   6: </validations>


 
image



4) Diseño de los campos del formulario

Mediante los siguientes XML lo que se puede hacer es cambiar los colores de fondo de los campos y de los textos.

   1: <action type="backgroundcolor" attributename="description" color="#FFF00F"/>
   2: <action type="backgroundcolor" attributename="address1_line1" color="#FF660F"/>
   3: <action type="backgroundcolor" attributename="address1_line2" color="#33300F"/>
   4: <action type="backgroundcolor" attributename="address1_line3" color="#55500F"/>
   5: <action type="fontcolor" attributename="address1_line2" color="#FFFFFF"/>
   6: <action type="fontcolor" attributename="address1_line3" color="#FFFFFF"/>

 
image


5) Convertir un Lookup en un despegable

La idea de este XML, es que la introducción de un campo de tipo Lookup, pueda ser realizada mediante un desplegable.


   1: <action type="lookuptocombo" attributename="new_paisid" entityname="new_pais" 
   2:     entityid="new_paisid" entityattributename="new_name" iframename="IFRAME_pais"/>

image



6) Convertir un Lookup en un selector de tipo Radio

El siguiente XML, convierte un campo de tipo Lookup en un selector de tipo radio.


   1: <action type="lookuptoradio" attributename="new_paisid" entityname="new_pais" 
   2:     entityid="new_paisid" entityattributename="new_name" iframename="IFRAME_paisradio"/>
image


7) Introducción de un campo de tipo selector múltiple (checkbox) de una entidad

La idea de esta funcionalidad, es que mediante un selector múltiple (checkboxes), se puedan seleccionar diversos valores provenientes una entidad de CRM.

El XML que define esta funcionalidad es el siguiente:


   1: <action type="multipleselect" attributename="new_paises" entityname="new_pais" 
   2:     entityid="new_paisid" entityattributename="new_name" iframename="IFRAME_paismultiple"/>

image


Bueno, esperamos seguir avanzando con mas ideas y mas funcionalidades. Se aceptan sugerencias Guiño


un saludo,

miércoles, 8 de agosto de 2012

Citas periódicas: atributo daysofweekmask

Una de las nuevas funcionalidades de CRM 2011 es la posibilidad de crear Citas periódicas.

En el formulario de las mismas se puede definir una periodicidad definiendo una serie de días de la semana:

image

Estos “Checkboxes” de días se almacenan en un atributo de la entidad RecurringAppointmentMaster (http://msdn.microsoft.com/en-us/library/gg334207.aspx) que se llama “daysofweekmask” de tipo “Integer”.

En realidad, esto almacena un número con todas las combinaciones posibles de días que puede haber entre estos 7 valores. El tema es que si quiere crear citas periódicas por código, necesito saber que valores introducir. Para esto lo que se hace es asignar valores a cada uno de los días y sumando los valores asignados a cada uno de los seleccionados, nos dará cada uno de los 127 posibles números.

Domingo 1
Lunes 2
Martes 4
Miércoles 8
Jueves 16
Viernes 32
Sábado 64

La asignación completa de dicha tabla no está en la SDK y puede consultarse aquí: http://technet.microsoft.com/en-us/library/ee808920.aspx

Así, por ejemplo si quiere que algo se ejecute los lunes(2) y miércoles(8) el valor a introducir en daysofweekmask es 10.

Un saludo,

lunes, 6 de agosto de 2012

DynamicForm 2.1: Selección múltiple de Lookups

En Microsoft Dynamics CRM 2011, como sabrán existen algunos campos de tipo Lookup en los que se pueden seleccionar varios valores, pero esta funcionalidad no es genérica y solo está habilitada para algunos campos por ejemplo los partylist (como los de asistentes de una cita o destinatarios de un Email, etc.).
Bien, la idea de hoy es añadir una funcionalidad genérica, que permita de manera sencilla seleccionar varios valores de una tabla relacionada.
El resumen de la entrega de hoy:
Formulario: Cuenta
Evento: OnLoad()
Atributos: (new_paises).
Funcionalidad: Al cargar el formulario, en un IFRAME se crea dinámicamente un listado de checkboxes con los valores de los países disponibles. Mientras se van seleccionando o eliminando los valores de los checkboxes, en un campo ntext, se concatenan los valores seleccionados con sus Guids y sus nombres. 
Todo este ejemplo estará como siempre disponible en Codeplex:
http://elblogdedynamicscrm.codeplex.com/documentation
En el XML, he añadido una nueva acción:
   1: <action type="multipleselect" attributename="new_paises" entityname="new_pais" 

   2:  entityid="new_paisid" entityattributename="new_name" iframename="IFRAME_paismultiple"/>

La nueva acción se llama “multipleselect” y como su nombre lo indica. Los atributos son los siguientes (iguales al de las versiones anteriores de lookuptocombo y lookuptoradio): 
  • attributename: nombre del campo de tipo ntext en donde se concatenan los valores en el formulario
     
  • entityname: nombre de la entidad a donde apuntan los checkboxes
     
  • entityid: nombre del campo clave de la entidad
     
  • entityattributename: campo nombre de la entidad que será utilizado para enseñar los valores del desplegable.
     
  • iframename: nombre del iframe donde se incluirá el listado de checkboxes dinámicamente.
He creado un nuevo método que realiza las acciones que se llama MultipleSelect:

   1: function MultipleSelect(attributename,entityname,iframename,entityid,entityattributename)

   2: {
   3:     var result=RetrieveEntitiesByFilter (entityname, "statecode", "Active", entityid+","+
   4:         entityattributename, false, "");
   5:     var i=0;
   6:     var svalue="";
   7:     var svalue=getValue(attributename);
   8:     if (!svalue)
   9:     {
  10:         svalue="";
  11:     }
  12:     var HTMLselect="<form style='font-size:11Px;font-family:Segoe UI, Tahoma, Arial;'>";
  13:     for (i=0;i<result.recordCount;i++)
  14:     {
  15:         var selected="";
  16:         var name=eval("result[i]."+entityattributename);
  17:         var id=eval("result[i]."+entityid);
  18:         
  19:         if (svalue.indexOf(id)!=-1)
  20:         {
  21:             selected="CHECKED";
  22:         }
  23:        
  24:         var js="onclick='parent.ActualizoSelects(document,"+result.recordCount+",
  25:                     document.all.attributename.value);'"
;
  26:         HTMLselect+="<input "+js+" type='checkbox' name='opt"+i+"' id='opt"+i+
  27:                 "' nombre='"+name+"' value='"+id+"' "+selected+" /> "+name+"<br />";
  28:     }
  29:     HTMLselect+="</form> ";
  30:     HTMLselect+="<input type='hidden' id='entityname' name='entityname' 
  31:         value='"
+entityname+"'/><input type='hidden' id='attributename'
  32:         name='attributename' value='"
+attributename+"'/>";
  33:     var myIframe=document.getElementById(iframename);
  34:     myIframe.contentWindow.document.body.innerHTML = HTMLselect;
  35:     myIframe.contentWindow.document.body.style.margin="0px;";
  36: }

El funcionamiento es muy similar a los looktocombo y lookuptoradio pero en este caso cambia un poco el funcionamiento en cuanto a la función que se llama para realizar los cálculos que es “ActualizoSelects()”:


   1: function ActualizoSelects(doc,cant, attributename)
   2: {

   3:     var str='';var i=0;
   4:     for (i=0;i<cant;i++)
   5:     {        
   6:         if (doc.getElementById('opt'+i).checked)
   7:         {
   8:             if (i!=0)
   9:             {
  10:                 str+="\n";
  11:             }
  12:             str+=doc.getElementById('opt'+i).value+';'+doc.getElementById('opt'+i).nombre;
  13:         }
  14:     }
  15:     setValue(attributename,str);
  16: }
Esta función recorre todos los checkboxes y se genera un “string” concatenando los valores con sus ids y nombres en formato .csv.

El ejemplo y la solución completa funcionando la he dejado como siempre en CodePlex.

En el formulario la funcionalidad sería como lo siguiente:

image


La idea es que en el campo “new_paises” se concatena esa cadena de caracteres en formato .csv. De esta manera, se puede utilizar también este campo en las búsquedas avanzadas.