Árvore de páginas

Objetivo

La consulta rápida es responsable de presentar al usuario los datos de indicadores definidos por las áreas de negocio para cada uno de los ERPs TOTVS. La obtención de estas informaciones es realizada a través de servicios REST implementados por cada uno de los segmentos. El widget de consulta rápida será semejante al de la figura a continuación:

Registro de consultas

El registro de consulta rápida debe realizarse a través del formulario FRM0015 - Indicadores. En este registro es necesario llenar con la información de la consulta.

Icon

Para que sea posible la visualización de la consulta rápida en el Fluig, la misma debe estar liberada, es decir, el desarrollo de la misma debe ser finalizada a través de la herramienta GOLD.

 

 

El nombre de la consulta debe seguir el estándar compuesto por el código del sistema Logix, la letra "i" y la secuencia de identificación del indicador.

Desarrollo

Después de la creación, debe desarrollarse la fuente 4GL con las funciones estándares para la ejecución de la consulta rápida en Fluig. Actualmente tres funciones son necesarias para cada indicador, siendo:

  1. START: función responsable por retornar datos iniciales de la consulta rápida;
  2. SEARCH: función responsable para retornar los datos de la consulta; y
  3. AUTO_COMPLETE: función responsable por retornar las informaciones del autocompletar del widget en Fluig.


Icon

Hasta ahora, no será posible efectuar la llamada del LOG de seguridad estándar del LOGIX en las funciones de la consulta rápida. Estas consultas no se registran en el menú y no se dan permisos en el ERP, apenas vía Fluig Identity. Por este motivo si las funciones poseen llamadas del LOG de seguridad, la ejecución de la consulta será interrumpida.


Función de START

En el 4GL el nombre de esta función debe tener el sufijo _indicator_start, no podrá poseer parámetros y deberá retornar para el Fluig una variable RECORD con las informaciones de montaje del widget de consulta rápida, como:

  • los filtros que se podrán realizar;
  • las columnas que compondrán la grilla con los datos de la consulta;
  • la lista de filtros predefinidos que se podrán utilizar; y
  • la lista con el nombre de los programas que se podrán ejecutar a partir de la consulta.
Exemplo
#------------------------------#
FUNCTION logi1_indicator_start()
#------------------------------#
    DEFINE lr_start RECORD
                        filters   ARRAY[2] OF RECORD
                                      table_name  LIKE frm_column.table_name,
                                      column_name LIKE frm_column.column_name
                                  END RECORD,
                                  
                        columns   ARRAY[3] OF RECORD
                                      table_name  LIKE frm_column.table_name,
                                      column_name LIKE frm_column.column_name,
                                      can_order   SMALLINT
                                  END RECORD,
                                  
                        selection ARRAY[3] OF
                                  RECORD
                                      code        CHAR(03),
                                      label       CHAR(50)
                                  END RECORD,
                                  
                        actions   ARRAY[2] OF
                                  RECORD
                                      code        CHAR(08),
                                      label       CHAR(50)
                                  END RECORD
                    END RECORD
                                               
    #Define las columnas de filtro de la consulta rápida
    LET lr_start.filters[1].table_name  = 'log_grupos'
    LET lr_start.filters[1].column_name = 'grupo'
    
    LET lr_start.filters[2].table_name  = 'log_grupos'
    LET lr_start.filters[2].column_name = 'des_grupo'
    
    #Define las columnas de la consulta rápida
    LET lr_start.columns[1].table_name  = 'usuarios'
    LET lr_start.columns[1].column_name = 'cod_usuario'
    LET lr_start.columns[1].can_order   = TRUE
    
    LET lr_start.columns[2].table_name  = 'usuarios'
    LET lr_start.columns[2].column_name = 'nom_funcionario'
    LET lr_start.columns[2].can_order   = TRUE
    
    LET lr_start.columns[3].table_name  = 'usuarios'
    LET lr_start.columns[3].column_name = 'ind_admlog'
    LET lr_start.columns[3].can_order   = FALSE
    
    #Define cuáles valores estarán en la selección de filtros
    LET lr_start.selection[1].code  = '*'
    LET lr_start.selection[1].label = 'Todos los usuarios'
    
    LET lr_start.selection[2].code  = 'S'
    LET lr_start.selection[2].label = 'Solamente administradores'
    
    LET lr_start.selection[3].code  = 'N'
    LET lr_start.selection[3].label = 'Solamente usuarios comunes'
    
    #Define cuáles programas podrán ser llamados por la consulta
    LET lr_start.actions[1].code  = 'log02700'
    LET lr_start.actions[1].label = 'Usuarios'
    
    LET lr_start.actions[2].code  = 'log02720'
    LET lr_start.actions[2].label = 'Grupos del usuario'
    
    RETURN lr_start
