Está en la página 1de 29

ORDEN DE EJECUCIN DE REGLAS Y FRMULAS

134

Orden de ejecucin de reglas y frmulas


Transaccin "Factura"
FacturaId* FacturaFecha ClienteId ClienteTotalCompras CategoriaDescuento FacturaDescuento = FacturaSubTotal *CategoriaDescuento FacturaEnvioCargo = Max( EnvioFecha, EnvioFecha <=FacturaFecha,,EnvioCargo) FacturaSubTotal = SUM( FacturaLineaImporte ) FacturaTotal = FacturaSubTotal FacturaDescuento + FacturaEnvioCargo (ProductoId* ProductoPrecio ProductoStock FacturaLineaCantidad FacturaLineaImporte) = FacturaLineaCantidad * ProductoPrecio

Cliente

ClienteId* ClienteNombre CategoriaId ClienteTotalCompras

Categoria

CategoriaId* CategoriaDescuento

Envio

EnvioFecha* EnvioCargo

Producto

ProductoId* ProductoPrecio ProducStock

Reglas:

Add( FacturaTotal, ClienteTotalCompras); Error( Stock insuficiente ) if ProductoStock<0; Subtract( FacturaLineaCantidad, ProductoStock);

La forma de programar el comportamiento de las transacciones es definiendo reglas, las cuales se escriben de forma declarativa. A su vez si hay clculos para efectuar, se puede optar por la alternativa de definir atributos frmula. El programador GeneXus en ningn momento especifica la secuencia de ejecucin de las reglas y frmulas definidas en una transaccin, sin embargo al momento de generar, GeneXus determina las dependencias existentes entre las reglas y frmulas definidas. Supongamos que estamos definiendo una aplicacin para una empresa que vende determinados Productoos, y que cuenta con un servicio de entrega a domicilio que lleva la mercadera a sus clientes. Y definimos entre otras, las siguientes 5 transacciones: "Cliente" (para registrar los clientes de la empresa) Categoria (a las que pertenece cada cliente) Envio (envos: guarda un histrico de costos de envo) "Factura" (facturas que se emiten a los clientes) "Producto" (Productoos vendidos por la empresa) Se resalta la estructura de la transaccin "Factura", con sus atributos frmulas (algunas horizontales, otras verticales, otras aggregate/select) y sus reglas declaradas. En qu orden se dispararn las reglas y frmulas de la transaccin "Factura"?

135

rbol de evaluacin
R. Add(FacturaTotal, ClienteTotalCompras); F. FacturaTotal = FacturaSubTotal - FacturaDescuento + FacturaEnvioCargo F. FacturaDescuento = FacturaSubTotal*CategoriaDescuento F. FacturaEnvioCargo = MAX( EnvioFecha, EnvioFecha <= FacturaFecha,,EnvioCargo) F. FacturaSubTotal = SUM( FacturaLineaImporte ) F. FacturaLineaImporte = FacturaLineaCantidad *ProductoPrecio R. Subtract(FacturaLineaCantidad, ProductoStock) ; R. Error( Stock insuficiente) if ProductoStock < 0 ;

ClienteTotalCompras

FacturaTotal

FacturaDescuento FacturaEnvioCargo
error (Stock insuficiente )

FacturaSubTotal

EnvioFecha

FacturaFecha EnvioCargo

ProductoStock FacturaLineaImporte FacturaLineaCantidad

CategoriaDescuento

ProductoPrecio

Al momento de generar el programa asociado a la transaccin "Factura", GeneXus extraer las dependencias existentes entre las reglas y frmulas definidas; construir lgicamente un rbol de dependencias (o rbol de evaluacin) que determinar la secuencia de evaluacin. Podemos imaginar que el rbol se ejecuta de abajo hacia arriba, es decir que cada vez que cambia el valor de un atributo, se ejecutan todas las reglas y frmulas que dependen de ese atributo (y que en el rbol se encuentran hacia arriba). Por ejemplo, si cambia la cantidad de una lnea de una factura (FacturaLineaCantidad), como este atributo interviene en la frmula que calcula el importe de la lnea (FacturaLineaImporte), dicha frmula se redisparar. Por cambiar el importe de una lnea, deber redispararse la frmula correspondiente al subtotal de la factura (FacturaSubTotal) y en consecuencia, tambin deber recalcularse la frmula correspondiente al descuento (FacturaDescuento), ya que depende del subtotal. Deber redispararse tambin la frmula correspondiente al total de la factura (FacturaTotal) ya que depende tanto del valor de FacturaSubTotal como del valor de FacturaDescuento. Por ltimo, por cambiar el total tambin se tendr que disparar la regla Add(FacturaTotal, ClienteTotalCompras);. Adems de dispararse todas las frmulas y reglas involucradas en la rama derecha del rbol desde el atributo FacturaLineaCantidad, tambin se dispararn las frmulas y reglas involucradas en la rama izquierda. Es decir, que al cambiar el valor del atributo FacturaLineaCantidad, se redisparar tambin la regla Subtract(FacturaLineaCantidad, ProductoStock); y en consecuencia, por modificar esta regla el valor del atributo ProductoStock, se evaluar si habr que disparar la regla Error(Stock insuficiente) if ProductoStock < 0; Concluyendo, las reglas y frmulas que se definen en una transaccin suelen estar interrelacionadas y GeneXus determina las dependencias entre ellas as como su orden de evaluacin. Observemos las 2 ltimas reglas definidas: Subtract(FacturaLineaCantidad, ProductoStock); Error(Stock insuficiente) if ProductoStock < 0;

136

Estas reglas estn interrelacionadas porque las dos involucran al atributo ProductoStock. Ahora, mientras la segunda solamente consulta su valor, la primera lo actualiza. Entonces, la regla que actualiza al atributo ser la que se disparar primero, y luego se disparar la que lo consulta. Toda regla que actualice el valor de un atributo se disparar antes que una regla que lo consulte (esto se puede observar claramente en el rbol). Por este motivo es que la regla Error consulta si el atributo ProductoStock qued con valor negativo; porque como dijimos la sustraccin se realizar primero. En la programacin clsica se suele consultar primero si alcanza el stock, y en caso de que sea suficiente recin se hace la sustraccin. Por eso quienes estn aprendiendo GeneXus pueden intuitivamente escribir la regla: Error(Stock insuficiente ') if FacturaLineaCantidad > ProductoStock. Esta sintaxis es correcta, sin embargo no es correcta su lgica ya que como venimos explicando, en el rbol de evaluacin determinado por GeneXus primero se disparar la regla Subtract y luego la regla Error; por lo tanto tendremos que especificar que se dispare el mensaje de error si es que qued el stock con valor negativo, dado que ya se habr ejecutado la sustraccin al momento de consultar el valor de ProductoStock. As que la regla que se debe definir es: Error(Stock insuficiente) if ProductoStock < 0; Y no: Error(Stock insuficiente ') if FacturaLineaCantidad > ProductoStock; Cuando se dispara una regla Error, se detiene cualquier actualizacin a la base de datos y se desarma el rbol de evaluacin, quedando todo en el estado anterior a producirse el error. Siguiendo el ejemplo que venamos viendo, si al dispararse la regla Subtract el stock quedara negativo, se disparara la regla Error. Como consecuencia de dispararse la regla Error, se deshara el Subtract que se haba ejecutado, as como todas las dems reglas y frmulas que se hayan ejecutado (reclculo de los atributos FacturaLineaImporte, FacturaSubTotal, ...., ClienteTotalCompras). Cmo podemos ver el orden de evaluacin determinado por GeneXus? Al especificar una o varias transacciones, seleccionando la opcin Detailed Navigation, se detallar en el listado de navegacin resultante el orden de ejecucin de todas las reglas y frmulas definidas en la transaccin.

