Pular para o conteúdo principal

v1.4 — Envio de arquivo em duas etapas, campos novos e erros literais

Atualização do contrato a partir das mudanças de comportamento dos handlers (baseline 20/07 → 06/08), com auditoria completa das 22 famílias de endpoints tocadas no período. Destaques: o envio de planilha em duas etapas passou a ser documentado, vários campos de resposta que já eram devolvidos entraram nos schemas, e cerca de 80 operações tiveram a lista literal de mensagens de erro corrigida ou criada.

✨ Added

  • POST /sku/template e POST /orders/template e POST /job — documentado o fluxo de envio de arquivo em duas etapas, que já é o usado pelo produto e não existia no contrato: Action=RequestUploadUrl devolve UploadUrl, Key, Method, Headers (obrigatórios no envio), SizeBytes e ExpiresIn; em seguida Action=ConfirmUpload com o Key cria o processamento. O envio direto por multipart/form-data continua válido. Reenviar o mesmo arquivo é idempotente: devolve o IDJob já existente.

  • Campos novos de resposta — todos nullable. Já eram retornados pela API; só não estavam no contrato:

    OperaçãoCamposObservação
    POST /user/signin/localToursSeen · Origin
    GET /user/privilege · GET /user/{iduser}ToursSeen
    GET /hub/order/claim/{idhuborderclaim}ClaimAffectsReputationNão é booleano: 1 não afeta, 2 afeta, 3 não se aplica, 0 o canal não informou, null a consulta falhou
    GET /orders/hub/{idorder} · GET /hub/order/{idintegration}SalesChannelLogoUrl · IDConsumer · Index
    GET /orders/hub · GET /company/dashboard/order/statusStatusColorCode
    GET /sku/distribution-centerDistributionCenterIDConsumerList · DistributionCenterConsumerList · IDStockKeepingUnitWarehouseBestBeforeDays · WarehouseBestBeforeDaysName
    GET /type/order/payment/{idtypepayment}/rateAdditionalBusinessDays · AdditionalBusinessDaysPosition · NfTPag · NfTBand · RefundMethodEm AdditionalBusinessDaysPosition: 1 início, 2 final
    GET /sku/inventory-summary/{idstockkeepingunitinventorysummary}ItemsCount · HasNextPageItems · InventoryLogs
    GET /skuQtyReserved · QtyHandling · QtyOnStock · QtyReservedHandling
    GET /sku/movementIDCategory · AbcCurve · MainImageThumbnailURL · Category · CategoryTree
    GET /fulfillment/packing/picking-list/{idpickinglist}KitBarCodeListDentro de cada item
    GET /fulfillment/picking/basketIDPickingListNo histórico do cesto
    GET /orders/{idorder}ExchangeReceiptBase64Encode
  • Query params documentados — existiam e eram lidos pelo handler, mas não estavam no contrato:

    OperaçãoParâmetroPara que serve
    GET /ordersLastIDPaginação por cursor
    GET /orders/hubCreationTimestampFrom · CreationTimestampToRecorte por data de criação
    PUT /orders/{idorder}Resend · TypeMessageReenvio de mensagem ao cliente
    GET /accounts/payableIDTypeCostCenterFiltro por centro de custo
    GET /sku/batchIDCompanySalesPolicyPreço da política informada
    GET /type/order/typeIsTransferSó tipos de transferência
    POST /purchase/{idpurchase}/checkCreateNewPurchaseSentMoreRecebimento a mais gera novo recebimento
    POST /sku/pricing/{idsku}UpdateIfPossibleAtualiza só o que for possível

    Além desses, Page foi documentado em cinco listagens que já paginavam sem dizer.

  • Request bodies modelados onde o contrato trazia corpo vazio ou parcial:

    OperaçãoO que entrou
    POST /ordersCorpo completo, com Items[] e Payments[] detalhados
    POST /consumer · PUT /consumer/{idconsumer}Cadastro de cliente
    PUT /sku/{idsku}Cadastro de SKU
    POST /supplier · PUT /supplier/{idsupplier}Cadastro de fornecedor
    PUT /purchase/{idpurchase} · POST /purchase/{idpurchase}/checkRecebimento e conferência
    POST /sku/pricing/{idsku}Preços
    POST /user/reportRelatório customizado
    POST /company/sales-policyPolítica comercial
    POST /fulfillment/pickingPicking
    POST /hub/warehouseDE-PARA de armazém
    POST /user/signin/localLogin
    PUT /sku/resupply/{idstockkeepingunitresupplylist}Ressuprimento
    POST /purchase/feed/invoice-xmlFeed de NF-e
  • 400 documentado no envio de anexo do HubPOST /hub/order/{idintegration}/action/file e POST /hub/order/claim/{idhuborderclaim}/action/file só declaravam 200. Agora trazem as sete mensagens de recusa: arquivo não enviado, arquivo inválido, falha ao salvar, recusa do canal por extensão/tamanho, canal sem recurso de anexo, pedido de integração não localizado e integração não autenticada.

  • Enums cruzados com os CSVs canônicos: tipos de devolução (31 valores) e categorias e bandeiras de pagamento; CST e modalidade de ICMS na resposta de POST /tax/{idtaxdepartment}/cfop/{idtax}/interstate e do PUT correspondente; status de pedido em GET /company/dashboard/order/status; tipos de SKU em GET /sku e nas demais listagens; e status de pedido de compra e de reserva no detalhamento de saldo.

