Sí, SEUR se conecta con Odoo, y para el caso base sin desarrollo a medida: el módulo delivery_seur_atlas del repositorio OCA l10n-spain, AGPL-3, para Odoo 15 a 19. Habla con la API Atlas por REST, crea la expedición al validar el albarán, adjunta la etiqueta al picking y escribe el código de envío en carrier_tracking_ref. Lo que nadie cuenta es qué credenciales pide, qué pasa con el multibulto y el reembolso, y por qué el seguimiento a veces no vuelve.
Todo lo técnico de aquí sale de leer el código, no de un folleto: delivery_seur_atlas 19.0.1.0.0 en OCA/l10n-spain, más delivery_state, delivery_package_number y delivery_price_method en la rama 19.0 de OCA/delivery-carrier. Campos, formatos, endpoints y códigos de evento están citados tal cual aparecen en el módulo.
¿Se puede conectar SEUR con Odoo?
Sí. El módulo añade «Seur Atlas» a la lista de proveedores del método de envío y, a partir de ahí, SEUR es un transportista más dentro de Inventario. Depende de tres módulos OCA de delivery-carrier —delivery_package_number, delivery_price_method y delivery_state— y sin los tres no instala.
La pregunta útil no es si se puede, sino qué cubre. Cubre alta de expedición, etiqueta, número de seguimiento en el albarán, enlace de rastreo, anulación e histórico de estados. No cubre tarifas, reembolso ni medidas reales de paquete. El resto del artículo es el detalle de esas dos listas.
Qué hace falta antes de tocar Odoo
Contrato con SEUR y credenciales de Atlas, que no salen de un panel de autoservicio: el README del módulo dice que las pidas a tu oficina de SEUR. Son seis campos y conviene tenerlos los seis antes de abrir el método de envío.
| Campo del módulo | Qué es |
|---|---|
seur_atlas_vat | NIF de la cuenta. Se rellena solo con el de la compañía. |
seur_atlas_account_code | Código de cuenta: dos números separados por un guion. El guion importa (ver el tracking). |
seur_atlas_username | Usuario del contrato. |
seur_atlas_password | Contraseña de ese usuario. |
seur_atlas_client | Código de cliente. Viaja como client_id. |
seur_atlas_secret | Secreto. Viaja como client_secret. No es la contraseña. |
Usuario y contraseña por un lado, client_id y client_secret por otro: cuatro secretos, no dos. El módulo los pide con los nombres de Odoo —usuario, contraseña, cliente, secreto—, que no tienen por qué coincidir con los del contrato: conviene mapearlos antes de rellenar nada.
# 1. Token: la peticion que hace el modulo antes de cualquier otra
POST https://servicios.apipre.seur.io/pic_token
grant_type=password
client_id=<Client> client_secret=<Secret>
username=<Username> password=<Password>
-> access_token # el modulo documenta 30 segundos de vida
# 2. Resto de llamadas, con Bearer <access_token>
POST /pic/v1/shipments # crea la expedicion
GET /pic/v1/labels # descarga la etiqueta
POST /pic/v1/shipments/cancel # anula
GET /pic/v1/tracking-services/extended # historico de estados
# Hosts que tiene que ver tu Odoo (puerto 443)
test servicios.apipre.seur.io
prod servicios.api.seur.ioDos detalles que salen caros. El entorno del método de envío decide si se llama a apipre o a api, y no es una casilla: es el botón de la cabecera que alterna entre Test Environment y Production Environment. Si se queda en pruebas, expides contra apipre y esas etiquetas no valen. Y el timeout por defecto es de 5 segundos, cambiable con el parámetro seur_atlas_timeout; con latencia se queda corto y el almacén ve un error que no lo es.
Qué se genera al validar y en qué formato sale la etiqueta
Al pulsar Validar, el módulo manda la expedición, recibe un shipmentCode, lo escribe en el campo de seguimiento del picking y descarga las etiquetas, que quedan como adjuntos del albarán. Ningún portal aparte: lo único que se interpone es el asistente de bultos, y solo cuando el albarán no trae paquetes hechos.
- Formato: PDF, ZPL o A4 troquelado.
- Plantilla:
NORMAL,CUSTOM_REFERENCE,Z4_ONE_BODY,Z4_TWO_BODIESoGEOLABEL. Cambia el diseño, no el formato del fichero. - Salida: el fichero, un enlace de descarga o los dos. Con «enlace» no te llega la etiqueta, te llega una URL.
- QR AZTEC: hay casilla, pero el propio campo avisa de que solo vale para recogidas ECB.
El detalle que quema: el ZPL no se guarda como PDF ni como .zpl, sino como adjunto .txt en ISO-8859-15, a propósito, porque SEUR manda la etiqueta con la instrucción ^CI10. Si tu cola de impresión lo reconvierte a UTF-8, los acentos del destinatario salen rotos: el fichero es correcto, el intermediario lo estropea.