137

Alteraciones del orden de disparo de las reglas

Error Total

ProveedorId* Calculado Ingresado FacturaId* ... FacturaEntTotal Total ingresado FacturaLineaImporte ( ProductoId* FacturaLineaCantidad FacturaLineaPrecio FacturaLineaImporte = FacturaLineaPrecio * FacturaLineaCantidad) ... FacturaCalcTotal = SUM(FacturaLineaImporte) Total calculado

Total

Error(El total ingresado no coincide con el total calculado') if (FacturaEntTotal<>FacturaCalcTotal) On AfterLevel Level ProductoId;

En la mayora de los casos el orden de ejecucin de las reglas definido por GeneXus a partir de nuestras especificaciones es el deseado. Pero en algunos casos podemos querer cambiar el momento de disparo de una regla. Ejemplo: Definimos una transaccin para registrar las facturas que nos entregan nuestros proveedores. El identificador del primer nivel es compuesto por el identificador de proveedor y el identificador de factura, ya que el nmero de factura no nos sirve como identificador nico, porque proveedores distintos pueden repetir el mismo nmero de factura. Para cada factura de un proveedor que se ingrese, nos interesa controlar que el total que venga escrito en la factura (y que se ingresar en el atributo FacturaEntTotal) sea correcto. Para hacer este control, definimos al atributo FacturaCalcTotal como frmula vertical SUM(FacturaLineaImporte), y agregamos una regla Error que se disparar si no coinciden los valores de los atributos FacturaEntTotal y FacturaCalcTotal: Error('El total ingresado no coincide con el total calculado') FacturaEntTotal; if FacturaCalcTotal <>

Si construimos el rbol de evaluacin correspondiente a las frmulas y regla que hemos definido en esta transaccin:

138

vemos que las dependencias indican que cada vez que se agreguen, modifiquen o eliminen valores de los atributos FacturaLineaPrecio e FacturaLineaCantidad en las lneas, se recalcular el valor del atributo FacturaLineaImporte correspondiente; en consecuencia, se recalcular el valor del atributo frmula FacturaCalcTotal que hemos definido para tener el total calculado de la factura; y como este atributo est involucrado en la condicin de disparo de la regla Error, si se cumple dicha condicin de disparo, se disparar la regla Error(El total ingresado no coincide con el total calculado) if FacturaCalcTotal <> FacturaEntTotal. Ahora, prestemos atencin a que la condicin de disparo FacturaCalcTotal <> FacturaEntTotal se va a cumplir repetidamente en la medida que el operador vaya ingresando lneas, porque para cada lnea que se ingrese se calcular el valor del atributo frmula FacturaLineaImporte de la lnea, y en consecuencia se recalcular el valor del atributo frmula FacturaCalcTotal. Pero el valor calculado de este atributo no coincidir con el valor ingresado en el atributo FacturaEntTotal hasta que no se hayan ingresado todas las lneas de la factura; entonces, se disparar la regla Error(El total ingresado no coincide con el total calculado) if FacturaCalcTotal <> FacturaEntTotal;. Concluimos entonces que en este caso no nos sirve lo que determina el rbol de evaluacin, ya que no queremos que se evale la condicin de disparo de la regla Error cada vez que el operador ingrese, modifique o elimine lneas, sino que recin necesitamos que se evale cuando el usuario haya terminado de trabajar con todas las lneas de la factura. GeneXus ofrece eventos o momentos de disparo en las transacciones, que ocurren antes o despus de determinada accin, como la grabacin del cabezal, o de una lnea. Las reglas de las transacciones pueden condicionarse de manera tal de dispararse en el preciso instante en que ocurre alguno de esos eventos de disparo. Siguiendo el ejemplo que venamos viendo, existe un evento de disparo que ocurre luego de iterar en un nivel y salir del mismo. La sintaxis de este evento de disparo es: AfterLevel Level Atributo, debiendo ser Atributo un atributo perteneciente al nivel que se ha iterado y se abandona. De modo que a la regla Error de nuestro ejemplo, le agregaramos este evento de disparo, y quedara definida de la siguiente forma: Error(El total ingresado no coincide con el total calculado) if FacturaCalcTotal<>FacturaEntTotal On AfterLevel Level FacturaLineaPrecio; Con este evento de disparo que hemos agregado a la regla logramos controlar lo que desebamos en el momento adecuado. Adems de este evento de disparo, existen otros que veremos a continuacin.

139

Eventos de disparo
La mayora de las reglas de transacciones permiten que se les agregue de ser necesario un evento o momento de disparo. Al agregar un evento o momento de disparo a una regla, estaremos especificando que la regla se deber ejecutar en ese determinado momento. Eventos de disparo:
BeforeValidate AfterValidate BeforeInsert, BeforeUpdate, BeforeDelete AfterInsert, AfterUpdate, AfterDelete AfterLevel BeforeComplete AfterComplete

Al momento de la confirmacin de la transaccin, ocurre una serie de acciones que es necesario conocer para poder programar correctamente el comportamiento de las reglas. Para una transaccin de dos niveles, podramos enumerarlas como sigue: validacin de los datos del cabezal grabacin fsica del cabezal (ya sea insercin, modificacin o eliminacin) validacin de los datos de la primera lnea grabacin fsica de los datos de la primera lnea validacin de los datos de la segunda lnea grabacin fsica de los datos de la segunda lnea validacin de los datos de la n-sima lnea grabacin fsica de los datos de la n-sima lnea commit La accin de validacin de los datos del cabezal ocurre cuando se han validado todos y cada uno de los campos ingresados en el cabezal. Observar que en este punto ya se han disparado todas las reglas que correspondan a atributos del cabezal y que no tenan evento de disparo asociado (ejemplo: Default(FacturaFecha, &today)). Inmediatamente despus se grabar el registro correspondiente al cabezal. Anlogo es el caso de las lneas: la validacin de los datos de una lnea ocurre cuando ya se han validado todos y cada uno de los datos de la lnea, y tambin se han disparado todas las reglas correspondientes segn el rbol de evaluacin (ejemplo: subtract( FacturaLineaCantidad, ProductoStock)). Inmediatamente despus de esta accin de validacin, se grabar fsicamente el registro correspondiente a la lnea. Cada transaccin, al terminar de trabajar con un cabezal y sus lneas, realiza un commit (es automtico; ser colocado en el cdigo generado por GeneXus, a menos que el analista especifique lo contrario, como veremos ms adelante). Es decir, si se van a ingresar los datos de dos facturas distintas utilizando la transaccin Factura, luego de ingresados los datos de la primera, se commitearn sus registros, y luego se ingresar la segunda, al cabo de lo cul se commitearn sus registros. Los eventos de disparo de reglas permiten definir que se ejecuten antes o despus de alguna de las acciones que acabamos de enumerar. Veremos cundo ocurre cada evento de disparo.

140

Evento de disparo: BeforeValidate Este evento de disparo ocurre un instante de tiempo antes de que la informacin de la instancia con la que se est trabajando (cabezal o lnea x) sea validada (o confirmada). Es decir, ocurrir un instante de tiempo antes de la accin de validacin del cabezal o validacin de la lnea, segn corresponda. Observar que aqu tambin se habrn disparado todas las reglas segn el rbol de evaluacin que no estn condicionadas a evento de disparo alguno. Eventos de disparo: AfterValidate, BeforeInsert, BeforeUdate, BeforeDelete El evento de disparo AfterValidate permite especificar que una regla se ejecute inmediatamente antes de que se grabe fsicamente cada instancia del nivel al cual est asociada la regla, en la tabla fsica correspondiente, y despus de que se hayan validado los datos de esa instancia. En otras palabras, si se le agrega el evento de disparo AfterValidate a una regla, la misma se ejecutar para cada instancia del nivel al cual est asociada, inmediatamente antes de que la instancia se grabe fsicamente (ya sea que se inserte, modifique o elimine) como registro en la tabla fsica asociada al nivel. EJEMPLOS 1. Hay veces en las que no contamos con la posibilidad de utilizar la propiedad Autonumber para numerar de forma automtica y correlativa los atributos que son clave primaria simple. Tal funcionalidad es provista por los manejadores de base de datos (DBMSs) y GeneXus la aprovecha y permite usarla; sin embargo en los casos en los que no se trabaja con un manejador de base de datos, no contamos con la posibilidad de utilizar esta facilidad. En esos casos en los que necesitamos numerar de forma automtica y correlativa ciertos atributos, y no podemos utilizar la propiedad Autonumber, debemos resolverlo programndolo. Para ello solemos definir una transaccin conteniendo dos atributos, uno para almacenar un literal y otro para almacenar el ltimo nmero asignado automticamente al atributo descripto por el literal1; la transaccin conlleva la creacin de una tabla, y definimos un procedimiento que consulta esa tabla, obtiene el ltimo nmero asignado para el atributo a ser numerado, le suma uno y devuelve el prximo nmero, adems de actualizarlo en la tabla. Para invocar al procedimiento de numeracin automtica se debe definir en las transacciones que lo requieran una regla del siguiente estilo: ClienteId = PGetNumber.udp( Cliente ) if Insert on AfterValidate; En este caso se est queriendo autonumerar el atributo ClienteId de la transaccin Cliente Del mismo modo, si queremos autonumerar el identificador de facturas, escribiramos en la transaccin Factura la siguiente regla: FacturaId = PGetNumber.udp( Factura ) if Insert on AfterValidate; De esta forma definimos que se efecten numeraciones automticas en las transacciones nicamente cuando se realicen inserciones (por la condicin de disparo: if Insert) e inmediatamente antes de que se grabe fsicamente cada instancia a ser insertada (por el evento de disparo: on AfterValidate) a travs del primer nivel de la transaccin (porque en las dos reglas de invocacin mostradas, hay solamente un atributo involucrado que pertenece al primer nivel de las transacciones "Cliente" y "Factura" respectivamente). El motivo por el cual agregamos el evento de disparo on AfterValidate a estas reglas es para invocar al procedimiento de numeracin automtica inmediatamente antes de que se inserte el registro en la base de datos y luego de la validacin, intentando de esta forma tener el mayor grado de seguridad posible de que el nmero asignado ser utilizado (y no perder nmeros). Piense unos instantes el lector cundo se disparara la regla anterior de no estar condicionada a evento de disparo alguno, y qu podra pasar en el caso de que fallara la validacin de alguno de los datos del cabezal. La respuesta es simple: se perdera un nmero. Es decir, si el nmero de factura anterior fuera 5 y el usuario quisiera ingresar la siguiente factura, la regla de asignacin con udp que invoca la procedimiento de numeracin se disparara ni bien se ingresara a la transaccin estando en modo insert, ya que involucra al primer atributo del cabezal. El procedimiento devolvera el nmero 6, y si validando los datos del cabezal se encuentra algn error que no permite continuar con el proceso, y se abandonara la transaccin, por ejemplo, ese nmero 6 se habr perdido y la prxima factura, que correlativamente debera tener el nmero 6 no lo tendr, tendr el 7.

---------------------------------------------------------------------------------------------------------------------------1 Cuando vimos la regla serial introdujimos este tema de numeracin de cabezales, con la transaccin Numero que era la que tena el literal: NumeroCodigo y el ltimo nmero asignado a la transaccin correspondiente a ese literal: NumeroUltimo

141

Existen tres eventos de disparo que ocurren en el mismo momento que el AfterValidate, pero que ya contienen intrnseco el modo. Ellos son: BeforeInsert, BeforeUpdate y BeforeValidate. Es equivalente escribir la regla presentada antes como lo hicimos, a escribirla: FacturaId = PGetNumber.udp( Factura ) on BeforeInsert; Observar que aqu es redundante condicionar la regla a If Insert. Por tanto, valen las siguientes equivalencias: on BeforeInsert on BeforeUpdate on BeforeDelete If Insert on AfterValidate If Update on AfterValidate If Delete on AfterValidate

Si hacemos un esquema de las acciones que rodean al evento de disparo, quedarn claros los dos sinnimos elegidos para este evento (AfterValidate y BeforeInsert para modo insert) VALIDACIN DE LOS DATOS AfterValidate BeforeInsert BeforeUpdate BeforeDelete GRABACIN DEL REGISTRO (insert, update, delete segn corresponda)

2) Si definimos una regla a la cual le incluimos tambin el evento de disparo on AfterValidate, u on BeforeInsert, BeforeDelete, BeforeUdate pero a diferencia de los ejemplos recin vistos, se referencia en la regla al menos un atributo del segundo nivel de la transaccin en la cual se est definiendo la regla, la misma estar asociada al segundo nivel1. Por lo tanto, la regla se ejecutar inmediatamente antes de que se grabe fsicamente cada instancia correspondiente al segundo nivel de la transaccin.

