Diferencia entre revisiones de «Tarea I: Creando una oficina sin papeles»

De Egeasy
Saltar a: navegación, buscar
(Analizando el diagrama de flujo de información)
(Evolucionando el ''workflow'')
Línea 216: Línea 216:
 
       -{{AT|destino.valor}} = $crear([Documentos]);
 
       -{{AT|destino.valor}} = $crear([Documentos]);
 
       -{{AT|Al_finalizar.Codigo}} = {{STR|"$firmar([&Destino]->[Datos generales].[Firma del escrito]); $guardar([&Destino]); "}};
 
       -{{AT|Al_finalizar.Codigo}} = {{STR|"$firmar([&Destino]->[Datos generales].[Firma del escrito]); $guardar([&Destino]); "}};
{{PR|fin}}
 
 
{{PR|tipo}} [Comprobar documentación] {{PR|es}} {{RE|tarea}}
 
      -{{AT|fuente.definicion}} = [Expediente de beca];
 
      -{{AT|destino.definicion}} = [Entrada];
 
{{PR|fin}}
 
 
{{PR|tipo}} [Elaborar resolución positiva] {{PR|es}} {{RE|tarea}}
 
      -{{AT|fuente.definicion}} = [Expediente de beca];
 
      -{{AT|destino.definicion}} = [Resolución positiva];
 
      -{{AT|destino.valor}} = $crear([Documentos]);
 
{{PR|fin}}
 
 
{{PR|tipo}} [Elaborar resolución negativa] {{PR|es}} {{RE|tarea}}
 
      -{{AT|fuente.definicion}} = [Expediente de beca];
 
      -{{AT|destino.definicion}} = [Resolución negativa];
 
      -{{AT|destino.valor}} = $crear([Documentos]);
 
{{PR|fin}}
 
 
{{PR|tipo}} [Firmar propuesta de resolución] {{PR|es}} {{RE|tarea}}
 
      -{{AT|fuente.definicion}} = [Expediente de beca];
 
      -{{AT|localizacion}} = [Datos generales];
 
      -{{AT|Al_finalizar.Codigo}} = {{STR|"$firmar([&Destino]->[Datos generales].[Firma de la propuesta]); $guardar([&Destino]); "}};
 
{{PR|fin}}
 
 
{{PR|tipo}} [Firmar resolución] {{PR|es}} {{RE|tarea}}
 
      -{{AT|fuente.definicion}} = [Expediente de beca];
 
      -{{AT|localizacion}} = [Datos generales];
 
      -{{AT|Al_finalizar.Codigo}} = {{STR|"$firmar([&Destino]->[Datos generales].[Firma de la resolución]); $guardar([&Destino]); "}};
 
{{PR|fin}}
 
 
{{PR|tipo}} [Registrar salida de documentación] {{PR|es}} {{RE|tarea}}
 
      -{{AT|fuente.definicion}} = [Libro de salida];
 
      -{{AT|destino.definicion}} = [Salida];
 
      -{{AT|destino.valor}} = $crear([Contenido]);
 
 
  {{PR|fin}}
 
  {{PR|fin}}
  

Revisión del 12:17 4 mar 2009

Construir una aplicación paso a paso

Hasta ahora, los usuarios del Registro utilizan el software sólo para introducir o consultar datos, sin realizar ningún trámite ni llevar a cabo un procedimiento administrativo.

Supongamos que la organización ofrece becas para la realización de estudios en el extranjero. Estas becas las gestiona el Servicio de Ayudas y Subvenciones. Los interesados deben presentar las solicitudes en el Registro de Entrada y Salida. Un auxiliar del Registro revisa la documentación y, en caso de faltar algo, elabora un requerimiento para el interesado. Este requerimiento debe firmarlo el jefe de servicio del Registro.

Una vez la documentación esté completa, se remite al Servicio de Ayudas y Subvenciones quien resuelve la beca por el procedimiento de concurrencia sin concurso; es decir, que todos aquellos interesados que cumplan con los requisitos recibirán la beca.

