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.invoiceyaccount.move,stock.quant.packageystock.package,base.automationybase.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_automationen Odoo 10 llena el campo de disparador debase.action.rule, que esa versión llamakind(notrigger).
Detección¶
- Versión: mayor y menor de
common.version()(server_version_info, o parseado deserver_version); el mayor se acota a 10-19. El menor es 0 en una serie estable y N en las líneassaas~<mayor>.Nde Odoo Online, que quedan entre dos series estables: 18.0 < saas~18.1 < … < saas~18.4 < 19.0. ConODOO_TRANSPORT_PREFenautoojson2, 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), luegoGET /json/version(19.0+) y solo al final el clásicocommon.version.jsonrpcyxmlrpcconservancommon.versionprimero. El transporte guarda la serie sin acotar (p. ej. 20.0, saas~21.1) para su propia elección. - Edición: sufijo
+een la cadena de versión; si no, se sondea el móduloweb_enterprise(ir.module.module); si no,unknown. - Despliegue: host
*.odoo.com⇒saas, en otro casoonprem.odoo_online_profiledice además qué tan segura es esa detección (deployment_confidence):versioncuando la cadena de versión es una líneasaas~, que solo corre Odoo Online (entonces reportasaasincluso en un dominio propio);hostcuando solo decide el nombre del host, porque*.odoo.comtambién lo usa Odoo.sh, y una base Online en una serie estable detrás de su propio dominio pareceonprem.
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.