Skip to content

Integracion con Odoo ERP

Por que Odoo

Odoo es el ERP open source mas popular, con una comunidad activa y modularidad total. Es ideal para empresas de transporte que quieren personalizar su integracion sin depender de licencias costosas.

Lo que puedes integrar

Modulo OdooCon que se conectaQue sincroniza
Facturacion (account)Contratos firmadosFacturas de transporte
CRM (crm)Clientes de CargofferOportunidades y clientes
Inventario (stock)Datos de cargaMovimientos de stock
Compras (purchase)Servicios de transporteOrdenes de compra

Guia paso a paso: Integracion via XML-RPC

Paso 1: Conectar con Odoo

python
import xmlrpc.client

ODOO_URL = "https://tu-odoo.ondemand.com"
ODOO_DB = "produccion"
ODOO_USER = "admin"
ODOO_PASSWORD = "tu_password"

# Autenticar
common = xmlrpc.client.ServerProxy(f"{ODOO_URL}/xmlrpc/2/common")
uid = common.authenticate(ODOO_DB, ODOO_USER, ODOO_PASSWORD, {})

if uid:
    print(f"Conectado a Odoo (uid: {uid})")
else:
    print("Error de autenticacion")

Paso 2: Buscar o crear cliente por CIF

python
models = xmlrpc.client.ServerProxy(f"{ODOO_URL}/xmlrpc/2/object")

def buscar_cliente(cif):
    partner_ids = models.execute_kw(ODOO_DB, uid, ODOO_PASSWORD,
        "res.partner", "search", [[["vat", "=", cif]]])
    return partner_ids[0] if partner_ids else None

def crear_cliente(nombre, cif):
    partner_id = models.execute_kw(ODOO_DB, uid, ODOO_PASSWORD,
        "res.partner", "create", [{
            "name": nombre,
            "vat": cif,
            "customer_rank": 1,
            "company_type": "company"
        }])
    return partner_id

Paso 3: Crear factura desde contrato

python
def crear_factura_odoo(contrato):
    """Crea una factura de cliente en Odoo a partir de un contrato de Cargoffer."""
    
    # Buscar o crear el cliente
    partner_id = buscar_cliente(contrato["client"]["cif"])
    if not partner_id:
        partner_id = crear_cliente(
            contrato["client"]["name"],
            contrato["client"]["cif"]
        )
    
    # Crear factura
    invoice_data = {
        "move_type": "out_invoice",
        "partner_id": partner_id,
        "invoice_date": contrato["date"],
        "invoice_line_ids": [(0, 0, {
            "name": f"Transporte {contrato['serviceCode']}: {contrato.get('description', '')}",
            "quantity": 1,
            "price_unit": contrato["amount"],
            "tax_ids": [(6, 0, [])]  # Sin impuestos (IRPF de transportistas)
        })]
    }
    
    invoice_id = models.execute_kw(ODOO_DB, uid, ODOO_PASSWORD,
        "account.move", "create", [invoice_data])
    
    # Validar la factura (pasar a estado "publicada")
    models.execute_kw(ODOO_DB, uid, ODOO_PASSWORD,
        "account.move", "action_post", [[invoice_id]])
    
    return invoice_id

Paso 4: Automatizar con webhook

python
from flask import Flask, request
import threading

app = Flask(__name__)

@app.route("/webhook/cargoffer", methods=["POST"])
def webhook_cargoffer():
    evento = request.json
    
    if evento["event"] == "contract.signed":
        contrato = evento["data"]
        # Ejecutar en segundo plano
        threading.Thread(target=crear_factura_odoo, args=(contrato,)).start()
        return {"status": "ok", "message": "Factura en proceso"}, 200
    
    return {"status": "ignored"}, 200

Caso de uso: Sincronizacion diaria

Tu sistema puede ejecutar un proceso nocturno que:

  1. Consulta contratos del dia en Cargoffer
  2. Para cada contrato, crea la factura en Odoo
  3. Si el cliente no existe, lo crea automaticamente
  4. Marca el contrato como facturado
python
import requests
from datetime import datetime, timedelta

TOKEN=*** = "https://tu-odoo.com"

def sincronizacion_nocturna():
    ayer = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
    
    r = requests.get(
        f"https://api.pro.cargoffer.com/api/company/contracts/?dateFrom={ayer}",
        headers={"Authorization": f"Bearer {TOKEN}"}
    )
    
    for contrato in r.json():
        factura_id = crear_factura_odoo(contrato)
        print(f"Factura {factura_id} creada para {contrato['serviceCode']}")

Documentacion relacionada

Documentación de Cargoffer