Páginas filhas
  • 5. Widget de consulta rápida

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

...

O cadastro de consulta rápida deve ser realizada realizado através do formulário FRM0015 - Indicadores. Neste cadastro é necessário preencher com as informações da consulta.

Nota

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 ter sido encerrado 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çãoo cadastro da consulta rápida, deve ser desenvolvido o fonte 4GL com as funções padrões para a execução da consulta rápida mesma no Fluig. Atualmente são necessárias três 4 funções para cada indicador, sendo:

  1. START: função responsável por retornar dados iniciais da consulta rápida;
  2. SEARCH: função responsável para retornar os dados da consulta;
  3. GET_DATA: função semelhante a função SEARCH, preparada para receber e tratar filtro customizado do widget do Fluig; 
  4. AUTO_COMPLETE: função responsável por retornar as informações do auto-completar do widget no Fluig. 

Nota

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.

...

  • os filtros que poderão ser realizados;
  • as colunas que irão compor comporão 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.

...

A execução da função acima irá permitir possibilitará a inicialização do widget de consulta rápida e irá criá-lo semelhante a , o qual será criado de forma semelhante à tela abaixo:

Função de SEARCH

Informações

Quando for necessário utilizar filtro customizado, a função SEARCH pode ser omitida, sendo obrigatório implementar apenas a função GET-DATA.

No 4GL o nome desta função deve ter o sufixo _indicator_search, deve ter e receberá como parâmetros:

  1. nome da coluna de filtro selecionada pelo usuário;
  2. valor do filtro informado pelo usuário;
  3. valor do filtro pré-definido selecionado;
  4. nome da coluna de ordenação;
  5. tipo de ordenação;
  6. quantidade de linhas por página; e
  7. número da página de consulta atual.

...

Bloco de código
themeEclipse
languagenone
#---------------------------------------------------------------------------------------------------------------#
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 QSFWQVLOGIX_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 QSFWQVLOGIX_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

...

Informações

A tecnica apresentada aqui foi pensada para reduzir ao máximo a necessidade de alteração dos programas já construidos em função , motivada pela inclusão de novos parâmetros. Por isso, é apresentada a passagem dos mesmos usando a função _ADVPL_QSSetParametersFWQVSetParametersLogix(), cuja chamada também é realizada pelo serviço REST , desenvolvido pelo Framework, e que é o responsável por chamar o programa de consulta rápida desenvolvido pela da área de negócio/segmento.

Esta função é de definição opcional e deve ser criada quando houver necessidade de tratar filtros customizados do widget de consulta rápida. Ela será executada quando estiver presente no fonte 4GL e RPO e deve estar preparada para tratar o parâmetro customfilter quando este for informado na chamada REST proveniente do widget de consulta rápida.

No 4GL o nome da função deve conter o sufixo _indicator_get_data e não receberá parâmetros. Estes serão passados para a função através de uma área de memória compartilhada, acessível através da função _ADVPL_QSGetParameterFWQVGetParameterLogix("nome_do_parametro"), onde "nome_do_parâmetro" é o identificador do campo dentro da área de memória compartilhada que contem o valor desejado.

O Quando da criação dessa função, o corpo da função SEARCH deve ser transferido para a função GET-DATAela, sendo que a primeira deve ser mantida no 4GL, por questões de compatibilidade, e deve ser reescrita para apenas chamar a função GET-DATA passando os parâmetros através da área de memória compartilhada.

Transferindo dados para a função GET-DATA

Os dados devem Havendo necessidade, os parâmetros podem ser transferidos para a função GET-DATA usando uma variável do tipo RECORD, que deve ser definida exatamente como segue:

...

A variável RECORD deve ser preenchida com os valores correspondentes antes de ser passada como parâmetro para a função _ADVPL_QSSetParametersFWQVSetParametersLogix(<variavel_record>). Lembre-se de inicializar o a variável RECORD antes de atribuir valores ao mesmoaos campos da mesma.

 

 

Exemplo

Trecho demonstrando a função SEARCH reescrita para chamar a função GET-DATA, caso seja necessário manter as duas funções no fonte. Também é mostrada a definição da variável RECORD e a utilização da função _ADVPL_QSSetParametersFWQVSetParametersLogix().

