No artigo de hoje vamos demonstrar em como atualizar a tabela SYD, com os dados de NCMs.
A lógica aqui é a seguinte:
- O primeiro passo, é exibido uma pergunta se deseja confirmar
- É feito o download do JSON com as nomenclaturas automaticamente no link https://portalunico.siscomex.gov.br/classif/api/publico/nomenclatura/download/json?perfil=PUBLICO
- Através da classe JSONObject é convertido o texto para uma variável em AdvPL
- A chave Nomenclaturas é atribuída em outra variável (jNomenclat) e é feito um laço de repetição em todas as nomenclaturas (incrementando uma régua de progresso)
- Se a nomenclatura tiver 8 caracteres (sem os pontos) e não existir na SYD, irá acionar o execauto de inclusão (o nome do execauto é MVC_EICA130)
- No final é exibido uma mensagem de log com os sucessos ou falhas (as falhas é gravado um log na pasta \x_logs\ dentro da Protheus Data)
Abaixo o código fonte desenvolvido, conforme a lógica descrita acima.
//Bibliotecas
#Include "TOTVS.ch"
/*/{Protheus.doc} User Function zImpSYD
Função para atualizar a tabela de NCM no Protheus
@type Function
@author Atilio
@since 12/11/2022
@obs A atualização é baseada no JSON disponível para download em:
https://www.gov.br/receitafederal/pt-br/assuntos/aduana-e-comercio-exterior/classificacao-fiscal-de-mercadorias/download-ncm-nomenclatura-comum-do-mercosul
/*/
User Function zImpSYD()
Local aArea := FWGetArea()
//Se a pergunta for confirmada
If FWAlertYesNo("Deseja atualizar a tabela de NCMs no Protheus?", "Continua")
Processa({|| fImporta() }, 'NCMs...')
EndIf
FWRestArea(aArea)
Return
Static Function fImporta()
Local cLinkDown := "https://portalunico.siscomex.gov.br/classif/api/publico/nomenclatura/download/json?perfil=PUBLICO;charset=iso-8859-1" //Dica do charset enviada por João
Local cTxtJson := ""
Local cError := ""
Local jImport
Local jNomenclat
Local jNCMAtu
Local nNCMAtu := 0
Local cCodigo := ""
Local cDescric := ""
Local aDados := {}
Local cLog := ""
Local nLinhaErro := 0
Local nTamDescri := TamSX3("YD_DESC_P")[01]
//Variáveis para log do ExecAuto
Private lMSHelpAuto := .T.
Private lAutoErrNoFile := .T.
Private lMsErroAuto := .F.
//Baixa o JSON disponível
cTxtJson := HttpGet(cLinkDown)
//cTxtJson := FWNoAccent(cTxtJson) //Dica do João, será tratado direto na variável cDescric
//Se houver conteúdo
If ! Empty(cTxtJson)
jImport := JsonObject():New()
cError := jImport:FromJson(cTxtJson)
DbSelectArea("SYD")
SYD->(DbSetOrder(1)) // YD_FILIAL + YD_TEC + YD_EX_NCM + YD_EX_NBM + YD_DESTAQU
//Se não tiver erro no parse
If Empty(cError)
jNomenclat := jImport:GetJsonObject('Nomenclaturas')
//Percorre os NCM
nTotal := Len(jNomenclat)
ProcRegua(nTotal)
For nNCMAtu := 1 To nTotal
IncProc("Processando registro " + cValToChar(nNCMAtu) + " de " + cValToChar(nTotal) + "...")
//Pegando o NCM atual, o código e a descrição
jNCMAtu := jNomenclat[nNCMAtu]
cCodigo := jNCMAtu:GetJsonObject("Codigo")
cDescric := jNCMAtu:GetJsonObject("Descricao")
//Remove caracteres especiais da descrição
cDescric := FWNoAccent(DecodeUTF8(cDescric, "cp1252")) //Dica do João para tratar a acentuação
cDescric := StrTran(cDescric, "-", "")
cDescric := StrTran(cDescric, "<i>", "")
cDescric := StrTran(cDescric, "</i>", "")
cDescric := Alltrim(cDescric)
cDescric := Upper(cDescric) //Dica do João, para gravar tudo em caixa alta padronizado
cDescric := Left(cDescric, nTamDescri) //Dica do Renato, para gravar somente conforme o tamanho do campo no Dicionário
//Removendo os pontos do código
cCodigo := Alltrim(cCodigo)
cCodigo := StrTran(cCodigo, ".", "")
cCodigo := StrTran(cCodigo, "-", "")
//Se o código tiver 8 caracteres e não conseguir posicionar no registro
If Len(cCodigo) == 8 .And. ! SYD->(MsSeek(FWxFilial("SYD") + cCodigo))
aDados := {}
aAdd(aDados, {"YD_TEC", cCodigo, Nil})
aAdd(aDados, {"YD_DESC_P", cDescric, Nil})
aAdd(aDados, {"YD_UNID", "UN", Nil})
//Aciona a inclusão do registro
lMsErroAuto := .F.
MSExecAuto({|x, y| MVC_EICA130(x, y)}, aDados, 3)
//Se houve erro, gera o log
If lMsErroAuto
cPastaErro := '\x_logs\'
cNomeErro := 'erro_syd_cod_' + cCodigo + "_" + dToS(Date()) + '_' + StrTran(Time(), ':', '-') + '.txt'
//Se a pasta de erro não existir, cria ela
If ! ExistDir(cPastaErro)
MakeDir(cPastaErro)
EndIf
//Pegando log do ExecAuto, percorrendo e incrementando o texto
cTextoErro := ""
cTextoErro += "Codigo: " + cCodigo + CRLF
cTextoErro += "Descricao: " + cDescric + CRLF
cTextoErro += "--" + CRLF + CRLF
aLogErro := GetAutoGRLog()
For nLinhaErro := 1 To Len(aLogErro)
cTextoErro += aLogErro[nLinhaErro] + CRLF
Next
//Criando o arquivo txt e incrementa o log
MemoWrite(cPastaErro + cNomeErro, cTextoErro)
cLog += '- Falha ao incluir registro, codigo [' + cCodigo + '], veja o arquivo de log em ' + cPastaErro + cNomeErro + CRLF
Else
cLog += '+ Sucesso no Execauto no codigo ' + cCodigo + ';' + CRLF
EndIf
EndIf
Next
//Se tiver log, mostra ele
If ! Empty(cLog)
cDirTmp := GetTempPath()
cArqLog := 'importacao_' + dToS(Date()) + '_' + StrTran(Time(), ':', '-') + '.log'
MemoWrite(cDirTmp + cArqLog, cLog)
ShellExecute('OPEN', cArqLog, '', cDirTmp, 1)
EndIf
Else
FWAlertError("Houve uma falha na conversão do JSON: " + CRLF + cError, "Erro no Parse")
EndIf
EndIf
Return
Bom pessoal, por hoje é só.
Abraços e até a próxima.



