Shopify + Odoo ERP Integration: The Complete Guide

Comprehensive guide to integrating Shopify with Odoo ERP — inventory sync, order management, customer data, financial reporting, and automation workflows.

E
ECOSIRE Research and Development Team
|19 de marzo de 202613 min de lectura2.8k Palabras|

Parte de nuestra serie eCommerce Integration

Leer la guía completa

Integración Shopify + Odoo ERP: la guía completa

A medida que las tiendas Shopify crecen, la brecha entre lo que Shopify maneja de forma nativa y lo que la empresa realmente necesita para la excelencia operativa se convierte en una limitación significativa. Gestión de inventario en múltiples almacenes, contabilidad multidivisa, pedidos de fabricación activados por las ventas de Shopify, CRM sofisticado con historial completo del cliente y reabastecimiento automatizado de proveedores: todo esto requiere un ERP, y Odoo es cada vez más el sistema elegido por las empresas de comercio electrónico del mercado medio.

Shopify + Odoo no es una integración plug-and-play. Requiere decisiones arquitectónicas cuidadosas sobre qué sistema posee qué datos, qué se sincroniza en qué dirección y cómo manejar casos extremos como envíos parciales, procesamiento de devoluciones y mapeo de variantes. Esta guía cubre todo, desde la arquitectura de integración hasta patrones de implementación específicos.

Conclusiones clave

  • Odoo es la fuente de verdad para inventario, clientes y contabilidad; Shopify es la fuente de verdad para las transacciones de comercio electrónico
  • La sincronización de inventario bidireccional (Shopify → Odoo para pedidos, Odoo → Shopify para niveles de existencias) es el requisito de integración principal
  • La gestión del catálogo de productos debe estar en Odoo y sincronizarse con Shopify, no al revés
  • Los registros de clientes se fusionan entre sistemas utilizando el correo electrónico como identificador único
  • Ciclo de vida del pedido: Shopify crea el pedido → Odoo recibe el pedido → Odoo crea la entrega → actualizaciones de cumplimiento Shopify
  • El procesamiento de devoluciones requiere coordinación: Shopify inicia la devolución → Odoo procesa el recibo → ambos sistemas se actualizan
  • La API Webhook de Shopify proporciona eventos de pedidos en tiempo real; Odoo los recibe a través del middleware del conector
  • Existen conectores directos Odoo-Shopify (Syncee, OdooConnector) pero las integraciones personalizadas a través de REST API ofrecen más control

Comprender la arquitectura de integración

Antes de implementar, defina el sistema autorizado para cada dominio de datos:

Tipo de datosSistema AutoritarioDirección de sincronizaciónFrecuencia
Catálogo de productosOdooOdoo → ShopifySobre el cambio de producto
Niveles de inventarioOdooOdoo → ShopifyEn tiempo real
PedidosShopifyShopify → OdooTiempo real (webhook)
Registros de clientesOdoo (fusionado)Bidireccional (clave de correo electrónico)Por encargo
PreciosOdooOdoo → ShopifySobre el cambio de precio
Tarifas de envíoShopifySólo ShopifyN/A
PagosShopifyShopify → Odoo (contabilidad)Sobre la liquidación
DevolucionesShopify iniciadoShopify → OdooSobre la creación de retorno

Por qué Odoo posee inventario:

El seguimiento de inventario de Shopify es funcional pero limitado para operaciones multicanal y de múltiples almacenes. El módulo de inventario de Odoo maneja: seguimiento de números de serie y lotes, gestión de almacenes en múltiples ubicaciones, reglas de reabastecimiento automatizadas, integración de fabricación (inventario de componentes de disminución de productos terminados) y operaciones de cumplimiento basadas en códigos de barras. Shopify debe reflejar la realidad del inventario de Odoo, no al revés.

Por qué Shopify es la capa de comercio:

El proceso de pago, el procesamiento de pagos, el cálculo de tarifas de envío, la recaudación de impuestos y la experiencia de atención al cliente de Shopify son los mejores de su clase. El comercio electrónico B2C de Odoo (sitio web de Odoo) es funcional pero no está al nivel de Shopify para el comercio DTC. La arquitectura óptima mantiene a Shopify como la interfaz comercial y a Odoo como la columna vertebral operativa.


Métodos de integración: aplicaciones de conector frente a API personalizada

Opción 1: aplicaciones de conector prediseñadas

Varias aplicaciones de mercado de Shopify y Odoo brindan integración prediseñadas:

