Saltar a contenido

Compatibilidad entre versiones (Odoo 10-19)

El servidor MCP resuelve nombres de modelos, campos y capacidades según la versión, edición y despliegue detectados. La fuente autoritativa y verificable es el mapa de deltas del repositorio (server/src/odoo_mcp/compat/deltas.py); esta página lo resume.

Novedades en v1.5.0

  • La política de permisos sigue los renombres. Una regla sobre cualquiera de los dos nombres de un par renombrado o fusionado de este mapa aplica a ambos, en todas las versiones (account.invoice y account.move, stock.quant.package y stock.package, base.automation y base.action.rule, etc.), y un rechazo sobre cualquiera de los dos gana. Ver Precedencia.
  • La matriz de sandboxes (Odoo 10.0 a 19.0) revisa también la política de permisos contra cada serie real, y omite con su razón una revisión cuyo modelo o campo no existe en esa serie.
  • odoo_add_automation en Odoo 10 llena el campo de disparador de base.action.rule, que esa versión llama kind (no trigger).

Detección

  • Versión: mayor y menor de common.version() (server_version_info, o parseado de server_version); el mayor se acota a 10-19. El menor es 0 en una serie estable y N en las líneas saas~<mayor>.N de Odoo Online, que quedan entre dos series estables: 18.0 < saas~18.1 < … < saas~18.4 < 19.0. Con ODOO_TRANSPORT_PREF en auto o json2, la versión se lee sin iniciar sesión y sin un endpoint obsoleto, así que no deja ninguna línea en el log de Odoo: primero la ruta propia del cliente web (POST /web/webclient/version_info, 10.0 en adelante), luego GET /json/version (19.0+) y solo al final el clásico common.version. jsonrpc y xmlrpc conservan common.version primero. El transporte guarda la serie sin acotar (p. ej. 20.0, saas~21.1) para su propia elección.
  • Edición: sufijo +e en la cadena de versión; si no, se sondea el módulo web_enterprise (ir.module.module); si no, unknown.
  • Despliegue: host *.odoo.com ⇒ saas, en otro caso onprem. odoo_online_profile dice además qué tan segura es esa detección (deployment_confidence): version cuando la cadena de versión es una línea saas~, que solo corre Odoo Online (entonces reporta saas incluso en un dominio propio); host cuando solo decide el nombre del host, porque *.odoo.com también lo usa Odoo.sh, y una base Online en una serie estable detrás de su propio dominio parece onprem.

Renombres de modelos

Nombre moderno Nombre histórico Frontera
account.move account.invoice ver la advertencia sobre v10 a v12
account.move.line account.invoice.line ver la advertencia sobre v10 a v12
stock.package stock.quant.package nuevo en v19

Para stock.package puedes pasar cualquiera de los dos nombres; el resolver devuelve el válido en la instancia destino.

Contabilidad: account.move y account.invoice NO son un simple renombre

En Odoo 13 el modelo de facturas account.invoice se fusionó dentro del modelo de asientos contables account.move (y account.invoice.line dentro de account.move.line). Pero en Odoo 10 a 12 ambos coexisten como modelos distintos con semántica distinta: account.move son los asientos de diario y account.invoice son las facturas.

Por eso, sustituir globalmente un nombre por otro es peligroso, sobre todo en escrituras y borrados (odoo_create/odoo_write/odoo_unlink): una operación pensada para facturas podría caer sobre asientos de diario (o viceversa) en v10 a v12.

Regla práctica en instancias v10 a v12: nombra explícitamente el modelo que quieres (account.invoice para facturas, account.move para asientos) y verifica con odoo_fields_get antes de escribir. En v13 y superiores ya solo existe account.move, así que la ambigüedad desaparece.

El resolver ya aplica esta regla: mapea account.invoice → account.move solo en v13+ y nunca reescribe account.move hacia atrás.

Cambios de campos

Modelo Campo Cambio Frontera
account.move.line analytic_account_id → analytic_distribution renombre v16
product.template uom_po_id eliminado (usar uom_id) saas~18.1 (Online) y 19.0
res.partner company_type eliminado (usar is_company) saas~19.1 (Online); sigue en 19.0

