Automated Action to prevent duplicates

As standard, Odoo does not have “uniqueness” checks on many fields. This can be problematic, for example if there are

  • multiple products with the same name (which one to choose?)
  • multiple customers or vendors with the same name

Either they are different, in which case they should be given different names, or someone has entered the same data twice.

It is possible to set a field as being unique in the Model definition, but it’s also possible to use Automated Actions.

How to do it

If you are not familiar with Automated Actions, start here

Enable Developer Mode and navigate to Settings / Technical / (Automation) / Automated Actions:

Click on CREATE and enter the following:

Model:  Product Template
Action To Do:    Execute Python Code
Trigger Condition:   On Creation & Update
Before Update Domain: Internal Reference is set
Apply on:  Match all records 

Python Code

if record.default_code:
   existing_product = env['product.template'].search([('id','!=',record.id),('default_code','=',record.default_code)])
   if existing_product:
     raise Warning("You can't have the same Internal Reference Number in Odoo twice!")

Odoo 14

There is a small change in the syntax:

raise UserError("You can't have the same Internal Reference Number in Odoo twice!")

30 thoughts on “Automated Action to prevent duplicates

  1. Hi,
    Thanks for the valued python Code, i detect one problem:
    Even with internal references that don’t exist, the program its giving me the message “You can’t have the same Internal Reference Number in Odoo twice!”
    Maybe the problem is solved with an extra line of code but I don’t have the knowledge for it

    Like

  2. I believe this technique does work, but maybe there are some special cases that need additional checking.

    Is this always happening? Or only some reference numbers?

    Like

  3. Hi,
    I’ve been looking for a solution like this for quite a long time, but the Odoo support turned me down!
    Thanks a lot for the tip.
    I tried to create the action for contacts, but I’m really too bad at Python to achieve it…
    Would you be kind enough to write the code for contacts as well ?

    Like

      1. Thanks a lot, Chris, I hadn’t found this solution yet, I’ll give it a try in the next few days.

        Like

  4. This is very helpful for me.
    Duplicate Internal Reference Numbers has led to product import challenges.

    Please how about HIDING THE BUTTON IN POS SALES SCREEN that allows a
    cashier to serve another customer while the first in queue is not ready?
    i mean a cashier to be able to serve only one customer at a time…no multiple order forms visible?

    Like

    1. Sorry, but that’s too technical for me (especially because POS is totally different from the rest of Odoo)

      Like

    1. It should work if you replace Product Template with Product and product.template with product.product (in the Python)

      Like

    1. You mean that Odoo should display an error if no internal code? That can be done, but it might cause problems in various places where you can create a product “on the fly”.

      Alternatively you could make it mandatory using Studio / creating an Extension View.

      Like

      1. I can make it mandatory using Studio already but can I raise the my own message such as “Default code is empty”

        Like

      2. You’d need an Automated Action with some simple Python code. If you look at the examples above under “Validation” it might help.

        Like

    1. That’s a TERRIBLE idea, but yes, it’s possible.
      It’s often a bad idea to use raw SQL, especially manipulative ones within Odoo environment, let alone you’ll be in action execution context.
      Odoo has many ORM features, including but not limited to multi level caches, secure rollback systems, access control mechanisms etc. and you completely bypass them all…
      Usually, it’s only required for complex QUERIES, mostly for reporting.

      If you still insist on using it, you have env in execution context, it holds current cursor in env.cr

      Like

  5. Thank you for this valuable code, It is very helpful.

    But I have a problem, I need to allow duplication but, if the name is the same it has to show the warning message. Other should be exactly as same as the previous product.

    Like

  6. Thanks for so much effort Chris, I believe it’ll help many people.

    Just a side note, since we won’t use any data on the record, we can just use search_count instead, it fetches the “count of records” instead of the records themselves and is faster.

    Like

  7. Hi, I’m hoping this thread is still active. I’m trying to use automated actions to prevent duplication of employees from their identification number. I used the following code but it don’t seem to work.

    employee = env[’employee.employee’].search([(‘default_identification no’ , ‘=’ , record.identification_no)])
    if len(employee) >1 :
    raise warning(“You cannot create duplicate”)

    Like

  8. Hi. I hope this thread is still active. I’m trying to prevent duplicate employees using Python code

    employee = env[’employee.employee’].search([(‘default_identification no’ , ‘=’ , record.identification_no)])
    if len(employee) >1 :
    raise warning(“You cannot create duplicate”)
    Can anyone assist as it is not working please?

    Like

  9. I have tried to use the code for preventing duplicate Product Names instead of Internal Reference.
    It still allows the duplication of Product Names.
    NOTE: I am using Odoo 16
    I modified the code to be as follows:
    Model: Product
    Action To Do: Execute Python Code
    Trigger: on Creation & Update
    Before Update: Name is set
    Apply On: Match all records

    Code:
    if record.name:
    existing_product = env[‘product.template’].search([(‘name’,’!=’,record.name),(‘name’,’=’,record.name)])
    if existing_product:
    raise UserError(“You can’t have the same Prouct Name in Odoo twice!”)

    Like

    1. Hi, this code works for me:
      if record.name:
      existing_product = env[‘product.template’].search([(‘id’,’!’,record.id),(‘name’,’=’,record.name)])
      if existing_product:
      raise Warning(“You can’t have the same Name in Odoo twice!”)

      Like

Leave a comment