20/2/08

Cerrar automáticamente actividades de una campaña

Este problema ha surgido varias veces y hasta ahora no se me había ocurrido una solución satisfactoria. Cuando creamos una campaña (express o no) de marketing, si usamos un canal como cartas o tareas, tenemos que tener a una persona (o varias) que vayan cerrando las actividades cerradas. Esto está bien para un telemarketing o una distribución de trabajos entre varias personas.

¿Pero qué pasa si lo que estamos haciendo es un envío masivo de cartas que envía una sola persona y de una sola vez? ¿Le obligamos a irlas cerrando una por una? No existe el Cerrar masivocomo existe la edición masiva. Tampoco podemos lanzar un workflow sobre un conjunto de actividades. Tampoco parece buena opción ni siquiera registrar la acción, al fin y al cabo para eso tenemos la herramienta en un entorno de marketing.

¿Qué se me ha ocurrido? Suena un poco chapuza: crear una regla de Workflow sobre las cartas que, cuando detecta que están asociadas a una campaña, las cierra automáticamente al cabo de un cierto tiempo. ¿Y cómo las detecta? Sólo se me ocurre poner alguna marca en la categoría, por ejemplo MAILING.



Así quedaría una regla de este tipo. Habría que hacer lo mismo para los otros tipos de actividades que lo requieran. Y aleccionar a los usuarios para que se use bien, claro.

1/2/08

Uso de ObjectDataSource contra CRM


Imaginemos que queremos llegar a esto: una página ASPX que permita leer y modificar datos de CRM, por ejemplo de una cuenta de cliente. Hay mil maneras de hacerlo, sólo que esta a mi me parece especialmente elegante por el poco código que hay que añadir. Es una solución al estilo ASP.NET 2.0, así que vamos a trabajar con Visual Studio 2005 (o 2008).
Lo primero es crear el código del componente de datos, que actuará de intermediario entre el control ObjectDataSource y el web service de CRM. La clase se llama Cuenta y representa la capa de lógica de negocio especializada en operaciones sobre cuentas de cliente. Por cierto, ¿alguien sabe cómo colorear sintaxis (facilmente) en Blogger?


using System;
using System.ComponentModel;
using CrmNetLib.CrmSdk;

namespace CrmNetLib
{

[DataObject]
public class Cuenta
{
private CrmService crm;

public Cuenta()
{
crm = new CrmService();
crm.Credentials = System.Net.CredentialCache.DefaultCredentials;
}

[DataObjectMethod(DataObjectMethodType.Select, true)]
public account Buscar(Guid id)
{
return (account)crm.Retrieve(EntityName.account.ToString(),
id, new AllColumns());
}

[DataObjectMethod(DataObjectMethodType.Update, true)]
public void Actualizar(account cuenta)
{
crm.Update(cuenta);
}



}
}




Fijaos en los atributos DataObject y DataObjectMethod. Sirven para que el asistente del ObjectDataSource que pondremos en la página reconozca el objeto como candidato a fuente de datos. Y ahora vamos a la página aspx: lo primero que hacemos es añadir un objeto ObjectDataSource configurando su fuente al objeto comercial (=de lógica de negocio) Cuenta. En mi caso lo he definido en un proyecto aparte de nombre CrmNetLib, pero podría estar en el mismo proyecto, por ejemplo dentro de la carpeta App_Code.




En la siguiente pantalla del asistente, configuramos los métodos de búsqueda y actualización para que apunten a los métodos Buscar y Actualizar de nuestra clase. En un caso más completo, sólo nos faltaría mapear también los métodos de borrado e inserción.









Como el método de búsqueda tiene un parámetro (el id de la cuenta), tenemos que relacionarlo con algún valor de entrada. Escogemos el QueryString de la página, con lo que la URL de acceso tendrá el siguiente aspecto:



http://www.servidor.com/aplicacion/editarcuenta.aspx?id=//GUID de la cuenta//




Por otro lado, el método de actualización recibe un parámetro de tipo account sacado directamente de la SDK de CRM que representa una cuenta con todos sus atributos. También podríamos usar un método que tuviera como parámetros los atributos del objeto, en este caso id, nombre, teléfono y fax.