ConectorEnfoqueCosto mensualVentajasContras
Zapiet + OdooMiddleware a través de Zapier$50-200Configuración rápidaPersonalización limitada, fallo de un solo punto
SinceConector directo$29-99Sincronización del catálogoProcesamiento de pedidos limitado
OdooConnector.comDiseñado específicamente$200-500IntegralRequiere experiencia en Odoo
Tienda online+ (aplicación Odoo)Odoo-nativoComunidad libreOdoo-nativoSoporte básico de Shopify
Webkul Shopify OdooDiseñado específicamentePersonalizadoCiclo de vida completoConfiguración compleja

Los conectores prediseñados funcionan bien para: catálogo de productos estándar y sincronización de pedidos para modelos comerciales simples sin estructuras de variantes complejas, múltiples almacenes o dependencias de fabricación.

Opción 2: integración personalizada a través de API

Para requisitos comerciales complejos, una integración personalizada utilizando la API REST/GraphQL de Shopify y la API JSON-RPC/REST de Odoo proporciona el mayor control y confiabilidad.

Arquitectura de integración personalizada:

Shopify (Commerce Layer)
│
│ Webhooks (orders/create, orders/updated, refunds/create, inventory_levels/update)
│
▼
Integration Service (Node.js / Python middleware)
│
│ Event processing, transformation, error handling, retry logic
│
▼
Odoo (ERP Layer)
│
│ Odoo JSON-RPC API (sales orders, inventory, customers, accounting)
│
└── Inventory updates → Shopify Admin API

Pila de tecnología para integración personalizada:

  • Middleware: Node.js (para la alineación del ecosistema Shopify) o Python (para la alineación del ecosistema Odoo)
  • Cola: Redis o RabbitMQ para un procesamiento confiable de eventos
  • Base de datos: PostgreSQL para estado de integración, claves de idempotencia, registros de errores
  • Alojamiento: AWS Lambda o similar para controladores de webhooks (se escala automáticamente con los picos de tráfico de Shopify)

Sincronización de pedidos: Shopify → Odoo

La sincronización de pedidos es la ruta de integración más crítica. Cada pedido de Shopify debe crear un pedido de venta de Odoo correspondiente que activa el cumplimiento y actualiza los registros financieros.

Configuración del webhook de Shopify para eventos de pedidos:

// Register webhooks via Shopify API
const webhooks = [
  {
    topic: 'orders/create',
    address: 'https://your-integration.com/webhooks/shopify/orders',
    format: 'json'
  },
  {
    topic: 'orders/updated',
    address: 'https://your-integration.com/webhooks/shopify/orders/updated',
    format: 'json'
  },
  {
    topic: 'orders/fulfilled',
    address: 'https://your-integration.com/webhooks/shopify/orders/fulfilled',
    format: 'json'
  },
  {
    topic: 'refunds/create',
    address: 'https://your-integration.com/webhooks/shopify/refunds',
    format: 'json'
  }
];

Transformación de un pedido de Shopify a un pedido de venta de Odoo:

def shopify_order_to_odoo_sale_order(shopify_order: dict) -> dict:
    """Transform Shopify order payload to Odoo sale.order format"""

    # Find or create Odoo partner (customer)
    partner_id = find_or_create_odoo_partner(
        email=shopify_order['email'],
        name=shopify_order['customer']['first_name'] + ' ' + shopify_order['customer']['last_name'],
        phone=shopify_order['customer'].get('phone'),
        shipping_address=shopify_order['shipping_address']
    )

    # Map line items
    order_lines = []
    for item in shopify_order['line_items']:
        odoo_product_id = get_odoo_product_from_shopify_variant(
            item['variant_id']
        )
        order_lines.append({
            'product_id': odoo_product_id,
            'product_uom_qty': item['quantity'],
            'price_unit': float(item['price']),
            'name': item['name'],
            'shopify_line_id': item['id'],  # Custom field for traceability
        })

    # Add shipping as a service product line
    if float(shopify_order.get('shipping_lines', [{}])[0].get('price', 0)) > 0:
        order_lines.append({
            'product_id': SHIPPING_PRODUCT_ID,  # Configured in settings
            'product_uom_qty': 1,
            'price_unit': float(shopify_order['shipping_lines'][0]['price']),
            'name': shopify_order['shipping_lines'][0]['title'],
        })

    return {
        'partner_id': partner_id,
        'order_line': [(0, 0, line) for line in order_lines],
        'shopify_order_id': shopify_order['id'],  # Custom field
        'shopify_order_name': shopify_order['name'],  # e.g., #1001
        'note': shopify_order.get('note', ''),
        'state': 'sale',  # Confirm order automatically
    }

