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:
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):
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):
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.