Al recibir la documentación, un técnico del Servicio de Ayudas y Subvenciones comprueba la documentación para ver si el interesado cumple con los requisitos. A continuación, procede a elaborar resolución positiva (o negativa). La resolución la deben firmar el jefe del Servicio de Ayudas y Subvenciones y el director de la organización.

Una vez firmada, la resolución se remite al Registro, donde un auxiliar se encarga de darle salida. El procedimiento se puede resumir en el siguiente diagrama.

Procedimiento de concesión de becas

¿Qué nos hace falta?

Para implementar este workflow, primero debemos identificar los ítems de información y, a continuación, definirlos en el sistema. Analizando, vemos que necesitamos cuatro objetos diferentes:

  • Entrada, para las tareas de Registrar entrada de documentación y Comprobar documentación. Este tipo ya lo tenemos definido.
  • Requerimiento, para las tareas de Elaborar requerimiento y Firmar requerimiento.
  • Resolución positiva y Resolución negativa, para las tareas de Elaborar resolución positiva/negativa, Firmar propuesta de resolución, Firmar resolución y Registrar salida de documentación.

Además, todos los documentos relacionados con una solicitud deben almacenarse en alguna parte. Para ello, definiremos también el tipo Expediente de beca.

Por último, debemos definir dos nuevas habitaciones, donde se enviarán sus tareas específicas: la Oficina de Ayudas y Subvenciones y la Oficina de dirección.

Definir los escritos

Definimos el requerimiento de documentación con dos componentes: una componente escrito, para la plantilla del documento, y una componente formulario, para los campos firma.

tipo [Requerimiento de documentación] es contenedor
    [Escrito] es documento
        -plantilla_documento = "Req 001.rtf";
    fin

    [Datos generales] es formulario
        [Firma del escrito] es firma
    fin
fin

Hacemos lo mismo para las resoluciones. En este caso, como las resoluciones la firman dos personas, debemos incluir dos campos firma, uno para la propuesta y otro para la resolución.

tipo [Resolución positiva] es contenedor
    [Escrito] es documento
        -plantilla_documento = "Res 001.rtf";
    fin

    [Datos generales] es formulario
        [Firma de la propuesta] es firma
        [Firma de la resolución] es firma
    fin
fin
tipo [Resolución negativa] es contenedor
    [Escrito] es documento
        -plantilla_documento = "Res 002.rtf";
    fin

    [Datos generales] es formulario
        [Firma de la propuesta] es firma
        [Firma de la resolución] es firma
    fin
fin

Definir el Expediente de beca

Cada vez que se inicie un trámite de beca, abriremos un expediente en el que se recogerá toda la documentación relacionada con el trámite. Este expediente tendrá un número (asignado automáticamente) que identificará el trámite y una fecha de alta que indicará la fecha en la que se inició el trámite. Asimismo, tendrá un vínculo a la Entrada que dio lugar al trámite.

Crearemos el expediente con dos componentes: una componente para el formulario de datos y otra para la colección en la que se almacerán todos los documentos.

tipo [Expediente de beca] es contenedor
    [Datos generales] es formulario
        [Nº de expediente] es timbre
            -certificado.valor = [&Valor_secuencia];
            -certificado.secuencia.nombre = "STR$EXPEDIENTE"; 
            -certificado.secuencia.longitud = 5; 
        [Fecha de alta] es fecha
        [Solicitud] es vinculo
            -vinculo.definicion = [Entrada];
            -vinculo.etiqueta = [Datos generales].[Número] + " (" + [Datos generales].[Remitente]->[Datos generales].[Nombre/Razón social] + " " +  [Datos generales].[Remitente]->[Datos generales].[Apellidos] + ")";
            -vinculo.valores = $matriz([Libro de entrada].[Contenido]);
    fin

    [Documentos] es coleccion
        -nombre_tabla = "TC$EXPEDIENTE_BECA";

        contiene [Requerimiento de documentación]
        contiene [Resolución positiva]
        contiene [Resolución negativa]

        columna [Nombre]
            -columna_bd.nombre = "DOCUMENTO";
            -origen = [&Nombre];
    fin
