Valor devuelto, no funciona en sub-modelos heredados

Al configurar una variable de modelo de producto, existen dos opciones para configurar como se comportará esta variable en caso de utilizar modelos heredados (un modelo de producto ejecuta otro modelo de producto):

Product Builder | Variables

La opción “Valor devuelto” no funciona en AX 3 y 4 (el problema esta corregido en la 2009) debido a un fallo en la programación de las clases estándar del configurador de producto.

Para solucionarlo editar el método de clase \Classes\PBATreeNodeCompile\PBAVarMethods() en su línea #101 y modificar la línea:

PBATableVariable.Vartype            == PBAvartype::Datatype     &&

por:

PBATableVariable.Vartype            &= PBAvartype::Datatype     &&

Después de este cambio será necesario compilar todos los modelos de producto para volver a generar sus clases corregidas.

Error en modelo de producto con opciones de gráfico AX4

Si AX 4 está configurado en un idioma que no es inglés (yo lo he probado en castellano pero entiendo que funcionará de la misma manera en otros idiomas), al ejecutar un modelo de producto al que se hayan configurado opciones de gráfico, AX mostrará un error de ejecución. Es un error de traducción del estándar que ya está corregido en la versión 2009.

Para solucionarlo, editar el método de clase \Classes\PBAFrontEndControlWin\run(), en su línea #8, y modificar la línea:

graphicControl = element.design().controlName('Graphic');

por:

graphicControl = element.design().controlName("@SYS40661");

Después de este cambio será necesario compilar todos los modelos de producto para volver a generar sus clases.

Optimización de rendimiento para Product Builder

El configurador de producto de AX es uno de los módulos que personalmente mas me gustan de este ERP. Su potencia y utilidad son innegables pero también lo és que no resulta demasiado eficiente en algunos casos. Uno de sus puntos débiles es el rendimiento al mostrar los formularios configurables y para ello se ha publicado en el blog Dynamics AX Live un interesante y sencillo truco para reducir el tiempo de carga de los formularios del PB.

La idea es no forzar a AX a aplicar propiedades de estos formularios que ya están aplicadas, cosa que el estándar sí hace, y con esto se reducirán muchísimas llamadas al formulario sobre todo en los que dispongan de muchas variables.

Para ello iremos al método SetControlProperties de las clases PBAFrontEndControl y PBAFrontEndControlWin y buscamos el siguiente código:

dataSource.object(valueTmpBuildForm.activeField()).enabled(enabled);
dataSource.object(valueTmpBuildForm.activeField()).mandatory(mandatory);
dataSource.object(valueTmpBuildForm.activeField()).visible(visible);

y sustituimos por este:

if(dataSource.object(valueTmpBuildForm.activeField()).enabled() != enabled)
    dataSource.object(valueTmpBuildForm.activeField()).enabled(enabled);
if(dataSource.object(valueTmpBuildForm.activeField()).mandatory() != mandatory)
    dataSource.object(valueTmpBuildForm.activeField()).mandatory(mandatory);
if(dataSource.object(valueTmpBuildForm.activeField()).visible() != visible)
    dataSource.object(valueTmpBuildForm.activeField()).visible(visible);

Mientras escribía este post he recordado que tengo un documento en alguna parte de mi disco duro con un par de bugs localizados en el estándar del Product Builder. En cuanto lo encuentre los publicaré.

HOWTO: AX – Distribuir ficheros con SysFileDeployment

A veces es util poder distribuir a los clientes de AX ficheros auxiliares que van a necesitar para la ejecución del programa, por ejemplo, controles ocx, librerias dll, iconos, imágenes, etc.

Gracias a André Arnaud, que amablemente respondió a una duda mía en los foros de la Microsoft Dynamics Community he descubierto el framework de AX SysFileDeployment que viene perfecto para esta tarea.

La idea de este framework es heredar clases para indicar a AX qué ficheros deben copiarse a la parte cliente cada vez que se realiza una nueva instalación de AX. Este framework tiene bastantes limitaciones pero la ventaja es que en su código se gestiona bastante bien el tema de permisos para copiar ficheros situados en el servidor hacia el cliente.

Comparto las pruebas que yo he realizado por si a alguien le pudieran servir. En primer lugar, hay que generar una nueva clase heredada de SysFileDeploymentFile indicando a AX qué fichero hay que copiar, dónde esta y hacia donde copiarlo. Esta es la estructura básica de la clase heredada, que esta bien autodocumentada por si se necesita mas personalización:

class SysFileDeploymentFileJAEEIcon extends SysFileDeploymentFile
{
   public Filename filename()
   {
       return 'jaestevan.png';
   }

   //AOSRunMode::Server
   protected FilenameOpen sourcePath()
   {
       return "C:\\Archivos de programa\\Microsoft Dynamics AX\\50\\Application\\Share\\Include\\";
   }

   //AOSRunMode::Client
   protected FilenameSave destinationPath()
   {
       return xInfo::directory(DirectoryType::Include);
   }
}

