Odoo is an ERP software, which is open-source software meaning we have access to the source code. Odoo tracks our business aspects of the company such as sales, purchase, finance, assets, more resources, and all transactions of the business. An Odoo developer can create customized modules and can integrate them easily into the existing workflow of the business.
In this blog, we are going to discuss module guidelines in Odoo 14.
Module Structure
The module is used for connecting multiple platforms, which means an Odoo module consists of different application programs. A module contains different directories and files. We can look one by one on this blog
Directories:
An Odoo module is organized into different directories. Each directory has its own purposes.
data/:
In this directory, we include the demo or data files. We can add demo data or other data into our application through XML files. These files are included in this directory.
The syntax is:
<odoo>
<data noupdate=”1”>
<!-- Only loaded when installing the module <operation/>
</data>
</odoo>
<odoo>
<data>
<!-- (Re)Loaded at install and update <operation/>
</data>
</odoo>
models/:
Inside the model’s directory, we can include all the models and an __init__ file. Those are python files.
If we create an application then the model consists of all properties of the application such as fields, functions. we can inherit or extend already existing models. _name is an important attribute of a model, which defines the name of the model. Model is actually the database table, the name of the model will be the table name by replacing ‘.’ to ‘_’. And also we can add corresponding fields and functions inside the model.
For example:
test_model.py
from odoo import fields, models
class ModelTest(models.Model):
_name = "model.test"
_description = "Model Test "
name = fields.Char(string=”name”)
We need to import all the model files onto the __init__.py file.
For example:
__init__.py
from . import test_model
controllers/:
In the case of front-end modules, we can’t use models, instead, we use controllers. For example, we need to show all products on the website, in this case, we can use controller files. All controller files are included on the directory controllers. Like models, there is also an __init__.py file for importing the controllers.
We use @http.route as a decorator in the controller for routing, which means we can navigate from one page to specific pages.
For example:
main.py
from odoo import http
from odoo.http import request
class Product(http.Controller):
@http.route('/products', type='http', auth='public', website=True)
def my_products(self , **kwargs):
products = request.env[product.product].sudo().search([])
return request.render('my_module.product_details_page', {'product_details':
products})
__init__.py
from . import main
views/:
This is another directory containing templates and views. These are XML files. In views, we define how the records will be displayed to the users. We can do high-level customization on the views. Views consist of visualizations like form, tree, kanban, activity, and many more.
The syntax is:
<record id="model_view_id" model="ir.ui.view">
<field name="name">NAME</field>
<field name="model">MODEL</field>
<field name="arch" type="xml">
<VIEW_TYPE>
<VIEW_SPECIFICATIONS/>
</VIEW_TYPE>
</field>
</record>
We can inherit existing templates, and can xpath the script or style tags. These template files are also given inside the view directory.
For example:
<template id="assets_backend" name="test_asset" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/test_module/static/src/js/test.js"></script>
</xpath>
</template>
We can give the path of all javascript, CSS, SCSS files like this way.
static/:
This directory contains all web assets. A directory src is inside the static, and src contains other directories like JS/, CSS/, SCSS/, img, and many more. we can give javascript files inside the js directory. All CSS, SCSS, img must be on under corresponding directories.
security/:
Security is important for all applications. We can define what a user can do and can’t do in our application by using security. We can set different permissions for the user.
-> Group-based access control:
We can create records by using XML, Groups are also created as records and the corresponding model is res.groups. And we can set read, write, create, delete permissions to these groups.
-> Access rights:
All the access rights are defined in the file ir.model.access.csv. Each of the access rights will be associated with a model, group, and permissions like read, write, create, delete.
For Example:
Id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
Access_account_tax,account.tax,model_account_tax,account.group_account_invoice,1,0,0,0
-> Record rules:
We can define some rules for our records. Rules are associated with the model ir.rule. By these rules, we can limit or restrict some access rights. We can limit access rights based on the domain_force.
For Example:
<record id="hr_user_work_entry_employee" model="ir.rule">
<field name="name">Work entries/Employee calendar filter: only self</field>
<field name="model_id" ref="model_hr_user_work_entry_employee"/>
<field name="domain_force">[('user_id', '=', user.id)]</field>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
<field name="perm_create" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_unlink" eval="1"/>
<field name="perm_read" eval="0"/>
</record>
wizard/:
This directory contains all wizard related files. In wizard we use Transient Model instead of Model. Wizard is not persistent, it will be removed from the database after a certain time. For launching wizards we set the target as new in window actions.
ie:
<record id="wizard_example" model="ir.actions.act_window">
<field name="name">Wizard Example</field>
<field name="res_model">wizard.model</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="binding_model_id" ref="model_context_model_ref"/>
</record>
report/:
There are different types of reports in Odoo. All python objects and XML files related to reports are included in this directory. In Odoo, we create reports based on Wkhtmltopdf, Twitter Bootstrap, QWeb Templates.
A report contains:
– ir.actions.report: It contains different basic parameters for our report.
<record id="action_account_original_vendor_bill" model="ir.actions.report">
<field name="name">Original Bills</field>
<field name="model">account.move</field>
<field name="binding_model_id" ref="model_account_move"/>
<field name="report_type">qweb-pdf</field>
<field name="report_name">account.report_original_vendor_bill</field>
<field name="report_file">account.report_original_vendor_bill</field>
<field name="attachment">'original_vendor_bill.pdf'</field>
<field name="attachment_use">True</field>
<field name="binding_view_types">list</field>
</record>
Qweb view:
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="web.external_layout">
<div class="page">
<h2>Report title</h2>
</div>
</t>
</t>
</t>
test/:
In this directory, we can include all Python tests. If we create python files, we can also add unit tests for our module. These tests are included in this directory.
And also a module has a __manifest__.py file and an __init__.py file directly inside the main directory. The __manifest__.py file consists of all the module descriptions in a single dictionary.
For Example:
__manifest__.py
{
'name': 'Maintenance',
'version': '1.0',
'sequence': 100,
'category': 'Manufacturing/Maintenance',
'description': """
Track equipments and maintenance requests""",
'depends': ['mail'],
'summary': 'Track equipment and manage maintenance requests',
'website': 'https://www.odoo.com/page/tpm-maintenance-software',
'data': [
'security/maintenance.xml',
'security/ir.model.access.csv',
'data/maintenance_data.xml',
'data/mail_data.xml',
'views/maintenance_views.xml',
'views/maintenance_templates.xml',
'views/mail_activity_views.xml',
'data/maintenance_cron.xml',
],
'demo': ['data/maintenance_demo.xml'],
'installable': True,
'application': True,
'license': 'LGPL-3',
}
In the case of __init__.py file we can import all python directories.
Ie,
__init__.py
from . import models
from . import controllers
These are the most important guidelines for creating a module in Odoo 14.