fin

Por último, necesitamos almacenar los expedientes en alguna parte. Para ello, crearemos un objeto del sistema en los que almacenarlo.

[Expedientes de beca] es contenedor
    [Contenido] es coleccion
        -nombre_tabla = "TC$EXPEDIENTES";

        contiene [Expediente de beca]

        columna [Nº de expediente]
            -columna_bd.nombre = "NUMERO";
            -origen = [Datos generales].[Nº de expediente];
        columna [Fecha de alta]
            -columna_bd.nombre = "FECHA_ALTA";
            -origen = [Datos generales].[Fecha de alta];
    fin
fin


Definir las oficinas

Tan sólo nos queda definir la oficinas y ubicar los recursos necesarios en cada una. En nuestro caso, se reduce sólo al estante de expedientes, ya que es el único recurso común a las tres oficinas.

[Oficina de Ayudas y Becas] es habitacion
    -publico = falso;

    ubicado [Expedientes de beca] 
        -lugar = "Estantes";
fin

[Oficina de la dirección] es habitacion
    -publico = falso;

    ubicado [Expedientes de beca] 
        -lugar = "Estantes";
fin

¿Cómo funciona el motor de workflow?

Hasta ahora nos hemos centrado en definir los ítems de información que nos iban a hacer falta para llevar a cabo el procedimiento de concesión de beca. En los próximos apartados veremos cómo implementar el flujo de trabajo, pero primero explicaremos cómo funciona el motor de workflow de la plataforma.

En egeasy, los procedimientos administrativos se definen en dos pasos. En primer lugar, debe definirse el flujo de tareas. Esta definición se hace en un fichero con extensión nmt. Los ficheros nmt son ficheros de texto plano que se crean en la carpeta Data del proyecto. Una vez definido el flujo de tareas, procederemos a definir los atributos de cada tarea: ítem de trabajo, código que se ejecuta al terminar la tareas, ... Estas definiciones se realizan en ficheros ndf, como hemos hecho con el resto de los recursos.

Comenzaremos con el flujo de tareas. Lo primero que debemos hacer es crear, en la carpeta Data, el fichero concesion_beca.nmt. A continuación, abrimos el fichero con el editplus.

Los ficheros nmt se componen de métodos. Por hacer un símil, un método sería equivalente a un procedimiento de PASCAL. Cada método lanza tareas, invoca a otros métodos y ejecuta sentencias en ODL. Adicionalmente, puede tener parámetros de E/S y variables locales.

Aquí tenemos un ejemplo.

metodo RegistrarEntrada();
    var
        TareaRegistro: tarea;
inicio
    TareaRegistro = $lanzar("Registrar entrada");
    TareaRegistro.[&Destino]->[Datos generales].[Asunto] = "Esto es una prueba";
    $guardar(TareaRegistro.[&Destino]);
fin

En este segmento de código hemos definido el método RegistrarEntrada. A continuación, hemos definido la variable TareaRegistro de tipo tarea. Después hemos definido la secuencia de tareas.

Cuando comienza la ejecución de un método, el motor de workflow posiciona el cursor en la primera línea del método que está justo después de inicio. Comienza a ejecutar línea por línea hasta que alguna de las sentencias lanza una tarea. Entonces, el sistema crea una nueva tarea, le asigna un ítem de trabajo y establece el estado de la tarea a pendiente. La ejecución del método queda detenida hasta que se finalice la tarea. En nuestro ejemplo, al iniciarse la ejecución del método se lanzaría la tarea Registrar entrada.