Eventos de disparo: AfterInsert, AfterUpdate, AfterDelete As como existe un evento de disparo que permite definir que determinadas reglas se ejecuten inmediatamente antes de que se produzca la grabacin fsica de cada instancia de un nivel (AfterValidate, BeforeInsert, BeforeUpdate, BeforeDelete), tambin existen eventos de disparo para definir que ciertas reglas se ejecuten inmediantamente despus de que se inserten, modifiquen o eliminen fsicamente instancias de un nivel. Estos eventos son AfterInsert, AfterUpdate y AfterDelete. El evento de disparo AfterInsert permite definir que una regla se ejecute inmediatamente despus de que se inserte fsicamente cada instancia del nivel al cual est asociada la regla; el AfterUdate luego de que se actualice fsicamente la instancia, y el AfterDelete luego de que se elimine. EJEMPLOS Supongamos que en la transaccin "Cliente" queremos invocar a un reporte que realice la impresin de los datos de cada cliente con el cual se trabaje por medio de la transaccin. En qu momento debemos realizar la invocacin al reporte desde la transaccin? Caso 1: RPrintCliente.call( ClienteId ) on AfterValidate; No es adecuado agregarle este evento de disparo a la regla de invocacin al reporte, porque ste se invocara inmediatamente antes de la grabacin fsica de cada cliente. En consecuencia, el reporte no encontrara al cliente con sus datos en la tabla Cliente (si se estaba insertando un cliente por medio de la transaccin), o lo encontrara con sus datos desactualizados (si se estaba modificando un cliente por medio de la transaccin). Si en cambio se estaba eliminando un cliente por medio de la transaccin, el reporte encontrara los datos del cliente en la tabla Cliente y los listara justamente antes de la actualizacin fsica (eliminacin). Si se desea esto, es decir, emitir un listado con los datos de cada cliente que se elimine, sera adecuado definir la siguiente regla: RPrintCliente.call( ClienteId ) on BeforeDelete; o su equivalente: RPrintCliente.call( ClienteId ) if delete on AfterValidate;

