Resposta rápida
- Onde fica
- Configurador, rotina de Gatilhos (
CFGX037), gravado naSX7. - Quando age
- ao preencher o campo de origem, atualiza o campo de destino — o contradomínio.
- Tipos
Pprimário,Eestrangeiro,Xposicionamento.- Diagnóstico mais barato
.F.na condição desliga o gatilho sem apagá-lo.- Armadilha
- gatilho que lê tabela posicionada por outro gatilho depende da sequência.
Consulta rápida7 seções
O usuário digita o produto e a descrição aparece. Digita a data de
nascimento e a idade se calcula. Nenhuma linha de código na rotina: quem faz
isso é um registro na SX7, o dicionário de gatilhos. Este texto mostra o que
cada coluna desse registro decide, usando gatilhos reais do pedido de venda, e
monta o gatilho de idade do cadastro de motoristas desta série.
Anatomia de um gatilho
| Coluna | O que decide |
|---|---|
X7_CAMPO | O campo de origem — o que o usuário preenche |
X7_SEQUENC | A sequência. Um campo pode ter vários gatilhos: 001, 002… |
X7_REGRA | A expressão AdvPL cujo resultado vai para o destino |
X7_CDOMIN | O contradomínio — o campo que recebe o valor |
X7_TIPO | P, E ou X (abaixo) |
X7_SEEK | S para posicionar numa tabela antes de avaliar a regra; N para não posicionar |
X7_ALIAS | A tabela a posicionar |
X7_ORDEM | O índice usado no posicionamento |
X7_CHAVE | A expressão da chave de busca |
X7_CONDIC | Expressão lógica: o gatilho só age quando ela é verdadeira |
X7_PROPRI | Quem é dono do gatilho — S nos do padrão |
Os três tipos
Pela documentação da TOTVS da rotina de gatilhos:
| Tipo | Nome | Para quê |
|---|---|---|
P | Primário | Atualizações visuais e externas do mesmo arquivo |
E | Estrangeiro | Atualizações de dados em outros arquivos |
X | Posicionamento | Posicionar o arquivo do alias sem atualizar nada — para estabelecer relacionamento entre arquivos |
Na prática, quase tudo é P: é o tipo da grande maioria dos gatilhos do
dicionário padrão, e é o que você usa quando um campo da tela preenche outro
campo da mesma tela.
Gatilhos reais: o produto do pedido de venda
C6_PRODUTO tem uma fila de gatilhos no padrão. Três deles mostram as três
formas de buscar dado:
Sequência 001 — C6_PRODUTO → C6_CLASFIS
| Coluna | Valor |
|---|---|
X7_REGRA | CodSitTri() |
X7_SEEK | S |
X7_ALIAS / X7_ORDEM | SF4 / 01 |
X7_CHAVE | a expressão abaixo |
X7_CONDIC | vazio |
IIf(!Empty(SB1->B1_TS),xFilial("SF4")+SB1->B1_TS,xFilial("SF4")+M->C6_TES)Sequência 002 — C6_PRODUTO → C6_CODLAN
| Coluna | Valor |
|---|---|
X7_REGRA | SF4->F4_CODLAN |
X7_SEEK | N |
X7_CONDIC | vazio |
Sequência 007 — C6_PRODUTO → C6_CC
| Coluna | Valor |
|---|---|
X7_REGRA | a expressão abaixo |
X7_SEEK | N |
X7_CONDIC | A410ENTCTB() |
Posicione('SB1',1,xfilial('SB1')+M->C6_PRODUTO, 'B1_CC')Seek no próprio gatilho (001). Com X7_SEEK = S, o gatilho posiciona a
SF4 pela ordem 1 com a chave de X7_CHAVE e só então avalia a regra. A
regra pode então ler campos da tabela posicionada.
Carona no posicionamento anterior (002). A regra lê SF4->F4_CODLAN sem
posicionar nada. Ela depende de a SF4 já estar no registro certo — e, na
prática, quem acabou de posicioná-la foi a sequência 001, que vem antes. A
documentação não descreve a ordem de execução; o padrão, aqui, conta com ela.
É a armadilha da ficha: trocar a ordem das sequências, ou desligar a 001,
faz a 002 ler o registro que estiver lá — sem erro nenhum.
Busca dentro da regra (007). Posicione() faz o posicionamento e devolve
o campo numa expressão só, sem usar X7_SEEK. É o estilo mais fácil de ler e
o que não depende de ninguém. A condição A410ENTCTB() limita quando o
gatilho age.
M->: o valor que está na tela
Na sequência 007, a regra usa M->C6_PRODUTO; na 001, o M->C6_TES está na
chave de busca, não na regra; a 002 não tem M-> em coluna nenhuma. A página
da rotina de gatilhos é direta: no tipo P, referências a campos do próprio
arquivo devem ser precedidas de M->, que representa a variável de memória —
o exemplo dela é M->C6_QTDVEN. É a mesma notação que a RegToMemory cria
quando coloca uma tabela em memória para edição. SC6->C6_PRODUTO, sem o
M->, é o campo do registro posicionado na tabela.
Regra de bolso: o campo que o usuário está preenchendo se lê com M->; o
campo de uma tabela posicionada se lê com ALIAS->.
O gatilho de idade do cadastro de motoristas
Na ZA1, preencher ZA1_NASC deve calcular ZA1_IDADE. O padrão já tem esse
gatilho, pronto para copiar a forma: no dicionário padrão, o campo de data de
nascimento BTS_DATNAS preenche BTS_IDADE com
If(Empty(M->BTS_DATNAS),0,DateDiffYear(dDataBase,M->BTS_DATNAS)). Adaptado:
| Coluna | Valor |
|---|---|
X7_CAMPO | ZA1_NASC |
X7_SEQUENC | 001 |
X7_REGRA | If(Empty(M->ZA1_NASC), 0, DateDiffYear(dDataBase, M->ZA1_NASC)) |
X7_CDOMIN | ZA1_IDADE |
X7_TIPO | P |
X7_SEEK | N |
X7_CONDIC | vazio |
Por que cada peça:
dDataBase, nãoDate().dDataBaseé a data-base informada no login;Date()é a do servidor. Se o usuário trabalha com data-base retroativa, a idade deve ser a daquela data (Tipos de dados em AdvPL).DateDiffYear()é função do padrão. Ela devolve os anos completos entre as duas datas, inteiros, olhando mês e dia: aniversário que ainda não chegou não conta. A ordem dos parâmetros não importa.If(Empty(...), 0, ...)evita calcular com data vazia quando o usuário apaga o campo.
O gatilho só roda quando o ZA1_NASC é preenchido ou alterado. Como o
ZA1_IDADE da série é real, o banco guarda a idade na data do cadastro, e ela
não acompanha os aniversários. No padrão, o BTS_IDADE é virtual e não ocupa
coluna no banco. Para mostrar sempre a idade atual, o caminho é um campo
virtual.
A tentação é fazer a conta à mão, porque data menos data dá número de dias:
Int((dDataBase - M->ZA1_NASC) / 365.25). Erra no dia do aniversário. De
26/09/2000 a 26/09/2026 são 9.496 dias; dividido por 365,25 dá 25,998, e o
Int() devolve 25. A pessoa fez 26 naquele dia. DateDiffYear() devolve 26.
Numa tela MVC, o gatilho do dicionário vem junto com a estrutura do campo.
Segundo a Central de Atendimento TOTVS, não há como retirá-lo da rotina; a
saída indicada é condicionar a execução. O cadastro da ZA1 é MVC e aparece no
próximo artigo,
onde se confere a idade saindo sozinha.
.F. na condição: o interruptor de diagnóstico
Uma tela está trazendo valor errado num campo, ou travando ao sair de um campo, e há seis gatilhos no caminho. Qual deles?
A condição é avaliada antes: se ela for falsa, o gatilho não age. Então
.F. em X7_CONDIC desliga aquele gatilho sem apagar o registro. Desligue um
de cada vez, repita a digitação, e o culpado aparece. O próprio padrão tem
gatilhos com .F. na condição — o recurso é legítimo.
O uso produtivo da condição é restringir. A documentação da rotina dá o
exemplo de um gatilho de L2_PRODUTO que só deve rodar no módulo 12, o
SIGALOJA: a condição testa o módulo, e o gatilho fica quieto nos demais. É o
mesmo papel do A410ENTCTB() no gatilho 007 do produto. E é a saída que a
Central de Atendimento indica para o gatilho que não deve agir numa rotina
MVC específica.
Se o gatilho simplesmente não dispara, confira também o campo de origem na
SX3: nos campos do padrão que têm gatilho (C6_PRODUTO, A1_EST),
X3_TRIGGER vem S. Compare com o seu.
Confira no seu ambiente
Todos os gatilhos de um campo, na ordem em que estão cadastrados:
SELECT X7_SEQUENC, X7_REGRA, X7_CDOMIN, X7_TIPO, X7_SEEK,
X7_ALIAS, X7_ORDEM, X7_CHAVE, X7_CONDIC, X7_PROPRI
FROM SX7010
WHERE X7_CAMPO = 'C6_PRODUTO'
AND D_E_L_E_T_ = ' '
ORDER BY X7_SEQUENCO sufixo 010 é o da empresa; troque pelo do seu ambiente. Para a pergunta
inversa — “quem está escrevendo neste campo?” — filtre pelo destino:
SELECT X7_CAMPO, X7_SEQUENC, X7_REGRA, X7_CONDIC
FROM SX7010
WHERE X7_CDOMIN = 'C6_CC'
AND D_E_L_E_T_ = ' '
ORDER BY X7_CAMPO, X7_SEQUENCEssa segunda é a que resolve o “o campo muda sozinho e ninguém sabe por quê”.
Se uma tela sua tem gatilho em cascata que ninguém consegue explicar, fale com a gente.
Referências
TDNtdn.totvs.com
TDN — Gatilhos (CFGX037 - SIGACFG)Tipos P, E e X; sequência, domínio, regra, posiciona e condição; M-> no tipo P.TDNtdn.totvs.com
TDN — RegToMemory, variáveis de memóriaA função que coloca uma tabela em memória para edição (M->).Central de Atendimentocentraldeatendimento.totvs.com
Central de Atendimento TOTVS — Retirar o gatilho (SX7) de uma rotina MVCGatilho do dicionário não é removido da estrutura MVC; a saída indicada é condicionar a execução.
Continue por aqui
- Vídeo
ProtheusTutorial
Pastas e agrupamentos: organizando a tela do cadastro
Pastas e agrupamentos no cadastro do Protheus: pasta é a aba, agrupamento divide os campos na tela. Onde cada um mora (SXA, X3_FOLDER, X3_AGRUP).