Cualquier usuario con los permisos suficientes puede ir a la bandeja de Tareas disponibles y comenzar la tarea. Cuando lo hace, la plataforma abre el ítem de trabajo asignado y cambia el estado de la tarea a realizándose.

Cuando el usuario finaliza la tarea, el sistema cambia el estado a terminada y retoma la ejecución del método que invocó a la tarea. En nuestro ejemplo, asignaría a la variable TareaRegistro la tarea que se acaba de terminar. A continuación ejecutaría las siguientes líneas de código, que modifican el ítem de trabajo de la tarea para después almacenarlo.

Un método termina de ejecutarse cuando el cursor alcanza la palabra fin.

¿Cómo comienza a ejecutarse un método?

Todo proceso tiene un punto de entrada que lanza a ejecutar la primera línea del primer método. Este punto de entrada es un tipo de tarea que se define como raíz en los ficheros de definiciones ndf.

Por tanto, para cada proceso que exista en nuestro sistema de información, tendremos que definir una tarea, llamémosla inicializadora del proceso.

Veamos a continuación la definición de esta tarea, que se corresponde con el proceso Solicitud de beca:

tipo [Solicitud de beca] es tarea
    -descripcion = "Proceso que se encarga de realizar la resolución de una solicitud de beca";
    -fuente.definicion = [Registro de entrada y salida];
    -destino.definicion = [Expediente de beca];
    -destino.valor = $crear([Expedientes de beca].[Contenido]);
    -Al_Comenzar.Nombre = "Metodos\concesion_beca.RegistrarEntrada";
    -es_raiz = verdadero;
fin

La forma de indicar que la tarea Solicitud de beca inicia un proceso de nuestro sistema de información es mediante el atributo lógico es_raiz. Dicho atributo tiene asignado por defecto el valor falso, de forma que poniéndolo a verdadero, conseguiremos que dicha tarea inicie un proceso que será lanzado por un usuario.

Ahora bien, ¿sobre qué recurso queremos que se lance la tarea?

Siempre que lanzamos una tarea, es necesario indicar sobre qué recursos podremos lanzar esa tarea. Para ello, ODL proporciona un atributo llamado fuente.definicion. En nuestro caso, indicaremos la habitación Registro de entrada y salida. Esto significa que el usuario podrá lanzar la tarea Solicitud de beca una vez haya accedido a dicha habitación del centro. No obstante, también podremos asignar al atributo la definición de un contenedor, de manera que la tarea se lanzará una vez se haya accedido a un contenedor de ese tipo. Esta opción la contemplaremos más adelante.

El método a ejecutar una vez se lance la tarea, lo indicaremos en el atributo Al_Comenzar.Nombre, que como vemos, tiene asignado el método creado anteriormente RegistrarEntrada. La nomenclatura que se utiliza para indicar el método es especificar la ruta del fichero donde está incluído el método a partir de la carpeta Data del modelo, y una vez indicada la ruta, añadiremos un punto seguido del nombre del método.

Por último, indicaremos en el atributo destino.definicion lo que se conoce como maintarget de un proceso, es decir, aquel contenedor que se asociará al proceso durante su ejecución. El maintarget de Solicitud de beca será un contenedor de tipo Expediente de beca. ¿Por qué? Porque las tareas que se lancen dentro de este proceso y la información que se genere se almacenará en un Expediente de beca. Además, no sólo queremos indicar el maintarget del proceso Solicitud de beca, sino que también queremos crear el expediente una vez se inicie el proceso. Para ello, utilizaremos la función $crear definida en la librería de funciones de ODL, que nos permite crear un objeto, indicándole la colección o exportación donde se va a almacenar. El tipo de objeto será el definido en destino.definicion. El objeto devuelto por $crear se asignará al atributo destino.valor.

Analizando el diagrama de flujo de información