END FUNCTION

La ejecución de la función anterior permitirá la iniciación del widget de consulta rápida y lo creará semejante a la pantalla a continuación:

Función de SEARCH

En el 4GL el nombre de esta función debe tener el sufijo _indicator_search, debe tener como parámetros:

  1. nombre de la columna de filtro seleccionada por el usuario;
  2. valor del filtro informado por el usuario;
  3. valor del filtro predefinido seleccionado;
  4. nombre de la columna de ordenación;
  5. tipo de ordenación;
  6. cantidad de líneas por página; y
  7. número de la página de consulta actual.

Todos estos parámetros deben ser considerados al ejecutar la consulta en el banco de datos y el retorno debe ser una variable RECORD con:

  1. los datos de la consulta;
  2. cantidad total de registros encontrados en el banco de datos;
  3. cantidad total de registros que se retornarán al Fluig;
  4. número total de páginas conforme a la consulta efectuada; y
  5. número de la página actual de consulta.
Ejemplo
#---------------------------------------------------------------------------------------------------------------#
FUNCTION logi1_indicator_search(l_filter_column,l_filter_value,l_selection,l_sort_col,l_sort_order,l_rows,l_page)
#---------------------------------------------------------------------------------------------------------------#
    DEFINE l_filter_column CHAR(50),  #Coluna de filtro (opcional)
           l_filter_value  CHAR(300), #Valor del filtro de la columna anterior (opcional)
           l_selection     CHAR(01),  #Valor seleccionado en la lista de filtros (opcional)
           l_sort_col      CHAR(50),  #Columna de ordenación (opcional)
           l_sort_order    CHAR(04),  #Tipo de ordenación ASC o DESC (opcional)
           l_rows          SMALLINT,  #Máximo de registros por página
           l_page          SMALLINT   #Página actual de investigación
    
    DEFINE l_sql_stmt      CHAR(500),
           l_sql_count     CHAR(500),
           l_where_clause  CHAR(250)
           
    DEFINE l_ind           SMALLINT,
           l_position      INTEGER
    
    DEFINE lr_search       RECORD
                               data  ARRAY[60] OF 
                                     RECORD     #Lista con los resultados de la consulta
                                         cod_usuario     LIKE usuarios.cod_usuario,
                                         nom_funcionario LIKE usuarios.nom_funcionario,
                                         ind_admlog      LIKE usuarios.ind_admlog
                                     END RECORD,
                               count SMALLINT,  #Total de registros que se retornarán
                               total INTEGER,   #Total de registros encontrados en la consulta (sin la paginación)
                               cpage INTEGER,   #Página de registros actual
                               pages SMALLINT   #Total de páginas resultantes de la consulta
                           END RECORD
                           
    INITIALIZE lr_search.* TO NULL
                           
    #Verifica la columna y el filtro informado por parámetro
    IF  l_filter_column IS NOT NULL AND l_filter_value IS NOT NULL THEN
        LET l_where_clause = "UPPER(g."||l_filter_column CLIPPED||") LIKE '%"||UPSHIFT(l_filter_value) CLIPPED||"%'"
    ELSE
        LET l_where_clause = "1=1"
    END IF
    
    #Adiciona el filtro conforme seleccionado
    IF  l_selection IS NOT NULL AND l_selection <> "*" THEN
        LET l_where_clause = l_where_clause CLIPPED," AND u.ind_admlog = '",l_selection CLIPPED,"'"
    END IF
    
    #Monta el SQL de la consulta rápida
    LET l_sql_stmt = "SELECT DISTINCT",
                           " u.cod_usuario,",
                           " u.nom_funcionario,",
                           " u.ind_admlog",
                      " FROM usuarios u",
                      " LEFT OUTER JOIN log_usu_grupos l",
                        " ON l.usuario = u.cod_usuario",
                      " LEFT OUTER JOIN log_grupos g",
                        " ON g.grupo   = l.grupo",
                     " WHERE ",l_where_clause
    
    #Monta el SQL de COUNT (es necesario ser sin ORDER BY)
    LET l_sql_count = "SELECT COUNT(*) FROM ("||l_sql_stmt CLIPPED||") t"
    
    #Atribuye el ORDER BY para el SQL de la consulta rápida
    IF  l_sort_col IS NOT NULL AND l_sort_order IS NOT NULL THEN
        LET l_sql_stmt  = l_sql_stmt CLIPPED||" ORDER BY "||l_sort_col CLIPPED||" "||l_sort_order
    ELSE
        LET l_sql_stmt  = l_sql_stmt CLIPPED||" ORDER BY 1"
    END IF
    
    WHENEVER ERROR CONTINUE
    PREPARE var_indicator_count FROM l_sql_count
    WHENEVER ERROR STOP
    IF  sqlca.sqlcode <> 0 THEN
        CALL QS_consoleDebugMessage(l_sql_count)
        CALL log0030_processa_err_sql("PREPARE SQL","var_indicator_count",1)
        RETURN NULL
    END IF
    
    WHENEVER ERROR CONTINUE
    EXECUTE var_indicator_count INTO lr_search.total
    WHENEVER ERROR STOP
    IF  sqlca.sqlcode <> 0 THEN
        CALL log0030_processa_err_sql("EXECUTE SQL","var_indicator_count",1)
        FREE var_indicator_count
        RETURN NULL
    END IF
    
    #Cuenta la cantidad de página que resultó la consulta
    LET lr_search.pages = LOG_round(lr_search.total/l_rows,0)
    
    #Verifica si la página informada excedió el total de páginas
    IF  lr_search.pages > 0 THEN
        IF  l_page > lr_search.pages THEN
            LET lr_search.cpage = lr_search.pages
        ELSE
            LET lr_search.cpage = l_page
        END IF
    ELSE
        LET lr_search.pages = 1
        LET lr_search.cpage = l_page
    END IF
    
    WHENEVER ERROR CONTINUE
    FREE var_indicator_count
    PREPARE var_indicator_search FROM l_sql_stmt
    WHENEVER ERROR STOP
    IF  sqlca.sqlcode <> 0 THEN
        CALL QS_consoleDebugMessage(l_sql_stmt)
        CALL log0030_processa_err_sql("PREPARE SQL","var_indicator_search",1)
        RETURN NULL
    END IF
    
    WHENEVER ERROR CONTINUE
    DECLARE cq_indicator_search CURSOR FOR var_indicator_search
    WHENEVER ERROR STOP
    IF  sqlca.sqlcode <> 0 THEN
        CALL log0030_processa_err_sql("DECLARE CURSOR","cq_indicator_search",1)
        FREE var_indicator_search
        RETURN NULL
    END IF
    
    WHENEVER ERROR CONTINUE
    OPEN cq_indicator_search
    WHENEVER ERROR STOP
    IF  sqlca.sqlcode <> 0 THEN
        CALL log0030_processa_err_sql("OPEN CURSOR","cq_indicator_search",1)
        FREE var_indicator_search
        RETURN NULL
    END IF
    
    #Calcula la posición del registro actual como la página y la cantidad de
    #líneas por página
    LET l_ind = 1
    LET l_position = ((l_rows * l_page) - l_rows) + 1
    
    WHILE TRUE
        WHENEVER ERROR CONTINUE
        FETCH ABSOLUTE l_position cq_indicator_search INTO lr_search.data[l_ind].*
        WHENEVER ERROR STOP
        IF  sqlca.sqlcode <> 0 THEN
            IF  sqlca.sqlcode <> NOTFOUND THEN
                CALL log0030_processa_err_sql("FETCH CURSOR","cq_indicator_search",1)
            END IF
            
            EXIT WHILE
        END IF
        
        LET l_ind = l_ind + 1
        LET l_position = l_position + 1
        
        #No puede exceder el límite de registros por página
        IF  l_ind > l_rows THEN
            EXIT WHILE
        END IF
    END WHILE
    
    WHENEVER ERROR CONTINUE
    CLOSE cq_indicator_search
    FREE  cq_indicator_search
    WHENEVER ERROR STOP
    
    LET lr_search.count = l_ind - 1
    RETURN lr_search
