Beruflich Dokumente
Kultur Dokumente
En esta entrada vamos a ver como introducir un control de tipo rbol en las paginas de Peoplesoft.
Anteriormente para cumplir este requerimiento el Application Designer provea un control llamado
tree. En la ltimas versiones de las PeopleTools se recomienda no usar ms este control, en
cambio Peoplecode posee una funcin llamada GenerateTree que permite cargar los rboles en un
control de tipo HTML Area.
En los peoplebooks se encuentra un ejemplo de como cargar los rboles creados por el gestor de
rboles en una pgina creada por nosotros. La ruta del ejemplo en los PeopleBooks
es Home > PeopleBooks > Enterprise PeopleTools 8.51 PeopleBook: PeopleCode Developer's
Guide > Using HTML Trees and the GenerateTree Function.
El ejemplo que vamos a describir en esta entrada nos permitir crear un rbol a partir de cualquier
estructura jerrquica que se cree dentro de peoplesoft.
El primer paso es crear nuestra estructura jerarquica, para eso creamos un componente que
permita insertar los empleados de una organizacin de tal forma que estn relacionados con su
jefe.
A continuacin podemos ver la estructura del registro PE_TREE_EMPLE que vamos a utilizar para
ingresar la estructura jerrquica de los empleados.
Luego creamos la pgina PE_TREE_EMPLEADOS para administrar los datos del registro
PE_TREE_EMPLE. La pgina debe verse como se muestra a continuacin
Luego creamos un componente con registro de bsqueda INSTALLATION y un men que nos
permita registrar el componente dentro del portal.
En nuestro nuevo componente ingresamos unos datos de prueba como se ven en la ilustracin:
El siguiente paso es crear un Application Package que nos permita administrar los datos ingresado
por el componente PE_TREE_EMPLEADOS en forma de nodos de un rbol. Para lo anterior
crearemos la clase es pe_nodoEmpleado dentro del paquete PE_TREE_EMPLEADOS. Est clase
nos permitir manejar como un nodo cada uno de los registros ingresados por el componente
PE_TREE_EMPLEADOS. La clase tambin poseer un arreglo de objetos de est misma clase
que
representar
los
hijos
del
nodo.
A continuacin podemos ver el cdigo completo de la clase descrito lnea por lnea.
/*Lo primero es declarar nuestra clase*/
class pe_nodoEmpleado
/*El mtodo constructor recibir compo parmetros el nombre del nodo (En
nuestro caso el nombre del nodo ser el id del empleado que se creo), la
descripcin (El nombre del empleado que se creo) y un indicador que
indica si el nodo raz del rbol o no*/
method pe_nodoEmpleado(&str_nombreNodo_par As string,
&str_descNodo_par As string, &bol_nodoRaiz_par As boolean);
/*El siguiente mtodo permite cargar los hijos del nodo actual en un
arreglo */
method pe_cargarHijos();
/*El mtodo getNodo permite retornar un nodo que se encuentre dentro de
la estructura de nodos que se est procesando. */
method pe_getNodo(&str_nombreNodo_par As string) Returns
PE_TREE_EMPLEADOS:pe_nodoEmpleado;
/*El mtodo getNodo permite retornar un nodo que se encuentre dentro de
la estructura de nodos que se est procesando. */
method pe_getNodoNumber(&nbr_idNodo As number) Returns
PE_TREE_EMPLEADOS:pe_nodoEmpleado;
/*Mtodo que retorna el total de hijos del nodo*/
method pe_totalHijos() Returns number;
/*Propiedad para consultar el nombre del nodo*/
property string NOMBRE_NODO get;
/*Propiedad
para
consultar
la
descripcin
del
nodo*/
que
indica
si
ya
fueron
cargados
los
nodos
hijos*/
que
indica
si
el
nodo
tiene
hijos
no*/
/*Para cada uno de los empleados hijos del nodo actual, se crear un
nodo y se agrega al arreglo de nodos hijos del nodo actual*/
While &sql_hijos.Fetch(&str_cod, &str_nombre)
&obj_hijo = create PE_TREE_EMPLEADOS:pe_nodoEmpleado(&str_cod,
&str_nombre, False);
&obj_hijos.Push(&obj_hijo);
End-While;
/*Se marca el nodo para que indique que ya fueron cargados los nodos*/
&bol_cargoHijos = True;
end-method;
get NOMBRE_NODO
/+ Returns String +/
Return &str_nombreNodo;
end-get;
get DESCR_NODO
/+ Returns String +/
Return &str_descNodo;
end-get;
get CARGO_HIJOS
/+ Returns Boolean +/;
Return &bol_cargoHijos;
end-get;
get TIENE_HIJOS
/+ Returns Boolean +/;
Local number &nbr_hijos = 0;
/*si ya fueron cargados los hijos se valida que el arreglo de nodos hijos
tenga hijos*/
If &bol_cargoHijos Then
If &obj_hijos.Len = 0 Then
Return False;
Else
Return True;
End-If;
Else
/*Si no han sido cargados los hijos se
para verificar si tienes nodos hijos*/
If &bol_nodoRaiz Then
SQLExec("select count(1) from
PE_CODIGO_JEFE = ' '", &nbr_hijos);
Else
SQLExec("select count(1) from
PE_CODIGO_JEFE = :1", &str_nombreNodo,
End-If;
If &nbr_hijos = 0 Then
Return False;
Else
Return True;
End-If;
End-If;
end-get;
get NODO_RAIZ
/+ Returns Boolean +/
Return &bol_nodoRaiz
end-get;
method pe_getNodo
/+ &str_nombreNodo_par as String +/
/+ Returns PE_TREE_EMPLEADOS:pe_nodoEmpleado +/
Local number &nbr_nodos;
Local PE_TREE_EMPLEADOS:pe_nodoEmpleado &obj_hijo;
/*Retorna el nodo buscado, si es el actual, si es algn nodo hijo o si
es algn nodo hijo de los nodos hijos del nodo actual*/
If &str_nombreNodo_par = &str_nombreNodo Then
Return %This;
Else
If &bol_cargoHijos Then
For &nbr_nodos = 1 To &obj_hijos.Len
If &str_nombreNodo_par = &obj_hijos [&nbr_nodos].NOMBRE_NODO
Then
Return &obj_hijos [&nbr_nodos];
Else
&obj_hijo = &obj_hijos
[&nbr_nodos].pe_getNodo(&str_nombreNodo_par);
If &obj_hijo <> Null Then
Return &obj_hijo;
End-If;
End-If;
End-For;
Return Null
Else
Return Null;
End-If;
End-If;
end-method;
method pe_getNodoNumber
/+ &nbr_idNodo as Number +/
/+ Returns PE_TREE_EMPLEADOS:pe_nodoEmpleado +/
Return &obj_hijos [&nbr_idNodo];
end-method;
method pe_totalHijos
/+ Returns Number +/
Return &obj_hijos.Len;
end-method;
Con algunas modificaciones a la clase anterior se puede tener una clase que administre cualquier
tabla que almacene una estructura jerrquica.
La funcin GenerateTree funciona utilizando
generacin del rbol y otro que contiene cada
registro lo llamaremos PE_TREE_HDR
TREECTL_HDR_SBR y el segundo registro
utilizando el subrecord TREECTL_NDE_SBR.
parmetros de
rbol. El primer
el subrecord
se debe crear
El siguiente paso en nuestro ejemplo es crear un registro derived que almacene el campo tipo
LONG que tendr el cdigo HTML que generar la funcin GenerateTree y el campo Char(50) que
controlar los eventos que se generen en el HTML creado por la funcin GenerateTree.
En la siguiente imagen se puede ver la estructura de los 4 registro que estamos utilizando en
nuestro proyecto.
/*Se importa la clase que creamos para administrar los nodos del rbol de
empleados*/
import PE_TREE_EMPLEADOS:pe_nodoEmpleado;
/*Declaramos la variable que tendr el nodo raz de nuestro rbol*/
Component PE_TREE_EMPLEADOS:pe_nodoEmpleado &obj_nodos;
/*Declaramos el rowset que contendr la estructura que se utilizar para
ejecutar la funcin GenerateTree*/
Component Rowset &TREECTL;
&NODE_ROWSET = CreateRowset(Record.PE_TREE_NDE);
&TREECTL = CreateRowset(Record.PE_TREE_HDR, &NODE_ROWSET);
&TREECTL.InsertRow(1);
&REC = &TREECTL.GetRow(2).GetRecord(1);
/* Set the HDR options:
/*Asignamos el nombre de la pgina en la que va a ser mostrado el rbol*/
&REC.GetField(Field.PAGE_NAME).Value = "PE_TREE_EXAMPLE";
/*Asignamos el nombre del campo que usaremos para controlar los eventos
generados en el rbol*/
&REC.GetField(Field.PAGE_FIELD_NAME).Value = "PE_EVENT_FIELD";
/*Los siguientes campos se asignan por defecto*/
&REC.GetField(Field.PAGE_SIZE).Value = 15;
&REC.GetField(Field.DISPLAY_LEVELS).Value = 8;
&REC.GetField(Field.COLLAPSED_IMAGE).Value = "PT_TREE_COLLAPSED";
&REC.GetField(Field.EXPANDED_IMAGE).Value = "PT_TREE_EXPANDED";
&REC.GetField(Field.END_NODE_IMAGE).Value = "PT_TREE_END_NODE";
&REC.GetField(Field.LEAF_IMAGE).Value = "PT_TREE_LEAF";
&REC.GetField(Field.IMAGE_WIDTH).Value = 15;
&REC.GetField(Field.IMAGE_HEIGHT).Value = 12;
&REC.GetField(Field.INDENT_PIXELS).Value = 20;
/*Se crea el nodo raz de nuestro rbol de empleados*/
&obj_nodos = create PE_TREE_EMPLEADOS:pe_nodoEmpleado("Empleados", "Todos
los Empleados", True);
/*Si el nodo tiene hijos en la variable &PARENT_FLAG X que indica que el
nodo tiene hijos y no estos no se han desplegado*/
If &obj_nodos.TIENE_HIJOS Then
&PARENT_FLAG = "X";
Else
&PARENT_FLAG = "Y";
End-If;
&NODE_ROWSET = &TREECTL.GetRow(2).GetRowset(1);
&NODE_ROWSET.InsertRow(1);
&REC = &NODE_ROWSET.GetRow(2).GetRecord(1);
/*Se le indica al nodo que no es una hoja*/
&REC.GetField(Field.LEAF_FLAG).Value = "N";
/*Se asigna el nombre del nodo*/
&REC.GetField(Field.TREE_NODE).Value = "Empleados";
/*Se asigna la descripcin del nodo*/
&REC.GetField(Field.DESCR).Value = "Todos los Empleados";
/*Se asignan los siguiente valores por defecto*/
&REC.GetField(Field.RANGE_FROM).Value = "";
&REC.GetField(Field.RANGE_TO).Value = "";
&REC.GetField(Field.DYNAMIC_FLAG).Value = "N";
&REC.GetField(Field.ACTIVE_FLAG).Value = "Y";
&REC.GetField(Field.DISPLAY_OPTION).Value = "B";
&REC.GetField(Field.STYLECLASSNAME).Value = "PSHYPERLINK";
/*Se asigna el valor de la variable PARENT_FLAG*/
&REC.GetField(Field.PARENT_FLAG).Value = &PARENT_FLAG;
/*Se indica que el nodo est a nivel 1 dentro del rbol*/
&REC.GetField(Field.TREE_LEVEL_NUM).Value = 1;
&REC.GetField(Field.LEVEL_OFFSET).Value = 0;
/*Se ejecuta la funcin GenerateTree y el resultado se asigna al control
HTMLAREA que agregamos a la pgina */
PE_TREE_EXP.HTML_AREA_01 = GenerateTree(&TREECTL);
El ltimo paso de nuestro ejemplo es agregar el cdigo necesario al evento FieldChange del
campo PE_TREE_EXP.PE_FIELD_EVENT. El cdigo que agregaremos a este evento controla
cuando se despliegan o se colapsan los nodos y la carga de los nodos hijos cada vez que sea
necesario.
/*Se importa la clase para administrar los nodos de empelados*/
import PE_TREE_EMPLEADOS:pe_nodoEmpleado;
/*Se declara el rowset que contiene la informacin de los nodos que sern
generados por la funcin GenerateTree*/
Component Rowset &TREECTL;
/*Se declara el objeto que contiene el nodo raz del rbol de empleados*/
Component PE_TREE_EMPLEADOS:pe_nodoEmpleado &obj_nodos, &obj_nodoActual;
Local PE_TREE_EMPLEADOS:pe_nodoEmpleado &obj_nodoActual, &obj_Hijo;
/*Si el evento es de despliegue de un nodo*/
If Left(PE_TREE_EXP.PE_EVENT_FIELD, 1) = "X" Then
/*Se obtiene la fila que representa el nodo sobre el cual fue ejecutado
el evento*/
&ROW = Value(Right(PE_TREE_EXP.PE_EVENT_FIELD,
Len(PE_TREE_EXP.PE_EVENT_FIELD) - 1)) + 1;
&NODE_ROWSET = &TREECTL.GetRow(2).GetRowset(1);
/*Se obtiene el registro que corresponde al nodo sobre el que se ejecut
el evento*/
&PARENT_REC = &NODE_ROWSET.GetRow(&ROW).GetRecord(1);
/*Se valida el nivel del nodo sobre el que se ejecuto el evento */
&PARENT_LEVEL = &PARENT_REC.GetField(Field.TREE_LEVEL_NUM).Value;
&ROW = &ROW + 1;
/*Se obtiene el objeto nodo que corresponde al nodo del rbol sobre el
que se ejecuto el evento*/
&obj_nodoActual =
&obj_nodos.pe_getNodo(&PARENT_REC.GetField(Field.TREE_NODE).Value);
/*Si el nodo tiene hijos se cargan los hijos al rbol*/
If &obj_nodoActual.TIENE_HIJOS Then
&obj_nodoActual.pe_cargarHijos();
Local number &nbr_nodos;
/*Se recorren los hijos del nodo y se agregan al rowset que se est
usando de base para el rbol*/
For &nbr_nodos = 1 To &obj_nodoActual.pe_totalHijos()
&obj_Hijo = &obj_nodoActual.pe_getNodoNumber(&nbr_nodos);
&LEVEL_OFFSET = 0;
&NODE_ROWSET.InsertRow(&ROW - 1);
&REC = &NODE_ROWSET.GetRow(&ROW).GetRecord(1);
If &obj_Hijo.TIENE_HIJOS Then
&PARENT_FLAG = "X";
&REC.GetField(Field.LEAF_FLAG).Value = "N";
&REC.GetField(Field.TREE_NODE).Value = &obj_Hijo.NOMBRE_NODO;
&REC.GetField(Field.DESCR).Value = &obj_Hijo.DESCR_NODO;
&REC.GetField(Field.RANGE_FROM).Value = "";
&REC.GetField(Field.RANGE_TO).Value = "";
Else
/*Si el nodo no tiene hijos se marca como una hoja para diferenciarlo en
el rbol */
&PARENT_FLAG = "N";
&REC.GetField(Field.LEAF_FLAG).Value = "Y";
&REC.GetField(Field.TREE_NODE).Value = " ";
en la imagen siguiente