Rotina Banco de dados

📘

Importante

Os exemplos deste tutorial são para Oracle, contudo também é aplicável no SQLServer

A base desse tipo de ação é uma Stored Procedure que será contextualizada e executada pelo sistema. Como existem vários recursos de programação e diferenças significativas entre os SGDB (Oracle e SqlServer) suportados pelo Sankhya-Om, a melhor maneira de criar a stored procedure é fazê-lo diretamente no banco. Assim, a interface de configuração das ações desse tipo coleta as informações necessárias para criar o corpo da procedure. Dessa forma, siga as orientações a seguir:

  • Abra o Construtor de telas e nele localize a tabela de exemplo "Tarefa";
  • Na aba Ações, crie uma ação do tipo "Rotina no Banco de Dados" e informe a "Descrição";
  • No campo "Nome da rotina", informe o nome da procedure propriamente dito.
1919

No campo "Depois de executar, recarregar", selecione uma dentre as seguintes opções:

  • Toda a grade: Recarrega todos os registros da grade principal da tela, independente dos itens selecionados.
  • Os registros selecionados: Recarrega somente os registros selecionados para a ação.
  • O registro pai (Quando existir): No caso em que a ação é registrada para uma tela Detalhe, recarrega o registro da tela Mestre. Caso seja selecionado para uma tela não Detalhe, toda a grade será recarregada.
  • O registro principal (Quando existir): A diferença é sutil, mas entenda que uma tela Mestre, pode ser Detalhe de outra. Por exemplo, quando estamos executando uma ação para a tela "Participantes", o registro pai seria a "Etapa" e o registro principal seria a "Tarefa", pois Participante é Detalhe de Etapa que por sua vez, é Detalhe de Tarefa.

Em seguida, salve a ação e clique no botão "Criar uma template da rotina" para gerar um template da procedure.

Nota: Quando a procedure está compilada no Banco, o campo "Nome da rotina" ficará desabilitado.

O template criado revela como deve ser o “esqueleto” da proc, ou seja, quais são os parâmetros e entrada e saída que ela deve ter. Confira abaixo:

CREATE OR REPLACE PROCEDURE "STP_CHECK_LIST" (
       P_CODUSU NUMBER,
       P_IDSESSAO VARCHAR2,
       P_QTDLINHAS NUMBER, 
       P_MENSAGEM OUT VARCHAR2
) AS
BEGIN
END;
/

Referente aos parâmetros, teremos:

  • P_CODUSU: Código do usuário logado – pode ser útil em alguns casos;
  • P_IDSESSAO: Esse identificador serve para separar o ambiente da execução
  • P_QTDLINHAS: Determina quantas linhas estavam selecionadas no grid, no momento da execução.
  • P_MENSAGEM: (parâmetro de saída): Se houver atribuição de um valor para esse parâmetro, ao final da execução essa mensagem será mostrada ao usuário.

Em seguida, recompile a procedure da seguinte forma:

CREATE OR REPLACE PROCEDURE "STP_CHECK_LIST" (
       P_CODUSU NUMBER,
       P_IDSESSAO VARCHAR2,
       P_QTDLINHAS NUMBER,
       P_MENSAGEM OUT VARCHAR2
) AS
BEGIN
       INSERT INTO AD_TADTAR(CODTAREFA, DESCRTAR) VALUES(1, 'Logística');
       INSERT INTO AD_TADETA(CODTAREFA, CODETAPA, DESCRICAO) VALUES(1, 1, 'Ligar para transportadora e agendar carregamento');
       INSERT INTO AD_TADPTA(CODTAREFA, CODETAPA, CODPARTICIPANTE, NOME) VALUES(1, 1, 1, 'Antônio');
END;
/

Ao executar a ação, podemos comprovar a inclusão dos registros.

Até aqui, já é possível fazer uma infinidade de ações, afinal, todo arsenal de programação do banco de dados pode usado para incluir/alterar/remover registros de qualquer tabela, efetuar desde os mais simples aos mais elaborados cálculos. Além disso, antes de executar a procedure, o Sankhya-Om prepara o ambiente de execução, passando alguns parâmetros. Esses parâmetros podem ser obtidos da seguinte forma:

Ao retornar à aba Ações, adicione um parâmetro do tipo texto chamado NOMEPARTICIPANTE e recompile a procedure assim:

CREATE OR REPLACE PROCEDURE "STP_CHECK_LIST" (
       P_CODUSU NUMBER,
       P_IDSESSAO VARCHAR2,
       P_QTDLINHAS NUMBER,
       P_MENSAGEM OUT VARCHAR2
) AS
       V_PROXIMO_ID_PARTICIPANTE NUMBER;
