Pragiva — Tecnologia na prática

MT100GE2 o ponto de entrada da parcela do Documento de Entrada

Dispara depois da SE2 gravada, uma vez por parcela, sem PARAMIXB em uma das duas telas que o chamam — e o retorno não bloqueia nada.

Desenvolvimento Referência técnica 2 min de leitura

Assista o vídeo

MT100GE2 em resumo

Onde fica
A103AtuSE2(), do MATA103 (tela padrão de Documento de Entrada), e A100Grava(), do MATA100 (tela clássica).
Quando dispara
depois que a parcela já foi gravada na SE2, uma vez por parcela, dentro do laço que percorre aColsSE2.
PARAMIXB
no MATA103, {aColsSE2[nX], nOpcA, aHeadSE2, nX, aColsSE2}. No MATA100, não existe.
Retorno
ignorado nas duas rotinas — a chamada é um comando solto, sem If nem atribuição.
Serve para bloquear?
Não. A parcela já está gravada quando o PE roda.
Consulta rápida4 seções

Para o mecanismo geral de ponto de entrada, veja Ponto de entrada no Protheus. Para o ponto de entrada que roda antes, na gravação do cabeçalho e itens da mesma rotina, veja MT100GRV.

O que ele recebe, e só no MATA103

A chamada que importa hoje é a do MATA103:

ADVPL / TLPP
If lPe100Ge2
    ExecBlock("MT100GE2",.F.,.F.,{aColsSE2[nX],nOpcA,aHeadSE2,nX,aColsSE2})
EndIf
PosiçãoConteúdo
PARAMIXB[1]aColsSE2[nX] — a linha da parcela que acabou de ser gravada
PARAMIXB[2]nOpcA — a operação em curso
PARAMIXB[3]aHeadSE2 — o cabeçalho de campos da SE2, para localizar a posição de cada E2_* em aColsSE2[nX]
PARAMIXB[4]nX — o índice da parcela dentro do laço
PARAMIXB[5]aColsSE2 — o array completo de parcelas, não só a atual

PARAMIXB[1] e PARAMIXB[5][nX] apontam para a mesma linha — é a mesma referência de array, então alterar um dos dois altera o outro. Isso importa porque, neste ponto, a linha já foi gravada: mexer em aColsSE2[nX] depois do ExecBlock não volta para a SE2 sozinho. Quem precisa persistir um campo tem que abrir a SE2 de novo.

Já na tela clássica (MATA100), a chamada não passa nada:

ADVPL / TLPP
If (lMT100GE2)
    ExecBlock("MT100GE2",.F.,.F.)
EndIf

Um User Function MT100GE2() que lê PARAMIXB[1] sem checar o tipo antes quebra a tela clássica, porque ali a variável simplesmente não existe. Detalhes de como PARAMIXB funciona — e por que conferir antes de ler: PARAMIXB: o array que às vezes não é seu.

A armadilha: a parcela já foi gravada

Nas duas rotinas a chamada é solta, sem capturar retorno:

ADVPL / TLPP
ExecBlock("MT100GE2",.F.,.F.,{aColsSE2[nX],nOpcA,aHeadSE2,nX,aColsSE2})

Não há lRet := nem If. Um Return .F. dentro do PE não interrompe nada, e o desenvolvedor que espera bloquear a gravação de uma parcela aqui está no PE errado — quando o MT100GE2 roda, a inclusão da parcela já terminou.

O que o PE serve para fazer é complementar a SE2 depois de pronta: gravar um campo próprio, disparar uma integração, ajustar algo que depende do título já existir. Para isso, a forma correta é reabrir o registro corrente da SE2 com RecLock("SE2", .F.) — sem .T., porque não é inclusão: a parcela deste laço, se recém-gravada pelo padrão, está posicionada e ainda está aberta para edição naquele mesmo fluxo.

Exemplo

ADVPL / TLPP
#Include "Protheus.ch"

/*/{Protheus.doc} MT100GE2
Executado apos a gravacao de cada parcela da SE2, no Documento de Entrada.
Preenche um campo proprio de rastreio a partir do numero do titulo.
@type user function
@return Nil, o retorno nao e avaliado pelo padrao
/*/
User Function MT100GE2()

    Local aArea    := SE2->(GetArea())
    Local aColsSE2 := {}
    Local aHeadSE2 := {}
    Local nPosPref := 0
    Local nPosNum  := 0
    Local nX       := 0

    // No MATA100 (tela classica) o PARAMIXB nao existe: sem essa
    // checagem, o mesmo fonte quebra as duas telas de formas diferentes.
    If Type("PARAMIXB") <> "A" .Or. Len(PARAMIXB) < 5
        RestArea(aArea)
        Return
    EndIf

    aHeadSE2 := PARAMIXB[3]
    nX       := PARAMIXB[4]
    aColsSE2 := PARAMIXB[5]

    nPosPref := AScan(aHeadSE2, {|x| AllTrim(x[2]) == "E2_PREFIXO" })
    nPosNum  := AScan(aHeadSE2, {|x| AllTrim(x[2]) == "E2_NUM" })

    If nPosPref == 0 .Or. nPosNum == 0
        RestArea(aArea)
        Return
    EndIf

    // A parcela ja esta gravada. Para alterar campo dela agora, reabre
    // o registro corrente da SE2 — nao e inclusao.
    RecLock("SE2", .F.)
        SE2->E2_XORIGEM := AllTrim(aColsSE2[nX][nPosPref]) + AllTrim(aColsSE2[nX][nPosNum])
    SE2->(MsUnLock())

    RestArea(aArea)

Return

Armadilhas específicas

Tentar bloquear a gravação aqui. O retorno não é lido. Quem precisa impedir a parcela de ser gerada tem que agir antes, num ponto de entrada de validação — não neste.

Ler PARAMIXB[1] sem checar o tipo. Na tela clássica (MATA100) o array não existe, e a mesma rotina roda nas duas telas.

Reabrir a SE2 com RecLock em modo inclusão. A parcela deste laço já foi gravada; RecLock("SE2", .T.) cria um segundo registro em vez de completar o que já existe.

Assumir que PARAMIXB[1] é a única parcela do lote. aColsSE2[nX] é só a linha atual; se a regra depende de outras parcelas do mesmo título, o array completo está em PARAMIXB[5].

Referências

  1. TDNtdn.totvs.com

    TDN — MATA103, Documento de Entrada

Continue por aqui