sábado, 19 de noviembre de 2011

Como usar Control de Ruta en AWE (Application Workflow Engine))

En la entrada anterior aprendimos como crear un workflow para una transacción utilizando AWE. En esta entrada queremos aumentar las posibilidades del AWE incluyendo el manejo del control ruta dentro de nuestro Workflow. 

Para los que no está familiarizados con el Control Ruta les cuento que es una herramienta que se utiliza en la anterior tecnología de workflow para restringir el enrutamiento de las transacciones.  Por ejemplo, tu tienes una trasacción que solo necesita una aprobación, entonces creamos un rol de aprobador y se lo asociamos a las personas que pueden aprobar la transacción, pero si la transacción se debe aprobar por una sola persona teniendo en cuenta la ciudad donde se haya generado la transacción, o sea el que aprueba las transacciones de Cali no es el mismo que aprueba el de Bucaramanga, ahí es donde entra a jugar el control ruta,  este nos permite asignarle a un usuario el rol de aprobador y además las ciudades para las cuales el debe realizar las aprobaciones.  

Para nuestro ejemplo vamos a usar el control de ruta para separar los aprobadores de transacciones por país, dependiendo del país en el que se registre el equipo debemos asignar un aprobador diferente.

El primer paso en nuestro ejemplo es crear un tipo control ruta, esto lo hacemos por la siguiente ruta: Inicio > Peopletools > Workflow > Rutas y Roles > Tipos de Control Ruta. En este componente agregamos un nuevo tipo llamado PAISES y como tabla de validación le asignamos COUNTRY_TBL. 

El siguiente paso es crear agrupaciones de países para que luego sean asignados a los aprobadores. En nuestro caso crearemos 2 grupos,  uno que representará a los países involucrados en la NBA y otro en el que asociaremos los países de latinoamerica.  Para esto vamos a Inicio > Peopletools > Workflow > Rutas y Roles > Perfiles de   Control de Rutas.  En esta ruta agregamos 2 perfiles:

- EQUIPOS LATAM:  A este perfil le asociamos el tipo de control ruta que creamos (PAISES) y le agregamos los países de Suramerica. 

- EQUIPOS NBA: A este perfil le asociamos el tipo de control ruta que creamos (PAISES) y le agregamos los países de la NBA. 

En la entrada anterior habíamos creado 3 usuarios para realizar las aprobaciones: PE_APROBADOR1 Asociado al rol PE_APROBADORES_UNO, PE_APROBADOR2 Asociado al rol PE_APROBADORES_DOS y PE_APROBADOR3 Asociado al rol PE_APROBADORES_TRES.  El siguiente paso es asociar a esos 3 usuarios al perfil control ruta "EQUIPOS LATAM" para que estos usuarios queden habilitados solo para aprobar los equipos asociados a países de Suramérica. Esto lo hacemos en Inicio > Peopletools > Seguridad > Perfiles de Usuario > Perfiles de Usuario, buscamos cada uno de los usuarios y vamos al rol de aprobación que tiene asociado cada uno de ellos.   Para cada rol asociado al usuario existe un link llamado Control Ruta,  en ese link podemos asociar el perfil control ruta "EQUIPOS LATAM". 

Para los aprobadores de los equipos de la NBA debemos crear 3 usuario más. PE_APROBADOR1_1 Asociado al rol PE_APROBADORES_UNO, PE_APROBADOR2_1 Asociado al rol PE_APROBADORES_DOS y PE_APROBADOR3_1 Asociado al rol PE_APROBADORES_TRES y en el control ruta asociamos el perfil "EQUIPOS NBA". 

Ahora debemos crear las consultas que nos permitirán enlazar el control ruta con el Application Workflow Engine.  Por cada rol que manejamos debemos crear 1 consulta por el gestor de consultas de Peoplesoft. De esta forma para nuestro ejemplo las consultas quedarán de la siguiente forma:

- PE_APROBADORES_UNO_QRY:


SELECT A.ROLEUSER 
  FROM PSROLEUSER A, PS_RTE_CNTL_RUSER B, PS_RTE_CNTL_LN C, PS_PE_EQUIPOS D
  WHERE A.ROLEUSER = B.ROLEUSER
     AND A.ROLENAME = B.ROLENAME
     AND B.RTE_CNTL_PROFILE = C.RTE_CNTL_PROFILE
     AND C.RTE_CNTL_TYPE = 'PAISES'
     AND D.COUNTRY BETWEEN C.RTE_FROM_VALUE AND C.RTE_TO_VALUE
     AND D.PE_ID_EQUIPO = :1
     AND A.ROLENAME = 'PE_APROBADORES_UNO'



