---
name: odoo-module-creator
description: Creates complete Odoo 16.0 modules with proper structure, manifests, models, views, and security. This skill should be used when the user requests creation of a new Odoo module, such as "Create a new module for inventory tracking" or "I need a new POS customization module" or "Generate module structure for vendor management".
---
# Odoo Module Creator
## Overview
This skill enables creation of complete, production-ready Odoo 16.0 Enterprise modules with proper directory structure, manifest files, models, views, security configurations, and documentation. It follows OCA guidelines and Siafa project standards.
## Module Creation Workflow
### Step 1: Gather Module Requirements
Ask clarifying questions to collect essential information:
1. **Module technical name** (snake_case format, e.g., `stock_batch_tracking`, `pos_custom_receipt`)
2. **Module display name** (human-readable, e.g., "Stock Batch Tracking", "POS Custom Receipt")
3. **Module purpose** (1-2 sentence description of functionality)
4. **Module category** (select from: Sales, Inventory, Accounting, Point of Sale, Human Resources, Manufacturing, Purchases, Warehouse, Website, etc.)
5. **Dependencies** (base modules required, e.g., `stock`, `account`, `point_of_sale`)
6. **Module type** (see Module Types section below)
7. **Target addon directory** (e.g., `addons-stock`, `addons-pos`, `addons-account`)
### Step 2: Determine Module Type
Identify which type of module to create based on the purpose:
**A. Simple Model Module** - CRUD operations for a new business entity
- Creates new models with fields and views
- Example: Customer feedback tracking, equipment registry
**B. Extension Module** - Extends existing Odoo models
- Inherits and adds fields/methods to existing models
- Example: Add serial number tracking to stock.picking
**C. POS Customization** - Point of Sale enhancements
- Extends POS models, screens, or receipts
- Example: Custom receipt format, loyalty points integration
**D. Stock/Inventory Enhancement** - Warehouse and inventory features
- Stock valuation, warehouse operations, batch tracking
- Example: Inter-warehouse transit, GRN-invoice linking
**E. Accounting Customization** - Financial module extensions
- Account moves, vendor bills, analytic accounting
- Example: Multi-dimensional analytics, custom invoicing
**F. Report Module** - Custom reports (PDF, Excel)
- QWeb templates, data aggregation, export functionality
- Example: Sales analysis, inventory valuation reports
**G. Integration Module** - External API/service connectors
- REST API clients, webhooks, data synchronization
- Example: Beatroute connector, payment gateway integration
**H. Widget/UI Customization** - Frontend enhancements
- JavaScript widgets, custom views, web controllers
- Example: Kanban view customizations, dashboard widgets
### Step 3: Generate Module Structure
Create the complete directory structure with all required files:
```
module_name/
├── __init__.py
├── __manifest__.py
├── models/
│ ├── __init__.py
│ └── [model_files].py
├── views/
│ ├── [model]_views.xml
│ └── menu_views.xml
├── security/
│ ├── security_groups.xml (if needed)
│ └── ir.model.access.csv
├── data/ (optional)
│ └── data.xml
├── wizards/ (if needed)
│ ├── __init__.py
│ └── [wizard_name].py
├── report/ (if reports needed)
│ ├── __init__.py
│ ├── [report_name].py
│ └── templates/
│ └── [report_template].xml
├── static/
│ ├── description/
│ │ ├── icon.png
│ │ └── index.html
│ └── src/ (for JS/CSS if needed)
│ ├── js/
│ └── css/
└── tests/ (recommended)
├── __init__.py
└── test_[module].py
```
### Step 4: Generate __manifest__.py
Create manifest with standard metadata:
```python
{
'name': '[Module Display Name]',
'version': '16.0.1.0.0',
'category': '[Category]',
'summary': '[Brief one-line description]',
'description': """
[Detailed multi-line description of module functionality]
Key Features:
- Feature 1
- Feature 2
- Feature 3
""",
'author': 'Jamshid K',
'website': 'https://siafadates.com',
'license': 'LGPL-3',
'depends': [
'base',
# Additional dependencies
],
'data': [
'security/security_groups.xml', # Load first
'security/ir.model.access.csv',
'views/[model]_views.xml',
'views/menu_views.xml',
'data/data.xml', # If needed
'report/templates/[report].xml', # If needed
],
'assets': { # If JS/CSS needed
'web.assets_backend': [
'module_name/static/src/js/*.js',
'module_name/static/src/css/*.css',
],
},
'demo': [], # Demo data if applicable
'installable': True,
'auto_install': False,
'application': False, # True for standalone apps
}
```
### Step 5: Generate Model Files
Create model files following Odoo ORM best practices:
```python
from odoo import models, fields, api
from odoo.exceptions import UserError, ValidationError
import logging
_logger = logging.getLogger(__name__)
class ModelName(models.Model):
"""Description of the model."""
_name = 'module.model'
_description = 'Model Description'
_inherit = ['mail.thread', 'mail.activity.mixin'] # If needed
_order = 'create_date desc'
# Fields
name = fields.Char(
string='Name',
required=True,
index=True,
tracking=True,
help='Primary identifier for this record'
)
active = fields.Boolean(
string='Active',
default=True,
help='If unchecked, this record will be hidden'
)
state = fields.Selection([
('draft', 'Draft'),
('confirmed', 'Confirmed'),
('done', 'Done'),
('cancel', 'Cancelled'),
], string='Status', default='draft', required=True, tracking=True)
company_id = fields.Many2one(
'res.company',
string='Company',
required=True,
default=lambda self: self.env.company
)
# Relational fields
partner_id = fields.Many2one('res.partner', string='Partner')
line_ids = fields.One2many('module.model.line', 'parent_id', string='Lines')
# Computed fields
total_amount = fields.Float(
string='Total Amount',
compute='_compute_total_amount',
store=True
)
# Constraints
_sql_constraints = [
('name_unique', 'UNIQUE(name, company_id)', 'Name must be unique per company!'),
]
@api.depends('line_ids', 'line_ids.amount')
def _compute_total_amount(self):
"""Compute total amount from lines."""
for record in self:
record.total_amount = sum(record.line_ids.mapped('amount'))
@api.onchange('partner_id')
def _onchange_partner_id(self):
"""Update fields when partner changes."""
if self.partner_id:
# Logic here
pass
@api.constrains('total_amount')
def _check_total_amount(self):
"""Validate total amount is positive."""
for record in self:
if record.total_amount < 0:
raise ValidationError('Total amount must be positive!')
def action_confirm(self):
"""Confirm the record."""
self.ensure_one()
if self.state != 'draft':
raise UserError('Only draft records can be confirmed!')
self.write({'state': 'confirmed'})
_logger.info('Record %s confirmed by user %s', self.name, self.env.user.name)
```
### Step 6: Generate View Files
Create XML view definitions:
```xml
module.model.treemodule.modelmodule.model.formmodule.modelmodule.model.searchmodule.modelModel Namemodule.modeltree,form{}
Create your first record!
Click the create button to add a new record.
```
### Step 7: Generate Security Files
Create security groups (if needed):
```xml
Module Category100UserManager
```
Create access rights CSV:
```csv
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_model_user,module.model.user,model_module_model,group_user,1,1,1,0
access_model_manager,module.model.manager,model_module_model,group_manager,1,1,1,1
```
### Step 8: Generate Tests (Recommended)
**Use the `odoo-test-creator` skill** to create comprehensive test suites for the module. The odoo-test-creator skill provides:
- Test templates for different module types (basic models, constraints, inheritance)
- Best practices specific to Siafa project standards
- Solutions to common testing pitfalls (database constraints, HTML fields, permissions)
- Proper import patterns and setUp methods
To create tests with the odoo-test-creator skill, simply invoke:
```
Use the odoo-test-creator skill to create tests for [module_name]
```
The skill will:
1. Analyze the module structure to determine what needs testing
2. Select appropriate test templates based on module type
3. Generate comprehensive test methods for CRUD operations, constraints, computed fields, and business logic
4. Handle database constraints properly (using existing records vs. creating with .sudo())
5. Apply Siafa-specific patterns and best practices
**Quick Test Example** (if not using the skill):
```python
from odoo.tests.common import TransactionCase
from odoo.exceptions import UserError
class TestModel(TransactionCase):
"""Test cases for module.model"""
def setUp(self):
"""Set up test data"""
super().setUp()
self.Model = self.env['module.model']
# Use existing records when possible
self.partner = self.env['res.partner'].search([], limit=1)
if not self.partner:
self.skipTest("No partner available for testing")
def test_01_create_model(self):
"""Test creating a model record"""
record = self.Model.create({
'name': 'Test Record',
'partner_id': self.partner.id,
})
self.assertTrue(record)
self.assertEqual(record.state, 'draft')
def test_02_constraint_validation(self):
"""Test constraint validation"""
record = self.Model.create({
'name': 'Test Record',
'partner_id': self.partner.id,
})
with self.assertRaises(UserError) as context:
record.write({'invalid_field': 'invalid_value'})
self.assertIn('expected error', str(context.exception))
```
**Important:** For production modules, always use the `odoo-test-creator` skill to ensure comprehensive test coverage and proper handling of Siafa-specific constraints.
## Code Standards and Best Practices
Follow these standards when generating module code:
1. **Naming Conventions**
- Module name: `snake_case` (e.g., `stock_batch_tracking`)
- Model name: `module.model` (e.g., `stock.batch.tracking`)
- Fields: `snake_case` (e.g., `batch_number`, `expiry_date`)
- Methods: `snake_case` with verb prefix (e.g., `action_confirm`, `_compute_total`)
- XML IDs: `view_model_type` (e.g., `view_batch_tracking_form`)
2. **Import Order**
```python
# Standard library
import logging
from datetime import datetime
# Odoo imports
from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError
from odoo.tools import float_compare, float_is_zero
```
3. **Field Attributes**
- Always provide `string` parameter
- Add `help` text for complex fields
- Use `tracking=True` for important fields
- Set `index=True` for searchable fields
- Include `company_id` for multi-company support
4. **Method Decorators**
- Use `@api.depends()` for computed fields
- Use `@api.onchange()` for onchange methods
- Use `@api.constrains()` for validation
- Use `@api.model` for class-level methods
5. **Error Handling**
- Use `UserError` for user-facing errors
- Use `ValidationError` for constraint violations
- Always log important actions with `_logger`
6. **Security**
- Always create access rights CSV
- Use security groups for sensitive operations
- Add record rules if row-level security needed
- Test with different user permissions
## Module Type Templates
Reference the `assets/templates/` directory for complete templates by module type:
- `simple_model/` - Basic CRUD module
- `extension/` - Inheriting existing models
- `pos_custom/` - POS customizations
- `stock_enhancement/` - Inventory features
- `report_module/` - Custom reports
## Resources
### assets/templates/
Contains complete module templates for different module types. Use these as starting points and customize based on specific requirements.
### assets/icon.png
Default module icon. Replace with custom icon if needed (PNG, 128x128px recommended).
### assets/index.html
Module description HTML template for the Apps menu.