Data Providers - Más conocimientos

Anuncio
Data Providers - Más conocimientos
Introduciremos nuevos conocimientos sobre el uso de los Data Providers.
Para ello propondremos una implementación práctica en nuestra aplicación.
Supongamos que la agencia de viajes decide que todos los clientes que han contratado más de
3 excursiones, recibirán una tarjeta especial de tipo “Full Services”, que les permitirá disfrutar
de todos los servicios en forma gratuita. Y en caso de haber contratado 3 o menos excursiones,
recibirán la tarjeta de tipo “Partial Services”.
Contamos entonces con la transacción “Customer” que permite registrar para cada cliente sus
datos junto con la lista de excursiones realizadas:
Page
1
Y la transacción “ServiceCard” que permite definir las tarjetas:
Video filmado con GeneXus X Evolution 2 – upgrade2
Cada tarjeta tiene un identificador que se autonumera, un cliente… y hemos definido el
atributo ServiceCardType basado en el dominio enumerado Type, que admite solamente los
valores “Full” o “Partial”.
Hemos definido también el web panel WPCards, que simplemente ofrece un botón que
disparará el proceso automático de generación y visualización de nuevas tarjetas.
¿Qué deberá suceder al presionar el botón?
Para todos aquellos clientes que aún no tengan tarjeta emitida, se les deberá crear una tarjeta
del tipo que corresponda, teniendo en cuenta la cantidad de excursiones que han contratado.
Propondremos una solución usando un Data Provider que cargue y devuelva la colección de
tarjetas a ser generada, y luego recorreremos la colección y grabaremos las tarjetas en la base
de datos.
¿Y cómo hacemos esto?
En primer lugar, configuramos la transacción ServiceCard como Business Component para
grabar las tarjetas haciendo uso del concepto de Business Component.
Después, creamos un objeto de tipo Data Provider de nombre DPCards y arrastramos la
transacción ServiceCard sobre el source de ese Data Provider.
Video filmado con GeneXus X Evolution 2 – upgrade2
Page
Una sintaxis idéntica a la que se genera cuando arrastramos un tipo de datos estructurado
sobre el source de un Data Provider… y con esta práctica vemos que también podemos
arrastrar una transacción que ha sido declarada como Business Component.
2
¿Qué estamos viendo?
En este caso particular, no hemos definido un SDT en la base de conocimiento, pero la sintaxis
nos permite deducir que se cargará una estructura en memoria con ítems de igual nombre y
tipo que los atributos de la transacción ServiceCard.
Recordemos que estos no son atributos:
sino los ítems de la estructura que se cargará en memoria.
Bien. Hasta ahora la idea entonces, es que se cargarán en memoria tarjetas. ¿Pero a partir de
dónde y con qué condiciones y particularidades?
Necesitamos recorrer la tabla CUSTOMER, filtrar los clientes que aún no tienen una tarjeta
emitida y para ellos agregar una tarjeta en la colección.
La tabla base de un Data Provider, es decir la tabla que navegará, se determina por los
atributos que referenciemos del lado derecho de los signos de asignación.
Al ítem CustomerId, es claro que le vamos a asignar el atributo CustomerId.
Al ítem ServiceCardId no le necesitamos asignar ningún valor específico, porque recordemos
que esta estructura fue arrastrada de 1 transacción BC.. y por lo tanto este ítem está basado
en el atributo ServiceCardId, que pertenece al dominio Id y su propiedad autonumber está
configurada en Yes.
Page
Observemos cuales son los atributos que figuran del lado derecho de los signos de asignación.
Solamente CustomerId, porque los atributos que están dentro de la fórmula, no se tienen en
cuenta para la determinación de esta tabla base sino que determinan la tabla a ser navegada
por la fórmula.
3
Ahora veamos que a ServiceCardType le podemos asignar el valor que retorne una fórmula
condicional, es decir que la fórmula devolverá el tipo “Full” o “Partial” de acuerdo a la cantidad
de excursiones que ha contratado el cliente:
Video filmado con GeneXus X Evolution 2 – upgrade2
Así que la tabla navegada por el Data Provider es CUSTOMER. Pero no queremos navegar
todos los clientes y para cada uno cargar una tarjeta, sino que queremos recorrer solamente
aquellos clientes que aún no tienen tarjeta.
Los Data Providers permiten en su sintaxis, que les incluyamos todas las cláusulas permitidas
en For each, así que agregaremos esta cláusula Where :
De esta forma entonces logramos navegar todos los clientes cuya cantidad de tarjetas es 0, o
sea, que no tienen tarjetas.
Pero observemos un poco más esta cláusula Where:
Dado que el único atributo referenciado está dentro de una fórmula, entonces no participa en
la determinación de la tabla base del Data Provider. De haberse evaluado directamente,
entonces si hubiera participado.
Bien. Observemos el Data Provider, y veamos que podemos simplificarlo un poco más.
Cuando un ítem en la estructura de un Data Provider se carga con un atributo de igual nombre,
entonces podemos abreviar la declaración de esta forma:
Ahora analicemos la salida, el output, del Data Provider:
Al haber arrastrado la transacción ServiceCard, automáticamente, la propiedad Output quedó
asociada a ella.
Video filmado con GeneXus X Evolution 2 – upgrade2
Page
La estructura que estamos cargando no representa una colección. Solamente representa una
instancia en memoria, con la estructura de 1 registro de la tabla asociada a la transacción
ServiceCard.
4
¿Y la propiedad Collection?
Sin embargo nosotros necesitamos obtener una colección de tarjetas generadas, entonces
configuramos la propiedad Collection con valor True… e indicamos un nombre para la
colección que devolverá cargada este Data Provider:
Volvamos ahora al web panel para invocar al Data Provider.
En el evento Enter asociado al botón, declaramos una variable &ServiceCardCollection que
GeneXus automáticamente define como una colección de ServiceCard al tener el término
Collection en su nombre.
El evento Enter entonces queda simplemente así:
Event Enter
&ServiceCardCollection=DPCards()
End Event
Vayamos ahora al form del web panel, e insertemos la variable &ServiceCard.
Por tratarse de una variable colección, automáticamente GeneXus entiende que debe mostrar
el contenido en un grid.
Video filmado con GeneXus X Evolution 2 – upgrade2
Page
No. Por ahora las tarjetas están cargadas en memoria y hemos mostrado el contenido de la
colección.
5
Ahora bien, ¿esto alcanza para que las tarjetas devueltas por el Data Provider efectivamente se
graben en la tabla SERVICECARD asociada a la transacción ServiceCard?
Cuando estudiamos la utilización de transacciones como BC, vimos que para grabar debemos
usar el método Save y luego ejecutar el comando Commit. Así que nos está faltando recorrer la
colección devuelta por el Data Provider y proceder a grabar cada elemento de la colección
como registro en la tabla física. Y posteriormente a la grabación de todas las tarjetas, vamos a
declarar el comando Commit.
Para recorrer entonces la colección de tarjetas devuelta por el Data Provider, contamos con el
comando For elemento in Colección.
Esta variable &oneCard debe ser definida. Representa a cada elemento que se va iterando de
la colección. Vamos a definirla:
Ahora volvamos al evento para completar el código que recorre la colección:
Event Enter
&ServiceCardCollection= DPCards()
For &oneCard in &ServiceCardCollection
&oneCard.Save()
Endfor
Commit
End Event
Ahora sí el desarrollo de lo solicitado está completo. Presionemos F5 para ver el
comportamiento.
Page
6
Ejecutamos el web panel. Presionamos el botón. Y vemos en la grilla la lista de tarjetas que se
generaron.
Video filmado con GeneXus X Evolution 2 – upgrade2
Vamos ahora a ejecutar la transacción Service Card para verificar que las tarjetas han sido
realmente grabadas como registros.
Ahora bien. Puede surgirnos la pregunta: ¿Qué sucederá si volvemos a presionar el botón
“Generate Cards” en el web panel?
¿Se volverán a crear las tarjetas para los mismos clientes?
No, porque en el Data Provider filtramos que solamente queríamos navegar aquellos clientes
sin tarjeta.
Vamos a comprobarlo:
Presionamos otra vez el botón, y vemos que no se generaron tarjetas esta vez.
Para finalizar, vale mencionar que hay otras soluciones para resolver este mismo
requerimiento en GeneXus.
En esta implementación hemos usado el concepto de Business Component para actualizar la
base de datos, aprovechando los beneficios que los mismos nos proveen y hemos combinado
su uso con el hecho de cargar previamente una estructura colección en memoria con los datos
a grabar.
Page
7
El uso de un Data Provider para esto, es muy sencillo y nos ahorra escribir código explícito.
Video filmado con GeneXus X Evolution 2 – upgrade2
Descargar