Ir al contenido

Cómo crear un módulo en Odoo: estructura básica paso a paso

Un ejemplo completo con modelo, permisos, vistas y menú para entender cómo se construye un módulo en las versiones recientes de Odoo.

Table of contents

No titles in the blog post

Odoo está construido por módulos: Ventas, Inventario o el sitio web son módulos, y tú puedes crear los tuyos para agregar lo que tu empresa necesita. En esta guía construimos uno sencillo, paso a paso, con la sintaxis de las versiones recientes de Odoo.

La estructura de carpetas

Un módulo es una carpeta de Python con algunos archivos obligatorios. Nuestro ejemplo registrará los proyectos de los clientes:

Estructura del módulo
proyecto_cliente/
├── __init__.py
├── __manifest__.py
├── models/
│   ├── __init__.py
│   └── proyecto.py
├── security/
│   └── ir.model.access.csv
└── views/
    └── proyecto_views.xml

1. El manifiesto

El archivo __manifest__.py describe el módulo: nombre, versión, dependencias y qué archivos de datos cargar. La versión suele seguir el formato versión de Odoo + versión del módulo.

__manifest__.py
{
    "name": "Proyectos de clientes",
    "version": "20.0.1.0.0",
    "summary": "Registro sencillo de proyectos",
    "category": "Services",
    "author": "creationsdev",
    "license": "LGPL-3",
    "depends": ["base"],
    "data": [
        "security/ir.model.access.csv",
        "views/proyecto_views.xml",
    ],
    "application": True,
}

Los archivos __init__.py solo importan el código: en la raíz from . import models y dentro de models from . import proyecto.

2. El modelo

El modelo define la tabla y sus campos. Odoo crea la tabla en PostgreSQL automáticamente al instalar el módulo.

models/proyecto.py
from odoo import fields, models


class ProyectoCliente(models.Model):
    _name = "proyecto.cliente"
    _description = "Proyecto de cliente"

    name = fields.Char(string="Proyecto", required=True)
    cliente_id = fields.Many2one("res.partner", string="Cliente")
    fecha_entrega = fields.Date(string="Fecha de entrega")
    estado = fields.Selection(
        [("idea", "Idea"), ("desarrollo", "En desarrollo"), ("en_vivo", "En vivo")],
        default="idea",
    )

3. Los permisos de acceso

Sin permisos, nadie puede ver el modelo. El archivo CSV da acceso a los usuarios internos:

security/ir.model.access.csv
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_proyecto_cliente_user,proyecto.cliente.user,model_proyecto_cliente,base.group_user,1,1,1,1

4. Las vistas, la acción y el menú

Las vistas definen cómo se ve la información. Fíjate en dos detalles de las versiones recientes: la vista de lista usa la etiqueta <list> (antes <tree>) y la condición para ocultar un campo se escribe directamente en invisible, sin el antiguo attrs.

views/proyecto_views.xml
<odoo>
    <record id="proyecto_cliente_view_list" model="ir.ui.view">
        <field name="name">proyecto.cliente.list</field>
        <field name="model">proyecto.cliente</field>
        <field name="arch" type="xml">
            <list>
                <field name="name"/>
                <field name="cliente_id"/>
                <field name="fecha_entrega"/>
                <field name="estado"/>
            </list>
        </field>
    </record>

    <record id="proyecto_cliente_view_form" model="ir.ui.view">
        <field name="name">proyecto.cliente.form</field>
        <field name="model">proyecto.cliente</field>
        <field name="arch" type="xml">
            <form>
                <sheet>
                    <group>
                        <field name="name"/>
                        <field name="cliente_id"/>
                        <field name="estado"/>
                        <field name="fecha_entrega" invisible="estado == 'idea'"/>
                    </group>
                </sheet>
            </form>
        </field>
    </record>

    <record id="proyecto_cliente_action" model="ir.actions.act_window">
        <field name="name">Proyectos</field>
        <field name="res_model">proyecto.cliente</field>
        <field name="view_mode">list,form</field>
    </record>

    <menuitem id="proyecto_cliente_menu_root" name="Proyectos" action="proyecto_cliente_action"/>
</odoo>

5. Instalar el módulo

  1. Copia la carpeta del módulo en una ruta incluida en addons_path de tu configuración.
  2. Reinicia el servicio de Odoo.
  3. Activa el modo desarrollador, entra a Aplicaciones y usa Actualizar lista de aplicaciones.
  4. Busca "Proyectos de clientes" e instálalo.

Desde la terminal también puedes instalarlo con -i proyecto_cliente y actualizarlo después de cada cambio con -u proyecto_cliente, indicando la base de datos con -d.

Equipo de desarrollo probando un módulo nuevo de Odoo en un portátil
Prueba cada cambio en una base de datos de desarrollo antes de llevarlo a producción.

Buenas prácticas

  • Nunca modifiques el código de Odoo: extiende con herencia (_inherit en Python y xpath en vistas). Así tus cambios sobreviven a las actualizaciones.
  • Usa nombres con prefijo para evitar choques con otros módulos.
  • Define bien la seguridad: grupos, permisos y reglas de registro.
  • Escribe pruebas para la lógica importante.
  • Versiona tu código con Git y despliega desde ahí.

Un ejemplo real

Nuestro módulo Loterías Colombia sigue esta misma estructura, con modelos para juegos, sorteos y premios, vistas de análisis y páginas web públicas generadas desde los datos.

Cuando llegue la hora de actualizar tu módulo a una versión nueva, te servirá nuestra guía para migrar Odoo sin perder datos.

Preguntas frecuentes

¿Qué lenguajes necesito para crear módulos en Odoo?

Python para los modelos y la lógica, XML para vistas y datos, y JavaScript con el framework OWL si quieres personalizar la interfaz.

¿Puedo instalar mi módulo en Odoo Online?

No. Odoo Online no permite módulos personalizados. Necesitas Odoo.sh o un servidor propio.

¿Sirve el mismo módulo para Community y Enterprise?

Sí, mientras solo dependa de módulos disponibles en la edición donde lo instales.

¿Necesitas un módulo a la medida?

Desarrollamos módulos de Odoo para tus procesos, con código limpio y listo para actualizar.

Escríbenos por WhatsAppContar mi proyecto

Los precios, versiones y estados de proyectos mencionados corresponden a la fecha de publicación y pueden cambiar. Verifica siempre la información vigente en las fuentes oficiales de Odoo.