Anatomía de un módulo de Odoo: qué hay dentro y por qué importa
Abrimos un módulo de Odoo por dentro —manifiesto, modelos, campos, seguridad y vistas— para entender por qué casi todo se declara en lugar de programarse.
Forma parte de nuestra guía completa: Desarrollo de módulos en Odoo.
La primera vez que abrí un módulo de Odoo esperaba encontrar código. Mucho código. Bucles, controladores, plantillas HTML cosidas a mano. Lo que me encontré fue otra cosa: un puñado de archivos pequeños donde casi todo eran declaraciones. "Esto es un modelo. Tiene estos campos. Se muestra así. Lo puede ver este grupo." El motor hace el resto.
Esa es la idea que más cuesta interiorizar y, a la vez, la que explica por qué un buen módulo envejece bien. Vamos a abrir la caja pieza a pieza.
El manifiesto: el DNI del módulo
Todo módulo empieza por __manifest__.py. No tiene lógica; es la ficha de identidad que Odoo lee para saber qué cargar, en qué orden y de qué depende.
{
"name": "Inmobiliaria",
"version": "1.0",
"depends": ["base", "mail"],
"data": [
"security/ir.model.access.csv",
"views/property_views.xml",
"views/property_menus.xml",
],
"application": True,
"license": "LGPL-3",
}
Aquí ya hay decisiones importantes. El orden de la lista data es el orden de carga: si una vista referencia un permiso que aún no existe, Odoo se queja. Y depends no es decorativo: declara de qué módulos parte el tuyo, y eso condiciona qué puedes heredar. Un manifiesto descuidado es la primera señal de que el resto del módulo va a doler.
Modelos: una clase de Python que se convierte en tabla
El corazón del módulo es el modelo. Una clase que hereda de models.Model y que, casi por arte de magia, se traduce en una tabla de PostgreSQL sin que escribas una sola línea de SQL.
from odoo import models, fields
class Property(models.Model):
_name = "estate.property"
_description = "Propiedad inmobiliaria"
name = fields.Char(required=True)
expected_price = fields.Float()
bedrooms = fields.Integer(default=2)
date_availability = fields.Date()
El _name es la identidad global del modelo dentro de todo Odoo: con él se construye la tabla (estate_property), se referencian permisos y se enlazan relaciones. El _description parece un detalle cosmético, pero Odoo lo usa en mensajes de error y avisos; omitirlo es de las cosas que delatan prisa.
El tipo de campo dice más de lo que parece
Elegir entre Char, Text, Selection o Many2one no es solo elegir cómo se guarda el dato: define cómo se valida, cómo se indexa y cómo se ve en la interfaz. Un Selection te da una lista cerrada y consistente; un Char te deja la puerta abierta a que cada usuario escriba "Madrid", "madrid" y "MADRID". Esa decisión, tomada en treinta segundos, marca la calidad de tus datos durante años.
Por eso insisto tanto a los equipos: el modelado no es la parte aburrida previa a "lo interesante". El modelado es lo interesante. Lo desarrollamos a fondo en nuestra guía de buenas prácticas para módulos.
La seguridad no es un añadido
Aquí mucha gente tropieza. En cuanto creas un modelo, Odoo necesita saber quién puede leerlo, escribirlo o borrarlo. Si no se lo dices, el modelo existe pero nadie lo ve. El mínimo viable vive en un CSV:
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_property_user,property.user,model_estate_property,base.group_user,1,1,1,1
Esto es solo la mitad de la historia —los permisos a nivel de modelo—. La otra mitad, las reglas que filtran qué registros ve cada usuario, es donde se concentran los errores más caros. Le dedicamos un artículo entero: accesos vs reglas de registro.
Las vistas son XML, no plantillas
La interfaz de Odoo no se "programa". Se declara. Le dices qué campos quieres y en qué orden, y el framework dibuja el formulario, la lista o el kanban.
<record id="estate_property_view_form" model="ir.ui.view">
<field name="name">estate.property.form</field>
<field name="model">estate.property</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="name"/>
<field name="expected_price"/>
<field name="bedrooms"/>
</group>
</sheet>
</form>
</field>
</record>
Cuesta acostumbrarse si vienes de un mundo donde tú controlas cada <div>. Pero esta renuncia es justo lo que te da el panel responsive, el modo oscuro, los filtros y la edición en lote gratis. Pelearte con el framework para clavar un pixel suele salir caro; aprender a pensar en declaraciones, no.
Lo que aprendí abriendo módulos ajenos
He auditado bastantes módulos heredados, y los problemas casi nunca están en la lógica de negocio. Están en los cimientos: manifiestos con dependencias mal declaradas, campos Char donde debía haber relaciones, vistas que reescriben el formulario entero en vez de heredarlo. Cuando llega la migración a la siguiente versión, esos atajos pasan factura con intereses.
Entender la anatomía de un módulo no te convierte en desarrollador de Odoo de la noche a la mañana, pero sí te da algo más valioso: criterio para distinguir un módulo que durará de uno que será una carga. Y si vas a invertir en desarrollo a medida, ese criterio te ahorra dinero.
¿Tienes un módulo a medida que ya te da problemas en cada actualización, o un desarrollo nuevo entre manos? En una sesión de diagnóstico lo revisamos y te decimos sin rodeos si los cimientos aguantan. También puedes ver cómo abordamos el desarrollo de módulos.
Comentarios (0)
Sé el primero en comentar.
Inicia sesión para dejar un comentario.
AccederLos comentarios se revisan antes de publicarse.
Artículos relacionados
Acciones automatizadas en Odoo: deja que el ERP haga el trabajo aburrido
Acciones de servidor, reglas de automatización y tareas planificadas: las tres piezas para que Odoo reaccione, avise y ejecute solo, sin que nadie se acuerde.
Informes PDF con QWeb en Odoo: del formulario al documento que cierra ventas
QWeb es HTML que se convierte en PDF. Te enseñamos a montar un informe, recorrer registros con t-foreach y por qué t-field te ahorra mil dolores de cabeza.
Herencia en Odoo: la función que decide si tu código sobrevive a las actualizaciones
Extensión clásica, delegación y herencia de vistas. Las tres formas de modificar Odoo sin tocar el core —y por qué heredar en vez de copiar te ahorra cada migración.