Las dos fronteras se verificaron contra el código fuente público de Odoo en cada rama estable y saas de la 16.0 a la saas-19.4.

Los campos eliminados se descartan de la consulta con una advertencia dropped_fields, en lugar de hacer fallar toda la llamada.

Capacidades

Capacidad Disponibilidad
api_key_auth Odoo ≥ 14 (las anteriores requieren contraseña)
update_field_translations Odoo ≥ 16 (las anteriores usan escritura con contexto de idioma)

Las API keys se aceptan igual en /jsonrpc y en /xmlrpc/2 (ambos llaman a dispatch_rpc de Odoo, 14 a 19), y son la única credencial que acepta JSON-2. El transporte auto conserva el fallback a XML-RPC para cuando un proxy bloquea o altera /jsonrpc.

Métodos

Método Cambio Usar en su lugar
name_get obsoleto en v17, eliminado en v18 leer display_name (10 a 19)
read_group (clásico) obsoleto en 19.0; no existe en saas~19.1 a saas~19.4; vuelve en 20.0 con la firma de _read_group formatted_read_group (saas~18.4+)
formatted_read_group nuevo en saas~18.4 (módulo web)
check_access_rights obsoleto en 19.0, eliminado desde saas~19.1 has_access (18.0+)

Las entradas de métodos también son datos (METHOD_DELTAS). odoo_read_group llama a formatted_read_group desde saas~18.4 y conserva los argumentos y la salida clásicos; ver la Referencia de herramientas.

Endpoints RPC

Novedades en v1.4.0: transporte JSON-2

Odoo 19 marca obsoletos /xmlrpc y /jsonrpc (cada llamada deja una advertencia en el log del servidor de Odoo), y Odoo 22 y Odoo Online saas~21.1 los retiran. Su reemplazo, JSON-2 (/json/2/<modelo>/<método>), existe desde saas~18.4 y 19.0 y acepta solo API key. Desde la v1.4.0 el plugin lo usa automáticamente.

Endpoint Series Credencial Notas
/xmlrpc/2 10.0 a 21.0 contraseña, o API key 14+ obsoleto en 19.0 (pasó al módulo rpc, de instalación automática); cada llamada deja una advertencia en el log de Odoo; se retira en Odoo 22 y en Odoo Online saas~21.1
/jsonrpc 12.0 a 21.0 contraseña, o API key 14+ igual que /xmlrpc/2 (ambos pasan por dispatch_rpc, 14 a 19)
JSON-2 POST /json/2/<modelo>/<método> saas~18.4, 19.0+ solo API key (Authorization: bearer) solo argumentos con nombre; cabecera X-Odoo-Database; sin advertencia de obsolescencia

Transporte auto

Con ODOO_TRANSPORT_PREF=auto (opción Transport preference, el valor por defecto), el servidor decide según la serie sin acotar, el tipo de credencial y si ODOO_URL lleva user:pass@ (autenticación básica para un gateway, que necesita la misma cabecera Authorization que la key de JSON-2):

Caso Orden Notas
Antes de saas~18.4 (Odoo 10 a 18, saas~18.1 a 18.3) JSON-RPC → XML-RPC como antes
saas~18.4 / 19.0+, con API key y sin user:pass@ JSON-2 → JSON-RPC → XML-RPC JSON-2 queda fijo tras el primer inicio de sesión; JSON-RPC y XML-RPC solo si un proxy bloquea JSON-2
mismo rango, con contraseña o user:pass@ JSON-RPC → XML-RPC desde 19.0 odoo_version devuelve un transport_notice con la solución y el servidor lo registra una vez
saas~21.1 / Odoo 22+, con API key solo JSON-2 ya no queda otro endpoint
saas~21.1 / Odoo 22+, con contraseña o user:pass@ ConfigError define una API key y quita user:pass@

