Reviews Odoo 16.0 code for best practices, security issues, performance problems, and OCA guidelines compliance. This skill should be used when the user requests code review, such as "Review this code" or "Check this module for issues" or "Is this code optimized?" or "Security review needed for this module".
Reviews Odoo 16.0 code for security vulnerabilities, performance issues, and OCA guidelines compliance. Triggered when user requests code review with phrases like "review this code" or "check for issues".
/plugin marketplace add jamshu/jamshi-marketplace/plugin install odoo-dev@jamshi-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/oca_guidelines.mdreferences/performance_patterns.mdreferences/security_checklist.mdThis skill provides comprehensive code review for Odoo 16.0 modules, checking for security vulnerabilities, performance issues, OCA guideline compliance, and general best practices.
SQL injection, XSS vulnerabilities, improper sudo() usage, missing input validation.
N+1 queries, inefficient searches, unnecessary database operations.
Code style, structure, naming conventions, documentation.
Proper API usage, error handling, logging, testing.
Code organization, readability, documentation, modularity.
Determine what to review:
Check each category systematically following the patterns below.
1. SQL Injection Risk
# BAD - SQL injection vulnerability
self.env.cr.execute("SELECT * FROM table WHERE id = %s" % record_id)
# GOOD - Parameterized query
self.env.cr.execute("SELECT * FROM table WHERE id = %s", (record_id,))
2. XSS Vulnerabilities
# BAD - Unescaped HTML field
description = fields.Char(string='Description')
# GOOD - Use Text or Html field with sanitization
description = fields.Html(string='Description', sanitize=True)
3. Improper sudo() Usage
# BAD - sudo() without justification
records = self.env['model'].sudo().search([])
# GOOD - Check permissions properly
if self.env.user.has_group('base.group_system'):
records = self.env['model'].search([])
4. Missing Input Validation
# BAD - No validation
def process(self, value):
return int(value)
# GOOD - Proper validation
def process(self, value):
if not value or not isinstance(value, (int, str)):
raise ValueError('Invalid value')
try:
return int(value)
except ValueError:
raise ValidationError('Value must be a valid integer')
1. N+1 Query Problem
# BAD - N+1 queries
for order in orders:
print(order.partner_id.name) # Database query for each iteration
# GOOD - Prefetch
for order in orders:
pass # partner_id prefetched automatically
print([o.partner_id.name for o in orders])
# EVEN BETTER - Explicit prefetch
orders = orders.with_prefetch(['partner_id'])
2. Inefficient Searches
# BAD - Search in loop
for partner in partners:
orders = self.env['sale.order'].search([('partner_id', '=', partner.id)])
# GOOD - Single search
orders = self.env['sale.order'].search([('partner_id', 'in', partners.ids)])
3. Unnecessary Database Operations
# BAD - Multiple writes
for line in lines:
line.write({'processed': True})
# GOOD - Batch write
lines.write({'processed': True})
4. Inefficient Computed Fields
# BAD - Not stored, recalculated every time
total = fields.Float(compute='_compute_total')
# GOOD - Stored with proper depends
total = fields.Float(compute='_compute_total', store=True)
@api.depends('line_ids.amount')
def _compute_total(self):
for record in self:
record.total = sum(record.line_ids.mapped('amount'))
1. Naming Conventions
snake_case (e.g., stock_batch_tracking)model.name (e.g., stock.batch)snake_casesnake_case with verb prefix_method_name2. Import Order
# Standard library
import logging
from datetime import datetime
# Third-party
from lxml import etree
# Odoo
from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError
from odoo.tools import float_compare
3. Docstrings
class Model(models.Model):
"""Brief description of model."""
_name = 'model.name'
_description = 'Model Description'
def method(self, param):
"""Brief description of method.
Args:
param: Description of parameter
Returns:
Description of return value
"""
pass
4. Field Attributes
# GOOD - Complete field definition
name = fields.Char(
string='Name',
required=True,
index=True,
tracking=True,
help='Detailed help text'
)
1. Error Handling
# BAD - Generic exception
try:
value = int(data)
except:
pass
# GOOD - Specific exception with logging
try:
value = int(data)
except ValueError as e:
_logger.error('Invalid data: %s', e)
raise ValidationError('Please provide a valid number')
2. Logging
# BAD - Print statements
print("Processing record", record.id)
# GOOD - Proper logging
_logger.info('Processing record %s', record.id)
_logger.debug('Record data: %s', record.read())
3. Method Decorators
# Ensure proper decorator usage
@api.depends('field1', 'field2') # For computed fields
def _compute_field(self): pass
@api.onchange('field1') # For onchange methods
def _onchange_field(self): pass
@api.constrains('field1') # For constraints
def _check_field(self): pass
@api.model # For class-level methods
def create_from_ui(self, vals): pass
4. Transaction Safety
# BAD - Commit in method
def method(self):
self.process()
self.env.cr.commit() # Don't do this!
# GOOD - Let Odoo handle transactions
def method(self):
self.process()
# Transaction committed automatically
Provide review results in this format:
string without _() for translatable text)# CODE BEING REVIEWED
class SaleOrder(models.Model):
_inherit = 'sale.order'
total_weight = fields.Float(compute='_compute_weight')
def _compute_weight(self):
for order in self:
weight = 0
for line in order.order_line:
product = self.env['product.product'].search([('id', '=', line.product_id.id)])
weight += product.weight * line.product_uom_qty
order.total_weight = weight
Review Findings:
HIGH - Performance Issues:
line.product_id.weight directlystore=True and @api.depends decoratorMEDIUM - Best Practices:
@api.depends decorator
@api.depends('order_line.product_id.weight', 'order_line.product_uom_qty')weight to total_weightImproved Code:
class SaleOrder(models.Model):
_inherit = 'sale.order'
total_weight = fields.Float(
string='Total Weight',
compute='_compute_weight',
store=True,
help='Total weight of all order lines'
)
@api.depends('order_line.product_id.weight', 'order_line.product_uom_qty')
def _compute_weight(self):
"""Compute total weight from order lines."""
for order in self:
order.total_weight = sum(
line.product_id.weight * line.product_uom_qty
for line in order.order_line
)
Complete OCA (Odoo Community Association) coding guidelines for Odoo modules.
Comprehensive security checklist for Odoo development.
Common performance patterns and anti-patterns with examples and fixes.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.