Añadir lookup multiselección en un diálogo de SysOperation Framework

¡Primer post del 2020! ¡Feliz año nuevo! Sí, ya se que estamos a pasado mediados de enero…

Cuando añades un campo en un Data Contract de la SysOperation Framework el lookup que genera el framework (si el EDT lo tiene) es un lookup simple, de selección única. Vamos a ver cómo crear un lookup que permita la selección múltiple en MSDyn365FO.

El SysOperation Framework y MVC

Pero antes un poco de introducción. El SysOperation Framework se introdujo en Dynamics AX 2012 para sustituir al RunBase Framework, y se usa para crear procesos que se ejecutarán por lotes. Las clases de RunBase siguen estando en Dynamics 365 for Finance and Operations. Algunos procesos estándar las siguen usando, mientras otras las usan para luego llamar a clases del SysOperations Framework.

Aunque podemos seguir usando las clases del RunBase Framework recomendaría usar las SysOperations ya que tienen mejor rendimiento y usan un patrón de software moderno como el MVC (aunque de moderno tiene poco porque existe desde los 70…).

Para hacer esto necesitamos crear una clase de tipo Data Contract para nuestro modelo de datos, una Controller que define como se ejecuta el proceso, una Service con la lógica (que será un DataProvider en el caso de reports) y una clase UIBuilder para modificar el comportamiento del diálogo. En este ejemplo el lookup mostrará las empresas disponibles y ejecutará un report.

Data Contract

La clase Data Contract es nuestro modelo de datos y tenemos que etiquetarla con el atributo DataContract. Para crear el lookup de selección múltiple vamos a declarar una List en vez de una variable del tipo del EDT que tiene la relación con la tabla que queremos seleccionar. El método parm tiene que ir decorado con los atributos DataMemeber y AifCollectionType.

Nuestro Data Contract va a ser así:

El SysOperation Framework creará la UI automáticamente si los miembros están marcados con el atributo DataMember, otra ventaja respecto el RunBase.

Clase Service (Data Provider)

La clase Service es en la que desarrollaremos la lógica. Como dije esta clase es distinta dependiendo de si queremos ejecutar un report o un proceso por lotes.

Data Provider

Para un report crearemos una clase Data Provider (DP) en la que rellenaremos la tabla temporal con la que alimentamos el report:

Service

Para una clase que ejecute lógica de negocio hacemos lo siguiente, extendiendo una clase distinta:

Controller

El controller es donde definimos como queremos que sea la clase, síncrona o asíncrona, es bastante sencillo:

Como estoy ejecutando un report no defino cómo se ejecutará la clase. Si creo una clase para ejecutar en Batch el controller debería ser así (ojo que, como el servicio, también extiende otra clase distinta):

Aquí es donde le decimos a la clase como ejecutarse, en este ejemplo de forma síncrona con el parámetro _executionMode. Podemos usar 4 formas distintas de proceso:

  • Synchronous: ejecuta el proceso i deja la UI congelada hasta que termina el proceso.
  • Asynchronous: ejecuta el proceso por lotes.
  • Reliable asynchronous: ejecuta el proceso por lotes nada más darle al OK. Mientras se ejecuta aparece en la lista de lotes pero desaparece al terminar.
  • Scheduled batch: igual que el Reliable asynchronous pero el job no se borra de la lista al terminar.

Clase UIBuilder

La clase UIBuilder nos permite cambiar la forma en la que la clase DC genera la UI o también mejorar la funcionalidad de un campo, que es lo que queremos nosotros:

Creamos un dialog field y lo inicializamos con el método parm de nuestra lista en el DC. Después en el método postRun llamamos al método SysLookupMultiSelectCtrl::constructWithQuery. Le podemos pasar una query que ya exista o crear una con X++ como he hecho yo. Atención, atentos a que no se llama al super en ninguno de los dos métodos, de otro modo lo que pasaría es que el SysOperation Framework crearía los campos y tendríamos un error en tiempo de ejecución.

El resultado

Con todas las clases creadas ahora podemos ejecutar la clase Controller y ver cómo se ve el lookup.

Añadir lookup multiselección en un diálogo de SysOperation Framework 1

Los registros se pueden seleccionar, ¡tantos como queramos!

Añadir lookup multiselección en un diálogo de SysOperation Framework 2

Y ahora podemos recuperar los datos usando el método parm en nuestra clase Service o Data Provider y usar los valores. ¡Genial!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.