Pragiva — Tecnologia na prática

FA040INC o ponto de entrada que valida a inclusão no Contas a Receber

FA040INC roda no OK da inclusão do título, sem PARAMIXB, e o .F. barra a gravação. Pelo ExecAuto o log pode trazer só 'Processo invalido'.

Desenvolvimento Referência técnica 4 min de leitura

Assista o vídeo

FA040INC em resumo

Onde fica
FA040Inclu(), dentro do FINA040 (Contas a Receber).
Quando dispara
na validação final da inclusão do título (o “tudo OK” da tela), junto com as outras validações do próprio padrão.
PARAMIXB
não existe. O padrão chama o ponto de entrada sem array.
Retorno
usado — .F. barra a inclusão.
Serve para bloquear?
Sim, na inclusão.
Consulta rápida6 seções

Como não há PARAMIXB, a regra trabalha com o que já está em memória: as variáveis M->E1_* do título que está sendo incluído.

É o equivalente a receber do FA050INC, do Contas a Pagar. O desenho é o mesmo; o que muda é o cTudoOk do receber, que tem um desvio por tipo de título (abaixo).

Para o mecanismo geral de como o padrão chama um PE, veja Ponto de entrada no Protheus.

Como o padrão monta a chamada

O FA040Inclu() não chama o PE na hora. Ele monta uma string de validação (cTudoOk) e a entrega à rotina de inclusão. Se o ponto de entrada estiver compilado, a chamada ExecBlock("FA040INC", .F., .F.) entra nessa string. Nada é passado no quarto parâmetro, por isso não há PARAMIXB.

A string tem um IIF pelo tipo do título:

  • Tipo de adiantamento (M->E1_TIPO dentro da variável de tipos de recebimento antecipado do padrão): valida data de movimento financeiro, lançamento do PCO e FA040VLMV(), e só então chama o PE.
  • Demais tipos: valida o lançamento do PCO e chama o PE. As conferências de amarração de entidades contábeis, valor, ISS e abatimento são somadas dentro desse mesmo ramo, depois do PE.

Depois do IIF, vêm validações comuns aos dois ramos, como F040VlCpos() e FA040Num(). O retorno entra numa expressão lógica com .And.: devolva sempre .T. ou .F., nunca Nil ou outro tipo. Se uma condição anterior reprovar, o PE em princípio nem é chamado (curto-circuito do .And., inferido, não testado no ambiente).

Duas coisas a saber sobre o contexto:

  • A chamada acontece dentro do BEGIN TRANSACTION que o FA040Inclu() abre. Não faça diálogo demorado nem comite nada por conta própria ali.
  • Antes de tudo isso, o FA040Inclu() ainda consulta o F040BLQ (se devolver .F., a rotina sai sem mensagem) e a verificação de data de movimento (F040DTMV, se existir). Ambos rodam antes do FA040INC.

Na tela: .F. mantém o usuário na inclusão

Na inclusão manual o cTudoOk vai para a AxInclui como validação do OK. Um .F. do PE deixa a tela aberta. A regra precisa avisar (Help()): sem mensagem, o botão parece não funcionar.

Por ExecAuto: o que dá para afirmar

O FINA040 declara lF040Auto como Private, verdadeira quando a rotina recebe o array de campos do MsExecAuto. Com ela ligada, o FA040Inclu() segue outro caminho e passa o cTudoOk por dois pontos:

  1. EnchAuto(cAlias, aAutoCab, cTudoOk, nOpc). Se devolver .F., o padrão mostra a ajuda FALHATUDOK e interrompe com lRet := .F..
  2. AxIncluiAuto(cAlias, cTudoOk, ...), que avalia o cTudoOk antes de gravar. Se for falso, a função grava no log Processo invalido, devolve 3 e não grava. Nesse trecho ela não atribui lMsErroAuto.

Para o FA040INC:

  • O título não é gravado quando o PE retorna .F. (verificado em AxIncluiAuto).
  • O log automático traz só Processo invalido, sem a sua mensagem. Quem chama não sabe qual regra barrou.
  • O FA040Inclu() não marca lMsErroAuto por conta própria neste caminho. A EnchAuto é compilada e não dá para conferir se ela avalia o cTudoOk e sinaliza o erro. Então o chamador pode ver lMsErroAuto ainda .F. com o título não gravado.

O jeito seguro é o PE fazer o que ele controla: escrever a causa no log com AutoGRLog() e marcar lMsErroAuto := .T. quando a variável existir. Isso não depende do que a EnchAuto faz. Para ler o log do lado de quem chama, veja MsExecAuto: como descobrir por que a rotina falhou.

Exemplo

Regra de demonstração: títulos de certos tipos não podem ser incluídos sem histórico (). A lista de tipos e a regra são da empresa, não do padrão.

ADVPL / TLPP
#Include "Protheus.ch"

/*/{Protheus.doc} FA040INC
Executado na validacao final da inclusao do titulo (FA040Inclu).
Nao recebe PARAMIXB: le as variaveis de memoria M->E1_*.
@type user function
@return logical, .F. barra a inclusao
/*/
User Function FA040INC()

    Local lRet   := .T.
    Local lAuto  := (Type("lF040Auto") == "L" .And. lF040Auto)
    Local cTipos := "NF /DP "   // tipos da regra de demonstracao
    Local cMsg   := "Informe o histórico do título (E1_HIST) para este tipo."

    // Regra por tipo: os demais tipos seguem sem validacao
    If !Empty(M->E1_TIPO) .And. M->E1_TIPO $ cTipos .And. Empty(M->E1_HIST)
        lRet := .F.

        If lAuto
            // Sem tela: a causa vai para o log do ExecAuto
            AutoGRLog("FA040INC: " + cMsg)
            If Type("lMsErroAuto") == "L"
                lMsErroAuto := .T.
            EndIf
        Else
            Help(" ", 1, "FA040INC",, cMsg, 1, 0)
        EndIf
    EndIf

Return lRet

Repare que o retorno é sempre lógico, que a regra sai sem tocar em nada quando o tipo não é o dela, e que a mensagem tem dois destinos: tela ou log.

Armadilhas

Retornar .F. calado. Na tela o botão OK parece travado; no ExecAuto o chamador só vê Processo invalido.

Esperar PARAMIXB. Não existe. Ler PARAMIXB[1] aqui é erro.

Retornar outro tipo. O retorno entra numa cadeia .And.; Nil ou texto quebra a avaliação.

Abrir diálogo sob ExecAuto. Sem tela, MsgYesNo e similares travam a thread. Decida por lF040Auto.

Aplicar a regra a título que não é seu. O FA040Inclu() também é chamado por outros fluxos, como a substituição de títulos, então o PE pode rodar fora da tela comum. Se a regra vale só para certa origem ou tipo, filtre por M->E1_ORIGEM ou M->E1_TIPO.

Os vizinhos

PEMomentoBloqueia?
F040BLQAntes de tudo, ao entrar na inclusãoSim, sai sem mensagem
FA040INCValidação final da inclusãoSim

O equivalente a pagar é o FA050INC.

Continue por aqui