Ahora sólo queda añadir el control DetailsView para ver los datos de la cuenta. Una vez en la zona del diseñador, escogemos el ObjectDataSource como fuente de datos. Aparecerán todos los campos de la clase account(o sea, muchos campos(.





Para reducirlos a un número manejable, sólo tenemos que escoger la opción Editar campos... Decido quedarme con nombre, teléfono y fax. Si además habilitamos la edición del control, ya habremos terminado en un tiempo record una página de edición de cuentas.

Este es el aspecto final de la página en el diseñador de Visual Studio:




24/12/07

CRM vs. SharePoint

Aparte de parecer el título de una película estilo "Alien vs. Predator", o más que un artículo es una declaración de intenciones de las que se hacen típicamente en estas fechas. Se trata de enumerar las maneras que existen (que se me ocurren) de conectar SharePoint y CRM, de forma más genérica primero y luego con ejemplos concretos en artículos individuales (y aquí es donde empiezan las buenas intenciones).

Integración visual en CRM Podemos añadir un IFRAME a un formulario de CRM que muestre una página de SharePoint. La página en cuestión podría (debería) estar libre de decoraciones estilo SharePoint para que el encaje sea más limpio. Esto se puede hacer fácilmente con SharePoint designer. Por ejemplo: para una cuenta de CRM, mostrar en su formulario una biblioteca de documentos de SharePoint con los documentos asociados al cliente. La URL de SharePoint se puede crear dinámicamente en el evento OnLoad del formulario, y debería incluir información para filtrar la biblioteca, por ejemplo el número de cliente.

CRM List Web Part Muestra una lista de entidades de CRM dentro de SharePoint (WSS o MOSS). También permite (como muchos otros web parts) filtrar detalles de otro web part. Por ejemplo: un Web Part con una lista de cuentas de CRM y otro conectado con los contactos asociados. Se puede descargar aquí y ya lo ha contado (mejor) Marco Amoedo en este post. Sencillo de configurar, pero con pocas funcionalidades y - en principio - no extensible, puesto que el código no está disponible.

Business Data Catalog Dentro de MOSS 2007 tenemos el gran invento del BDC: una herramienta que nos permite ver datos externos a SharePoint integrados como Web Parts. A diferencia del sistema anterior, es un sistema genérico que permite conectar a cualquier base de datos, (digamos Oracle, MySQL etc.) y necesita ser configurado abundantemente a nivel SQL. Para empezar, necesitaremos una Application Definition File específica para la fuente de datos. Hay gente que ha desarrollado la apropiada para CRM, en concreto Rehman Gul en este ejemplo.

Worflows/CallOuts/Plugins de CRM En cualquiera de sus versiones (la más clásica de CRM 3.0 o la nueva de CRM 4.0 integrada con Windows Workflow Foundation) podemos detectar eventos de CRM que actualicen o creen información en SharePoint. En el caso de los wf de CRM 3.0, estos eventos están limitados a la creación, cambio de estado y cambio de propietario. Con los CallOuts/Plugins no tenemos esta limitación. Por ejemplo: cada vez que se crea una cuenta de cliente en CRM, podríamos lanzar un proceso que cree una biblioteca de documentos en SharePoint. Habría que desarrollar la funcionalidad utilizando la SDK de SharePoint en una dll que integrar como una acción del workflow de CRM (versión 3.0). Para la versión 4.0 habría que desarrollar una CustomActivity.

Workflows de SharePoint Buenas noticias, también basados en WF. Tanto en WSS como en MOSS podemos asociar workflows a listas o bibliotecas de documentos. Las acciones elementales del workflow son actividades que pueden incluir cualquier código personalizado, incluyendo llamadas a la SDK de CRM. Por ejemplo: podríamos tener un sitio de SharePoint expuesto en Internet que permita al usuario dar de alta una solicitud de servicio en una lista especializada. El wf asociado a la lista podría crear un incidente en nuestro CRM a través de la SDK. Ventaja: la interfaz de usuario final es la propia de SharePoint. Si estamos en un sitio de "publishing" podemos darle el aspecto que queramos con sólo cambiar el diseño de la página con SharePoint designer.

Web Parts La SDK de WSS permite desarrollar nuestros propios Web Parts, que ahora además están totalmente integrados en ASP.NET 2.0, así que podemos probarlos en cualquier página aspx, no sólamente en un site de SharePoint. La idea es la misma que en el punto anterior, pero más cercano a la interfaz de usuario: el Web Part llama a la SDK de CRM directamente, sin que haya un almacenamiento en SharePoint. El ejemplo: el mismo del punto anterior, pero sin lista en SharePoint. La pega: tenemos que diseñar la interfaz de usuario directamente en código (C# o VB) sin un editor visual a través de un CustomControl de ASP.NET 2.0

Servicio Windows Esta es la versión asíncrona de algunas de las opciones que hemos visto. La idea es tener relacionados una entidad de CRM (digamos Artículos de la KB) con una lista/biblioteca de SharePoint. Un servicio periódico utlizaría ambas SDKs para sincronizar los elementos concordantes. Habría que añadir una columna a la lista con el GUID de CRM y un campo en la entidad de CRM con el identificador de SharePoint para hacerlo posible.

15/12/07

Mi primer Redeployment/Reimplementación de CRM 3.0

Suena como un anuncio de colonia, ya lo sé. El caso es que me he encontrado con algunos problemillas (qué sorpresa) y aquí van, para que no se olvide. En líneas generales, el proceso que se explica en la carpeta RedeploymentTool es correcto. Sólo añadir que:
  • El backup de la base de datos original no debería incluir los usuarios (SQLAccessGroup y demás) que crea la instalación de CRM. Estarán basados en el directorio activo antiguo. Aunque se vaya a instalar sobre el mismo directorio activo, no conviene que estén, pues la instalación intentará volver a crearlos y dará un error, poco explicativo, por cierto de tipo GrantDatabaseAccessAction.
  • Puede que dé un error AddLicenseAction. Se puede omitir, como recomienda Matt Parks aquí, pero también se puede entrar a la base de datos, tabla Licenses, y cambiar (por ejemplo) una letra de la clave de activación. El programa de instalación machacará esta tabla, en cualquier caso.
Por lo demás, todo fue bien, aunque me sorprendió no encontrar demasiada información en la web sobre Redeployment. Es una herramienta fundamental para fabricar entornos de prueba.

14/12/07

Plantillas de correo y "slugs"

Aviso que esta entrada es de las de "no te olvides de...". Se trata de las plantillas de correo electrónico, una herramienta muy potente de CRM que, sin embargo, tiene sus limitaciones. En principio podemos copiar cualquier HTML a nuestra plantilla con un copiar y pegar. Todo va bien hasta que intentas copiar estilos que hayan sido definidos en la cabecera. Por ejemplo:

<style type="text/css">
H1 {border-width:1;border:solid;text-align:center}
</style>

La primera en la frente: el "copiar y pegar" tan sólo copia la parte de BODY, no la de HEAD. Así que tendremos que utilizar el estilo directamente en cada etiqueta:

<h1 style="border-width:1;border:solid;text-align:center">Titulo</h1>

Vamos con otra: los slugs. Los slugs son cadenas que permiten introducir campos de la entidad en el texto de la plantilla. Por ejemplo, para insertar el nombre de un contacto, podemos poner

Estimado {!contact:firstname;}

Un cliente pensó (con razón) que sería interesante poner un enlace en HTML a una aplicación web en la plantilla. Algo como

<a href='http://www.emp.com/registro.aspx?id={!account:accountid;}>Registro online</a>

Como véis, hemos metido un slug dentro de una etiqueta de código HTML. Además, hemos escogido el campo accountid que es un GUID que en la interficie de usuario está oculto. ¿Funciona esto? Pues sí y no. Para empezar, no creo que esté soportado. De hecho, el editor de HTML de la plantilla da errores a veces imprevisibles. Lo que he aprendido (a base de golpes) es que, por ejemplo, si en lugar de poner comillas simples (como en el ejemplo anterior) ponemos comillas dobles el editor falla y no podemos guardar la plantilla. Es sólo un ejemplo de los problemas que puede dar. Pese a todo, merece la pena echarle un vistazo.

29/10/07

Prefiltrado en infomes

Aquí va una pequeña advertencia y recordatorio - sobre todo para mi mismo - acerca del prefiltrado de informes en CRM. Esta característica es muy, muy útil, ya que te permite reutilizar un mismo informe de muchas maneras, tan sólo cambiando el filtrado. Este prefiltrado se gestiona desde CRM - no desde el diseño del informe - a través de la interfaz habitual de búsqueda avanzada. De esta forma, un informe de Incidentes cerrados la última semana se puede convertir en Incidentes cerrados para clientes con más de 500 empleados el último año o cualquier otra cosa que nos permita hacer la búsqueda avanzada.

En principio lo unico que hay que hacer (cito el MOC de personalización) es ponerle a las entidades que queramos prefiltrar un alias que comience por CRMAF_ . En el siguiente ejemplo, he escogido como alias CRMAF_FI para representar los casos, o sea la vista FilteredIncident.


SELECT CRMAF_FI.ticketnumber, CRMAF_FI.customeridname
FROM FilteredIncident AS CRMAF_FI


Este informe permitirá prefiltrar por atributos del caso. Lo podemos complicar un poco más añadiendo la tabla de cuentas:


SELECT CRMAF_FI.ticketnumber, CRMAF_FA.name
FROM FilteredIncident AS CRMAF_FI
INNER JOIN FilteredAccountt AS CRMAF_FA
ON FilteredIncident.customerid = FilteredAccount.accountid


Esto nos permitirá prefiltrar por caso y/o cuenta. Bueno, pues aquí viene la advertencia: el editor de informes integrado en Visual Studio añade delante de cada vista o tabla un dbo. que hace que deje de funcionar el prefiltrado. Por ahora, se lo tengo que quitar a mano con un Reemplazar, porque no he encontrado la opción para evitar este comportamiento.

25/10/07

Crear un contrato por código

Admitámoslo, crear un contrato en CRM es una pesadez. Al menos eso es lo que dicen algunos de los usuarios del módulo de servicio que conozco. Hay que seleccionar el cliente, crear el contrato, establecer la plantilla de contrato, fechas de inicio y finalización (cuatro en total), las direcciones (dos), añadir la línea de contrato, volver a poner las fechas de inicio y finalización, establecer el precio...

Bueno, pues todo esto es lo que hace este tocho código que véis aquí debajo. No es perfecto, pero puede ahorrar algo de tecleo.

public static Guid CrearContrato(
Guid idCuenta,
Guid idPlantillaContrato,
int numeroMinutos,
int importe)
{
// Buscar los datos del cliente
ColumnSet cs = new ColumnSet();
cs.Attributes = new string[] { "name", "address1_addressid" };
account cuenta =
crm.Retrieve(EntityName.account.ToString(), idCuenta, cs) as account;

// Buscar los datos de la plantilla
contracttemplate plantilla =
crm.Retrieve(EntityName.contracttemplate.ToString(), idPlantilla,
new AllColumns());

// Crear un título para el contrato
string tituloContrato = String.Format(
"{0} - {1} {2} min ({3:MM/yy})",
cuenta.name, plantilla.name, numeroMinutos, DateTime.Now);

// Establecer fechas (contrato de 10 años de duración)
string fechaInicio =
DateTime.Now.ToString("yyyy/M/ddT00:00:00");
string fechaFin =
DateTime.Now.AddYears(10).ToString("yyyy/M/ddT00:00:00");

// Crear el contrato
contract contrato = new contract();
contrato.contracttemplateid = new Lookup();
contrato.contracttemplateid.Value = idPlantillaContrato;
contrato.customerid = new Customer();
contrato.customerid.Value = idCuenta;
contrato.customerid.type = EntityName.account.ToString();
contrato.billingcustomerid = contrato.customerid;
contrato.activeon = new CrmDateTime();
contrato.activeon.Value = fechaInicio;
contrato.expireson = new CrmDateTime();
contrato.expireson.Value = fechaFin;
contrato.billingstarton = new CrmDateTime();
contrato.billingstarton.Value = fechaInicio;
contrato.billingendon = new CrmDateTime();
contrato.billingendon.Value = fechaFin;
contrato.serviceaddress = new Lookup();
contrato.serviceaddress.Value = cuenta.address1_addressid.Value;
contrato.billtoaddress = new Lookup();
contrato.billtoaddress.Value = cuenta.address1_addressid.Value;
contrato.title = tituloContrato;
Guid idContrato = crm.Create(contrato);

// Crear la línea de detalle del contrato
contractdetail linea = new contractdetail();
linea.title = "Linea " + tituloContrato;
linea.contractid = new Lookup();
linea.contractid.Value = idContrato;
linea.activeon = new CrmDateTime();
linea.activeon.Value = fechaInicio;
linea.expireson = new CrmDateTime();
linea.expireson.Value = fechaFin;
linea.customerid = new Customer();
linea.customerid.type = EntityName.account.ToString();
linea.customerid.Value = idCuenta;
linea.totalallotments = new CrmNumber();
linea.totalallotments.Value = numeroMinutos;
linea.price = new CrmMoney();
linea.price.Value = importe;
Guid idLinea = crm.Create(linea);

return idContrato;
}

4/10/07

Accediendo a CRM con ASP.NET 2.0

Se puede (?) ver aquí debajo mi primera prueba de video blogger sobre programación.




Se trata de llamar a los web services de CRM a través de un ObjectDataSource, que permite encapsular los comandos SELECT, UPDATE, INSERT y DELETE típicos en un objeto de lógica de negocio. Para el caso, se han mapeado a los métodos Retrieve, Update, Create y Delete del CrmService. Luego se muestran los resultados con DataBinding a un control DetailsView, que permite ver todos los campos de un registro.

23/7/07

Llamar a web services de CRM desde JavaScript

En este thread de las news de CRM en español firmado por Nuria he encontrado un enlace a un blog donde se cuenta una alternativa cómoda para llamar a los web services de CRM desde JavaScript en cliente. En concreto, se trata de cómo ocultar/mostrar campos de un formulario en función de los roles a los que pertenece el usuario.

La entrada de blog es de Ronald Lemmen y se encuentra aquí.

Muy chulo (¡pero ojo, no soportado!)

25/5/07

Autonumeración "a la carta" en CRM

Todos hemos visto cómo Microsoft CRM genera códigos automáticos para unos pocos tipos de registros: Contratos, Ofertas, Pedidos, Facturas y artículos de la Knowledge Base. ¿Qué podemos hacer si necesitamos que, además de estas entidades, alguna otra se autonumere también? Pues recurrir a la personalización del formulario correspondiente haciendo que llame a un pequeño servicio que programaremos en el servidor.

Empezaremos por programar el servicio de autonumeración. Abrimos Visual Studio y generamos un proyecto web sobre la misma carpeta en la que tenemos el servidor de CRM. En este caso, la he llamado autonum.



Para que nuestro proyecto web conecte con el servidor de CRM, sólo tenemos que añadir una referencia Web a su Web service, que como sabéis está en

http://maquina:puerto/MSCRMServices/2006/crmservice.asmx


Le damos un nombre apropiado a la referencia, por ejemplo CrmSdk.



Ahora, creamos un nuevo WebForm y le damos el nombre default.aspx Esta será la página que nos proporcionará los números correlativos para nuestra entidad. Aquí tenéis el código:


void Page_Load(object sender, System.EventArgs e){
string entidad = Request["e"];
string campo = Request["c"];
string prefijo = Request["p"];
string numCars = Request["n"];
string formato = "{0}{1:D" + numCars + "}";
string anterior = UltimoCodigo(entidad, campo);
string parteNumerica = anterior.Substring(prefijo.Length);
int num = 1 + Int32.Parse(parteNumerica);
Response.Write(String.Format(formato, prefijo, num));
}

string UltimoCodigo(string entidad, string campo) {
string fetch = @"<fetch count='1' mapping='logical'>
<entity name='{0}'>
<order attribute='createdon' descending='true'/>
<attribute name='{1}'/>
</entity>
</fetch>";
fetch = String.Format(fetch, entidad, campo);
CrmService crm = new CrmService();
crm.Credentials = System.Net.CredentialCache.DefaultCredentials;
string res = crm.Fetch(fetch);
XmlDocument dom = new XmlDocument();
dom.LoadXml(res);
XmlNode nodoCuenta = dom.SelectSingleNode("//" + campo);
if (nodoCuenta != null)
return nodoCuenta.FirstChild.Value;
else
return "?";
}



Como véis, lo único que hace es lanzar una consulta FetchXml que busca la última entidad creada (ordenando por el campo createdon) y extrae su código, que puede ser cualquier atributo que escojamos. En el ejemplo, la entidad es account y el campo accountnumber.

Ahora tenemos que personalizar el evento OnLoad de la entidad para que, al cargarse un nuevo formulario, se conecte a nuestra página en el servidor y rellene su valor en el campo que hayamos escogido. Vamos a Configuración - Personalización y escogemos la entidad Cuenta. Luego, escogemos su formulario y abrimos sus propiedades:




El código Javascript utiliza una conexión al estilo AJAX con el objeto XmlHttp. Como la llamada es asíncrona, no bloqueará el formulario para la introducción de otros datos. Aquí tenéis el código:

if (crmForm.FormType != 1)
return;
var entidad = "account";
var campo = "accountnumber";
var prefijo = "A-";
var numCars = 4;
var xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
var params = "?e=" + entidad +"&c=" + campo + "&p=" + prefijo + "&n=" + numCars;

xmlHttp.open("GET", "/autonum" + params, true);
xmlHttp.setRequestHeader('Content-Type', 'text/xml');
xmlHttp.send('');

xmlHttp.onreadystatechange=function() {
if(xmlHttp.readyState == 4 && xmlHttp.status == 200)
{
var objDoc = xmlHttp.responseText;
if( xmlHttp.responseText.length > 0 )
crmForm.accountnumber.DataValue = xmlHttp.responseText;
}
}

A continuación, publicamos las personalizaciones y nos vamos a la lista de cuentas.




La última cuenta cread tiene el código A-0126. Hemos configurado los parámetros de la llamada para que considere el prefijo A- y utilice 4 dígitos en el código. Cuando le damos al botón Nuevo ...



Aparece la ventana de creación de nuevas cuentas, pero esta vez con el siguiente número de cuenta rellenado automáticamente. ¡Conseguido!

18/5/07

Cambiar la vista asociada por defecto

Os redirijo al blog de un colega que ha traducido y adaptado un artículo de stunnware donde se explica cómo cambiar la vista asociada por defecto de cualquier entidad de CRM. Por ejemplo, que muestre todas las actividades del historial de un cliente en lugar de sólo las de los últimos 30 días.

Inglés (Stunnware): http://www.stunnware.com/crm2/topic.aspx?id=JS11
Castellano (Jordi Bilbao): http://bloqjb.blogspot.com/2007/04/cambiar-la-vista-por-defecto-crm-30.html

Es una personalización no soportada, ojo.

23/4/07

Buscador fuentes CRM y gadget

He encontrado esta aplicación que te permite lanzar búsquedas sobre CRM desde el Internet Explorer 7, como una fuente más de información. También incluye un gadget de Vista para lanzar la búsqueda desde el escritorio. Muy chulo.

http://blogs.msdn.com/joris_kalz/pages/Vista-Microsoft-CRM-Search-Gadget.aspx

11/4/07

Cambiar la configuración de correo

Tanto entrante como saliente, si después de instalar CRM necesitamos por el motivo que sea cambiar el servidor de Exchange.

http://support.microsoft.com/kb/906471/

Encontrado en la KB de Microsoft.

10/4/07

Campañas de marketing de correo electrónico

Aquí van un par de trucos del lado oscuro de CRM: el módulo de marketing. Cuando tratamos de distribuir una actividad de campaña de marketing basada en el canal e-mail, podríamos esperar que CRM enviara los correos inmediatamente, ¿no? Pues no. En su lugar, lo que hace es crear actividades de correo electrónico que quedan abiertas y pendientes de enviar. Como no existe el botón Enviar en plan masivo, no queda más remedio que ir abriendo y enviando los correos uno por uno, lo que no parece ser de recibo.

Visto el problema, y a partir del Rollup 1 de CRM, se puede cambiar una clave en el registro que modifica este comportamiento. Si creamos una clave de tipo DWORD en la dirección

HKLM\Microsoft\MSCRM\CampaignSendEmail

y le ponemos el valor 1, el resultado de distribuir la actividad será el envío directo de los correos. En principio, y para unos pocos destinatarios, funciona. ¿Por qué esta precaución? He visto en este artículo de las news que hay gente a la que le ha fallado de forma aleatoria, presuntamente por incluir un enlace mailto: en el cuerpo del mensaje.

4/4/07

Luchando contra las Actividades de Servicio

Luchando contra una pequeña extensión de CRM que incluye funcionalidades con la parte de programación de actividades de servicio me he encontrado con los siguientes dos problemas, que muestro aquí para no olvidar.

  1. Problema al copiar una entidad que incluya el objeto activityparty
    Los objetos activityparty representan los participantes en una cita o en una actividad de servicio. En el caso de la actividad de servicio, pueden estar tanto entre los clientes (atributo customers) o en los recursos (atributo resources). Bueno, pues si los copiamos de unos previamente existentes, obtendremos un error SOAP SQL integrity violation que no ayuda mucho. Bien, pues el único problema es que hay que crear Guids nuevos para cada activityparty. Se soluciona con un simple

    foreach (activityparty ap in actividad.resources)
    ap.activitypartyid = Guid.NewGuid();

    Gracias a David Jennaway en las news de crm.developer
  2. Problema con el formato de las fechas en CrmDateTime
    Independientemente de lo que diga la SDK, sólo funciona bien con el formato yyyy/M/ddTHH:mm:00 sobre el campo Value. Hay que olvidarse (al menos yo me olvido) de los atributos date y time y especificar de golpe ambas, o sea:

    actividad.scheduledstart.Value =
    fechaInicio.ToString("yyyy/M/ddTHH:mm:00");

24/3/07

Problema con las colas de correo

Si después de haber creado la cola de actividades y casos tal como explica Marco Amoedo en su blog os seguís dando de cabezazos (como yo hice) porque los correos siguen sin entrar. Si os dáis cuenta de que el correo de los usuarios entra sin ningún problema en sus buzones. Si os habéis encontrado con este problema, la solución, en una línea de letra grande y roja es:

El propietario de la cola sí importa

Cuando alguien asigna una actividad o caso a una cola, el propietario sigue siendo el original, el creador del elemento. Ningún problema. Sin embargo, cuando llega un nuevo correo, el router tiene que crear una actividad de la nada, sin propietario (y casi todo en CRM tiene propietario) así que, ¿a quién se la asigna? Pues al propietario de la cola. ¿Y qué pasa si el propietario de la cola no tiene permisos para crear actividades (ejemplo típico: el administrador con acceso restringido) Pues que no funciona.

Moraleja rellenad el propietario de la cola con un usuario con licencia en CRM y permiso para crear e-mails en la unidad de negocio a la que pertenece.

21/3/07

Mostrar el nombre de la organización en Outlook

Esta es sin duda una de las peticiones más solicitadas por los clientes que instalan la versión Outlook de CRM. Aproximadamente cuatro segundos después de la instalación, cuando descubren que sus contactos no se pueden organizar por organización. Es decir, utilizar el campo Organización de Outlook para agrupar sus contactos por empresa. Pues no, no se puede, pero tenemos esta alternativa que nos proponen aquí.

http://www.workopia.com/howto/DisplayParentAccountOutlookContactForm.htm

Sacado del blog del equipo de CRM http://blogs.msdn.com/crm/

8/11/06

Programa de "beta-testers" del Update Rollup 1

Está disponible en el blog de desarrollo de CRM en MS un programa para aquellos partners que quieran participar en las pruebas de la beta del próximo Update Rollup de CRM, que está previsto que salga a "finales de año".

Más información: http://blogs.msdn.com/crm/archive/2006/08/09/693420.aspx

12/9/06

Seguridad en el nivel de campo

Mucha gente cree que sobre el modelo de seguridad de CRM hay mucho que añadir. La prueba está en que partners han empezado a desarrollar extensiones al modelo que permiten, por ejemplo, aplicar una política de seguridad en el nivel del campo (atributo) además de en el nivel de registro (objeto).

Como muestra, fijaos en lo que hacen en c360:

http://www.c360.com/FieldLevelSecurity.aspx

Esta imagen que incluyo es la interfaz de administador, donde se decide qué roles o equipos pueden acceder a un campo de un formulario, y con qué tipo de permisos.