Saltar al contenido principal
Odoo · Método de auditoría

Auditar un conector Odoo heredado: qué mirar en una tarde antes de tocar una línea

Has heredado un conector de marketplace, transportista, firma o EDI que hizo otro. Falla, o nadie se fía. Diez puntos, el síntoma que delata cada uno y la consulta que lo confirma en minutos.

Ficha de una instancia del conector Mirakl en Odoo: conexión de prueba OK, 206 ofertas y el contador de registros de llamadas a 0

Una auditoría útil de un conector Odoo no empieza por los tests. Empieza por el log y por una operación real de punta a punta: un pedido que entra, un envío que sale, un reembolso que vuelve. El conector Mirakl pasaba su suite en verde en Odoo 19, 18 y 17 y escondía 18 fallos confirmados; otro conector de marketplace daba 236 de 236 en builds reales de Odoo.sh y escondía 20 fallos de contrato y 12 de versión. Aquel artículo cuenta el fallo; este, el método: diez puntos en orden, el síntoma que delata cada uno y la prueba que cabe en una tarde.

Idea clave: el conector que heredas ya te dice qué le pasa, en la tabla de log y en los crons apagados.

Qué recoger antes de sentarte

Cuatro datos que no dependen de quien hizo el conector. La versión real de Odoo: SELECT latest_version FROM ir_module_module WHERE name = 'base';. La versión de la API del tercero que asume el código, casi siempre visible en la URL base. La fecha del último cambio de los mocks: git log -1 --format=%cd -- tests/. Y quién recibe los errores: un correo, una actividad, un fichero o nadie.

Los diez puntos, en orden

1. ¿Escribe el log de verdad?

Síntoma: la tabla de log tiene cero filas tras meses de crones. Prueba: SELECT last_value FROM pg_sequences WHERE sequencename = '<tabla_log>_id_seq';. Un NULL ahí significa que esa secuencia no se ha leído nunca: nadie borró las filas, es que no se escribió ninguna. Eso salió en la producción del conector Mirakl. El ayudante que devuelve el modelo de log devolvía un recordset vacío al tener éxito, y en Odoo un recordset vacío es falso, así que if not log_model: return False acertaba siempre y cada «esto lo registramos» era un no-op. El arreglo es if log_model is False.

2. La fecha de corte de la sincronización

Síntoma: un pedido creado por la mañana y enviado por la tarde se queda en Odoo con el estado de la mañana. Prueba: tres pedidos que cambiaron de estado ayer en el marketplace, comparados con write_date y el estado en Odoo. En Mirakl el conector pedía start_date, que filtra por fecha de creación, en vez de start_update_date, que filtra por fecha de cambio.

3. Idempotencia: doble pedido, doble reembolso

Síntoma: dos sale.order con la misma referencia externa, o un reembolso que aparece dos veces en el marketplace. Prueba: SELECT client_order_ref, count(*) FROM sale_order GROUP BY 1 HAVING count(*) > 1;, y crear un duplicado desde odoo shell para ver si la base lo rechaza de verdad: que la restricción esté escrita en el modelo no significa que exista en Postgres. En Odoo 19 un _sql_constraints heredado ya no crea nada y el ORM solo deja un aviso en el log, así que pierdes la garantía sin enterarte; al revés es ruidoso, porque models.Constraint no existe en 17 ni en 18 y ahí el módulo ni siquiera importa. Y el cliente HTTP: en Mirakl se reintentaba ante 5xx y timeout para cualquier método, también para el PUT del reembolso.

4. Errores HTTP y reintentos

Síntoma: la cuenta amanece «no autorizada» y toda la sincronización parada. Prueba: provoca un 401, un 429 y, si se puede, un 403 de cuota. En el segundo caso, el 403 de cuota no venía en el formato de error documentado y se leía como fallo de permisos: un límite de velocidad lo detenía todo. Lo que debe verse: Retry-After respetado y con un tope, los 5xx y los timeouts reintentados solo en lecturas, el 429 también en escrituras porque el servidor lo rechazó sin procesarlo, y la cuenta bloqueada solo por un fallo de autenticación real.

5. Mocks frente a contrato real

Síntoma: un campo que siempre llega vacío, un filtro que «no filtra». Prueba: pon el OpenAPI actual del proveedor en el repositorio y compara los parámetros de cada wrapper, las claves de cada cuerpo de escritura y los campos que lee cada parser. En el segundo caso salieron 16 discrepancias así en 88 operaciones, y cuatro más solo llamando: una cabecera de paginación relativa impedía importar un solo pedido a partir de la página uno.

6. Permisos y SSRF vía redirección

Síntoma: ninguno, y por eso va en la lista. Prueba: grep -rn "allow_redirects\|\.sudo()\|has_group" models/. Cada llamada saliente debe llevar allow_redirects=False y rechazar un 3xx, porque requests sigue redirecciones por defecto y un host comprometido puede mandarte a una IP interna. Y cada action_* que trabaja con sudo() debe comprobar el grupo en el servidor: el groups= del botón es solo interfaz. En julio de 2026 lo aplicamos a unos dieciséis conectores propios.

7. Crons: numbercall e intervalos

Síntoma: «el cron dejó de correr el martes», sin error ni traza. Prueba en Odoo 17: SELECT cron_name, active, numbercall, nextcall FROM ir_cron WHERE cron_name ILIKE '%conector%';. En 17 numbercall vale 1 por defecto, así que un cron declarado sin él corre una vez y se desactiva solo, como está en el ir_cron.py de la serie 17.0. Odoo 18 eliminó el campo y 19 no lo tiene, así que quien probó en 18 o 19 nunca lo vio. Y mira el intervalo: una sincronización completa cada diez minutos acaba en un 429.