-------------------------------------------------------------------------------------------------------------------------Existe otra forma de provocar que una regla que contiene atributos de un nivel determinado, se dispare en el nivel siguiente, mediante la clusula Level que mencionamos cuando vimos conceptos importantes sobre reglas de transacciones.

tiempo

142

para restringir el disparo de la regla nicamente a cuando se est eliminando un cliente, porque es el nico caso en el sera correcto utilizar el evento de disparo AfterValidate (ya que justamente necesitamos emitir el reporte antes de la eliminacin). Caso 2: RPrintCliente.Call( ClienteId ) on AfterInsert; El evento de disparo AfterInsert ocurre inmediatamente despus de que se inserte fsicamente cada instancia asociada a cierto nivel de la transaccin (en este caso, como el nico atributo involucrado en la regla es ClienteId, se trata de una regla asociada al primer y nico nivel de la transaccin "Cliente"). Como lo indica claramente su nombre, el evento de disparo AfterInsert slo ocurre al insertar una nueva instancia (precisamente luego de ser insertada como registro fsico). Es por ello que cuando se agrega el evento de disparo on AfterInsert a una regla, no es necesario agregarle la condicin de disparo if insert. Es correcto agregarle este evento de disparo a la regla de invocacin al reporte, ya que el reporte se invocara inmediatamente despus de que se inserte fsicamente cada cliente. As que el reporte encontrara al cliente con sus datos en la tabla Cliente y los imprimira. Lo que debe quedar claro es que con esta definicin el reporte se invocar nicamente luego de realizar inserciones. Caso 3: RPrintCliente.Call( ClienteId ) on AfterUpdate; El evento de disparo AfterUpdate ocurre inmediatamente despus de que se actualice fsicamente cada instancia asociada a cierto nivel de la transaccin (en este caso, como el nico atributo involucrado en la regla es ClienteId, se trata de una regla asociada al primer y nico nivel de la transaccin "Cliente"). Es adecuado agregarle este evento de disparo a la regla de invocacin al reporte, ya que el reporte se invocara inmediatamente despus de que se actualice fsicamente un cliente. As que el reporte encontrara al cliente con sus datos actualizados en la tabla CLIENTES y los imprimira. El reporte se invocar nicamente luego de realizar actualizaciones. Caso 4: RPrintCliente.Call( ClienteId ) on AfterDelete; El evento de disparo AfterDelete ocurre inmediatamente despus de que se elimine fsicamente cada instancia asociada a cierto nivel de la transaccin (en este caso, como el nico atributo involucrado en la regla es ClienteId, se trata de una regla asociada al primer y nico nivel de la transaccin "Cliente"). No es adecuado agregarle este evento de disparo a la regla de invocacin al reporte, porque el reporte se invocara inmediatamente despus de la eliminacin fsica de cada cliente. En consecuencia, el reporte no encontrara al cliente con sus datos en la tabla Cliente. Caso 5: RPrintCliente.Call( ClienteId ) on AfterInsert, AfterUpdate; RPrintCliente.Call( ClienteId ) if delete on AfterValidate; Para finalizar, estas dos reglas son las adecuadas para invocar a un reporte en la transaccin "Cliente", con el objetivo de imprimir los datos de cada cliente con el cual se trabaje, abarcando los tres modos de trabajo. Como se puede observar en la primera regla es posible incluir varios eventos de disparo separados por coma, cuando los mismos aplican a una misma regla. Es decir, es lo mismo definir estas dos reglas independientes: RPrintCliente.Call( ClienteId ) on AfterInsert; RPrintCliente.Call( ClienteId ) on AfterUpdate; que esta regla: RPrintCliente.Call( ClienteId ) on AfterInsert, AfterUpdate;

143

Caso 6: Si definimos una regla a la cual le incluimos el evento de disparo on AfterInsert, pero a diferencia de los ejemplos recin vistos, se referencia en la regla al menos un atributo del segundo nivel de la transaccin en la cual se est definiendo la regla, la misma estar asociada al segundo nivel. Por lo tanto, la regla se ejecutar inmediatamente despus de que se inserte fsicamente cada instancia correspondiente al segundo nivel de la transaccin. Anlogo es el caso de on AfterUpdate y on AfterDelete. Ampliamos el esquema que habamos efectuado antes, de las acciones que rodean a los eventos de disparo vistos hasta ahora: VALIDACIN DE LOS DATOS AfterValidate BeforeInsert BeforeUpdate BeforeDelete

tiempo tiempo

GRABACIN DEL REGISTRO (insert, update, delete segn corresponda) AfterInsert AfterUpdate AfterDelete

Este esquema se repite para cada instancia del nivel. Por ejemplo, pensemos en el ingreso de las lneas de una factura. Para cada lnea ocurrir este esquema, por lo que podemos pensar en un loop que se repite hasta que se termina de grabar la ltima lnea. La accin que sucede a la grabacin de la ltima lnea sera el abandonar ese nivel (en este caso el de las lneas de factura). Y luego de esa accin, a menos que venga otro nivel con el que se volvera a ingresar en el esquema anterior, ocurrir la ltima accin en la ejecucin, que es el commit. Entre la accin de abandonar el nivel, y el commit tendremos un evento (que admite dos nombres distintos) y otro para luego del commit. Son los que veremos a continuacin pero que ya mostramos en esquema: VALIDACIN DE LOS DATOS CABEZAL AfterValidate BeforeInsert BeforeUpdate BeforeDelete GRABACIN DEL REGISTRO (insert, update, delete segn corresponda) AfterInsert AfterUpdate AfterDelete VALIDACIN DE LOS DATOS LNEA AfterValidate BeforeInsert BeforeUpdate BeforeDelete GRABACIN DEL REGISTRO (insert, update, delete segn corresponda) AfterInsert AfterUpdate AfterDelete ABANDONAR NIVEL 2 AfterLevel - BeforeComplete COMMIT AfterComplete

loop

144

