Resposta rápida
- Mecanismo
- o fonte padrão testa com
ExistBlock()e dispara comExecBlock(). - PARAMIXB
- só existe quando
ExecBlockrecebe um quarto argumento. - Retorno
- só importa quando a chamada é atribuída (
xRet := ExecBlock(...)), nunca quando é comando solto. - Prova de execução
- uma linha de
ConOut()na primeira instrução da função, antes de qualquerReturnantecipado.
Quando um PE “não dispara” ou “não bloqueia”, a causa está numa dessas quatro linhas — raramente na lógica de negócio escrita dentro dele.
Consulta rápida6 seções
Ponto de entrada é um gancho que a TOTVS deixa dentro do fonte padrão: em
posições escolhidas, a rotina pergunta se existe uma User Function com um
nome pré-definido e, se existir, executa.
É o que permite customizar o ERP sem editar o fonte padrão — o seu código vive num fonte separado, no RPO custom, e sobrevive à próxima aplicação de pacote.
Este texto é a base. Ele explica o mecanismo uma vez, para que as páginas de cada ponto de entrada possam ser curtas e falar só do que é específico delas.
As duas linhas que explicam tudo
O padrão faz sempre a mesma coisa:
If ExistBlock("NOME_DO_PE")
xRet := ExecBlock("NOME_DO_PE", .F., .F., aParametros)
EndIfExistBlock()verifica se a funçãoU_NOME_DO_PEexiste no RPO.ExecBlock()executa.- O quarto argumento, quando existe, é o que vira
PARAMIXBdentro da sua função. - O retorno só importa se a rotina padrão atribuir esse retorno a alguma coisa.
Guarde as duas últimas. Elas respondem as duas perguntas que trazem todo mundo
ao Google: “por que não dispara?” e “por que retorno .F. e nada acontece?”.
“Retornei.F. e não bloqueou”
Compare as duas formas como o padrão chama um PE:
Execblock("MT410INC", .F., .F.) // comando: o retorno some
lRet := Execblock("MT410TOK", .F., .F.,{nOpc,aRecnoSE1RA}) // expressão: valeNa primeira, ExecBlock é usado como comando. O que a sua função devolve é
descartado ali mesmo. Retornar .F. não cancela nada, e nenhuma quantidade de
código dentro do PE muda isso.
Na segunda, o retorno é atribuído. Aí sim .F. interrompe a operação.
Não dá para descobrir isso pela documentação: dá para descobrir abrindo o fonte
padrão e olhando se tem um := antes do ExecBlock. É o primeiro lugar para
onde ir quando um PE “não bloqueia”.
E o corolário: se o retorno é usado, sempre retorne lógico explícito.
Esquecer o Return faz o padrão avaliar If lRet .And.... com Nil, e o
comportamento aí depende da versão do engine.
“Compilei e não acontece nada”
Quatro causas, em ordem de frequência:
1. O prefixo U_ escrito à mão. User Function U_MT410INC() compila sem
erro e nunca dispara. O compilador já prefixa U_ sozinho; escrever de novo
cria U_U_MT410INC, e ExistBlock("MT410INC") retorna .F. para sempre.
User Function MT410INC() // certo
User Function U_MT410INC() // compila, nunca roda2. O fonte não está no RPO que o ambiente usa. Compilou contra o RPO
errado, ou o ambiente aponta para outro RpoCustom. Confira no
appserver.ini do ambiente, não no do seu colega.
3. A sessão é antiga. A atualização do RPO passa a valer para novas conexões. Reconecte antes de concluir que não funcionou.
4. Você está no PE errado. O nome existe, compila e roda — só que naquele momento do fluxo, que não é o que você imaginava. É o caso mais chato, porque tudo parece certo. A seção seguinte resolve.
Como provar que ele executou
Esta é a parte que quase não tem resposta escrita, e é a que economiza mais tempo.
ConOut() é o mais barato e o mais confiável. Escreve no console do
Application Server, que vai para o console.log da pasta do serviço. Ponha uma
linha na primeira instrução da função, antes de qualquer Return
antecipado:
ConOut("[MT410INC] " + DtoC(Date()) + " " + Time() + " | Pedido: " + SC5->C5_NUM)Se essa linha não aparece no console.log depois de executar a operação, o PE
não está sendo chamado — e o problema é uma das quatro causas acima, não a sua
lógica. Se aparece, o PE roda e o problema é outro.
FWLogMsg() para o que fica em produção. Carrega nível e origem, então dá
para filtrar depois:
FWLogMsg("INFO",, "MT410INC",,,, "Pedido " + SC5->C5_NUM + " processado")Regra prática: ConOut para depurar, FWLogMsg para deixar.
O teste negativo, que quase ninguém faz. Provar que executou é metade. A outra metade é provar que não executa onde não deve. Se o PE está numa função de inclusão, altere um registro e confirme que o log fica em silêncio. Cancele uma inclusão pela metade e confirme o mesmo. É assim que você descobre que estava no PE errado antes do cliente descobrir.
O que todo ponto de entrada deveria ter
Independente de qual seja:
Chave de desligamento. Um parâmetro no SX6 que desliga a customização sem recompilar. Sem ele, a alternativa em produção é despublicar o fonte às pressas.
If !SuperGetMv("MV_XPVAUD", .F., .F.)
Return
EndIfGetArea e RestArea, inclusive nos caminhos de erro. PE que deixa área
de trabalho deslocada quebra outra rotina, horas depois, sem nenhuma pista
apontando para você.
Local e Static apenas. Public e Private no seu fonte podem
sobrescrever silenciosamente uma variável da rotina padrão com o mesmo nome. O
bug resultante é impossível de rastrear.
Guarda para contexto sem tela. MsgAlert, Pergunte, qualquer
MSDIALOG: sob ExecAuto, job agendado ou integração REST, isso trava a thread
até o timeout do server. Não é erro que aparece no log — é conexão pendurada.
Use IsBlind() para decidir.
Mensagem antes de bloquear. Em PE cujo retorno é usado, devolver .F.
calado faz o botão OK simplesmente não fechar a tela. O usuário abre chamado
dizendo “o sistema travou”.
E o PARAMIXB?
É o assunto que mais gera erro silencioso em ponto de entrada, e ele não é específico de nenhum: está em PARAMIXB: o array que às vezes não é seu.
Para ver o mecanismo aplicado a um caso concreto, com o momento exato do disparo: MT410INC.
Referências
TDNtdn.totvs.com
TDN — Pontos de Entrada
Continue por aqui
- Vídeo
DesenvolvimentoReferência técnica
F340VALOK: o ponto de entrada que barra o OK da compensação a pagar
F340VALOK roda ao clicar OK na lista de títulos da compensação a pagar, recebe a lista em PARAMIXB e, retornando .F., mantém o usuário na lista.
- Vídeo
DesenvolvimentoReferência técnica
F340VLD: o ponto de entrada que barra a compensação no Contas a Pagar
F340VLD roda ao confirmar a primeira tela da compensação a pagar (FINA340), sem PARAMIXB. Retornando .F., a tela não fecha e nenhum título chega a ser listado.