API: produtos — o que o sistema preenche sozinho, estoque, variações e bloco fiscal

QUANDO USAR ESTA FONTE

Você cadastra ou edita produto pelo aplicativo API e alguma coisa veio diferente do que mandou: campo preenchido sem você pedir, estoque zerado, preço zero, variação que não bate, bloco fiscal vazio, retorno quase vazio depois de salvar.

Esta fonte trata só do recurso de produtos da API. O cadastro de produto, a grade, a tabela de preço, o NCM, o CEST e a movimentação de estoque, como conceito, se respondem pelas fontes do ERP. Aqui entra só o que a API faz por cima disso.

Duas coisas já ditas em outras fontes da pasta e que não se repetem aqui: produto criado pela API nasce sem variação e sem composição, e a edição preserva o que ele já tem (fonte geral da pasta API); e a lista de campos que trocam de nome entre a API e o ERP (fonte de nomes de campo, filtros e retorno). Quem o token representa está na fonte de usuário, loja e permissões do token.

O QUE A API PREENCHE SOZINHA NO CADASTRO

No cadastro de produto o código grava alguns campos sem perguntar:

Unidade de entrada e unidade de saída. Se a empresa tem uma unidade de produto marcada como padrão, a API usa essa unidade nas duas pontas e ignora a unidade que você tenha mandado no corpo. Se a empresa não tem nenhuma unidade padrão, vale a unidade que você enviou. Sem padrão e sem envio, o cadastro é recusado com "É necessário informar a unidade de medida de entrada!" e código 404 — o produto não é criado.

Quantidade de saída. Vira 1 quando a unidade padrão é aplicada.

Endereço do produto. É montado a partir do nome, em minúsculas e com hífen no lugar dos espaços e acentos. Se esse endereço já existir, o sistema monta outro acrescentando um sufixo.

Valor de custo médio. Recebe uma cópia do valor de custo que você enviou. Sem valor de custo, vai zero.

Código interno. Quando você não manda, o sistema gera um número aleatório. O produto nunca fica sem código.

Emite nota fiscal. Assume 1 quando você não manda o campo, no cadastro e na edição. Guarde este, porque é ele que explica os retornos vazios mais adiante. Na edição isso tem um efeito colateral: um produto marcado como "não emite nota", editado pela API sem esse campo, volta marcado como "emite nota".

Fornecedores. Assume 0 quando você não manda.

ESTOQUE: NÃO EXISTE LANÇAMENTO, EXISTE QUANTIDADE

Não há endereço de entrada e saída de estoque na API. Não dá para lançar movimentação nem dar baixa por ela. Isso é do ERP.

O que existe é o campo estoque dentro do próprio corpo do produto, no cadastro e na edição, junto com estoque_min e estoque_max. Eles gravam direto a quantidade, o mínimo e o máximo, e só da loja da chamada. As outras lojas do usuário ficam com o registro criado e a quantidade intocada.

No cadastro, quando você não manda o campo que diz se o produto movimenta estoque, o sistema assume que movimenta — e a quantidade é gravada normalmente. O que zera a quantidade é mandar esse campo explicitamente desligado: aí a quantidade, o mínimo e o máximo vão a zero mesmo que você tenha mandado número.

Na edição vale o que já está gravado no produto: produto que não movimenta estoque tem a quantidade limpa. E há mais três regras:

Se você não enviar o campo estoque, a API não toca no estoque. Enviar o campo vazio também não conta.

O mínimo e o máximo só entram junto com o estoque. Mandar estoque_min sozinho, sem estoque, não faz nada.

Produto com controle de lote não muda de quantidade pela edição: o sistema mantém a quantidade atual. Quantidade de produto com lote se ajusta pelo ERP.

NO RETORNO, O ESTOQUE É SEMPRE DE UMA LOJA SÓ

Toda leitura de produto devolve o campo estoque. Ele é a soma das linhas de estoque daquele produto em uma loja, e não da empresa inteira. Cada linha de variação também traz o seu próprio estoque, da mesma loja.

