Skip to content
Iván Rodrigo edited this page Jul 20, 2022 · 9 revisions

Introducción

El objetivo de este motor de aprobación es ser lo más genérico posible al proyecto que se este usando, por ello dispone de BADIs para poder cambiar estados de aprobación, aprobadores, etc. Además de un sistema de configuración sencillo para ir añadiendo o modificando workflow.

El motor esta desarrollando enteramente en ABAP Orientado a Objetos.

Las características que actualmente tiene el motor son:

  • Configuración mediante tablas de los worflows y pasos que va a tener.
  • Clase principal donde es muy sencillo iniciar un workflow, modificar sus datos y realizar aprobaciones.
  • BADIs para poder cambiar aprobadores, estados o realizar procesos una vez se ha grabado el workflow.
  • Dispone de un sistema de estado que es flexible, es decir, se puede indicar que el estado A puede ir al B o al C, a través de la BADIs se podrá determinar si tiene que ir al B o al C. En caso de un workflow normal que tiene los pasos A->B->C no es necesario implementar nada ya que todo esta automátizado.
  • Se pueden crear workflow de tipo borrador.
  • Log de modificaciones donde se puede saber al detalle cualquier cambio que se hace en el workflow.
  • Clase de búsqueda que permite buscar datos de los workflow por casi cualquier campo del modelo de datos. Dicha clase hace uso de CDS para que las búsqueda en sistema HANA sea lo más optima posible.

Configuración

Desde el menú de ámbito ZWFE es posible acceder a toda la configuración del motor:

Menu ambito

Backups

Actualmente los backups no están implementando del motor debido a que para el proyecto que se crea el funcionamiento no va por usuarios nominales, va por roles.

Owners

Los Owners es una figura que indica que permite indicar quien serán los responsables del paso. Dentro de la transacción ZWFE_T005 podemos tener algo como lo siguiente:

Owners

En esta imagen se ven que hay distintos owners que luego se asignarán a los distintos pasos de los workflows configurados.

En la transacción ZWFE_T006 es donde se indica los aprobadores del paso, puede haber tantos aprobadores como se quiera. El aprobador puede ser un usuario nominal, email o cualquier otra cosa que permita determinar quien tiene que aprobar.

Usuarios fijos del owner

Para el proyecto de donde proviene la imagen, el aprobador es un rol. Dicho rol esta asignados a usuarios. Entonces la aplicación que llama al motor lo que hace primero es buscar el rol que tiene el usuario, y con el rol busca cuales son los workflows activos con dicho rol.

Status

En la transacción ZWFE_T002 es donde se configuran todos los pasos que pueden ser usados por los workflow que se configuren:

Status

Será en el flujo de pasos del workflow donde se indicará cual de ellos será el paso inicial, completado, etc.

Workflow

Dentro de la transacción ZWFE_WORKFLOW, que por detrás tiene un cluster de vista, es donde se configura el workflow y como se va comportar:

Workflow

En esta pantalla inicial es donde se parametrizan los distintos workflow que se quieran utilizar. Si se selecciona sobre uno de ellos y se pulsa sobre la carpeta Status:

Status del worklfow

Es donde se indicará el owner del status y cual va ser su comportamiento: inicial, borrador, completado, etc.

Si selecciona un status y se pulsa sobre la carpeta Flow status se configura a que estados puede ir:

Flujo de status

Cuando el paso E001 se aprueba el motor mirará cual es su siguiente estado, que no este indicado como rechazado, que en este caso es el COMPL. Y como esta estado esta marcado como Completado el Worflow terminará.

Validaciones

En el cluster de vistas no hay ninguna verificación de la consistencia de los datos del workflow. Esta validación se realizará en el momento que se instance la clase que gestionará el workflow. Donde en el caso de los estados realizará las siguientes validaciones:

  • Tiene que haber un, solo uno, estado inicial marcado.
  • Que no haya status completados marcados. Puede haber varios status completados marcados.
  • Que no haya status rechazados marcados. Puede haber varios status rechazados marcados.

Utilidades

En el apartado de utilidades tenemos:

  • ZWFE_R_DEL_ALL_WF_ID --> Permite el borrado completo de un workflow a partir de su ID. Este programa se creo para borrar pruebas que se iban haciendo, pero puede usarse para el borrado de históricos.

Clases

Clases principales