Eventos de disparo: AfterLevel, BeforeComplete El evento de disparo AfterLevel permite definir que una regla se ejecute inmediatamente despus de terminar de iterar determinado nivel. SINTAXIS: regla [if condicin de disparo] [on AfterLevel Level atributo]; DONDE: regla: es una regla de las permitidas en transacciones condicin de disparo: es una expresin booleana que permite involucrar atributos, variables, constantes y funciones, as como los operadores Or, And, Not. atributo: es un atributo perteneciente al nivel para el cual se desea que luego de ser iterado, se ejecute la regla. FUNCIONALIDAD: Si el atributo que se especifica a continuacin del evento de disparo AfterLevel pertenece al segundo nivel de la transaccin, la regla se ejecutar cuando se hayan terminado de iterar todas las lneas del segundo nivel. Y si el atributo que se especifica a continuacin del evento de disparo AfterLevel pertenece al primer nivel siguiendo el mismo concepto- la regla se ejecutar cuando se haya terminado de iterar por todos los cabezales. Observar que esto se da al final de todo, es decir, una vez que se hayan ingresado todos los cabezales y sus lneas y se cierre la transaccin (en ese momento se habrn iterado todos los cabezales). Por lo tanto, si el atributo especificado pertenece al primer nivel, la regla se disparar una vez sola antes del Evento Exit (es un evento que se ejecuta una sla vez cuando se cierra una transaccin en tiempo de ejecucin, como veremos). Ejemplo: Rever el ejemplo presentado antes, donde tenamos una transaccin para representar las facturas que nos entregan nuestros proveedores, y donde queramos controlar que el total calculado de cada factura coincidiera con el total ingresado. All tenamos la regla: Error('El total ingresado no coincide con el total calculado') if FacturaCalcTotal<>FacturaEntTotal; que necesitramos se disparara luego de ingresadas todas las lneas de la factura. Por tanto, el evento de disparo apropiado ser AfterLevel Level att, donde att sea cualquier atributo de las lneas. El evento de nombre BeforeComplete, en este caso, coincide con el AfterLevel. Si observamos el esquema presentado en la pgina anterior, podemos ver que el instante de tiempo que hay entre que se abandona el ltimo nivel y se realiza el commit es el instante en que ocurren estos eventos. Son dos nombres para referirnos a lo mismo. Cuidado que esto es as siempre y cuando el nivel abandonado sea el ltimo. Supngase por ejemplo una transaccin con dos niveles paralelos. Por ejemplo, si agregamos al cliente sus direcciones de mail y sus nmeros telefnicos (puede tener varios): ClienteId* ClienteNombre (ClienteTelefono* ) (ClienteEMail* ) El momento en que deber dispararse una regla condicionada a: On AfterLevel Level ClienteTelefono NO COINCIDIRA con el de una regla condicionada a on BeforeComplete. Mientras que la primera se disparar cuando se abandona el nivel de los telfonos, y antes de entrar a validar todos los emails, la segunda se disparar despus de abandonar este ltimo nivel. En este caso el evento BeforeComplete coincidir con el AfterLevel Level ClienteEMail. Evento de disparo: AfterComplete Este evento corresponde al instante de tiempo que sucede al commit. Hablaremos ms de este evento unas pginas adelante, cuando estudiemos la integridad transaccional. Si se abre la transaccin de facturas, se ingresan 3 facturas (cabezal y sus respectivas lneas) y se cierra la transaccin, ocurrirn 3 commits (uno al final de cada ingreso de cabezal + lneas) y 3 eventos AfterComplete.

145

Ejemplo en transaccin de 2 niveles


Interactivamente y antes de confirmar:
REGLAS STAND-ALONE

EVALUACION DE REGLAS Y FORMULAS SEGN ARBOL

EVALUACION DE REGLAS Y FORMULAS SEGN ARBOL

PARA CADA LINEA

El siguiente ejemplo pretende mostrar visualmente en qu momentos se irn disparando las reglas y frmulas definidas en una transaccin. Las reglas que no posean evento de disparo, as como las frmulas, se ejecutarn en forma interactiva a medida que el usuario vaya pasando por los campos (ejecucin en el cliente). El disparo de reglas y frmulas se ir haciendo de acuerdo al rbol de evaluacin, siguiendo el orden que ste determina. Una vez que el usuario confirme la pantalla (esto es: presione el botn Apply Changes), los datos se enviarn al servidor y all se realizarn las validaciones y disparo de reglas y frmulas mencionadas antes, nuevamente, adems de dispararse las reglas que estn condicionadas a eventos de disparo, por primera vez, junto con las grabaciones de los registros correspondientes, en el orden que se muestra en la siguiente hoja. Esto se realizar en el servidor.

146

Ejemplo en transaccin de 2 niveles


Al confirmar los datos, se ejecutan en el siguiente orden:

REGLAS STAND-ALONE EVALUACION REGLAS Y FRMULAS SEGN ARBOL BeforeValidate VALIDACIN AfterValidate / BeforeInsert / Update / Delete GRABACION DEL CABEZAL AfterInsert / Update / Delete EVALUACION DE REGLAS Y FORMULAS SEGN ARBOL PARA CADA LINEA

BeforeValidate VALIDACIN AfterValidate / BeforeInsert / Udpate / Delete GRABACION DE LA LINEA AfterInsert/Update/Delete ABANDONAR NIVEL 2 AfterLevel Level attNivel2 - BeforeComplete COMMIT AfterComplete

Reglas stand alone Las reglas stand alone son aquellas que: 1. Pueden ejecutarse con la informacin provista por los parmetros recibidos. 2. No dependen de nada para ejecutarse. Ejemplos de reglas stand alone (por poder ejecutarse con la informacin provista por los parmetros): &A = parmetro2; Msg( ... ) if parmetro1 = 7; Ejemplos de reglas stand alone (por no depender de nada para ejecutarse): msg( You are in the Factura transaction); &A = 7; Por lo tanto, son las primeras reglas que pueden ejecutarse. Luego de la ejecucin de las reglas stand alone, se ejecutan las reglas asociadas al primer nivel de la transaccin, que no tengan evento de disparo definido, siguiendo el orden de dependencias determinado por GeneXus (as como las frmulas asociadas al primer nivel). A modo de ejemplo, se disparar la regla: Default( FacturaFecha, &Today); Despus de ejecutadas las reglas mencionadas para el cabezal, se ejecutarn todas las reglas que tengan como evento de disparo BeforeValidate, ya que inmediatamente despus ocurrir la accin de validacin (o confirmacin) de la informacin de ese primer nivel. Inmediatamente despus de la validacin del primer nivel se ejecutan las reglas asociadas al primer nivel de la transaccin que incluyan en su definicin el evento de disparo AfterValidate, o los BeforeInsert, BeforeUpdate, BeforeDelete, dependiendo del modo en el que se est. Por ejemplo: Si no podemos autonumerar las facturas con la propiedad Autonumber por no ser soportada por el DBMS elegido: FacturaId = PGetNumber.udp(Factura) on BeforeInsert;

147

Seguidamente a la ejecucin de las reglas asociadas al primer nivel con alguno de estos eventos de disparo se ejecuta la accin de grabacin; es decir, se grabar fsicamente la instancia correspondiente al primer nivel de la transaccin como registro fsico en la tabla correspondiente (en este ejemplo, en la tabla: Factura). Inmediatamente despus de haberse grabado esa instancia: si la grabacin correspondi a una insercin: se ejecutarn las reglas asociadas al primer nivel de la transaccin con evento de disparo AfterInsert. si la grabacin correspondi a una actualizacin: se ejecutarn las reglas asociadas al primer nivel de la transaccin con evento de disparo AfterUpdate. si la grabacin correspondi a una eliminacin: se ejecutarn las reglas asociadas al primer nivel de la transaccin con evento de disparo AfterDelete.