BEGIN

       -- Para descobrir o próximo codparticipante...
       SELECT
             MAX(CODPARTICIPANTE) + 1
       INTO
             V_PROXIMO_ID_PARTICIPANTE
       FROM
             AD_TADPTA
       WHERE
             CODTAREFA = 1 AND CODETAPA  = 1;

       -- No primeiro participante, o valor da variável estará nulo.  
       IF V_PROXIMO_ID_PARTICIPANTE IS NULL THEN
             V_PROXIMO_ID_PARTICIPANTE := 1;
       END IF;

       INSERT
             INTO AD_TADPTA (
                  CODTAREFA,
                  CODETAPA,
                  CODPARTICIPANTE,
                  NOME
             ) VALUES (
                  1,
                  1,
                  V_PROXIMO_ID_PARTICIPANTE,
                  ACT_TXT_PARAM(P_IDSESSAO, 'NOMEPARTICIPANTE')
             );
END;
/

Posteriormente, a procedure irá obter o valor informado através da função ACT_TXT_PARAM. Isso é possível porque o Sankhya-Om injeta esses parâmetros no banco, antes de executar a procedure, por isso existe o parâmetro P_IDSESSAO mencionado acima, sendo que ele é necessário para isolar o ambiente dessa execução.

Além da função ACT_TXT_PARAM mencionada acima, existem outras três funções, uma para cada tipo de dado, observe:

  • ACT_TXT_PARAM: Retorna um valor VARCHAR, usada para parâmetro do tipo texto.
  • ACT_INT_PARAM: Retorna um valor NUMBER, usada para parâmetro do tipo numero inteiro.
  • ACT_DEC_PARAM: Retorna um valor NUMBER, usada para parâmetro do tipo numero decimal.
  • ACT_DTA_PARAM: Retorna um valor DATE, usada para parâmetro do tipo data.

Todas essas funções têm a mesma estrutura. Recebem o ID da sessão como primeiro argumento e o Nome do parâmetro como segundo.

Também estão disponíveis a PK de todos os registros selecionados na grade no momento da execução. Para obter essas informações, existem quatro funções semelhantes, observe:

  • ACT_TXT_FIELD: Retorna um valor VARCHAR, usada para campos do tipo texto.
  • ACT_INT_FIELD: Retorna um valor NUMBER, usada para campos do tipo numero inteiro.
  • ACT_DEC_FIELD: Retorna um valor NUMBER, usada para campos do tipo numero decimal.
  • ACT_DTA_FIELD: Retorna um valor DATE, usada para campos do tipo data.

A diferença no uso dessas funções, é que além do ID da sessão e o Nome do campo, é necessário também informar um Índice que determina a sequencia das linhas selecionadas. Assim, considere o exemplo:

CREATE OR REPLACE PROCEDURE "STP_CHECK_LIST" (
       P_CODUSU NUMBER,
       P_IDSESSAO VARCHAR2,
       P_QTDLINHAS NUMBER,
       P_MENSAGEM OUT VARCHAR2
) AS
       V_PROXIMO_ID_PARTICIPANTE NUMBER;
       V_CODTAREFA NUMBER;
       V_NOMEPARTICIPANTE VARCHAR2(4000);
BEGIN       
       -- Pegamos o valor digitado pelo usuário e guardamos nesta variável.
       V_NOMEPARTICIPANTE := ACT_TXT_PARAM(P_IDSESSAO, 'NOMEPARTICIPANTE');

       -- Como visto, P_QTDLINHAS determina quantas linhas estão selecionadas  
       FOR I IN 1..P_QTDLINHAS
       LOOP
           -- Aqui, "I" representa a qual linha estamos nos referindo.
           V_CODTAREFA := ACT_INT_FIELD(P_IDSESSAO, I, 'CODTAREFA');

           SELECT
                 MAX(CODPARTICIPANTE) + 1
           INTO
                 V_PROXIMO_ID_PARTICIPANTE
           FROM
                 AD_TADPTA
           WHERE
                 CODTAREFA = V_CODTAREFA  AND CODETAPA  = 1;

           -- No primeiro participante, o valor da variável estará nulo.  
           IF V_PROXIMO_ID_PARTICIPANTE IS NULL THEN
                 V_PROXIMO_ID_PARTICIPANTE := 1;
           END IF;

           -- Com todos os valores necessários, fazemos a inclusão  
           INSERT
                 INTO AD_TADPTA (
                      CODTAREFA,
                      CODETAPA,
                      CODPARTICIPANTE,
                      NOME
                 ) VALUES (
                      V_CODTAREFA,
                      1,
                      V_PROXIMO_ID_PARTICIPANTE,
                      ACT_TXT_PARAM(P_IDSESSAO, 'NOMEPARTICIPANTE')
                 );
       END LOOP;
