Odoo howto’s



How to create a purchase order from a sales order?

  1. Create a product, check ‘Replenish on Order (MTO)’ on the inventory tab and add a vendor in the purchase tab.
  2. Create and confirm a sales order with the product => a purchase order is created automatically.

Since Odoo 14 MTO is hidden (route is archived) and can be reactivated or replaced by using reordering rules > https://odootricks.tips/odoo-14-replenishment-mto/.


Make to Order vs Stock

  • Make to Order = produce (manufacturing order) / buy every time you sell it (purchase order) on demand
  • Make to Stock = deliver from stock = buy periodically to replenish inventory


Set up a development environment with PyCharm

  • Create an Odoo? folder and clone Odoo with the command git clone https://github.com/odoo/odoo.git –branch ?.0 –single-branch –depth 1.
  • Create a virtual environment in that folder (with Python3 since Odoo 11) …
    • virtualenv ./venv -p /usr/bin/python(3)
    • source ./venv/bin/activate
    • pip(3) install -r odoo/requirements.txt (If psycopg2 is version 2.7.1 in this file, set it to first.)
    • deactivate
  • Open the Odoo? folder in PyCharm …
    • Change the standard Python interpreter of your project to the newly created environment … File > Settings > Project: Odoo? > Python Interpreter > Cog icon + Add > Select Odoo?/venv/bin/python(2.7).
    • Make a run configuration …
      • + Python
      • Script path = Odoo?/odoo/odoo -bin (or openerp-server before Odoo10)
      • Parameters
        • Odoo should be able to connect to your database, so make sure the params –db_user and –db_password are correctly set.
        • If you have more environments of Odoo of even different versions, it’s a good idea to force the selection of the correct database by setting –db-filter=^Odoo?$ as parameter.

How to rename an installed module?

Data is lost when you uninstall and reinstall, so https://gist.github.com/antespi/38978614e522b1a99563.


How to trigger an onchange event?

def _onchange_code_prefix_start(self):
    if not self.code_prefix_end or self.code_prefix_end < self.code_prefix_start:
        self.code_prefix_end = self.code_prefix_start

How to add a value to a many2one or many2many field?

if electronic not in self.inbound_payment_method_ids:
    self.inbound_payment_method_ids = [(4, electronic.id)]


General tips

  • Add a space with ampersand hashtag 160 ;
AssertionError: Element odoo has extra content: record, line 3

1/ If you are extending a view, check if your model name is the one of the parent view.

2/ To spot invalid syntax, go to an online relax ng validator like https://www.liquid-technologies.com/online-relaxng-validator. Add the contents of your view in the first input field, the contents of odoo/odoo/import_xml.rng in the second and validate. The errors here will give you precise info on the error. Here is an example …

Odoo howto's 1 - Open source software freelancer


How to extend/overrule/override <record>?

<record>s of model ‘ir.ui.view’ have an inherit_id property …

    <record id="product_template_search_view" model="ir.ui.view">
        <field name="model">product.template</field>
        <field name="inherit_id" ref="product.product_template_search_view" />
        <field name="arch" type="xml">
            <field name="name" position="after">
                <field name="product_brand_id" />

<record>s of models other than ‘ir.ui.view’ do not work with an inherit_id. If you want to change a field value of a record, you should copy the definition of the <record> in your module, prefix the id with the original module name (+ dot) and include the field you wish to change like for example …

<record id="purchase_requisition.type_multi" model="purchase.requisition.type">
   <field name="exclusive">exclusive</field>

If that <record> is wrapped in a noupdate=”1″ you should make the record writable first (and unwritable again after) like this …

<odoo noupdate="0">
	<function name="write" model="ir.model.data">
   		<function name="search" model="ir.model.data">
       			<value eval="[('module', '=', 'purchase_requisition'), ('name', '=', 'type_multi')]"/>
   		<value eval="{'noupdate': False}" />
	<record id="purchase_requisition.type_multi" model="purchase.requisition.type">
   		<field name="exclusive">exclusive</field>
	<function name="write" model="ir.model.data">
   		<function name="search" model="ir.model.data">
       			<value eval="[('module', '=', 'purchase_requisition'), ('name', '=', 'type_multi')]"/>
   		<value eval="{'noupdate': True}" />
How to add default views for a model?

Just create an action and menu item for the model …

    <record id="product_template_attribute_action" model="ir.actions.act_window">
        <field name="name">Product Template Attributes</field>
        <field name="res_model">product.template.attribute.line</field>
        <field name="view_mode">tree,form</field>
    <menuitem id="menu_product_template_attribute_action"
How to control the order of view inheritance?
<record id="product_template_tree_view" model="ir.ui.view">
    <field name="model">product.template</field>
    <field name="inherit_id" ref="product.product_template_tree_view"/>
    <field name="priority" eval="32"/>

The default priority of a view is 16. The definition above will apply this extension after most inherited views.

How to create xpath expressions?


<xpath expr="//field[@name='invoice_line_ids']/tree/field[@name='company_id']" position="after">
<xpath expr="//div[hasclass('o_primary')]" position="after">
<xpath expr="//link[last()]" position="after">
<xpath expr="." position="inside">
<xpath expr="//templates/descendant::field[@name='partner_id']" position="after">
<xpath expr="//button[@name='action_timer_start'][hasclass('btn-primary')]" position='after'>
How to move a field in a view?
  <xpath expr="//field[@name='active']" position="before">
    <xpath expr="//field[@name='barcode']" position="move"/>

Before Odoo 12 you first have to set the moving field to invisible and adding it again at the right position!

<field name="product_brand_id" position="attributes">
    <attribute name="invisible">1</attribute>
<field name="name" position="before">
    <field name="product_brand_id"/>
Search view > How to set a default filter in search bar?



How to create a new report?
<template id="report_saleorder_document">
    <t t-call="web.external_layout">
        <t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)" />
        <div class="page">
            <div class="oe_structure"/>

<template id="report_saleorder">
    <t t-call="web.html_container">
        <t t-foreach="docs" t-as="doc">
            <t t-call="sale.report_saleorder_document" t-lang="doc.partner_id.lang"/>
How to extend a report?
<template id="report_saleorder_document" inherit_id="sale.report_saleorder_document">
    <xpath expr="//div[@t-if='doc.user_id.name']" position="replace"/>

How to create a new report based on an existing one?

<template id="report_saleorder_document2" inherit_id="sale.report_saleorder_document" primary="True">

<template id="report_saleorder">
    <t t-call="web.html_container">
        <t t-foreach="docs" t-as="doc">
            <t t-call="sale.report_saleorder_document2" t-lang="doc.partner_id.lang"/>

Domain examples

[('applicability', '=', 'taxes'), ('country_id', '=', tax_fiscal_country_id)]
['|', '|', ('name','ilike',self), ('company_name','ilike',self), ('email_normalized','ilike',self)]
['|', ('product_ids', 'ilike', self), ('line_ids.product_id','ilike',self)]

Dot notation can be used in domain!


Technical > Email > Templates

How to extend/overrule/override an email template?

If you want to do this in code look at How to extend/overrule/override <record>?.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top