Documentos de Académico
Documentos de Profesional
Documentos de Cultura
05 OrdenEjecucionReglasYFormulas PDF
05 OrdenEjecucionReglasYFormulas PDF
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
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
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
Error
Total
Total
ProveedorId*
Calculado Ingresado
FacturaId*
...
FacturaEntTotal
Total ingresado
FacturaLineaImporte
( ProductoId*
FacturaLineaCantidad
FacturaLineaPrecio
FacturaLineaImporte = FacturaLineaPrecio *
FacturaLineaCantidad)
...
FacturaCalcTotal = SUM(FacturaLineaImporte)
Total calculado
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
140
---------------------------------------------------------------------------------------------------------------------------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)
-------------------------------------------------------------------------------------------------------------------------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
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
loop
COMMIT
AfterComplete
144
(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
EVALUACION DE REGLAS Y
FORMULAS SEGN ARBOL
EVALUACION DE REGLAS Y
FORMULAS SEGN ARBOL
PARA
CADA
LINEA
146
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
&A = parmetro2;
&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
149
Ejemplos
Cundo se dispararn las siguientes reglas?
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)
151
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
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
155
Eventos en Transacciones
Evento Start
Evento User Event
Evento After Trn
Evento Exit
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
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
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
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
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
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
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.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------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