CLAUDE.md: correct two Odoo 19 API claims found building O1

Coding standards said "No APIs deprecated in 17 or 18" as if that
were sufficient - it isn't, because it's phrased as a non-regression
check against an assumed-correct baseline, and the baseline itself
(an 18-era mental model of _sql_constraints and res.groups) was
already wrong for 19. Verified against a real odoo:19.0 container
while building mc_education_base: _sql_constraints is replaced by
per-attribute models.Constraint(sql, message), and res.groups lost
category_id in favor of a new res.groups.privilege record referenced
via privilege_id.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
metatroncubeswdev 2026-09-11 08:53:52 -04:00
parent 8b7bd91f74
commit 1e5ac14510

View File

@ -99,12 +99,23 @@ that being true, not staged.
## 4. Coding standards
- Odoo 19 conventions throughout. No APIs deprecated in 17 or 18.
- **Correction (found building O1, verified against a real `odoo:19.0` container — an 18-era
mental model gets both of these wrong):**
- `_sql_constraints = [(name, sql, message), ...]` is gone. Declare each constraint as its own
class attribute instead: `_my_constraint = models.Constraint(sql, message)`. The rule below
("prefer a database constraint when the database can express it") still holds — only the
syntax changed.
- `res.groups.category_id` is gone. A group now points at a `res.groups.privilege` record via
`privilege_id`, and the privilege carries `category_id` (still an `ir.module.category`).
Create one `res.groups.privilege` per module category and point every group at it. See
`addons/mc_education_base/security/mc_education_security.xml` for the pattern.
- `_name`, `_description` and `_order` on every model. `_rec_name` where the display field is not
`name`.
- Computed fields declare `@api.depends` accurately and are `store=True` only when they need to be
searched or grouped. A stored compute with wrong depends is a silent data-corruption bug.
- Constraints: prefer `_sql_constraints` over `@api.constrains` when the database can express it.
The "one active enrollment per student per year" rule is a SQL constraint.
- Constraints: prefer a database constraint (`models.Constraint`, see above) over `@api.constrains`
when the database can express it. The "one active enrollment per student per year" rule is a
database constraint.
- `ondelete` is explicit on every `Many2one`. Think about whether it should be `restrict`
(financial and academic history) or `cascade` (child lines).
- `tracking=True` on fields a school will argue about later: enrollment status, fee amounts, marks,