8. La versión de Odoo que el código asume

Síntoma: un formulario sin chatter, una pestaña «payload» en blanco, un pedido cancelado en el marketplace que sigue confirmado en Odoo. Prueba: grep -rn "<chatter/>\|widget=\"json\"\|read_group\|<tree\|<list" views/ models/. En Mirakl salieron los cuatro a la vez: <chatter/> existe desde 18, widget="json" solo en 19, read_group está deprecado en 19, y sale.order.action_cancel() devuelve un asistente en 17 y 18 para un pedido confirmado, así que la cancelación nunca ocurría. Es la lista de un módulo que compila en Odoo 19 y no se instala.

9. Migración de los datos históricos

Síntoma: arreglas el cálculo y los pedidos antiguos siguen mal, porque el conector no vuelve a tocar un pedido existente. Prueba: cuenta los registros anteriores a la corrección que incumplen la regla nueva y decide entre un script de migración o una corrección única y documentada. En Mirakl fueron 18 pedidos con el IVA duplicado en el total; se corrigieron los 15 activos, solo si el total coincidía con el del marketplace. Y una trampa: los datos noupdate de base, los grupos entre ellos, no se reaplican al actualizar, así que un cambio de pertenencia deja el grupo vacío en producción y lleno en tu base limpia.

10. Documentación del tercero frente a comportamiento real

Síntoma: el código hace lo que dice el PDF y el servidor hace otra cosa. Prueba: una llamada real por familia de endpoint y una revisión de qué endpoints están deprecados hoy. En Mirakl el modelo de importación por fichero seguía vigente, pero la mensajería usaba un endpoint deprecado. En el segundo caso, un endpoint aceptaba un único valor donde la documentación decía lista, y ese referencial llevaba vacío desde el principio. Va el último porque es el más caro.

La tarde, resumida

PuntoSíntomaPrueba
LogCero filas tras meses de cronescount(*) y pg_sequences.last_value
Fecha de corteEstados congeladosPedidos de ayer contra write_date
IdempotenciaDuplicados, doble reembolsoGROUP BY HAVING; ¿rechaza la base el duplicado?
Errores HTTP«No autorizada» tras un 429/403Provocar 401, 429, 403
MocksCampo siempre vacíoOpenAPI actual contra wrappers y parsers
SSRF y permisosNingunogrep allow_redirects, sudo(), has_group
CronsSe apaga sin error (17)SELECT active, numbercall FROM ir_cron
Versión de OdooChatter o payload en blancogrep chatter, widget json, read_group, tree/list
HistóricoLo viejo sigue mal tras el arregloContar registros previos que incumplen la regla
DocumentaciónEl servidor no hace lo que dice el PDFUna llamada real por familia de endpoint

Qué sale de la auditoría: un informe con severidad, no una lista de deseos

El informe ordena por daño: primero dinero (doble reembolso, pedido duplicado, IVA dos veces), después datos (estado congelado, log que no escribe, cron apagado), después ergonomía. Cada hallazgo lleva su reproducción y lo que no se reproduce se tacha: en la auditoría de Mirakl entraron 121 candidatos, 33 se refutaron en un pase escéptico y solo 18 sobrevivieron.

La segunda salida es el gate: la suite que había, en verde antes y después, no prueba la corrección. La prueba es la corrida en las tres series sobre builds reales, 163 de 163 en 19, 18 y 17 para Mirakl, más una verificación en vivo. Es lo que separa un conector nativo bien hecho de una capa intermedia que sobrevive a base de no comprometerse.

Cuándo se parchea y cuándo se reescribe

Se parchea cuando el modelo de datos es correcto (una tabla por objeto del tercero, un log, una referencia externa única) y los fallos viven en la capa HTTP, las ventanas y las versiones: cabe en una versión, como con Mirakl. Se reescribe cuando falla el fondo: una API que el proveedor ha retirado, sin log ni referencia externa, escrituras no idempotentes por diseño, o un conector atado a una serie de Odoo cuando necesitas tres. Es la decisión que preparamos para consultorías y partners tecnológicos que heredan integraciones, y también cuando el conector es el de su propio software.

Preguntas frecuentes

¿Por qué no empezar por la suite de tests?

Porque una suite en verde dice que el código coincide con su mock, no con el proveedor ni con producción. La suite va al final, como gate de la corrección.

¿Hace falta acceso a producción?

Para los puntos 1, 2, 3, 7 y 9 sí, o a una copia: la secuencia del log, los estados congelados, los duplicados y los crons apagados solo se ven en datos reales.

¿Qué entregáis al final?

Un informe con cada hallazgo probado y ordenado por dinero, datos y ergonomía; la recomendación de parchear o reescribir; y, si se corrige, el arreglo con su gate en las series de Odoo del cliente. El detalle está en servicios.

Enlaces útiles dentro de FlexigoTech

Los tests estaban en verde y el conector no funcionaba32 fallos que la suite no veíaConector Mirakl OdooQué debe resolver en un marketplace realIngeniería Odoo para consultoríasAuditoría y soporte de integraciones heredadasPartners tecnológicosCómo trabajamos con partners de OdooConector Odoo para tu softwareCuando el conector a auditar es el de tu plataforma

Lo que hacemos sobre esto

Integraciones a medidaQué hace, capturas, versiones y precio.

¿Has heredado un conector que falla o del que nadie se fía?

Cuéntanos qué integra, en qué versión de Odoo corre y qué síntoma ves. Te decimos qué puntos de la lista miraríamos primero y qué hace falta para hacerlo. Escribe a comercial@flexigobe.com o llama al +34 616 809 504.

Hablar con un ingeniero