Pragiva — Tecnologia na prática

MT103ENEG libera a exclusão da nota que deixaria o saldo negativo

MT103ENEG só roda quando MV_ESTNEG não é S, recebe o alias do SD1 e decide com .T. ou .F. se a exclusão do documento de entrada segue. Veja quando ele não é chamado.

Desenvolvimento Referência técnica 4 min de leitura

Assista o vídeo Ver o fluxograma

MT103ENEG em resumo

Onde fica
função A103ValEstNeg(), chamada pela validação de exclusão do documento de entrada (MaCanDelF1()).
Quando dispara
na exclusão da nota, quando o saldo do produto no armazém ficaria negativo (ou menor que a reserva) e MV_ESTNEG não é S.
PARAMIXB
{cAliasSD1}, o alias do item que está sendo validado.
Retorno
usado. Tem de ser lógico: .T. deixa a exclusão seguir, .F. (ou qualquer outro tipo) a barra.
Serve para bloquear?
Ao contrário: o padrão já bloqueia. Este PE serve para liberar.
Consulta rápida7 seções

Sem o PE, o padrão mostra o aviso “O saldo do produto/local ficará negativo após a exclusão” e aborta. Com o PE compilado, o aviso some e quem decide é você.

Quando ele é chamado, e quando não é

O cálculo é feito item a item: o padrão parte de do produto e armazém e subtrai de cada item da nota. Se o item veio de ordem de produção ou está em trânsito, soma de volta a quantidade do movimento correspondente na SD3. Se o resultado ficar negativo, ou menor que , entra a regra de estoque negativo:

NãoSimSimNãoSimNãoNãoSimSimNãoNãoSimExclusão do documento de entradaSaldo do SB2 após excluirfica negativo ou abaixo da reserva?Segue a exclusãoMV_ESTNEG = S?Padrão: aviso e confirmação,ou bloqueio se tem rastro oulocalizaçãoRotina automátical103Auto?Não chama o PE e reaproveita oúltimo resultado,que começa em .F.PE MT103ENEG existe?Aviso e bloqueioProduto com rastroe sem localização?XExecBlock MT103ENEGRetornou lógico?.T. libera, .F. bloqueia

Três saídas que o PE nunca vê:

  • igual a S. O padrão tem o próprio tratamento (pergunta “Continua?” para produto sem rastro e sem localização; bloqueio para produto com rastro ou localização). O PE não entra.
  • Exclusão por rotina automática (l103Auto verdadeiro). O padrão não chama o PE e não mostra mensagem. Ele reaproveita o último resultado guardado na validação: começa em .F., e só muda quando o PE é chamado para algum item. Numa nota de um item, ou quando nenhum item anterior passou pelo PE, a exclusão é barrada mesmo com o PE compilado. Numa nota de vários itens, esse resultado vem de uma chamada anterior, e não de uma avaliação do item atual. Teste esse cenário antes de contar com ele.
  • Produto com controle de lote e sem controle de endereço. Para esse produto o PE também não é chamado e o resultado é .F.. O comentário no fonte diz que o produto não poderá ter lote ou localização; pelo código, o que escapa do PE é exatamente a combinação rastro sem localização.

Existe ainda o parâmetro : se verdadeiro, todo esse bloco de verificação de saldo é pulado.

Armadilha: o retorno é a decisão inteira

O padrão faz lRet := ExecBlock(...) e só reconhece tipo lógico. Se o seu PE terminar sem Return, ou retornar Nil, número ou texto, o padrão assume .F. e bloqueia a exclusão, sem mostrar mensagem. O resultado é um PE “que não libera nada”, sem erro que aponte o motivo.

O oposto também vale: Return .T. incondicional permite excluir qualquer nota que deixaria o estoque negativo, para qualquer produto e armazém. Restrinja pela sua regra.

Como é o único ponto onde o aviso do padrão é suprimido, mostre uma mensagem quando você bloquear. Retornar .F. calado deixa o usuário sem explicação.

O que ele recebe

PARAMIXB[1] é o alias (texto) da área de trabalho do item de nota. Pode ser a própria SD1 ou uma consulta temporária, então não use SD1-> direto: leia pelo alias, como (cAlias)->D1_COD. O posicionamento é no item que gerou a validação; o PE é chamado de novo para cada item que ficar negativo.

Exemplo

A regra do exemplo: liberar a exclusão apenas quando o item está num armazém listado num parâmetro, por exemplo um armazém de consignação onde o saldo negativo é aceito.

ADVPL / TLPP
#Include "Protheus.ch"

/*/{Protheus.doc} MT103ENEG
Chamado ao excluir a nota de entrada quando o saldo ficaria negativo
e MV_ESTNEG nao e S. Libera so para armazens listados em parametro.
@type function
@param PARAMIXB[1], character, alias do item de nota em validacao
@return logical, .T. libera a exclusao; .F. mantem o bloqueio
/*/
User Function MT103ENEG()

    Local aArea    := GetArea()
    Local cAlias   := ""
    Local cLocal   := ""
    Local cProd    := ""
    Local cLiberar := ""
    Local lRet     := .F.

    If Type("PARAMIXB") <> "A" .Or. Len(PARAMIXB) < 1 .Or. ValType(PARAMIXB[1]) <> "C"
        RestArea(aArea)
        Return .F.
    EndIf

    cAlias   := PARAMIXB[1]
    cLocal   := (cAlias)->D1_LOCAL
    cProd    := AllTrim((cAlias)->D1_COD)
    cLiberar := SuperGetMv("MV_XARMNEG", .F., "")

    If !Empty(cLiberar) .And. cLocal $ cLiberar
        lRet := .T.
    Else
        // O padrao nao mostra o aviso quando o PE existe: avise aqui.
        Help(" ", 1, "MT103ENEG",, ;
            "A exclusao deixaria o saldo do produto " + cProd + ;
            " no armazem " + cLocal + " negativo.", 1, 0)
    EndIf

    RestArea(aArea)

Return lRet

O Return .F. do início cobre o caso de PARAMIXB inesperado e mantém o comportamento seguro: bloquear. O Help só aparece no ramo em que a regra não liberou.

Parâmetros

MV_ESTNEG é o que decide se o PE entra em cena: o fonte compara o conteúdo com S. MV_XARMNEG é do exemplo (parâmetro de cliente, a criar, caractere): guarda os códigos de armazém concatenados, como 0102, e o exemplo testa com $. Funciona porque o armazém tem dois caracteres; se o seu tiver tamanho diferente, compare por outro critério.

Confira no seu ambienteSQL
SELECT X6_VAR, X6_TIPO, X6_DESCRIC, X6_CONTEUD
  FROM SX6010
 WHERE X6_VAR IN ('MV_ESTNEG', 'MV_NEGATBF', 'MV_XARMNEG')

A consulta mostra o cadastro no seu ambiente. Ela não diz qual rotina lê o parâmetro; isso vem do comportamento descrito acima.

Solução de problemas

SintomaCausa provávelCorreção
PE compilado, mas a exclusão continua barradaMV_ESTNEG é S, ou a exclusão vem por rotina automática, ou o produto tem lote e não tem endereçoConferir os três casos; nos dois últimos o PE não é chamado
Exclusão barrada e sem avisoPE devolveu Nil ou valor não lógicoGarantir Return lógico em todos os caminhos
Aviso do padrão sumiu e a exclusão foi barradaPE existe e devolveu .F. sem mensagemExibir Help antes de devolver .F.

Os vizinhos

Para o fim do documento de entrada depois de gravar, veja o MT103FIM. Para o mecanismo geral, veja Ponto de entrada no Protheus e PARAMIXB.

Continue por aqui