Objetivo
A consulta rápida é responsável por apresentar para o usuário dados de indicadores definidos pelas áreas de negócio para cada um dos ERPs TOTVS. A obtenção destas informações é feita através de serviços REST implementados por cada um dos segmentos. O widget de consulta rápida será semelhante ao da figura abaixo:
Cadastrando as consultas
O cadastro de consulta rápida deve ser realizada através do formulário FRM0015 - Indicadores. Neste cadastro é necessário preencher com as informações da consulta.
Para que seja possível a visualização da consulta rápida no Fluig, a mesma deve estar liberada, ou seja, o desenvolvimento da mesma deve ser encerrada através da ferramenta GOLD.
O nome da consulta deve seguir o padrão composto pelo código do sistema Logix, a letra "i" e a sequencia de identificação do indicador.
Desenvolvimento
Após a criação, deve ser desenvolvido o fonte 4GL com as funções padrões para a execução da consulta rápida no Fluig. Atualmente são necessárias três funções para cada indicador, sendo:
- START: função responsável por retornar dados iniciais da consulta rápida;
- SEARCH: função responsável para retornar os dados da consulta; e
- AUTO_COMPLETE: função responsável por retornar as informações do auto-completar do widget no Fluig.
Até o momento, não será possível efetuar a chamada do LOG de segurança padrão do LOGIX nas funções da consulta rápida. Estas consultas não são cadastradas no menu e não são dadas permissões no ERP, apenas via Fluig Identity. Por este motivo se as funções possuírem chamadas do LOG de segurança, a execução da consulta será interrompida.
Função de START
No 4GL o nome desta função deve ter o sufixo _indicator_start, não poderá possuir parâmetros e deverá retornar para o Fluig uma variável RECORD com as informações de montagem do widget de consulta rápida, como:
- os filtros que poderão ser realizados;
- as colunas que irão compor a grade com os dados da consulta;
- a lista de filtros pré-definidos que poderão ser utilizados; e
- a lista com o nome dos programas que poderão ser executados a partir da 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 as colunas de filtro da 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 as colunas da 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 quais valores estarão na seleção de filtros LET lr_start.selection[1].code = '*' LET lr_start.selection[1].label = 'Todos os usuários' LET lr_start.selection[2].code = 'S' LET lr_start.selection[2].label = 'Somente administradores' LET lr_start.selection[3].code = 'N' LET lr_start.selection[3].label = 'Somente usuários comuns' #Define quais programas poderão ser chamados pela consulta LET lr_start.actions[1].code = 'log02700' LET lr_start.actions[1].label = 'Usuários' LET lr_start.actions[2].code = 'log02720' LET lr_start.actions[2].label = 'Grupos do usuário' RETURN lr_start END FUNCTION
A execução da função acima irá permitir a inicialização do widget de consulta rápida e irá criá-lo semelhante a tela abaixo:
Função de SEARCH
No 4GL o nome desta função deve ter o sufixo _indicator_search, deve ter como parâmetros:
- nome da coluna de filtro selecionada pelo usuário;
- valor do filtro informado pelo usuário;
- valor do filtro pré-definido selecionado;
- nome da coluna de ordenação;
- tipo de ordenação;
- quantidade de linhas por página; e
- número da página de consulta atual.
Todos estes parâmetros devem ser considerados ao executar a consulta no banco de dados e o retorno deve ser uma variável RECORD com:
- os dados da consulta;
- quantidade total de registros encontrados no banco de dados;
- quantidade total de registros que serão retornado para o Fluig;
- número total de páginas conforme a consulta efetuada; e
- número da página atual de consulta.
Exemplo
#---------------------------------------------------------------------------------------------------------------# 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 do filtro da coluna acima (opcional) l_selection CHAR(01), #Valor selecionado na lista de filtros (opcional) l_sort_col CHAR(50), #Coluna de ordenação (opcional) l_sort_order CHAR(04), #Tipo de ordenação ASC ou DESC (opcional) l_rows SMALLINT, #Máximo de registros por página l_page SMALLINT #Página atual de pesquisa 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 com os resultados da 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 serão retornados total INTEGER, #Total de registros encontrados na consulta (sem a paginação) cpage INTEGER, #Página de registros atual pages SMALLINT #Total de páginas resultantes da consulta END RECORD INITIALIZE lr_search.* TO NULL #Verifica a coluna e o 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 o filtro conforme selecionado 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 o SQL da 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 o SQL de COUNT (é necessário ser sem ORDER BY) LET l_sql_count = "SELECT COUNT(*) FROM ("||l_sql_stmt CLIPPED||") t" #Atribui o ORDER BY para o SQL da 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 #Conta a quantidade de página que resultou a consulta LET lr_search.pages = LOG_round(lr_search.total/l_rows,0) #Verifica se a página informada ultrapassou o 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 a posição do registro atual conforme a página e a quantidade de #linhas 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 #Não pode ultrapassar o limite 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
Função AUTO-COMPLETE
No 4GL o nome desta função deve ter o sufixo _indicator_autocomplete, deve ter como parâmetro:
- nome da coluna selecionado para filtro; e
- e o valor do filtro informado pelo usuário.
O retorno deve ser uma variável RECORD com:
- os dados da consulta; e
- o total de registros encontrados no banco de dados.
Exemplo
#-------------------------------------------------------------------# FUNCTION logi1_indicator_autocomplete(l_filter_column,l_filter_value) #-------------------------------------------------------------------# DEFINE l_filter_column CHAR(50), #Coluna de filtro (opcional) l_filter_value CHAR(300) #Valor do filtro da coluna acima (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 data ARRAY[500] OF CHAR(200), count SMALLINT END RECORD INITIALIZE lr_autocomplete.* TO NULL #Verifica a coluna e o 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 o SQL do auto-completar 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 função é executada quando o usuário informa algum filtro na consulta, conforme mostra o exemplo abaixo:
Posicionamento automático no registro selecionado
Quando o usuário, no widget de consulta rápida, selecionar um registro na grade e clicar em uma das ações selecionadas é necessário que a execução do programa Logix selecionado já exiba o registro selecionado já consultado.
Para que isso possa ser realizado é necessário alterar os programas que são informados como ações na função de START. Deve-se incluir nestes programas uma verificação para obter os parâmetros de execução utilizando a função APPLICATION_getNumArgs e já efetuar a operação de consulta.
Exemplo
#-----------------# 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 se há um argumento de execução para o 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
Quando executado através do widget de consulta rápida do Fluig, a função APPLICATION_getNumArgs sempre irá retornar no mínimo três parâmetros, sendo:
- ACTION: a palavra "INDICATOR" para identificar que trata-se da ação de um indicador;
- INDICATOR: o código do indicador cadastrado no FRM0015.
A partir do segundo parâmetro, são enviados as colunas com os valores selecionados pelo usuário.