Claude
Skills
Sign in
Back

odoo-module-creator

Included with Lifetime
$97 forever

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".

Securityassets

What this skill does


# 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
<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <!-- Tree View -->
    <record id="view_model_tree" model="ir.ui.view">
        <field name="name">module.model.tree</field>
        <field name="model">module.model</field>
        <field name="arch" type="xml">
            <tree string="Model Name">
                <field name="name"/>
                <field name="partner_id"/>
                <field name="state" decoration-info="state == 'draft'"
                       decoration-success="state == 'done'"/>
                <field name="total_amount" sum="Total"/>
                <field name="company_id" groups="base.group_multi_company"/>
            </tree>
        </field>
    </record>

    <!-- Form View -->
    <record id="view_model_form" model="ir.ui.view">
        <field name=

Related in Security