Mappings & EDI Hub
Como o Lefia converte um formato em outro (arquitetura)
A interlíngua de conceito: toda fonte vira conceito, o conceito vira qualquer destino. Sem tradutores N×N.
Atualizado em 8/6/2026
Como o Lefia converte um formato em outro
A pergunta certa não é "como traduzo OData para INVOIC?". É "como faço qualquer fonte virar qualquer destino sem escrever um tradutor para cada par?".
A ideia central: a interlíngua de conceito
O Lefia não converte formato para formato direto. Se fizesse isso, cada formato novo exigiria N tradutores (um por destino). Em vez disso, tudo passa por uma camada intermediária — o conceito:
- Quem conhece a fonte só diz: "este campo é este conceito" (ex.:
TotalTaxAmountéamount.tax). - Quem conhece o destino só diz: "este conceito vira este segmento/qualifier" (ex.:
amount.taxviraMOA+124). - As duas pontas nunca se falam direto — só pelo conceito.
É isto que dá o agnosticismo: o conhecimento do INVOIC é escrito uma vez e serve para OData V2, V4, IDoc, X12, NF-e… Adicionar um formato novo não toca os outros.
As 3 camadas de dados (tudo declarativo, em tabelas)
| Camada | Tabela | O que guarda |
|---|---|---|
| Catálogos | catalog_user_messages | a estrutura fiel de cada mensagem (campos, tipos, cardinalidade), derivada do XSD/spec |
| Anotação fonte → conceito | catalog_field_semantics | (formato, campo) → concept_key |
| Vocabulário de conceito | semantic_concepts | a lista canônica de conceitos + aliases (is_deprecated / deprecated_replacement_key) |
| Conhecimento do destino | message_qualifier_needs + anotações do msg destino | concept_key → segmento + qualifier |
| De-para de valores | KB value_map | códigos (ex.: unidade SAP ST → UN/Rec20 PCE) |
Nada disso é código TypeScript por formato. Formato novo = dado novo.
O pipeline determinístico (o "compilador")
Vive em
compile-mapping.ts → destination-compiler.ts. Sem IA no fio:buildIntents— lê as anotações da fonte e produz intents{campo, conceito}(aplicaapproved > pending).loadCompileKnowledge(standard_destino, msg_destino)— carrega TODO o conhecimento do destino. Não recebe parâmetro de origem — é a prova de que é agnóstico.compileIntents— para cada intent: canonicaliza o conceito (resolve alias) e pergunta ao destino "onde mora este conceito no fio?". Emite a(s) regra(s).- Enriquecimentos — pricing por valor, expansão de array de parceiro, derivações computadas (preço = valor / qtd), dedup, poda de órfão.
applyMapping+serialize— executa as regras sobre o payload real e monta o texto EDIFACT/X12/XML final.
Os 3 tipos de regra que ele emite
| Tipo | O que faz | Exemplo |
|---|---|---|
| Folha (Caso A) | conceito → 1 campo direto | item.net_amount → valor do MOA |
| Qualificada (Caso B/C) | 2 regras na mesma instância: o qualifier-constante + o valor | MOA01 = 124 + MOA C51602 = TotalTaxAmount |
| Computada | derivação | preço unitário = GrossAmount / BillingQuantity |
Otransform_config.group(ex.:MOA+124) amarra o qualifier ao valor e distingue uma instância da outra. É isto que diferencia 7 segmentos MOA legítimos de um conflito real.
Exemplo end-to-end (um campo, Billing → INVOIC)
payload: TotalTaxAmount = 19.00
anotação: BillingDocument/TotalTaxAmount → document.tax_amount (catalog_field_semantics)
canonical: document.tax_amount → amount.tax (semantic_concepts)
need: amount.tax → segmento MOA, qualifier 124 (message_qualifier_needs)
compilador: { MOA01 = "124" } + { MOA C51602 = TotalTaxAmount }
serializa: MOA+124:19.00'
Troque a fonte por um IDoc cujo campo esteja anotado a
amount.tax → sai exatamente o mesmo MOA+124, sem nenhum código novo.Design-time vs runtime
- Design-time (botão Sugerir via IA): roda o compilador e salva as regras em
mappings.field_mappings— é o que você vê no editor de mapping. Onde o conceito da fonte ainda não existe, o auto-concept (IA) anota na hora: a IA emite só o conceito, o compilador monta o fio. - Runtime (
process-message): quando chega uma mensagem real, lê o mapping salvo e roda os passos 4→5. Determinístico, sem IA.
Como um formato NOVO entra
Não se escreve tradutor. Faz-se:
- Sobe o catálogo (XSD/spec) →
catalog_user_messages. - Anota os campos a conceitos (
catalog_field_semantics) — manual ou auto-concept. - Se for destino novo: preenche os
message_qualifier_needs(concept → segmento + qualifier) e o profile do standard.
Pronto — ele entra na interlíngua e fala com todos os outros.
Nota: OData V2 vs V4
A_BillingDocument (V2, navegação to_Item) e BillingDocument (V4, navegação _Item) são a mesma fonte SAP em duas serializações. São dois catálogos com anotações próprias, mas o destino é o mesmo — então o que muda entre eles é só a camada de anotação, nunca o compilador.