miércoles, 11 de julio de 2012

Manipular campos por su nombre (por programación)

Esto que voy a escribir no sólo aplica a SalesLogix, sino a cualquier programación que estén haciendo en C#, o en cualquier otro lenguaje NET si prestan suficiente atención.

Un usuario me dió la tarea de crear un formulario con 50 preguntas parametrizables, cuya respuesta debería poderse escribir mediante un TextBox, o mediante un PickList (equivalente del dropdown en SalesLogix).

Al final, lo que se quiere lograr, es que en una tabla "Extension" (relación 1 a 1 con la tabla principal) hayan 50 campos con las preguntas y las respuestas así:  Campo "Preg1" - Valor "Es casado/a?: Si".

Poner los campos en el AppArchitect es súmamente sencillo, para hacerlo, coloqué un Label con nombre L, junto le puse un TextBox con nombre T, y junto le puse un Picklist con nombre P.  Para efectos de velocidad, los puse dentro de un "Control Container" (esto es sólo en SalesLogix).  Luego sólo fue necesario darle copiar al control container e ir pegando los 49 restantes (obviamente ya había creado las celdas).

El SalesLogix lo que hará es pegar los controles y cada vez que los pegas, le suma 1 al Id de cada control, es decir, la primera vez que pegué, el Label le puso L2, al TextBox le puso T2 y al PickList le puso P2.

Muy importante! Al terminar de pegar los controles hay que ir a renombrar los primeros objetos a L1, T1 y P1 respectivamente.

Ok, ahora viene la parte interesante.

Quiero hacer constar, que ninguno de los controles está "Binded" sino que voy a mover todo por programación!

Primero ponemos un botón y en el evento le asignamos el Business Rule "Save".

Generamos y hacemos "deploy to..." del proyecto (para que vaya el código), y buscamos el "SmartPart" con nuestra encuesta y ubicamos el método donde se guarda el formulario.

Copiamos todo lo que está el método y volvemos al AppArchitect, cambiamos que el botón en lugar de hacer "Business Rule" ahora sea un "C# Snippet Action Item" y pegamos lo que copiamos del formulario en el portal que hicimos el deploy.

Al código, justo antes de donde está " _entity.Save(); " hay que agregar lo siguiente:

for (int i = 1; i<=50; i++)
{
Label lctn = (Label)this.FindControl("L" + i.ToString());
TextBox tctn = (TextBox)this.FindControl("T" + i.ToString());
Sage.SalesLogix.Web.Controls.PickList.PickListControl pctn = (Sage.SalesLogix.Web.Controls.PickList.PickListControl)this.FindControl("P" + i.ToString());

_entity.ExtensionEntity_ReqInfo["Preg" + i.ToString()]=lctn.Text + ": " + tctn.Text + pctn.PickListValue;
}

Como pueden observar, la referencia a mi tabla actual se llama " _entity ", y tiene una tabla extensión que se llama " ExtensionEntity_ReqInfo " con los 50 campos que se llaman "Preg1, Preg2...Preg50".

Las 3 primeras líneas son para obtener los controles en cuestión.  La línea final es para llenar la tabla en cada campo "Preg1...Preg50" con la concatenación de [Pregunta] + ": " + [Respuesta].

Ahora agreguemos un evento al "Load" del formulario que también será "C# Snippet Action Item" y al crearlo, asegurémonos de poner en True la opción para que el método sea llamado cada vez que se repinta el formulario.

En el código coloquen lo siguiente:

string WfRelId = DialogService.DialogParameters["WfRelId"].ToString();
Sage.Entity.Interfaces.IC_Preguntas pregs = Sage.Platform.EntityFactory.GetById<Sage.Entity.Interfaces.IC_Preguntas>(WfRelId);


for (int i = 1; i<=50; i++)
{
Label lctn = (Label)this.FindControl("L" + i.ToString());
TextBox tctn = (TextBox)this.FindControl("T" + i.ToString());
Sage.SalesLogix.Web.Controls.PickList.PickListControl pctn = (Sage.SalesLogix.Web.Controls.PickList.PickListControl)this.FindControl("P" + i.ToString());
string qeRI = (string)pregs["Question" + i.ToString()];
string prRI = (string)_entity.ExtensionEntity_TicketReqInfo["Preg" + i.ToString()];
lctn.Text = qeRI;
if (lctn.Text != "") { if ((string)pregs["ControlType" + i.ToString()] == "TextBox") { tctn.Visible = true; tctn.Text = prRI.Replace(qeRI + ": ",""); }

else
{ pctn.Visible = true; pctn.PickListName=(string)pregs["PicklistRespName" + i.ToString()]; pctn.PickListValue = prRI.Replace(qeRI + ": ",""); }   }
}


Las 2 primeras líneas son, 1, para obtener un parámetro con el ID de registro que corresponde a las preguntas que queremos hacer, y 2, para obtener el registro con las 50 preguntas, las 50 especificaciones de si es TextBox o PickList, y los 50 posibles nombres de PickList.

