Puente holográfico que traduce el flujo ámbar de un servidor antiguo en datos cian hacia un ERP y un CRM modernos
Software / APIsDesarrollo Web

Middleware a Medida para ERP, CRM y Legacy

Codezone
Codezone Empresa de Desarrollo Web y Software a Medida

Un middleware a medida es una capa propia entre tu ERP, tu CRM y el software antiguo que traduce formatos, mapea identidades y aplica las reglas de la integración. Existe para conectar sistemas que no se entienden sin sustituir ninguno. Lo desarrollamos en los proyectos de integración de Codezone.

El coste de no tenerlo aparece en el tercer sistema: cada conexión nueva obliga a tocar las anteriores, nadie sabe qué integración escribió un campo y una actualización del ERP rompe tres flujos sin un sitio donde mirar.

Al terminar sabrás si tu caso pide esa capa o aguanta sin ella. El transporte que usa dentro lo decide la elección entre API, webhook y cola de mensajes.

Qué es un middleware de integración

Es un servicio propio que recibe los datos de un sistema, los convierte a un modelo común y los entrega al destino en su formato. Centraliza traducción, reintentos y registro en un sitio, así que añadir un sistema nuevo es escribir un adaptador, no modificar los que ya funcionan.

Por qué las conexiones punto a punto se descontrolan

El problema es combinatorio y está documentado desde antes del cloud. Los patrones de integración empresarial lo calculan: una solución con seis aplicaciones que se hablan entre sí necesita 30 traductores sin modelo común y solo 12 con él, según el patrón de modelo de datos canónico.

Con dos sistemas la capa intermedia sobra. Con cuatro o cinco se paga sola, y la señal no es el número: es que nadie responde de memoria qué pasa cuando se crea un cliente.

Maraña de cables de neón entre nodos que se convierte en un hub ordenado con un nodo central
El cableado directo crece más rápido de lo que se documenta.

Qué Hace la Capa Intermedia

  • Traducción de formatos: pasa el XML del ERP, el JSON del CRM y el fichero plano del sistema antiguo a un modelo común, y de vuelta.
  • Mapeo de identidades: guarda que el cliente 4471 del ERP es el contacto `c_88a2` del CRM, porque ningún sistema conoce los identificadores del otro.
  • Reglas de la integración: qué se sincroniza, en qué condiciones y con qué valor por defecto cuando el origen no trae el campo.
  • Reintentos: qué se reintenta, cuántas veces y qué se aparta para revisión manual.
  • Registro: por operación, el dato de entrada, el transformado y el resultado del destino. Sin esto no se audita ni se repara nada.

El Maestro de Cada Dato se Decide Antes del Código

Por cada entidad compartida hay un sistema que manda y los demás obedecen. El ERP suele mandar en artículos y facturas; el CRM en la oportunidad y el contacto comercial. El middleware no arbitra: aplica la decisión que ya tomaste.

Si no se decide, dos sistemas escriben el mismo campo y el último en llegar gana, con el teléfono del cliente cambiando según quién lo tocó. Ese reparto lo ordena qué datos sincronizar entre ERP y CRM y quién manda, con el detalle de una integración con Sage, Holded u Odoo.

El sistema antiguo que solo habla por ficheros

Muchos sistemas en producción no tienen API: exportan un CSV a una carpeta por la noche, o solo dejan leer su base de datos. Se integran igual, con un adaptador que trata esa carpeta como un endpoint: detecta el fichero, valida la estructura, lo convierte al modelo común y registra qué filas entraron.

Leer directo de su base de datos funciona, pero acopla tu integración a su esquema. Martin Fowler lo describe: la base de datos compartida se convierte en un punto de acoplamiento profundo entre las aplicaciones que la usan, lo que aumenta el riesgo de cambiarlas y dificulta su evolución, según su descripción de la base de datos de integración. Si lees de ahí, hazlo en una vista acordada y de solo lectura.