🔄 Changed

  • GET /sku/balance e GET /sku/{idsku}/warehouse — mudou o significado de QtyReserved e QtyHandling: pedidos do fluxo de orçamento (5056) e 23 Em espera etiqueta passaram a contar como reserva, e 97 Reversa finalizada saiu de manuseio. O total (QtyOnStock) não muda — muda a distribuição.
  • GET /accounts/receivable/marketplace-conciliation — os campos *Pct são frações de 0 a 1 (0,15 = 15%), não percentuais; e o corte de página é aplicado antes do agrupamento, então uma conciliação pode ficar partida entre duas páginas.
  • PUT /hub/product/{idhubproduct} — com SyncVariations=1 a resposta é um objeto (IDHubProduct, TotalUpdates, Results[]), não o anúncio. Falhas individuais não abortam a sincronização.
  • GET /type/order/payment — com OrderReturn=1 a lista começa com um item sintético cujo IDTypePayment é o literal ORIGINAL (deixa de ser numérico).
  • GET /sku/inventory-summary/{idstockkeepingunitinventorysummary} e correlatos — a lista de Items passou a ser paginada em 5000 registros; use Page e confira HasNextPageItems.
  • GET /sku/production/{idstockkeepingunitproduction} — no detalhe da ordem de produção, a lista Items é dos insumos consumidos, não do que foi produzido; as descrições dos campos diziam o contrário. Corrigido um a um. O que a ordem produz está no cabeçalho (IDSku, SkuName, Quantity); Items traz o que saiu do estoque para fabricá-lo, com custo por linha. Vale para as outras sete operações de produção, que devolvem o mesmo detalhe.
  • Cerca de 60 operações tiveram a lista de mensagens [BadRequest] criada ou corrigida com o texto literal do handler — inclui ~25 correções de acentuação (estaestá, excluidoexcluído, codigocódigo) que quebravam tratamento de erro por comparação de texto.

🐛 Fixed

  • DELETE /accounts/receivable/{idaccountreceivable}/payment/{idaccountpayment} — a documentação prometia devolver a conta atualizada; o corpo real vem sempre vazio ([]). A exclusão acontece normalmente — refaça o GET para atualizar a tela. (Defeito de implementação: a recarga usa a chave do lado "a pagar". Reportado ao time.)
  • POST /sku/{idsku}/cost/recalculate — o schema do 200 documentava {status, message}, campos que o handler nunca produziu. O corpo real é {Message} com texto fixo.
  • POST /sku/template — o schema do 200 documentava o envelope interno da integração em vez do corpo entregue ao cliente (IDJob + Message).
  • GET /hub/order/claim/{idhuborderclaim} — os valores de ShippingMethod documentados (carrier, delivered_by_seller) não existem; os reais são mail, entrusted, personal_delivery e email.
  • PUT /companySefazAmbienteNF, SefazAmbienteNFC e SefazAmbienteServiceInvoice estavam marcados como nullable sendo colunas obrigatórias: enviar null faz a gravação falhar.
  • 4 descrições de operação que continham texto de instrução em vez do conteúdo (POST /sku/promotion, PUT /sku/promotion/{idstockkeepingunitpromotion}, abertura e fechamento de caixa) foram restauradas.

🧹 Limpeza de contrato