Qual loja: na listagem e na consulta de um produto, o parâmetro loja_id (ou loja) na URL define a loja usada para montar estoque e valores do retorno. Sem esse parâmetro, vale a loja que a chamada já resolveu — a do token, quando o token está preso a uma loja. A regra completa está na fonte de usuário, loja e permissões do token.

Por isso estoque zerado em produto que tem estoque quase sempre é loja errada, e não defeito.

O BLOCO DE VARIAÇÕES

A lista variacoes do retorno é montada a partir das linhas de estoque do produto naquela loja. Isso significa que produto sem variação também traz a lista preenchida, com uma linha só, de código igual ao do produto e sem códigos de variação. Se o produto não tem linha de estoque naquela loja, a lista volta vazia e o estoque volta 0.

Cada item tem sempre os mesmos campos:

id, que é o identificador da linha de estoque daquela combinação naquela loja. É esse id que aparece nos valores próprios da variação.

variacao_api_id, que são os códigos das variações que formam a combinação, separados por dois-pontos. Vem vazio em produto sem variação.

codigo, o código daquela combinação.

nome, montado pelo sistema a partir da grade e desses códigos. Você não envia esse nome.

estoque, a quantidade daquela combinação naquela loja.

valores, a lista de preços.

Um detalhe que confunde: valores só é diferente de uma variação para a outra quando a variação está marcada como tendo valores próprios. Quando não está, todas as variações repetem os valores do produto — e a variação marcada que não tiver nenhuma linha de preço nas tabelas daquela loja também repete os do produto.

OS VALORES POR TABELA DE PREÇO

O campo valores traz uma linha por tabela de preço, com tipo_id, nome_tipo, lucro_utilizado, valor_custo e valor_venda.

E aqui está a regra que responde a maior parte dos "o preço veio zero": a API só traz as tabelas de preço vinculadas à loja da chamada. Se nenhuma tabela estiver vinculada àquela loja, valores volta vazio e o valor_venda do produto volta 0. O produto tem preço; a consulta é que não enxerga aquela tabela.

Outro ponto: em produto com variações que têm valores próprios, o valor_venda que aparece na raiz do produto é o da última variação com valores próprios que foi lida, não um preço do produto — e volta 0 se essa última variação não tiver linha de preço. Para produto com variação, use o valores de cada variação, nunca o da raiz.

A edição aceita mudar preço: mandando a lista valores, cada item com tipo_id e valor_venda, a API atualiza o preço daquelas tabelas. Nesse bloco, tipo_id que não existe no produto, item sem tipo_id ou sem valor_venda derrubam a chamada — mas a mensagem específica não sai: vira o 500 genérico "Falha ao editar produto." Se um PUT com valores está dando 500, comece tirando a lista valores para isolar.

GRADES E TABELAS DE PREÇO TÊM CADASTRO PRÓPRIO PELA API

Grade e tabela de preço não se cadastram dentro do produto. Cada uma tem o seu próprio endereço, com consulta, cadastro, edição, visualização e exclusão. Unidade de produto também tem endereço próprio, com os mesmos cinco. Marca de produto é só consulta.

Na tabela de preço, dois campos são obrigatórios. Sem nome, a resposta é 400 com "É obrigatório informar o nome!". Sem lucro, 400 com "É obrigatório informar o lucro!". Vale no cadastro e na edição. Ela também aceita marcar a tabela como padrão e como padrão da loja virtual.

Na grade, o corpo pede o nome da grade e a lista de variações, cada uma com o seu nome. As recusas são 400 e as mensagens são literais: "É obrigatório informar o nome da grade!", "É obrigatório informar os dados de variação!", "É obrigatório informar o nome da variação!" e "Já existe uma variação com este nome na mesma grade!". Esta última é sobre a lista que você mandou: ela dispara quando o mesmo nome aparece duas vezes no próprio corpo, e é verificada antes de salvar qualquer coisa.