Esa tabla llamada C_Preguntas, tiene 4 campos que son el ID, 50 columnas de pregunta "Question1...Question50", 50 columnas de tipo "ControlType1...ControlType50" y 50 columnas para establecer el nombre del picklist "PicklistRespName1...PicklistRespName50".

Las preguntas van callendo en la línea con la variable " qeRI " y las respuestas en la siguiente en la variable " prRI ".  Pero ojo, al guardar, dijimos que la respuesta se guardaba como [Pregunta] + ": " + [Respuesta].  Por eso hay unos Replace en la sentencia siguiente.

En el IF, vemos que dependiendo del "ControlType", si es TextBox, mostramos el campo TextBox correspondiente con su respuesta, y si no, el PickList con el valor seleccionado.

Ya con esto, manipulamos por programación y sin mucho esfuerzo, los 50 campos del formulario.

jueves, 23 de febrero de 2012

Crystal mostrando la moneda incorrecta

Se presentó el problema en un cliente de que no importaba lo que hiciéramos en el reporte, al desplegarlo por Web, siempre traía los campos "Currency" formateados con Euros.

Luego de una intensa revisión y pruebas se determinó lo siguiente:

  1. Asegurarse de que el "Reports Portal" está apuntando a su Application Pool y que el pool esté configurado correctamente con WebDLL.
  2. Revisar las opciones en la pestaña "ASP.NET" del portal de reportes, y en la ventana emergente, ver las opciones en la pestaña "Application" que están relacionadas a la cultura.  En este lugar se puede colocar la cultura que desee.  Este cambio a nivel de portal, luego debería reflejarse en los ASP.NET de todos los "Virtual Directories" dentro de este portal, pero vale la pena revisarlos.
  3. Revisar la configuración regional y de idioma del usuario WebDLL (muy importante, firmarse al servidor con el WebDLL porque las opciones regionales son por usuario).  Cambiar el idioma, la ubicación, y el idioma en la pestaña "Advanced".
  4. Entrar y personalizar la cadena de moneda aunque aparente estar correcta.
  5. Reiniciar el application pool y el portal de reportes.
Con estos pasos nuestros reportes web deberían listarse con el formato de moneda correcto.

martes, 24 de enero de 2012

Fuentes más pequeñas en diálog Area-Category-Issue (SLX7.5.3 Web)

Este es un problema más que nada estético.

Resulta que las fuentes del control Area-Category-Issue son muy grandes y a veces se hace dificil seleccionar la opción adecuada.

Hasta que Sage no incorpore una propiedad para establecer el ancho de los "dependant" lookups estamos lmitados a por lo menos hacer más pequeñas las letras.

Para esto, buscamos en la carpeta "css" el archivo que se llama sage-styles.css y agregamos el siguiente estilo:

.formtable .yui-panel .hd select
{
    font-size: 80%;
}

Con esto haremos las letras más chicas y nos dará un pequeño espacio adicional para leer las opciones:





En este caso era para Area-Category-Issue, pero la verdad el cambio funciona para cualquier lookup dependiente.

Actualización:  Existe un post en CustomerFX de un conocido programador.  El enlace es http://customerfx.com/pages/integrationblog/2012/07/27/expanding-the-area-category-issue-picklist-popup-screen-in-the-saleslogix-web-client.aspx y en el mismo explica cómo modificar unos archivos "js" (javascript) internos del SalesLogix los cuales permiten ampliar este dependent lookup.

Actualización 2:  Utilizando CSS encontré un método mucho mejor, como mil veces más sencillo y aplica para cualquier campo que necesiten ampliar.  El post lo puse en:  http://www.slxdeveloper.com/forum.aspx?forumid=4002&postid=32203

Expandir los nombres de los reportes (SLX 7.5.3 Web)

Constantemente los clientes se quejan de que el espacio donde se ven los reportes es muy reducido, y el nombre de la mayoría siempre queda truncado por el tamaño del control.

Para solucionarlo, deben buscar el smartpart que se llama Reporting.ascx y buscar la línea que tiene el control de selección de reportes.  Pueden hacer una búsqueda de:  select name="reportname"

Seguidamente vamos a modificar el DIV que está al inicio, y le vamos a colocar 500 pixeles de ancho en el atributo STYLE.  También vamos a agregar el atributo STYLE al "select control" y le pondremos de ancho un 100%.  La línea completa debería quedar así:

<div style="width:500px"><select name="reportname" id="reportname" onchange="reportNameChanged()" size="12" style="width:100%"></select></div>

Puse en negrita lo que deben agregar.

Al visualizar el listado de reportes se debería ver así:


Mucho mejor para los usuarios que el pequeño espacio que trae por defecto!

lunes, 23 de enero de 2012

Mostrar formularios del DialogWorkSpace en un Sales Process (SLX7.5.3)

Muchos de ustedes habrán notado que no es posible mostrar formularios en los Sales Processes web.

Recientemente tuve la necesidad de revisar esto por un flujo muy interesante de un cliente, así que les traigo la solución, un poco "dirty" como dirían, pero totalmente funcional.