Las clases que deben usar en los proyectos son dos:

  1. ZCL_WFE_WORKFLOW_ENGINE encapsula la funcionalidad del motor y es la que se usará para inciar workflow, actualizarlo y aprobarlo/rechazarlo. Los métodos principales son:

    1. NEW_WORKFLOW --> Crea un nuevo workflow. Se le pasará el nombre del workflow, los valores, si se quiere en modo borrador o normal.
    2. CONTINUE_WORKFLOW_STEP --> Realiza la aprobación o rechazo de un Workflow. Se le pasa el ID del workflow y el paso a realizar(los pasos posibles están indicados en la interface ZIF_WFE_DATA=>CS_WF_PROCESS-STEP_RESULT. Donde tenemos dos campos que son: APPROVE o REJECT).
    3. UPDATE_VALUES --> Actualiza los valores del workflow. Se le pasa el ID del worlfow y sus valores. Dentro de los métodos indicados hay un parámetro, IV_PROCESS_USER, que permite indicar el usuario real de quien realiza el proceso. Esto esta motivado porque este motor nació de un proyecto donde el usuario de conexión de SAP desde UI5 era genérico, por lo tanto, nunca se sabía quien realmente estaba creando, modificando o aprobando. Esto hizo que este parámetro (que se le pasaba el email del portal donde estaba la aplicación UI5) permitiese guardar el usuario real en cada acción.
  2. ZCL_WFE_MODEL_DATA_QUERY clase permite buscar en el modelo de datos los workflow casí por cualquier campo. En la mayoría de métodos hay un parámetro llamado IT_PARAMS_SL donde se le pasan los campos y sus valores a buscar. Este parámetro se basa en la estructura RSPARAMSL_255 que se usa en la opción WITH SELECTION-TABLE de la sentencia SUBMIT. Los métodos son:

    1. GET_ALL_WF_ID_DATA --> Busca toda la información del workflow a partir de un rango de ID
    2. GET_ALL_DATA --> Busca toda la información del worflow filtrando por casi todos los campos del modelo.
    3. GET_HEADER_DATA --> Busca toda la información de cabecera filtrando por casi todos los campos del modelo.
    4. GET_VALUES_DATA --> Busca toda la información de los valores filtrando por casi todos los campos del modelo.
    5. GET_STEPS_DATA --> Busca toda la información de los pasos filtrando por casi todos los campos del modelo.
    6. GET_STEPS_APPROVERS_DATA --> Busca toda la información de los aprobadores de los pasos filtrando por casi todos los campos del modelo.
    7. GET_HEADER_DATA --> Busca toda la información de cabecera filtrando por casi todos los campos del modelo.

Los campos que se pueden usar para el filtrado de datos están definidos en la interface ZIF_WFE_DATA=>CS_MODEL_DATA, en cada una de las estructura hay una llamada FIELDS, ejemplo: ZIF_WFE_DATA=>CS_MODEL_DATA-HEADER-FIELDS donde están los campos que se puedan usar.

Diagrama

El diagrama UML de clases es el siguiente:

Diagrama de clases

Funcionamiento

El funcionamiento se explicará mediante ejemplo que es donde mejor se entienden. Aún así, en el programa "ZWFE_R_EXAMPLE_CALLS" están los ejemplos aquí listados.

Crear un nuevo workflow

DATA(lo_wf) = NEW zcl_wfe_workflow_engine( ).

 lo_wf->new_workflow(
  EXPORTING
    iv_workflow = 'MY_DATA'
    iv_process_user = '[email protected]'
    it_values   =  VALUE #( ( field = 'MATERIAL' value = '22434' )
                            ( field = 'CUSTOMER' value = '000223E' )
                            ( field = 'CSR' value = '01223030' )
                            ( field = 'AM' value = '22200' )
                            ( field = 'KUNNR' value = '2343434' )
                            ( counter = 1 field = 'CHEM_COMP_CHEMICALID' value = '5' )
                            ( counter = 1 field = 'CHEM_COMP_MIN' value = '1' )
                            ( counter = 1 field = 'CHEM_COMP_MAX' value = '5' )
                            ( counter = 1 field = 'CHEM_COMP_UNIT' value = '%' )
                            ( counter = 2 field = 'CHEM_COMP_CHEMICALID' value = '9' )
                            ( counter = 2 field = 'CHEM_COMP_MIN' value = '10' )
                            ( counter = 2 field = 'CHEM_COMP_MAX' value = '15' )
                            ( counter = 2 field = 'CHEM_COMP_UNIT' value = 'KG' )
                             )
    iv_draft    = abap_false
  IMPORTING
    ev_wf_id    = DATA(lv_wf_id)
    et_return   = DATA(lt_return) ).

WRITE:/ lv_wf_id.

Actualizar valores

DATA(lo_wf) = NEW zcl_wfe_workflow_engine( ).

lo_wf->update_values(
  EXPORTING
    iv_wf_id  = '005056010BFD1EDBB58801A43D0D20BD'
    it_values = VALUE #( ( field = 'STATUS_MAT' value = '05' ) )
    iv_process_user = '[email protected]'
  IMPORTING
    et_return = DATA(lt_return) ).

Aprobar/Rechazar

DATA(lo_wf) = NEW zcl_wfe_workflow_engine( ).

