jueves, 4 de noviembre de 2010

¿Cómo eliminar un equipo?

Al menos la versión 4.0 del Dynamics no permite desde su interfaz eliminar un equipo, un poco raro ¿verdad? bueno, no pasa nada, para todo hay una solución :-)

Tenemos que acceder a la base de datos del CRM y borrar el registro del equipo de la tabla TeamBase. Previamente deberemos quitar a los integrantes del equipo.

Nota: Existen dos tablas (Team y TeamBase) pero con solo eliminar el registro de TeamBase es suficiente porque automáticamente se elimina de la otra tabla.

miércoles, 27 de octubre de 2010

Incluir un link referente a una entidad en emails con un Triggers

Esto es otra opción además de la que anteriormente escribí en el post Incluir un link referente a una entidad bastante más sencilla (desde mi punto de vista) aunque tocando la base de datos del CRM, lo que puede poner nervioso a más de uno. Pero a mi me funciona :-)

PASO 1:
Crear un atributo de tipo nvarchar con una longitud de 250 en la entidad que queramos al que llamare 'new_enlace', en mi caso en una entidad personalizada llamada "new_vacaciones". Publicamos los cambios en la entidad.

PASO 2:
Hay que crear un Trigger tal que así:
CREATE TRIGGER [dbo].[TR_Link_Vacaciones] ON [dbo].[New_vacacionesExtensionBase]
AFTER INSERT
AS
DECLARE @ID AS uniqueidentifier
BEGIN
 SET NOCOUNT ON
 SELECT @ID = (SELECT New_vacacionesId FROM Inserted )
 UPDATE New_vacacionesExtensionBase
 SET New_enlace = '<a href=''http://miservidorCRM/UNIDADPRINCIPAL/userdefined/edit.aspx?etc=10025&id=' + cast(@ID AS nvarchar(50)) + '''>aquí.</a>'
END

PASO 3:
Agregar al cuerpo del email del workflow de turno la típica frase:
"Para visualizar este registro puede hacer clic" y añadimos el campo 'new_enlace' de la entidad 'new_vacaciones'. Obsérvese que el tag href ya lleva el texto 'aquí.' por lo que quedaría completa la frase.

miércoles, 22 de septiembre de 2010

Vista asociada en un Iframe

Por requerimientos del cliente (como siempre) necesitaba poner en una pestaña la vista asociada de una entidad relacionada con la del formulario principal ¿que qué es esto? me explico: Tengo una entidad personalizada que llamamos Linea de venta (algo así como una linea de un presupuesto) que está relacionada con las Ofertas en N:1 respectivamente. El cliente no quiere hacer más clics de los necesarios por lo que me veo a mostrar la vista asociada de las lineas de venta de la oferta directamente en una de las pestañas del formulario, ¿dónde? en un Iframe, y aquí os pego el código:

En el evento OnLoad del formulario:
function GetFrameSource(tabSet) {
 if (crmForm.ObjectId != null) {
   var oId = crmForm.ObjectId;
   var oType = crmForm.ObjectTypeCode;
   var security = crmFormSubmit.crmFormSubmitSecurity.value;
   return "areas.aspx?oId=" + oId + "&oType=" + oType + "&security=" + security + "&tabSet=" + tabSet;
 }
 else {
   return "about:blank";
 }
}

crmForm.all.IFRAME_view.src = GetFrameSource("new_quote_new_linea"); 
crmForm.all.IFRAME_view.allowTransparency=true;

Notas:
"new_quote_new_linea" es el nombre de la relación 1:N entre ambas entidades.
IFRAME_view es el nombre del frame donde vamos a colocar la vista asociada.

miércoles, 15 de septiembre de 2010

Aumentar en número de registros por página

Como sabéis existe un límite de registros por página que puede definir el usuario en el menú Herramientas > Opciones. El máximo que puedes elegir es 250 registros.

Pues con una pequeña consulta y un Update podemos cambiarlo y poner la cantidad que queramos.

Ahí va:

UPDATE UserSettings
SET PagingLimit = 10000
WHERE SystemUserId = 
(SELECT su.SystemUserId FROM SystemUser su
WHERE su.FullName Like 'Administrador%')

lunes, 28 de junio de 2010

Google Maps en nuestro CRM 4.0

En muchas ocasiones el comercial debemos consultar dónde están las oficinas del cliente al que va a visitar, con esto simplificamos mucho mas la tarea pues nos vamos a basar simplemente en los datos postales que contenga el cliente y una simple página HTML con un mínimo código Javascript.

PASO 1:
Creamos un fichero html con el siguiente código, incluye el javascript que llamará a las librerías de Google:

<html>
<head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <title></title>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> 
    <script type="text/javascript">
        var geocoder;
        var map;
        function initialize() {
            geocoder = new google.maps.Geocoder();
            var latlng;
            latlng = new google.maps.LatLng(40.396764, -3.713379);    
            var myOptions = { zoom: 15, center: latlng, mapTypeId: google.maps.MapTypeId.ROADMAP };
            map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
            var address = location.search; 
            address = address.substring(address.indexOf('=') + 1);
            codeAddress(address);   
        }
        function codeAddress(address) {
            if (geocoder) {
                geocoder.geocode({ 'address': address },
                function(results, status) {
             if (status == google.maps.GeocoderStatus.OK) {
                 map.setCenter(results[0].geometry.location);
                 var marker = new google.maps.Marker({ map: map, position: results[0].geometry.location });
             }
             else {
                 alert("Error cargando el mapa: "
                 + status + "\n" 
                 + "Asegúrese de rellenar correctamente País, Provincia, Ciudad, Dirección y Código postal.");
             }
         });
            }
        }
    </script>
</head>
<body style="margin: 0px; padding: 0px;" onload="initialize()">
    <div id="map_canvas" style="width: 100%; height: 100%">
    </div>
</body>
</html>

PASO 2:
En la entidad Cuenta (podríamos hacerlo en cualquiera que tuviera campos de dirección) editamos el evento onLoad del formulario para insertar el siguiente código que hará que cuando pulsemos en una pestaña se cargue el mapa:

crmForm.all.tab5Tab.onclick = function() { 
var url = ""; 
if (crmForm.all.address1_country.DataValue != null)  
   url = crmForm.all.address1_country.DataValue; 
if (crmForm.all.address1_stateorprovince.DataValue != null)  
   url += (url == "" ? "" : ", ") + crmForm.all.address1_stateorprovince.DataValue; 
if (crmForm.all.address1_city.DataValue != null)  
   url += (url == "" ? "" : ", ") + crmForm.all.address1_city.DataValue; 
if (crmForm.all.address1_line1.DataValue != null)  
   url += (url == "" ? "" : ", ") + crmForm.all.address1_line1.DataValue; 
if (crmForm.all.address1_line2.DataValue != null)  
   url += (url == "" ? "" : ", ") + crmForm.all.address1_line2.DataValue; 
if (crmForm.all.address1_line3.DataValue != null)  
   url += (url == "" ? "" : ", ") + crmForm.all.address1_line3.DataValue;
if (crmForm.all.address1_postalcode.DataValue != null)  
   url += (url == "" ? "" : ", ") + crmForm.all.address1_postalcode.DataValue; 
if (url != "") {
   url = "MIHOST/localizador.html?address=" + url;
   crmForm.all.IFRAME_mapa.src = url; }
}
Consideraciones:
  tab5Tab - el número corresponde al la pestaña donde está el mapa, recordar que como un array, empieza en 0 el conteo. Esta es mi 6ª pestaña en realidad.
  MIHOST/ - es donde está publicado el fichero html

PASO 3:
Creamos un campo iframe dentro de la pestaña que tendrá el mapa y lo llamamos IFRAME_mapa. Obviamente este nombre puede cambiarse si se hace también en el código anterior.
En la url del mapa escribimos: about:blank
Marcamos la casilla para que se expanda todo lo posible en el formulario.

PASO 4:
Publicamos los cambios de la entidad y nos quedará algo así:

martes, 9 de marzo de 2010

Botón en un formulario que ejecuta un Workflow


Lo primero de todo es crear un atributo personalizado en la entidad del formulario donde queremos poner el botón. El atributo tiene que ser de tipo nvarchar (texto) y establecer la propiedad Búsqueda en No.
Publicamos el cambio y creamos el workflow (tiene que ser a petición) que vamos a lanzar cuando se pulse el botón.

Editamos el evento onload del formulario de dicha entidad y este código es el que crea (transforma el atributo) en un botón:
function CrearBoton(fieldname, buttontext, buttonwidth,clickevent)
{
functiontocall=clickevent;
crmForm.all.new_button.DataValue = buttontext;
crmForm.all.new_button.style.borderRight="#3366cc 1px solid";
crmForm.all.new_button.style.paddingRight="5px";
crmForm.all.new_button.style.borderTop="#3366cc 1px solid";
crmForm.all.new_button.style.paddingLeft="5px";
crmForm.all.new_button.style.fontSize="11px";
crmForm.all.new_button.style.backgroundImage="url(/_imgs/btn_rest.gif)";
crmForm.all.new_button.style.borderLeft="#3366cc 1px solid";
crmForm.all.new_button.style.width=buttonwidth;
crmForm.all.new_button.style.cursor="pointer";
crmForm.all.new_button.style.lineHeight="18px";
crmForm.all.new_button.style.borderBottom="#3366cc 1px solid";
crmForm.all.new_button.style.backgroundRepeat="repeat-x";
crmForm.all.new_button.style.fontFamily="Tahoma";
crmForm.all.new_button.style.height="20px";
crmForm.all.new_button.style.backgroundColor="#cee7ff";
crmForm.all.new_button.style.textAlign="center";
crmForm.all.new_button.style.overflow="hidden";
crmForm.all.new_button.attachEvent("onmousedown",push_button);
crmForm.all.new_button.attachEvent("onmouseup",release_button);
crmForm.all.new_button.attachEvent("onclick",testfunction);
}

function push_button(){
window.event.srcElement.style.marginLeft="1px";
window.event.srcElement.style.marginTop="1px";
}

function release_button(){
window.event.srcElement.style.marginLeft="0px";
window.event.srcElement.style.marginTop="0px";
}

Función que ejecutará el workflow:
ExecuteWorkflow = function(entityId, workflowId)
{
    var xml = "" + 
    "" + 
    "<envelope xmlns:soap="\"http://schemas.xmlsoap.org/soap/envelope/\"" xmlns:xsd="\"http://www.w3.org/2001/XMLSchema\"" xmlns:xsi="\"http://www.w3.org/2001/XMLSchema-instance\"">" + 
    GenerateAuthenticationHeader() +
    "  " + 
    "    <execute xmlns="\"http://schemas.microsoft.com/crm/2007/WebServices\"">" + 
    "      <request xsi:type="\"ExecuteWorkflowRequest\"">" + 
    "        <entityid>" + entityId + "</entityid>" + 
    "        <workflowid>" + workflowId + "</workflowid>" + 
    "      </request>" + 
    "    </execute>" + 
    "  " + 
    "</envelope>" + 
    "";

    var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
    xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
    xmlHttpRequest.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Execute");
    xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
    xmlHttpRequest.send(xml);
    var resultXml = xmlHttpRequest.responseXML;
    return(resultXml.xml);
}

Función del evento OnClick del botón que llamará al la que ejecuta el workflow pasándole el id del de la entidad y el del wf.
function testfunction()
{
   var theWorkflowId = "5F63397D-2868-4B74-9E6E-A5C6012981F3"; //change to your workflow Id
   ExecuteWorkflow(crmForm.ObjectId, theWorkflowId);
}


create_button_from_textattribute('new_button', 'email','184px',testfunction);

lunes, 1 de marzo de 2010

Ocultar botón de vista asociada

En el evento OnLoad() del formulario de la entidad principal (candidato en mi caso) pegamos este código:

_tryhide = function()
{
   try
   {
      // Localizamos el Frame que contiene el elmento a ocultar.
      with (document.all['new_new_candidato_new_experienciaprofesionalFrame'].contentWindow.document)
      { 
         if (readyState != 'complete') return setTimeout(arguments.callee,100); 
         // Id del boton que queremos ocultar
         with (getElementById ('_MBtoplocAssocOneToMany10002newnewcandidatonewexperienciaprofesional'))
         {
            style.display='none';
         } 
      } 
   } 
   catch(e) 
   { 
      return setTimeout(arguments.callee,100); 
   }
}

//Ponemos el elemento que queremos que capture el evento que ejecuta la funcion

document.getElementById('nav_new_new_candidato_new_experienciaprofesional').attachEvent('onfocus',_tryhide);

Consideraciones a tener en cuenta:
'new_new_candidato_new_experienciaprofesionalFrame'
es el nombre del Frame donde está la vista asociada.

'_MBtoplocAssocOneToMany10002newnewcandidatonewexperienciaprofesional'
es el botón que queremos ocultar, en mi caso es el Agregar Experiencia profesional existente.

Por último
'nav_new_new_candidato_new_experienciaprofesional'
es la barra de navegación de la vista asociada.


¿Cómo localizo los nombres de mi Frame, botón y barra de navegación? Por ejemplo con el IExplorer 8.0 abriendo la ventana (en mi caso del candidato) y pulsando F12 que te muestra el código fuente. Luego hacemos búsquedas tipo *Frame, _MBtoplocAssocOneToMany* o nav_*.

y eso es todo, esperos haberos ayudado.

Fuente: be CRM