Efetuei alguns ajustes neste fonte devido a atender minhas necessidades, mas acredito que outros poderam ter o mesmo problema.
Na linha 55 foi necessario alterar o link para este link Local cLinkDown := “https://portalunico.siscomex.gov.br/classif/api/publico/nomenclatura/download/json?perfil=PUBLICO;charset=iso-8859-1”, por causa da codificação em que os acentos estão retornando para o advpl.
Na linha 44 comentei esta parte //cTxtJson := FWNoAccent(cTxtJson), devido não estar retirado as informações de acentos corretamente.
Desta forma foi necessario incluir uma linha logo abaixo da linha 73 foi incluido a tratativa da descrição das NCMS cDescric := FWNoAccent(decodeUTF8(cDescric, “cp1252”)), devido a codificação em que os registros são retornados.
Já na linha 84, incrementei desta forma para ficar um padrão na gravação dos dados, aAdd(aDados, {“YD_DESC_P”, UPPER(cDescric), Nil})
Bom dia João, tudo joia?
Opa, ficamos felizes que nosso singelo exemplo tenha lhe ajudado.
E ficamos honrados pela melhoria que foi elaborada por você e gentilmente disponibilizada.
Um grande abraço.
Boa noite! Além de seguir as orientações do João, precisei limitar o tamanho da variável cDescric devido ao campo YD_DESC_P, que suporta apenas 40 caracteres.
//Limita a descrição para 40 caraceteres
cDescric := SubStr(cDescric, 1, 40)
Bom dia Renato, tudo joia?
Opa, obrigado pela contribuição, atualizamos o exemplo, linhas 37 e 77.
Um grande abraço.
Atílio, boa tarde! Muito obrigado pelo retorno. Você já pegou o tamanho na sx3, ficou muito bom. Abraço.
Bom dia Renato, tudo joia?
Opa, nós que agradecemos pelo comentário e feedback.
Um grande abraço.
Muito bom!! Está de parabéns, coisas simples e banais que a totvs poderia implementar.
Bom dia Rodrigo, tudo joia?
Obrigado pelo comentário e carinho, é muita bondade e generosidade sua.
Um grande abraço.
Boa tarde pessoal, não sou DEV e por isso, apenas compilei o cod. fonte acima. Porém, não funcionou. Não cadastrou os NCM’s na Tabela SYD.
Bom dia Marcos, tudo joia?
Faça esse procedimento:
1. Baixe o zMiniForm disponível nesse link: https://terminaldeinformacao.com/2018/02/13/funcao-para-executar-formulas-protheus-12/
2. Compile ele na sua base usando o VSCode
3. Coloque ele no menu, conforme esse tutorial: https://terminaldeinformacao.com/2023/05/31/como-adicionar-uma-rotina-em-um-menu-do-protheus/
4. Abra o zMiniForm e execute a fórmula: u_zImpSYD()
Tenha uma ótima e abençoada terça feira.
Um grande abraço.
Boa tarde,
Sabem informar se há em algum link o JSON já com as alíquotas para alimentar a SYD com as alíquotas também?
Bom dia Wendel, tudo joia?
Infelizmente desconhecemos algum lugar que tenha as alíquotas de NCM em JSON.
Tenha uma ótima e abençoada sexta feira.
Um forte abraço.
Como faço apara atualizar TIPI e II??
Bom dia Maximiliano, tudo joia?
No JSON que vem do Governo, não tem essa informação.
Você precisaria, ou validar se tem alguma página do Governo, ou algum lugar para se basear para atualizar esse campo conforme os NCM.
Ou alinhar com algum consultor fiscal, para ver se ele teria a lista de NCM com a informação para ser atualizada.
Tenha uma ótima e abençoada sexta feira.
Um forte abraço.