Mapping — arrays e items (SAP to_Item, lines, partners)
Suporte a estruturas item-level: SAP to_Item.results[], linhas de pedido, e PARCEIROS como array (to_Partner[*] por PartnerFunction → NAD+BY/IV/PE automáticos). Ver também "Instâncias qualificadas".
Mapping — arrays e items
Atualizado 2026-05-06. Resolve o gap onde mappings de items SAP retornavam null silenciosamente.
Sintaxe de path
Origem (
source_field) e destino (destination_field) aceitam:| Sintaxe | Significado | Exemplo |
|---|---|---|
header.field | Path simples aninhado | to_Item.Material (legacy: pega 1º item de array) |
path[N].field | Index numérico explícito | to_Item[0].Material |
path[].field | Wildcard — todos os items | to_Item[].Material (recomendado) |
to_Item[*] | OData V2 V auto-resolve | aceita tanto array direto quanto { results: [...] } |
Cenários
1. Sales Order com items → JSON multi-line
Source: payload SAP OData V2 (
to_Item.results = [...])[
{ "source_field": "SalesOrder", "destination_field": "BEG.BEG03", "transform": "direct" },
{ "source_field": "TransactionCurrency", "destination_field": "CUR.CUR02", "transform": "direct" },
{ "source_field": "to_Item[].SalesOrderItem", "destination_field": "items[].PO101", "transform": "direct" },
{ "source_field": "to_Item[].Material", "destination_field": "items[].PO107", "transform": "direct" },
{ "source_field": "to_Item[].RequestedQuantity","destination_field":"items[].PO102", "transform": "direct" }
]
Resultado:
{
"BEG.BEG03": "13",
"CUR.CUR02": "USD",
"items": [
{ "PO101": "10", "PO107": "TG11", "PO102": "100" },
{ "PO101": "20", "PO107": "TG12", "PO102": "50" }
]
}
2. Aggregations no header (totals derivados de items)
[
{ "source_field": "to_Item[*].NetAmount", "destination_field": "header.totalAmount", "transform": "sum" },
{ "source_field": "to_Item[*]", "destination_field": "header.lineCount", "transform": "count" }
]
Transforms novos:
sum, count, first, last. Operam em path com [*] ou OData wrapper.3. Broadcast — campo escalar do header replicado em cada item
[
{ "source_field": "to_Item[].Material", "destination_field": "items[].productId", "transform": "direct" },
{ "source_field": "TransactionCurrency", "destination_field": "items[*].currency", "transform": "direct" }
]
currency aplica USD em todos os items. Constants também broadcasta.Backward compat (mappings AI-suggested antigos)
Mapping suggesteado pela IA antes de 2026-05-06 usava
to_Item.Material (sem [*]). Esses mappings:- Header destination (
PO1.PO107): resolve no PRIMEIRO item do array (legacy compat). Gera warning sugerindoto_Item[*].Materialse quiser todos. - **Destination com
[*]** (items[*].productId): expande automaticamente pra todos os items do array fonte. Não precisa editar — funciona como esperado.
100 mensagens em prod ganharam dados sem reprocessamento manual. Se quiser reaproveitar, basta clicar Reprocessar no monitor ou usar bulk em
/admin/queue.Erros estruturados (do #67)
Todos os erros do mapping seguem o tipo
MappingError:missing_required(error): source ausente em camporequiredsource_path_invalid(warning): source ausente em campo opcionaltype_mismatch(error): tipo incompatível com transform (sumem string,truncateem number)transform_failed(error): config inválida (parseInt → NaN, JSON.parse falhou)
Sugestão de origem via fuzzy match continua funcionando —
to_Iten.Material sugere to_Item[*].Material se houver match próximo.Não suportado nesta versão
- Wildcards aninhados (
a.b[].c[].d): só primeiro[*]expande - Filter por condição (
items[?type=='foo'].field): backlog - Joins entre arrays (linhas + impostos por linha): backlog
Esses ficam como sub-items futuros do roadmap se virarem prioridade.
Migração automática (2026-05-06)
Os 3 mappings ativos de Sales Order foram migrados pra sintaxe
[*] baseado no catálogo X12 850 (loops PO1, N1, REF, DTM, ITD, etc.). 30 fields convertidos.Daqui pra frente, o AI suggester pós-processa toda sugestão usando o catálogo de formatos — segments que são loops naturais (PO1, LIN, det, items, etc.) recebem
[*] automaticamente. Não precisa editar manual.Formatos com loops conhecidos:
- X12 850 (PO), 855 (PO ack), 810 (invoice), 856 (ship notice)
- EDIFACT ORDERS, INVOIC, DESADV
- JSON OData-style (items, partners, lines, taxes)
- NFe / NFSe XML (det, dup, ListaServicos.Servico)
Formatos sem catálogo ainda: HL7 v2, MLLP, JSON Purchase Order proprietário (esses passam direto sem
[*]). Adicionar é trivial — editar src/lib/mapping/destination-formats.ts.SAP OData V2 — tratamento dedicado (v1.3.0)
Navigation property não expandida (__deferred)
40% das mensagens SAP OData chegam com
to_Item.__deferred quando o connector não fez $expand. Antes: items vazios silenciosamente. Agora gera warning acionável:Origem to_Item: navigation property "to_Item" não foi expandida na query OData. Adicionar $expand=to_Item no connector da integração.
Fix: editar query OData do connector pra incluir $expand=to_Item,to_Partner,to_PricingElement,to_Text (separados por vírgula).Conversão de datas SAP (/Date(timestamp)/)
SAP serializa datas no formato Microsoft JSON:
/Date(1473206400000)/. O transform date_format agora converte de verdade.{ "transform": "date_format", "transform_config": { "format": "iso" } }
Options de
format:
iso(default):2016-09-07T00:00:00.000Z— ISO 8601 datetime UTCdate:2016-09-07— só dataepoch_ms:1473206400000— milliseconds desde epoch (number)
Aceita também:
/Date(ms+offset)/— ignora offset, usa UTCYYYYMMDDbare (ex:"20160907")
__metadata ignorado em sugestões
OData V2 envolve cada entity em
{ "__metadata": { "uri": "...", "type": "..." } }. Antes essas chaves apareciam em fuzzy suggestions (typo Materil podia sugerir __metadata.uri). Agora __metadata e __deferred são silenciosamente ignorados — só dados de negócio aparecem nas sugestões.OData V4 + tipos Edm — v1.4.0
V4 wrapper { value: [...] }
OData V4 usa
value no lugar de results. Tudo que vale pra V2 vale pra V4: path[*].field, aggregations, smart fallback, índice numérico.to_Item.value[*].Material ← OData V4 explícito
to_Item[*].Material ← funciona pra V2 e V4 (recomendado)
to_Item.Material ← legacy, primeiro item de array (V2 ou V4)
Transform time_format (Edm.Time)
Edm.Time vem em ISO 8601 duration:
PT12H30M0S. Transform converte pra HH:MM:SS:{ "source_field": "startTime", "destination_field": "start_at", "transform": "time_format" }
Resultado:
"PT12H30M0S" → "12:30:00". Aceita partes faltando (PT9H → 09:00:00), trunca seconds fracionados.Transform to_number (Edm.Decimal/Edm.Double)
SAP serializa decimais como string (
"1755.00") pra preservar precisão. Pra cliente JSON que quer number nativo:{ "source_field": "NetAmount", "destination_field": "net", "transform": "to_number" }
Resultado:
"1755.00" (string) → 1755 (number). Strings non-numéricas passam direto sem error (defensivo).Não suportado nesta versão (backlog)
- Pagination
__next/@odata.nextLink: connector atual REST genérico só pega 1ª página. Connector OData dedicado é item #72 (M, ~3h) - Wildcards aninhados:
a.b[].c[].dsó primeiro[*]expande - Filter por condição:
items[?type=='foo'].field - Joins entre arrays: linhas + impostos por linha
Histórico de versões
- V3.7
UI editor visual de filter_lookup — drawer recursivo com cláusulas + grupos AND/OR aninhados. 13 operadores em PT (é igual a, está em, maior que, contém, é nulo, etc.). 5 match strategies (Primeiro/Último/Único/Somar todos/Juntar como texto) em radio cards. Field selector com datalist autocomplete inferido do source_field nested. Botões "+ Cláusula" e "+ Grupo OR/AND aninhado" alternam por nível. Cor por depth (verde/azul/âmbar). JSON.stringify ↔ JSON.parse ponte entre Record<string,string> storage e FilterNode rich schema.
5/25/2026 · updated
- V3.6
Novo transform "filter_lookup" — regras condicionais com AND/OR aninhado multi-clause. Schema FilterNode recursivo + 13 operadores (eq/neq/in/gt/contains/isNull/...) + 5 match strategies (first/last/single/sum_all/join_all). Engine handle nested 2-level (caso SAP pricing: filter ConditionType==PR00 em to_PricingElement[*]). 42 tests.
5/25/2026 · new
- V3.5
Sessão 24/05 — épico canonical loopPath fechado 100% (4 PRs sequenciais). #259 audit + gap doc. #260 helper buildLoopPath + NF-e refator. #261 FHIR nested + EDIFACT single-level. #262 xsd-generic refator. 1688 tests, 0 todos.
5/24/2026 · updated
- V3.0
Engine writeDest detecta destino dotted e usa write deep com heurística EDIFACT ([CS]\d{3} middle = composite). Serializer EDIFACT usa : entre composite sub-elements.
5/21/2026 · updated
- 1.4.0
OData V4 wrapper { value: [...] } suportado (pareia com V2 results). Transforms novos: to_number (Edm.Decimal/Double string → number), time_format (Edm.Time PT12H30M0S → HH:MM:SS). 16 testes adicionais.
5/6/2026 · updated
- 1.3.0
OData V2 SAP — tratamento completo: __deferred detectado e gera warning acionável ("Adicionar $expand=to_Item no connector"), transform date_format real converte /Date(timestamp)/ pra ISO 8601 (formats: iso/date/epoch_ms), fuzzy suggest ignora __metadata e __deferred. Audit em prod: 203 mensagens (40%) com __deferred agora têm warning explícito vs falha silenciosa antes.
5/6/2026 · updated
- 1.2.0
Catálogo expandido: HL7 v2 (loops OBX/OBR/DG1/AL1/IN1/NK1/ROL/NTE/ORC/RXA), JSON Purchase Order proprietário (items/lines/partners/taxes), MLLP como alias de HL7 v2. resolveFormat agora cobre "JSON Webhook", "REST JSON", "Webhook JSON", "X12-850 via AS2", "X12 855", "X12 856 ASN", e variações. Removido CTT do X12 850 loops (é summary segment único). Re-migração: +4 mappings, +6 fields.
5/6/2026 · updated
- 1.1.0
Catálogo de formatos (X12 850/810/855/856, EDIFACT ORDERS/INVOIC/DESADV, OData JSON, NFe, NFSe). Migração automática dos 3 mappings ativos legacy: 30 fields convertidos pra sintaxe [*]. AI suggester pós-processa toda sugestão. Re-backfill em 313 mensagens com estrutura PO1[*], N1[*] correta.
5/6/2026 · updated
- 1.0.0
Mapping suporta arrays/items: sintaxe path[*].field, OData wrapper auto, transforms sum/count/first/last. Backward compat: mappings AI-suggested antigos `to_Item.X` resolvem no 1º item (header) ou expandem pra todos (destination [*]). Audit em prod identificou 100 mensagens com campos/items recuperados.
5/6/2026 · new