Saltar a contenido

Manual del Programador

Introducción

En cada sección se encontrará la explicación del segmento de código que se está estudiando.

La sección se divide de la siguiente forma:

Nombre del programa El nombre del programa que se va a detallar.

Objetivo Descripción genérica de lo que pretende lograr este segmento de código.

Tablas El nombre de las tablas y la base de datos que se van a acceder. Así como una breve explicación de el uso que se le va a dar a esta tabla.

Variables Las variables más importantes que se van a manipular durante la ejecución. La columna referencia nos indica si la variable es de entrada (proviene de una página Web u otro programa como parámetro). O si es global para el código que se ejecuta.

Secuencia La secuencia lógica de pasos que se sigue durante la ejecución del programa.

Alguna convenciones de programación

Todas las variables que inicien con $rs son variables de acceso a bases de datos y contienen recordsets con el resultado de un query.

Las variables de entrada provenientes de una página web se almacenan en el hash %in, y se accede al valor de la siguiente forma: $in{'nombre de campo'}

Importante

En la instalación original, eFlow respalda únicamente los siguientes directorios: /home/eflow/cron /home/eflowweb/cgi-bin /home/eflowweb/html ruta a librerías de perl/vendor_perl/Eflow

Para que el código que desarrolle y todo lo relacionado al mismo se respalde, debe instalar toda la información en esos directorios. O modificar el programa /home/eflow/cron/back_up.pl ; para adecuarlo a sus necesidades.

De lo contrario no se respaldarán sus desarrollos en el procedimiento de respaldos.

Constantes del sistema

En la versión normal de eFlow se localizan en el archivo user_check.pm

Variable Significado y uso
$EF_ROOT Path al directorio donde se encuentran almacenadas las rutinas de eFlow
$EF_CGI Path al directorio cgi-bin donde se localizan todos los programas relacionados con eFlow
$EF_WEBCGI Directorio cgi-bin para construcción de URLs
$EF_SERVER Ip o dominio del servidor Web que contiene el programa de eFlow
$EF_WEB Path al directorio del servidor donde se encuentran almacenadas las páginas y archivos de eFlow.
$EF_WEBS Path al directorio del servidor donde se encuentran almacenadas las páginas y archivos de eFlow en la sección de servidor seguro
$EF_EMAIL Dirección de correo electrónico que se utiliza en el from que envía el sistema
$AUTOMATIC 0 Corriendo desde Web, 1 Corriendo con cron : automatic.pl

Variables comunes en todas las rutinas

Variable Significado y uso
%in Variable donde se almacenan los datos de entrada de un formulario web
$in{'process'} Número de procesos que se está ejecutando
$in{'station'} Estación que se está procesando
$in{'folio'} Folio electrónico que se está procesando
$in{'opt_station'} Estación destino
$user_name Nombre del usuario que ejecuta la rutina
$Sdate Fecha del sistema (AAAA-MM-DD)
$Stime Hora del sistema (HH:MM:SS)
$Stimestamp Fecha y hora del sistema
$Smon Mes del sistema (1 al 12)
$Smonth Mes del sistema (Enero -- Febrero)
$Syear Año del sistema
$Sday Día del sistema (1 Lunes - 7 Domingo)

Variables importantes dentro de las rutinas de update