carrier_tracking_ref.El fallo de configuración más frecuente. El módulo no calcula tarifas: su método de tarificación levanta un NotImplementedError. Y el campo Price method de delivery_price_method viene por defecto en «Carrier obtained price». Si lo dejas así y algo le pide precio a Odoo —la tienda, el botón de añadir envío al pedido—, revienta. Hay que ponerlo en Precio fijo o Basado en reglas.
Multibulto: el caso que rompe las integraciones ingenuas
El módulo manda una lista de bultos construida a partir de number_of_packages, el entero que aporta delivery_package_number y que un asistente pide al validar. El problema es lo que va dentro de cada bulto.
- El peso se reparte a partes iguales: el peso del envío dividido entre el número de bultos. Dos bultos de 2 y 18 kg se declaran como 10 y 10.
- Las medidas van a 1×1×1. Literalmente, en el código, con un TODO al lado reconociéndolo. Con eso, las medidas que recibe SEUR no son las del bulto real: cualquier cálculo suyo que dependa del volumen parte de un dato que el módulo se ha inventado.
- Si el número de bultos es cero, la lista se va vacía. El campo tiene 0 por defecto: si el tipo de operación no pregunta por bultos, o alguien valida desde código, se manda una expedición sin bultos.
Y la vuelta, que es donde duele en soporte: la respuesta que el propio test del módulo reproduce trae tres cosas —shipmentCode, ecbs y parcelNumbers— y el código solo lee la primera. Si un cliente reclama un bulto de seis, quien atiende no tiene su número. Las etiquetas sí vuelven una por bulto: cada una con su código de bulto, que es lo que da nombre al adjunto, y un campo pack del tipo «1/6» que el módulo ni mira.
Contra reembolso: qué campo lo lleva y qué pasa si falta
Respuesta corta: ninguno. El envío que se manda a SEUR no lleva importe de reembolso. Lo único parecido es un campo charges fijado a «P» en el código, que dice quién paga el porte: «P» la empresa, «D» el destinatario. No hay casilla para cambiarlo y el comentario del código lo admite. Eso es el porte, no el reembolso.

