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.
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:
- START: función responsable por retornar datos iniciales de la consulta rápida;
- SEARCH: función responsable para retornar los datos de la consulta; y
- AUTO_COMPLETE: función
responsable por retornar las informaciones del autocompletar del widget
en Fluig.
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:
- nombre de la columna de filtro seleccionada por el usuario;
- valor del filtro informado por el usuario;
- valor del filtro predefinido seleccionado;
- nombre de la columna de ordenación;
- tipo de ordenación;
- cantidad de líneas por página; y
- 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:
- los datos de la consulta;
- cantidad total de registros encontrados en el banco de datos;
- cantidad total de registros que se retornarán al Fluig;
- número total de páginas conforme a la consulta efectuada; y
- 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:
- nombre de la columna seleccionado para filtro; y
- y el valor del filtro informado por el usuario.
La devolución debe ser una variable RECORD con:
- los datos de la consulta; y
- 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:
- ACTION: la palabra "INDICATOR" para identificar que se trata de la acción de un indicador;
- 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.