Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
b0cb98e
[REF]stock_ux: remove _action_done overrite in stock.picking
mav-adhoc Dec 3, 2025
2bfc0bd
[ADD]stock_voucher: add email notification on voucher assignation
mav-adhoc Dec 3, 2025
dccf6e0
[FIX]stock_voucher:divition zero
jcadhoc Dec 12, 2025
75f2ba3
[FIX] stock_orderpoint_manual_update: Fix craation off new rules
maq-adhoc Dec 15, 2025
1af282b
[IMP] stock_voucher: added 'sequence_to' field to autoprinted deliver…
jue-adhoc Dec 15, 2025
71de7f0
Update project.toml from template
vib-adhoc Dec 17, 2025
0efa3b5
[UPD] Copilot instructions
adhoc-cicd-bot Dec 19, 2025
189360d
[FIX] stock_ux: Check column exists before creating in pre-migration …
ced-adhoc Dec 19, 2025
a0ab091
[FIX]stock_ux: margin in zpl report
mav-adhoc Nov 21, 2025
55347f5
[FIX]stock_voucher: calculate package number correctly
mav-adhoc Dec 30, 2025
05d91eb
[FIX]stock_ux: call super() in _check_quantity in stock.move
mav-adhoc Dec 22, 2025
f4becaf
[UPD] Copilot instructions
adhoc-cicd-bot Jan 14, 2026
f65d74d
[FIX]stock_ux: add origin condition to origin description
mav-adhoc Jan 20, 2026
9e1b187
[FIX]stock_ux:hide return button
jcadhoc Jan 22, 2026
1d01237
[FIX]stock_voucher:declared value
jcadhoc Jan 8, 2026
b6de1fa
Update project.toml from template
vib-adhoc Jan 29, 2026
bf9c48b
[IMP] stock_ux: apply improved superuser handling for quantity constr…
jcadhoc Feb 5, 2026
f81fbcd
[UPD] Copilot instructions
adhoc-cicd-bot Feb 18, 2026
e7ea750
[IMP] stock_ux: Mover validación de cantidad de constraint a button_v…
vib-adhoc Jan 29, 2026
24a2558
[IMP]stock_picking_state: add operation type
jcadhoc Mar 3, 2026
45065c2
[FIX]stock_voucher_ux: controller page counting
mav-adhoc Mar 5, 2026
da2fdf9
[IMP] stock_currency_valuation: add with company
maq-adhoc Mar 4, 2026
e0379bd
[FIX] stock_currency_valuation: fix currency diff SVL
maq-adhoc Mar 13, 2026
e3d8273
[ADD]stock_ux: Add ZPL report for product labels
jcadhoc Mar 16, 2026
f057fe9
[BOT] Bump version: stock_ux 18.0.1.9.0
roboadhoc Mar 17, 2026
46201c8
[IMP] stock_currency_valuation: Fix picking default valuation
maq-adhoc Mar 16, 2026
9f7ab12
[FIX] stock_currency_valuation: Fix ignore _prepare_pdiff_vals when s…
maq-adhoc Mar 19, 2026
9df7452
[FIX] stock_currency_valuation: User error on secondary currency purc…
feg-adhoc Mar 18, 2026
8e567fb
[FIX] stock_ux: prevent deletion of moves from orders
jcadhoc Feb 19, 2026
a8d3eb9
[FIX]stock_ux: check_manual_lines execution time
mav-adhoc Mar 27, 2026
2622dd7
[IMP]stock_ux: improve margin in stock.picking.type kanban view
mav-adhoc Apr 15, 2026
114d817
[IMP] stock_voucher: add active field to stock book
les-adhoc Apr 14, 2026
881e5a6
[FIX]stock_ux:delete in mrp explode
jcadhoc Apr 23, 2026
5bc8776
[IMP] stock_voucher_ux: add translations for error msgs and sequence_…
jue-adhoc May 5, 2026
1e29975
[BOT] Bump version: stock_voucher_ux 18.0.1.3.0
roboadhoc May 6, 2026
1e7ca83
[IMP] stock_ux: add configurable multiple above max replenishment
les-adhoc May 15, 2026
97028f7
[FIX]stock_batch_picking_ux: assign book_id when validating a batch p…
mav-adhoc Apr 9, 2026
75ba994
[BOT] Bump version: stock_batch_picking_ux 18.0.1.2.0
roboadhoc May 20, 2026
f682d5a
[FIX] stock_currency_valuation: apply UoM conversion when secondary c…
rov-adhoc May 18, 2026
b07e73e
[FIX] stock_orderpoint_manual_update: preserve replenishment notifica…
les-adhoc May 20, 2026
fb91712
[FIX] sale_order_type_invoice_policy_invoice_link: avoid access error…
les-adhoc May 26, 2026
b0c08d8
[FIX] stock_ux: add migration for multiple over max fields
les-adhoc May 26, 2026
e16cba8
[IMP]stock_ux: print move description if no sale line
mav-adhoc May 19, 2026
bc3a429
[ADD] stock_delivery_zone: backport from 19.0 to 18.0
les-adhoc Jun 9, 2026
a740484
[FIX] stock_orderpoint_manual_update: keep qty_forecast in DOM to avo…
mav-adhoc Jun 12, 2026
5510a86
[FIX] stock_ux: skip manual lines check on manual action_assign
jcadhoc Jun 11, 2026
e4aac34
[FIX] stock_voucher_ux: asignar números de remito antes de imprimir
mav-adhoc Jun 2, 2026
40c9206
[FIX] stock_voucher_ux: regenerar PDF tras asignar números en autopri…
mav-adhoc Jun 2, 2026
e3a95ce
[FIX] stock_voucher_ux: usar XML ID correcto para regenerar PDF de re…
mav-adhoc Jun 3, 2026
118efa8
[FIX] stock_voucher_ux: flush ORM antes de regenerar PDF con nros de …
mav-adhoc Jun 3, 2026
6480d59
[FIX] stock_voucher/ux: asignar nros de remito antes de imprimir (pre…
mav-adhoc Jun 3, 2026
5c4c4f2
[IMP] stock_batch_picking_ux: improve batch detailed operations behavior
les-adhoc Jun 1, 2026
22aafbe
[FIX] stock_batch_picking_ux: reset quantities to zero only on recept…
les-adhoc Jun 17, 2026
ce5fe2b
[FIX] stock_ux: allow return moves when block_additional_quantity is set
lef-adhoc Jun 18, 2026
cee7a2b
Fix warehouse propagation in MTO procurements
jcadhoc May 21, 2026
7b9376a
[FIX] stock_ux: narrow MTO warehouse propagation fix
jcadhoc May 26, 2026
df356f2
[FIX] stock_ux: avoid AttributeError when mrp_subcontracting is absent
Jun 24, 2026
e6fd8cc
[FIX] stock_ux: add missing EOF newline in MTO test
Jun 24, 2026
563719c
[FIX] location_security: avoid false 'Invalid Location' outside picki…
Jun 18, 2026
8fda9c2
[REM] stock_picking_returned_qty: deprecate unused module
Jun 26, 2026
975c62f
[FIX] stock_voucher_ux: number preprinted vouchers by real pages
mav-adhoc Jun 25, 2026
f5dc113
[FIX] stock_voucher: propagate super() result on cancel backorder
les-adhoc Jul 2, 2026
7f12109
[BOT] Bump version: stock_voucher 18.0.1.7.0
roboadhoc Jul 6, 2026
4bb3651
[FIX] stock_voucher_ux: read aeroo copies from the printed remito report
mav-adhoc Jul 6, 2026
1392828
[IMP] Update repository from template
vib-adhoc Jul 20, 2026
a65a34f
Merge pull request #977 from adhoc-dev/18.0-update-repository-stock
az-adhoc Jul 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .copier-answers.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Do NOT update manually; changes here will be overwritten by Copier
_commit: d46567f
_commit: 8677dea
_src_path: https://github.com/ingadhoc/addons-repo-template.git
description: ADHOC Odoo Stock & Warehouse Management Addons
is_private: false
Expand Down
364 changes: 50 additions & 314 deletions .github/copilot-instructions.md

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions .github/instructions/i18n.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
applyTo:
- "**/models/**/*.py"
- "**/wizards/**/*.py"
- "**/wizard/**/*.py"
- "**/controllers/**/*.py"
- "**/report/**/*.py"
- "**/i18n/**/*.po"
- "**/i18n/**/*.pot"
---

# Revisión de internacionalización (i18n)

## Marcar texto traducible

- Todo texto que se muestra al usuario debe estar envuelto en `_()` o `self.env._()` (indistinto):
```python
raise UserError(_("No se puede eliminar un pedido confirmado."))
return {'warning': {'title': _("Atención"), 'message': _("Stock insuficiente.")}}
```
- Import típico: `from odoo import _, _lt` (usar `_lt` cuando el texto se define a nivel módulo/clase y la traducción se resuelve en runtime).

## Qué marcar como issue

- `raise UserError("...")` o `ValidationError("...")` con string literal.
- `return {'warning': {'message': "texto"}}`.
- Mensajes de `raise`, `notifications`, toast, `display_name` calculado, labels en wizards, títulos de acciones construidas dinámicamente.
- Textos en `_message_post` que muestran al usuario.

## Qué NO marcar

- Nombres técnicos de campos (`'partner_id'`, `'name'`).
- Claves de diccionarios (`'state': 'draft'`).
- Logs técnicos (`_logger.info("...")`) — no se traducen.
- Nombres de xml_ids.
- Cadenas en tests, comentarios, docstrings.
- `fields.Char(string="Name")`: el `string=` se recoge para i18n automáticamente, no requiere `_()`.

## Uso correcto de `_()`

- `_()` resuelve traducción **en el momento de la llamada** (runtime del idioma del usuario).
- `_lt()` (lazy translate) para strings definidas a nivel módulo; la traducción se resuelve al serializar, útil en selecciones y listas de constantes.
- No concatenar fragmentos traducibles con `+`: usar `%` o f-string sobre la cadena ya traducida:
```python
# MAL (rompe traducción)
raise UserError(_("Error en ") + record.name)
# BIEN
raise UserError(_("Error en %s") % record.name)
```
- Evitar format con claves traducibles múltiples; preferir placeholders con nombre:
```python
raise UserError(_("Falta %(field)s en %(model)s") % {'field': name, 'model': model})
```

## Archivos `.po` / `.pot`

- No editar manualmente traducciones generadas por `odoo i18n export` salvo correcciones puntuales.
- Commits que solo tocan `.po` / `.pot` de exportación suelen ser benignos; no requieren tests ni script de migración.
- Si se agrega un idioma nuevo, verificar que esté listado en `i18n/` y que las cadenas base existan en `.pot`.

## Convención del equipo (ADHOC)

- Idioma destino principal: **español latinoamericano formal**. Evitar tuteo en mensajes de sistema ("usted" vs "tú").
- Mantener consistencia terminológica: "pedido" (no "orden"), "contacto" (no "partner" en user-facing), "factura", etc.
- Placeholders (`%s`, `%(name)s`) deben mantenerse idénticos entre el mensaje original y la traducción.

## Criterio de severidad

- **Medio**: texto al usuario sin `_()`, aislado.
- **Bajo**: patrón que podría mejorarse (concatenación con `+`, falta de `_lt` en constante de módulo).
- No-issue: archivo `.po` autogenerado con cambios de exportación rutinarios.
48 changes: 48 additions & 0 deletions .github/instructions/manifest.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
applyTo:
- "**/__manifest__.py"
---

# Revisión de `__manifest__.py`

## Archivos referenciados

- Todo archivo usado por el módulo (vistas, seguridad, datos, reportes, wizards, demo) debe estar listado en alguna de las claves del manifest (`data`, `demo`, `assets`).
- Si un archivo XML/CSV se borra del módulo, debe removerse del manifest; si se agrega uno nuevo, debe incluirse.
- Orden relativo importa: datos de seguridad antes de datos que los referencian; vistas después de sus modelos.

## Dependencias (`depends`)

- Deben listarse todos los módulos cuyos modelos/vistas/xml_ids se usan directamente.
- **No** declarar dependencias innecesarias (infla el árbol de instalación).
- Módulos de localización (`l10n_*`) solo cuando el módulo depende funcionalmente; no por conveniencia.

## Versión

- Formato `<serie>.<mayor>.<menor>.<patch>` (ej. `19.0.1.0.0`). La serie (`19.0`, `18.0`) debe coincidir con la rama y la versión de Odoo target.
- **Regla obligatoria de versión**: cualquier cambio estructural que requiera script en `migrations/` debe **bumpear la versión** del módulo, y la carpeta bajo `migrations/` debe coincidir.
- Solo comentar la versión **una vez por revisión**, aunque haya múltiples archivos afectados.

## Metadatos

- `name`, `summary`, `description` deben estar definidos y ser consistentes.
- `author`, `license` presentes. En Adhoc, típicamente `"ADHOC SA"` y licencia según convención del repo.
- `category` coherente con el tipo de módulo.
- `installable: True` salvo que explícitamente esté siendo discontinuado.
- `application: True` solo para módulos que deben aparecer como aplicación raíz (no para sub-módulos).

## Assets (bundles)

- `assets` debe listar bundles correctos (`web.assets_backend`, `web.assets_frontend`, `web.report_assets_common`, `web.assets_tests`, etc.).
- Extensiones coherentes: `.js`, `.scss`, `.css`, `.xml` (OWL templates).
- Archivos borrados deben quitarse también de `assets`.

## Hooks

- `pre_init_hook`, `post_init_hook`, `uninstall_hook`, `post_load`: si están declarados, verificar que apunten a funciones existentes en el módulo (`from . import hooks` o similar).
- Los hooks deben ser idempotentes y no dependientes de datos demo.

## Demo data

- Datos de demo en la key `demo`, **no** mezclados con `data`.
- Al introducir funcionalidad nueva que se beneficia de casos visibles, considerar agregar demo; al introducir módulo de configuración, no es necesario.
59 changes: 59 additions & 0 deletions .github/instructions/migrations.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
applyTo:
- "**/migrations/**/*.py"
- "**/__manifest__.py"
- "**/models/**/*.py"
---

# Revisión de scripts de migración

> Si el diff introduce cambio estructural en un modelo, **siempre** evaluar si corresponde proponer script en `migrations/<version>/`.

## Cuándo proponer script

1. **Rename de campo almacenado** (`Char`, `Many2one`, etc. o `compute` con `store=True`). **No** si es `compute` sin store.
2. **Rename de modelo**: siempre. Toca `ir.model`, `ir.model.data`, tablas relacionales, vistas, acciones.
3. **Cambio de tipo de campo** con cambio real en DB (`Char→Many2one`, `Selection→Many2one`, `Many2one→Many2many`). Cambios compatibles (`Char→Text`, ajustes de `Float`) no requieren script.
4. **Split/merge de campos**.
5. **Nuevo `compute` con `store=True`** que aplique a registros históricos → post-script de backfill en lotes. Advertir si el modelo tiene millones de registros.
6. **Cambio en keys de `selection`**: renombrar/eliminar existentes → script que mapee `old → new`. Agregar nuevas keys **no** requiere script.
7. **Cambio de dominio** en relacional que excluya valores usados históricamente → limpiar/remapear.
8. **Nueva `UNIQUE`/índice** (`_sql_constraints` o `models.Constraint`): pre-script que resuelva duplicados antes de crear la constraint.
9. **Cambios en `ir.model.data` / XML IDs** (rename `module.name → module2.name2`): script para actualizar referencias.
10. **Registros con `noupdate="1"`** cuyo contenido lógico cambia: forzar update por `xml_id`.
11. **Cambios en reglas de acceso / multi-company / multi-website**: rellenar campos obligatorios, recomputar ownership.

> **No** proponer script solo por `required=True` nuevo sin default, salvo que el diff evidencie datos históricos incompatibles.

## Pre / Post / End

- **pre**: antes del update. Preparar datos/esquemas para evitar fallos.
- **post**: después. Recalcular, limpiar, ajustar referencias.
- **end**: al final del upgrade global. Tareas cross-módulo o finales.

Regla: **rompe durante el upgrade → pre**; **recalcula después → post**; **global al final → end**.

## Mapeo cambio → acción

- **Rename campo almacenado** → pre: copiar datos viejo→nuevo. Post: cleanup + recomputes.
- **Rename modelo** → pre: mapear `ir.model`/`ir.model.data`. Post: re-enlazar vistas, acciones, menús, reglas.
- **Split/merge** → pre: copiar a nuevos campos antes de que el schema borre el viejo. Post: normalizar/recompute.
- **`compute` nuevo con `store=True`** → post: backfill en lotes (pre opcional en modelos grandes para preparar columna).
- **Cambio de tipo con conversión** → pre: columna temporal + conversión. Post: swap/rename/borrar vieja.
- **`selection` (remove/rename keys)** → pre: mapeo `old → new` (usar `change_field_selection_values` si aplica). Post: validar consistencia.
- **Nueva `UNIQUE`** → pre: resolver duplicados. Post: crear índice si aplica.
- **`noupdate="1"` con cambio lógico** → post: update por `xml_id`.

## Convenciones

- Ubicación: `migrations/<module_version>/` (ej. `migrations/19.0.1.0/`). Versión debe coincidir con `__manifest__.py`.
- Nombres: `pre_<desc>.py`, `post_<desc>.py`, `end_<desc>.py`.
- **Idempotentes**: seguros ante re-ejecución.
- **En lotes** (`batch_size` razonable) para datasets grandes.
- Logs claros (`_logger.info`); comentario al inicio documentando supuestos y garantías.
- Evitar transacciones muy largas; `env.cr.commit()` controlado o helpers de progreso.

## Versión del manifest

- Al introducir cambio estructural, **bumpear** versión en `__manifest__.py` para que el script corra (ej. `19.0.1.0 → 19.0.2.0`).
- La carpeta bajo `migrations/` debe coincidir con la nueva versión.
68 changes: 68 additions & 0 deletions .github/instructions/models.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
applyTo:
- "**/models/**/*.py"
- "**/wizards/**/*.py"
- "**/wizard/**/*.py"
- "**/report/**/*.py"
---

# Revisión de modelos Python

## Relaciones y campos

- `Many2one`/`One2many`/`Many2many` deben declarar `comodel_name` y `ondelete` apropiado. Evitar `ondelete='cascade'` sin justificación.
- Nombres de campos claros, consistentes, sin conflictos con campos heredados.
- `required=True` sin `default` **solo** si no hay datos históricos que puedan romperse. Si los hay, proponer `default` o migración.
- Campos `compute` con `store=True` que dependen de datos históricos pueden necesitar backfill (ver `migrations.instructions.md`).

## Decoradores `@api.*`

- `@api.depends` debe listar **todas** las dependencias reales, incluidas las dotted (`@api.depends('partner_id.email')`).
- `@api.constrains` **no** acepta dotted paths, solo nombres simples.
- `@api.onchange` no debe escribir a BD ni modificar campos computados.
- Evitar decoradores obsoletos: `@api.one`, `@api.multi` (Odoo 13+ no los acepta).
- **Odoo 18+**: para prevenir borrado usar `@api.ondelete(at_uninstall=False)` en vez de sobreescribir `unlink`.
- `@api.model` solo cuando el método no depende de `self` como recordset.
- `@api.model_create_multi` para métodos `create` que aceptan lista de dicts (obligatorio en Odoo 17+).

## Herencia y `super()`

- Métodos redefinidos deben llamar `super()` salvo que el contrato diga lo contrario. Preservar el tipo/shape del retorno.
- `_name` + `_inherit` juntos solo cuando se busca crear modelo nuevo (multi-table inheritance); marcar si no hay razón clara.
- No sobrescribir `create`/`write`/`unlink` solo para side effects triviales; preferir `@api.depends`, `@api.constrains` o `@api.ondelete`.

## Constraints e índices

- **Odoo 19+**: usar `models.Constraint(...)`, `models.Index(...)`, `models.UniqueIndex(...)` como declarativas a nivel de clase, en vez de `_sql_constraints`. Si el diff ya toca constraints, sugerir migrar a la nueva API.
- Mensajes de constraint deben ser traducibles (`_("...")`).
- Añadir `UNIQUE` sobre tabla con datos existentes puede fallar; ver `migrations.instructions.md`.

## ORM seguro y eficiente

- Evitar `search` dentro de loops → usar dominio con `in` sobre ids o `_read_group`.
- Evitar `write`/`create`/`unlink` uno a uno en loops → vectorizar sobre recordset.
- `create` en Odoo 17+: preferir lista de dicts `create([{...}, {...}])`.
- `mapped`, `filtered`, `search_count`, `search_fetch` antes que recorrer en Python.
- Navegación relacional segura: `rec.partner_id.email` devuelve falso si `partner_id` vacío; no duplicar el check.
- Acceso por índice (`recordset[0]`) puede lanzar `IndexError`; guardar con `if rec: ...` o rediseñar para operar sobre el recordset completo.
- Evitar `sudo()` amplio/innecesario en métodos de negocio; justificar cada uso.
- En Odoo 19, `cr.execute` crudo desaconsejado → usar clase `SQL` con `execute_query_dict()`. Si hay `cr.execute` con interpolación (`%`, f-string, `.format`) → bloqueante, ver `security.instructions.md`.

## Nombres y estilo

- Métodos privados prefijo `_` (sigue siendo la convención estándar; ya bloquea RPC por sí solo). `@api.private` **no** es un reemplazo del prefijo: es para el caso de excepción de un método sin `_` (API pública existente, o método interno del ORM) que necesita bloquearse de RPC sin renombrarlo. Ver docstring de `private` en `odoo/orm/decorators.py`.
- Métodos muy largos (>50 líneas) → sugerir split.
- Comparaciones booleanas: `if x:` / `if not x:` (no `== True` / `== False`).
- `else` después de `return` innecesario.
- Imports no utilizados deben removerse.

## Dominios

- En Odoo 19 es válido `Domain('field', 'op', 'value')` y combinar con `&`, `|`, `~`. No marcar como error.
- `Domain` permite uso en `filtered`: no hace falta convertir a lista.
- Nunca construir dominios como strings y pasarlos por `eval` (ver `security.instructions.md`).

## Selecciones

- Agregar nuevos values a un `selection` **no** requiere migración.
- Renombrar/eliminar keys existentes → proponer script que mapee `old → new` (ver `migrations.instructions.md`).
82 changes: 82 additions & 0 deletions .github/instructions/performance.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
applyTo:
- "**/models/**/*.py"
- "**/wizards/**/*.py"
- "**/wizard/**/*.py"
- "**/controllers/**/*.py"
- "**/report/**/*.py"
---

# Revisión de rendimiento (ORM)

## Anti-patrones que bloquean performance

- **Search en loop** → N+1 queries. Reemplazar por una sola `search` con dominio `in` sobre ids, o `_read_group` / `search_fetch`.
```python
# MAL
for order in orders:
payments = self.env['payment'].search([('order_id', '=', order.id)])
# BIEN
payments = self.env['payment'].search([('order_id', 'in', orders.ids)])
```
- **Create/write/unlink en loop** → múltiples roundtrips a DB. Vectorizar:
```python
# MAL
for vals in data:
self.env['res.partner'].create(vals)
# BIEN (Odoo 17+)
self.env['res.partner'].create(data) # lista de dicts
```
- **`search([])` + filtrado en Python** → traer todos los records. Usar dominio preciso.
- **`mapped` en loop** sobre recordsets grandes → preferir una única `.mapped('field')` fuera del loop.

## `@api.depends` afinado

- Listar todas las dependencias **reales**, incluidas las dotted: `@api.depends('partner_id.email')` para evitar consultas extra.
- No listar campos ajenos al compute (dispara recomputes innecesarios).
- Evitar depender de campos no almacenados en cadenas largas.

## Agregados

- Para sumar/contar preferir `read_group` / `_read_group` / `formatted_read_group` (Odoo 17+) antes que iterar + `sum`/`len`.
- `search_count(domain)` en vez de `len(search(domain))`.
- `browse(ids)` en lugar de re-buscar cuando ya se tienen ids.

## Relacionales

- **N+1 por navegación**: si un `@api.depends` dispara muchas lecturas, ajustar dependencias o prefetch.
- `mapped('campo_relacional.subcampo')` agrupa lecturas y usa prefetch; preferir a loops manuales.
- `filtered_domain(domain)` para filtrados con mismo idioma que `search`.

## Cron y jobs largos

- **Odoo 19**: usar `self.env['ir.cron']._commit_progress(remaining=N)` / `_commit_progress(processed=M)` en crons en lugar de `notify_progress` / commits manuales ad hoc.
- Procesar en **lotes** (`batch_size` razonable, p. ej. 500–1000) y commitear por lote.
- Logs con `_logger.info` para observabilidad.

## Computes y store

- `store=True` sobre `compute` implica backfill en historia → ver `migrations.instructions.md`.
- `compute` sin store se reevalúa por read; si se accede repetidas veces en un loop, cachear localmente.
- `write` dentro de un compute → anti-patrón, genera recursión o recomputes encadenados.

## Transacciones

- `flush()` explícito solo cuando se requiere forzar la orden de escritura antes de leer. No usar en loops.
- `env.cr.commit()` en crons o scripts de migración, pero nunca dentro de lógica transaccional de usuario.
- `invalidate_cache` solo si hay razón concreta (modificación externa por SQL directo).

## Vistas XML relacionadas (cross-reference)

- Filtros en listas grandes sobre campos no indexados → sugerir `index=True` en el modelo.
- Columnas de lista que nunca se muestran: `column_invisible="1"` (evita cargar valores). Ver `views.instructions.md`.

## Cuándo NO optimizar

- Loops sobre recordsets pequeños y acotados (< ~20 elementos) donde la claridad gana a la micro-optimización.
- Código de setup/install que corre una única vez.
- Para diffs chicos y acotados, evitar proponer reescrituras masivas — preferir marcar la regla para futuras iteraciones.

## Beneficios indirectos

- Mantenerse dentro del ORM hereda controles de acceso, auditoría, reglas multi-compañía y prefetch automático. Queries crudas pierden todo eso.
Loading
Loading