Qué pasa si falta: la expedición sale sin reembolso, el repartidor entrega sin cobrar y te enteras tarde, por el histórico de eventos. El módulo traduce los códigos de SEUR que rodean el reembolso —LI534 «comprobar si es reembolso», LI541 «sin efectivo a la entrega», LI552 «no aceptan reembolso»—, así que los eventos llegan; el importe es lo que no se manda nunca. Si vendes así, esto es desarrollo, no configuración.
Por qué el tracking no siempre vuelve a Odoo
Tres motivos, todos en el código, y ninguno es «la API va mal».
1. Es un cron diario, no tiempo real
delivery_state instala una acción planificada, «Update deliveries states», con intervalo de un día. Recorre los albaranes en estado Hecho cuyo estado de transportista no sea ya entregado, anulado o «sin más actualizaciones». Si esperas ver el estado diez minutos después de expedir, no va a pasar: o bajas el intervalo, o pulsas el botón en el albarán. Quien habla de «tracking en tiempo real» no ha mirado el cron.
2. Pregunta por tu referencia, no por el código de SEUR
La consulta va con tipo de referencia REFERENCE y, como referencia, el nombre del albarán (WH/OUT/00042), no el código de expedición que devolvió SEUR. Si la expedición se dio de alta fuera de Odoo, se creó en el portal con otra referencia o el albarán se renombró, SEUR no devuelve nada y el módulo sale en silencio: ni estado, ni error, ni aviso. Parece que funciona. Además el código de cuenta se parte por el guion para sacar cuenta y unidad de negocio: sin guion, la llamada ni se hace.
3. El estado que intenta escribir ya no existe
Este es el bueno. El módulo traduce 403 códigos de evento de SEUR a los estados de delivery_state. De ellos, 101 apuntan al valor incidence, igual que el valor por defecto para cualquier código desconocido. Y incidence ya no está en esa lista: la rama 15.0 de delivery_state lo tenía, la 16.0 lo renombró a incident y ahí sigue en la 19.0, mientras que el módulo de SEUR no lo cambió en ninguna de sus cinco ramas. Un campo de selección de Odoo no acepta un valor que no esté en su lista: levanta un ValueError. Hay un código, LI730, que además apunta a la cadena literal «SEE MESSAGE», que tampoco es un valor válido.
Traducido a almacén: mientras todo va bien, el tracking vuelve. En cuanto un envío entra en incidencia —ausente, dirección desconocida, retenido en aduana— o llega un código que el módulo no conoce, la actualización de ese albarán se cae. Desde el cron, el error se guarda en un campo del picking y se avisa en el canal de administración, donde nadie mira; desde el botón, te salta a la cara. Es el patrón exacto de la queja: «el tracking va… hasta que hay un problema». Y no salta en las pruebas porque el único test del módulo simula un código que mapea a «en tránsito».
Antes de depurar nada, activa el registro en el método de envío. Tampoco es una casilla: es el botón de la cabecera que pone No debug hasta que lo pulsas y pasa a Debug requests. El módulo llama al registro en cada petición, pero Odoo solo escribe en ir.logging con eso activado. Sin ello no tienes ni la petición ni la respuesta de SEUR: estás adivinando.
Cuándo compensa integrar y cuándo no
No es cuestión de tamaño de empresa, sino de dónde está el trabajo repetido. El criterio que usamos:
- Todavía no compensa por debajo de una decena de envíos al día con un solo servicio, un bulto y sin reembolso: el mantenimiento se comería el ahorro.
- Empieza a compensar en cuanto alguien retranscribe direcciones al portal: cada retranscripción es una entrega fallida en potencia, y una entrega fallida se paga dos veces en portes.
- Compensa claramente con más de un servicio SEUR que haya que acertar, multibulto habitual, soporte respondiendo «¿dónde está?» fuera de Odoo, o porte facturado que quieres en el pedido y no en una hoja de cálculo.
Y lo que hay que presupuestar aunque el módulo sea libre: parchear el mapeo de estados, añadir el reembolso, mandar medidas reales de paquete si algún día quieres tarifas y bajar el cron. Es un punto de partida honesto, no un producto terminado.
Si has llegado queriendo decidir entre SEUR y otro transportista, esa comparación no toca aquí: se decide por operativa y contrato, no por API. Está separada en logística en Odoo y en módulo nativo frente a OCA.
Preguntas frecuentes
¿Se puede conectar SEUR con Odoo sin desarrollo a medida?
Sí para el caso base: un servicio, un bulto, etiqueta y seguimiento. Hace falta desarrollo si vendes contra reembolso, si quieres que SEUR te tarifique o si necesitas los números de seguimiento por bulto.
¿En qué formato sale la etiqueta de SEUR en Odoo?
PDF, ZPL o A4 troquelado, con cinco plantillas, adjunta al albarán y una por bulto. El ZPL se guarda como fichero de texto en ISO-8859-15, no en UTF-8: si algo lo reconvierte, los acentos se rompen al imprimir.
¿Por qué el albarán no actualiza el estado del envío?
Tres motivos: la actualización va por un cron diario; la consulta se hace por el nombre del albarán y no por el código de expedición, así que cualquier desajuste devuelve vacío en silencio; y el estado de incidencia usa un valor que el módulo delivery_state renombró en su rama 16.0, de modo que falla justo cuando hay una incidencia.
Enlaces útiles
Lo que hacemos sobre esto
¿Quieres SEUR dentro de tu Odoo?
Miramos tu contrato, tu volumen y tu flujo real de almacén, y te decimos qué se resuelve con configuración y qué hay que desarrollar. Sin vender módulo antes de mirar.