END;
/

Com duas Tarefas selecionadas, execute novamente a ação.
De acordo com a procedure, o nome do participante informado, será incluído na etapa 1 das duas tarefas.

De acordo com a proc o nome do participante informado pelo usuário será incluído na etapa 1 das duas tarefas.

Dicas

Mecanismo de confirmação: Em algumas situações, pode ser necessário solicitar a confirmação do usuário durante a execução da ação. Por exemplo, digamos que uma etapa normalmente tenha no máximo dois participantes, e se estiver sendo solicitada a inclusão de um terceiro participante, o usuário deverá ser consultado antes de proceder a inclusão, recompilando a procedure, confira abaixo:

Recompile a procedure assim:

CREATE OR REPLACE PROCEDURE "STP_CHECK_LIST" (
       P_CODUSU NUMBER,
       P_IDSESSAO VARCHAR2,
       P_QTDLINHAS NUMBER,
       P_MENSAGEM OUT VARCHAR2
) AS
       V_PROXIMO_ID_PARTICIPANTE NUMBER;
       V_CODTAREFA NUMBER;
       V_NOMEPARTICIPANTE VARCHAR2(4000);
       V_TOTAL_PARTICIPANTES NUMBER;
       V_DESCRTAREFA VARCHAR(4000);
       V_DESCRETAPA VARCHAR(4000);
       V_TITULO VARCHAR(4000);
       V_MENSAGEM VARCHAR(4000);
       V_INCLUIR BOOLEAN;
BEGIN       
       -- Pegamos o valor digitado pelo usuário e guardamos nesta variável.
       V_NOMEPARTICIPANTE := ACT_TXT_PARAM(P_IDSESSAO, 'NOMEPARTICIPANTE');

       -- Como visto, P_QTDLINHAS determina quantas linhas estão selecionadas  
       FOR I IN 1..P_QTDLINHAS
       LOOP
           -- Aqui, "I" representa a qual linha estamos nos referindo.
           V_CODTAREFA := ACT_INT_FIELD(P_IDSESSAO, I, 'CODTAREFA');

          SELECT
                 TAR.DESCRTAR,
                 ETA.DESCRICAO,
                 MAX(CODPARTICIPANTE) + 1,
                 COUNT(1)
           INTO
                 V_DESCRTAREFA,
                 V_DESCRETAPA,
                 V_PROXIMO_ID_PARTICIPANTE,
                 V_TOTAL_PARTICIPANTES
           FROM
                 AD_TADTAR TAR
                 INNER JOIN AD_TADETA ETA ON ETA.CODTAREFA = TAR.CODTAREFA
                 INNER JOIN AD_TADPTA PTA ON PTA.CODTAREFA = ETA.CODTAREFA AND PTA.CODETAPA = ETA.CODETAPA
           WHERE
                 TAR.CODTAREFA = V_CODTAREFA  AND ETA.CODETAPA = 1
           GROUP BY
                 TAR.DESCRTAR, ETA.DESCRICAO;

           -- No primeiro participante, o valor da variável estará nulo.  
           IF V_PROXIMO_ID_PARTICIPANTE IS NULL THEN
                 V_PROXIMO_ID_PARTICIPANTE := 1;
           END IF;

           --Se o total de participantes ainda não chegou ao limite, a inclusão está liberada
           IF V_TOTAL_PARTICIPANTES < 2 THEN
               V_INCLUIR := TRUE;
           ELSE -- Senão, faz uma pergunta ao usuário.
               V_TITULO := 'Máximo de participantes atingido';
               V_MENSAGEM := 'A etapa "' || V_DESCRETAPA || '" (Tarefa "' || V_DESCRTAREFA || '") já possui ' || V_TOTAL_PARTICIPANTES || ' participantes.\n\nDeseja continuar?';
               V_INCLUIR := ACT_ESCOLHER_SIMNAO(V_TITULO, V_MENSAGEM, P_IDSESSAO, I) = 'S';
           END IF;

           IF V_INCLUIR THEN
               -- Com todos os valores necessários, fazemos a inclusão  
               INSERT
                     INTO AD_TADPTA (
                          CODTAREFA,
                          CODETAPA,
                          CODPARTICIPANTE,
                          NOME
                     ) VALUES (
                          V_CODTAREFA,
                          1,
                          V_PROXIMO_ID_PARTICIPANTE,
                          ACT_TXT_PARAM(P_IDSESSAO, 'NOMEPARTICIPANTE')
                     );
           END IF;
       END LOOP;