- PE_APROBADORES_DOS_QRY:

SELECT A.ROLEUSER 
  FROM PSROLEUSER A, PS_RTE_CNTL_RUSER B, PS_RTE_CNTL_LN C, PS_PE_EQUIPOS D
  WHERE A.ROLEUSER = B.ROLEUSER
     AND A.ROLENAME = B.ROLENAME
     AND B.RTE_CNTL_PROFILE = C.RTE_CNTL_PROFILE
     AND C.RTE_CNTL_TYPE = 'PAISES'
     AND D.COUNTRY BETWEEN C.RTE_FROM_VALUE AND C.RTE_TO_VALUE
     AND D.PE_ID_EQUIPO = :1
     AND A.ROLENAME = 'PE_APROBADORES_DOS'

- PE_APROBADORES_TRES_QRY:

SELECT A.ROLEUSER 
  FROM PSROLEUSER A, PS_RTE_CNTL_RUSER B, PS_RTE_CNTL_LN C, PS_PE_EQUIPOS D
  WHERE A.ROLEUSER = B.ROLEUSER
     AND A.ROLENAME = B.ROLENAME
     AND B.RTE_CNTL_PROFILE = C.RTE_CNTL_PROFILE
     AND C.RTE_CNTL_TYPE = 'PAISES'
     AND D.COUNTRY BETWEEN C.RTE_FROM_VALUE AND C.RTE_TO_VALUE
     AND D.PE_ID_EQUIPO = :1
     AND A.ROLENAME = 'PE_APROBADORES_TRES'

Como podemos ver, cada consulta está asociada a un rol y además está enlazada al tipo de control ruta PAISES. La consulta adicionalmente tiene un PROMPT que filtra el ID del equipo que se está procesando, esto lo usa el sistema para poder filtrar los usuarios aprobadores que corresponden para cada equipo dependiendo del país que hayamos seleccionado. 

El último paso es modificar las listas de usuario que creamos en la entrada anterior,  para que ahora apunten a las consultas que acabamos de crear y no directamente a los roles. Las listas de usuarios modificadas deben verse de la siguiente forma: 


Y listo de está forma hemos modificado nuestro workflow para que tenga en cuenta el control ruta, solo queda hacer las pruebas y terminamos. 

Espero que está entrada les sea de utilidad, hasta la siguiente publicación. 


sábado, 29 de octubre de 2011

AWE: Application Workflow Engine

En está entrada vamos a ver el nuevo (Nuevo desde la versión 8.48) framework para incluir Workflows dentro de nuestras aplicaciones.  

La gran ventaja que presenta este framework frente a la anterior tecnología de workflow presente en PEOPLESOFT,  es que después de implantar el workflow dentro de nuestro aplicativo, no es necesario realizar trabajo técnico adicional, ya que todo el mantenimiento y parametrización adicional del workflow se puede realizar a través de la PIA. 

Lo primero que vamos a hacer son los pasos que se deben realizar por un técnico para poder incluir el worflow dentro del aplicativo.   

Para nuestro ejemplo necesitamos una página donde vamos a registrar los diferentes equipos deportivos, supongamos que ya tenemos la página y se ve de la siguiente forma:






Digamos que a este componente deseamos agregarle la funcionalidad del workflow, que para cada equipo que se adicione a la base de datos debe pasar por un proceso de aprobación. 


El primer paso es agregar al registro principal de nuestro componente (PE_EQUIPOS) un campo que represente el estado del equipo. El campo debe permitir 3 valores:


P: Pendiente
A: Aprobado
R: Rechazado


Adicionalmente debemos crear un registro derived que contendrá 4 campos:


- Un campo que representará el botón Enviar el que permitira iniciar el proceso de aprobación del registro


- Un segundo campo que representará el botón de Aprobar que permitirá al aprobador aprobar el registro. 

- Un tercer campo que representará el botón de rechazar que permitirá al aprobador rechazar el registro. 

- Y un último campo que permitirá ingresar comentarios al momento de aprobar o rechazar un registro. 

Después de agregar estos campos la página de nuestro componente debe lucir de la siguiente forma:





El siguiente paso es crear el registro que permitirá llevar el control de los procesos de aprobación de cada uno de los equipos,  en este record (de tipo SQL TABLE) se almacena el rastreo del workflow que estamos definiendo.  El registro debe ser construido de la siguiente forma:

1. Debe tener todos los campos llave del record principal de nuestro componente (en nuestro caso PE_EQUIPOS y la llave sería PE_ID_EQUIPO)

2. Debe incluir el subrecord EOAW_XREF_SBR.



Ahora debemos crear un Application Class que permita manejar el proceso del workflow.  Esta clase permite básicamente controlar la actualización del estado del registro, o sea permite actualizarlo a Pendiente, Aprobado o Rechazado según sea el caso. 


Está clase debe ser una clase derivada de la clase base EOAW_CORE:ApprovalEventHandler y debe implementar los siguientes métodos:


1. OnProcessLaunch: En este método se actualiza el estado del registro a P para indicar que el proceso acaba de iniciar y que el registro se encuentra pendiente de aprobación 


2. OnHeaderApprove: En este método se actualiza el estado del registro a A para indicar que el registro se encuentra aprobado

3. OnHeaderDeny: En este método se actualiza el estado del registro a R para indicar que el registro se encuentra rechazado

La clase padre posee una propiedad llamada &appInst que nos permite acceder a algunos métodos y propiedades para distintos procesos, en nuestra clase ejemplo utilizamos el método &appInst.thread.SetAppKeys para obtener la llaves del registro para el cual se está realizando el proceso de Workflow, en nuestro caso PE_EQUIPOS y la llave PE_ID_EQUIPO. 

Por último la clase tiene un método privado cuya finalidad es ejecutar el UPDATE sobre el campo estado del registro PE_EQUIPOS el cual es utilizado desde los otros 3 métodos. 

A continuación podemos ver el código completo de la clase:

import EOAW_CORE:*;
import EOAW_CORE:ENGINE:*;

class PE_APPROVAL_HANDLER extends EOAW_CORE:ApprovalEventHandler
   method PE_APPROVAL_HANDLER();
   method OnProcessLaunch(&appInst As EOAW_CORE:ENGINE:AppInst);
   method OnHeaderApprove(&appinst As EOAW_CORE:ENGINE:AppInst);
   method OnHeaderDeny(&userinst As EOAW_CORE:ENGINE:UserStepInst);
private
   method updateProcessFlag(&status As string);
   instance Record &RecordEquipo;
   Constant &APPROVED = "A";
   Constant &DENIED = "D";
   Constant &PENDING = "P";
end-class;

method PE_APPROVAL_HANDLER
   %Super = create EOAW_CORE:ApprovalEventHandler();
   &RecordEquipo = CreateRecord(Record.PE_EQUIPOS);
end-method;

method updateProcessFlag
   /+ &status as String +/
   Local string &IdEquipo;
   
   &IdEquipo = &RecordEquipo.PE_ID_EQUIPO.Value;
   
   SQLExec(SQL.PE_EQUI_UPD_APPR_FLAG, &status, &IdEquipo);
   
end-method;

method OnProcessLaunch
   /+ &appInst as EOAW_CORE:ENGINE:AppInst +/
   /+ Extends/implements EOAW_CORE:ApprovalEventHandler.OnProcessLaunch +/
   
   &appInst.thread.SetAppKeys(&RecordEquipo);
   %This.updateProcessFlag(&PENDING);
end-method;

method OnHeaderApprove
   /+ &appinst as EOAW_CORE:ENGINE:AppInst +/
   /+ Extends/implements EOAW_CORE:ApprovalEventHandler.OnHeaderApprove +/
   
   &appinst.thread.SetAppKeys(&RecordEquipo);
   %This.updateProcessFlag(&APPROVED);
end-method;

method OnHeaderDeny
   /+ &userinst as EOAW_CORE:ENGINE:UserStepInst +/
   /+ Extends/implements EOAW_CORE:ApprovalEventHandler.OnHeaderDeny +/
   
   &userinst.thread.SetAppKeys(&RecordEquipo);
   %This.updateProcessFlag(&DENIED);
end-method;

El siguiente paso dentro de nuestra implantación del workflow es escribir el código que inicia los objetos necesarios para el proceso,  esto se debe realizar el el evento POSTBUILD del componente. Antes de eso vamos a escribir una clase que nos permite controlar la visualización de los botones de Aprobación, Rechazo y Envío del componente.  

Esta clase debe permitir a partir de una instancia de la clase EOAW_CORE:LaunchManager y otra de la clase EOAW_CORE:ApprovalManager determinar si el usuario que está accediendo al componente es aprobador, si es así habilitará los botones de aprobación y rechazo.  Si el proceso está pendiente de ser iniciado la clase habilitará el botón Enviar. 

