From 1e5ac1451037b8d6b0eff1f1a046d3f1db2f01e3 Mon Sep 17 00:00:00 2001 From: metatroncubeswdev Date: Fri, 11 Sep 2026 08:53:52 -0400 Subject: [PATCH] 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 --- CLAUDE.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a9a3d04..5b1b727 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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,