END;
/

Com duas Tarefas selecionadas execute novamente a ação, informe o nome do participante e clique em "OK".

Será exibida uma mensagem de confirmação em que o sistema irá informá-lo que há mais de dois participantes.

Isso é feito através da função ACT_ESCOLHER_SIMNAO e durante a execução da rotina. Quando essa função é chamada, o sistema interrompe a ação, exibe o pop-up de confirmação na tela e espera a sua decisão.
Se o botão "Cancelar" for pressionado, a ação é cancelada.
Se o botão "Sim" for o escolhido, a ação é retomada e o retorno da função será "S".
Caso você selecione "Não", o retorno da função será "N".

Essa função recebe 4 argumentos, sendo eles:

  • P_TITULO: O título da janela de confirmação;
  • P_TEXTO: A mensagem de confirmação que será exibida;
  • P_CHAVE: Como dito anteriormente, serve para isolar o ambiente de execução da ação e é recebido como argumento na proc;
  • P_SEQUENCIA: Trata-se de um número inteiro, que serve para identificar a pergunta. Imagine que exista mais de uma chamada à “ACT_ESCOLHER_SIMNAO”, cada uma delas deverá ter um valor diferente para esse parâmetro. Assim, pode-se identificar corretamente as resposta do usuário.

🚧

Importante

Se existirem duas perguntas ACT_ESCOLHER_SIMNAO com mesma P_SEQUENCIA, a resposta da primeira pergunta será repassada para a segunda, e ela ficará sem efeito. A chamada está dentro do loop de registros, usamos a variável I como sequência, a fim da pergunta se repetir a cada registro.

Além da confirmação ACT_ESCOLHER_SIMNAO, existe outra função chamada ACT_CONFIRMAR, que recebe os mesmos argumentos e fará basicamente a mesma coisa. A diferença entre elas, é que não existe uma resposta, em que você pode escolher entre "OK", que nesse caso retoma a execução, ou "Cancelar", que faz a ação ser cancelada, portanto ACT_CONFIRMAR não terá retorno.

Referente ao "PK do registro mestre", quando uma ação é executada em uma tela detalhe, os campos PK da tela pai estarão disponíveis como se fossem parâmetros, podendo ser obtidos através de uma das funções ACT_TXT_PARAM, ACT_INT_PARAM, ACT_DEC_PARAM ou ACT_DTA_PARAM mencionadas acima. É possível utilizar o próprio nome do campo precedido de "MASTER_", assim, ações da aba "Participantes" podem usar, por exemplo, ACT_INT_PARAM(P_IDSESSAO, ‘MASTER_CODTAREFA’) e ACT_INT_PARAM(P_IDSESSAO, ‘MASTER_CODETAPA’).

PK do registro mestre: Completando nossa caixa ferramentas para Stored Procedures, quando uma ação é executada em uma tela detalhe, os campos PK da tela pai estarão disponíveis como se fossem parâmetros, podendo ser obtidos através de uma das funções ACTTXT_PARAM, ACT_INT_PARAM, ACT_DEC_PARAM ou ACT_DTA_PARAM mencionadas acima. O truque aqui, é usar o próprio nome do campo, precedido de **“MASTER, assim, ações da aba “Participantes” podem usar por exemplo, ACT_INT_PARAM(P_IDSESSAO, ‘MASTER_CODTAREFA’) e ACT_INT_PARAM(P_IDSESSAO, ‘MASTER_CODETAPA’).**

📘

Importante

A procedure pode retornar uma mensagem a ser exibida por meio do parâmetro de saída "P_MENSAGEM". Quando existir um valor para esse parâmetro, o Sankhya-Om o exibirá como uma informação:

CREATE OR REPLACE PROCEDURE "STP_CHECK_LIST" (
       P_CODUSU NUMBER,
       P_IDSESSAO VARCHAR2,
       P_QTDLINHAS NUMBER, 
       P_MENSAGEM OUT VARCHAR2
) AS
BEGIN
       P_MENSAGEM := 'A ação foi executada com sucesso!';
END;
/

Dessa forma, a ação será executada.

Como tirar dúvidas?

Para tirar dúvidas e compartilhar informações, use a sala Botões de Ação da comunidade Sankhya Developer.