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

Reglas:

Cliente

ClienteId*
ClienteNombre
CategoriaId
ClienteTotalCompras

Categoria

CategoriaId*
CategoriaDescuento

Envio

EnvioFecha*
EnvioCargo

Producto

ProductoId*
ProductoPrecio
ProducStock

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

ProductoStock FacturaLineaImporte
FacturaLineaCantidad

EnvioFecha

CategoriaDescuento

FacturaFecha
EnvioCargo

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

Total

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

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

tiempo

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.

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

tiempo

AfterValidate BeforeInsert BeforeUpdate BeforeDelete


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)

tiempo

AfterInsert AfterUpdate AfterDelete


ABANDONAR NIVEL 2
AfterLevel - BeforeComplete

loop

COMMIT
AfterComplete

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
quese
Aclaracin
importante:
Todas
laslas
operaciones
sombreadas,
tanto en
gris claro como
en gris
oscuro,
podramos
llamar si
abandono
segundo nivel.
Luego de modo
la misma
se ejecutarn
ejecutan
nicamente
se trata de del
una transaccin
de dos niveles;
que cuando
se trata de las
una
transaccin
de un nivel,
operaciones
no se
ejecutarn. El
motivo
de los dosdel
sombreados
distintos,
reglas definidas
con tales
evento
de disparo
AfterLevel
Level
Atributo
2do nivel.
Si noes
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.
(sombreado
gris ms oscuro). A continuacin seguimos explicando en orden, el resto de las operaciones
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:

Orden de
ejecucin

Event nombre de evento de usuario


cdigo
Endevent

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

//evento definido en la transaccin "Factura"

RPrintFactura.Call( FacturaId )
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:

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.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

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