Si se trata de una transaccin de dos niveles, como en este caso, a continuacin se ejecutar para cada una de las lneas: En primer lugar, las reglas asociadas al segundo nivel de la transaccin que no tengan evento de disparo definido, siguiendo el orden de dependencias determinado por GeneXus (as como las frmulas asociadas al segundo nivel). Ejemplos de ello son la regla Subtract( FacturaLineaCantidad, ProductoStock ); la frmula FacturaLineaImporte = FacturaLineaCantidad*ProductoPrecio. Despus de ejecutadas las reglas mencionadas para una lnea, se ejecutarn todas las reglas que tengan como evento de disparo BeforeValidate, dado que inmediatamente despus ocurre la validacin de la lnea; esto es una accin que ocurre a continuacin de haber terminado de trabajar con la lnea. Inmediatamente despus de la validacin de la lnea, se ejecutarn las reglas asociadas al segundo nivel de la transaccin que incluyan en su definicin alguno de los eventos de disparo: AfterValidate, BeforeInsert, BeforeUpdate, BeforeDelete. Seguidamente a la ejecucin de las reglas asociadas al segundo nivel con alguno de estos eventos de disparo se ejecutar la accin de grabacin; es decir, se grabar fsicamente la instancia correspondiente a la lnea como registro fsico en la tabla correspondiente (en este ejemplo, en la tabla: FACTURALINEA). Inmediatamente despus de haberse grabado la instancia correspondiente a la lnea como registro fsico en la tabla correspondiente: si la grabacin correspondi a una insercin: se ejecutarn las reglas asociadas al segundo nivel de la transaccin con evento de disparo AfterInsert. si la grabacin correspondi a una actualizacin: se ejecutarn las reglas asociadas al segundo nivel de la transaccin con evento de disparo AfterUpdate. si la grabacin correspondi a una eliminacin: se ejecutarn las reglas asociadas al segundo nivel de la transaccin con evento de disparo AfterDelete. Todas estas operaciones sombreadas de gris claro, se ejecutarn en el orden descrito, para cada una de las lneas. Luego de la iteracin de todas lneas, podemos suponer la existencia de una accin que Aclaracin importante: Todas laslas operaciones sombreadas, tanto en gris claro como en gris oscuro, se podramos llamar si abandono segundo nivel . niveles; Luego de modo la misma se ejecutarn ejecutan nicamente se trata de del una transaccin de dos que cuando se trata de las una transaccin de un nivel, operaciones no se ejecutarn. El motivo de los dos sombreados distintos, es reglas definidas con tales evento de disparo AfterLevel Level Atributo del 2do nivel . Si no para diferenciar el conjunto de operaciones que se ejecuta para cada una de las lneas (sombreado gris existe otro nivel, como es el caso del ejemplo, entonces coincidir con el evento de disparo claro) de las operaciones que se ejecutan solamente una vez finalizada la iteracin en las lneas BeforeComplete . oscuro). A continuacin seguimos explicando en orden, el resto de las operaciones (sombreado gris ms que se ejecutan, as sea que se trate de una transaccin de un nivel o dos.
Luego de haberse ejecutado todas las operaciones explicadas hasta el momento, se efectuar un commit, siempre y cuando el ambiente o plataforma de trabajo sea Cliente/Servidor.

148

A continuacin se ejecutarn las reglas con evento de disparo AfterComplete. Es de fundamental importancia que quede claro que todas las operaciones explicadas se ejecutarn en el orden en el que se han descrito, para cada factura con la cual se trabaje por medio de la transaccin "Factura" (ya sea que se ingrese, modifique o elimine). Puede ser til tener en cuenta que se han resaltado en negrita las acciones cada vez que se las ha mencionado. Las mismas son: validacin, grabacin , abandono del segundo nivel y commit. Es indispensable asimilar el orden en el que se ejecutan las reglas en una transaccin, cules son los eventos de disparo disponibles para asignarles, cundo se disparan exactamente, y qu acciones ocurren antes y despus de cada evento de disparo, ya que solamente conocindolos bien se podr programar el comportamiento de las transacciones adecuadamente. Es sencillo comprender que si necesitamos programar determinados controles o acciones en las transacciones, tendremos que saber bien si hacerlo antes de que se grabe el cabezal, despus de que se haya grabado el mismo, para cada una de las lneas despus de que se hayan grabado, o antes, despus del commit o antes, por lo tanto es fundamental tener claro todo este tema. Nos ha faltado mencionar cundo ocurrir una regla condicionada al evento de disparo: AfterLevel Level Atributo 1er nivel. Diferencia entre aplicacin 3 capas Win y aplicacin Web Aqu aparece una diferencia importante entre Win y Web, que tiene que ver con las caractersticas inherentes a cada una. Mientras que en Win la capa de la aplicacin que se encuentra en el cliente se mantiene conectada al servidor de manera continua (el servidor mantiene estado) , en Web la conexin es discreta: se logra cuando deben intercambiar informacin y luego se desconectan; no se mantiene un estado. Esto establece algunas diferencias en el comportamiento de las transacciones. Mientras que una aplicacin Win mantiene la conexin con el servidor de manera tal que ste pueda mantener el estado de una transaccin que se est ejecutando: controlar cundo se abri, cuntas instancias se han ingresado y cundo se ha cerrado la misma, en Web esto no es posible (no mantiene estado). Por tanto una regla condicionada al evento de disparo AfterLevel Level atributo del 1er. nivel solo se disparar en una transaccin Win (para una Web no tiene sentido) y lo har una sola vez, cuando se cierra la transaccin. Recordemos que una regla con evento de disparo AfterLevel Level Atributo 1er nivel se ejecuta luego de que se haya iterado por todos los cabezales, y esto se da al final de todo, es decir, una vez que se haya trabajado con todos los cabezales y sus lneas y se cierre la transaccin (en ese momento se habr iterado por todos los cabezales). No podemos dejar de mencionar algo que tambin se ejecutar una nica vez en la ejecucin de una transaccin: el Evento Start (lo primero que se ejecuta) y el Evento Exit (lo ltimo que se ejecuta). En una transaccin Web estos eventos se ejecutarn una vez por cada instancia de transaccin con la que se trabaje.

149

Ejemplos
Cundo se dispararn las siguientes reglas?
PSomething.call( FacturaId ) if Insert; Luego de validado el campo FacturaId e inferido que se est en modo Insert PSomething.call( FacturaId ) on BeforeInsert; Luego de disparadas todas las reglas y frmulas segn rbol, y validados todos los datos del cabezal. Un instante antes de insertar el registro. PSomething.call( FacturaId, ProductoId ) on BeforeInsert; Luego de disparadas todas las reglas y frmulas segn rbol, y validados todos los datos de la lnea. Un instante antes de insertar el registro. PSomething.call( FacturaId ) on BeforeInsert Level ProductoId; dem que el anterior. Observar que Level ProductoId especifica que se est hablando del BeforeInsert de las lneas y no del cabezal.

150

Ejemplos
Algunas reglas estn mal programadas. Cules? FacturaFecha = &today on AfterInsert;
Incorrecto: El ltimo momento para asignar valor a un atributo del cabezal es inmediatamente antes de su grabacin (BeforeInsert)

PSomething.call( FacturaFecha ) on AfterInsert;


Correcto: aqu se est pasando el valor de un atributo del cabezal; mientras se est en la instancia de la factura se tiene ese valor en memoria. ltimo momento posible para utilizarlo AfterComplete.

PSomething.call( FacturaId, ProductoId ) on AfterLevel Level ProductoId;


Incorrecto: la regla, sin el evento de disparo est asociada al 2do. Nivel, es decir, se disparara por cada lnea. Pero el evento de disparo la condiciona a ejecutarse al salir de las lneas. Qu valor tendra ProductoId?

151

Reglas con el mismo evento de disparo


Son disparadas en el orden en que fueron definidas Ejemplo 1 xxx.call() On AfterComplete; yyy.call() On AfterComplete; Ejemplo 2 pgmname.call( ClienteId, &flag) On AfterComplete; error(' ') if &flag = 'N On AfterComplete;

Reglas con el mismo evento de disparo Cuando en una transaccin se definen dos o ms reglas con el mismo evento de disparo, y no existe ninguna dependencia entre ellas, las mismas se ejecutarn respetando el orden de definicin. Ejemplos: 1) Se definen las siguientes reglas en una transaccin: xxx.Call() on AfterComplete; yyy.Call() on AfterComplete; Como las dos reglas definidas estn condicionadas con el mismo evento de disparo, y no existe ninguna dependencia entre ellas, las mismas se ejecutarn en el mismo orden en el cual se han escrito. 2) En una transaccin se necesita invocar a un procedimiento que realiza determinada validacin y retorna un valor S o N; si el valor devuelto es N, se debe dar un mensaje de error. Para resolver esto, evaluaremos dos posibilidades: 2.1) Definir las reglas: PXXX.call(&flag) on AfterValidate; error() if &flag=N on AfterValidate; 2.2) O definir las reglas: &flag = PXXX.udp() on AfterValidate; error() if &flag=N on AfterValidate;

