Odoo Code Review
Objective
Review Odoo code changes against clear criteria, identify risks, and score using a weighted scale from an Odoo-expert perspective — using the reference pack that matches the target Odoo version.
Resolve the target Odoo version
Before reviewing, resolve ODOO_VERSION (one of 16.0, 17.0, 18.0, 19.0) in this order. Stop at the first one that succeeds:
- Explicit argument passed to the agent invocation (e.g.
odoo_version: "19.0").
- Project config, in this order:
.odoo-version file at the repo root (contents: e.g. 19.0).
odoo_version key in .claude/odoo.json.
odoo.version key in package.json or tool.odoo.version in pyproject.toml.
- Manifest heuristic — scan workspace
__manifest__.py files for the 'version' key. Use the dominant major version (e.g. 18.0.1.0.0 → 18.0).
- Fallback — default to
19.0 (latest supported) and note the assumption in the review output so the user can correct it.
Derive ODOO_MAJOR from ODOO_VERSION by stripping .0 (e.g. 18.0 → 18). All guide paths below use these placeholders.
Supported versions: 16.0, 17.0, 18.0, 19.0. If resolution yields anything else, stop and tell the user the version is out of scope.
Pre-review Requirements
- Read
skills/odoo-${ODOO_VERSION}/SKILL.md as the master index for the resolved version's guides.
- Read
skills/odoo-${ODOO_VERSION}/references/api-highlights.md for the version-distinguishing rules (what changed, what to flag, what's allowed).
- Read relevant guides from
skills/odoo-${ODOO_VERSION}/references/ based on change scope:
- Models/ORM:
odoo-${ODOO_MAJOR}-model-guide.md
- Fields:
odoo-${ODOO_MAJOR}-field-guide.md
- Decorators:
odoo-${ODOO_MAJOR}-decorator-guide.md
- Performance:
odoo-${ODOO_MAJOR}-performance-guide.md
- Views/XML:
odoo-${ODOO_MAJOR}-view-guide.md
- Security:
odoo-${ODOO_MAJOR}-security-guide.md
- Controllers:
odoo-${ODOO_MAJOR}-controller-guide.md
- Transactions:
odoo-${ODOO_MAJOR}-transaction-guide.md
- Mixins:
odoo-${ODOO_MAJOR}-mixins-guide.md (mail.thread, activities)
- Testing:
odoo-${ODOO_MAJOR}-testing-guide.md
- Migration:
odoo-${ODOO_MAJOR}-migration-guide.md
- Actions:
odoo-${ODOO_MAJOR}-actions-guide.md
- Data Files:
odoo-${ODOO_MAJOR}-data-guide.md
- Manifest:
odoo-${ODOO_MAJOR}-manifest-guide.md
- Identify scope: module, file, and change context.
- Apply the version-distinguishing rules from
api-highlights.md (e.g. <tree> vs <list>, group_operator= vs aggregator=, optional _name in v19, etc.).
Expert Review Process
- Scope: Identify change scope, objectives, and key risks
- ORM & Model Methods: Search patterns, CRUD operations, recordset operations
- Field Definitions: Field types, computed fields, relational field parameters
- API Decorators:
@api.depends, @api.constrains, @api.ondelete, @api.model_create_multi
- Performance: N+1 detection, batch operations, field selection
- Transaction Management: Savepoints,
UniqueViolation, serialization
- Views & XML: Version-appropriate list tag, inheritance, structure (see
api-highlights.md)
- Security: ACL, record rules, exceptions,
sudo() usage
- Controllers: Auth types, CSRF protection, routing
- Mixins:
mail.thread, mail.activity.mixin, mail.alias.mixin usage
- Testing: Test coverage, proper test cases,
@tagged decorators
- Migration: Migration scripts, data migration patterns
- Actions: Window actions, server actions, cron jobs
- Data Files: XML/CSV data structure,
noupdate, shortcuts
- Manifest: Dependencies, external deps, hooks, assets
Complete Checklist
Rules below are version-neutral unless they reference api-highlights.md. Always combine this checklist with the version-specific highlights for the resolved ODOO_VERSION.
ORM & Model Methods (30%)
- ❌ DO NOT use
search() inside a loop (N+1 anti-pattern)
- ✅ Use
search_read() when dict output needed
- ✅ Use
read_group() for aggregate queries
- ✅ Use
IN domain instead of search in loop: [('order_id', 'in', orders.ids)]
- ✅ Batch
create([{...}, {...}]) for multiple records
- ✅ Use
recordset.write() instead of loop
- ✅ Use
recordset.unlink() instead of loop
- ✅
@api.model_create_multi on create() overrides (see api-highlights.md for version-specific enforcement)
Views & XML (15%)
- Use the list tag appropriate to
ODOO_VERSION (see api-highlights.md: <tree> in 16/17, <list> in 18+).
- Use the attrs syntax appropriate to
ODOO_VERSION: legacy attrs= / states= are valid in 16, but rejected in 17+ where direct expressions are required.
- Inheritance via
xpath / position — the nested list tag must match the version.
- Avoid duplicate
name= attributes in records.
Fields (15%)
Monetary with currency_field
Many2one with ondelete
- Computed field with
store=True if filtered/searched
- Aggregation parameter:
group_operator= (v16/17) vs aggregator= (v18+) — see api-highlights.md.
Decorators (10%)
@api.depends with complete dotted paths
@api.constrains for invariants
@api.ondelete(at_uninstall=False) instead of overriding unlink() for validation
@api.model_create_multi for batch create
Performance (10%)
- Avoid N+1 in loops
- Prefer
read_group() / search_read() over per-record fetches
- Use
prefetch_fields thoughtfully
Transactions (5%)
savepoint around recoverable failures
- Handle
UniqueViolation explicitly
- Advisory locks for cross-record serialization
Security (5%)
- Specific exceptions:
UserError, ValidationError, AccessError
- No bare
except Exception
sudo() used narrowly with justification
Controllers (3%)
- Correct
auth= (user, public, none)
csrf=False only with justification
type='json' vs type='http' matches the client
Mixins (3%)
mail.thread with proper tracking fields
mail.activity.mixin for activities
mail.alias.mixin with alias fields
Testing (2%)
- Regression test for each reproducible bug fix
- Tests for new functionality and important error paths
- Security-sensitive flows tested with the lowest practical permissions
- No state leakage between
subTest cases; records use the active environment
- Deterministic dates and fixtures; no unnecessary reliance on demo data
- External services mocked by default, with live integrations explicitly tagged
- Coverage drops investigated for missing meaningful cases
- Proper use of
@tagged
- Query count assertions for hot paths
Manifest & Data (2%)
- All dependencies declared
- External deps listed
- Hooks wired correctly
noupdate="1" for reference data
Scoring
Weight each section per the percentages above. Total out of 100. Report:
- Score per section with brief justification.
- Blocking issues (must fix before merge).
- Non-blocking suggestions.
- Explicitly name the resolved
ODOO_VERSION at the top of the report.
Deep Dive Checks
When reviewing, thoroughly check (references below use ${ODOO_MAJOR} — substitute the resolved value):
Does @api.depends have complete dependencies?
- Check dotted paths:
partner_id.email instead of just partner_id
- Missing dependencies cause N queries
- Reference:
skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-decorator-guide.md
Are there N+1 queries?
- Loop with
search(), browse(), read() inside
- Solution:
search_read() with IN domain or read_group()
- Reference:
skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-performance-guide.md
Are there batch operations?
create(), write(), unlink() in loop
- Solution: batch operations on recordset
- Reference:
skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-performance-guide.md
Is transaction safe?
UniqueViolation handling without savepoint
- Concurrent updates without advisory lock
- Reference:
skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-transaction-guide.md
Are version-specific patterns correct?
- List tag, attrs syntax, aggregation parameter, optional
_name (v19).
- Reference:
skills/odoo-${ODOO_VERSION}/references/api-highlights.md + odoo-${ODOO_MAJOR}-view-guide.md
Are field definitions correct?
Monetary with currency_field
Many2one with ondelete
- Computed field with
store=True if needed
- Reference:
skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-field-guide.md
Is exception handling correct?
UserError, ValidationError, AccessError
- No generic
Exception
- Reference:
skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-security-guide.md
Are mixins properly configured?
mail.thread with proper tracking fields
mail.activity.mixin for activities
mail.alias.mixin with alias fields
- Reference:
skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-mixins-guide.md
Is testing adequate?
- Regression test for each reproducible bug fix
- Tests for new functionality and important error paths
- Security-sensitive flows use the lowest practical permissions
- No state leakage between
subTest cases or stored record environments
- Deterministic dates and fixtures; no unnecessary demo-data dependency
- External services mocked by default and live integrations explicitly tagged
- Coverage drops investigated for missing meaningful cases
- Proper use of
@tagged decorators
- Query count assertions for performance
- Reference:
skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-testing-guide.md
Are migrations handled correctly?
- Proper migration script location
- Pre/post migration scripts
- Idempotent operations
- Reference:
skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-migration-guide.md
Are actions properly defined?
- Window actions with correct context
- Server actions for automation
- Cron jobs with proper intervals
- Reference:
skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-actions-guide.md
Are data files correct?
- Proper XML record structure
noupdate="1" for reference data
- CSV data properly formatted
- Reference:
skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-data-guide.md
Is manifest correct?
- All dependencies declared
- External dependencies listed
- Hooks properly configured
- Reference:
skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-manifest-guide.md
1---2name: odoo-code-review3description: Review Odoo code for correctness, security, performance, and version-specific standards (Odoo 16, 17, 18, or 19). Use when reviewing Odoo modules, diffs, or pull requests; produce a scored report with weighted criteria.4---5
6# Odoo Code Review
7
8## Objective
9
10Review Odoo code changes against clear criteria, identify risks, and score using a weighted scale from an Odoo-expert perspective — using the reference pack that matches the target Odoo version.
11
12## Resolve the target Odoo version
13
14Before reviewing, resolve `ODOO_VERSION` (one of `16.0`, `17.0`, `18.0`, `19.0`) in this order. Stop at the first one that succeeds:
15
161. **Explicit argument** passed to the agent invocation (e.g. `odoo_version: "19.0"`).
172. **Project config**, in this order:
18 - `.odoo-version` file at the repo root (contents: e.g. `19.0`).
19 - `odoo_version` key in `.claude/odoo.json`.
20 - `odoo.version` key in `package.json` or `tool.odoo.version` in `pyproject.toml`.
213. **Manifest heuristic** — scan workspace `__manifest__.py` files for the `'version'` key. Use the dominant major version (e.g. `18.0.1.0.0` → `18.0`).
224. **Fallback** — default to `19.0` (latest supported) and note the assumption in the review output so the user can correct it.
23
24Derive `ODOO_MAJOR` from `ODOO_VERSION` by stripping `.0` (e.g. `18.0` → `18`). All guide paths below use these placeholders.
25
26Supported versions: **16.0, 17.0, 18.0, 19.0**. If resolution yields anything else, stop and tell the user the version is out of scope.
27
28## Pre-review Requirements
29
30- Read `skills/odoo-${ODOO_VERSION}/SKILL.md` as the master index for the resolved version's guides.
31- Read `skills/odoo-${ODOO_VERSION}/references/api-highlights.md` for the version-distinguishing rules (what changed, what to flag, what's allowed).
32- Read relevant guides from `skills/odoo-${ODOO_VERSION}/references/` based on change scope:
33 - **Models/ORM**: `odoo-${ODOO_MAJOR}-model-guide.md`
34 - **Fields**: `odoo-${ODOO_MAJOR}-field-guide.md`
35 - **Decorators**: `odoo-${ODOO_MAJOR}-decorator-guide.md`
36 - **Performance**: `odoo-${ODOO_MAJOR}-performance-guide.md`
37 - **Views/XML**: `odoo-${ODOO_MAJOR}-view-guide.md`
38 - **Security**: `odoo-${ODOO_MAJOR}-security-guide.md`
39 - **Controllers**: `odoo-${ODOO_MAJOR}-controller-guide.md`
40 - **Transactions**: `odoo-${ODOO_MAJOR}-transaction-guide.md`
41 - **Mixins**: `odoo-${ODOO_MAJOR}-mixins-guide.md` (mail.thread, activities)
42 - **Testing**: `odoo-${ODOO_MAJOR}-testing-guide.md`
43 - **Migration**: `odoo-${ODOO_MAJOR}-migration-guide.md`
44 - **Actions**: `odoo-${ODOO_MAJOR}-actions-guide.md`
45 - **Data Files**: `odoo-${ODOO_MAJOR}-data-guide.md`
46 - **Manifest**: `odoo-${ODOO_MAJOR}-manifest-guide.md`
47- Identify scope: module, file, and change context.
48- Apply the version-distinguishing rules from `api-highlights.md` (e.g. `<tree>` vs `<list>`, `group_operator=` vs `aggregator=`, optional `_name` in v19, etc.).
49
50## Expert Review Process
51
521. **Scope**: Identify change scope, objectives, and key risks
532. **ORM & Model Methods**: Search patterns, CRUD operations, recordset operations
543. **Field Definitions**: Field types, computed fields, relational field parameters
554. **API Decorators**: `@api.depends`, `@api.constrains`, `@api.ondelete`, `@api.model_create_multi`
565. **Performance**: N+1 detection, batch operations, field selection
576. **Transaction Management**: Savepoints, `UniqueViolation`, serialization
587. **Views & XML**: Version-appropriate list tag, inheritance, structure (see `api-highlights.md`)
598. **Security**: ACL, record rules, exceptions, `sudo()` usage
609. **Controllers**: Auth types, CSRF protection, routing
6110. **Mixins**: `mail.thread`, `mail.activity.mixin`, `mail.alias.mixin` usage
6211. **Testing**: Test coverage, proper test cases, `@tagged` decorators
6312. **Migration**: Migration scripts, data migration patterns
6413. **Actions**: Window actions, server actions, cron jobs
6514. **Data Files**: XML/CSV data structure, `noupdate`, shortcuts
6615. **Manifest**: Dependencies, external deps, hooks, assets
67
68## Complete Checklist
69
70Rules below are version-neutral unless they reference `api-highlights.md`. Always combine this checklist with the version-specific highlights for the resolved `ODOO_VERSION`.
71
72### ORM & Model Methods (30%)
73- ❌ **DO NOT** use `search()` inside a loop (N+1 anti-pattern)
74- ✅ Use `search_read()` when dict output needed
75- ✅ Use `read_group()` for aggregate queries
76- ✅ Use `IN` domain instead of search in loop: `[('order_id', 'in', orders.ids)]`
77- ✅ Batch `create([{...}, {...}])` for multiple records
78- ✅ Use `recordset.write()` instead of loop
79- ✅ Use `recordset.unlink()` instead of loop
80- ✅ `@api.model_create_multi` on `create()` overrides (see `api-highlights.md` for version-specific enforcement)
81
82### Views & XML (15%)
83- Use the list tag appropriate to `ODOO_VERSION` (see `api-highlights.md`: `<tree>` in 16/17, `<list>` in 18+).
84- Use the attrs syntax appropriate to `ODOO_VERSION`: legacy `attrs=` / `states=` are valid in 16, but rejected in 17+ where direct expressions are required.
85- Inheritance via `xpath` / `position` — the nested list tag must match the version.
86- Avoid duplicate `name=` attributes in records.
87
88### Fields (15%)
89- `Monetary` with `currency_field`
90- `Many2one` with `ondelete`
91- Computed field with `store=True` if filtered/searched
92- Aggregation parameter: `group_operator=` (v16/17) vs `aggregator=` (v18+) — see `api-highlights.md`.
93
94### Decorators (10%)
95- `@api.depends` with complete dotted paths
96- `@api.constrains` for invariants
97- `@api.ondelete(at_uninstall=False)` instead of overriding `unlink()` for validation
98- `@api.model_create_multi` for batch create
99
100### Performance (10%)
101- Avoid N+1 in loops
102- Prefer `read_group()` / `search_read()` over per-record fetches
103- Use `prefetch_fields` thoughtfully
104
105### Transactions (5%)
106- `savepoint` around recoverable failures
107- Handle `UniqueViolation` explicitly
108- Advisory locks for cross-record serialization
109
110### Security (5%)
111- Specific exceptions: `UserError`, `ValidationError`, `AccessError`
112- No bare `except Exception`
113- `sudo()` used narrowly with justification
114
115### Controllers (3%)
116- Correct `auth=` (`user`, `public`, `none`)
117- `csrf=False` only with justification
118- `type='json'` vs `type='http'` matches the client
119
120### Mixins (3%)
121- `mail.thread` with proper tracking fields
122- `mail.activity.mixin` for activities
123- `mail.alias.mixin` with alias fields
124
125### Testing (2%)
126- Regression test for each reproducible bug fix
127- Tests for new functionality and important error paths
128- Security-sensitive flows tested with the lowest practical permissions
129- No state leakage between `subTest` cases; records use the active environment
130- Deterministic dates and fixtures; no unnecessary reliance on demo data
131- External services mocked by default, with live integrations explicitly tagged
132- Coverage drops investigated for missing meaningful cases
133- Proper use of `@tagged`
134- Query count assertions for hot paths
135
136### Manifest & Data (2%)
137- All dependencies declared
138- External deps listed
139- Hooks wired correctly
140- `noupdate="1"` for reference data
141
142## Scoring
143
144Weight each section per the percentages above. Total out of 100. Report:
145- Score per section with brief justification.
146- Blocking issues (must fix before merge).
147- Non-blocking suggestions.
148- Explicitly name the resolved `ODOO_VERSION` at the top of the report.
149
150## Deep Dive Checks
151
152When reviewing, thoroughly check (references below use `${ODOO_MAJOR}` — substitute the resolved value):
153
1541. **Does `@api.depends` have complete dependencies?**
155 - Check dotted paths: `partner_id.email` instead of just `partner_id`
156 - Missing dependencies cause N queries
157 - Reference: `skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-decorator-guide.md`
158
1592. **Are there N+1 queries?**
160 - Loop with `search()`, `browse()`, `read()` inside
161 - Solution: `search_read()` with `IN` domain or `read_group()`
162 - Reference: `skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-performance-guide.md`
163
1643. **Are there batch operations?**
165 - `create()`, `write()`, `unlink()` in loop
166 - Solution: batch operations on recordset
167 - Reference: `skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-performance-guide.md`
168
1694. **Is transaction safe?**
170 - `UniqueViolation` handling without savepoint
171 - Concurrent updates without advisory lock
172 - Reference: `skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-transaction-guide.md`
173
1745. **Are version-specific patterns correct?**
175 - List tag, attrs syntax, aggregation parameter, optional `_name` (v19).
176 - Reference: `skills/odoo-${ODOO_VERSION}/references/api-highlights.md` + `odoo-${ODOO_MAJOR}-view-guide.md`
177
1786. **Are field definitions correct?**
179 - `Monetary` with `currency_field`
180 - `Many2one` with `ondelete`
181 - Computed field with `store=True` if needed
182 - Reference: `skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-field-guide.md`
183
1847. **Is exception handling correct?**
185 - `UserError`, `ValidationError`, `AccessError`
186 - No generic `Exception`
187 - Reference: `skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-security-guide.md`
188
1898. **Are mixins properly configured?**
190 - `mail.thread` with proper tracking fields
191 - `mail.activity.mixin` for activities
192 - `mail.alias.mixin` with alias fields
193 - Reference: `skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-mixins-guide.md`
194
1959. **Is testing adequate?**
196 - Regression test for each reproducible bug fix
197 - Tests for new functionality and important error paths
198 - Security-sensitive flows use the lowest practical permissions
199 - No state leakage between `subTest` cases or stored record environments
200 - Deterministic dates and fixtures; no unnecessary demo-data dependency
201 - External services mocked by default and live integrations explicitly tagged
202 - Coverage drops investigated for missing meaningful cases
203 - Proper use of `@tagged` decorators
204 - Query count assertions for performance
205 - Reference: `skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-testing-guide.md`
206
20710. **Are migrations handled correctly?**
208 - Proper migration script location
209 - Pre/post migration scripts
210 - Idempotent operations
211 - Reference: `skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-migration-guide.md`
212
21311. **Are actions properly defined?**
214 - Window actions with correct context
215 - Server actions for automation
216 - Cron jobs with proper intervals
217 - Reference: `skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-actions-guide.md`
218
21912. **Are data files correct?**
220 - Proper XML record structure
221 - `noupdate="1"` for reference data
222 - CSV data properly formatted
223 - Reference: `skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-data-guide.md`
224
22513. **Is manifest correct?**
226 - All dependencies declared
227 - External dependencies listed
228 - Hooks properly configured
229 - Reference: `skills/odoo-${ODOO_VERSION}/references/odoo-${ODOO_MAJOR}-manifest-guide.md`