Una de las limitaciones de este framework es que sólo se ejecuta la primera vez que se ejecuta el cliente en un equipo determinado. Por tanto para distribuir nuevos ficheros o para hacer pruebas, como es mi caso, habría que modificar el método applBuildNo() de la clase ApplicationVersion, para forzar al sistema a actualizar la versión. Haciéndolo de este modo, AX detectará que tenemos ficheros pendientes de actualizar en el servidor y nos mostrará el siguiente diálogo:

SysFileDeploymentFile

Como no me apetecía andar modificando la build de mi entorno de pruebas, he hecho un pequeño Job que simula el código que se ejecutaría automáticamente de manera normal:

static void JAEE_SysFileDeployment(Args _args)
{
   container           classes;
   SysFileDeployment   sysFileDeployment;
   container           classVersion;
   classId             classId;
   ;

   classId = classNum(SysFileDeploymentCesserIcon);
   sysFileDeployment = classfactory.createClass(classId);
   classes += [[classId,sysFileDeployment.getServerVersion()]];

   classVersion = conpeek(classes, 1);
   classId = conpeek(classVersion, 1);

   sysFileDeployment = classfactory.createClass(classId);
   sysFileDeployment.setServerVersion(conpeek(classVersion, 2));
   sysFileDeployment.run();
}

Otra de las desventajas es que parece que esta clase no funciona demasiado bien en AX 4. Yo las pruebas que acabo de hacer en 2009 SP1 sí han funcionado, salvo un pequeño problema con las rutas de origen/destino, supongo que por ejecutar todo el entorno en la misma máquina (cliente, aplicación, AOS, ..).

A partir de aquí que cada uno investigue lo que necesite.

Descarga

HOWTO: AX – Expandir LMAT por código

AX nos deja expandir, o explotar, una línea de lista de materiales (L.MAT, o BOM en inglés) de manera que podamos manejar sus elementos al mismo nivel que el artículo L.MAT. La funcionalidad se llama Expandir L.MAT y la podemos ver, por ejemplo, en las líneas de un pedido:

Explode BOM | Expandir L.MAT

Esta función nos presenta un formulario para elegir las líneas que queremos “Explotar” fuera de la lista de materiales para su tratamiento:

Explode BOM | Expandir L.MAT

El código que este formulario ejecuta para realizar la expansión de la L.MAT se encuentra, en el caso de líneas de pedido de venta, en la tabla SalesLine) concretamente en el método: SalesLine.expandBOM(), por tanto para simular esta funcionalidad en X++, el mínimo código que podemos utilizar es el siguiente:

static void expandirLineaLMAT(Args _args)
{
   TmpFrmVirtual       tmpFrmVirtual;
                                         // Línea de la LMAT que se quiere expandir
   BOM                 tmpBOM          = BOM::findRecId(5637146401, false);    
                                         // Línea de venta desde la que expandir
   SalesLine           auxSalesLine    = SalesLine::find('00000003_050', 3, true);
   ;

   // Registro temporal que marca la línea a expandir
   tmpFrmVirtual.TableNum = tablenum(BOM);
   tmpFrmVirtual.RecordNo = tmpBOM.RecId;
   tmpFrmVirtual.write();

   // Expande la LMAT y genera la línea de venta nueva (función estándar)
   auxSalesLine.expandBOM(tmpFrmVirtual, tmpBOM);
   
   // la nueva línea de venta puede necesitar modificaciones despues de este proceso
}

y digo mímino porque la línea se insertará con la mayoría de sus opciones por defecto, por lo que es seguro que habra que añadir código extra para completar los datos necesarios según las necesidades.

Descarga

Modelos en AX

Sirva esta breve entrada como resumen de la interesantísima nueva funcionalidad de AX 6 publicada durante cuatro entregas en mfp’s (1, 2, 3, 4).

La idea de Modelo es una nueva abstracción superior a las capas para agrupar objetos pertenecientes a un mismo objetivo y será un avance importantísimo a la hora de implantar soluciones en las diferentes instalaciones de AX que maneja una empresa de desarrollo o un cliente final.

Supone un avance en el actual sistema de capas ya que permitira el manejo, importación y exportación de objetos situados en los diferentes modelos situados cada uno en una capa, de manera que podrán convivir desarrollos realizados por diferentes empresas, clietnes, finales, etc.

La lectura es obligada para cualquier desarrollador de AX, y mfc la resume perfectamente en estos puntos:

  • Los modelos ofrecen un método de transporte mucho mejor que los ficheros AOD usados hasta ahora, sobre todo porque peuden ser firmados y tener un manifiesto.
  • Los modelos permiten la instalación de desarrollos de orígenes diferentes en la misma capa.
  • Los modelos permiten segmentar un desarrollo en modelos mas pequeños y manejables.
  • Los modelos estan totalmente integrados en la experiencia de desarrollo con MorphX