j.a.estevan

Si no eres parte de la solución, eres parte del poblema

AX TIP: Mostrar label con saltos de línea mediante X++

Una característica bastante molesta que te encuentras programando para Microsoft Dynamics AX es la manera en la que se tratan los saltos de líneas al presentar texto en formularios utilizando etiquetas. Por ejemplo, la siguiente línea:

Box::yesNo("Línea 1 \n Línea 2", DialogButton::Yes, "Prueba multi línea!");

Presenta un diálogo normal con un texto en varias líneas (hace caso del carácter \n para poner un salto de línea):

strFmtLB 1 | Bien

Sin embargo al convertir el mismo texto en una etiqueta, el resultado es distinto:

// @TST001: Línea 1 \n Línea 2
Box::yesNo("@TST001", DialogButton::Yes, "Prueba multi línea!");

strFmtLB 2 | Mal

Y ocurre lo mismo si se utiliza una etiqueta con comodines (%1, %2, …) y la función strFmt de esta manera:

// @TST001: Línea 1 \n Línea 2
Box::yesNo(strFmt("@TST001"), DialogButton::Yes, "Prueba multi línea!");

Para que la etiqueta haga caso del salto de línea hay que utilizar la función strFmtLB:

// @TST001: Línea 1 \n Línea 2
Box::yesNo(strFmtLB("@TST001"), DialogButton::Yes, "Prueba multi línea!");

Y así si funcionará:

strFmtLB 3 | Bien

Pero esta función no sustituye a la anterior. Esto es, en caso de tener comodines y saltos de página habrá que incluir las dos funciones. Esto es bastante molesto cuando modificas una etiqueta y pones un salto de línea. Da la impresión de haberse roto algo que antes sí funcionaba, y es que esta función no esta incluida nunca en el código si no es necesaria de forma explícita.

26 de diciembre de 2011 | deja un comentario

Información de tablas durante el desarrollo en Dynamics AX

Cuando se desarrolla para Microsoft Dynamics AX es muy común tener que consultar tipos de datos, nombres de campos, tablas, etc. para mantener la coherencia entre objetos nuevos y estándar. Esta consulta se puede hacer mediante las propiedades de los formularios (el botón Configurar del menú contextual estándar) y consultando el diseño o la query que se muestra en este formulario o yendo directamente al objeto del AOT:

Pero si esta consulta la tenemos que hacer muy a menudo, como al principio de un gran desarrollo, es molesto tener que hacer todos estos pasos cada vez y se puede consultar mucho mas fácilmente de esta manera:

16 de diciembre de 2011 | deja un comentario

HOWTO: Ejecutar tu propio código .NET en Dynamics AX 2009

Aunque esto es algo que tiende a desaparecer en el próximo Microsoft Dynamics AX 2012, de momento es una funcionalidad muy útil en la versión 2009, ya que es la única manera de solventar algunas limitaciones técnicas.