Manejo de idempotencia:

Shopify puede entregar el mismo evento de webhook varias veces (reintentos de red). Su integración debe manejar eventos duplicados con elegancia:

def process_shopify_order_webhook(payload: dict):
    shopify_order_id = str(payload['id'])

    # Check if already processed
    if OrderSyncLog.objects.filter(
        shopify_order_id=shopify_order_id,
        status='completed'
    ).exists():
        logger.info(f"Order {shopify_order_id} already processed, skipping")
        return

    # Process and log
    try:
        odoo_order_id = create_odoo_sale_order(payload)
        OrderSyncLog.objects.create(
            shopify_order_id=shopify_order_id,
            odoo_order_id=odoo_order_id,
            status='completed'
        )
    except Exception as e:
        OrderSyncLog.objects.create(
            shopify_order_id=shopify_order_id,
            status='failed',
            error=str(e)
        )
        raise

Sincronización de inventario: Odoo → Shopify

Los niveles de inventario deben reflejar la realidad de Odoo en Shopify en tiempo real (o casi en tiempo real) para evitar la sobreventa.

Sincronización de inventario basada en activadores:

El enfoque más confiable es la sincronización basada en eventos: cuando el inventario cambia en Odoo (venta, recibo de compra, finalización de fabricación, ajuste de existencias), Odoo envía la cantidad actualizada a Shopify.

# In Odoo (using automated actions or override)
def _post_write_sync_to_shopify(self):
    """Called after inventory level changes in Odoo"""
    for move_line in self:
        product = move_line.product_id
        location = move_line.location_id

        if location.is_shopify_sync_location:
            shopify_variant_id = product.shopify_variant_id
            if shopify_variant_id:
                new_quantity = product.with_context(
                    location=location.id
                ).qty_available

                sync_inventory_to_shopify(
                    shopify_variant_id=shopify_variant_id,
                    quantity=int(new_quantity)
                )

def sync_inventory_to_shopify(shopify_variant_id: str, quantity: int):
    """Push inventory update to Shopify via Admin API"""
    inventory_item_id = get_inventory_item_id(shopify_variant_id)
    location_id = get_shopify_location_id()  # Primary Shopify location

    shopify.InventoryLevel.set(
        inventory_item_id=inventory_item_id,
        location_id=location_id,
        available=quantity
    )

Conciliación de inventario programada:

Incluso con la sincronización basada en eventos, programe una conciliación diaria completa del inventario:

  1. Exporte todas las cantidades de productos Odoo desde la ubicación designada de sincronización de Shopify
  2. Comparar con los niveles actuales de inventario de Shopify
  3. Actualice cualquier discrepancia (puede ocurrir debido a eventos de sincronización fallidos o ajustes manuales)
  4. Registrar los resultados de la conciliación para fines de auditoría.

Esta conciliación evita la desviación del inventario debido a pequeños fallos de sincronización acumulados.


Sincronización del catálogo de productos: Odoo → Shopify

Para las empresas que administran catálogos de productos en Odoo (con precios en múltiples monedas, especificaciones detalladas y matrices de variantes complejas), sincronizar el catálogo con Shopify elimina la doble entrada manual.

Arquitectura de mapeo de productos:

Odoo Product (product.template)
├── Shopify Product (via shopify_product_id field on Odoo template)
│
└── Odoo Product Variants (product.product)
    └── Shopify Variants (via shopify_variant_id field on Odoo product.product)

Qué sincronizar de Odoo a Shopify:

  • Nombre del producto (descripción de ventas de Odoo)
  • Descripción del producto (descripción HTML larga)
  • Imágenes (imágenes de plantilla de producto)
  • Precio (usando la lista de precios configurada de Shopify)
  • SKU (referencia interna de Odoo)
  • Código de barras (EAN/UPC de Odoo)
  • Peso (para cálculo de envío)
  • Estado activo/archivado (anular publicación en Shopify cuando el producto Odoo esté archivado)
  • Inventario (desde la ubicación de sincronización designada)

Qué NO sincronizar de Odoo a Shopify:

  • Metadatos SEO específicos de Shopify (etiquetas de título, meta descripciones: administrar en Shopify)
  • Etiquetas de productos de Shopify (administrar en Shopify)
  • Colecciones/categorías de Shopify (administrar en Shopify)
  • Contenido específico de Shopify (secciones de creación de páginas, descripciones enriquecidas formateadas para Shopify)