Para determinar si un usuario está habilitado para aprobar o rechazar la transacción se utilizá la propiedad hasPending del objeto EOAW_CORE:ApprovalManager la cual indica si el usuario que ingreso al objeto tiene pendiente realizar una aprobación sobre el registro. 

Para determinar si el registro está pendiente de iniciar el proceso de Workflow se usa la propiedad submitEnabled del objeto  EOAW_CORE:LaunchManager.  

La clase quedaría de la siguiente forma:  

import EOAW_CORE:LaunchManager;
import EOAW_CORE:ApprovalManager;

class PE_UTILIDADES
   method PE_UTILIDADES();
   method pe_ActualizarWF(&rs0 As Rowset, &obj_launch As EOAW_CORE:LaunchManager, &obj_approval As EOAW_CORE:ApprovalManager);
private
end-class;

method PE_UTILIDADES
end-method;

method pe_ActualizarWF
   /+ &rs0 as Rowset, +/
   /+ &obj_launch as EOAW_CORE:LaunchManager, +/
   /+ &obj_approval as EOAW_CORE:ApprovalManager +/
   Local Row &row1 = &rs0.GetRow(1);
   Local Record &rec_approval = &row1.GetRecord(Record.PE_EQUIPOS_WRK);
   Local boolean &isApprover = False;
   
   If &obj_approval.hasAppInst Then
      &isApprover = &obj_approval.hasPending;
   End-If;
   &rec_approval.PE_ENVIAR_BTN.Visible = &obj_launch.submitEnabled;
   &rec_approval.PE_APROBAR_BTN.Visible = &isApprover;
   &rec_approval.PE_RECHAZAR_BTN.Visible = &isApprover;
end-method;

Ya habiendo construida está clase podemos escribir el código del evento postbuild del componente:

Importamos las clases propias del AWE que necesitamos

import EOAW_CORE:LaunchManager;
import EOAW_CORE:ApprovalManager;


Importamos la clase que acabamos de crear para habilitar los botones según el estado del proceso y el usuario que esté ingresando al registro:


import PE_WF_EJEMPLO:PE_UTILIDADES;


Declaramos las variables de componente que se utilizan durante todo el proceso de Workflow:

Component EOAW_CORE:LaunchManager &obj_launch;
Component EOAW_CORE:ApprovalManager &obj_approval;


Creamos la variable para almacenar el nombre del proceso que vamos a ejecutar. Este es el nombre con el cual se va a identificar el proceso y el que se debe parametrizar en las páginas de parametrización d workflow. 

Local string &str_process = "EQUIPOS";


Creamos la variable record para el cual se ejecutará el workflow.

Local Record &rec_equipos = GetRecord(Record.PE_EQUIPOS);



Inicializamos las variables de componente que se utilizan durante todo el proceso de Workflow, los parámetros identifican el proceso de workflow que se va a ejecutar para el registro y con que usuario se está ejecutando ese proceso. 

&obj_launch = create EOAW_CORE:LaunchManager(&str_process, &rec_equipos, %OperatorId);
&obj_approval = create EOAW_CORE:ApprovalManager(&str_process, &rec_equipos, %OperatorId);



Actualizamos el estado de los botones de aprobación, rechazo y envío. 

Local PE_WF_EJEMPLO:PE_UTILIDADES &obj_utilidades = create PE_WF_EJEMPLO:PE_UTILIDADES();;
&obj_utilidades.pe_ActualizarWF(GetLevel0(), &obj_launch, &obj_approval);

El siguiente paso es escribir el código que ejecutará cada uno de los botones. El código que se colocará directamente en los bonotes solo activará una bandera y salvará el componente,  esto con el fin de ejecutar el código principal en el evento SavePostChange del componente.

Botón Aprobar:

PE_EQUIPOS_WRK.PE_APROBAR_BTN.Value = "Y";

&XSTATUS = PE_EQUIPOS.PE_ESTADO_EQUIPO;
PE_EQUIPOS.PE_ESTADO_EQUIPO = "";
PE_EQUIPOS.PE_ESTADO_EQUIPO = &XSTATUS;
DoSaveNow();

Botón Rechazar:

PE_EQUIPOS_WRK.PE_APROBAR_BTN.Value = "Y";

&XSTATUS = PE_EQUIPOS.PE_ESTADO_EQUIPO;
PE_EQUIPOS.PE_ESTADO_EQUIPO = "";
PE_EQUIPOS.PE_ESTADO_EQUIPO = &XSTATUS;
DoSaveNow();