Itens que a auditoria encontrou documentados sem existir no comportamento real.

  • 500 removido de POST /sku/image/{idsku}, PUT /sku/image/{idsku}/{idimage}, DELETE /sku/image/{idsku}/{idimage}, PUT /accounts/receivable/{idaccountreceivable}, GET /fulfillment/picking/basket, PUT /company e DELETE /consumer/{idconsumer}/voucher/{idconsumervoucher} — nenhum desses fluxos produz erro com o prefixo que o gateway mapeia para 500. O 404 de PUT /consumer/{idconsumer} também saiu pelo mesmo motivo.

  • POST /sku/image/{idsku} declarava corpo no 404 que a resposta não tem.

  • POST /sku/production/{idstockkeepingunitproduction}/finish — o formato declarado do 200 era um array de arrays que a API nunca devolveu. Passou a declarar o detalhe do recebimento, que é o que ela retorna de fato — o mesmo formato de GET /purchase/{idpurchase}.

  • POST /sku/distribution-center e PUT /sku/distribution-center/{idstockkeepingunitdistributioncenter}, e o mesmo par em /purchase/schedule — criação e atualização compartilhavam um único formato de corpo, mas as regras diferem: o que é obrigatório ao criar, e o que a omissão de um campo significa ao atualizar (apagar × manter). Agora cada uma declara o seu, e a descrição de cada campo diz o que a omissão faz.

  • GET /orders/hub e GET /orders/hub/{idorder} — a listagem e o detalhe do pedido integrado estavam descritos por um formato só, que misturava campos dos dois. Agora cada uma declara o que realmente devolve, com a parte comum compartilhada; e os blocos que eram objetos opacos — SKUs, pagamentos, mensagens e reclamações — passaram a apontar para as descrições que já existiam.

    Divergências corrigidas no caminho: ShippingEstimateHandlingLimitDate era date numa e date-time na outra (vale date-time); OrderId estava nullable sem ser; QuantityItems era integer numa e number na outra; CompanyIntegration vem nas duas, não só no detalhe. Entraram StatusColorCode e o enum de IDStatusInvoice. IDCompany e IntegrationLogoUrl saíram — eram documentados na listagem e nenhuma das duas consultas os devolve; o logotipo existe só no detalhe, com o nome SalesChannelLogoUrl.

    GET /hub/order/{idintegration} devolve exatamente o mesmo que GET /orders/hub/{idorder} — era essa duplicidade que mantinha os dois formatos.

✅ Fechado nesta leva

Itens que estavam listados como pendentes e foram resolvidos:

  • PUT /orders/{idorder}/sku/{idskumovement} não devolve o pedido inteiro: devolve um array de um item, em duas formas conforme a apuração de imposto do pedido. Com imposto manual, vem o item completo com todo o cadastro do SKU na mesma linha (177 campos); nos demais casos, o mesmo formato de POST /orders/{idorder}/sku, agora com IDNfCstIbsCbs. Ambas as formas estão declaradas.
  • PUT /orders/{idorder}/payment/{idaccountpayablereceivable} também não devolve o pedido — a rota é atendida pelo mesmo processo de contas a receber, e o corpo é o detalhe do título, igual ao de PUT /accounts/receivable/{idaccountreceivable}.
  • Tipos corrigidos: IDModuleFavorite, no cadastro de usuário (GET /user/{iduser} e correlatas), e IDWarehouseHub, no pedido integrado (GET /orders/hub/{idorder}), são string e não integer.
  • GET /company/dashboard/external e GET /user/signin/external foram descritos no spec de origem. Eles continuam fora da referência publicada por decisão de escopo (rotas de uso exclusivo do app, na lista de exclusão de prepare-spec) — o registro serve para quem lê o contrato interno.

🐞 Validação que virava erro de servidor — corrigido

Afetava POST /job, POST /sku/template, POST /orders/template e POST /sku/{idsku}/cost/recalculate, que compartilham a mesma função.

As validações dessas rotas encerravam a execução com erro em vez de devolver uma resposta, e o API Gateway convertia isso em 502 com o corpo genérico {"message": "Internal server error"}. Na prática, quem errava o envio de planilha ou a ação em massa recebia "erro interno" no lugar da mensagem que dizia o que fazer — eram 100 chamadas por semana terminando assim.

Corrigido nesta versão: as quatro rotas passaram a devolver 400 de verdade, com o texto em errorMessage, para todas as validações. O 400 documentado aqui vale integralmente; não há mais caso que escape como 502.

O mesmo defeito existia, numa única ocorrência, no envio de anexo em mensagem do Hub — POST /hub/order/{idintegration}/action/file e POST /hub/order/claim/{idhuborderclaim}/action/file —, na recusa por integração não autenticada. Também corrigido.

A varredura cobriu as 57 rotas de proxy: as 34 atendidas por PHP já respondiam 400 corretamente, e entre as 10 em Node só essas duas funções tinham o problema.

  • Nos itens do pedido (GET /orders/{idorder}), o campo ReverseTaxCalculation estava com a condição invertida: o texto dizia que os impostos somam quando o valor é 1, e o comportamento soma quando é 0. Corrigido.