Paso 1 - Procesando los "Form" en los Sales Process:

Busquen dentro de la carpeta SmartParts, la carpeta OpportunitySalesProcess.  Dentro abran para editar en notepad el archivo que se llama OpportunitySalesProcess_ClientScript.js y realicen una búsqueda de la función executeAction.  Allí podrán ver que la opción case 'Form' no hace absolútamente nada, así que deberán cambiarla de la siguiente manera:

        case 'Form':
            ProcessAction.prototype.Init = Init_Form;
            boolExecute = true;
            break;


Paso 2 - Creando la función para mostrar el diálogo:

Ok, ahora vamos a crear la función que nos permitirá mostrar nuestro diálogo.  Busquemos un espacio para escribir nuestra función y escriban lo siguiente:

function Init_Form() {
    var xmlDoc = sp_GetXmlDoc(this.xml);
    var objFrm = xmlDoc.getElementsByTagName('FormAction');
    var strFormName = objFrm[0].getElementsByTagName('LanForm')[0].getElementsByTagName('Name')[0].firstChild.nodeValue;
    DialogWorkspace.show(strFormName,'800','800','800','800');
    this.Finish();
    return false;
}

Ven los 800?  Lastimósamente no he logrado que el formulario sea de más de 500x500 y que esté en otro lugar que no sea X=0 Y=0, pero como es funcional, no me molesta tanto.  Vieron también que dice LanForm?  Déjenlo así, ya verán por qué.

Paso 3 - Creando el formulario... perdón, los!

Esto es lo único que puede parecer trillado.  Hay que crear el formulario en LAN y en WEB, es decir, en Architect y en Application Architect.  Por qué? porque el campo para poner el Web Form en el Sales Process utiliza los formularios que se hagan desde el WebAdmin, y no vamos a regresar a 7.0 con su programación horrible...  queremos un formulario de 7.5.3.

Como la función que hice no pasa parámetros (si encuentran la manera correcta de hacerlo les ruego que me avisen) el formulario que van a abrir recibirá el ID de la oportunidad, así que es mejor que vayamos a la entidad Opportunity para crear el formulario y de allí ya depende de su ingenio para darle funcionalidad.

Yo le voy a llamar dlgTestDrive:


Recuerden crear en el Architect un formulario que se llame igual, aunque esté vacío!



Paso 4 - Incorporando el formulario al Sales Process:

Ahora creamos un Sales Process y en algún punto, seleccionamos acción Form, y buscamos nuestro formulario:

Ahora falta únicamente probarlo, para ellos abrimos un SalesLogix desde Web, buscamos alguna oportunidad, le ponemos el Sales Process y buscamos el paso con el form.  Le damos clic a la descripción y:

Excelente!

miércoles, 18 de enero de 2012

Problemas con los campos moneda en SalesLogix Web 7.5.3

Por alguna razón, los campos tipo moneda (Currency) fallan cuando se utilizan navegadores con localizaciones en lugares fuera de "en-US", como en mi caso que es "es-PA" porque estoy en Panamá.

El problema que se presenta es que o bien sale un mensaje que dice "input string not in correct format" que impide marcar el botón para guardar, o al guardar el número, por ejemplo "3.99", el maldito se guarda como "399000" y si seguimos presionando guardar el número se va multiplicando por 1000...  súmamente molesto...

Afortunadamente he encontrado una manera de lidiar con los campos moneda y consiste en cambiar los campos tipo moneda a tipo número (Numeric).

Esto depende en gran medida de la implementación, si se van a utilizar todas las pantallas con campos tipo moneda o solo algunos.  En todo caso, si se va a realizar input a estos campos, cambiarlos a tipo número me ha dado muy buenos resultados.

Algo importante es que al cambiar los campos a tipo número, hay que colocarles el formato que queremos.  En Panamá, el formato sería {0:#,##0.00} lo cual nos presentaría 3211.3 como 3,211.30.

Si estamos en un formulario nativo del Application Architect, hay una propiedad de todos los campos en los formularios que se llama Data Bindings.  Dentro se "bindea" el campo a un atributo en la base de datos, y bajo el campo llamado "Binding" hay uno que dice Format String, que sería el lugar para colocar el formato que mostré.

Si es un formulario custom, y se están usando los WebEntityBindings, se colocaría el formato así:

WebEnityBinding miControl = new WebEntityBinding("CampoEnBD", "Text", "{0:#,##0.00}", "");

En ambos casos es muy importante setearle la propiedad "Format Type" del campo a "Number" o el formato no funcionará de la manera correcta.

martes, 10 de enero de 2012

El SalesLogix Mobile 2011 R1 desde un BlackBerry OS 5

Esto es una solución simple y sencilla para aquellas personas que están en países donde por algún motivo no es fácil o barato tener un nuevo BlackBerry con OS 6.

Si tienen un Curve u otro modelo de aquellos que sólo soportan BBOS 5, me es grato informarles que podrán utilizar el nuevo portal Mobile de SalesLogix (2011 R1, si, el que es HTML5 y CSS3) simplemente instalando Opera Mini.