Botón Enviar:

PE_EQUIPOS_WRK.PE_ENVIAR_BTN.Value = "Y";

&XSTATUS = PE_EQUIPOS.PE_ESTADO_EQUIPO;
PE_EQUIPOS.PE_ESTADO_EQUIPO = "";
PE_EQUIPOS.PE_ESTADO_EQUIPO = &XSTATUS;
DoSaveNow();

Ahora si vamos a revisar el código que debemos colocar en el evento SavePostChange del Componente:


Importamos las clases propias del AWE que necesitamos


import EOAW_CORE:LaunchManager;
import EOAW_CORE:ApprovalManager;

Importamos la clase que acabamos de crear para habilitar los botones según el estado del proceso y el usuario que esté ingresando al registro:


import PE_WF_EJEMPLO:PE_UTILIDADES;


Declaramos las variables de componente que se utilizan durante todo el proceso de Workflow:

Component EOAW_CORE:LaunchManager &obj_launch;
Component EOAW_CORE:ApprovalManager &obj_approval;

Local PE_WF_EJEMPLO:PE_UTILIDADES &obj_utilidades = create PE_WF_EJEMPLO:PE_UTILIDADES();;



Creamos la variable record para el cual se ejecutará el workflow.


Local Record &rec_equipos = GetRecord(Record.PE_EQUIPOS);



Creamos la variable record donde se encuentran los campos referentes a los botones:


Local Record &rec_wrk = GetRecord(Record.PE_EQUIPOS_WRK);


Validamos si se oprimió el botón enviar y si es así inicializa el proceso de workflow utilizando el método  DoSubmit. Siempre que se inicie o se reinicie un proceso de workflow la variable EOAW_CORE:ApprobalManger debe ser reiniciada. La propiedad hasAppInst indica si el proceso fue iniciado correctamente. 

If &rec_wrk.PE_ENVIAR_BTN.Value = "Y" Then
   &obj_launch.DoSubmit();
   If &obj_launch.hasAppInst Then
      &obj_approval = create EOAW_CORE:ApprovalManager(&obj_launch.txn.awprcs_id, &rec_equipos, %OperatorId);
   End-If;
Else

Validamos si se oprimió el botón aprobar y si es así se llama el método DoApprove para realizar la aprobación del registro. Si el usuario que está aprobando no es el aprobador final y existen  otros usuario que deben aprobar antes de que el registro quede en estado aprobado, el métdo DoApprove dejará el estado en pendiente y remitirá la transacción al siguiente aprobador

   If &rec_wrk.PE_APROBAR_BTN.Value = "Y" Then
      &obj_approval.DoApprove(&rec_equipos);
   Else

Validamos si se oprimió el botón rechazar y si es así se llama el método DoDeny para realizar el rechazo del registro.

      If &rec_wrk.PE_RECHAZAR_BTN.Value = "Y" Then
         &obj_approval.DoDeny(&rec_equipos);
      Else


Si el proceso de workflow ya se ha iniciado pero alguien le hizo alguna modificación al registro, es necesario volver a iniciar el proceso de aprobación, para eso se utiliza el método DoResubmit el cual resetea el proceso y lo inicia nuevamente. 



         If &obj_approval.hasAppInst And
               &obj_launch.resubmitEnabled Then
            &obj_launch.DoResubmit();
         End-If;


      End-If;
   End-If;
End-If;

Por último actualizamos el estado de los botones de workflow:

&obj_utilidades.pe_ActualizarWF(GetLevel0(), &obj_launch, &obj_approval);
&rec_wrk.PE_ENVIAR_BTN.Value = "N";
&rec_wrk.PE_APROBAR_BTN.Value = "N";
&rec_wrk.PE_RECHAZAR_BTN.Value = "N";

Con lo anterior finalizamos los pasos técnicos que son necesarios para habilitar el workflow dentro de un componente especifico,  el siguiente paso es parametrizar el proceso dentro del aplicativo. 


Las parametrizaciones del AWE se realiza por el menú Inicio > Componentes de Empresa > Aprobaciones > Aprobaciones.  En esta ruta encontramos todas las opciones que nos permiten parametrizar el workflow.  


1. Primero se debe registrar la trasacción,  por la opción de Registro de Transacciones. El id de proceso que debemos registrar para nuestro ejemplo es EQUIPOS,  el cual es el que hemos estado utilizando dentro del PeopleCode. 


