Pragiva — Tecnologia na prática

FA070TIT o ponto de entrada que confirma a baixa a receber

FA070TIT recebe o acumulado calculado pelo padrão e o retorno lógico decide a baixa: .F. impede. Chamado na baixa individual e na baixa em lote do FINA070.

Desenvolvimento Referência técnica 4 min de leitura

Assista o vídeo

FA070TIT em resumo

Onde fica
fA070Tit() (baixa individual, opção “Baixar”) e Fa070But() (botão de confirmação da tela de cada título na baixa em lote, opção “Lote”), ambas do FINA070.
Quando dispara
depois de o usuário confirmar a tela de baixa, antes de gravar.
PARAMIXB
{nParciais}, um único numérico.
Retorno
lógico, usado. .F. impede a baixa.
Serve para bloquear?
Sim. É o lugar certo para uma regra de negócio que decide se este título pode ser baixado.
Consulta rápida5 seções

Este ponto de entrada não exibe mensagem por conta própria: quem retorna .F. precisa explicar o motivo, senão a baixa simplesmente não acontece e ninguém sabe por quê.

Para o passo a passo da baixa do lado do operador, veja Baixa de título no Protheus: o que conferir no contas a receber. Para o mecanismo geral de chamada, veja Ponto de entrada no Protheus.

Os dois momentos em que ele dispara

O mesmo nome é chamado em dois lugares do FINA070, e o que muda é o caminho do usuário até ele.

CaminhoFunção que chamaMomento
Baixa individual (menu “Baixar”, ou baixa automática por ExecAuto)fA070Tit()Tela confirmada (OK), depois das validações da data da baixa (fora do intervalo entre a emissão e a data base), de SPB e do valor recebido; antes da checagem de data, motivo e valor vazios ou negativos e da gravação
Baixa em lote (menu “Lote”)Fa070But(), chamada pelo OK da tela de cada títuloCom o OK pressionado, antes da validação de banco e data e da conferência final da baixa (Fa070OK())

No lote, a rotina percorre os títulos do lote e abre a tela de cada um; o PE roda uma vez por título, no OK dele.

O que acontece com o .F. também difere:

  • Individual, com usuário: quando o .F. vem do seu User Function, o padrão volta para a tela para o usuário corrigir os dados. Se só o template do mesmo nome retornar .F., a função devolve .F. sem voltar à tela.
  • Individual, automática: não há tela para voltar; o padrão sai do laço de confirmação e abandona a baixa.
  • Lote: Fa070But() devolve .F. e não segue para a gravação daquele título. O comportamento da tela depois disso não foi verificado.

O que ele recebe

PosiçãoTipoConteúdo
PARAMIXB[1]NumériconParciais: acumulado calculado pelo padrão

Esse é o único dado. Ele não traz o valor que está sendo recebido agora, nem a data, nem o motivo de baixa. O nParciais é calculado pelo padrão a partir das baixas anteriores, com ajustes de adiantamento, de compensação em outras filiais e, conforme a parametrização, de impostos retidos na baixa. Em alguns caminhos equivale a E1_VALOR - E1_SALDO, mas não trate como igual em todos. Como pode incluir esses ajustes, um valor diferente de zero não prova que houve baixa anterior.

O título está posicionado na nos dois caminhos. Para decidir por cliente, tipo ou natureza, leia os campos dela, como SE1->E1_CLIENTE.

Detalhes de como conferir o PARAMIXB antes de ler: PARAMIXB: o array que às vezes não é seu.

A armadilha: o retorno sempre sobrescreve

Nos dois pontos o retorno do ponto de entrada é atribuído direto a lRet, sem combinar com o valor anterior por .And..

Há ainda uma chamada de template antes, que usa o mesmo nome e recebe o mesmo PARAMIXB. Se existir, o resultado dela também vai para lRet, e o seu User Function vem depois e sobrescreve. Então:

  • Retornar .T. por padrão anula a reprovação de um template do mesmo nome.
  • Retorne .T. só quando a sua regra tiver passado ou não se aplicar, e sempre devolva um lógico, sem deixar o retorno ao acaso.

Exemplo

Regra de exemplo: título de cliente inativo no cadastro ( igual a "1", “Inativo” no dicionário padrão) não pode ser baixado. O campo pode ter sido customizado no seu ambiente; confira antes de copiar a regra.

ADVPL / TLPP
#Include "Protheus.ch"

/*/{Protheus.doc} FA070TIT
Confirmação da baixa a receber (FINA070), individual e em lote.
Bloqueia a baixa de título de cliente com bloqueio cadastral.
@type user function
@return logical, .F. impede a baixa
/*/
User Function FA070TIT()

    Local aArea    := GetArea()
    Local aAreaSA1 := SA1->(GetArea())
    Local lRet     := .T.
    Local nParc    := 0

    // PARAMIXB traz só o total já baixado do título.
    If Type("PARAMIXB") == "A" .And. Len(PARAMIXB) >= 1 .And. ValType(PARAMIXB[1]) == "N"
        nParc := PARAMIXB[1]
    EndIf

    // O título está posicionado na SE1, tanto na baixa individual quanto no lote.
    SA1->(DbSetOrder(1))
    If SA1->(DbSeek(FWxFilial("SA1") + SE1->E1_CLIENTE + SE1->E1_LOJA))
        If SA1->A1_MSBLQL == "1"
            lRet := .F.

            // Sem mensagem, a baixa só "não acontece". Em execução
            // automática não há quem responda: registra no console.
            If IsBlind()
                ConOut("[FA070TIT] Baixa negada: cliente bloqueado. Título " + ;
                       SE1->E1_PREFIXO + SE1->E1_NUM + SE1->E1_PARCELA + ;
                       " | já baixado: " + cValToChar(nParc))
            Else
                Help(" ", 1, "FA070TIT",, ;
                    "Cliente bloqueado no cadastro. Baixa não permitida.", 1, 0)
            EndIf
        EndIf
    EndIf

    RestArea(aAreaSA1)
    RestArea(aArea)

Return lRet

O PARAMIXB[1] aparece na mensagem de log para mostrar a leitura; se a sua regra não precisa dele, pode ignorá-lo. A regra em si depende só da SE1 posicionada.

Armadilhas específicas

Bloquear sem mensagem. O padrão não avisa. Use Help() ou equivalente antes de lRet := .F., e ConOut quando a baixa vier de rotina automática.

Abrir diálogo em baixa automática. Na baixa por ExecAuto não há usuário para responder; um MsgYesNo pode travar a thread. Guarde com IsBlind().

Achar que roda uma vez. No lote, roda uma vez por título. Uma consulta pesada aqui se multiplica pelo tamanho do lote.

Achar que ele grava. Ele roda antes da gravação. Se você precisa reagir a uma baixa que já aconteceu, o lugar é outro ponto de entrada.

Esquecer o Return. O retorno vai direto para lRet e é testado com !lRet. Devolva sempre um lógico explícito.

Continue por aqui