Script “Data Selectors: reusing definitions” Supongamos que hemos agregado a la transacción Customer el atributo CustomerStatus, para poder representar uno de los tres estados (activo, en espera o cerrado) que puede tener un cliente en el sistema de la agencia de viajes. Para ello se ha definido un tipo de datos Status, enumerado, con esos tres valores. {ppt} Page 1 Ahora supongamos que en varios lugares de la aplicación, necesitamos trabajar con los clientes activos ingresados entre un par de fechas determinadas. Video filmado con GeneXus X Evolution 2 – upgrade3 Por ejemplo, en el web panel que mostraba todos los clientes y el total de precios de sus vuelos, y que permitía filtrar por nombre del cliente, ahora queremos mostrar siempre los clientes activos únicamente, dándole al usuario la posibilidad de ingresar un rango de fechas para poder filtrar también por los agregados al sistema dentro de ese rango. Otro ejemplo: necesitamos realizar un listado pdf que muestre para cada vuelo, además de la información del aeropuerto de partida y de llegada, la cantidad de clientes ACTIVOS registrados con asiento, entre los clientes ingresados hasta la fecha de hoy. Page 2 O por ejemplo, necesitamos realizar un listado pdf que reciba por parámetros un rango de fechas (&start y &end) y muestre los clientes activos que fueron ingresados al sistema entre ese par de fechas dadas. Video filmado con GeneXus X Evolution 2 – upgrade3 En definitiva, estaremos repitiendo en todos esos objetos estos tres filtros (para optimizar, podemos ordenar por CustomerStatus, dado que filtramos por igualdad por ese atributo): Page 3 Para ahorrarnos el trabajo de tener que repetir esas mismas especificaciones en todos los lugares donde las necesitemos (el web panel y los procedimientos anteriores, pero también podría ser en grupos de data providers o en grids de Panels en Smart Devices), podemos realizar esas definiciones en un único lugar, dándoles un nombre, y de allí en más utilizar ese nombre como referencia. Este lugar es el objeto Data Selector: Video filmado con GeneXus X Evolution 2 – upgrade3 {GeneXus} Creamos el objeto, al que llamaremos “ActiveCustomers”: y allí definimos las condiciones: El estado del cliente, CustomerStatus, activo. La fecha de ingreso del cliente al sistema: CustomerAddedDate, mayor o igual a la variable &start, –que será un parámetro de este objeto–, siempre y cuando no esté vacía. Y por último: CustomerAddedDate, menor o igual que la variable end, también parámetro recibido, cuando la variable &end no esté vacía. Debemos entonces definir las variables utilizadas como parámetros: start de tipo date, y end de tipo date. Page 4 Y también establecemos que ordene por CustomerStatus, para optimizar. Video filmado con GeneXus X Evolution 2 – upgrade3 Observemos que también aparece un nodo DefinedBy que permitirá, al igual que en el for each, nombrar atributos para que participen en la determinación de la tabla base. ¿De qué tabla base? Dependiendo de la forma de usarlo, este DataSelector será unas veces simplemente una definición, que se agregará a la consulta representada por un grid, un for each, un grupo de data provider, o una fórmula , –donde sea que se esté utilizando este data selector, y allí no tendrá sentido hablar de su tabla base–, pero otras representará una consulta en sí misma, que puede ejecutarse sobre la base de datos, como si fuera un for each, devolviendo un conjunto, para hacer algo con sus elementos. Allí sí tendrá sentido hablar de su propia tabla base, que en este caso será Customer. Lo veremos en los ejemplos que siguen. {Web panel ActiveCustomersFlights} Aquí hemos salvado el web panel que teníamos con otro nombre, y hemos definido e insertado en el form las variables &start y &end, de tipo date: Page 5 Si observamos las propiedades del grid, sólo estamos filtrando por CustomerFullName. Así, si ejecutamos, se mostrarán todos los clientes (los activos y los otros) cuyos nombres contengan lo ingresado por el usuario en esta variable {poner %Be en &CustomerFullName}… pero no se modificará lo mostrado si cambiamos estas otras…{&start y &end} Video filmado con GeneXus X Evolution 2 – upgrade3 Esto podemos apreciarlo en el listado de navegación: Page 6 Sin embargo, si vamos a las propiedades y especificamos a nivel del grid el Data Selector que hemos creado, ActiveCustomers, –vemos que se nos abre la propiedad Parameters para especificar los parámetros que debemos enviarle–: Video filmado con GeneXus X Evolution 2 – upgrade3 y damos F5… en el grid se mostrarán sólo los clientes activos, cuyos nombres contengan lo ingresado por el usuario en la variable &CustomerFullName y que hayan sido ingresados entre las dos fechas estipuladas por el usuario en las variables &start y &end. Video filmado con GeneXus X Evolution 2 – upgrade3 Page Podríamos haber implementado esto mismo, agregando las condiciones del Data selector directamente en la propiedad Conditions del grid, y el order del data selector en la propiedad Order. 7 Ya no los indica el listado de navegación: El comportamiento será el mismo, así como lo que nos informará el listado de navegación. Es decir: se combinará la definición del Data selector con las propiedades Conditions y Order del grid. En todo grid (estándar o freestyle), –salvo en el caso de transacciones–, podrá utilizarse un data selector. Esto también vale para grids de Panels for Smart Devices. Puede encontrar más documentación sobre Data selectors en Grids en nuestro wiki: http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?5386. {Procedure PrintActiveVIPCustomers} Ahora veamos la implementación del procedimiento que imprime un PDF web con todos los clientes VIP activos, ingresados entre un par de fechas recibidas por parámetro. Page 8 Si no tuviéramos definido el data selector haríamos: Video filmado con GeneXus X Evolution 2 – upgrade3 Pero teniéndolo, simplemente lo usamos, a través de la cláusula using: Así, queremos que el for each se resuelva utilizando, además de sus otras cláusulas, el data selector ActiveCustomers, al que le pasamos por parámetro los valores de las variables &start y &end que este reporte recibió a su vez como parámetros del objeto que lo llama. El comportamiento es en todo análogo a la especificación anterior (incluyendo la determinación de la tabla base del for each, que tomará en cuenta los atributos propios del for each, y los definidos dentro del Data selector). Page 9 Si ejecutamos el procedimiento, directamente, los parámetros &start y &end estarán vacíos, y por tanto, saldrán listados todos los clientes VIP activos: Video filmado con GeneXus X Evolution 2 – upgrade3 Vemos que su listado de navegación no nos permite discriminar si usamos el Data Selector o lo programamos manualmente: Video filmado con GeneXus X Evolution 2 – upgrade3 Page Aquí los atributos del Data Selector no participan en la determinación de la tabla base del for each, que en principio tiene como tabla base la de asientos de los vuelos. 10 Para el caso del comando for each, podría hacerse otro uso del Data Selector, que es ejecutándolo como si fuera una consulta independiente a la base de datos. No lo veremos en este curso, pero es el caso de usar el operador in en lugar de la cláusula using: En el where, se estarán filtrando los asientos que tienen clientes cuyo identificador se encuentra en el conjunto devuelto por el Data Selector, ejecutado como una consulta independiente. Es decir, se estará filtrando por los CustomerId que se encuentren en el conjunto de clientes activos ingresados entre el par de fechas &start y &end. Puede encontrar más documentación sobre Data selectors en For eachs en nuestro wiki:http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?5312 {ppts} Page 11 Ya habíamos visto cuando resumimos el comando for each, que al indicarle que use un Data Selector, le estaremos diciendo que agregue sus orders, condiciones y defined by, a los explícitos. Video filmado con GeneXus X Evolution 2 – upgrade3 Por eso, los atributos que figuren como parámetros, serán considerados para la determinación de la tabla base del for each (así como los que se encuentren internamente en el DataSelector). La otra posibilidad, es filtrar de acuerdo a los valores devueltos por un Data Selector. Aquí le estamos diciendo que filtre los registros del for each según el atributo mencionado se encuentre en el conjunto de valores devueltos al ejecutar el Data Selector como si fuera una consulta a la base de datos. Page 12 Aquí, el único atributo que participa de la determinación de la tabla base del for each es el del where. Los que aparecieran como parámetros o los internos al Data Selector no participarán. Video filmado con GeneXus X Evolution 2 – upgrade3 En este caso el Data Selector tendrá su propia tabla base, que será la accedida para obtener el conjunto resultante de la consulta: {GeneXus } Por último, veamos el ejemplo de uso de Data Selector en una fórmula count. Page 13 Estamos queriendo imprimir los vuelos, y por cada uno, además de los datos del aeropuerto de partida y de llegada, queremos desplegar el total de pasajeros (clientes) activos ingresados hasta la fecha del día, y que tienen reservados asientos en el vuelo: Video filmado con GeneXus X Evolution 2 – upgrade3 Page Puede encontrar más documentación sobre Data selectors en For eachs en nuestro wiki http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?5432 14 Para ello, hemos definido una variable, &active, que debemos calcular en el Source, antes de imprimir el printblock. Queremos contar todos los asientos de vuelos, utilizando el Data Selector, es decir, filtrando por todo lo que éste contiene): Video filmado con GeneXus X Evolution 2 – upgrade3 Si ahora necesitamos modificar los filtros, tanto para el web panel como para los pdfs que vimos, de manera tal que los clientes recuperados, además de ser los activos e ingresados entre dos fechas dadas, sean los VIP… al tener la información centralizada y encapsulada en un Data Selector, sólo tendremos que ir a modificar ese Data Selector, agregándole la condición, para que todos los objetos que lo utilicen queden automáticamente actualizados. {ppts} En suma… El Data selector es un objeto para almacenar un conjunto de parámetros, orders, conditions y definedby, para utilizarlo o invocarlo desde diferentes consultas y cálculos, y así reutilizar la misma navegación varias veces. Page 15 ¿Por tanto, en qué lugares podremos utilizar un Data Selector? En todos los que especifiquen consultas a la base de datos: Video filmado con GeneXus X Evolution 2 – upgrade3 Puede encontrar más documentación sobre Data selectors en nuestro wiki: Page 16 http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?5775 Video filmado con GeneXus X Evolution 2 – upgrade3