|
| 1 | + |
| 2 | +# Instrucciones para Copilot – Revisión de código Odoo (v18.0) |
| 3 | + |
| 4 | +## Contexto |
| 5 | + |
| 6 | +* El repositorio contiene **módulos Odoo** compatibles con la versión **v18.0** (o versiones compatibles cercanas). |
| 7 | +* El objetivo es **revisar cambios de código** y **sugerir mejoras seguras y relevantes**, sin hacer revisiones excesivamente estrictas. |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## Reglas generales |
| 12 | + |
| 13 | +1. **Responder siempre en español.** |
| 14 | +2. Detectar y corregir **errores de tipeo u ortografía evidentes** en nombres de variables, métodos o comentarios (cuando sean claros). |
| 15 | +3. No sugerir traducciones de docstrings o comentarios entre idiomas (no proponer pasar del inglés al español o viceversa). |
| 16 | +4. No proponer agregar docstrings si el método no tiene uno. |
| 17 | + |
| 18 | + * Si ya existe un docstring, puede sugerirse un estilo básico acorde a PEP8, pero **no será un error** si faltan `return`, tipos o parámetros documentados. |
| 19 | +5. No proponer cambios puramente estéticos (espacios, comillas simples vs dobles, orden de imports, etc.). |
| 20 | + |
| 21 | +--- |
| 22 | + |
| 23 | +## Revisión de modelos (`models/*.py`) |
| 24 | + |
| 25 | +* Verificar que: |
| 26 | + |
| 27 | + * Los campos (`fields.*`) tengan nombres claros, consistentes y no entren en conflicto con otros módulos. |
| 28 | + * Las relaciones (`Many2one`, `One2many`, `Many2many`) estén bien definidas y referencien modelos válidos. |
| 29 | + * Las constraints declaradas con `_sql_constraints` o `@api.constrains` mantengan la integridad esperada. |
| 30 | + * NOTA: En v19 se definen con `models.Constraint` |
| 31 | + * Los índices tradicionalmente se definían en `_sql_constraints = [('unique_name', 'UNIQUE(name)', 'mensaje')]`. |
| 32 | + * NOTA: En v19 usar `models.Index("campo")` para índices normales y `models.UniqueIndex("campo", "mensaje")` para únicos. |
| 33 | +* Sugerir uso de `@api.depends` si un campo compute carece de dependencias explícitas. |
| 34 | +* Si se redefine un método de Odoo, asegurar que se llama correctamente `super()`, manteniendo el contrato original. |
| 35 | +* Si hay lógica nueva, evitar loops costosos con búsquedas dentro de iteraciones; sugerir `mapped`, `filtered` u otras formas más eficientes. |
| 36 | + |
| 37 | +--- |
| 38 | + |
| 39 | +## 🧾 Revisión del manifest (`__manifest__.py`) |
| 40 | + |
| 41 | +* Confirmar que todos los archivos usados (vistas, seguridad, datos, reportes, wizards) estén referenciados en el manifest. |
| 42 | +* Verificar dependencias declaradas: que no falten módulos requeridos ni se declaren innecesarios. |
| 43 | +* **Regla de versión (obligatoria):** |
| 44 | + Siempre que el diff incluya **modificaciones en**: |
| 45 | + |
| 46 | + * definición de campos o modelos (`models/*.py`), |
| 47 | + * vistas o datos XML (`views/*.xml`, `data/*.xml`, `report/*.xml`), |
| 48 | + * seguridad (`security/*.csv`, `security/*.xml`), |
| 49 | + **y el `__manifest__.py` no incrementa `version`, sugerir el bump de versión** (por ejemplo, `1.0.0 → 1.0.1`). |
| 50 | + * Cambios funcionales mínimos → **patch** (`x.y.Z`). |
| 51 | + * Cambios de esquema o de compatibilidad → **minor** (`x.Y.0`). |
| 52 | + * Cambios disruptivos (breaking changes) → **major** (`X.0.0`). |
| 53 | + |
| 54 | +--- |
| 55 | + |
| 56 | +## Revisión de vistas XML (`views/*.xml`) |
| 57 | + |
| 58 | +* Confirmar que uses herencias (`inherit_id`, `xpath`) efectivamente, no redefiniciones completas innecesarias. |
| 59 | +* Validar que los campos referenciados en la vista existan en los modelos correspondientes. |
| 60 | +* Atento a cambios en versiones nuevas de Odoo: |
| 61 | + |
| 62 | + * En Odoo 18, el elemento `<tree>` fue reemplazado por `<list>` en vistas de tipo lista. |
| 63 | + * Odoo 18 simplificó atributos condicionales: `attrs`/`states` pueden reemplazarse por condiciones directas (`invisible="..."`, `readonly="..."`) cuando aplique. |
| 64 | +* Sugerir no duplicar vistas ni redefinir todo el `arch` si puede hacerse con `xpath`. |
| 65 | + |
| 66 | +--- |
| 67 | + |
| 68 | +## Seguridad y acceso |
| 69 | + |
| 70 | +* Verificar los archivos `ir.model.access.csv` para nuevos modelos: deben tener permisos mínimos necesarios. |
| 71 | +* No proponer abrir acceso global sin justificación. |
| 72 | +* Si se agregan nuevos modelos o campos de control de acceso, **recordar el bump de versión** (ver sección de manifest). |
| 73 | + |
| 74 | +--- |
| 75 | + |
| 76 | +## Detección de cambios estructurales (esquema / datos) |
| 77 | + |
| 78 | +Cuando el diff sugiera **cambios de estructura de datos**, **siempre proponer** un **script de migración** en la carpeta `scripts/`, usando pre/post/end según corresponda (ver mapeo más abajo) **y recordar el bump de versión**. |
| 79 | +Ejemplos de cambios estructurales: |
| 80 | + |
| 81 | +* Renombrar campos o modelos. |
| 82 | +* Cambiar tipos de campo (e.g. `Char → Many2one`, `Selection → Many2one`, `Float → Monetary`). |
| 83 | +* Quitar campos para reestructurar información en otros (split/merge). |
| 84 | +* Agregar campos `compute` **almacenados** (`store=True`) que requieren backfill. |
| 85 | +* Cambiar dominios/valores de `selection` (añadir/eliminar/renombrar keys). |
| 86 | +* Añadir `required=True` a campos existentes sin default en datos históricos. |
| 87 | +* Cambiar o añadir `_sql_constraints` (unique/index) que puedan fallar con datos existentes. |
| 88 | +* Cambios en `ir.model.data`/XML IDs (renombres, `no_update="1"`, cambios de `module`/`name`). |
| 89 | +* Cambios de reglas de acceso que requieran recalcular propiedad/propagación. |
| 90 | + |
| 91 | +--- |
| 92 | + |
| 93 | +## Scripts de migración en `scripts/`: pre / post / end |
| 94 | + |
| 95 | +> **Objetivo:** preservar datos y mantener instalabilidad/actualizabilidad segura. |
| 96 | +
|
| 97 | +- **pre**: Se ejecutan antes de actualizar el módulo. Útiles para preparar datos o estructuras que eviten fallos durante el upgrade. |
| 98 | +- **post**: Se ejecutan justo después de actualizar el módulo. Ideales para recalcular datos, limpiar residuos o ajustar referencias tras el cambio. |
| 99 | +- **end**: Se ejecutan al final de la actualización de todos los módulos. Indicados para tareas globales que dependen de múltiples módulos o para ajustes finales. |
| 100 | + |
| 101 | +### Mapeo de cambio → acción recomendada |
| 102 | + |
| 103 | +* **Rename de campo (mismo modelo)** |
| 104 | + |
| 105 | + * **Pre-script**: copiar datos del campo viejo al nuevo (o crear alias temporal) para no perder datos tras el upgrade. |
| 106 | + * **Post-script**: limpieza de residuos, recomputes si aplica. |
| 107 | + |
| 108 | +* **Eliminar campo y mover datos a otros campos (split/merge)** |
| 109 | + |
| 110 | + * **Pre-script**: crear campos destino (si es viable vía SQL/DDL) y migrar datos intermedios. |
| 111 | + * **Post-script**: normalizar referencias, recalcular computes, borrar helpers. |
| 112 | + |
| 113 | +* **Cambios en registros XML con `no_update="1"`** |
| 114 | + |
| 115 | + * **Post-script**: usar **force upgrade** (reaplicar datos) o actualizar esos registros por API (respetando `xml_id`) para reflejar cambios. |
| 116 | + |
| 117 | +* **Agregar campo `compute` con `store=True`** |
| 118 | + |
| 119 | + * **Pre-script (opcional si alto volumen/incidencia)**: crear columna en DB para evitar lock prolongado en upgrade. |
| 120 | + * **Post-script**: backfill **en lotes** (batch) para poblar el valor almacenado. |
| 121 | + |
| 122 | +* **Cambiar tipo de campo** |
| 123 | + |
| 124 | + * **Pre-script**: crear columna temporal con tipo nuevo y migrar datos (con conversión). |
| 125 | + * **Post-script**: swap/renombrar columnas, borrar columna vieja, recomputes. |
| 126 | + |
| 127 | +* **Cambios en `selection` (renombre/elim./nuevo valor default)** |
| 128 | + |
| 129 | + * **Pre-script**: mapear valores antiguos → nuevos (tabla de mapeo). |
| 130 | + * **Post-script**: validar que no quedan valores huérfanos. |
| 131 | + |
| 132 | +* **Agregar `required=True` a campo existente** |
| 133 | + |
| 134 | + * **Pre-script**: asignar default consistente a registros históricos (en lote) o rellenar desde lógica derivada. |
| 135 | + * **Post-script**: constraint check. |
| 136 | + |
| 137 | +* **Nuevas `_sql_constraints` (unique) / índices** |
| 138 | + |
| 139 | + * **Pre-script**: detectar y resolver duplicados o inconsistencias. |
| 140 | + * **Post-script**: crear índice/constraint y verificar. |
| 141 | + |
| 142 | +* **Renombrar modelo** |
| 143 | + |
| 144 | + * **Pre-script**: crear `ir.model.data`/mapeos, migrar `model` en `ir.model.data` y tablas rel. |
| 145 | + * **Post-script**: re-enlazar vistas, acciones, reglas y volver a chequear accesos. |
| 146 | + |
| 147 | +* **Cambios en XML IDs o modularización** |
| 148 | + |
| 149 | + * **Pre-script**: preparar mapeo `old_xmlid → new_xmlid`. |
| 150 | + * **Post-script**: actualizar referencias dependientes; si está marcado `no_update`, aplicar actualización manual. |
| 151 | + |
| 152 | +> **Regla general:** si el cambio puede **romper durante el upgrade**, prepara **pre-script**; si requiere **recalcular o reaplicar** después del código nuevo, usa **post-script**. Si se necesita una acción global al final, usa **end-script**. |
| 153 | +
|
| 154 | +--- |
| 155 | + |
| 156 | +## Convenciones de scripts en `scripts/` |
| 157 | + |
| 158 | +* Ubicación: `scripts/` |
| 159 | +* Nombres sugeridos: |
| 160 | + |
| 161 | + * `pre_<version>_<breve-descripcion>.py` |
| 162 | + * `post_<version>_<breve-descripcion>.py` |
| 163 | +* Requisitos: |
| 164 | + |
| 165 | + * Idempotentes (seguros si se ejecutan más de una vez). |
| 166 | + * En lotes (`batch_size` razonable) para datasets grandes. |
| 167 | + * Logs claros (uso de `_logger.info`). |
| 168 | + * Manejo de transacciones cuando aplique (evitar locks largos). |
| 169 | + * Documentar al inicio **qué suponen** y **qué garantizan**. |
| 170 | + |
| 171 | +**Esqueleto mínimo (ejemplo):** |
| 172 | + |
| 173 | +```python |
| 174 | +# scripts/pre_18.0_rename_partner_ref.py |
| 175 | +from odoo import api, SUPERUSER_ID |
| 176 | + |
| 177 | +def migrate(cr, registry): |
| 178 | + env = api.Environment(cr, SUPERUSER_ID, {}) |
| 179 | + # Ejemplo: copiar datos de 'old_ref' a 'new_ref' antes del upgrade |
| 180 | + partners = env['res.partner'].with_context(active_test=False).search([('old_ref', '!=', False)]) |
| 181 | + for batch in range(0, len(partners), 500): |
| 182 | + sub = partners[batch:batch+500] |
| 183 | + for p in sub: |
| 184 | + if not p.new_ref: |
| 185 | + p.new_ref = p.old_ref |
| 186 | +``` |
| 187 | + |
| 188 | +```python |
| 189 | +# scripts/post_18.0_backfill_stored_amount_total.py |
| 190 | +from odoo import api, SUPERUSER_ID |
| 191 | + |
| 192 | +def migrate(cr, registry): |
| 193 | + env = api.Environment(cr, SUPERUSER_ID, {}) |
| 194 | + Orders = env['sale.order'].with_context(active_test=False) |
| 195 | + ids = Orders.search([]).ids |
| 196 | + for i in range(0, len(ids), 200): |
| 197 | + batch = Orders.browse(ids[i:i+200]) |
| 198 | + # Forzar recompute del stored |
| 199 | + batch._compute_amount_total() |
| 200 | +``` |
| 201 | + |
| 202 | +--- |
| 203 | + |
| 204 | +## Checklist rápida para el review |
| 205 | + |
| 206 | +| Categoría | Qué comprobar Copilot | |
| 207 | +| ------------------ | -------------------------------------------------------------------------------------------------------- | |
| 208 | +| Modelos | Relaciones válidas; constraints; uso adecuado de `@api.depends`; `super()` correcto | |
| 209 | +| Vistas XML | Herencias correctas; campos válidos; adaptación a cambios de versión (p.ej. `<list>` vs `<tree>`) | |
| 210 | +| Manifest | **Bump de versión obligatorio** si hay cambios en modelos/vistas/seguridad/datos; archivos referenciados | |
| 211 | +| Seguridad | Accesos mínimos necesarios; reglas revisadas | |
| 212 | +| Migraciones | **Si hay cambios estructurales, exigir script en `scripts/` (pre/post/end)** y describir qué hace | |
| 213 | +| Rendimiento / ORM | Evitar loops costosos; no SQL innecesario; aprovechar mejoras de v18.0 | |
| 214 | +| Ortografía & typos | Errores evidentes corregibles sin modificar idioma ni estilo | |
| 215 | + |
| 216 | +--- |
| 217 | + |
| 218 | +## Heurística práctica para el bump de versión |
| 219 | + |
| 220 | +* **SI** el diff toca cualquiera de: `models/`, `views/`, `data/`, `report/`, `security/`, `wizards/` |
| 221 | + **Y** `__manifest__.py` no cambia `version` → **Sugerir bump**. |
| 222 | +* **SI** hay scripts `scripts/pre_*.py` o `scripts/post_*.py` nuevos → **Sugerir al menos minor bump**. |
| 223 | +* **SI** hay cambios que rompen compatibilidad (renombres, tipos, required sin default) → **Sugerir minor/major** según impacto. |
| 224 | + |
| 225 | +--- |
| 226 | + |
| 227 | +## Casos adicionales a cubrir (sugiere migración si aplica) |
| 228 | + |
| 229 | +* Introducción de **nuevos defaults** que dependen de datos existentes. |
| 230 | +* Cambio en **nombres técnicos** de vistas/acciones/menús (asegurar que `xml_id` no cambie o mapearlo). |
| 231 | +* **Indexaciones** nuevas (agregar índices en post para minimizar locks; validar cardinalidad). |
| 232 | +* Normalización de **monedas/impuestos** (migrar valores legacy; recalcular montos). |
| 233 | +* Cambios en **multi-company** o **multi-website** (poblar valores por compañía/sitio). |
| 234 | +* Ajustes en **traducciones** críticas de `selection` (asegurar mapping por key, no por etiqueta traducida). |
| 235 | + |
| 236 | +--- |
| 237 | + |
| 238 | +## Estilo del feedback |
| 239 | + |
| 240 | +* Ser breve, claro y útil. Ejemplos: |
| 241 | + |
| 242 | + * “El campo `partner_id` no se encuentra referenciado en la vista.” |
| 243 | + * “Este método redefine `write()` sin usar `super()`.” |
| 244 | + * “En v18.0, `<tree>` ya no se usa; reemplazar por `<list>`.” |
| 245 | + * “Tip: hay un error ortográfico en el nombre del parámetro.” |
| 246 | + * **Bump + migración:** “Se renombra `old_ref` → `new_ref`: falta **bump de versión** y **pre-script** en `scripts/` para copiar valores antes del upgrade; añadir **post-script** para recompute del stored.” |
| 247 | + |
| 248 | +* Evitar explicaciones largas o reescrituras completas salvo que el cambio sea claro y necesario. |
| 249 | + |
| 250 | +--- |
| 251 | + |
| 252 | +## Resumen operativo para Copilot |
| 253 | + |
| 254 | +1. **Detecta cambios en modelos/vistas/seguridad/datos → exige bump de `version` en `__manifest__.py`.** |
| 255 | +2. **Si hay cambio estructural → propone y describe script(s) de migración en `scripts/` (pre/post/inline),** con enfoque idempotente y en lotes. |
| 256 | +3. Mantén el feedback **concreto, breve y accionable**. |
0 commit comments