O que causa o erro A260Local no ExecAuto de Transferência de Produtos

Alguma vez, ao fazer o ExecAuto de Transferência de Produtos (MATA261), você se deparou com o erro A260Local? Saiba as situações que podem ocasionar esse erro no artigo de hoje.

Essa validação (A260Local), ela serve para verificar se o produto existe no armazém de destino, então teoricamente deve existir um registro na SB2 com essas informações. Mas e quando o registro existe, e o problema persiste?

Vamos pegar o cenário de teste que montei aqui, tenho um produto com o código F0001, e estou transferindo 1 quantidade do armazém 01 para o armazém 02, ai ele deu a mensagem de erro, conforme o print abaixo:

Mensagem do Erro

 

Fui consultar então no SQL como que estava a SB2, pois se fosse o caso, seria necessário criar um Saldo Inicial, porém já existia o produto nos dois armazéns (tanto origem como destino):

Existe na SB2

 

Então o que estava causando o bug? Comecei a investigar, até que lembrei, que o Seek da SB2, é Filial + Produto + Armazém, então cogitei essa hipótese, de que na função padrão, ele tenta posicionar a informação, só que não consegue devido a falta de espaços (conforme citado nesse artigo – Por qual motivo NUNCA devemos usar Trim em Seeks).

Notem abaixo, como que esta a variável cProduto, e como ela deveria estar (usando a função AvKey):

Exemplo do produto com espaços a direita

 

O que aconteceu então, é que no Execauto, estava passando a variável cProduto e ela estava indo como “F0001”, e ai na validação do armazém, ele tentou procurar o registro “F000102” e não encontrou.

Por isso, para resolver esse problema, nós precisamos enviar no ExecAuto o produto com todos os espaços a direita conforme o tamanho do seu B1_COD, então na minha base o código do produto ficaria “”F0001          ” e assim, a pesquisa na SB2 pela validação padrão ficará “F0001          02”.

Então apenas com essa tratativa de adicionar os espaços a direita, a rotina do ExecAuto da MATA261 já passa a funcionar normalmente sem acusar esse erro de A260Local.

Abaixo o código fonte desenvolvido para o exemplo:

//Bibliotecas
#Include "TOTVS.ch"

/*/{Protheus.doc} User Function zTestar
Função de teste
@type  Function
@author Atilio
@since 20/06/2023
/*/

User Function zTestar()
    Local aArea := FWGetArea()
    Local aAuto := {}
    Local cDocumen := {}
    Local cProduto := "F0001"
    Local cArmOrig := "01"
    Local cArmDest := "02"
    Local nOpcAuto
    Private lMsErroAuto := .F.

    //Adiciona espaços a direita, conforme o tamanho do campo
    cProduto := AvKey(cProduto, "B1_COD")

    //Posiciona no produto
    DbSelectArea("SB1")
    SB1->(DbSetOrder(1)) // B1_FILIAL + B1_COD
    If SB1->(MsSeek(FWxFilial("SB1") + cProduto))
        //Pega o documento e a data logada atual
        cDocumen := GetSxeNum("SD3","D3_DOC")
        aAdd(aAuto, {cDocumen, dDataBase})

        //Origem
        aLinha := {}
        aadd(aLinha,{"D3_COD",     cProduto,     Nil}) //Cod Produto origem
        aadd(aLinha,{"D3_DESCRI",  SB1->B1_DESC, Nil}) //descr produto origem
        aadd(aLinha,{"D3_UM",      SB1->B1_UM,   Nil}) //unidade medida origem
        aadd(aLinha,{"D3_LOCAL",   cArmOrig,     Nil}) //armazem origem
        aadd(aLinha,{"D3_LOCALIZ", "",           Nil}) //Informar endereço origem
        
        //Destino
        aadd(aLinha,{"D3_COD",     cProduto,     Nil}) //cod produto destino
        aadd(aLinha,{"D3_DESCRI",  SB1->B1_DESC, Nil}) //descr produto destino
        aadd(aLinha,{"D3_UM",      SB1->B1_UM,   Nil}) //unidade medida destino
        aadd(aLinha,{"D3_LOCAL",   cArmDest,     Nil}) //armazem destino
        aadd(aLinha,{"D3_LOCALIZ", "",           Nil}) //Informar endereço destino
        
        //Outros campos
        aadd(aLinha,{"D3_NUMSERI", "",           Nil}) //Numero serie
        aadd(aLinha,{"D3_LOTECTL", "",           Nil}) //Lote Origem
        aadd(aLinha,{"D3_NUMLOTE", "",           Nil}) //sublote origem
        aadd(aLinha,{"D3_DTVALID", '',           Nil}) //data validade
        aadd(aLinha,{"D3_POTENCI", 0,            Nil}) //Potencia
        aadd(aLinha,{"D3_QUANT",   1,            Nil}) //Quantidade
        aadd(aLinha,{"D3_QTSEGUM", 0,            Nil}) //Seg unidade medida
        aadd(aLinha,{"D3_ESTORNO", "",           Nil}) //Estorno
        aadd(aLinha,{"D3_NUMSEQ",  "",           Nil}) //Numero sequencia D3_NUMSEQ
        aadd(aLinha,{"D3_LOTECTL", "",           Nil}) //Lote destino
        aadd(aLinha,{"D3_NUMLOTE", "",           Nil}) //sublote destino
        aadd(aLinha,{"D3_DTVALID", '',           Nil}) //validade lote destino
        aadd(aLinha,{"D3_ITEMGRD", "",           Nil}) //Item Grade
        aadd(aLinha,{"D3_CODLAN",  "",           Nil}) //cat83 prod origem
        aadd(aLinha,{"D3_CODLAN",  "",           Nil}) //cat83 prod destino
        aAdd(aAuto, aLinha)

        //Aciona a inclusão de uma transferência múltipla
        nOpcAuto := 3
        MSExecAuto({|x, y| MATA261(x, y)}, aAuto, nOpcAuto)

        //Se houve erro, mostra a mensagem
        If lMsErroAuto
            MostraErro()

        //Se deu tudo certo, efetiva a numeração
        Else
            ConfirmSX8()
            FWAlertSuccess("Transferência realizada com sucesso!", "Sucesso")
        EndIf
    EndIf

    FWRestArea(aArea)
Return

Referências:

 

Bom pessoal, por hoje é só.

Abraços e até a próxima.

Dan (Daniel Atilio)
Cristão de ramificação protestante. Especialista em Engenharia de Software pela FIB, graduado em Banco de Dados pela FATEC Bauru e técnico em informática pelo CTI da Unesp. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor e mantenedor do portal Terminal de Informação.

Deixe uma resposta

Terminal de Informação