152

En la primera alternativa, se ha definido una regla call y una regla error. Ambas reglas tienen el mismo evento de disparo, y aparentemente existira dependencia entre ellas, ya que la regla de error est condicionada al valor de la variable &flag, y la variable &flag se pasa por parmetro en la regla call. Sin embargo, si bien la dependencia nos puede parecer evidente porque en el procedimiento programaremos a la variable &flag, de salida, en la seccin de reglas de la transaccin -que es donde se encuentran las reglas que estamos viendo-, el especificador de GeneXus no puede saber si los parmetros pasados en un call son de entrada, de salida, o de entrada-salida; en consecuencia el especificador no encontrar interdependencia entre las reglas call y error, ya que la variable &flag podra ser pasada como variable de entrada al procedimiento, y en ese caso por ejemplo, no habra una dependencia por la cual primero se deba ejecutar la regla call y luego la regla error. As que concluyendo, no se detectan dependencias entre las reglas call y error de la alternativa 2.1), por lo que las mismas se dispararn entonces en el orden en el que estn escritas. Es importante ver que si las reglas call y error estuvieran escritas en orden inverso (es decir, primero la regla error y despus la regla call), el comportamiento no ser el esperado en muchos casos. Con respecto a la segunda alternativa, observemos que la misma consiste en una regla con udp y una regla error. Ambas reglas tienen el mismo evento de disparo, y en este caso s existe dependencia entre ellas, ya que la regla error est condicionada al valor de la variable &flag, y como la invocacin al procedimiento se realiza con udp, para el especificador de GeneXus queda claro que la variable &flag vuelve modificada del procedimiento; por lo tanto el especificador de GeneXus entiende que primero se debe disparar la invocacin al procedimiento con udp y luego la regla error, porque la variable &flag se carga mediante la invocacin al procedimiento con udp, y luego de que dicha variable tenga valor, es que habr que evaluar si disparar la regla error, o no. En el caso 2.2) entonces, independientemente del orden de definicin de ambas reglas, la invocacin al procedimiento con udp se disparar primero, y luego de ello, se disparar la regla error (en caso de que se cumpla la condicin de disparo, claro est). Por esta razn se recomienda que siempre que se quieran definir validaciones de este tipo, se utilice udp en lugar de call.

153

Consideracin importante acerca del disparo de reglas


Reglas que no tienen evento de disparo asociado, se ejecutarn una vez o dos o tres, dependiendo de si se trabaja con Confirmation Cuidado si la regla es una invocacin a un procedimiento que actualiza la BD!
Para que no se dispare ms de una vez, habr que asignarle evento de disparo especfico a la regla, o estudiar bien la lgica del procedimiento y tener en cuenta la doble o triple ejecucin del mismo.

Esto no suceder con reglas de GeneXus (como subtract, add) que actualizan la BD porque GX tiene la inteligencia para realizar el update solo al confirmar (lo mostrado en forma interactiva se calcula en memoria).

Es importante tener en cuenta que las reglas que no tienen evento de disparo asociado, se ejecutarn una vez o dos o tres, dependiendo de lo que se haya configurado en la propiedad del modelo. Por ejemplo, si se trabaja en Web y propiedad Confirmation=No, valor por defecto, las reglas que no tengan evento de disparo asociado se dispararn: primero en forma interactiva en la medida que el usuario final vaya trabajando en el form, y luego nuevamente cuando el usuario final efecte la confirmacin. Es especialmente importante considerar esto en aquellos casos de reglas que consistan en invocaciones a procedimientos que actualicen la base de datos. Si se tiene una invocacin a un procedimiento que actualiza la base de datos, habr que optar por alguna de las siguientes alternativas para evitar que se dispare ms de una vez: asignarle evento de disparo especfico a la regla o bien decidir si configurar o no la propiedad confimation o estudiar bien la lgica del procedimiento y tener en cuenta la doble o triple ejecucin del mismo Por ltimo, si se configurara Confirmation= Yes, las reglas sin evento de disparo asociado tendran un triple disparo.

154

EVENTOS EN TRANSACCIONES

En las transacciones se permite la programacin dirigida por eventos, que es un estilo de programacin en el cul se define cdigo que permanece ocioso, hasta que suceden eventos provocados por el usuario o por el sistema, que provocan que el cdigo definido se ejecute. Los eventos son acciones reconocidas por un objeto que pueden suceder o no. A cada evento se le puede asociar cdigo, que se ejecutar solamente si el evento se produce. El cdigo que se le puede asociar a un evento se escribe siguiendo el estilo procedural; y cuando el evento se produce, el cdigo asociado al mismo se ejecutar secuencialmente.

155

Eventos en Transacciones

Evento Start Evento User Event Evento After Trn Evento Exit

Los eventos Start y Exit difieren de acuerdo a la interfaz que se utilice. Como en Web no se mantiene un estado en el servidor que permita saber qu es lo que se ejecut en el cliente, no es posible saber si se est ingresando la primera instancia de una factura, o si es la n-sima. Por esta razn, en Web, se disparar el evento cada vez que se enve al servidor la informacin de la instancia con la que se est trabajando. Anlogas consideraciones podemos hacer para el caso del evento Exit, razn por la cul el evento se ejecutar por cada iteracin, al final de la misma.

156

Evento Start
Se ejecuta:
cada vez que se somete el form de la transaccin al servidor, lo primero que se ejecuta.

SINTAXIS:

Event Start cdigo EndEvent

EJEMPLO: Event Start &entrada=Now() EndEvent

El evento Start es un evento del sistema, por lo tanto ocurre automticamente. En qu momento se ejecuta? En interfaz Web, ocurre una nica vez por iteracin, al principio (es lo primero que se ejecuta). Se ejecutar cada vez que se someta el form de la transaccin al servidor, es decir, cuando se presione cualquier botn del form (Get, Apply Changes, botones de navegacin, botn Select o cualquier botn con un evento de usuario asociado), es lo primero que se ejecuta. Notas generales: En el evento Start fundamentalmente se trabaja con variables. En cuanto a utilizar atributos en este evento, ya sea para evaluarlos y/o usarlos de algn modo menos para actualizarlos, se debe tener en cuenta que los nicos atributos que se tienen disponibles son los que se reciben por parmetro en la regla parm. Ningn otro atributo tendr valor en este evento, pues todava no se ha editado ninguna instancia de la transaccin.

157

Evento Exit
Se ejecuta:
cada vez que se somete el form de la transaccin al servidor, lo ltimo que se ejecuta.

SINTAXIS:

Event Exit cdigo Endevent

El evento Exit es un evento del sistema, por lo tanto ocurre automticamente. En qu momento se ejecuta? En interfaz Web, ocurre una nica vez por iteracin, al final (es lo ltimo que se ejecuta). Al igual que en el evento Start, en el evento Exit fundamentalmente se trabaja con variables. En cuanto a utilizar atributos en este evento, se debe tener en cuenta que los nicos atributos que se tienen disponibles son los que se reciben por parmetro en la regla Parm. Ningn otro atributo tendr valor en este evento. Como en aplicaciones con interfaz Web se dispara cada vez que se dibuja la pantalla, al final, no hace las veces de un verdadero exit, por lo que no suele utilizarse en este ambiente.

