Supongamos que hemos agregado a la transacción Customer el atributo CustomerStatus, para poder representar uno de los tres estados (active, on hold, closed) que puede tener un cliente en el sistema de la agencia de viajes. Para ello se ha definido un tipo de datos Status enumerado, como se ve en la imagen. Supongamos que en varios lugares de la aplicación, necesitamos trabajar con los clientes activos ingresados entre un par de fechas determinadas. Por ejemplo: • 1 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. • en 1 web panel que muestra todos los clientes y el total de precios de sus vuelos realizados (si el modelo de transacciones lo representara), supongamos que 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 en ese rango. • en 1 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, de los clientes ingresados hasta la fecha de hoy. En definitiva, estaremos repitiendo en todos esos objetos los tres filtros que mostramos arriba (para optimizar, podemos ordenar por CustomerStatus, dado que filtramos por igualdad por ese atributo). 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, así como en grupos de data providers, 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. Como vemos, en el ejemplo creamos un data selector al que llamamos “ActiveCustomers”, y allí definimos las condiciones, el order, y declaramos los parámetros &start y &end que se utilizan en dos de las condiciones. 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. Dependiendo de la forma de usarlo, este DataSelector será unas veces simplemente una definición, y otras representará una consulta en sí misma, que puede ejecutarse sobre la base de datos, como si fuera un for each, devolviendo un conjunto. Esta definición centralizada nos permitirá reutilizarla en todos los lugares donde se necesita esa consulta, facilitando el mantenimiento (si se necesita cambiar algo de la definición, se realiza en un único lugar y se aplica automáticamente a todos los lugares de la KB donde se utilice) y optimizando el conocimiento, gracias al nivel de encapsulamiento que proveen. Veamos cómo, una vez definido el data selector, lo utilizaríamos en los ejemplos que mencionamos. Teniendo el web panel que mostraba en un grid los clientes y el total de precios de sus vuelos, permitiendo al usuario filtrar por nombre completo del cliente (observar la propiedad Conditions del grid), queremos modificarlo, de modo que muestre sólo los clientes activos, que hayan sido ingresados entre dos fechas elegidas por el usuario. Observemos que hemos insertado dos variables: &start y &end para que el usuario pueda especificar el rango de fechas de ingreso del cliente al sistema, de modo tal que se refresque el grid cuando esas variables cambien. Podríamos hacerlo como hasta ahora, agregando a la propiedad Conditions: CustomerStatus = Status.Active; CustomerAddedDate >= &start when not &start.IsEmpty(); CustomerAddedDate <= &end when not &end.IsEmpty(); Y colocando en la propiedad Order: CustomerStatus. O utilizar el data selector que creamos antes. Para ello, la propiedad Data Selector del grid nos permite elegir entre los objetos de tipo Data Selector que hayamos definido en la KB. En la propiedad Parameters especificamos los parámetros que recibe el data selector. El comportamiento será el mismo al haberlo definido manualmente. Es decir: se combinará la definición del Data selector con las propiedades Conditions y Order del grid. Por tanto, en todo grid (estándar o freestyle), salvo 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. Aquí estamos queriendo imprimir un pdf con todos los clientes VIP activos ingresados entre un par de fechas recibidas por parámetro. Si no tuviéramos definido el data selector haríamos: For each Customer order CustomerStatus where CustomerStatus = Status.Active Where CustomerAddedDate >= &start when not &start.IsEmpty() Where CustomerAddedDate <= &end when not &end.IsEmpty() Where CustomerVIP print customer Endfor Teniéndolo, simplemente lo usamos, a través de la cláusula using. El comporamiento es en todo análogo a la especificación anterior. 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: For each FlightSeat Where CustomerId in ActiveCustomers( &start, &end) … endfor Puede encontrar más documentación sobre Data selectors en For eachs en nuestro wiki http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?5312 Ya habíamos visto cuando resumimos el comando for each que un Data Selector especifica, en base a los parámetros recibidos, un conjunto de condiciones y ordenamientos para la información de manera centralizada, de modo de no tener que repetir las cláusulas order, where y defined by (cláen cada lugar en que se necesiten. Al indicarle al for each que use (using) un Data Selector, le estaremos diciendo que agregue sus orders, condiciones y defined by, a los explícitos. Por eso, los atributos que figuren como parámetros deberán pertenecer a la tabla extendida de la tabla base del For each. 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 (att in) el conjunto de valores devueltos al ejecutar el Data Selector como si fuera una consulta a la base de datos. En este caso el Data Selector tendrá su propia tabla base, que será la accedida para obtener el conjunto resultante de la consulta. En este caso estamos queriendo imprimir los vuelos, y por cada uno, además de los datos del aeropuerto de partida y de llegada, el total de pasajeros (clientes) activos ingresados hasta la fecha del día, que tienen reservados asientos en el vuelo. En este caso, estamos utilizando el data selector dentro de la fórmula count. Puede encontrar más documentación sobre Data selectors en For eachs en nuestro wiki http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?5432 El Data selector es un objeto para almacenar un conjunto de parámetros, conditions, orders y definedby, para utilizarlo/invocarlo desde diferentes consultas y cálculos, y reutilizar la misma navegación varias veces. ¿Por tanto, en qué lugares podremos utilizar un Data Selector? En todos los que especifiquen consultas a la base de datos. Puede encontrar más documentación sobre Data selectors en nuestro wiki: http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?5775