Lo principal que se debe parametrizar en este punto son:



  • El registro de referencia (El registro que creamos utilizando el subrecord EOAW_XREF_SBR).
  • La opción de Activar notificaciones, donde definimos si queremos informar a los interesados en el workflow (Solicitantes, aprobadores, etc.) por correo electrónico,  por lista de trabajo o por ambos. 
  • El menú y el componente donde se realizan las aprobaciones.  Hacia este menú y componente redireccionará el motor de workflow a los interesados (Aprobadores) para continuar con el proceso. 
  • Clase de Gestión de Aprobación,  acá seleccionamos la clase que administrará el estado de los registros que se encuentren en proceso de aprobación.  En nuestro caso será PE_APPROVAL_HANDLER
  • En Niveles de Aprobación seleccionamos el registro al que le vamos a realizar el proceso de aprobación. 
A continuación podemos visualizar como quedaría la definición del proceso EQUIPOS:



2. La segunda configuración que se debe hacer es la que se refiere a las notificaciones que se deben enviar cada vez que ocurra un evento dentro del proceso de workflow.  Para esto se debe definir:



  • La vista de usuarios que se va a utilizar (Usuarios Aprob): a menos que suceda algo extraordinario o que se necesite información adicional de los usuarios la vista que siempre se debe usar es PSOPRDEFN_VW
  • El evento para el cual se realizará la notificación: Básicamente se deben parametrizar 3 eventos: En Aprobación Final, En Rechazo Final y Ruta para Aprobación.
  • Luego se define el menú, componente y página al cual se debe dirigir el notificado para realizar el proceso de workflow (Aprobar, Rechazar o Revisar según el caso)
  • Por último se define el perfíl al cual se debe notificar: En el caso de Rechazo y Aprobación Final se debe informar al solicitante para que este revise por que se rechazo o por que se aprobó. En caso de Runta para Aprobación se le debe informar al usuario que debe aprobar o rechazar la transacción o sea a los aprobadores. 
A continuación se pueden visualizar las parametrizaciones que se realizaron para los 3 eventos dentro de nuestro ejemplo. 








3. El siguiente paso es definir las listas de usuarios que realizarán aprobaciones dentro del workflow. Estás listas se pueden definir con base en un App Package, un Objeto SQL, un Rol   o una consulta realizada por el gestor de consultas.  Las listas de usuarios se definen por la opción Definición Lista Usuarios.  

Para nuestro ejemplo definiremos 3 listas de usuarios, cada una apuntando a un rol diferente. Utilizaremos 3 listas de usuarios por que tendremos 3 niveles de aprobación, o sea que un registro debe ser aprobado por 3 usuarios antes de cambiar de estado a Aprobado. 

A continuación podemos ver la primer lista de usuarios que se parametrizó (En entradas posteriores revisaremos los diferentes tipos de listas de usuario, y la forma de usar el control ruta para las listas de usuarios definidas como roles.):






4. El último paso a la hora de definir un workflow es definir el proceso de aprobación. Cada proceso consta de:

  • Fases: Todas las fases se deben ejecutar dentro de un proceso y  son secuenciales una detrás de otra. 
  • Las fases están compuestas por Rutas:  dentro de una fase las diferentes rutas son paralelas. A diferencia de las fases las rutas no necesariamente deben ser ejecutadas. Para que una ruta sea ejecutada debe cumplir los criterios definidos sino será ignorada. 
  • Por último las rutas están compuestos por pasos que deben ser ejecutados de forma secuencial y que a su vez pueden ser ignorados si no cumplen los criterios definidos para el paso. Dentro del paso se define la lista de usuarios que debe realizar la aprobación del paso. 
Para nuestro ejemplo se debe ingresar en cada uno de los criterios de las rutas, los pasos y el proceso y definirlo como se ve en la siguiente imagen:




La definición del proceso de nuestro ejemplo debe quedar como la siguiente figura:



5. Se me olvidaba, si deseamos poder hacer seguimiento a cada una de nuestras transacciones dentro del proceso de aprobación utilizando la opción Control de Aprobaciones, debemos agregar nuestro Id de Proceso a la opción Configuración del Monitor y debe quedar de la siguiente forma:



Listo ahora solo nos queda probar nuestro workflow, para lo anterior debemos crear los siguientes usuarios:

  • Solicitante: Usuario con permisos sobre el componente de equipos. 
  • Aprobador 1: Usuario con permisos sobre el componente de equipos y adicionalmente con el rol asociado a la lista de usuarios PE_EQUIPOS_UNO
  • Aprobador 2: Usuario con permisos sobre el componente de equipos y adicionalmente con el rol asociado a la lista de usuarios PE_EQUIPOS_DOS
  • Aprobador 3: Usuario con permisos sobre el componente de equipos y adicionalmente con el rol asociado a la lista de usuarios PE_EQUIPOS_TRES. 