158

Eventos de Usuario
Adems de los eventos ofrecidos por GeneXus, el analista puede definir eventos creados por l, llamados eventos de usuario. Cada evento de usuario luego se asocia a algn control del form de los que aceptan evento de usuario: botn, imagen o text block

SINTAXIS:

Event nombre de evento de usuario cdigo Endevent

Orden de ejecucin

1. 2. 3. 4.

Evento Start Lectura de atributos y variables del form Evento de usuario seleccionado Evento Exit

Como se puede observar en la sintaxis, se le debe dar un nombre a un evento de usuario, debindose declarar a continuacin de la palabra Event, encerrado entre comillas simples. EJEMPLO: Se desea que en la transaccin "Factura", el usuario tenga la posibilidad de imprimir la factura con la cual est trabajando: Event Print Factura EndEvent Cmo asociar un evento de usuario a un control? En el caso de interfaz web, adems de los botones, tambin las imgenes y los text blocks admiten la asociacin de evento de usuario. Para realizar la asociacin se debe insertar el control correspondiente en el form Web y luego en las propiedades del control, se deber seleccionar donde dice OnClickEvent uno de los eventos existentes, o se puede crear uno nuevo. Nota: se pueden ejecutar eventos asociados a botones con Alt+<letra>. Se logra colocando un & en el Caption del botn, antes de la letra con la que se desea acceder al evento. Ejemplo: si se desea que el cdigo del evento de usuario asociado a un botn de caption MyEvent se pueda ejecutar tambin con Alt+E, entonces en el Caption del botn, tendremos que escribir My&Event y se ver en el form web (en diseo) con un infraguin antes de la letra correspondiente, mientras que en ejecucin no se percibir nada: //evento definido en la transaccin "Factura" RPrintFactura.Call( FacturaId )

159

Evento After Trn


Ocurre inmediatamente despus de la ejecucin de las reglas con evento de disparo AfterComplete. Sintaxis: Event After Trn cdigo Endevent

Ejemplo: Event After trn Return EndEvent

El evento After Trn de las transacciones ocurre inmediatamente despus de la ejecucin de las reglas con evento de disparo AfterComplete. Por consiguiente, el cdigo que se incluya en este evento se ejecutar luego de culminada cada iteracin completa por medio de la transaccin (es decir, luego de haberse grabado cada cabezal con sus correspondientes lneas como registros fsicos en las tablas que corresponda y de haberse efectuado COMMIT). Existen las siguientes alternativas para programar comportamientos que se deseen ejecutar luego de cada iteracin completa por medio de una transaccin: 1. Definir reglas individuales con evento de disparo AfterComplete y dejar el evento After Trn sin cdigo 2. Definir todas las sentencias en el evento After Trn con estilo procedural, y no definir reglas con evento de disparo AfterComplete 3. Definir ambas cosas: algunas reglas con evento de disparo AfterComplete y cdigo en el evento After Trn Como venimos explicando, primero se ejecutan las reglas definidas con evento de disparo AfterComplete, e inmediatamente despus de las mismas se ejecuta el cdigo definido en el evento After Trn. Un concepto que es muy importante tener claro es que tanto en reglas con evento de disparo AfterComplete como en el evento After Trn, se conocen los valores de los atributos del primer nivel de la transaccin. Es decir, si bien ya se grabaron fsicamente los registros correspondientes al cabezal y las lneas de cierta iteracin completa, e incluso se efectu COMMIT, an se tienen disponibles los valores de los atributos del primer nivel, pudiendo estos utilizarse para pasarlos por parmetro en una invocacin, o evaluar su valor, o usarlos de algn modo salvo actualizarlos 1.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------1

Hay dos motivos por los cuales no es posible actualizar atributos en reglas con evento de disparo AfterComplete ni en el evento After Trn. El primer motivo es que ya se han hecho las grabaciones correspondientes e incluso se ha efectuado COMMIT, de modo que ya es tarde para asignar valores a atributos. Y adems, en lo que respecta al evento After Trn, en los eventos no se permite realizar asignaciones a atributos.

160

Ejemplo en transaccin de 2 niveles


Resumiendo, al confirmar los datos, se ejecutan en orden todo lo siguiente: START (lo primero en ejecutarse)
REGLAS STAND-ALONE EVALUACION REGLAS Y FRMULAS SEGN ARBOL BeforeValidate VALIDACIN AfterValidate / BeforeInsert / Update / Delete GRABACION DEL CABEZAL AfterInsert / Update / Delete EVALUACION DE REGLAS Y FORMULAS SEGN ARBOL PARA CADA LINEA

BeforeValidate VALIDACIN AfterValidate / BeforeInsert / Udpate / Delete GRABACION DE LA LINEA AfterInsert/Update/Delete ABANDONAR NIVEL 2 AfterLevel Level attNivel2 - BeforeComplete COMMIT AfterComplete After TRN

EXIT (lo ltimo en ejecutarse)

Para completar el diagrama visto anteriormente, agregamos al comienzo la ejecucin automtica del cdigo asociado al evento START y al final la ejecucin automtica del cdigo asociado al evento EXIT. Adems, incluimos la ejecucin del evento After TRN en el lugar que corresponde a su ejecucin.

161

Consideraciones
En los Eventos no se permite asignar valores a los atributos. Eventos Start y Exit: son sin tabla base.

Eventos de usuario y After Trn: son con tabla base.

No se permite asignar valores a atributos en los eventos. Los valores de los atributos pueden modificarse en las transacciones: hacindolo el usuario final, en tiempo de ejecucin, a travs del form (slo atributos de las tablas bases asociadas a la transaccin, o aquellos de la extendida permitidos por regla update) mediante reglas definidas por el programador (atributos de las tablas bases asociadas a la transaccin y sus extendidas) Solemos decir que los eventos Start y Exit son sin tabla base. Con esta expresin nos referimos a que en los eventos Start y Exit no hay consulta activa a la base de datos (ya que en el evento Start an no se ha hecho la consulta y en el evento Exit en Web se est cerrando la instancia y ya no disponemos de la consulta). Por este motivo es que no se conocen valores de atributos en los eventos Start y Exit, salvo los recibidos por parmetro. Por el contrario solemos decir que los eventos After Trn y de usuario son con tabla base, ya que cuando los mismos se ejecutan, s hay una consulta en edicin. Entonces, en particular en el evento After Trn, se conocen los valores de los atributos del primer nivel (el segundo nivel ya se ha iterado a esa altura y no hay posibilidad de posicionamiento en alguna lnea en particular); y en lo que respecta a los eventos de usuario se disponen los atributos de todos los niveles 1. Es fundamental comprender que as se disponga de los valores de ciertos atributos u otros dependiendo del evento, los mismos podrn utilizarse para ser evaluados y/o pasados por parmetro a objetos que se invoquen, y/o para alguna otra operacin cualquiera que no sea asignarles valor. Concluyendo, en ningn evento (no slo de transacciones, sino de ningn objeto GeneXus) se permite realizar asignaciones a atributos.

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------1 Si en un evento de usuario se referencian atributos de un segundo nivel u otro nivel subordinado, cuando el evento de usuario se ejecute se tendrn en cuenta los atributos de aquella lnea en la que se est posicionado; al momento de ejecutarse el evento de usuario se considerarn los valores de los atributos de dicha lnea. Y si el usuario no se haba posicionado explcitamente en determinada lnea, por defecto la lnea que estar seleccionada ser la primera, as que se considerarn los valores de los atributos de la misma.

162

También podría gustarte