Bloco de código
languagetext
#---------------------------------------------------------------------------------------------------------------#
FUNCTION log1i_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 lr_params RECORD
                        l_searchcol    CHAR(50),
                        l_searchval    CHAR(300),
                        l_selection    CHAR(01),
                        l_sortcol      CHAR(50),
                        l_sortorder    CHAR(04),
                        l_rows         CHAR(10),
                        l_page         CHAR(10),
                        l_customfilter CHAR(500)
                     END RECORD

    INITIALIZE lr_params.* TO NULL
    
    # O record recebe os parâmetros da função search
    LET lr_params.l_searchcol    = l_filter_column
    LET lr_params.l_searchval    = l_filter_value 
    LET lr_params.l_selection    = l_selection 
    LET lr_params.l_sortcol      = l_sort_col
    LET lr_params.l_sortorder    = l_sort_order
    LET lr_params.l_rows         = l_rows
    LET lr_params.l_page         = l_page 
    LET lr_params.l_customfilter = "" # Como customfilter não é recebido na função search, seu valor é vazio.
    
    CALL _ADVPL_QSSetParametersFWQVSetParametersLogix(lr_params) # Grava os parâmetros na área compartilhada
    
    RETURN LOG1ilogi1_indicator_get_data() # O retorno da função search é o mesmo da get_data

END FUNCTION

...

Os dados atribuidos à área de memória compartilhada são recuperados através da função _ADVPL_QSGetParameterFWQVGetParameterLogix("nome_do_parametro"), onde "nome_do_parametro" deve ser exatamente igual ao campo da variável RECORD que se deseja recuperar.
No exemplo abaixo, vemos o trecho

Exemplo

Trecho da função GET-DATA onde é feita a recuperação dos parâmetros.

Exemplo
Bloco de código
languagetext
#---------------------------------------------------------------------------------------------------------------#
FUNCTION log1i_indicator_get_data()
#---------------------------------------------------------------------------------------------------------------#
    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
           l_customfilter  CHAR(500)
    
    # ...Trecho de código omitido para maior clareza do exemplo...

    #Recupera os valores dos parametros
    LET l_filter_column = _ADVPL_QSGetParameterFWQVGetParameterLogix("l_searchcol")
    LET l_filter_value  = _ADVPL_QSGetParameterFWQVGetParameterLogix("l_searchval")
    LET l_selection     = _ADVPL_QSGetParameterFWQVGetParameterLogix("l_selection")
    LET l_sort_col      = _ADVPL_QSGetParameterFWQVGetParameterLogix("l_sortcol")
    LET l_sort_order    = _ADVPL_QSGetParameterFWQVGetParameterLogix("l_sortorder")
    LET l_rows          = _ADVPL_QSGetParameterFWQVGetParameterLogix("l_rows")
    LET l_page          = _ADVPL_QSGetParameterFWQVGetParameterLogix("l_page")
    LET l_customfilter  = _ADVPL_QSGetParameterFWQVGetParameterLogix("l_customfilter")

    CALL conout( "Executando LOG1i_indicator_get_data..." )
    CALL conout( "Coluna de filtro...: " || l_filter_column )
    CALL conout( "Valor de filtro....: " || l_filter_value )
    CALL conout( "Selecao............: " || l_selection )
    CALL conout( "Coluna de Ordenacao: " || l_sort_col )
    CALL conout( "Ordenacao:.........: " || l_sort_order )
    CALL conout( "LInhas.............: " || l_rows )
    CALL conout( "Pagina.............: " || l_page )
    CALL conout( "Filtro customizado.: " || l_customfilter )

    # A partir daqui, segue o restante da função get_data...

...

O valor informado no parâmetro customfilter deve estar de acordo com a sintaxe SQL usada no 4GL . Ou seja, e sua aplicação na pesquisa não requer tratamento especifico. Caso Ou seja, caso o conteúdo do parâmetro customfilter não esteja correto, não será necessário qualquer tratamento de exceção adicionalé responsabilidade do programa de consulta rápida tratar os eventuais erros de execução relacionados.

Exemplo

Trecho do corpo da função GET-DATA mostrando como utilizar o valor recebido no parâmetro customfilter.

...

No 4GL o nome desta função deve ter o sufixo _indicator_autocomplete, deve ter como parâmetro:

  1. nome da coluna selecionado selecionada para filtro; e
  2. e o valor do filtro informado pelo usuário.

...

Bloco de código
languagenone
linenumberstrue
#-------------------------------------------------------------------#
 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
                           
   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",
                     " 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 QSFWQVLOGIX_consoleDebugMessage(l_sql_stmt)
        CALL log0030_processa_err_sql("PREPARE SQL","var_indicator_autocomplete",1)
        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:

...

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 seja possível é 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.

...

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:

  1. ACTION: a palavra "INDICATOR" para identificar que trata-se da ação de um indicador;
  2. INDICATOR: o código do indicador cadastrado no FRM0015. 
  3. A partir do

...

  1. terceiro parâmetro, são

...

  1. enviadas as colunas com os valores selecionados pelo usuário.