1. El primer paso de nuestra prueba es ingresar un registro en el componente de equipos,  para eso ingresamos con el usuario Solicitante y creamos un equpo:




Como podemos ver al usuario solicitante se le habilita el botón enviar. Al dar clic en el botón enviar se iniciará el proceso de aprobación y se le ocultará el botón enviar para el usuario Solicitante.

Si vamos a la opción Inicio > Componentes de Empresa > Aprobaciones > Aprobaciones > Control de aprobaciones y buscamos por el Proceso "EQUIPOS" podemos ver que el equipo se encuentra en estado pendiente. Si ingresamos al registro podremos ver graficamente como va el proceso de aprobación,  incluso los pasos que faltan antes de la aprobación final. 

2. El segundo paso en nuestro ejemplo es ingresar al aplicativo con el usuario Aprobador 1 e ir a revisar nuestra lista de trabajo. Como podemos ver en la imagen tenemos pendiente una aprobación. 




3. Mediante el link que aparece en la lista de trabajo nos dirigimos hacia el componente de equipos al registro pendiente por aprobación. En la imagen se ve que ahora se encuentran habilitados el botón Aprobar y Rechazar.




4. El siguiente paso es aprobar la transacción e ingresar con los usuarios Aprobador 2 y Aprobador 3 y terminar el proceso completo hasta que el estado del registro quede aprobado. 

Con esto hemos terminado nuestra entraba básica sobre el manejo del AWE. En futuras entradas estaremos estudiando características adicionales de está tecnología, como son:

  • Control Ruta
  • Criterios de Selección de Rutas y Pasos
Bueno espero que les sea de utilidad está información y nos vemos en futuras publicaciones. 


miércoles, 14 de septiembre de 2011

Archivos Planos con XML Publisher

En está nueva entrada vamos estudiar la forma de generar archivos planos utilizando XML Publisher y sin necesidad de crear objetos por el app designer ni de escribir código. 

Para poder poner en práctica la información que vamos a generar en está entrada,  es necesario tener conocimientos básicos de XML y del Gestor de Consultas de PEOPLESOFT. 

Las plantillas XML Publisher que nos permiten generar archivos planos son las plantillas eText. Estas plantillas son creadas en MS WORD y son formato RTF igual que las que se usan normalmente para generar los reportes en PDF. 

La diferencia de estás plantillas con las plantillas normales es la estructura que se debe definir.

Para el ejercicio de generación de plantillas eText de esta entrada vamos a utilizar la consulta conectada que creamos en la entrada anterior. 

Al igual que para una plantilla XML Publisher normal, lo primero que tenemos que tener para desarrollar nuestra plantilla es la estructura XML sobre la cual vamos a trabajar. Para nuestro ejemplo la estructura será la siguiente: Estructura XML. Está estructura se descarga desde la consulta conectada. .


Luego de definir la estructura XML definimos que tipo de plantilla vamos a generar.  Generalmente los archivos planos se pueden generar: de longitud fija o delimitados. 


Para definir una plantilla eText de longitud fija utilizamos el siguiente encabezado:



La propiedad <TEMPLATE TYPE> define que queremos un archivo plano de longitud fija o delimitado. Para un archivo plano delimitado la cabecera que se debe utilizar es la siguiente:


Luego de definir las  propiedades generales de la plantilla, se procede a definir los datos que se van a generar dentro del archivo plano. Para lo anterior debemos definir las siguientes propiedades. 

1. Definir el nivel dentro del XML del cual vamos a extraer la información. En nuestro caso el archivo plano debe tener un primer tipo de fila que contenga los datos del rol. Estos datos se deben tomar de la ruta ConnectedQuery/PE_CQ_ROLES. Con este dato definimos la propiedad <LEVEL> (Esto aplica tanto para los archivos delimitado como para los de longitud fija.)

Luego de definir el nivel se definen las propiedades de cada uno de los datos que se incluirán en el archivo y dentro del nivel que estamos configurando. Para un archivo de longitud fija se deben definir las siguientes propiedades:

<POSITION>Indica a partir de que posición se empezará a escribir el dato dentro de la fila que se está generando
<LENGTH>Indica la longitud que va a tener el campo dentro de la fila que se está generando
<FORMAT>Define el formato del campo. Las opciones son NUMBER, ALPHA y DATE
<PAD>Indica el carácter con el cual se debe rellenar el campo para completar la longitud total del campo.  Por ejemplo si queremos rellenar el campo con espacios a la derecha está propiedad debe ser R, ' ', si deseamos llenar el campo con ceros a la izquierda el valor debe ser L, '0'
<DATA>Indica el elemento xml del cual se extraerá la información. Dentro de este campo se pueden usar funciones como condicionales y funciones XPATH que permitan extraer información de niveles diferentes al que se está trabajando. 
<COMMENTS>Comentarios que no afectarán en nada la generación del archivo. 

En nuestro ejemplo para una plantilla de longitud fija está sección para los roles debe lucir de la siguiente forma:


Dentro de una plantilla delimitada la propiedades a definir para cada uno de los campos que  formaran una fila del archivo plano

<MAXIMUM LENGTH>Máxima longitud que podrá tener el campo
<FORMAT>Define el formato del campo. Las opciones son NUMBER, ALPHA y DATE
<DATA>Indica el elemento xml del cual se extraerá la información. Dentro de este campo se pueden usar funciones como condicionales y funciones XPATH que permitan extraer información de niveles diferentes al que se está trabajando. 
<COMMENTS>Comentarios que no afectarán en nada la generación del archivo. 


En nuestro ejemplo está sección para los roles debe lucir de la siguiente forma:


Longitud Fija







Delimitada





Cada vez que inicializamos una sección <LEVEL> debemos terminar esa sección con un <END LEVEL> en nuestro caso no hemos puesto aún el <END LEVEL> debido a que los roles tienen dos secciones hijas: Usuarios y Listas de Permiso,  entonces para lograr este comportamiento lo que hacemos es anidar otras secciones <LEVEL> antes de cerrar la que pertenece a los roles. 


Para anidar el <LEVEL> que nos mostrará los usuarios, debemos agregar una sección igual a la anterior pero en el campo <LEVEL> asociamos el nodo XML que pertenece a los usuarios,  y adicionalmente agregamos en <END LEVEL> ya que los usuarios no tienen ningún otro nivel anidado. La sección de usuarios quedaría de la siguiente forma: 


Longitud Fija






Delimitada






De la misma forma la sección para las listas de permisos quedaría asi:


Longitud







Delimitada





Listo, por último agregamos el <END LEVEL> de nuestra sección de roles y con esto finalizamos nuestra plantilla;




Longitud Fija







Delimitada




Las plantillas completas las podemos descargar de los siguientes enlaces: Longitud FijaDelimitada


2. El siguiente paso es crear la definición del informe. Podemos utilizar el mismo origen de datos que utilizamos en la entrada anterior. El tipo de plantilla que debemos seleccionar es eTexto. 


3. Por último podemos ejecutar nuestro reporte por la ruta Inicio > Herramientas de Informes > XML Publisher > Gestor de Informes de Consulta.  Al ejecutarlo debemos seleccionar en formato "Texto" para que genere nuestro archivo plano.  Este proceso tiene un bug al momento de ejecutar un reporte que genera un archivo plano mediante una plantilla eText.  

Para corregir este bug se debe reemplazar el siguiente código que se encuentra en en app engine PSXPQRYRPT en la sección MAIN en el paso ExecRpt:



&oRptDefn.ProcessReport(&TemplateId, &LanguageCd, &AsOfDate, &oRptDefn.GetOutDestFormatString(&OutDestFormat));

Por el siguiente: 

      /*INICIO CHGA #001 */
      If &oRptDefn.TemplateType = "ETX" Then
         REM         Local File &fileCSV;
         REM         &fileCSV = GetFile(&ReportName | String(&ProcessInstance) | ".txt", "w", "UTF-8", %FilePath_Relative);
         REM         &fileCSV.WriteString(&oRptDefn.ProcessETextReport(&TemplateId, %Language_User, %Date));
         &oRptDefn.ProcessReport(&TemplateId, &LanguageCd, &AsOfDate, "TXT");
      Else
         
         /*FIN CHGA #001 */
         &oRptDefn.ProcessReport(&TemplateId, &LanguageCd, &AsOfDate, &oRptDefn.GetOutDestFormatString(&OutDestFormat));
      End-If;


Y listo con esto hemos creado un archivo plano utilizando las herramientas que el XML Publisher nos suministra, sin necesidad de escribir código (Bueno casi. ). 

Espero que esta entrada les sea de utilidad y nos vemos en la siguiente.