Pular para conteúdo

0021 — Reconciliação por remessa e re-arme na ordem certa — ponteiro do manifesto

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-09 · Decidido em: 2026-09-09

Contexto

O X-Adm rejeita filho sem pai, de forma terminal: cod_retorno 1XX não volta sozinho, e o cliente do ERP só coleta 000 ou 9XX. Quando o coletor leva o item de um pedido num ciclo e o contrato no seguinte, o item morre invisível e o pedido entra no ERP sem conteúdo.

Medido em produção em 2026-09-09 — o mesmo defeito em três pontos da cadeia:

pedido linha rejeitada mensagem do X-Adm pai ausente
260079421 contratos 120 "-Cliente CPF 072.508.149-07 não cadastrado." cliente
260079618 itensped 120 "-Pedido (10738.24) não cadastrado." contrato
260078864 itensped 120 "-Produto para o pedido (260078864) não cadastrado." produto

Onze pedidos, 76 linhas nesse estado, e nenhum aparecia como problema — porque este app reconciliava olhando só o contratos. O 260079618 estava CONFIRMADO com o item em 120.

A causa não é deste repo: a atomicidade do ingest se perde na fronteira do PowerSync, e o coletor não distingue "a linha não chegou" de "a linha não existe". A correção é cross-repo e a decisão de mérito é de outros donos.

Decisão

Este RD é ponteiro. A unidade de entrega passa a ser declarada pelo Integrador — o manifesto de remessa — e este app consome esse contrato:

repo papel spec
integracao/integrador-server declara a remessa no apto do apply; deriva status, bloqueado, resolvido .ia/005-manifesto-de-remessa
integracao/integrador-client só envia ao ERP o conjunto que uma remessa cobre inteira .ia/003-coleta-por-remessa
maxsul/powersync publica as tabelas do manifesto no bucket —
este repo enxerga o pedido travado e o destrava .ia/009-reconciliacao-por-remessa-e-rearme

O que muda aqui:

  1. Reconciliação pela remessa, não por tabela. GET /api/v1/integracao/remessas, duas chamadas dirigidas por rodada. CONFIRMADO ⟺ não há remessa viva e existe ao menos uma ENTREGUE; havendo viva, ela decide (TRAVADA → ERRO_XADM, ABERTA → segue ENVIADO). Isso alcança itensped e formulas, que a rota antiga (/retorno/{tabela}) nunca cobriu — 64 das 76 linhas travadas são fórmulas.
  2. A mensagem reportada é a do item não-bloqueado. O Integrador marca como bloqueado o filho cujo pai está morto; reportar o colateral faria o operador ler "Pedido não cadastrado" quando a causa é "Cliente não cadastrado".
  3. Pedido já CONFIRMADO volta à mesa quando a remessa dele está TRAVADA — sem isso os onze travados nunca seriam reclassificados.
  4. O re-arme migra para depois da entrega confirmada (PushEnviador, após marcarEnviado), e só para pedido que carrega rejeição terminal. Antes, o botão do painel re-armava no clique enquanto o PUT só sairia até 2 min depois pelo relay — reabrindo a linha no espelho com o dado velho, a ordem que o dono proíbe (api-integrador §6).
  5. Re-import automático: dado novo da PIED sobre pedido em falha o devolve à fila sozinho. (Desde 2026-09-10, só para ERRO de envio: o ERRO_XADM se resolve à mão — revisão da 0006.)
  6. Entrega única sob as duas instâncias: o relay da mensageria passa a rodar sob o advisory lock deste app.

Consequências

  • O valor depende dos outros três repos. Sem o manifesto publicado e sem a coleta por remessa, a reconciliação não acha remessa nenhuma e não muda status — degradação por desenho, mas os onze pedidos seguem invisíveis. Ordem: integrador-server → maxsul/powersync → integrador-client → este repo → re-arme dos travados.
  • O flash do Reimportar mudou para "Enfileirado: a remessa reabre no X-Adm junto com a entrega" — o botão não chama mais o Integrador.
  • GET /retorno/contratos foi aposentado neste app, com o RetornoXadm que o acompanhava. O campo chave_xadm deixa de ser preenchido — e não perde nada: estava nulo nas 21.326 linhas de pied_pedido.
  • mensageria.relay.enabled nasce false: quem agenda o relay é o RelayJob local. Reverter é devolver a property a true e apagar a classe. (Feito em 2026-09-09 — a xadm-mensageria 0.3.4 trouxe a eleição de réplica para dentro da lib; a property voltou a true e a classe saiu. Ver a revisão da decisão 0014.)
  • Divergência de mérito sobre o manifesto se resolve nas specs dos donos, não aqui.