END FUNCTION

Función AUTO-COMPLETE

En el 4GL el nombre de esta función debe tener el sufijo _indicator_autocomplete, debe tener como parámetro:

  1. nombre de la columna seleccionado para filtro; y
  2. y el valor del filtro informado por el usuario.

La devolución debe ser una variable RECORD con:

  1. los datos de la consulta; y
  2. el total de registros encontrados en el banco de datos.
Ejemplo
#-------------------------------------------------------------------#
FUNCTION logi1_indicator_autocomplete(l_filter_column,l_filter_value)
#-------------------------------------------------------------------#
    DEFINE l_filter_column CHAR(50), #Columna de filtro (opcional)
           l_filter_value  CHAR(300) #Valor del filtro de la columna anterior (opcional)
    
    DEFINE l_sql_stmt      CHAR(500),
           l_sql_count     CHAR(500),
           l_where_clause  CHAR(250)
           
    DEFINE l_ind           SMALLINT,
           l_position      INTEGER
    
    DEFINE lr_autocomplete RECORD
                               fecha  ARRAY[500] OF CHAR(200),
                               count SMALLINT 
                           END RECORD
                           
    INITIALIZE lr_autocomplete.* TO NULL
                           
    #Verifica la columna y el filtro informado por parámetro
    IF  l_filter_column IS NOT NULL AND l_filter_value IS NOT NULL THEN
        LET l_where_clause = "UPPER(g."||l_filter_column CLIPPED||") LIKE '%"||UPSHIFT(l_filter_value) CLIPPED||"%'"
    ELSE
        LET l_where_clause = "1=1"
    END IF
    
    #Monta el SQL del autocompletar
    LET l_sql_stmt = "SELECT g.",l_filter_column CLIPPED,
                     "  FROM log_grupos g",
                     " WHERE ",l_where_clause CLIPPED,
                     " ORDER BY 1"
    
    WHENEVER ERROR CONTINUE
    PREPARE var_indicator_autocomplete FROM l_sql_stmt
    WHENEVER ERROR STOP
    IF  sqlca.sqlcode <> 0 THEN
        CALL QS_consoleDebugMessage(l_sql_stmt)
        CALL log0030_processa_err_sql("PREPARE SQL","var_indicator_autocomplete",1)
        RETURN NULL
    END IF
    
    WHENEVER ERROR CONTINUE
    DECLARE cq_indicator_autocomplete CURSOR FOR var_indicator_autocomplete
    WHENEVER ERROR STOP
    IF  sqlca.sqlcode <> 0 THEN
        CALL log0030_processa_err_sql("DECLARE CURSOR","cq_indicator_autocomplete",1)
        FREE var_indicator_autocomplete
        RETURN NULL
    END IF
    
    WHENEVER ERROR CONTINUE
    LET l_ind = 1
    FOREACH cq_indicator_autocomplete INTO lr_autocomplete.data[l_ind]
        IF  sqlca.sqlcode <> 0 THEN
            CALL log0030_processa_err_sql("FOREACH CURSOR","cq_indicator_autocomplete",1)
            EXIT FOREACH
        END IF
        
        LET l_ind = l_ind + 1
        
        IF  l_ind > 500 THEN
            EXIT FOREACH
        END IF
    END FOREACH
    
    FREE cq_indicator_autocomplete
    WHENEVER ERROR STOP
    
    LET lr_autocomplete.count = l_ind - 1
    RETURN lr_autocomplete
