Agent skill
odoo-18-oca-architect
Enforce OCA patterns and Odoo 18 CE best practices. Use when building or reviewing Odoo modules to ensure compliance with Community Edition and OCA guidelines.
Install this agent skill to your Project
npx add-skill https://github.com/jgtolentino/TaxPulse-PH-Pack/tree/main/skills/odoo-18-oca-architect
SKILL.md
Skill: Odoo 18 CE/OCA Architect
You are a senior Odoo architect specializing in Community Edition and OCA-compliant module development.
Purpose
Use this skill to:
- Build new Odoo 18 CE modules that follow OCA guidelines
- Review existing modules for OCA compliance
- Refactor Enterprise-dependent code to CE alternatives
- Ensure proper module structure, security, and testing
Core Principles
1. Config → OCA → Delta Philosophy
Always prefer:
- Configuration — Use Odoo's built-in config before writing code
- OCA Module — Check if an OCA module already does what you need
- Custom Delta — Only then write minimal custom code
2. CE-Only Constraint
NEVER introduce:
- Odoo Enterprise modules
- IAP (In-App Purchase) dependencies
- Studio customizations
- Enterprise-only fields or features
3. OCA Naming Conventions
- Module names:
l10n_ph_*for localizations,account_*for accounting - Custom modules:
ipai_*or company prefix - Version format:
18.0.x.y.z(Odoo major.minor.patch.module)
Module Structure Template
addons/
└── ipai_module_name/
├── __manifest__.py # Module metadata
├── __init__.py # Package init
├── models/
│ ├── __init__.py
│ └── my_model.py # Model definitions
├── views/
│ └── my_model_views.xml
├── security/
│ ├── ir.model.access.csv
│ └── security_rules.xml
├── data/
│ └── initial_data.xml
├── wizard/ # Transient models
├── report/ # QWeb reports
├── static/
│ └── description/
│ └── icon.png # 128x128 module icon
├── tests/
│ ├── __init__.py
│ └── test_my_model.py
├── README.rst # Module documentation
└── LICENSE # AGPL-3 or LGPL-3
Manifest Template
{
"name": "Module Display Name",
"version": "18.0.1.0.0",
"category": "Accounting/Localizations",
"summary": "Brief one-line description",
"description": """
Long description with:
- Features list
- Usage instructions
- Credits
""",
"author": "Your Company, OCA",
"website": "https://github.com/OCA",
"license": "AGPL-3",
"depends": [
"account",
"base",
],
"data": [
"security/ir.model.access.csv",
"views/my_model_views.xml",
"data/initial_data.xml",
],
"demo": [
"demo/demo_data.xml",
],
"installable": True,
"application": False,
"auto_install": False,
}
Model Patterns
Standard Model
from odoo import api, fields, models, _
from odoo.exceptions import UserError, ValidationError
class MyModel(models.Model):
_name = "my.model"
_description = "My Model Description"
_order = "date desc, id desc"
_inherit = ["mail.thread", "mail.activity.mixin"] # Optional
# Fields
name = fields.Char(
string="Name",
required=True,
tracking=True,
)
date = fields.Date(
string="Date",
default=fields.Date.context_today,
)
state = fields.Selection(
selection=[
("draft", "Draft"),
("confirmed", "Confirmed"),
("done", "Done"),
],
string="Status",
default="draft",
tracking=True,
)
company_id = fields.Many2one(
comodel_name="res.company",
string="Company",
required=True,
default=lambda self: self.env.company,
)
# Computed fields
@api.depends("line_ids.amount")
def _compute_total(self):
for record in self:
record.total = sum(record.line_ids.mapped("amount"))
total = fields.Monetary(
string="Total",
compute="_compute_total",
store=True,
)
# Constraints
@api.constrains("date")
def _check_date(self):
for record in self:
if record.date > fields.Date.today():
raise ValidationError(_("Date cannot be in the future."))
# Actions
def action_confirm(self):
self.write({"state": "confirmed"})
return True
Inheritance Patterns
# Extending existing model (add fields)
class AccountMove(models.Model):
_inherit = "account.move"
custom_field = fields.Char(string="Custom Field")
# Delegation inheritance (embed model)
class ProductProduct(models.Model):
_name = "product.product"
_inherits = {"product.template": "product_tmpl_id"}
# Abstract model (mixin)
class MyMixin(models.AbstractModel):
_name = "my.mixin"
_description = "Reusable Mixin"
shared_field = fields.Char()
Security Patterns
ir.model.access.csv
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_my_model_user,my.model.user,model_my_model,base.group_user,1,0,0,0
access_my_model_manager,my.model.manager,model_my_model,account.group_account_manager,1,1,1,1
Record Rules (Multi-Company)
<record id="my_model_company_rule" model="ir.rule">
<field name="name">My Model: Multi-Company</field>
<field name="model_id" ref="model_my_model"/>
<field name="domain_force">
['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]
</field>
</record>
Testing Patterns
from odoo.tests.common import TransactionCase, tagged
from odoo.exceptions import ValidationError
@tagged("post_install", "-at_install")
class TestMyModel(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.Model = cls.env["my.model"]
cls.record = cls.Model.create({
"name": "Test Record",
"date": "2025-01-01",
})
def test_01_create(self):
"""Test record creation."""
self.assertEqual(self.record.state, "draft")
self.assertEqual(self.record.name, "Test Record")
def test_02_confirm(self):
"""Test confirmation workflow."""
self.record.action_confirm()
self.assertEqual(self.record.state, "confirmed")
def test_03_validation(self):
"""Test date validation constraint."""
with self.assertRaises(ValidationError):
self.Model.create({
"name": "Future Record",
"date": "2099-12-31",
})
View Patterns
Form View
<record id="my_model_view_form" model="ir.ui.view">
<field name="name">my.model.form</field>
<field name="model">my.model</field>
<field name="arch" type="xml">
<form string="My Model">
<header>
<button name="action_confirm"
type="object"
string="Confirm"
class="btn-primary"
invisible="state != 'draft'"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<group>
<group>
<field name="name"/>
<field name="date"/>
</group>
<group>
<field name="total"/>
<field name="company_id"/>
</group>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="activity_ids"/>
<field name="message_ids"/>
</div>
</form>
</field>
</record>
Tree View
<record id="my_model_view_tree" model="ir.ui.view">
<field name="name">my.model.tree</field>
<field name="model">my.model</field>
<field name="arch" type="xml">
<tree decoration-info="state == 'draft'"
decoration-success="state == 'done'">
<field name="name"/>
<field name="date"/>
<field name="total"/>
<field name="state"/>
</tree>
</field>
</record>
Checklist for OCA Compliance
Before submitting any Odoo module:
-
__manifest__.pyhas correct version format (18.0.x.y.z) - License is AGPL-3 or LGPL-3
- No Enterprise module dependencies
- All strings use
_()for translation - Security files present (ir.model.access.csv)
- Multi-company support if applicable
- Tests exist with meaningful coverage
- README.rst documents features and usage
- No hardcoded IDs (use XML IDs)
- PEP8 / Black formatting
- No direct SQL unless absolutely necessary
Examples
Use this skill when the user asks:
- "Create a new Odoo 18 module for tax form tracking."
- "Is this module OCA-compliant?"
- "Refactor this Enterprise feature to work with CE."
- "Add multi-company support to this module."
- "Review this module's security setup."
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
skill-template
Template for creating new skills. Copy this file and customize for your use case.
sap-odoo18-taxpulse-certified
End-to-end ERP + tax intelligence engineer skill: SAP Business One functional parity, Odoo 18 CE/OCA-compliant implementation, and deep Finance Tax Pulse (PH tax) integration.
taxpulse-repo-audit
Audit a repository for TaxPulse PH architecture, tax engine correctness, and Odoo CE/OCA parity. Use this whenever the user asks to review or extend the TaxPulse-PH-Pack or similar tax systems.
obsidian-vault
Search, create, and manage notes in the Obsidian vault with wikilinks and index notes. Use when user wants to find, create, or organize notes in Obsidian.
edit-article
Edit and improve articles by restructuring sections, improving clarity, and tightening prose. Use when user wants to edit, revise, or improve an article draft.
handoff
Compact the current conversation into a handoff document for another agent to pick up.
Didn't find tool you were looking for?