Automated Actions

Automated Actions (and their close cousin, Server Actions) are a powerful way to add functionality to Odoo without any programming (or with only a few lines of Python code).

Also, if you are using Odoo Online you cannot do development or install third-party add-ons but you can use Automated Actions (and Server Actions).

Automated Actions can be used to enhance and customize Odoo functionality in several ways:

Automated Actions can be triggered on Creation, Deletion or Update of a database record in the specified Odoo Model (database table), and can also be based on Form Modification or a Timed Condition.

Automated Actions can be conditioned on domains and / or “watched fields”, which makes it possible to define “business rules” (an action for one group of customers, or one type of product, etc.) and more complex logic can be added with Python code.


  1. Update fields on the selected model (database table)
    1. Set a fixed value (can be based on rules)
    2. Derive a new value:
    3. Clear a field
  2. Create new records on another table
  3. Send email (a useful feature, but email templates can be tricky to setup)
  4. Add followers (example on Odoo Help Forum)
  5. Create activities (so a user can follow-up)
  6. Validation (needs Python)
  7. Customize document numbering (needs Python)
  8. Other Python functions
    1. Copy Records
    2. Sort data
  9. It’s also possible to execute multiple server actions (for the same Model)

Getting started

Start by enabling developer mode and navigating to Settings / Technical / Automated Actions.

Note: Every Automated Action is also a Server Action, which enables it to be added as a “contextual action” (example).


If you cannot find this option, you may need to install the module “Automated Action Rules”.

First remove the “Apps” filter by clicking on the ‘X’:

Then search for “Automated”

If it’s not installed, click on ‘INSTALL’.

Now you might want to try one of the examples (links above). Or if you want to understand more about Automated Actions, read on:

Automated Action


Select the Model (database table)

Action To Do

  • Execute Python Code (see below)                             
  • Create
    • Create a new record in a specified model (db table). You specify the fields in the ‘Data to Write‘ tab.
  • Update the (current) Record
  • Execute several actions
    • Trigger several other server actions
  • Send Email
    • Automatically send an email (using a template)
  • Add Followers                           
  • Create Next Activity                                

Trigger Condition

This defines when the Automated Action can be triggered:

  1. On Creation [on_create]
  2. On Update [on_write]
  3. On Creation & Update [on_create_or_write]
  4. On Deletion [on_unlink]
  5. Based on Form Modification [on_change]
  6. Based on Timed Condition

Watched Fields

This was added in Odoo 13

This is optional, but if you specify any fields here the Automated Action will only be triggered if the value of these field(s) have changed.


For the first four trigger conditions, you can define the records to be selected using domains. Odoo will show you how many records meet the criteria and you can display a list of records to check whether your criteria is correct.

There are two domains:

  1. Before Update Domain (used for Updates only)
  2. Apply on

So it is possible to have “before” and “after” domains to trigger an action when a user makes a specific change (e.g. adding a salesperson to a customer – the field was blank before and now has a value).

Note that there are some limitations with domains if you create Automated Actions through the ‘front-end’ menu.

  • There is a pop-up dialog box which makes it easier to enter domains, but at the cost of limiting functionality.

Data to Write

The simplest way to update or write data is to select the fields from a list. This applies when the action is “Create” or “Update the Record”

Simple Python expressions can also be used

The first two lines are taking data from the record, the third line writes multiple (fixed) values to a many2many field, the last line takes data from the parent record. This is from the Add contacts to mailing lists example.

Python Code

Automated Actions can use a subset of Python. This is more powerful but requires a deeper understanding of Python. These are the commands that are available:

  • env: Odoo Environment
    • Information about current user and company, as per this example
  • model: Odoo Model (database table)
  • record: gives access to field values, e.g. record['company_id']
  • records: allows multiple records to be read / updated, as per this example
  • timedatetimedateutiltimezone: to retrieve date and time
  • log(message, level='info'): to record debug information in the ir.logging table
  • Warning: Display a Message (as per this example)
  • action = {...}
    • This allows you to call another Server Action for the same Model. The syntax is:
      • action = { "type": "ir.actions.server", "id": 372, }
        • 372 is the ID of the Server Action