END FUNCTION

Esta función es ejecutada cuando el usuario informa algún filtro en la consulta, como se muestra en el ejemplo a seguir:

Posicionamiento automático en el registro seleccionado

Cuando el usuario, en el widget de consulta rápida, seleccione un registro en la grilla y haga clic en una de las acciones seleccionadas es necesario que la ejecución del programa Logix seleccionado ya exhiba el registro seleccionado ya consultado.

Para que eso pueda ser realizado es necesario alterar los programas que son informados como acciones en la función de START. En estos programas se debe incluir una verificación para obtener los parámetros de ejecución utilizando la función APPLICATION_getNumArgs y ya efectuar la operación de consulta.

Ejemplo
#-----------------#
FUNCTION log02720()
#-----------------#
    DEFINE l_usuario LIKE log_usu_grupos.usuario
    IF  LOG_initApp("PADRAO") > 0 THEN
        RETURN
    END IF
    LET m_form_reference = _ADVPL_create_component(NULL,"LFORMMETADATA",m_container_reference)
    CALL _ADVPL_set_property(m_form_reference,"FORM","log02720",mr_log_usu_grupos,ma_log_usu_grupos)
    #Verifica si hay un argumento de ejecución para el programa
    IF  APPLICATION_getNumArgs() > 0 THEN
        IF  APPLICATION_getArg("action") = "INDICATOR" AND UPSHIFT(APPLICATION_getArg("indicator")) = "LOGI1" THEN
            LET l_usuario = DOWNSHIFT(APPLICATION_getArg("cod_usuario"))
        END IF
    END IF
    IF  l_usuario IS NOT NULL THEN
        CALL _ADVPL_get_property(m_form_reference,"EXECUTE_OPERATION","FIND","a.usuario='"||l_usuario CLIPPED||"'")
    ELSE
        CALL _ADVPL_set_property(m_form_reference,"ACTIVATE",TRUE)
    END IF
END FUNCTION

Cuando se ejecuta a través del widget de consulta rápida del Fluig, la función APPLICATION_getNumArgs siempre devolverá como mínimo tres parámetros, siendo:

  1. ACTION: la palabra "INDICATOR" para identificar que se trata de la acción de un indicador;
  2. INDICATOR: el código del indicador registrado en el FRM0015.

A partir del segundo parámetro, se envían las columnas con los valores seleccionados por el usuario.