Cards e filtros do mapping — hierarquia de confiança
Os 6 cards do mapping editor refletem dimensões granulares (não mutuamente exclusivas): total de campos com origem, com destino, mapeados por IA, mapeados manualmente, sem destino, sem origem. Click no card filtra.
Cards e filtros do mapping editor
A página de detalhe do mapping (\
/edi-hub/[id]\) mostra 6 cards no topo + 7 filtros 1:1 com os cards.Os 6 cards
| Card | Cor | O que conta |
|---|---|---|
| Campos Origem | Azul info | Linhas com \source_field !== null\ |
| Campos Destino | Roxo | Linhas com \destination_field !== null\ |
| Mapeados por IA | Ciano | Linhas com \ai_suggested = true\ (aguarda review humana) |
| Mapeados Manual | Verde | source+destination definidos por humano (!ai_suggested && !ignore) |
| Origem sem Destino | Amarelo | source && !destination (precisa decisão) |
| Destino sem Origem | Vermelho | !source && destination (destino solto) |
Importante: essas categorias não são mutuamente exclusivas. Uma linha mapeada manualmente é contada em "Origem", "Destino" E "Manual" simultaneamente. A soma dos 6 cards é maior que o total de linhas — isso é desenho.
Antes (v1.0): 4 cards mutuamente exclusivos (Confirmado/IA Pendente/Sem Mapping/Total). Feedback Bruno: genérico demais. v1.1 entrega visibilidade granular por dimensão.
Filtros
7 botões alinhados com os cards: \
Todos / Com Origem / Com Destino / IA / Manual / Sem Destino / Sem Origem\. Click no card também filtra (atalho visual).Banner OData (collapsible)
Quando source é OData/SAP e usa navigation properties, aparece banner discreto "N navigation properties OData no \$expand" — collapsed por default. Expande para troubleshoot 404.
Tickets
- #205 v1.0 implementação original (4 cards hierárquicos).
- v1.1 PR #54 — refator pra 6 dimensões granulares + lint clean + dead code.
Histórico de versões
- 1.6.0
Constante COM valor conta como "mapeado no destino" e particiona por ai_suggested — "Mapeados no Destino" = "Mapeados por IA" quando tudo veio da IA; fixedValue vira subconjunto informacional.
6/9/2026 · updated
- 1.5.0
Obrigatórios pelo PAI IMEDIATO (não pelo segmento de topo) + cobertura por forma CANÔNICA do path (rule [*] ↔ catálogo) + gate conta obrigatórios pelo MESMO modelo do card (required-coverage.ts helper único).
6/8/2026 · updated
- 1.4.2
Contadores/filtro do editor respeitam is_ignored (Bruno 30/05). O PR #387 fez o engine pular is_ignored (duplicata do dedup), mas a camada derivada (computeStats + matchesFilter + cobertura + emitido) só checava transform=ignore — então o card "Mapeados por IA" e o filtro ainda contavam a duplicata (linha que não executa). Helper isIgnoredRule(f) = transform===ignore || is_ignored===true, espelhando o runtime, aplicado em matchesFilter (ai/manual/destCovered/mapped/conflicts/destReqTotal), computeStats, computeEmittedSegments, conflictDests, cardinalityConflict, virtualRequiredRows, destCoverage, odataNavProperties. is_ignored adicionado ao tipo FieldMapping. Regra do Bruno consistente em toda a stack: 1 linha visível que produz valor = 1 mapeado; rejeitada e duplicata não contam. +2 tests.
5/30/2026 · updated
- 1.4.1
Fix follow-up do modelo dinâmico (Bruno 30/05): o modelo "obrigatório = segmento emitido" sub-contava destinos OData — campos escalares no topo da entidade (sem ".", ex: BillingDocumentDate, 88 no BillingDocument V4) viravam o próprio segmento e só contavam se mapeados, então required não-mapeado no topo não aparecia. Helper isRequiredEmitted espelha o validate-required (parentSegmentEmitted: campo sem pai sempre cobrado): top-level (sem ".") sempre conta; segmentado (EDIFACT/X12/IDoc ou nav OData to_X.Y) gateia por segmento emitido. Usado em computeStats + requiredDestPaths + virtualRequiredRows. Destinos EDIFACT por segmento emitido; OData cobra todos required de topo. +2 tests.
5/29/2026 · updated
- 1.4.0
Modelo DINÂMICO de "obrigatório" no editor (Bruno 30/05): "obrigatório" não é o M/C teórico do spec EDIFACT (que marca quase tudo required), e sim o conjunto MÍNIMO de campos que precisam estar preenchidos pra mensagem validar/ser aceita. O validador de runtime (validate-required.ts) já fazia isso via parentSegmentEmitted (required só é cobrado se o segmento pai for emitido); o editor estava desalinhado, contava required estático do catálogo e trazia free text de segmentos que o operador nem está montando. Agora o editor usa a MESMA lógica: computeStats destReqTotal/destReqUnmapped contam required só de segmento EMITIDO (top-segment de alguma rule ativa); destReqTotalAll continua = spec (referência). Filtro (requiredDestPaths + virtualRequiredRows) só required de segmento emitido → clicar "Obrigatórios" mostra exatamente o que a validação cobraria. Árvore + banner: segmento não-emitido não fica vermelho. Helpers puros topSegment + computeEmittedSegments. Removido o split oper·spec do PR-2 (superado). Substitui a heurística business (PR #384 fechado). Reclassificação de dados partner_profile→conditional mantida (inócua no modelo dinâmico). 2357 tests.
5/29/2026 · updated
- 1.3.0
Reconciliação dos cards de mapeamento (Bruno 29/05): "Mapeados no Destino"=88, "por IA"=68, "Manual"=0 não somavam. Investigação no mapping real A_BillingDocument→INVOIC_D01B revelou: (1) o "88" contava LINHAS de catálogo cobertas, não destinos — 2 rules da IA apontavam pra nome cru de componente (C51904/C55304) que existe em 12 segmentos LOC do INVOIC, e o destCovered casava por name → cada uma batia 12 linhas (64 normais + 2×12 = 88); (2) o "68 por IA" incluía 2 sugestões rejeitadas (transform=ignore). Real: 66 destinos mapeados, todos por IA. Fix (decisão Bruno opção B): destCovered passa a contar mapeamento COMPLETO ativo (origem→destino, não-ignore), particionado por ai_suggested → destCovered = ai + manual POR CONSTRUÇÃO. ai exclui ignore (68→66). Dest sem origem fica em noSource (não vira manual). matchesFilter alinhado (clicar o card mostra exatamente o que conta). Resultado: 66 = 66 IA + 0 Manual; cobertura de catálogo (X/645) fica no banner de cobertura estrutural. +1 test do invariante.
5/29/2026 · updated
- 1.2.0
Consistência dos obrigatórios no destino (Bruno 29/05): o card "Obrigatórios no Destino" mostrava 18 (subconjunto do operador — required_kind business/partner_profile) mas a árvore estruturada e o banner de cobertura embaixo mostravam ~89 (todos os required do spec, incl. technical/conditional). Parecia bug ("clico e aparecem mais campos"). Não era contagem errada — eram predicados diferentes sob o mesmo rótulo. Decisão do Bruno: mostrar os DOIS números sempre. Agora a árvore (mapping-structured-view) e o banner (mapping-coverage-banner) mostram "(X/Y oper · A/B spec)" por segmento quando diferem, e "(A/B req)" quando coincidem (OData/NFe/FHIR). Predicado único isOperatorRequired (lib/catalog/required-kind) reusado em computeStats, destCoverage e na árvore — não podem mais divergir. Card 18 oper · 89 spec ↔ soma da árvore 18 oper · 89 spec. Helper puro requiredDisplay + 5 tests.
5/29/2026 · updated
- 1.1.0
Cards/filtros refeitos em 6 dimensões granulares (Bruno feedback). Substitui 4 cards mutuamente exclusivos do v1.0.0 por: Campos Origem, Campos Destino, Mapeados IA, Mapeados Manual, Origem sem Destino, Destino sem Origem. NÃO mutuamente exclusivos — cada métrica isolada faz sentido pro operador. 7 filtros 1:1 + click no card filtra. Layout grid-cols-3 lg:grid-cols-6 (mobile-friendly). Inclui no mesmo PR: lint full repo limpo (0 errors/warnings — corrigiu 4 errors + 3 warnings que existiam: setState síncrono em useEffect, JSX unescaped entities, unused-vars, let→const). Dead code: removida getFieldSource() unused + 13 chaves i18n órfãs (mappedFields/noDestinationStat/aiSuggested/totalFields/statConfirmed/Pending/NoMapping/filterMapped/Unmapped/DestOnly/Confirmed/AiPending/NoMapping). PR #54.
5/17/2026 · updated
- 1.0.0
Mapping editor com cards/filtros consistentes (Confirmados/IA Pendente/Sem Mapping/Total — soma = total). Cards viraram botões click-to-filter. Banner OData collapsible. 5 chaves i18n novas. PR #45.
5/17/2026 · new