O BLOCO FISCAL

O retorno agrupa os campos fiscais em um bloco chamado fiscal, com ncm, cest, peso_liquido, peso_bruto e valor_aproximado_tributos. A correspondência desses nomes com o ERP está na fonte de nomes de campo.

Na entrada, os dois formatos são aceitos: os campos soltos na raiz do corpo, ou dentro do bloco fiscal. Se o mesmo campo vier nos dois lugares, vale o da raiz.

Campo em branco dentro do bloco fiscal é ignorado de propósito. Isso existe para você poder pegar o retorno de uma consulta e reenviá-lo inteiro sem apagar o que já estava gravado. Para limpar um campo fiscal de propósito, mande ele em branco na raiz, fora do bloco.

Na edição, o sistema lê o que já está gravado e mistura com o que você mandou. Mandar só o cest não zera o NCM. E edição sem nenhum campo fiscal não toca no registro fiscal.

O NCM é reduzido a números e procurado na tabela de NCM. Achou, o sistema preenche junto a descrição e os tributos. Não achou, o NCM é gravado assim mesmo, só sem descrição. O CEST segue o mesmo caminho, também reduzido a números.

O QUE COSTUMA DAR ERRADO

Qual loja vale na chamada. A ordem é: se o token está preso a uma loja, é ela e ninguém muda; senão vale o loja_id da URL; se não houver, o loja_id do corpo; se não houver nenhum, a matriz. Na edição, o loja_id da URL passa por uma checagem própria: loja que não seja do usuário do token responde 400 com "Loja inválida!". Um loja_id inválido que venha só no corpo é barrado antes, na entrada da API, com 401 e a mesma frase "Loja inválida!" — situação diferente, tratada na fonte de usuário, loja e permissões do token.

Editei e a resposta veio vazia. Acontece na edição de produto antigo que não tem registro de tributação nenhum: com emite nota fiscal em 1, que é o padrão quando você não manda o campo, a consulta que monta a resposta exige esse registro, não acha e devolve corpo vazio. O produto foi salvo. Para a resposta vir completa, mande junto qualquer campo fiscal — o NCM basta —, que aí a API cria o registro. Produto criado pela API não cai nisso: no cadastro o registro de tributação já nasce junto.

Consulta de um produto devolvendo 404 "Produto não encontrado!". Mesma causa, produto sem registro de tributação, e aqui não adianta mexer em emite nota fiscal: a consulta exige esse registro sempre. O jeito é dar dados fiscais ao produto. Repare que na listagem o mesmo produto aparece normalmente — só a consulta pelo id cai.

"Falha ao salvar dados." Genérica, e o código muda conforme a operação: 404 no cadastro, 400 na edição. Ela aparece quando o ERP recusou o registro. Peça o corpo da chamada, sem credenciais, e confira os obrigatórios do cadastro de produto do ERP.

"Falha ao adicionar produto.", "Falha ao editar produto.", "Falha ao visualizar produto." e "Falha ao listar produtos", com 500. São genéricas: substituem a mensagem original do erro. Não têm diagnóstico próprio. Reproduza a chamada com o corpo mínimo para isolar o campo.

Preço zerado ou lista de valores vazia. Causa: tabela de preço não vinculada à loja da chamada.

Estoque zerado. Causa: loja errada na chamada, ou produto que não movimenta estoque.

Cadastro recusado por unidade de medida. Causa: a empresa não tem unidade de produto marcada como padrão e a chamada não mandou uma unidade.

Depois de editar pela API, o produto apareceu em outra loja. A edição não recebe lista de lojas, e o ERP, sem ela, revincula o produto a todas as lojas do usuário do token. A consulta de um produto não devolve a lista de lojas dele — para conferir, use a tela do ERP.

Quase todo valor volta como texto, inclusive indicador de sim ou não; quem consome precisa converter. As exceções são o estoque, que vem como número por ser uma soma, e o valor_venda da raiz, que vem como o número 0 quando não há valor a mostrar.