Variable Significado y uso
$in{'process'} Número de procesos que se está ejecutando
$in{'station'} Estación que se está procesando
$in{'folio'} Folio electrónico que se está procesando
$in{'folio_label'} Etiqueta del folio que se está tramitando
$in{'opt_station'} Estación destino
$ef_user Vacío se ignora. Si valor > 0 se fuerza asigna el folio al número de usuario
@a_ef_user $a_ef_user[#etapa] igual a ef_user, pero aplica para etapas paralelas
$in{'ff##'} Valores de la página web que corresponden a campos del folio relacionado al proceso que se está ejecutando.
$EF_USER Número de plaza ocupara por el usuario
$ef_account Cuenta del usuario que está conectado
$ef_ip Ip desde la que se registró el usuario
$ruser Número del usuario
$user Depreciado, no se debe usar, número de puesto (usar $EF_USER)
$BB 1 = Conexión desde dispositivo móvil
$EXT Extensión preferida para imágenes (png, gif)
$EF Número de sitio al que se ha conectado
$user_permissions Permisos activos en del usuario según los grupos a los que pertenecía al momento de registrarse.
$lib Objeto Lib con varias funcionalidades descritas en Lib.pm

Variables de ambiente (%ENV)

Variable Significado y uso
$ENV{'REMOTE_ADDR'} Ip de la computadora que accede a este servidor
$ENV{'HTTP_HOST'} Dominio de la máquina
$ENV{'DOCUMENT_ROOT'} Path al directorio donde se encuentran ubicadas las páginas web

Diagrama de flujo del motor de eFlow

Como programar sin entrar en conflictos con el sistema de actualizaciones automáticas

Establecer las reglas básicas de programación para que el programador responsable de crear flujos en eFlow, no tenga conflictos con el motor y los componentes de eFlow y el sistema de actualizaciones automáticas.

  1. Utilice en todas sus subrutinas y funciones variables locales, no cree variables globales nuevas. Esto es siempre declare sus variables dentro de la subrutina que está desarrollando anteponiendo la palabra clave my, que le indica al compilador que la variable tiene alcance local.
  2. Si es absolutamente necesario crear una variable global, para utilizarla en tiempos diferentes de la ejecución del proceso, siempre anteponga el prefijo __mi___ al nombre de sus variables, para que no exista la posibilidad de que se alteren variables del sistema, por haber tomado un nombre que ya utiliza eFlow. (Ejemplo : $mi_id)
  3. No altere las variables globales de eFlow, a menos que entienda el impacto que va a tener en la ejecución del código. Más adelante se explica el uso de variables globales que puede alterar con sus propias subrutinas, y el impacto que van a tener el momento de que se ejecute el motor de eFlow.
  4. En algunos códigos de eFlow, existe un "comentario etiqueta" que separa las rutinas de eFlow del código utilizado para crear los documentos HTML que se presentan al usuario final, esta etiqueta es # USER_DEFINED. Debajo de esta etiqueta usted puede alterar el código y las etiquetas HTML para modificar virtualmente todo el diseño gráfico de la aplicación, así como crear nuevas ligas o funcionalidades que pueda necesitar. Mientras usted altere el código en esta sección, cualquier actualización que se envíe no modificará el código que usted haya desarrollado. No altere el nombre de esta etiqueta.
  5. Si crea modificaciones arriba de la etiqueta de USER_DEFINED, cuando existan actualizaciones se sobrescribirán sus modificaciones y tendrá que volver a escribir su código. Si le es absolutamente necesario realizar cambios por encima de la etiqueta USER_DEFINED, ya que de otra forma no puede resolver su problema, entonces se recomiendan alguna de las dos siguientes opciones :
    1. Si su modificación se requiere para un solo proceso y no se va a utilizar en mas procesos. El primer método preferido es que siempre utilice los post-procesos y páginas personales para que cree el código tan complejo como usted desee. Incluso puede copiar subrutinas que existen actualmente en el motor de eFlow a el código generado en el post-proceso que podrá sustituir código real del motor, simplemente escribiendo el mismo nombre de la subrutina en su motor. El resultado de esto es que las modificaciones solo tendrán impacto en el proceso donde require realmente estos cambios especiales y no en todos los procesos que desarrolle.
    2. Si su modificación es permanente y se va a utilizar en todos los procesos : copie la subrutina que desea alterar debajo de la etiqueta USER_DEFINED y en la copia que se encuentra abajo realice sus cambios. El resultado es que el compilador sobre escribirá el código que ya se encontraba antes por el que usted a sobrecargado debajo de la etiqueta USER_DEFINED. Este debe ser el método menos utilizado ya que ocasiona el problema que al enviar nuevas actualizaciones, esta subrutina no tendrá mejoras introducidas en el motor y en este caso usted tendrá que revisar manualmente los cambios introducidos en el motor y copiarlos y adecuarlos a su copia después de cada actualización.
    3. En cualquiera de los dos casos anteriores puede enviarnos la modificación realizada, indicar las razones por las que ha requerido realizar este cambio, y si la modificación es valiosa para el general de la base de usuarios de eFlow y no impacta en forma importante en el rendimiento de la aplicación, se incorporará al motor estándar de eFlow y de esta forma en la siguiente actualización y puede regresar a tener un motor estándar de eFlow en su empresa.
  6. Existen varios archivos con terminación_def.pl Estos archivos contienen la definición de como se despliegan los elementos de la forma en las etapas station. Puede modificar estos libremente para adecuar las formas si así lo requiere.
  7. Las librerías dentro de la carpeta Eflow, instalados en el directorio de librerías de Perl, contienen el motor de eFlow, procure no mover nada en esos códigos.

Listado de programas que puede alterar, porque no son sujetos de actualizaciones automáticas.

Microflow, procura no mover los archivos que le permiten a un usuario redefinir la imagen del producto y agregar sus funcionalidades. Excepto en raras ocasiones donde se tiene que eliminar un problema de seguridad o una funcionalidad que no opera adecuadamente, se tienen que actualizar estos archivos. De lo contrario no se modifican desde la instalación. Si en algún momento el equipo de desarrollo necesitara mover estos códigos por otras razones fuera de la seguridad (ejemplo: adicionar funcionalidades a eFlow), se liberarían con una nueva versión de eFlow para que no generen problemas con los desarrollos actuales.

La lista de archivos que se encuentran fuera de las actualizaciones normales de eFlow, son:

  • /home/eflow/cron
    • back_up.pl
  • /home/eflowweb/cgi-bin/eflow
    • comments.cgi, display_def.pl, login_def.pl, mmenu.cgi, pstation_def.pl, station.cgi, station_def.cgi, work_window.cgi, top.cgi
  • /home/eflowweb/cgi-bin/eflow/admin
    • back_up.cgi, menu_add_folio.cgi, style.cgi, delete_all_folios.cgi
  • /home/eflowweb/html
    • Se agregan nuevos elementos, como imágenes, etc. No se reemplaza nada existente.

Lista de archivos que no debe mover porque eFlow siempre actualizará. (Salvo exista en el la posibilidad de crear sus propios desarrollos bajo la etiqueta USER_DEFINED

  • .. ruta librerías de perl ../Eflow
    • Ningún archivo en este lugar, excepto por las constantes del sistema para adecuarlos a su instalación.
  • /home/eflow/cron
    • webupdate.pl
  • /home/eflowweb/cgi-bin/eflow
    • login.cgi, locked_station.cgi, start.cgi, eflow_webservice.cgi, email_station.cgi
  • /home/eflowweb/cgi-bin/eflow/admin
    • add_folio.cgi, install.cgi, webupdate.cgi, WUinstall.cgi, padd_folio.cgi
  • /home/eflowweb/cgi-bin/designer
    • No mover ningún archivo, todos son sujetos de modificaciones.
  • /home/eflowweb/cgi-bin/documentta
  • No mover ningún archivo, todos son sujetos de modificaciones.

Todos los otros archivos no mencionados en las dos listas anteriores.

  • Estos se pueden modificar, porque existe una baja probabilidad de que requieran cambios, pero puede ser que en raras ocasiones lo requieran.

Si ha realizado modificaciones a alguno de los archivos y no desea que ninguna actualización lo vuelva a alterar, cambie los permisos del archivo a lectura ejecución si es necesario, o incluso cambio el dueño del archivo para que eFlow no lo pueda actualizar.

Integración con PHP

Integrar soluciones o desarrollos basados en PHP que interactúen con eFlow es muy sencillo.

Primeramente para que sus scripts se ejecuten únicamente cuando el usuario se ha registrado en eFlow, coloque los dentro de un subdirectorio que contenga un archivo .htaccess con el siguiente código.

AuthType None
require valid-user
TKTAuthLoginURL cgi-bin/eflow/start.cgi
TKTAuthIgnoreIP on
TKTAuthTimeout 0
TKTAuthCookieExpires 2d

Seguido se presenta un pequeño script, de ejemplo.

<?php
    require_once('/home/eflowweb/cgi-bin/eflow/lib/user_check.php');
    $uc = new EflowUser();
    $user = $uc->user_check();
?>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="/css/eflow.css">
</head>
<body>
<?php
    echo "<a href='javascript:self.close();'><img src='/images/close.$uc->EXT' border='0' title='Cerrar' align='right'></a>n";
?>
<br>
<br>
<b>Validación de PHP</b><br>
<br>
<table border="0" cellspacing="1">
<?php
    echo "<tr><td class='title'>Usuario</td><td class='folio'>$user ($uc->EF_RUSER)</td></tr>n";
    echo "<tr><td class='title'>Nombre</td><td class='folio'>$uc->user_name</td></tr>n";
    echo "<tr><td class='title'>Cuenta</td><td class='folio'>$uc->ef_account</td></tr>n";
    echo "<tr><td class='title'>IP</td><td class='folio'>$uc->ef_ip</td></tr>n";
    echo "<tr><td class='title'>Imágenes</td><td class='folio'>.$uc->EXT</td></tr>n";
    echo "<tr><td class='title'>Empresa</td><td class='folio'>$uc->EF</td></tr>n";
    echo "<tr><td colspan='2' class='folio'>PHP funcionando y validaciones de seguridad correctas</td></tr>";
?>
</table>
</body>
</html>

eFlow ya tiene un directorio php creado y con el archivo .htaccess para que pueda desarrollar dentro de el las aplicaciones que desee.

Los ejemplos de desarrollo que se localizan al final del manual están desarrollados en Perl, pero con muy poco esfuerzo se pueden escribir en PHP y lograr exactamente los mismos resultados.

login.cgi

Objetivo

Registrar a usuario como loggeado para que pueda interactuar con el sistema.

Tablas

Nombre Tipo BD Descripción
users Tabla WorkFlow Tabla que contiene los datos del puesto.
rusers Tabla WorkFlow Tabla que contiene los datos del usuario
general Tabla WorkFlow En el campo menú se indica la ruta completa al programa que despliega el menú.

Variables

Nombre Tipo Referencia Descripción
$in{'user'} String Web Variable proviene de la página de log in y contiene la cuenta del usuario
$in{'passwd'} String Web Variable proviene de la página log in y contiene el password del usuario

Secuencia:

  1. Carga librerías
    1. Eflow::user_check para leer la forma y acceso a base de datos
    2. Net::Netmask para manipulación de direcciones IP y rangos.
  2. Leer datos de la forma y los almacena en %in
  3. Se conecta a base de datos y lee el usuario que tenga la cuenta $in{'user'}
  4. Valida que la cuenta exista (si no sale)
  5. Valida que el password para la cuenta es correcto (si no sale)
  6. Valida que el usuario esté activo en el sistema. (si no sale)
  7. Valida que la IP, desde donde se desea conectar el usuario, esté en los rangos autorizados. (si no sale)
  8. Si el usuario ya está loggeado verifica: que tenga autorizado abrir más sesiones y que no se haya excedido del número permitido de sesiones abiertas. Si es así abre una sesión más, de lo contrario sale.
  9. Copia nombre del usuario a users password.
  10. Si todo es correcto, crea un string encriptado para grabar datos de sección y graba cookies en el navegador para identificar al usuario.
  11. Presenta menú para este usuario. Puede ser uno definido en general (donde se debe escribir el nombre del menú en el campo menú). Si no existe un menú, se presenta el menú estándar de eFlow.

logout.cgi

Objetivo

Registrar salida del usuario en el sistema.

Si es llamado desde otro programa debe recibir como mínimo el número de usuario que se desea sacar del sistema y un mensaje de error.

Tablas

Nombre Tipo BD Descripción
users Tabla WorkFlow Tabla que contiene los datos del puesto.

Variables

Nombre Tipo BD Descripción
$user Entero Global Número de usuario que se accede al sistema

Secuencia:

  1. Carga librerías
    1. Eflow::user_check para poder leer formas
  2. Se ejecuta user_check para leer el usuario que accede al sistema.
  3. Leer datos de la forma o los parámetros de entrada si se le llamó desde otro programa.
  4. Borra usuario del navegador para que ya no se pueda usar nuevamente sin loggearse
  5. Valida que la cuenta exista y esté loggeada (si no sale con error)
  6. Descuenta 1 sesión de sesiones abiertas, quita registro de ip.
  7. Elimina cookies del navegador.
  8. Despliega menú de login. La página web verifica que esté en la ventana principal, de no ser así (está en un frame), y vuelve a presentar menú de login. El menú de log in se imprime solo si el usuario tiene JavaScript habilitado.

display.cgi

Objetivo

Busca los folios que le corresponden al usuario que realiza la consulta y le despliega los folios que tiene asignados.

Tablas

Nombre Tipo Referencia Descripción
station_folio Tabla WorkFlow Tabla donde se encuentran los folios y en que estación están asignados cada uno.
folio Tabla WorkFlow Obtiene los datos generales del folio. Se leen valores como fecha de creación, comentarios, número de folio y su estatus.
station Tabla WorkFlow Se obtienen datos de display_extras para que se impriman los datos que desea el usuario que aparezcan en la tabla de folios pendientes en la esta estación que se está procesando.

Variables

Nombre Tipo Referencia
$in{'view_process'} Web Indica que proceso se está viendo (0 = todos)
$in{'view_station'} Web Indica que estación se está viendo (0 = todas)
$user Web Indica que usuario está accediendo al sistema
$in{'supervise'} Web Si se deben de desplegar folios bajo supervisión
$in{'order'} Web Orden de sort de los datos
$in{'max'} Web Máximo número de folios a desplegar por estación
%tv Global Almacena las consultas externas a bases de datos para minimizar conexiones.

Secuencia:

  1. Leer datos de la forma o de parámetros si se llamó desde otro programa.
  2. Ejecuta user_check y recibe # de usuario si el usuario es válido.
  3. Leer de generales si se deben descontar días festivos en el despliegue de días pendientes.
  4. Verificar si se deben desplegar todos los procesos o uno definido.
  5. Se crea el recordset con todos los números de procesos que vamos a desplegar.
  6. Se entra a loop while para desplegar todos los procesos seleccionados.
  7. Se accede a la tabla station y se obtienen los números de estación y sus nombres y se cargan en un arreglo para rápido acceso al dato.
  8. Se accede a tabla folio_station, y se obtienen los folios que tiene asignados este usuario para el proceso que se está desplegando.
  9. Desplegar cabezal de página: subrutina header
  10. Se entra a loop para desplegar folios encontrados

    1. Si se cambió de estación se despliegan los títulos de la estación (subrutina title ejecuta el despliegue de los títulos)
    2. Se verifica que no hayamos excedido el máximo de folios a presentar por estación. Si se excede, salir del loop y ver siguiente proceso.
    3. Imprimir valores del folio en página web con subrutina print_values.
    4. Incrementar folios desplegados.
    5. Loop a
  11. Loop 8

  12. Imprimir final de página: subrutina footer

Sub header: Despliega encabezado de página HTML

Sub footer: Despliega final de página HTML

sub title

  1. Despliega los títulos de valores fijos: Fecha de creación de folio, fecha de entrada a estación, número de usuario que tiene asignado el folio, número de días, número de folio.
  2. Verifica si existen datos adicionales que desplegar.
  3. Entra a loop para desplegar datos adicionales en tabla
    1. Extrae de display_extras los títulos de los campos a desplegar
    2. Imprime el título
    3. Loop a
  4. Despliega título de último comentario.

sub print_values

  1. Se calculan los días calendario que tiene de vida el folio desde la asignación y su creación.
  2. Si se deben presentar días laborales, se descuentan los días festivos del total de días.
  3. Obtiene comentarios del folio y extrae el último de ellos.
  4. Si el folio está vencido en esta estación selecciona el rojo para marcar la celda.
  5. Despliega los valores fijos de: Fecha de creación de folio, fecha de entrada a estación, número de usuario que tiene asignado el folio, número de días, número de folio.
  6. Verifica si existen valores extras que desplegar.
  7. Entra a Loop para desplegar valores extra
    1. Obtiene la lista de valores
    2. Verifica de donde obtener el valor: de un Folio, o de una base de datos local, o de una base de datos externa.
    3. Obtiene el valor de la fuente correcta.
    4. Si el valor proviene de un FOLIO, se obtiene el valor real de este campo, llamada a true_value
    5. Despliega el dato
    6. Loop b.
  8. Despliega el último comentario.

sub true_value

  1. Se realiza query para determinar el tipo de campo del que se desea obtener el valor.
  2. Si el tipo de datos es mayor a 7, regresar con el campo vacío, este dato no se puede desplegar.
  3. Verificar si el valor real de este campo es un valor fijo o se obtiene de una base de datos externa.
  4. Si es de una base externa se entra a THEN
    1. Se verifica primeramente si ya se obtuvo con anterioridad este arreglo de valores. Verificar variable %tv
    2. Si ya se había procesado antes, se obtienen los valores sin consultar a la base externa nuevamente.
    3. Si entra a loop para obtener todos los valores posibles de la tabla externa.
    4. Se meten los datos en $opt_str, para que se vean como valores fijos para la siguiente parte del código.
    5. Se sale del loop y se salva la consulta en variable %tv
  5. Se extraen todos los valores de $opt_str.
  6. Se barre el arreglo de valores y se regresa el valor correcto.
  7. Si no se encontró un valor real se regresa el valor originalmente enviado.

comments.cgi

Objetivo

Y despliega los comentarios en una ventana nueva que se auto cierra.

Tabla

Nombre Tipo DB Descripción
folio Tabla WorkFlow Se lee el campo comments para extraer todos los comentarios

Variables

Nombre Tipo Subtipo Descripción
$in{'folio'} Entero Web Número de folio que se va a consultar
$in{'process'} Entero Web Proceso al que pertenece el folio que se va a consultar

Secuencia:

  1. Se realiza la conexión con la tabla folio del proceso $in{'process'}
  2. Se formatea el campo de comentarios para desplegarlo en una ventana nueva. El formateo consiste en reemplazar |D por Fecha: |N por Usuario: |C por Comentario: |E por
    n

Formato del campo comments:

|Dfecha alta|Nusuario|Ccomentario|E

station.cgi

Objetivo

Desplegar la estación de trabajo al usuario que accede a la estación.

Tablas

Nombre Tipo DB Descripción
station Tabla WorkFlow Tabla que contiene la información necesaria para desplegar los datos requeridos para esta estación.
Process Tabla WorkFlow Tabla de procesos
Folio_station Tabla WorkFlow Tabla de folios por estación

Variables

Nombre Tipo Subtipo Descripción
$in{'process'} Web Número de proceso
$in{'station'} Web Estación que se debe desplegar del proceso en cuestión
$in{'folio'} Web Folio que se va a desplegar
@Areq Global Arreglo que indica cuales son los formatos que pueden ser requeridos por el usuario y cuales no, aun cuando los haya marcado el usuario en el diseñador.
$p_name Global Nombre del proceso
$user_int Global Valor entero almacenado en el folio como dato del usuario
$user_char Global Valor caracter que tiene almacenado el folio como dato del usuario
$obj_id Global Número de folio electrónico asociado a este proceso
$folio_label Global Formato de despliegue del número de folio
$comments Global Contiene el último comentario del folio

Secuencia

  1. Ejecuta user_check para obtener # de usuario y valida que pueda ver estación.
  2. Verificar que el folio no ha sido movido por otro usuario, si es así regresa a desplegar display.
  3. Obtener valores globales.
  4. Verifica si la estación tiene una página de presentación personalizada, si es así valida que se tenga acceso a la rutina externa ejecutando get_path. Si página termina con .htm, se carga la página se despliega y se sale, si termina con .pl carga la librería y se llama al bloque main_page(), de lo contrario se ejecuta el programa y se sale de station.
  5. Si hay un preproceso, se valida si termina con .pl y se ejecuta main. Si tiene otra terminación se ejecuta el código externo, entregando el control o no dependiendo del caso.
  6. Se despliega el encabezado de la página HTML. Subrutina print_header
  7. Se ejecuta opt_destiny, para imprimir los destinos.
  8. Si existe una página personalizada y tiene como terminación .pl se ejecuta main_page2.
  9. Si existe un número de folio asociado a esta estación se despliega el folio electrónico al usuario utilizando la subrutina obj_folio
  10. Si existe página personalizada con terminación .pl se ejecuta main_page3
  11. Se imprime el final de la página HTML.

Subrutinas

sub print_header: Imprime el cabezal de la página HTML

sub html_footer: Imprime el final de la página HTML

sub get_path

Recibe como parámetro el nombre del archivo a verificar.

  1. Validar si se encuentra en el directorio de root de eFlow
  2. Si no es así, verificar se el nombre de archivo ya tiene la ruta correcta.
  3. Si no es así verificar si se puede localizar por medio de las direcciones almacenadas en Path.
  4. Si no se localiza el archivo imprimir un error.
  5. Si existe regresar la dirección completa.

sub opt_destiny

Configura la página web para que regrese posteriormente el destino correcto a update.cgi

Los campos importantes de la forma de la estación son:

opt_station: contiene el número de estación destino

ef_selection: Contiene 0 mientras no se haya seleccionado ninguna opción de destino

Si la opción es no desplegar las estaciones se imprimen valores hidden.

opt_station = "."

ef_selection="1"

En cualquier otro caso se inicializa ef_selection=0 y se verifica el tipo de formato para desplegar los destinos.

Formato de combo select: Se despliegan los destinos en un combo select

Formato de botones radio: Se despliega cada destino asociado a un botón radio.

En ambos casos si está activada la opción de presentar la opción Actualizar comentarios se imprime como primer opción de el combo o botones radio la opción "Actualizar comentarios"

sub obj_folio

  1. Se obtienen todos los campos del folio que deben de ser desplegables en esta estación. Tanto para ver como para editar.
  2. Se obtienen los valores del folio y el nombre del folio.
  3. Se barre el recordset para desplegar todos los campos que se pueden ver o editar en esta estación.
  4. Entramos al Loop
    1. Se obtienen los datos de formato del campo en cuestión.
    2. Si existe página personal con terminación .pl se ejecuta main_value.
      1. Si el valor devuelto es <> 0 se considera que el campo se ha procesado
      2. Se avanza al siguiente registro.
      3. Se omite la impresión del campo.
    3. Se llama a la subrutina common. Para que obtenga todos los valores comunes a todos los campos de un folio. Como son si es o no requerido, y obtiene los datos externos de un campo en caso de que el formato requiera acceso a una tabla externa.
    4. Se llama a la subrutina que conoce como desplegar el campo de acuerdo a su formato. La llamada se logra concatenando el valor "F" con el número de formato que van del 0 al 10. Por lo tanto para cada formato existe una subrutina Fn que despliega el valor del campo en la página web.
    5. Se avanza al siguiente registro del recordset.
    6. Loop a a.

Resumen de formatos:

Función Descripción
F0 Despliega los campos con formatos: File Upload, Selección de Usuario, Definido por usuario, Java o Active X, Selección de vencimiento, Firma electrónica.
F1 Despliega campos con formato texto
F2 Despliega el campo con valores posibles en formato combo select
F3 Despliega el campo con valores posibles en formato de botones de radio
F4 Despliega el campo con valores posibles en formato check box
F5 Despliega un campo texto de tipo password
F6
F7
F8
F9
F10 Despliega un campo textarea para ingresar texto en múltiples líneas.

Resumen de tipos de campo

Valor Tipo
1 Booleano
2 Fecha
3 Entero
4 Numérico
5 Texto
6 Tiempo
7 Attachment
8 Firma Digital
9 Selección de Usuario
10 Tiempo de Alarma
11 Definido por usuario
12 Link
13 Java - ActiveX

Ejemplo Página personal con terminación .pl:

sub main_page {

}

sub main_page2 {
}

sub main_page3 {
    print qq¡
    <script type="text/javascript" src="/lib/milibreria.js"></script>
    <script>
    function myvalidation() {
        if (DF.elemento.checked==false) {
            setWarning("Debe seleccionar el checkbox. !");
            return false;
        }
        return true;
    }
    Id('combo1234').onclick = function() {
        // Hacer algo con mi librería
        llenacombo(Id('combo1234').option[Id('combo1234').selectedIndex()].value);
    };
    </script>
    ¡;
}

sub main_value {
    return 0;
}

1;

El sistema tiene una rutina de JavaScript que realiza validaciones básicas : campos obligatorios, que el usuario haya seleccionado una acción y confirmar la acción seleccionada si el sistema se ha parametrizado para solicitar confirmación.

Validaciones personalizadas con JavaScript

El sistema valida si se ha creado una función "myvalidation()".

Si la función existe, se ejecuta para darle oportunidad a su código de Javascript de realizar cualquier tipo de validación de los elementos del formulario. Si la validación es exitosa su rutina debe regresar "true", de lo contrario debe regresar "false".

Debe adicionalmente presentar un mensaje de error al usuario.

update.cgi

Objetivo

Mover los folios entre estaciones.

Tablas

Nombre Tipo DB Descripción
station Tabla WorkFlow Tabla que contiene la información necesaria para desplegar los datos requeridos para esta estación.
folio_station Tabla WorkFlow Tabla de las estaciones en las que se encuentra un folio

Variables

Nombre Tipo Subtipo Descripción
$in{'process'} Web Número de proceso
$in{'station'} Web Número de estación que se va a actualizar
$in{'folio'} Web Número de folio que se va a mover
$AUTOMATIC Global Si el movimiento proviene de automatic.pl
$obj_id Global Número de folio electrónico asociado a este proceso
$process_name Global
$process_relax Global Aplicar reglas relajadas para este proceso
$in{'opt_station'} Web Destino

Secuencia:

  1. Ejecuta user_check para validar acceso del usuario.
  2. Validar acceso : llamada debe ser post, debe tener un referrer y referrer = server host
  3. Validar que el folio no ha sido movido anteriormente y se tengan permisos de accederlo.
  4. Si la estación tiene firma, se valida y aborta si ni es válida.
  5. Si existe un post proceso 1 : carga y ejecuta main1.
  6. Validar que destinos omitidos se hayan configurado
  7. Se valida que la estación destino no sea fin. Si es fin, se borra folio de folio_station y se inactiva folio cambiando estatus a 0.
  8. Se verifica estación destino para ver si no es un split de procesos paralelos:
    1. Si es split, borrar folios de folio_station relacionados con este movimiento, split de las opciones, separadas por comas y asignar a arreglo options.
    2. Barrer el arreglo options y obtener para cada caso el usuario al que se asignará el folio en la siguiente estación (subrutina select_user). Se inserta en folio_station el folio, estación, proceso al que se asignó el folio. Se repite hasta terminar con todos los datos de options.
    3. Leer station para averiguar si la estación que se está procesando es un join (reunión de varios flujos de proceso en un punto, después de haberlos separado anteriormente con un split)
      1. Si es un join, borrar de folio_station el folio de la estación que se acaba de juntar, eliminar de join_station esta estación, averiguar si ya no quedan estaciones pendientes por reunirse, si no es así entonces se hace display verdadero, si faltan estaciones por unirse se hace display falso.
    4. Se actualiza folio_station para que folio quede con los datos correctos: estación asignada, usuario al que quedó asignado el folio.
  9. Si la estación destino no es nula, se actualizan fecha de entrada de folio a estación.
  10. Se salvan los comentarios por si cambiaron.
  11. Si existe un número de folio electrónico asociado al proceso se salvan los datos que puedan venir en la página web. Si uno de los campos a actualizar está marcado como registrar, se salva en $register
  12. Se registra la transacción en log_update (se registra $register)
  13. Si estación destino no es nulo, se actualizan estadísticas y costos.
  14. Se ejecuta main2 en caso de que exista un post-proceso 1
  15. Se ejecuta main21 si existe un post-proceso2.
  16. Verificar que la nueva estación no sea de tipo obligatoria, si es así, actualizar locked en users para que user_check cache el estatus, y mandar directamente a la estación bloqueada.
  17. Si no fue obligatoria regresar al usuario a la lista de display con el formato de folios que se estaba usando.

Subrutinas importantes:

sub select_user

Si la estación destino es nulo, se regresa el número de usuario actual.

Se valida si debemos de definir el vencimiento del folio. Si ef_alarm no es nulo, se define en la variable $duetimeV el valor de la fecha de vencimiento del folio.

Si $ef_user está definido, el programador definió el usuario, regresar este usuario al proceso de actualización.

Dependiendo del tipo de next_user de la estación destino regresa el usuario al que se debe asignar el folio, los tipos pueden ser:

Valor actualización
< 0 El valor absoluto de next_user, es el número de usuario al que se debe asignar el folio.
0 Se leen usuarios de work_group al que pertenece la estación y se regresa el siguiente en la lista de acuerdo con last_user
1 Se leen usuarios de work_group al que pertenece la estación y se verifica cuales están registrados en el sistema, y se le asigna al siguiente de acuerdo a last_user.
2 Se asigna al usuario que tiene el folio en ese momento asignado
3 Se asigna usuario que viene en la variable de entrada $in{user} (de la forma station)
4 Se asigna al usuario 0 que es el sistema
5 Se asigna al usuario que actualiza en ese momento
6 Se asigna al usuario que dio de alta el folio
7 Se asigna al jefe del usuario que actualiza
8 Se asigna al jefe del usuario que creó el folio
10 GetNextUser del post-proceso1

sub statistics

Calcula tiempo promedio de actualización de la estación (en base a todos los folios que han sido procesados)

Calcula el tiempo máximo, mínimo, el folio que representó el folio máximo, el mínimo.

Actualiza tabla station_history, en intervalo de horas.

sub save_obj_folio

  1. Se obtienen del obj_def todos los campos válidos de este folio electrónico.
  2. Se inicia un Loop con los valores del folio electrónico
    1. Si el valor está definido en la página web se continua la ejecución. De lo contrario, se mueve el apuntador al siguiente recordset.
    2. Se guarda el valor de la página web en el hash %data.
    3. Se valida si el campo tiene formato 7. Si es así debemos de subir el Atachment de este folio al servidor.
    4. Si el formato es de tipo fecha se reordena el campo al formato estándar (aaaa-mm-dd)
    5. Si el formato es de tipo check box, se suman los valores de entrada en caso de que sea numérico o se concatenan en caso de que sea string
  3. Loop a 2
  4. Se actualizan los datos del folio electrónico con los campos que se obtuvieron de la página web.

post-procesos

Los post-procesos, son programas que se puede ejecutar en ciertos puntos del código que realiza las actualizaciones de folios, como se explicó en la sección correspondiente a update.cgi

Para desarrollar un post-proceso

  • El programa debe tener terminación .pl y debe estar escrito en Perl. Las ventajas son: se incorpora al código que se está ejecutando (se carga el código mediante una instrucción require), lo que permite ver todas las variables y rutinas globales de eFlow, permite controlar el flujo del programa (abortar, transferir a otras rutinas, etc).

Vamos a realizar una explicación más detallada de llamadas a librerías de Perl.

El esqueleto básico de un programa llamado desde la opción de post-proceso es:

sub main1 {
    código ..
}

sub main2 {
    código ..
}

sub getNextUser {
    my $rsw->Pg_VB->new();
    $rsw->connectdb("dbname=workflow$EF");
    código ..
    $rsw->execute("select * from users where ??");
    return ($rsw->itemvalue('id'),$rsw->itemvalue('ruser_id'));
}

mas subrutinas con código

1;

Importante

Utilizar variables locales en todas las subrutinas, para

evitar que se sobrescriban o alteren involuntariamente variables globales del sistema. Se recomienda anteponer el prefijo mi_ a todas las rutinas que se incorporen para que no haya problemas de duplicidad de nombres de subrutinas.

El esqueleto básico de un programa llamado desde la opción de post-proceso2 es:

sub main21 {
    código ..
}

mas subrutinas con código

1;

Los usos más frecuentes de main1 son:

  • Validar valores de la forma antes de mover el folio (que sean lógicos, tengan rangos adecuados, etc)
  • Alterar el destino o usuario que recibe un folio, de acuerdo a los datos capturados en la forma.
  • Realizar actualizaciones a otras tablas externas o bases de datos de otros sistemas.

Los usos más frecuentes de main2 son:

  • Notificaciones de correo electrónico una ves que se ha realizado el movimiento del folio.
  • Actualizaciones de otros sistemas externos, una ves que el folio se ha movido correctamente y conocemos el usuario al que se asignó el folio.

Todos los valores que vienen de la forma se encuentran almacenados en la variable hash %in con el formato $in{'ff###'} donde ### es el número que se asignó al campo durante la etapa de diseño del folio.

Ejemplo tradicional de post-proceso:

sub main1 {
    #Validar si se están actualizando comentarios
    if (!$in{'opt_station'}) {return 0;}

    if ($in{'opt_station'} == 3) {
        #Si estación destino es 3 ejecutar los siguiente
        #Se crea un Nuevo objeto de acceso a base de datos
        my $rs = Pg_VB->new();
        #Se realiza conexión a base de datos
        $rs->connectdb("dbname=workflow");
        #Actualiza tabla con SQL
        $rs->execute("update obj1 set ff1='$user_name' where folio=$in{'folio'}");
        #Regresar sin seguir ejecutando más
        return 0;
    }
    if (!$in{'comments'}) {
        #Si la actualización viene sin comentarios enviar mensaje de error
        $lib->("Debe escribir un comentatio, NO SE PUEDE CONTINUAR",'',1);
    }
}

sub main2 {
    #Llamar a rutina local que envía un correo electrónico
    $lib->email_user(2,"Título","Mensaje");
}

sub getNextUser {
    if ($in{'opt_station'} == 1) {
        return 4;
    }
    return 19;
}

1;

Cuando una estación está declarada como Automática o Manual / Automática.Tome en cuenta que los post-procesos se ejecutan aun cuando el programa esté corriendo por un trabajo de cron. En estos casos no se está interactuando con un usuario.

Por lo tanto debe diseñar su proceso para que se adecue a esta condición. Para saber si estamos corriendo desde cron revise $AUTOMATIC (valor de 1, es que corremos en cron)

La segunda cosa importante de entender es que no debe ejecutar la función exit en un post-proceso que corre con cron, porque todo el cron se detiene y esto puede dejar folios sin moverse. Para evitar que el folio se actualice haga $in{'opt_station'} = '';

Cuando nos encontramos ejecutando en modo AUTOMÁTICO, no tenemos información proveniente de la forma de la estación. Si su script requiere de estos valores va a tener que obtenerlos por medio de un query y agregarlos al hash %in. La variable $obj_id, tiene el ID del Documento Electrónico al que debemos conectarnos para obtener los valores.

add_folio.cgi

Objetivo

Realizar el alta de folios. Recibe como dato de principal el numero de proceso a dar de alta.

Bases de Datos

Nombre Tipo Subtipo Descripción
users Tabla WorkFlow Tabla que contiene los datos del usuario y se usa para obtener los datos del usuario necesarios para dar de alta.
Folio Tabla WorkFlow Tabla donde se dará de alta el folio.
folio_station Tabla Workflow Tabla donde se guardaran algunos datos del folio y la estación.
$sdk Global Objeto Objeto a paquete SDK

Secuencia:

  1. Validamos que usuario sea válido.
  2. Se realiza la conexión con la base de datos workflow.
  3. Validar que proceso exista y addnew esté configurado.
  4. Se valida que si el proceso tiene un folio electrónico asociado, la tabla de datos exista.
  5. Verificar si existe librería addnew$in{'process'}.pl
    1. Sí, cargar y llamar rutina before_addnew();
  6. Se llama a $sdk->insert_folio, para que inserte el nuevo documento en el proceso.
  7. Si existe addnew$in{'process'}.pl
    1. Sí, Llamar rutina after_addnew();
  8. Se envía al usuario a la estación n para que el ingrese los datos necesarios para este nuevo folio.

Si crea una librería addnew#.pl en el directorio : /home/eflowweb/cgi-bin/eflow/admin

(# es el número de proceso)

Esta se carga y se ejecuta código personalizado antes y después de crear e insertar el nuevo folio en la tubería del proceso.

## Código ejemplo

addnew.pl

sub before_addnew {
    if ($in{'process'} == 8) {
        Ejecuta este código ...
    }
}

sub after_addnew {
    if ($in{'process'} == 3) {
        Ejecuta este código ...
    }
}

1;

admin/dell_all_folios.cgi

Objetivo

Eliminar los folios existentes y reiniciar a 1 el contador de folios.

Bases de Datos

Nombre Tipo Subtipo Descripción
folio_station Tabla WorkFlow Tabla donde se localizan los folios asignados.
Folio Tabla WorkFlow Tabla donde se dará de alta el folio.
obj# Tabla Workflow Tabla donde están almacenados los valores de cada folio

Secuencia:

  1. Presenta advertencia
  2. Permite seleccionar un grupo de procesos
  3. Muestra los procesos asignados al grupo que tienen menos de 20 folios creados.
  4. Se ejecuta código de eliminación de folios :
    1. Trunca tabla asociada de folios en workflow, obj#
    2. Reiniciar el contador de folios a 0
    3. trunca la tabla folio#
    4. trunca la tabla folio_station#
    5. trunca la tabla station_history#
    6. trunca la tabla log_update#
    7. realiza los mismos pasos del 3 al 6 pero en efhistory para eliminar cualquier historia previa
    8. Ejecuta my_clean_up(), donde el usuario realiza sus propias rutinas de limpieza
    9. Envía mensaje de éxito al terminar.

Como realizar sus propias limpiezas en caso de tener tablas adicionales o enlaces con otros sistemas que se deben reiniciar.

En el paso 8, la rutina de limpieza ejecuta la subrutina my_clen_up(), y se le envían como parámetros el número de proceso que se está limpiando y el número de obj de la base de datos workflow para eliminar cualquier dato adicional.

Ejemplo de como usar :

sub my_clean_up {
    my $process=shift;
    my $objid=shift;
    if ($process == 18) {
        my $rsx = Pg_VB;
        $rsx->connectdb("dbname=usertable");
        $rsx->execute("truncate table det_facturas");
    }
}

$rs : ya tiene establecida una conexión a la base de datos workflow

$rsf : ya tiene establecida una conexión a la base de datos workflow

$rsh : ya tiene establecida una conexión a la base de datos efhistory

Si requiere de conexiones adicionales las debe de crear dentro de la subrutina como variables locales.

Como modificar el diseño gráfico del sistema

Objetivo

Explicar el procedimiento para realizar modificaciones al diseño gráfico del sistema sin perderlas al momento de realizar actualizaciones.

Cascading Style Sheets

La manipulación de cascading style sheets ubicadas en el directorio: /home/eflowweb/html/css

Hay una definición general : eflow.css y otras auxiliares que se usan en ciertos códigos.

Se recomienda entrar como administrador a eFlow y seleccionar uno de los esquemas de colores existentes que le parezca adecuado para modificar.

Una ves seleccionado, entre a la termina, y edite los archivos que se encuentran en :

RUTA_PAGINA_WEB/html/css

Cree un directorio con el nombre de su esquema (sin espacios, acentos o caracteres latinos).

Modifique a su gusto todos los colores de las hojas de estilo. Visualice los cambios en el navegador de Internet recargando las páginas.

Una ves terminado copie todas las hojas de estilo a el directorio que creo.

Edite el archivo :

RUTA_CGI-BIN/eflow/admin/style.cgi

Localice el código donde se encuentra la instrucción SELECT, y agregue una líne OPTION, donde el valor de la etiqueta es el nombre del directorio donde salvó sus hojas de estilo y el valor de desplegar en la aplicación sea el nombre que le quiera dar a este esquema de colores.

Salve el código. Y ahora ya podrá seleccionar este esquema desde la interfase web.

Modificar codificación de Impresión de las páginas.

Los archivos con terminación_def.pl contienen las instrucciones para desplegar los diferentes elementos de la forma. Usted puede modificar estos archivos para que el diseño gráfico de los formularios se adecuen a su gusto.

Puede incluso escribir nuevas rutinas si así lo requiere. Al momento que se envían actualizaciones estos archivos no son reemplazados.

Es posible para cualquier programador modificar las rutinas de impresión, agregar iconos, imágenes, etc. También incluso puede modificar la estructura con la que se imprimen las páginas de forma que se pueda cambiar el lay out de cómo se distribuye la información en la ventana.

Uso de página personalizada en estación "Personal Page"

En estos casos el diseño de la página queda totalmente bajo la responsabilidad del programador. En este caso el diseñador de la página debe de crear todos los campos que sean editables, ocultos u omitidos. Debe de crear la forma de indicar a eFlow los posibles destinos mediante botones como lo hace eFlow o cualquier otro método que deje en la variable opt_station del formulario la estación destino.

Para que se desplieguen los valores que se han procesado en la página el programador debe dejar las siguientes etiquetas para que eflow las reemplace antes de desplegar su página:

%VALUE###% : donde ### representa el número de campo definido en el documento electrónico (ejemplo el campo ff48, tendría la etiqueta en el documento html %VALUE48%)

%LABEL###% : si el campo está compuesto por valores y etiquetas (como suele suceder en el caso de campos select o radio) el diseñador hace que el valor de la etiqueta aparezca en ese lugar en ves del valor de la base de datos.

%OPT###% : Reemplaza la etiqueta por las opciones disponibles de un campo select (ejemplo, si el campo ff34 es un campo select, se reemplaza la etiqueta por ...)

%RADIO###%: Reemplaza la etiqueta por las opciones de un campo con formato de botones de radio (ejemplo: si el campo ff40 es un campo con opciones de radio, se reemplaza por )

"NOTA

eFlow agregará automáticamente los campos ocultos de los valores : process, station, folio, view_process, view_station, supervise y max, antes de la etiqueta , por lo tanto "no incluya estos campos ocultos en su formulario".

user_check.pm

Objetivo

Revisar el estatus actual del usuario. Recibe como parámetro skip_action (1 locked).

Validar el estatus del usuario. Verifica si esta bloqueado en algún otro proceso o estación.

Para saber que usuario es el que llama se utilizan cookies.

Variables, validaciones y Bases de Datos

Nombre Tipo Subtipo Descripción
users Tabla WorkFlow Tabla que contiene los datos del usuario y se usa para obtener los datos del usuario necesarios para dar de alta.

Secuencia:

  1. Se lee cookie para saber quien es el usuario conectado
  2. Se verifica string encriptado para validar que son cookies válidas y no creadas por el usuario.
  3. Se verifica que usuario está realmente registrado y se verifica que su ip sea la misma, desde la cual se registró inicialmente.
  4. Verifica que el campo locked del usuario este vacío, sino el usuario esta bloqueado y despliega la estación que debe terminar.
  5. Regresa el número de usuario que del usuario.

Esta librería también deja algunas variables estándar para todos los procesos como son:

Variable Descripción
$user_name Nombre completo del usuario que se detectó
$Sdate Fecha del sistema al momento de verificar usuario
$Stime Hora de acceso al momento de detectar al usuario
$Stimestamp Fecha y hora de acceso del usuario
$session_id Session que se está conectando (si el usuario tiene varias)
SetSystemTime() Función que actualiza valores de tiempo $Sdate, $Stime, etc.
UserName(n) Función que actualiza el nombre completo del usuario (en la variable $user_name) de acuerdo al número de usuario n que se le envía.
$skip_action Variable que define si se debe usar o no la validación de access_id, esto es útil porque en ocasiones cuando se despliegan muchos frames al mismo tiempo se cambian los access_id en desorden y los frames se despliegan con mensajes de error de loggin.
$Sday Día
$Shour Hora
$Smin Minuto
$Ssec Segundos
$Smon Mes
$Syear Año
$Stime Tiempo en segundos desde 1900
$BB 0, acceso desde PC, 1 acceso desde dispositivo móvil
$ef_account Cuenta del usuario
$user_permisions Entero con la codificación de bits prendidos de acuerdo a los grupos a los que pertenece
$EXT Extensión de imágenes preferida
$ruser Id usuario
$EF_USER Id Puesto

Para validar sus scripts con user_check

Use Eflow::user_check;

$user = user_check(); print PrintHeader();

Pg_VB

Interface de comandos parecida a la de Visual Basic~®~ para acceso a datos de SQL.

Método Parámetros Regresa Uso
new Ninguno Objeto creado para acceder a Postgresql $rs=Pg_VB->new();
connectdb String de conexión
formato:
dbname=nombre base de datos;
port=Puerto;
host= host;
user=usuario;
passwd=password;
Si no se puede conectar se detiene el programa $rs->connectdb("dbname=workflow");
execute Ejecuta un query notas $rs->execute("query");
recordcount Ninguno Registro en el que me encuentro $rs->recordcount;
recordtotal Ninguno Total de registros del último query $rs->recordtototal;
EOF Ninguno Verdadero si me encuentro en el último registro $rs->EOF;
BOF Ninguno Verdadero si me encuentro al inicio de los registros $rs->BOF;
movefirst Ninguno Mueve el inicio de los registros $rs->movefirst
movelast Ninguno Se mueve al último registro $rs->movelast;
move Posición Se mueve a la posición N $rs->move(posición);
moveprevious Ninguno Se a posición anterior $rs->moveprevious;
movenext Ninguno Se mueve siguiente posición $rs->movenext
itemvalue Nombre del campo Valor del campo $rs->itemvalue(nombre_campo);
error_description Ninguno Regresa la descripción del último error $rs->errordescription;
error_number Ninguno 1 Error, 0 No hay error $rs->errornumber;
findfirst Campo de búsqueda Se posiciona en primer registro que cumpla condición $rs->findfirst(campo,regex);
findlast Ir al Último registró que cumpla condición $rs->findlast(campo,regex);
findnext Ninguno Busca siguiente $rs->findnext;
findprevious Ninguno Busca anterior $rs->findprevious;
getHash Ninguno Hash con recordset %hash = $rs->getHash();
getHash_ref Ninguno Referencia al recordset $ref =$rs->getHash
getType Tabla Hash con tipos %hash = $rs->getType;
fType campo Regresa el tipo de un campo específico $tipo = $rs->fType(nombre_campo);
update Nombre de la tabla,hash_datos,where,bandera Error detiene $rs->update("tabla",%hash[,where][,1]);
insert Nombre de la tabla,hash_datos,bandera Error detiene $rs->insert("tabla",%hash*[,1]);
NOMATCH Ninguno Si no se logro localizar find $rs->NOMATCH;

Notas

Insert y retorno último Id insertado

Si el insert se ejecuta por medio del método : execute.

Usar returning en instrucción SQL, y agregar nombre de la columna a la llamada

$id = $rs->execute("insert into tabla (valor) values (2) returning id",'id');

Si el insert se ejecuta por medio del método : insert

Agregar pseudocolumna : RETURN_LAST_ID con el nombre de la columna serial

$data{'RETURN_LAST_ID'} = 'id';
$id = $rs->insert('tabla',\%data,1);

Delete, Update

Regresan el número de registros afectados

$n_eliminados = $rs->execute("delete from tabla where x = 1");
$n_modificados = $rs->execute("update tabla set y=0 where x = 1");
$n_modificados = $rs->update("tabla",\%data,"x=1",1);

use Eflow::Libs

Librería de métodos comunes para eFlow. Disponibles en post-procesos y páginas personales.

Método Parámetros Regresa Uso
new Ninguno Crear objeto $lib=Libs->new();
Alert mensaje[,imágen,printheader] Nada $lib->Alert("Hola","Ok.png",1);
Error mensaje[,imágen,printheader] Nada $lib->Error($DBI::errstr,'',1);
fnumeric Número,decimales Número formateado $numS = $lib->fnuemric(1000,2);
fnumeric_hash %hash,decimal Formatea todo el hash $lib->fnumeric_hash(%h,2)
redirect (url,segundos,mensaje) Nada $lib->redirect('start.cgi',4,"mensaje");
round (numero,decimales) Número redondeado $num = $lib->round($numero,3);
email_user usuario=número usuario o email
subj=Título
mensaje=Mensaje de texto
Nada $lib->email_user(34,'Prueba','Revisar eFlow');
$lib->email_user('juan@x,com','Prueba','Revisar eFlow');
email_user_html usuario=número usuario o email
subj=Título
mensaje=Mensaje de texto
Nada $lib->email_user_html(34,'Prueba',$html);
$lib->email_user_html('juan@x.com','Prueba',$html);
hash_decode %hash[,'encoding'] Decodifica $lib->hash_decode(%hash,'iso-8859-1');
hash_encode %hash[,'encoding] Codifica $lib->hash_encode(%hash,'iso-8859-1');
str_decode $str[,'encoding] Decodifica cadena $lib->str_decode($str,'iso-8859-1');
str_encode $str[,'encoding] Codifica cadena $lib->str_encode($str,'iso-8859-1');
FileUpload file handle,fine name Guarda Archivo $lib->FileUpload($q->Upload('var'),"/path/fmyile.png");

use Eflow::Libs2

Librería para proporcionar manejo de fechas no laborables.

Método Datos Regresa Uso
new Ninguno Crear objeto $lib=Libs2->new();
holiday Año,mes,día Vacío o descripción evento $workday = $lib->holiday($y,$m,$d,$wd,0,1,$rs);

Esta librería se debe adaptar con los eventos que no tienen fecha fija en el año, como ejemplo tenemos las semanas santas católicas.

Esta librería no se actualiza con el sistema de actualizaciones automáticas.

SDK

El Kit para desarrollo de Software se creó con el propósito de apoyar el desarrollo de actividades cotidianas de programación y así facilitar la creación de post-procesos en los flujos de trabajo.

use Eflow::sdk

Para facilitar la programación de desarrollos propios se ha desarrollado esta librería que realiza algunas acciones que pueden ser de interés para el usuario. Eflow las utiliza internamente de forma que con esto se asegura uno que van a funciona como funcionen para el sistema en general.

Método Parametros Regresa y que hace Uso
new $EF Crear objeto $sdk=Eflow::sdk->new($EF,$Stimestamp,$rswf,$rsfd,$cookie{'modperl'},$rsh);
insert_folio Process (numero folio,etiqueta) $sdk->insert_folio($process,$station,$user,$ruser,'mi etiqueta');
splash_display Process Nada $sdk->splash_display($in{'process'}."mi mensaje",$in{'view_process'},$in{'view_station'},$in{'supervise'},$in{'max'});
splash_go Mensaje Nada $sdk->splash_go("mi mensaje","http://www.google.com",3);
finish_related_folios Terminar folio y paralelos $sdk->finish_related_folios($in{'process'},$in{'station'},$in{'folio'},$user,$user_name[,"3,4,5"]);

JavaScript

validate.js

Función Parámetros Opciones Ejemplo Uso
validate Objeto,tipo,opciones,evento onkeypress="return validate(this,'tipo','opciones',event)";
Entero ninguna validate(this,'int','',event);
Entero negativos validate(this,'int','-',event);
decimal validate(this,'dec',' 10|2',event);
decimal negativos validate(this,'dec','-15|3',event);
alfabético Caracteres validate(this,'alfa','.,-',event);
capitalizar validate(this,'alfa-1-0','.,-',event);
validate(this,'alfa-1-1','.,-',event);
validate(this,'alfa-0-1','.,-',event);
alfanumérico Caracteres validate(this,'alfn','.-,',event);
Libre Caracteres validate(this,'free','abc123',event);
Máscara Mascara validate(this,'mask','(nnn) nnn nnnn',event);
Fecha validate(this,'date','',event);
validate2 Usar en onblur onblur="validate2(this,'tipo','opciones')";
Función Parámetros Uso
openWindow Popup window openWindow('x','url.cgi',1,800,600);
addShadowMarkUp AddShadowMarkUp();
ShadowOn onsubmit="ShadowOn()";
ShadowOff ShadowOff();
BlockCR BlockCR();
GetContent URL GetContent('miscript.cgi?valores');
setCookie Nombre,valor,días setCookie('llave','48',360);
delCookie Nombre delCookie('llave');
readCookie Nombre readCookie('llave');
setWarning Mensaje setWarning("Mesnaje al usuario");
setMsg ID setMsg('msgid',"Mensaje",'on');
setMsg('msgid',"",'off');
suppressBackspace Eviar que usuario use onload="suppressBackspace();"
Id Id elemento var obj = Id('row'+i);

eflow.js

Contiene en forma minimizada : validate.js + navigate.js + calendar.js

Para usar calendario se debe cargar : overlib.js

Ejemplo :

<head>
<link rel="stylesheet" type="text/css" href="/css/eflow.css">
<script language='JavaScript' src="/lib/overlib.js"></script>
<script language='JavaScript' src="/lib/eflow.js"></script>
</head>

### calendar.js + overlib.js

Abre un calendario para llenar un campo de texto con la fecha
seleccionada

Ejemplo:

<head>
<link rel="stylesheet" type="text/css" href="/css/eflow.css">
<script language='JavaScript' src="/lib/overlib.js"></script>
<script language='JavaScript' src="/lib/caledar.js"></script>
</head>

<form name="Forma">
<input type="text" name="fecha" value="" size="10" class="form" readonly><a href="javascript:show_calendar('Forma.fecha');"><img src="/images/cal.png"></a>
</form>

Programas en cron

Listado de programas que se ejecutan con cron y su función

Nombre Periodicidad Descripción
automatic.pl Cada 15 minutos Mueve los folios de estaciones declaradas como automáticas cuando el folio ha llegado a su fecha de vencimiento.
move_pool.pl Cada 15 minutos Mueve los folios que se encuentran en el la cola de asignación.
station_delayed.pl Cada 15 minutos Envía un email a los supervisores con la relación de todos los folios que se encuentran retrasados en los procesos.
move2history.pl Fines de semana Cada fin de semana busca los folios con más de 3 meses de haberse terminado y los mueve a la base de datos históricos.
clean_up_daily.pl 1 AM cada día Limpia registros de usuarios, limpia banderas de emails enviados para que station_delayed.pl vuelva a notificar.
clean_up_weekly.pl 1 AM todos los sábados Borra todos los folios del sistema que ya han caducado de acuerdo a la configuración de cada folio. Para liberar espacio de disco duro.
back_up.pl 4 AM diario Respalda todos los sábados las bases de datos y el directorio de eflow.

Todos los archivos cron vienen con comentarios para entender su funcionalidad.

Para agregar, modificar o eliminar programs que corre el servicio de tareas programadas de cron se debe entrar al directorio /home/eflow/cron y editar el archivo eflow.cron

Para tener un detalle de como utilizar el servicio de cron lea el manual con : man cron

Una explicación básica es :

Detener servicios de cron : crontab -r ó crontab -e Arrancar servicios de cron : crontab archivo_cron Var servicios programados : crontab -l

Archivo de cron :

Unidades de tiempo ruta/programa

minuto hora día mes dia_de_la_semana ruta/programa

*Cada unidad de tiempo
*/nn Cada nn unidades de tiempo
nn,nn,nn A las nn y nn y nn unidades de tiempo
nn-nn Cada unidad de tiempo en el intervalo de nn a nn
n En la unidad específica minutos de 0 al 59
horas del 0 a 23 horas
días del 1 al 31
meses del 1 al 12
día semana 0 Domingo, 1 Lunes, 2 Martes, 3 Miércoles, 4 Jueves, 5 Viernes, 6 Sábado

Ejemplos :
Cada minuto * * * * *
Cada 15 minutos */15 * * * *
A las 3:20 AM 20 3 * * *
El sábado a las 2:35 PM 35 14 * * 6
Los días 15 de cada mes a las 3 PM 0 3 15 * *
Los días 1,7,15 y 25 de Enero, Marzo y Septiembre a las 1:20 PM 20 13 1,7,15,25 1,3,9 *
Los 1 de cada mes que sean sábados o domingos a las 8:00 AM 8 1 * 6,0

eFlow deja instalados estos programas con una frecuencia de ejecución baja para minimizar los recurso utilizados por eFlow en el servidor. Pero si estas frecuencias no son adecuadas al momento de operar. Puede incrementar el tiempo de ejecución modificando los parámetros en el archivo eflow.cron y ejecutando:

crontab eflow.cron

automatic.pl

Este programa de cron merece una explicación especial, porque es muy seguro que eventualmente tenga que interactuar con el, cuando desarrolle post-procesos que funcionen en etapas de que se ejecuten de forma automática.

  1. Cuando el documento se mueve en forma automática, la constante $AUTOMATIC tiene el valor de 1 (o verdadero).
  2. Para mantener las mismas variables entre el método automático y manual, se definen las mismas variables y mantienen su significado como son el hash %Sin. Ejemplos : $in{'process'}, $in{'station'}, $in{'folio'}.
  3. Los datos de la forma no se pasan al script en el modo automático. Si requiere de los valores para realizar acciones, puede ejecutar la rutina get_foliodata, para obtener los valores. Por ejemplo : %fd = get_foliodata();
  4. automatic.pl, reinicia en cada nueva actualización de un folio los siguientes valores, por si los manipula en una actualización previa. %in{'process'}, $in{'station'}, $in{'folio'}, $in{'opt_station'}, $ef_user, $user, $ruser, $user_name
  5. Nunca ejecute la instrucción "exit", en un código que se ejecute con automatic.pl, porque esto detendrá todo el proceso de actualizaciones, y no se actualizara cualquier otro folio pendiente en la cola. Si desea salir sin hacer nada más ni mover el documento, asigne vacío a $in{'opt_station'}, lo que será interpretado por el motor como una actualización de comentarios. Ejemplo : $in{'opt_station'} = ''; return 0;