Antes de seguir desarrollando el workflow, vamos a estudiar el diagrama de flujo de información facilitado al principio de este artículo. Es recomendable que abramos la imagen ampliada en una pestaña nueva del navegador, de manera que podamos ir fijándonos en el diagrama a medida que vamos comentando aspectos de él.

En lo que al flujo de información se refiere, sólo hemos desarrollado la tarea raíz que inicia el proceso Solicitud de beca, que a su vez invoca al método RegistrarEntrada. Una vez llegados a este punto,

Evolucionando el workflow

A la hora de implementar una tarea, hay que tener en cuenta qué ítems van a participar en la ejecución de esa tarea. También habrá que analizar si al lanzar la tarea hay que pasarle algún parámetro de entrada, o lo que se suele llamar target o dominio de la tarea. Iremos siguiendo el flujo de información del diagrama para la implementación de cada una de ellas, y comentaremos qué ítems necesitarán.<p>Cuando se produce una Entrada en nuestro sistema de información, se crea un Expediente de beca único y se registrará esa entrada en el expediente creado. En caso de generarse más entradas debido a una falta de documentación, no se creará un expediente nuevo, sino que al ser un requerimiento, se almacenará y por tanto, estará asociado al expediente que se creó en la primera entrada.

Una vez iniciamos el proceso Solicitud de beca, se invocará al método RegistrarEntrada. Al ser un proceso nuevo, lo primera que debemos hacer es crear un expediente de beca y registrar. Por tanto, habrá que modificar de la siguiente manera el método RegistrarEntrada
metodo RegistrarEntrada();
    var
inicio
$lanzar("Registrar expediente de beca");
$lanzar("Registrar entrada");
fin

Como vemos, nuestro código ya lanza las tareas de registrar el expediente y la entrada. Pero al fijarnos en el diagrama vemos que es posible que se elaboren informes de requirimiento de información que hasta que no se entreguen no se puede continuar con el proceso. Para ello, introduciremos una estructura condicional:

metodo RegistrarEntrada();
    var

documentacion_incompleta: logico;

inicio

documentacion_incompleta = verdadero; TareaRegistroBeca=$lanzar("Registrar expediente de beca"); mientras documentacion_incompleta TareaRegistroEntrada=$lanzar("Registrar entrada"); Entrada = TareaRegistroEntrada.[&Destino]; TareaRegistroBeca.[&Destino]->[Datos generales].[Solicitud] = Entrada; $guardar(TareaRegistroBeca.[&Destino]); si (TareaRegistroEntrada.[&Destino]->[Datos generales].[Documentación completa?] = "Sí") documentacion_incompleta = falso; sino ElaborarRequerimiento = $lanzar("Elaborar requerimiento"); // $lanzar("Firmar requerimiento", ElaborarRequerimiento.[&Destino]);// fin fin


tipo [Registrar entrada] es tarea
      -fuente.definicion = [Expediente de beca];
      -destino.definicion = [Entrada];
      -destino.valor = $crear([Libro de entrada].[Contenido]);
      -Al_finalizar.Codigo = "$sellar([&Destino]->[Datos generales].[Número]); $guardar([&Destino]); ";
fin
tipo [Registrar expediente de beca] es tarea
      -fuente.definicion = [Expediente de beca];
      -Al_finalizar.Codigo = "$sellar([&Destino]->[Datos generales].[Nº de expediente]); $guardar([&Destino]); ";
fin


tipo [Elaborar requerimiento] es tarea
      -fuente.definicion = [Expediente de beca];
      -destino.definicion = [Requerimiento de documentación];
      -destino.valor = $crear([Documentos]);
fin
tipo [Firmar requerimiento] es tarea
      -fuente.definicion = [Expediente de beca];
      -destino.definicion = [Requerimiento de documentación];
      -destino.valor = $crear([Documentos]);
      -Al_finalizar.Codigo = "$firmar([&Destino]->[Datos generales].[Firma del escrito]); $guardar([&Destino]); ";
fin

Siguiente tarea

Véase también