Secuencias Numéricas Automáticas y Gestión de Datos Maestros
En los sistemas empresariales, la mayoría de los documentos (presupuestos, facturas, préstamos, expedientes) requieren un código correlativo único autoincremental (por ejemplo, PREST/2026/0001). Odoo gestiona esta lógica de forma transaccional mediante el modelo ir.sequence.
1. Definición de la Secuencia en XML (data/ir_sequence_data.xml) #
Las secuencias se definen en la carpeta data/ y en este ejemplo se protegen con el atributo noupdate="1" para que el contador de la base de datos no se reinicie al actualizar el módulo:
1<?xml version="1.0" encoding="utf-8"?> 2<odoo> 3 <data noupdate="1"> 4 <!-- Secuencia correlativa para Préstamos de Biblioteca --> 5 <record id="seq_library_loan" model="ir.sequence"> 6 <field name="name">Secuencia de Préstamos</field> 7 <field name="code">library.loan.sequence</field> 8 <field name="prefix">PREST/%(year)s/</field> 9 <field name="padding">5</field> 10 <field name="number_next">1</field> 11 <field name="number_increment">1</field> 12 <field name="company_id" eval="False"/> 13 </record> 14 </data> 15</odoo>
code: Código de búsqueda (puede repetirse por compañía) que se utilizará desde el código Python.prefix: Prefijo configurable que admite variables dinámicas como%(year)s,%(month)so%(day)s.padding: Número de dígitos rellenados con ceros a la izquierda (ej.5produce00001,00002).
Añade data/ir_sequence_data.xml al manifiesto antes de las vistas.
2. Asignación Automática en el Método create del ORM #
Añade la siguiente clase al final de models/biblioteca.py; conserva el modelo original. Asignamos un valor por defecto provisional ('/' o 'Nuevo') y generamos el número definitivo durante la creación:
1from odoo import models, fields, api 2 3class LibraryLoanSequence(models.Model): 4 _inherit = 'library.loan' 5 _description = 'Préstamos de Libros' 6 7 name = fields.Char( 8 string='Número de Referencia', 9 required=True, 10 copy=False, 11 readonly=True, 12 default='/' 13 ) 14 15 @api.model_create_multi 16 def create(self, vals_list): 17 for vals in vals_list: 18 if vals.get('name', '/') == '/': 19 # Obtiene el siguiente número de secuencia de forma atómica y segura 20 vals['name'] = self.env['ir.sequence'].next_by_code('library.loan.sequence') or '/' 21 return super().create(vals_list)
3. Gestión de Datos con noupdate="1" vs noupdate="0" #
Cuando declaras archivos de datos o vistas en la lista 'data' de tu manifiesto, el comportamiento ante futuras actualizaciones del módulo depende del tag <data>:
1<odoo> 2 <!-- 1. noupdate="0" (Comportamiento por defecto): 3 Se actualiza al instalar o actualizar (-i/-u modulo), no por reiniciar. Ideal para vistas XML, menús y acciones. --> 4 <data noupdate="0"> 5 <!-- Vistas y menús aquí... --> 6 </data> 7 8 <!-- 2. noupdate="1": 9 Se inserta ÚNICAMENTE en la primera instalación del módulo. 10 Si el usuario final modifica el registro desde la UI de Odoo, la actualización del código NO lo sobrescribirá. 11 Ideal para: Secuencias, Categorías iniciales, Reglas de correo y Configuración base. --> 12 <data noupdate="1"> 13 <!-- Secuencias y datos maestros aquí... --> 14 </data> 15</odoo>
Resumen del tema
Conceptos clave #
- Secuencias Correlativas (
ir.sequence): generador transaccional de códigos correlativos únicos con formato parametrizable (prefix,suffix,padding). - Consumo en ORM: llamada a
self.env['ir.sequence'].next_by_code('codigo_secuencia')dentro del métodocreate(vals_list). - El Atributo
noupdate="1": protección de datos maestros y secuencias para evitar que actualizaciones posteriores del módulo sobrescriban los datos o reinicien contadores. - Separación
data/vsdemo/: los archivos endatason de infraestructura de negocio y siempre se cargan; los dedemose cargan cuando la instalación permite datos de demostración; no dependen del test runner.
Qué debes recordar #
noupdate="1" es una decisión de mantenimiento, no un requisito para que una secuencia funcione. Protege también las personalizaciones del usuario, pero una actualización deliberada puede requerir un script de migración.
Usa ir.sequence para generar códigos únicos y encapsula tus registros iniciales en <data noupdate="1"> para proteger los datos de negocio de tus clientes.