How to Create an Action Server in Odoo

Action Server or more precisely ir.actions.server is an action in odoo which allows us to call python code from the user interface. Actually Action Server has many options, but I think the most useful option in real life is the Execute Python Code. This option has functionality similar to a button with an object type like the code below.

<button name="action_confirm" string="Confirm" class="btn-primary" type="object" />

The difference is that the button above can only be used in the form view. Meanwhile, Action Server can be placed in multiple views, including menu item. Then, when should we use the Action Server ?

Use Action Server if we can’t place the button that triggers the action in the Form View. For example on menu item. If we can place it in the Form View, it’s better to use the normal button, it’s easier.

Second, use the Action Server if the action we are going to call requires calculations or checking conditions before responding to the user. If not, just use the Action Window combined with Domain.

As a sample case, suppose a company only allow one sales target data per database. Where the data can be edited and cannot be deleted. To handle this case, in Form View we can add parameter delete=”0″ so the data cannot be deleted. You can also add the create=”0″ parameter so user cannot create new data.

But wait, if we add the create=”0″ parameter in Form View, we can’t add the data forever, right ?

That’s why we need an Action Server. If we use an Action Server, we can make a condition about when user clicks on the Sales Target menu we can check whether there is a sales target data or not. If the data exist, display it to the user, if there is no data, then the data is automatically made in the backend, then display it to the user. So user cannot create the sales target data freely via user interface and we can ensure that there is only one sales target data because it has been checked on the Action Server.

As a simulation of the case above, first create a sales target model like below.

# -*- coding: utf-8 -*-

from odoo import models, fields, api, exceptions, _

class SalesTarget(models.Model):
    _name = 'ng.sale.target'

    name = fields.Char(default='Sales Target')
    target_line_id = fields.One2many('ng.sale.target.line', 'target_id')
    

class SalesTargetLine(models.Model):
    _name = 'ng.sale.target.line'

    user_id = fields.Many2one('res.users', string='Sales Person')
    total_target = fields.Float(string='Total Target', default=0)
    target_id = fields.Many2one('ng.sale.target')


    

Then make the form.

<record id="ng_sale_target_form" model="ir.ui.view">
    <field name="name">Sales Target</field>
    <field name="model">ng.sale.target</field>
    <field name="arch" type="xml">
        <form string="Sales Target" create="0" delete="0">
            <sheet>
                <h2>Enter the sales target per Sales Person</h2>
                <notebook>
                    <page string="Sales Target">
                        <field name="target_line_id">
                            <tree editable="bottom">
                                <field name="user_id" />
                                <field name="total_target" />
                            </tree>
                        </field>
                    </page>
                </notebook>
            </sheet>
        </form>
    </field>
</record>

Next, create a menu item and an action server.

<!-- Action Server -->
<record id="action_open_sale_target_form" model="ir.actions.server">
    <field name="name">Sales Target</field>
    <field name="type">ir.actions.server</field>
    <field name="state">code</field>
    <!-- model name -->
    <field name="model_id" ref="model_ng_sale_target"/> 
    <!-- The name of the method to be called -->
    <field name="code">action = model.open_sales_target()</field>
</record>

<!-- Menuitem on Sales >> Configuration menu -->
<menuitem name="Sales Target"
        id="menu_sale_target"
        parent="sale.menu_sale_config"
        action="action_open_sale_target_form" />

Finally add a method with the same name with the Action Server above to the model.

def open_sales_target(self):
    # check whether there is a sales target data or not
    existed_data = self.env['ng.sale.target'].search([],limit=1)

    # if no, create the new one
    if not existed_data:
        existed_data = self.create({})        
    
    # display the sales target data to the user using an Action Window
    return {
        'type': 'ir.actions.act_window',
        'view_type': 'form',
        'view_mode': 'form',
        'res_model': 'ng.sale.target',
        'res_id': existed_data.id,
    }

Don’t forget to import the code above into the related files then install the module. Open Sales >> Configuration >> Sales Target menu. Insert data, then save. Then open it several times. Please notice, no matter how many times we open the form, the id will not change. The Create and Delete buttons are also not visible. This means that we can ensure that we only have one Sales Target data.

Download the Source Code

Related Article

Leave a Reply

Your email address will not be published.