De-para: da resposta da fonte ao canônico
O de-para (responseMapping) é o que transforma a resposta crua de um ERP no registro canônico
do SFA. Ele é configuração, não código: quem integra escreve regras na tela do conector, e o runtime as
interpreta a cada execução.
Onde fica: Integrações → Conectores → editar → De-para, com duas visões, Tabela e JSON. A
tabela cobre o caso comum (uma linha por campo). A aba JSON é onde se escreve o que a tabela ainda não
representa — hoje, flatten e filter.
O formato
{
"itemsPath": "value", // onde está o array de registros na resposta
"flatten": { … }, // explosão 1→N (pai → filhos)
"filter": [ … ], // descarte antes de projetar
"rules": [ … ] // o de-para em si
}
Precedência na projeção: rules → fields (legado) → item cru. Mapeamentos antigos no formato
fields (rename simples) são convertidos para rules ao abrir o editor.
O editor preserva as chaves que ele não edita (flatten, filter, e o que vier depois): elas entram no
parse e voltam no salvar. Ainda assim, prefira editá-las na aba JSON — é lá que você as vê.
Uma regra (FieldRule)
interface FieldRule {
targetField: string; // campo canônico de destino (tem de existir na entidade alvo)
source?: string; // caminho na origem (ex.: "ItemCode", "data.razaoSocial")
template?: string; // alternativa a `source`; tem precedência
type?: "string" | "number" | "boolean" | "date" | "json";
transforms?: FieldTransform[]; // aplicados NA ORDEM, antes da coerção
defaultValue?: unknown; // usado pelo transform `default`
required?: boolean;
}
Ordem de avaliação de cada regra:
extrai (template se houver, senão source) → transforms, em ordem → coerção de tipo →
checagem de obrigatório.
O targetField é validado contra os campos da entidade alvo — campo inexistente vira erro no
dry-run, não lixo no banco.
Origem: um caminho ou um template
A coluna Origem aceita as duas formas, e a escolha é pelo que você digita:
| O que você escreve | Como é gravado | Quando usar |
|---|---|---|
ItemCode | source | o valor vem de um campo só |
{{PriceList}}*{{_parent.ItemCode}} | template | juntar mais de um campo (chave natural composta) |
AliasName || CardName | sources | o dado está num campo ou noutro, conforme o cadastro |
Quando o campo vem vazio em alguns registros
Separe as origens com ||: vale a primeira que trouxer valor.
AliasName || CardName || {{CardCode}}-sem-nome
É o caso clássico do SAP B1: o nome fantasia está em AliasName para uns clientes e só em CardName
para outros. Cada alternativa pode ser um caminho ou um template — então a última pode ser uma
composição, como acima.
Se nenhuma trouxer valor, entra o Valor padrão da linha (o transform default). A ordem
completa é: alternativas → valor padrão → demais transforms → coerção de tipo.
0 e false não são vaziosVazio, aqui, é null, ausente, ou string só com espaços. Um preço 0 ou um booleano false são
respostas legítimas da fonte — pular para a próxima origem nesse caso seria inventar dado.
Um template que é exatamente {{campo}} devolve o valor cru (preserva número, booleano, objeto);
misturado com texto, interpola como string.
Filtros por campo
Dentro de um template, cada campo aceita filtros encadeados com |, aplicados antes de o valor
entrar na string:
| Filtro | Resultado |
|---|---|
trim / lower / upper / ascii | apara as pontas / caixa baixa / caixa alta / sem acento |
nospace | remove todo espaço, inclusive o interno |
digits | só os dígitos (30.534.322/0001-81 → 30534322000181) |
slug[:sep] | sem acento, minúsculo, não-alfanumérico vira sep (padrão -) |
replace:de:para | troca literal (não é regex); para vazio remove |
{{SalesEmployeeName|slug:.}}.{{SalesEmployeeCode}}@smart.com
→ vago.thais.abc.1.219@smart.com
O replace é literal de propósito: uma expressão regular vinda da configuração roda por registro, e uma
expressão catastrófica derrubaria a sincronização inteira. Os casos que pediriam regex já têm filtro
dedicado.
O filtro age em cada campo antes da concatenação; o transform age no valor final da regra.
{{a|nospace}}-{{b}} tira o espaço só de a; o transform trim aparia a string inteira.