Odoo is a suite of open source business apps that cover all your company needs: CRM, eCommerce, accounting, inventory, point of sale, project management, etc. Odoo apps integrate seamlessly to provide a full-featured software platform. It is a system that offers a wide range of features and functionality.
While it’s possible to use Odoo without any code snippets, you may find that certain tasks are easier if you have some coding experience. In this post, we’ve gathered a selection of useful Odoo code snippets for you to reference. Whether you’re looking to create custom reports or configure VAT settings, we’ve got something for everyone.
Table of Contents
Odoo Code Snippets
Customization
Inherit or Modify a Search View —
<record id="account_invoice_search_extended" model="ir.ui.view"> <field name="name">account.invoice.inherit.search</field> <field name="model">account.invoice</field> <field name="inherit_id" ref="account.view_account_invoice_filter"/> <field name="arch" type="xml"> <xpath expr="//field[@name='number']" position="replace"> <field name="number" string="Invoice" context="{'active_test': False}" filter_domain="['|','|','|','|', ('number','ilike',self), ('origin','ilike',self), ('reference', 'ilike', self), ('partner_id', 'child_of', self), ('invoice_line_ids.name','ilike',self) ]"/> </xpath> </field> </record>
Create a Custom Model and Its View —
from odoo import models, fields, api, _ class Payroll(models.Model): _name = 'custom.payroll' _description = 'Payroll' name = fields.Char(string="Number", readonly=True, copy=False, default='New') state = fields.Selection([ ('draft', 'Draft'), ('verify', 'Waiting'), ('done', 'Done'), ('cancel', 'Rejected'), ], string='Status', index=True, readonly=True, copy=False, default='draft') @api.model def create(self, vals): if vals.get('name', 'New') == 'New': vals['name'] = self.env['ir.sequence'].next_by_code('salary.number') or 'New' result = super(Payroll, self).create(vals) return result
Create a Wizard —
class SaleOrderWizard(models.TransientModel): _name = 'wizard.sale.order.download' def _default_orders(self): return self.env['sale.order'].browse(self._context.get('active_ids')) sale_ids = fields.Many2many('sale.order', string='Sales', default=_default_orders, auto_join=True, required=True, readonly=True) @api.multi def download_all(self): if self.sale_ids: for sale in self.sale_ids: # Do something here
Override a Model’s Create Update and Delete Methods —
class CustomModel(models.Model): _name='custom.model' name = fields.Char(string='Document Name') @api.model def create(self, values): res = super(CustomModel,self).create(values) return res @api.multi def write(self, values): res = super(CustomModel, self).write(values) return res @api.multi def unlink(self, values): res = super(CustomModel, self).unlink() return res
Open Success Message Popup —
<record id="mymodule_message_wizard_form" model="ir.ui.view"> <field name="name">mymodule.message.wizard.form</field> <field name="model">mymodule.message.wizard</field> <field name="arch" type="xml"> <form> <field name="message" readonly="True"/> <footer> <button name="action_close" string="Ok" type="object" default_focus="1" class="oe_highlight"/> </footer> </form> </field> </record>
Add a Custom Field to Contact Form —
<record model="ir.ui.view" id="view_res_partner_form_inherit"> <field name="name">module.res.partner.form.inherit</field> <field name="model">res.partner</field> <field name="inherit_id" ref="base.view_partner_form"/> <field name="arch" type="xml"> <xpath expr="//field[@name='vat']" position="after"> <field name="reference_code"/> </xpath> </field> </record>
Auto Generate Name Column with Sequence —
<record id="my_model_sequence" model="ir.sequence"> <field name="name">My Model Sequence</field> <field name="code">my.model</field> <field name="active">TRUE</field> <field name="prefix">TEST-</field> <field name="padding">4</field> <field name="number_next">1</field> <field name="number_increment">1</field> </record>
Add Filter and Group By to Search View —
<record model="ir.ui.view" id="custom_view_product_search_form_inherit"> <field name="name">product.template.search.form</field> <field name="model">product.template</field> <field name="inherit_id" ref="product.product_template_search_view"/> <field name="arch" type="xml"> <xpath expr="//search/filter[@name='consumable']" position="after"> <filter string="Has External Reference" name="filter_lazada" domain="[('has_external_reference','!=', '')]"/> <group expand="0" name="group_by" string="Group By"> <filter name="group_product" string="Product" domain="[]" context="{'group_by' : 'product_id'}"/> </group> </xpath> </field> </record>
Display Another Field in Many2one Instead of Name —
class ProductTemplate(models.Model): _inherit = 'product.template' @api.multi def name_get(self): self.browse(self.ids).read(['name', 'default_code', 'description']) return [(template.id, '%s%s%s' % (template.default_code and '[%s] ' % template.default_code or '', template.name, template.description and ' (%s)' % template.description or '')) for template in self]
Datetime
Set Default Date Field as Today or Any Date —
//today end_date = fields.Date(string='End Date', default=fields.Date.context_today, required=True) //from external source end_date = fields.Date(string='End Date', default=fields.Date.to_date(self._context.get('date_from')), required=false) //any date import time start_date = fields.Date(string="Start Date", default=time.strftime('%Y-01-01'))
Create Email Template and Send Email Programmatically —
class MyModel(models.Model): _name = 'my.model' _description = 'My Model' @api.multi def send_email(self): body_html = 'Hi {},<br/><br/>'.format(someone_name) body_html += '<div>The body goes here</div>' email_values = { 'email_to': '[email protected]', 'email_from': '[email protected]', 'body_html': body_html, } template_id = self.env['mail.template'].search([('model', '=', 'custom.model')], limit=1) template_id.send_mail(template_id.id, force_send=True, email_values=email_values)
Menu & Navigation
Add a Menu Item to a Model's Navigation —
<record id="act_download_sale" model="ir.actions.act_window"> <field name="name">Download Sales</field> <field name="res_model">wizard.sale.download</field> <field name="view_mode">form</field> <field name="view_id" ref="download_sale_form_view"/> <field name="target">new</field> </record> <menuitem id="menu_sale_export" parent="sale.sale_order_menu" name="Download Sales" sequence="0" action="act_download_sale"/>
Open an External URL from Menu Item —
<record model="ir.actions.act_url" id="act_open_tleapps"> <field name="name">Tle Apps</field> <field name="url">https://www.tleapps.com</field> <field name="target">new</field> </record> <menuitem name="Tle Apps" id="menu_reports" parent="menu_root" action="act_open_tleapps"/>
Report
Create a Custom QWeb Report —
<template id="custom_invoice_custom_report"> <t t-call="web.html_container"> <t t-foreach="docs" t-as="doc"> <t t-call="my_module.custom_invoice_external_layout"> <div class="page" style="font-family: sans-serif; font-size: 15px;"> <div t-if="doc.name"> Invoice No.: <span t-field="doc.name"/> </div> <div t-if="doc.partner_id.name"> Partner: <span t-field="doc.partner_id.name"/> </div> <!-- Invoice lines --> <t t-foreach="doc.invoice_line_ids" t-as="line"> </t> </div> </t> </t> </t> </template> <!-- Layout -->
Modify Header and Footer —
<?xml version="1.0" encoding="utf-8"?> <openerp> <data> <template id="report_header_footer" inherit_id="web.external_layout_standard"> <xpath expr="//div[@class='header']" position="replace"> <div class="header"> </div> </xpath> <xpath expr="//div[@class='footer o_standard_footer']" position="replace"> <div class="footer o_standard_footer"> </div> </xpath> </template> </data> </openerp>
Settings
Create Settings —
<?xml version="1.0" encoding="utf-8"?> <odoo> <data> <record id="res_config_settings_view_form" model="ir.ui.view"> <field name="name">res.config.settings.view.form.inherit</field> <field name="model">res.config.settings</field> <field name="priority" eval="99"/> <field name="inherit_id" ref="base.res_config_settings_view_form"/> <field name="arch" type="xml"> <xpath expr="//div[hasclass('settings')]" position="inside"> <div class="app_settings_block" data-string="My Module" string="My Module" data-key="my_module"> <h2>My Module Settings</h2> <div class="row mt16 o_settings_container"> <div class="col-12 col-lg-6 o_setting_box"> <div class="o_setting_left_pane"/> <div class="o_setting_right_pane"> <label string="Email From" for="custom_field"/> <div class="text-muted">Store custom data</div> <field name="custom_emails" widget="text"/> </div> </div> </div> </div> </xpath> </field> </record> </data> </odoo>