lo_wf->continue_workflow_step(
  EXPORTING
    iv_wf_id       = '005056010BFD1EDBBAC345CB1176C0BD'
    iv_step_result = zif_wfe_data=>cs_wf_process-step_result-approve
    iv_process_user = [email protected]'
  IMPORTING
    et_return      = DATA(lt_return_continue) 
    ev_wf_completed = DATA(lv_wf_completed) )

Consulta de todos los datos

DATA(lo_query) = NEW zcl_wfe_model_data_query( ).

lo_query->get_all_data(
  EXPORTING
    it_params_sl       = VALUE #( ( selname = zif_wfe_data=>cs_model_data-header-fields-workflow kind = 'S' sign = 'I' option = 'EQ' low = 'PROFILE' )
                                  ( selname = zif_wfe_data=>cs_model_data-header-fields-wf_status kind = 'S' sign = 'I' option = 'EQ' low = zif_wfe_data=>cs_wf_process-wf_status-active )
                                  ( selname = zif_wfe_data=>cs_model_data-steps_approvers-fields-approver kind = 'S'  sign = 'I' option = 'EQ' low = 
                                    'US_XXXX_APPROVALS_CHEMIST'  )
                                  ( selname = zif_wfe_data=>cs_model_data-values-fields-field kind = 'S'  sign = 'I' option = 'EQ' low = 'KUNNR'  )
                                  ( selname = zif_wfe_data=>cs_model_data-values-fields-value kind = 'S'  sign = 'I' option = 'EQ' low = '2343434'  ) )
  IMPORTING
    et_all_data        = DATA(lt_all_data)
    et_header          = DATA(lt_header)
    et_steps           = DATA(lt_steps)
    et_steps_approvers = DATA(lt_steps_approvers)
    et_values          = DATA(lt_values) ).

Consulta de todos los datos por ID

DATA(lo_query) = NEW zcl_wfe_model_data_query( ).

lo_query->get_all_wf_id_data(
  EXPORTING
    it_r_wf_id         = VALUE #( ( sign = 'I' option = 'EQ' low = '005056010BFD1EDC8097BEA0C0B720BD' ) )
  IMPORTING
    et_header          = DATA(lt_header)
    et_steps           = DATA(lt_steps)
    et_steps_approvers = DATA(lt_steps_approvers)
    et_values          = DATA(lt_values) ).

Búsqueda del log de modificaciones

DATA(lo_query) = NEW zcl_wfe_model_data_query( ).

lo_query->get_changelog_data(
  EXPORTING
    it_r_wf_id        = VALUE #( ( sign = 'I' option = 'EQ' low = '005056010BFD1EDBB58801A43D0D20BD' ) )
  IMPORTING
    et_changelog_data =  DATA(lt_changelog_data) ).

Enhacements o BADIs.

Para poder modificar el funcionamiento del workflow y evitar tener que tocar las tripas del motor, cumpliendo la premisa de ser independiente al proyecto, se ha creado el enhacement spot ZWFE_ENHACEMENT_WORKFLOW que contiene, al menos de momento, dos BADIs que son:

  • ZWFE_BADI_ENGINE -> Actualmente no tiene funcionalidad alguna pero en un futuro es posible que se utilice dentro de la clase ZCL_WF_ENGINE, que como se ha visto en el funcionamiento, es la clase que gobierna todo el motor.
  • ZWFE_BADI_WF_MODEL -> Esta BADI actualmente esta implementada en la clase ZCL_WFE_WORKFLOW, clase con las tripas del motor, tiene una serie de métodos que nos permiten realizar acciones sobre los workflow. Los métodos que tienen son:
    • CHANGE_STEP_APPROVERS --> Permite cambiar el aprobador de un paso en el proceso de aprobación/rechazo. En este método tendremos como parámetro:
      • Status determinado
      • Valores del workflow
      • Aprobadores determinados para ese status.
    • POST_SAVE_WORKFLOW --> Se lanza una vez el workflow ha sido grabado con éxito. Este método como parámetro esta la propia clase que se esta usando donde se podrá recuperar los valores necesarios del workflow y realizar las acciones que se necesiten, como enviarlo mail, realizar notificaciones, etc.
    • DETERMINE_NEXT_STATUS --> Se lanza en el proceso de aprobación/rechazo y permite indicar cual será el siguiente status. Este método solo tiene sentido usarse cuando hay más de un status configurado al status actual, el motivo es porque solo se puede ir al status indicado en el flujo configurado. A este método tiene como parámetros:
      • Status actual
      • Valores del workflow
      • Status siguientes
      • Resultado del paso(si se rechaza o aprueba)

En las BADIs creada tienen un filtro donde se le pasará el nombre del workflow. Esto hace que cada workflow tenga su propia BADI, simplificando las implementaciones al no mezclarse código en los métodos de distintos workflows.