La sustitución progresiva es la salida. El patrón de la higuera estranguladora moderniza poco a poco: el middleware hace de fachada del sistema antiguo y cada función se reescribe detrás sin que los demás noten el cambio. Fowler lo plantea como un proceso gradual en el que inversión y retorno se producen de forma visible y escalonada. Es el camino de modernizar una aplicación legacy sin parar el negocio.

CodeZone Pro Tip: normaliza cada registro de cliente a un modelo común validado antes de escribir en el destino, resolviendo el identificador cruzado en la tabla de mapeo, para que un campo mal formado no entre en el CRM ni se cree un duplicado.
from dataclasses import dataclass
from datetime import date
import re

CIF_RE = re.compile(r"^[A-Z0-9]{9}$")

@dataclass(frozen=True)
class Cliente:
    cif: str
    razon_social: str
    email: str | None
    alta: date
    id_erp: str | None = None
    id_crm: str | None = None

def desde_erp(fila: dict) -> Cliente:
    # El ERP manda el CIF con guiones y espacios: se normaliza aqui,
    # no en el destino, para que la clave de cruce sea siempre la misma.
    cif = re.sub(r"[\s\-\.]", "", fila["NIF"]).upper()
    if not CIF_RE.match(cif):
        raise ValueError(f"CIF invalido en el ERP: {fila['NIF']!r}")
    return Cliente(
        cif=cif,
        razon_social=fila["NOMBRE"].strip(),
        email=(fila.get("MAIL") or "").strip().lower() or None,
        alta=date.fromisoformat(fila["F_ALTA"]),
        id_erp=str(fila["COD_CLI"]),
    )

def desde_crm(doc: dict) -> Cliente:
    # El CRM no exige CIF: si falta, se rechaza antes de tocar el ERP
    # para no crear una ficha que luego nadie puede cruzar.
    cif = (doc.get("tax_id") or "").replace(" ", "").upper()
    if not CIF_RE.match(cif):
        raise ValueError("Contacto del CRM sin CIF utilizable")
    return Cliente(
        cif=cif,
        razon_social=doc["company_name"].strip(),
        email=(doc.get("email") or "").strip().lower() or None,
        alta=date.fromisoformat(doc["created_at"][:10]),
        id_crm=doc["id"],
    )

def resolver_identidad(c: Cliente, mapeo: dict[str, dict]) -> Cliente:
    # La tabla de mapeo es la memoria de la integracion: sin ella
    # cada sincronizacion vuelve a crear el mismo cliente dos veces.
    conocido = mapeo.get(c.cif, {})
    return Cliente(
        **{**c.__dict__,
           "id_erp": c.id_erp or conocido.get("id_erp"),
           "id_crm": c.id_crm or conocido.get("id_crm")}
    )

Ese adaptador convierte un problema recurrente en un fallo visible: el registro malo se rechaza con el motivo escrito, en vez de aparecer días después como una ficha duplicada que alguien fusiona a mano.

Dos siluetas de ficha de contacto en ámbar y cian unidas por un puente de luz que las identifica como la misma
La tabla de mapeo es lo que permite reconocer al mismo cliente dos veces.

Lo que Cuesta Mantener esta Capa

Una capa intermedia es software propio con su mantenimiento: cada cambio de versión del ERP o del CRM puede tocar un adaptador, y conviene reservar presupuesto recurrente antes de descubrirlo en el primer incidente. Esa estructura la detalla la factura recurrente de un software a medida.

A cambio es un coste acotado y visible en un repositorio, no repartido en integraciones que nadie recuerda. Antes de la primera línea conviene tener los procesos mapeados y, si vas a mover histórico, un plan de migración de datos.

Edificio holográfico de bloques donde los antiguos en ámbar se sustituyen uno a uno por bloques nuevos en cian
La fachada aguanta mientras las piezas de dentro se cambian una a una.

La visión de conjunto se decide en el planteamiento de integración de sistemas en Madrid, donde encajan una extranet B2B hecha a medida o la cadena de aprobación de compras.

Cinta holográfica de bloques de datos con símbolos de entrada y salida a lo largo de un centro de datos
Cada operación deja constancia de lo que entró y de lo que salió.

Si tienes tres sistemas conectados a parches, revisamos qué conviene centralizar.