But there’s no need to understand everything that can be done using Python. In fact, you can create Automated Actions without any Python at all.

Set customer lead time

  • Model = product.template
  • Trigger Condition = On Creation
  • Apply On (domain) = Can be Sold
    • Note that Odoo tells you that 94 records meet the criteria (and you can click here to view a list of those records)
  • Action To Do = Update the Record
  • Data to Write
    • Field = Customer Lead Time
    • Evaluation Type = Value
    • Value = 10

So we can see that using “Update the Record” is quite simple and requires only a basic knowledge of the Odoo database (but user-defined defaults can also be used to do something similar).

However, using simple Python expressions allows us to go beyond what can be done with user-defined defaults. Here we can use values from the current record, from a parent (e.g. update Sales Order Line with information from the Sales Order Header), from related Models (db tables) and environment variables.

Other Examples

This is quite powerful. It’s possible to create analytic accounts for sales orders, which replicates the standard functionality in Odoo to automatically create an Analytic Account for each project.

  • This example also contains some information about how to overcome a bug in Automated Actions.

There will be other business cases where this could be a good technique.

Advanced Python stuff

As explained in the comments, it is possible to use advanced Python commands to update “child” records. This Cybrosys blog seems to have a good explanation: How to pass values to the child lines of one2many fields

33 thoughts on “Automated Actions

  1. Can I set an automated action to automatically confirm a production order when I create it?
    I tried this Python code (I don´t know any python) but it doesn’t seem to do anything:

    What I need to do is to import several production orders in Confirmed stage so that it will trigger inventory rules. Would this be the better way to solve it?


  2. I’m not so familiar with Production Orders, but in theory this Python code should set orders to confirmed status:

    for rec in records:
    record[‘state’] = “confirmed”


    1. Hi Chris!
      I got an error message with that code, but I finally got it right (nearly by chance) with a server action and this code:


      “action_confirm” refers to the method associated to the confirmation button on the production order form.
      Thanks a lot for all the information and help, it was very usefull!!


  3. Hi Chris,

    Can I set an automated action to display a message which does not disrupt the process workflow on a delivery order? I tried using the raise a warning option but this stops the workflow. I just want to display a message after the delivery order is done.

    Thank you in Advance!


    1. I am not aware of any way to display a warning message “inline”, but there are some options:

      1. Add a message to the “chatter”, which means it will be visible to everyone,
      2. Send a message to the user (or to a group),
      3. Send an email to any specified email address (it’s probably best to create a group email address for this).

      I will try to add information on these options later.


  4. Hi, I noticed that for calculated fields, the trigger does not work.
    Eg. If a customer has a variable membership product and I want to use automated action to trigger a reminder email to be sent out 30 days before the membership expires.

    As a variable membership, the expiry date is calculated from the start date PLUS the membership duration.

    When I create an automated action using the “Based on Timed Condition” for Trigger Condition, it does not trigger.

    Is this a known limitation or am I just doing it wrong ?

    Thank you.


  5. Hi – quick question.

    How would I go about to change a field in the product template model? I have a custom field called “x_new_field_PD13904344933904755”. I want to do a calculation when the selling price or the cost price is updated.

    It works when I edit the record like this:

    ‘x_new_field_PD13904344933904755’: record.list_price – record.standard_price

    But – when you click the “update cost” link next to the standard_price field (the cost one), it pops up with a form where you add your new cost. That does NOT trigger the action.

    What would you advise the best way would be?

    Thanks in advance…


  6. Hello
    How can I prevent POS creation if no customer is selected on pos in odoo ?
    i update on automated Actions and select a Point of Sale Orders on , and select a execute python code on and select a Based on Form Modification on and select payments(pos.order) on then add this python code :
    if not record.partner_id:
    raise Warning(‘Please check customer’)


    1. ahmed mesallam:

      Make the automated action triggered on creation instead of on form modification ..
      then the pos order can’t be validated if the customer not set


  7. Hi I have created an automated action to detect a change to a field on a contact record.

    on update
    field – fiscal position
    exacute python code – records.message_post(body=”Fiscal position updated.”)
    I would like to make this display what the field was updated to!

    I tried records.message_post(body=”Fiscal position updated.” + record.property_account_position_id) but this just creates an error?

    this was based on another online tut. do you have any recommendations for displaying the updated fiscal position field on a contact record?

    Any help would be much apprecited.


  8. Hi Chris, I have a quick question.
    My base uses multi-company and when I create an item, the cost and taxes do not change for all of them.
    Is it possible to write a script that applies the change to all companies?

    Thanks in advance.


  9. Hi Chris,

    I am using Odoo 14 (online Version) and I am trying to customize the Sales Order Sequence so that it also includes the Customer Number: Year-CustomerNumber-InvoiceNumber.

    I did it up to the customer number using Odoo Studio.
    How can I add the customer number (I set it under Company/Sales & Purchase/Misc/Reference) to the quotation/sales number sequence?

    Thank you in advance!


  10. Hi Chris,
    I would like to trigger the creation of a delivery order for rental orders.
    Is it possible to create a delivery order using an automated action with ‘create new record’?
    If yes, how?

    Thank you and best regards,


  11. I need to send the Promo Code (Buy 2 Get one Free – B123) to the customer via email.

    Is there a way to configure Odoo to send the email automatically


    1. You can setup an automated action to send an email using a template that has the code in it (you have to setup the promo code ahead of time anyway so you already know the code). You would use the domain in auto action to determine when to send. As an example, you can use when a user creates an account, so in the domain it would be created by public user with an on creation trigger. In that scenario when an anonymous user chooses to create an account, they get an email with a promo code.


  12. I got a doubt. I want to create a new task per month, every time a sales order it’s crated(it is crated one per month). For example, I wanna create a task for March on 1st March. And another one for April, on April 1st. How can i do it?


  13. Thanks Chris for sharing all these tips; love your blog as reference. My question – do you have any experience with the ‘based on timed condition’ automatic action? I have created an automatic action to evaluate the end date of (custom module) contract. It should put the contract in a stage ‘terminated’ if the end date > today. It works whenever I create contracts with an end date after today (eg. within ending within 2 minutes or tomorrow). It doesn’t appear to work if I create a new contract with an end date in the past.
    So the basis question is, what am I missing here?


  14. Hello Chris,

    I find your blog really helpful! Thank you for sharing all these tips!
    I have 2 separate questions, perhaps you could help me with them, I have reached the odoo forum already with no success 😦

    1. I want to create an automated action that automatically deletes the project’s partners once the project is moved to the “completed” stage. Via tudio I managed to get the trigger, domain, and scope of the action correctly (I tested it already by setting the action to send an eamil), what I can’t find online is help to set the actual resulting action (delete project partners, as they don’t need to be involved anymore). I don’t know coding or phyton, so far I managed to set all my automatic actions by “create a new activity” but this one is more complex than that. Could you please help me with this?

    2. I need to create an a automated action that automatically moves a project to the “completed” stage, once ALL the project’s tasks are moved to the “completed” stage inside the project.

    Thank you for all your help!


    1. To delete any records, we usually use python code to do an unlink, after identifying the appropriate records. I don’t recall there are any standard activities that allow you to delete records.


      1. Thank you! I ended up using a python expression as you mentioned!

        Domain: [(“”, “ilike”, “completed”)]
        Action: Update record
        field: ids
        Value: [(5, 0, False)]


    2. Luckily I was able to solve question 1, by using a Python expresion (I leave it here in case someone needs it in the future, v. 16):

      Domain: [(“”, “ilike”, “completed”)]
      Action: Update record
      field: ids
      Value: [(5, 0, False)]


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s