Gestión de datos del cliente

Los clientes que existen tanto en Shopify (desde su cuenta de tienda) como en Odoo (como contactos/socios) necesitan una fusión cuidadosa para crear un único perfil unificado.

Estrategia de deduplicación mediante correo electrónico:

def find_or_create_odoo_partner(email: str, name: str, **kwargs) -> int:
    """Find existing Odoo partner by email or create new one"""
    existing = Partner.search([
        ('email', '=', email)
    ], limit=1)

    if existing:
        # Update with latest data from Shopify
        existing.write({
            'phone': kwargs.get('phone', existing.phone),
        })
        return existing.id
    else:
        # Create new partner
        partner = Partner.create({
            'name': name,
            'email': email,
            'phone': kwargs.get('phone'),
            'type': 'contact',
            'customer_rank': 1,
            'shopify_customer_id': kwargs.get('shopify_customer_id'),
        })
        return partner.id

ID de clientes de Shopify almacenados en Odoo:

Agregue un campo personalizado shopify_customer_id al modelo res.partner de Odoo. Esto permite la búsqueda bidireccional: busque el socio de Odoo desde Shopify ID, encuentre el cliente de Shopify desde el socio de Odoo.


Bucle de cumplimiento: Odoo → Shopify

Cuando Odoo procesa una entrega (recogida + validación), el pedido se cumple. Shopify debe ser notificado a:

  • Marcar el pedido como cumplido
  • Enviar el correo electrónico de confirmación de envío al cliente.
  • Registre el número de seguimiento
def sync_fulfillment_to_shopify(odoo_picking: StockPicking):
    """Called after Odoo delivery is validated"""
    shopify_order_name = odoo_picking.sale_id.shopify_order_name
    tracking_number = odoo_picking.carrier_tracking_ref

    # Find Shopify order
    shopify_orders = shopify.Order.find(name=shopify_order_name)
    if not shopify_orders:
        return

    shopify_order = shopify_orders[0]

    # Create fulfillment in Shopify
    fulfillment = shopify.Fulfillment.create({
        'order_id': shopify_order.id,
        'tracking_number': tracking_number,
        'tracking_company': odoo_picking.carrier_id.name,
        'notify_customer': True,  # Sends Shopify's shipping email
        'line_items': [
            {'id': line.shopify_line_id}
            for line in odoo_picking.sale_id.order_line
            if line.shopify_line_id
        ]
    })

Integración contable: Shopify Sales → Odoo Financials

Cada venta de Shopify debe aparecer eventualmente en el módulo de contabilidad de Odoo como una entrada de venta publicada.

Enfoque de integración para la contabilidad:

Opción 1: Contabilidad a nivel de pedido: cada pedido de Shopify crea una factura de Odoo (o el pedido de venta de Odoo genera una factura cuando se completa). Los pagos registrados en Shopify activan el registro de pago en Odoo.

Opción 2 — Contabilidad a nivel de liquidación: las liquidaciones de Shopify Payments (depósitos bancarios diarios o semanales) se registran en Odoo como asientos de diario que se concilian con las transacciones bancarias. Esto es más sencillo de mantener pero proporciona una contabilidad menos granular.

Para la mayoría de los comerciantes del mercado medio, la contabilidad a nivel de liquidación (Opción 2) es suficiente y significativamente menos compleja de implementar y mantener.

Datos de pago de Shopify → Entrada de diario de Odoo:

def process_shopify_payout(payout_data: dict):
    """Create Odoo journal entry for Shopify Payments payout"""
    journal = ShopifyJournal.get_or_create()  # Shopify clearing account

    entry = AccountMove.create({
        'journal_id': journal.id,
        'date': payout_data['date'],
        'ref': f"Shopify Payout {payout_data['id']}",
        'line_ids': [
            (0, 0, {
                'account_id': SHOPIFY_CLEARING_ACCOUNT_ID,
                'credit': payout_data['amount'],
                'name': f"Shopify sales - {payout_data['period']}",
            }),
            (0, 0, {
                'account_id': SHOPIFY_FEES_ACCOUNT_ID,
                'debit': payout_data['fees'],
                'name': 'Shopify Payments fees',
            }),
            (0, 0, {
                'account_id': BANK_ACCOUNT_ID,
                'debit': payout_data['amount'] - payout_data['fees'],
                'name': f"Bank deposit - Shopify payout {payout_data['id']}",
            }),
        ]
    })
    entry.action_post()

