Índice
- O problema da integração
- Conceitos que você precisa entender
- Arquitetura de referência
- Passo 1: Mapear dados do ERP
- Passo 2: Criar camada de middleware
- Passo 3: Implementar sincronização
- Passo 4: Webhooks para tempo real
- Passo 5: Observabilidade
- Erros comuns
- Caso real: e-commerce que integrou ERP em 6 semanas
O problema da integração {#problema}
ERP (Enterprise Resource Planning, ou "Sistema de Gestão Empresarial") é o sistema que controla o coração da empresa: pedidos, estoque, financeiro, clientes. Exemplos comuns no Brasil: SAP, TOTVS, RM, e sistemas feitos sob medida.
O problema é que ERPs legados (sistemas antigos, instalados há 10-20 anos) raramente expõem APIs REST modernas. Eles foram desenhados para operar isoladamente, como uma ilha. Suas integrações costumam ser via:
- Arquivos em disco: o ERP gera um CSV/TXT/XML em uma pasta, outro sistema lê essa pasta periodicamente
- Tabelas compartilhadas no banco: dois sistemas leem/escrevem na mesma tabela do banco de dados
- WebServices SOAP: um formato antigo de comunicação baseado em XML, verboso e complexo (SOAP significa Simple Object Access Protocol — irônico, já que não é simples)
- Conexões diretas ao banco de dados: um sistema acessa o banco do outro diretamente (arriscado e frágil)
Sistemas modernos esperam APIs REST (um padrão de comunicação pela web, usando HTTP — o mesmo protocolo dos sites) com autenticação OAuth (um sistema de "carteirinha" que prova quem você é), respostas em JSON (formato de dados leve e legível) e webhooks (explico adiante).
Analogia: Imagine que o ERP é um funcionário que só fala alemão e se comunica por cartas escritas à mão. O sistema moderno é um funcionário que só fala português e se comunica por WhatsApp. Para eles conversarem, você precisa de um tradutor que entende ambos os idiomas e formatos. Esse tradutor é o que chamamos de middleware.
A lacuna entre os dois mundos é a fonte de 80% dos problemas de integração em empresas. A boa notícia: com a arquitetura certa, essa ponte é construída de forma robusta e manutenível.
Conceitos que você precisa entender {#conceitos}
Antes de mergulhar na implementação, vamos alinhar 6 conceitos-chave:
API REST
Analogia: Uma API é como um garçom de restaurante. Você (o cliente) faz um pedido (request) seguindo o cardápio (os endpoints disponíveis). O garçom leva o pedido à cozinha (o servidor), e traz o prato pronto (a resposta). Você não precisa saber como a cozinha funciona — só precisa saber pedir.
REST (Representational State Transfer) é um conjunto de regras para construir APIs usando HTTP. As operações básicas (CRUD — Create, Read, Update, Delete) mapeiam para verbos HTTP:
| Operação | Verbo HTTP | Exemplo |
|---|---|---|
| Criar | POST | POST /pedidos — cria um pedido novo |
| Ler | GET | GET /pedidos/123 — busca o pedido #123 |
| Atualizar | PUT/PATCH | PUT /pedidos/123 — atualiza o pedido #123 |
| Deletar | DELETE | DELETE /pedidos/123 — remove o pedido #123 |
Middleware
Analogia: Middleware é como um intérprete em uma reunião de negócios internacional. O brasileiro fala português, o alemão fala alemão. O intérprete ouve um, traduz para o outro, e vice-versa. Nenhum dos dois precisa aprender o idioma do outro.
O middleware é a camada que fica entre o ERP e o sistema moderno, traduzindo formatos, protocolos e garantindo que a comunicação flua de forma confiável.
Fila de mensagens (Message Queue)
Analogia: Uma fila de mensagens é como uma caixa de correio comum da empresa. Quando chega uma carta, ela fica na caixa até alguém pegar. Se o carteiro (produtor) entrega uma carta e o destinatário (consumidor) não está, a carta não se perde — fica esperando. O carteiro não precisa esperar o destinatário chegar para ir embora.
Isso é fundamental para integrações: o ERP pode gerar 100 mudanças em 1 minuto. Se tentarmos processar todas síncronas (uma por vez, esperando cada uma terminar), o ERP trava. Com fila, as mudanças entram na fila instantaneamente e são processadas no ritmo do sistema moderno.
Ferramentas comuns: RabbitMQ, Kafka, Amazon SQS.
Webhook
Analogia: Um webhook é como um alarme de incêndio. Em vez de você ficar checando a cada 5 minutos "tem fogo? tem fogo?", o alarme te avisa no momento em que o fogo começa. Você não pergunta — é avisado.
Um webhook é um endpoint (URL) no seu sistema que o ERP chama automaticamente quando algo acontece. Em vez de você perguntar ao ERP a cada minuto "tem pedido novo?" (polling), o ERP te avisa no momento exato em que o pedido é criado.
Idempotência
Analogia: Idempotência é como um carimbo de "PAGO" em uma conta. Se você carimbar uma, dez ou cem vezes, o resultado é o mesmo: a conta está marcada como paga. Não cria múltiplas contas pagas.
Na prática: se a mesma mensagem for processada 2 vezes (por exemplo, devido a um retry), o resultado deve ser o mesmo de processar 1 vez. Não cria duplicatas.
CDC (Change Data Capture)
Analogia: CDC é como uma câmera de segurança que grava tudo que acontece no banco de dados. Em vez de você perguntar "mudou alguma coisa?" a cada minuto, a câmera te entrega um log de tudo que mudou, no momento exato.
Tecnicamente: CDC monitora o log de transações do banco de dados e captura mudanças (insert, update, delete) em tempo real, sem precisar de polling. Ferramenta popular: Debezium.
Arquitetura de referência {#arquitetura}
[ERP Legado] [Sistema Moderno]
│ │
│ (arquivo/SQL/SOAP) │ (REST API + JSON)
↓ ↓
[Adapter ERP] ────→ [Middleware] ────→ [Adapter API]
│
[Fila de Mensagens (RabbitMQ)]
│
[Logger + Monitor + Alertas]
Analogia completa: O ERP "fala" gerando arquivos e registros no banco. O Adapter ERP é como um "ouvidor" que captura essas mudanças. O Middleware é o "tradutor" que converte para o formato que o sistema moderno entende. A Fila é a "caixa de correio" que segura as mensagens até serem processadas. O Adapter API é o "garçom" que entrega as mensagens ao sistema moderno.
Princípios da arquitetura:
- Adapter Pattern (padrão de adaptador): cada sistema tem um adaptador que traduz seu protocolo. Se o ERP mudar, só o adapter muda — o resto fica intacto.
- Assíncrono: comunicação via fila, não síncrona. O ERP não espera o sistema moderno responder.
- Idempotente: reprocessar uma mensagem não causa duplicação.
- Observável: cada mensagem tem um ID único e é rastreável do início ao fim.
Passo 1: Mapear dados do ERP {#passo-1}
Antes de escrever qualquer código, documente quais dados do ERP serão integrados e como eles estão estruturados.
Analogia: Antes de construir uma ponte entre duas ilhas, você precisa mapear o terreno de cada lado. Quais estradas chegam à margem? Qual o tipo de solo? Sem esse mapeamento, a ponte pode desabar.
# mapeamento-erp.yaml — Documentação dos dados a integrar
entidades:
pedido:
origem: tabela TBL_PEDIDO (SQL Server)
campos:
- nr_pedido: "ID único do pedido (int, chave primária)"
- dt_emissao: "Data de emissão (datetime)"
- cd_cliente: "Código do cliente — FK para TBL_CLIENTE"
- vl_total: "Valor total (Decimal 12,2 — até 99.999.999,99)"
- st_pedido: "Status: A=Aberto, F=Faturado, C=Cancelado"
trigger: "INSERT ou UPDATE em TBL_PEDIDO"
frequencia: "Aproximadamente 200 pedidos/dia"
cliente:
origem: tabela TBL_CLIENTE (SQL Server)
campos:
- cd_cliente: "ID único do cliente (int)"
- nm_cliente: "Nome ou razão social (varchar 100)"
- nr_cnpj: "CNPJ sem máscara (varchar 14)"
- ds_email: "E-mail de contato (varchar 200)"
trigger: "INSERT ou UPDATE em TBL_CLIENTE"
frequencia: "Aproximadamente 20 clientes novos/dia"
Dica: Use database triggers (gatilhos no banco que disparam quando algo muda) ou CDC (Change Data Capture) para detectar mudanças em vez de polling (ficar perguntando "tem novidade?" a cada minuto). Isso reduz a carga no ERP e diminui o tempo de latência.
Erro comum: Pular o mapeamento e ir direto ao código. Resultado: 3 semanas depois, descobre que o campo
st_pedidopode ter 6 valores diferentes, não 3 como você assumiu. O mapeamento é a parte mais importante — invista tempo nele.
Passo 2: Criar camada de middleware {#passo-2}
O middleware é o coração da integração. Ele faz 4 coisas:
- Lê mudanças do ERP (via trigger, CDC ou polling)
- Transforma para um formato canônico (JSON padronizado que o sistema moderno entende)
- Publica em fila (RabbitMQ/Kafka)
- Consome da fila e envia para a API moderna
Analogia: O middleware é como uma central de triagem de correios. Recebe cartas de diversos remetentes (ERP), padroniza o formato (envelope padrão), coloca na esteira (fila), e a esteira leva para o destinatário (API moderna) no ritmo certo.
Exemplo em Python (FastAPI + RabbitMQ)
# adapter_erp.py — Adapter que lê mudanças do ERP e publica na fila
import json
from datetime import datetime
from pika import BlockingConnection, ConnectionParameters, BasicProperties
def on_erp_change(entity: str, action: str, data: dict):
"""
Chamado quando o ERP notifica uma mudança (via trigger ou CDC).
Args:
entity: nome da entidade que mudou ('pedido', 'cliente', etc.)
action: o que aconteceu ('created', 'updated', 'deleted')
data: os dados do registro que mudou
"""
# Constrói mensagem no formato canônico (padrão para todos os sistemas)
message = {
# ID único da mensagem — usado para idempotência (evitar duplicação)
"id": f"{entity}-{data['id']}-{action}-{datetime.utcnow().isoformat()}",
"entity": entity, # qual entidade mudou
"action": action, # o que aconteceu: created | updated | deleted
"data": data, # os dados em si
"timestamp": datetime.utcnow().isoformat(), # quando ocorreu
}
# Conecta ao RabbitMQ e publica a mensagem na fila
connection = BlockingConnection(ConnectionParameters("rabbitmq"))
channel = connection.channel()
# Declara a fila como 'durable' — sobrevive a reinícios do RabbitMQ
channel.queue_declare(queue="erp_changes", durable=True)
# Publica a mensagem
channel.basic_publish(
exchange="",
routing_key="erp_changes",
body=json.dumps(message),
# delivery_mode=2 = mensagem persistente (não se perde em restart)
properties=BasicProperties(delivery_mode=2),
)
connection.close()
# consumer_api.py — Consumer que lê da fila e envia para a API moderna
import json
from pika import BlockingConnection, ConnectionParameters
def on_message(ch, method, properties, body):
"""
Chamado quando uma mensagem chega na fila.
O RabbitMQ chama esta função automaticamente para cada mensagem.
"""
message = json.loads(body)
# === IDEMPOTÊNCIA ===
# Verifica se esta mensagem já foi processada (pode chegar duplicada
# devido a retries). Usa o ID único da mensagem.
if already_processed(message["id"]):
# Já processou? Confirma o recebimento e ignora
ch.basic_ack(method.delivery_tag)
return
# === ENVIO PARA API MODERNA ===
# Conforme a ação, chama o endpoint correto da API REST
if message["action"] == "created":
# POST: cria um novo registro no sistema moderno
response = api.post(f"/{message['entity']}", json=message["data"])
elif message["action"] == "updated":
# PUT: atualiza o registro existente
response = api.put(
f"/{message['entity']}/{message['data']['id']}",
json=message["data"]
)
elif message["action"] == "deleted":
# DELETE: remove o registro
response = api.delete(f"/{message['entity']}/{message['data']['id']}")
# === TRATAMENTO DE RESPOSTA ===
if response.ok:
# Sucesso: marca como processado (para idempotência) e confirma
mark_processed(message["id"])
ch.basic_ack(method.delivery_tag)
else:
# Falha: rejeita e coloca de volta na fila (com retry)
# Em produção: usar dead letter queue após N tentativas
ch.basic_nack(method.delivery_tag, requeue=True)
Explicação do fluxo: O Adapter ERP detecta uma mudança (ex: novo pedido no ERP) → cria uma mensagem JSON → publica na fila RabbitMQ. O Consumer lê a mensagem da fila → verifica se já processou (idempotência) → envia para a API moderna (POST/PUT/DELETE) → confirma ou rejeita a mensagem.
Passo 3: Implementar sincronização {#passo-3}
Há dois tipos de sincronização: carga completa (one-time, no início) e incremental (contínua, após a carga inicial).
Carga completa (one-time)
A primeira vez que você liga a integração, precisa sincronizar todos os dados históricos. Faça em batches (lotes) para não sobrecarregar o ERP.
-- Carga inicial: busca pedidos em lotes de 10.000
-- OFFSET/FETCH NEXT garante que pegamos os dados em páginas, sem travar o ERP
SELECT * FROM TBL_PEDIDO
WHERE dt_emissao >= '2024-01-01'
ORDER BY nr_pedido
OFFSET 0 ROWS FETCH NEXT 10000 ROWS ONLY;
-- Depois: OFFSET 10000, 20000, 30000... até terminar
# sincronizacao_inicial.py — Carga completa em batches
def sincronizar_pedidos_completos():
offset = 0
batch_size = 10000
while True:
# Busca um lote de pedidos do ERP
pedidos = erp_db.execute(
f"SELECT * FROM TBL_PEDIDO ORDER BY nr_pedido "
f"OFFSET {offset} ROWS FETCH NEXT {batch_size} ROWS ONLY"
)
if not pedidos:
break # não há mais dados
# Envia cada pedido para a fila (mesmo fluxo do adapter)
for pedido in pedidos:
on_erp_change("pedido", "created", pedido)
offset += batch_size
print(f"Sincronizados {offset} pedidos...")
# Pausa entre batches para não saturar o ERP
time.sleep(2)
Incremental (contínuo)
Após a carga inicial, você só precisa sincronizar as mudanças novas:
- Abordagem 1 — Watermark com timestamp: use o campo
updated_atcomo "marca d'água". A cada 1-5 minutos, busque registros atualizados desde a última marca.
# sincronizacao_incremental.py — Polling com watermark
def sincronizar_incremental():
# last_watermark = timestamp da última sincronização (salvo em arquivo/banco)
last_watermark = carregar_ultimo_watermark()
# Busca apenas registros modificados após o último watermark
novos_pedidos = erp_db.execute(
"SELECT * FROM TBL_PEDIDO WHERE updated_at > ? ORDER BY updated_at",
[last_watermark]
)
for pedido in novos_pedidos:
on_erp_change("pedido", "updated", pedido)
# Atualiza o watermark para o timestamp do último registro processado
if novos_pedidos:
salvar_watermark(novos_pedidos[-1]["updated_at"])
- Abordagem 2 — CDC (Change Data Capture): usa Debezium + Kafka Connect para capturar mudanças em tempo real, sem polling. Mais eficiente, mas mais complexo de configurar.
Erro comum: Fazer polling a cada 1 segundo. Isso sobrecarrega o ERP com consultas que 99% das vezes não retornam nada. Use intervalos de 1-5 minutos, ou melhor, use CDC/webhooks.
Passo 4: Webhooks para tempo real {#passo-4}
Para notificações em tempo real (sem precisar de polling), use webhooks. O sistema moderno expõe um endpoint que o ERP (ou o middleware) chama quando algo acontece.
// Node.js — endpoint que recebe webhook do sistema moderno
app.post('/webhooks/erp', async (req, res) => {
const { event, entity, id, data } = req.body;
// 1. VALIDAR ASSINATURA (segurança obrigatória!)
// Verifica que o webhook realmente veio de quem diz ter vindo
// usando HMAC-SHA256 (uma assinatura criptográfica)
if (!verifySignature(req.headers['x-signature'], req.body)) {
return res.status(401).send('Invalid signature');
}
// 2. COLOCAR NA FILA PARA PROCESSAMENTO ASSÍNCRRONO
// Não processa aqui — responde 200 rápido e processa depois
await queue.add('erp_event', { event, entity, id, data });
// 3. RESPONDER 200 IMEDIATAMENTE
// Não faz o ERP esperar o processamento terminar
res.status(200).send('OK');
});
Analogia do webhook: O webhook é como um interfone. Quando alguém toca, você responde "oi, recebido" imediatamente (HTTP 200), e depois vai abrir o portão (processar). Você não faz a pessoa esperar no interfone enquanto você caminha até o portão.
Padrões essenciais de webhook:
- Sempre responder 200 em menos de 5 segundos: não bloquear quem chama. Se precisar processar algo demorado, coloque em fila e responda 200.
- Assinar payloads com HMAC-SHA256: para garantir que o webhook veio de quem diz ter vindo (não de um atacante fingindo ser o ERP)
- Implementar retry exponencial no envio: se o receptor não responder 200, tentar novamente em 1min, 5min, 30min, 2h...
- Idempotência: mesmo evento enviado 2x não deve criar duplicata
Erro comum: Processar o webhook síncronamente. Se o processamento demora 10 segundos e o ERP tem um timeout de 5 segundos, o ERP acha que falhou e reenvia. Você processa 2 vezes. Solução: responder 200 imediatamente e processar em background.
Passo 5: Observabilidade {#passo-5}
Observabilidade é a capacidade de saber o que está acontecendo com sua integração sem precisar "adivinhar". Integração sem observabilidade é caos em produção — você só descobre que parou quando alguém reclama.
Analogia: Observabilidade é como o painel do carro. Sem ele, você só descobre que acabou a gasolina quando o carro para no meio da estrada. Com o painel, você vê o marcador e abastece antes de ficar sem combustível.
1. Logging estruturado
Cada mensagem deve ser logada com um correlation ID (ID de correlação) que permite rastrear uma mensagem do início ao fim:
{
"correlation_id": "pedido-12345-created",
"entity": "pedido",
"action": "created",
"status": "success",
"latency_ms": 142,
"timestamp": "2026-08-26T10:30:00Z",
"source": "erp_adapter",
"target": "api_moderna",
"message_size_bytes": 1240
}
Por que correlation ID?: Imagine que um pedido falha no sistema moderno. Com o correlation ID, você busca no log e vê exatamente: quando o ERP gerou, quando entrou na fila, quando o consumer processou, onde falhou. Sem isso, você está caçando agulha em palheiro.
2. Métricas (Prometheus + Grafana)
Métricas agregadas que permitem ver tendências e anomalias:
integration_messages_total{entity, action, status}— total de mensagens processadas, por entidade/ação/statusintegration_latency_seconds{entity}— tempo de processamento por entidadeintegration_queue_depth— quantas mensagens estão na fila esperandointegration_error_rate— percentual de mensagens que falharam
3. Alertas
Falhas silenciosas são o pior cenário em integração. Configure alertas automáticos:
| Condição | Ação | Urgência |
|---|---|---|
| Erro rate > 5% | Slack/PagerDuty | Alta |
| Queue depth > 1000 mensagens | Slack | Média |
| Latência > 30s | Investigar | Média |
| Nenhuma mensagem em 1h | Verificar ERP | Alta |
4. Dead Letter Queue (DLQ)
Mensagens que falham N vezes (ex: 5 tentativas) vão para uma fila separada chamada DLQ (Dead Letter Queue, ou "Fila de Cartas Mortas"). Lá, elas não bloqueiam a fila principal e podem ser analisadas manualmente.
Analogia da DLQ: É como a mesa de "correspondência devolvida" nos correios. Cartas que não puderam ser entregues (endereço errado, destinatário ausente) vão para lá, onde um funcionário humano analisa e decide o que fazer. Enquanto isso, o fluxo normal de entregas continua.
Erros comuns {#erros}
Erro 1: Síncrono em vez de assíncrono
O que acontece: No trigger do ERP (que dispara quando um pedido é criado), o código chama a API moderna diretamente e espera a resposta. Se a API moderna cair, ficar lenta ou demorar, o ERP trava — o usuário não consegue salvar o pedido.
O que NÃO fazer:
# ❌ ERRADO: chamada síncrona no trigger do ERP
def on_pedido_created(pedido):
# Chama a API diretamente e espera a resposta
response = requests.post("https://api.moderna.com/pedidos", json=pedido)
response.raise_for_status() # se falhar, o ERP trava
# O usuário do ERP fica esperando isso terminar!
O que fazer:
# ✅ CERTO: publica na fila e retorna imediatamente
def on_pedido_created(pedido):
# Coloca na fila (microsegundos) e retorna
on_erp_change("pedido", "created", pedido)
# O ERP continua funcionando normalmente
# A API moderna será chamada assíncronamente pelo consumer
Erro 2: Sem idempotência
O que acontece: Uma mensagem é processada, mas o basic_ack não chega
ao RabbitMQ (problema de rede). O RabbitMQ reenvia a mensagem. O consumer
processa de novo → cria um pedido duplicado no sistema moderno.
O que NÃO fazer:
# ❌ ERRADO: sem verificação de idempotência
def on_message(ch, method, properties, body):
message = json.loads(body)
# Processa direto, sem verificar se já processou
api.post(f"/{message['entity']}", json=message["data"])
ch.basic_ack(method.delivery_tag)
# Se a mensagem chegar 2x, cria 2 registros!
O que fazer:
# ✅ CERTO: verificar idempotência antes de processar
def on_message(ch, method, properties, body):
message = json.loads(body)
# Verifica no banco se este ID já foi processado
if ja_processado(message["id"]):
ch.basic_ack(method.delivery_tag) # confirma e ignora
return
api.post(f"/{message['entity']}", json=message["data"])
marcar_como_processado(message["id"]) # registra no banco
ch.basic_ack(method.delivery_tag)
Erro 3: Polling agressivo
O que acontece: Para detectar mudanças no ERP, o sistema consulta o banco a cada 1 segundo. Para 99% das consultas, não há nada novo. Isso gera carga desnecessária no banco do ERP, que já tem outros usuários usando.
O que NÃO fazer:
# ❌ ERRADO: polling a cada 1 segundo
while True:
novos = erp_db.execute("SELECT * FROM TBL_PEDIDO WHERE updated_at > ?", [last_check])
processar(novos)
time.sleep(1) # muito agressivo!
O que fazer:
# ✅ CERTO: intervalo razoável (1-5 min) ou use CDC
# Opção 1: polling a cada 2 minutos (aceitável para a maioria dos casos)
while True:
novos = erp_db.execute("SELECT * FROM TBL_PEDIDO WHERE updated_at > ?", [last_check])
processar(novos)
time.sleep(120) # 2 minutos
# Opção 2 (melhor): CDC com Debezium — captura mudanças em tempo real
# sem polling. Configura uma vez e esquece.
Erro 4: Sem tratamento de erro — mensagens se perdem
O que acontece: A API moderna retorna erro 500 (servidor indisponível).
O código não trata o erro, a mensagem é confirmada (basic_ack) e perdida.
O pedido existe no ERP mas não no sistema moderno — inconsistência silenciosa.
O que NÃO fazer:
# ❌ ERRADO: confirma a mensagem mesmo se a API falhar
def on_message(ch, method, properties, body):
message = json.loads(body)
try:
api.post(f"/{message['entity']}", json=message["data"])
except Exception:
pass # ignora o erro!
ch.basic_ack(method.delivery_tag) # confirma mesmo assim — mensagem perdida!
O que fazer:
# ✅ CERTO: rejeita a mensagem em caso de erro (volta para a fila)
def on_message(ch, method, properties, body):
message = json.loads(body)
try:
response = api.post(f"/{message['entity']}", json=message["data"])
response.raise_for_status() # lança exceção se status >= 400
ch.basic_ack(method.delivery_tag)
except Exception as e:
logger.error(f"Falha ao processar {message['id']}: {e}")
# Rejeita e coloca de volta na fila para retry
# Após N falhas, vai automaticamente para DLQ
ch.basic_nack(method.delivery_tag, requeue=True)
Erro 5: Mapeamento rígido de campos
O que acontece: O ERP adiciona um campo novo na tabela de pedidos
(ex: vl_desconto). A integração espera um schema fixo e quebra ao
encontrar o campo novo.
O que NÃO fazer:
# ❌ ERRADO: schema rígido que quebra com qualquer mudança
def transformar_pedido(erp_row):
return {
"id": erp_row["nr_pedido"], # se esse campo sumir, quebra
"data": erp_row["dt_emissao"], # se renomear, quebra
"cliente": erp_row["cd_cliente"], # se mudar tipo, quebra
"total": erp_row["vl_total"],
# não há como receber campos novos sem mudar o código
}
O que fazer:
# ✅ CERTO: schema flexível com campos opcionais
def transformar_pedido(erp_row):
result = {
"id": erp_row.get("nr_pedido"),
"data": erp_row.get("dt_emissao"),
"cliente": erp_row.get("cd_cliente"),
"total": erp_row.get("vl_total"),
}
# Campos extras do ERP são preservados (não quebra se ERP adicionar campos)
extras = {k: v for k, v in erp_row.items() if k not in result}
result["_extras"] = extras # campos não mapeados ficam aqui
return result
Erro 6: Sem monitoramento
O que acontece: A integração para de funcionar (RabbitMQ reiniciou, API mudou versão, senha expirou). Ninguém percebe. O cliente liga reclamando que "o sistema não está atualizando". Você descobre o problema 3 dias depois, com dados desatualizados.
O que fazer: Monitoramento proativo é obrigatório. Configure alertas para:
- Erro rate > 5% → alerta imediato
- Nenhuma mensagem processada em 1h → verificar se ERP/middleware está vivo
- Queue depth crescendo → consumer pode estar travado
- Latência aumentando → possível degradação
Caso real: e-commerce que integrou ERP em 6 semanas {#caso-real}
Um e-commerce de moda (faturamento R$ 8M/ano) usava um ERP TOTVS e uma plataforma de e-commerce (VTEX). Os dados eram sincronizados manualmente: um funcionário exportava CSVs do ERP e importava na VTEX, 3x ao dia.
Problemas:
- Estoque desatualizado: clientes compravam produtos sem estoque
- Preços desincronizados: preço promocional na VTEX não refletia no ERP
- 1 funcionário full-time só fazendo export/import manual
- Erros frequentes: planilha errada, importação duplicada
Solução implementada (6 semanas):
- Semana 1-2: Mapeamento de entidades (produto, estoque, preço, pedido)
- Semana 2-3: Adapter ERP lendo mudanças via trigger no SQL Server
- Semana 3-4: Middleware + RabbitMQ + consumer enviando para VTEX API
- Semana 4-5: Webhook da VTEX para enviar pedidos de volta ao ERP
- Semana 5-6: Observabilidade (logs, métricas, alertas) + testes
Resultados:
- Sincronização em tempo real (< 30 segundos do ERP → e-commerce)
- Estoque sempre atualizado: vendas de produtos sem estoque: 0
- 1 funcionário realocado para tarefas de maior valor
- Erros de sincronização: reduzidos em 98%
- ROI em 2 meses (economia de salário + redução de chargebacks)
A lição: A integração bem feita não é apenas técnica — ela resolve problemas de negócio reais (estoque desatualizado = cliente frustrado = chargeback = prejuízo).
Precisa integrar seu ERP com sistemas modernos? A Inicialize Tec implementa integrações robustas com middleware, filas e observabilidade. Conversamos sobre seu caso.