json2 fuerza JSON-2; jsonrpc y xmlrpc fuerzan ese endpoint. Ninguno cambia de transporte por su cuenta. Una llamada pasa a otro transporte solo cuando este no puede ejecutarla dos veces: versión, inicio de sesión y lecturas siempre; escrituras solo si la petición nunca llegó a Odoo. Un límite de llamadas (HTTP 429) nunca cambia de transporte: las lecturas esperan Retry-After (máximo 30 s, 3 intentos) y las escrituras se reportan.

En JSON-2, odoo_execute recibe los ids de los registros en ids y los demás argumentos por nombre en kwargs. JSON-2 envía los métodos @api.readonly a un cursor de solo lectura, que es una réplica cuando el host de Odoo define db_replica_host: una lectura justo después de una escritura puede ir retrasada ahí.

Herramientas de Odoo Online

Las seis herramientas de Odoo Online funcionan en cualquier Odoo 10-19 y se degradan según la versión (detalle en la Referencia de herramientas):

Herramienta Notas por versión
odoo_online_profile API keys desde 14, caducidad desde 18; en 19.0 solo un administrador puede leer la lista de módulos (para otros usuarios vuelve null y unavailable dice por qué)
odoo_api_catalog /doc-bearer necesita 19.0+ y la API key de un administrador; un usuario normal recibe la tabla integrada
odoo_access_check por registro desde 18 (has_access); check_access_rights en 10-17; grupo de exportación desde 16
odoo_record_documents PDF guardado de la factura desde 17; estas herramientas no renderizan reportes (odoo_report está obsoleta y nunca funcionó por RPC)
odoo_import_preview 16-19, por JSON-RPC o JSON-2
odoo_import 12-19, por JSON-RPC o JSON-2; atómica en todas las versiones

Ediciones

Los modelos exclusivos de Enterprise (lista heurística: documents.document, sign.request, account.consolidation.period, quality.check, helpdesk.ticket, planning.slot, appraisal.appraisal) lanzan un CompatError cuando la instancia se detecta como Community. El sondeo de módulos en tiempo de ejecución es la fuente autoritativa.

Fronteras "best-effort"

Las fronteras que no se han confirmado contra el código de Odoo o una instancia real se marcan como best-effort. Como el mapa es dato plano cubierto por pruebas dirigidas por tabla, corregir una frontera es una edición de una línea más una fila de prueba (ver Contribuir). Además, cada semana el workflow de la matriz de sandboxes contrasta las entradas de res.partner con un Odoo Community 10.0-19.0 real, y desde la v1.5.0 también la política de permisos: el bloque policy de odoo_version contra --check-policy, los rechazos de standard que necesitan los metadatos de Odoo, el campo de enlace de cada modelo de delegación instalado, odoo_add_field y odoo_add_automation bajo builder (base.action.rule en 10.0) y --verify-audit sobre la auditoría de la ejecución; desde la v1.5.1, también el rechazo de un default_<campo> con una lista en un contexto pasado por posición. Desde la v1.6.0 el servidor inicia sesión con la API key del sandbox en cada serie desde la 14.0 (por JSON-2 en la 19.0) y con la contraseña en 10.0 a 13.0, y el workflow revisa que ninguna de las dos llegue a la auditoría y que un segundo sandbox up conserve la key.

En la práctica

Escribe contra el nombre moderno, salvo contabilidad en v10 a v12: account.invoice/account.move es una fusión, no un renombre. En v10 a v12 nombra explícitamente el modelo que quieres (account.invoice para facturas, account.move para asientos) y verifica con odoo_fields_get antes de escribir. El resolver (resolve_model) mapea account.invoice → account.move solo en v13+ y nunca reescribe account.move hacia atrás. Si una consulta devuelve dropped_fields, significa que ese campo no existe en la versión destino: revisa el nombre moderno equivalente en la tabla de arriba. Desde la v1.5.0, una regla de la política de permisos sobre account.move restringe también account.invoice en v10 a v12, y al revés. En v10 a v12, pasa el contexto por nombre (en kwargs): esas versiones toman como contexto un objeto pasado por posición, desde la v1.5.1 la política lo revisa como tal, y desde la v1.6.0 rechaza sus claves que no son campos del modelo ni claves de contexto permitidas (ver el límite conocido 10).

Referencia de skill: /odoo-tools:odoo-crossversion.