Preguntas frecuentes

¿Cuánto tiempo lleva implementar una integración Shopify-Odoo?

Una integración básica (sincronización de pedidos, sincronización de inventario, sincronización de clientes) utilizando un conector prediseñado tarda entre 2 y 4 semanas, incluida la configuración, las pruebas y la migración de datos. Una integración personalizada que cubra todo el ciclo de vida (pedidos, inventario, sincronización de cumplimiento, devoluciones, contabilidad) demora entre 8 y 16 semanas, según la complejidad del negocio. Los escenarios complejos (Odoo con múltiples almacenes, fabricación, múltiples divisas y múltiples empresas) agregan de 4 a 8 semanas adicionales. Presupuesto para mantenimiento continuo: las integraciones requieren actualizaciones cuando Shopify u Odoo lanzan cambios en la API.

¿Debo administrar productos en Shopify u Odoo?

Para catálogos de productos simples: administre en Shopify y actualice manualmente Odoo para fines de fabricación/adquisición. Para catálogos complejos (muchas variantes, precios en múltiples monedas, especificaciones técnicas, listas de materiales de fabricación): adminístrelos en Odoo y sincronícelos con Shopify. El factor crítico es dónde trabaja realmente su equipo de producto. Si su equipo de merchandising vive en Shopify, obligarlos a trabajar en Odoo crea fricciones. Si su equipo de operaciones administra productos en Odoo para fabricación y adquisiciones, Shopify sync es el enfoque correcto.

¿Qué sucede con los pedidos existentes de Shopify cuando la integración entre en funcionamiento?

Los pedidos históricos no necesitan migrar a Odoo. La integración procesa nuevos pedidos a partir de la fecha de entrada en funcionamiento. Para datos históricos (registros de clientes, catálogo de productos, líneas base de inventario), realice una migración de datos única antes de que la integración entre en funcionamiento: importe datos históricos de clientes a Odoo, importe catálogo de productos y establezca líneas base de inventario en Odoo para que coincidan con las cantidades actuales de Shopify.

¿Cómo manejo los pedidos de Shopify con productos que no existen en Odoo?

Este caso extremo rompe con las integraciones ingenuas. Crea un respaldo: cuando un pedido de Shopify contiene una ID de variante que no se asigna a un producto de Odoo, crea el pedido en Odoo con un marcador de posición de producto "Producto desconocido" y alerta a tu equipo de integración. Defina una cola de errores con notificación: el personal de operaciones revisa los productos no asignados, crea el producto Odoo y reprocesa el pedido fallido. Esto es preferible a una falla silenciosa o bloquear todas las órdenes mientras se espera una solución de mapeo.

¿Esta integración puede admitir múltiples tiendas Shopify (por ejemplo, diferentes tiendas del mercado)?

Sí, pero con mayor complejidad. Cada tienda Shopify es una conexión API independiente. Una instancia de Odoo puede recibir pedidos de múltiples tiendas Shopify, con el origen de la tienda rastreado a través de un campo personalizado. La asignación de inventario entre tiendas requiere una lógica adicional: ya sea un grupo de inventario compartido (Odoo asigna entre tiendas según la demanda del pedido) o un inventario segregado por ubicación (cada tienda tiene una ubicación de Odoo designada). La integración de múltiples tiendas duplica el alcance de las pruebas y la carga de mantenimiento continuo.


Próximos pasos

Una integración Shopify-Odoo bien implementada transforma la eficiencia operativa: elimina la entrada manual de datos, evita la sobreventa, permite informes sofisticados y conecta las ventas de comercio electrónico con los procesos de fabricación, adquisiciones y financieros.

ECOSIRE crea Shopify y integraciones de Odoo ERP para comerciantes del mercado medio, cubriendo diseño de arquitectura, desarrollo personalizado, migración de datos, pruebas y soporte continuo. Nuestro equipo de integración ha implementado conexiones Shopify-Odoo para más de 30 comerciantes en diversas categorías de productos.

Contacta a nuestro equipo de integración para diseñar tu arquitectura de integración Shopify-Odoo.

E

Escrito por

ECOSIRE Research and Development Team

Construyendo productos digitales de nivel empresarial en ECOSIRE. Compartiendo perspectivas sobre integraciones Odoo, automatización de eCommerce y soluciones empresariales impulsadas por IA.

Más de eCommerce Integration

Chatea en whatsapp