Me estoy refiriendo a la posibilidad de utilizar el .NET CLR Interop para ejecutar desde nuestro código X++ librerías desarrolladas en .NET (ya sea C# o VB.NET). Esta integración también tiene sus propias limitaciones pero amplía de manera notable las posibilidades de desarrollo en AX 2009.

Voy a hacer un ejemplo paso a paso, y el primer paso es crear la propia librería desde Visual Studio. En mi caso voy a utilizar (el ya súper antiguo) Visual Studio 2005 para crear un nuevo proyecto “Biblioteca de clases”:

Dynamics AX 2009 DLL Interop

El código va a ser muy sencillo para no complicar la prueba, simplemente devolverá el nombre del equipo donde se ejecuta el código (esto se puede utilizar para comprender la ejecución de código en el cliente (devolverá la máquina local) o en el servidor (devolverá el AOS):

01 de noviembre de 2011 | hay 3 comentarios

HOWTO: Enviar emails desde X++

Email

Enviar correos desde Microsoft Dynamics AX mediante código X++ es muy sencillo, pero requiere de demasiado código si se quiere aplicar de manera reutilizable.

Para enviar un email utilizando la clase SysMailer estándar haremos algo parecido a esto:

 

 

SysMailer   sysMailer;

SysEmailParameters  sysEmailParameters      = SysEmailParameters::find();
InteropPermission   interopPermissionClr    = new InteropPermission(InteropKind::ClrInterop);
InteropPermission   interopPermissionCOM    = new InteropPermission(InteropKind::ComInterop);
Set                 permissionset           = new set(Types::Class);

#define.DefaultFromAddress("from@jaestevan.com")
;

try
{
    // Permisos
    permissionset.add(interopPermissionClr);
    permissionset.add(interopPermissionCOM);
    CodeAccessPermission::assertMultiple(permissionset);

    //Inicialización de los parámetros de correo electrónico.
    sysMailer = new SysMailer();

    if (sysEmailParameters.smtpRelayServerName)
    {
        sysMailer.SMTPRelayServer(sysEmailParameters.smtpRelayServerName,
                                  sysEmailParameters.smtpPortNumber,
                                  sysEmailParameters.smtpUserName,
                                  sysEmailParameters::password(),
                                  sysEmailParameters.ntlm);
    }
    else
    {
        sysMailer.SMTPRelayServer(sysEmailParameters.smtpServerIPAddress,
                                  sysEmailParameters.smtpPortNumber,
                                  sysEmailParameters.smtpUserName,
                                  SysEmailParameters::password(),
                                  sysEmailParameters.ntlm);
    }

    // Dirección de origen
    sysMailer.fromAddress(#DefaultFromAddress);
}
catch
{
    throw error("No se puede inicializar el envío de emails");
}

// OK! SysMailer inicializado con parámetros y dirección de origen

// Añadir destinatario
sysMailer.tos().appendAddress("test@jaestevan.com");

// Se pueden añadir destinatarios en copia (CC)
sysMailer.ccs().appendAddress("cc@jaestevan.com");

// Subject del mensaje
sysMailer.subject("Mensaje de prueba");

// Cuerpo del mensaje
sysMailer.htmlBody("<a href='http://www.jaestevan.com'>BODY de ejemplo en HTML!</a>");

// Hasta se pueden añadir ficheros adjuntos!
sysMailer.attachments().add("ficherodeejemplo.txt");

// Let's dance!
sysMailer.sendMail();

// Renuncia de los permisos
CodeAccessPermission::revertAssert();

28 de octubre de 2011 | hay 4 comentarios

¿Agile en el canal Dynamics? ¿Locura?

Insanity: doing the same thing over and over again and expecting different results.- Albert Einstein
(Locura es hacer lo mismo una y otra vez y esperar resultados diferentes)

Como expuse en mi anterior post: ¿Sure Step vs Agile? Condenados a entendernos, estoy convencido de que un cambio de filosofía hacia el mundo ágil no sólo es positivo sino que es totalmente posible dentro del mundo de los grandes ERP en general, y del canal Dynamics en particular.

Como exponía en ese artículo, hay varios handicap que superar como la resistencia al cambio (hay que cambiar la mentalidad de muchas personas involucradas), la falta de confianza en el sistema para proyectos de largo alcance o incluso la falta de colaboración del cliente. Sin embargo hay ciertos trabajos muy típicos de esta industria que son ideales para empezar a experimentar con este cambio, a pesar de que el proyecto, en general, se gestione con Sure Step:

  • Migraciones (cambios de versión): Una migración es un proceso totalmente acotado con tareas claramente definidas y planificables, pero lo importante es que en este proceso no es tan importante la documentación (a menudo no es para nada importante) como la implicación del cliente en el proceso tanto para la realización de diversas pruebas al finalizar cada tarea, como para solucionar consultas sobre la marcha en caso de imprevistos (en las migraciones siempre hay imprevistos). Lo de “ágil” se vuelve literal ya que cuando el proceso de migración termina se tiene que implantar en tiempos de parada del cliente, casi siempre en un fin de semana.
  • Soporte post-arranque: Cuando se da por finalizada una implantación nueva y el cliente empieza a utilizar el sistema, a menudo se dará cuenta de que hay pequeños (o grandes) detalles que quiere modificar porque no se habían previsto durante las fases previas. La buena gestión de estas modificaciones puede diferenciar el éxito o el fracaso de una implantación ya que una cosa es que el proyecto finalice, y otra que el cliente de por cubiertas sus necesidades (o las que cree que lo son). Hacerle participe del coste y el esfuerzo de esos “extra” puede ser determinante para cerrar la implantación con todas las partes satisfechas.
  • Actualciones de mantenimiento: De la misma manera que en el punto anterior, trabajar con un sistema programable como lo son todos los grandes ERP’s hace que siempre haya pequeños o grandes cambios a realizar para optimizar el trabajo diario. La buena gestión de las necesidades, el desarrollo y la implantación de los cambios sin interferir el trabajo de los usuarios es determinante para que los mantenimientos se finalicen con éxito y sin fricciones.

Si alguien ya ha empezado o esta interesado en estos cambios me encantaría recibir opiniones en los comentarios. Y si alguien quiere comentar o debatir en persona estaré en la próxima Conferencia Agile-Spain 2011 (#cas_2011)

10 de octubre de 2011 | deja un comentario

AX TIP: Validar permisos (claves de seguridad) por código

A veces en nuestros desarrollos queremos limitar ciertos procesos a usuarios que tengan activa determinada clave de seguridad (Security Key):


(la imagen es de la documentación oficial)

 Para hacerlo utilizaremos las funciones que el estándar dispone para ello. Encontramos un ejemplo de utilización en la clase estándar SysTest:

// Only a developer can run unit tests
if (hasSecuritykeyAccess(securitykeynum(SysDevelopment), AccessType::Delete))
{
    // Código protegido
    ...
}
else
{
    throw error(strfmt("@SYS97038", securitykeystr(SysDevelopment), enum2str(AccessType::Delete)));
}
02 de octubre de 2011 | deja un comentario

Microsoft Dynamics AX Hotfix: Ley de Morosidad (España)

Están disponibles los objetos actualizados de Microsoft Dynamics AX para cumplir con los requisitos de la Ley de Morosidad según el BOE-A-2010-10708:

  • Microsoft Dynamics AX 2009 SP1

* requiere login

27 de septiembre de 2011 | deja un comentario

Microsoft Dynamics AX 2012 Virtual Launch Event

Hace ya algunos meses que venimos hablando de Microsoft Dynamics AX 2012, desde su presentación en la Microsoft Dynamics AX Technical Conference 2011 de la que ya hablamos en su día, se ha publicado muchísima información sobre las novedades que nos esperan en esta nueva versión.

Aprovechando el Microsoft Dynamics AX 2012 Virtual Launch Event de esta semana se han liberado también multitud de materiales oficiales muy interesantes, algunos accesibles sólo desde Partner Source, y otros totalmente abiertos:

En primer lugar son muy interesantes las demos interactivas que se han publicado en la web oficial del producto y ofrecen una oportunidad de simular de primer mano la utilización de la nueva interfaz tanto para temas de desarrollo como funcional. Sin instalar nada, desde la propia web utilizando Silverlight, vale la pena probarlos:

Demo interactiva

12 de septiembre de 2011 | deja un comentario

HOWTO: Facturación selectiva de líneas en Dynamics AX

En Microsoft Dynamics AX, como en la gran mayoría de ERP’s, se pueden facturar líneas de forma parcial y agruparlas según diferentes criterios. El usuario puede elegir el número de líneas que desee:

PurchFormLetter | 1

y facturarlas completamente o en parte, dejando el resto pendiente de facturar o no, agrupandolas en facturas por clientes, por dirección, etc.:

PurchFormLetter | 2

05 de septiembre de 2011 | deja un comentario

Microsoft Dynamics AX Design Patterns

Dado el tamaño y la inmensa funcionalidad incluida en Microsoft Dynamics AX, parece lógico pensar que se han seguido diferentes patrones de diseño para implementarlo, y en efecto así es.

Conocer y respetar estos patrones de diseño y tambien las buenas practicas es muy importante para mantener un buen nivel en nuestros desarrollos y procurar no “romper” el funcionamiento estándar de la aplicación con nuestras modificaciones, si bien no todos ellos estan completamente documentados, la mayoría se perfeccionan con la experiencia, pero la base se puede aprender mediante la documentación oficial:

Estos patrones no son arbitrarios, como se puede comprobar la mayoría se basan en patrones de diseño mas o menos estándar o al menos comunmente reconocidos como válidos, por ejemplo:

30 de agosto de 2011 | deja un comentario