Record Rules are an important part of security in Odoo. They control which records users can access. For example, sales users can only access their own quotations and sales orders (see below).
- Record Rules can make it easier to develop functionality in Odoo (because the rules have already been setup)
- However, they can cause problems if there are multiple requirements related to one Model (database table).
- So it is possible that installing another app or module (or just enabling another feature, such as Private Addresses) can have unexpected results.
Quick Guide
- Users are members of application access groups (e.g. Peter Lee might be a Purchase Manager and an Inventory User).
- Each of those access groups may “inherit” access from a related group, for example
- Purchase Manager inherits the Purchase User rights
- Purchase User inherits the Internal User rights
- Users will also be members of ‘technical’ access groups, each of which has a specific purpose, for example:
- Manage multiple units of measure
- Analytic accounting
- Each of the access groups (both types) will grant access to:
- Database
- Models
- Records (through Record Rules)
- Fields (not normally used)
- Views
- Menus
- Windows Actions
- Other elements (Buttons, Filters, Wizards)
- Database
- Access from all these groups is combined, so a user could have Read access from one group and Write access from another group (see Permissions below).
- If there are no Record Rules, there are no record-level restrictions.
- In Odoo version 11 and earlier, the Administrator account was not subject to Record Rules. In Odoo 12 and later, the Administrator account is a member of all Access Groups and subject to Record Rules, but it is also possible to become a “Superuser” and bypass access rules.
Record Rules
Record Rules make use of domain to specify which records can be selected.
There are two types of Record Rule:
- Global rules (with no access group specified).
- These restrict access, and cannot be bypassed by other Record Rules.
- They are generally used for multi-company restrictions.
- They are quite easy to understand!
- Group-specific rules (for one or more access groups – e.g. Purchase Manager)
- These grant permission (subject to the restrictions imposed by the Global Rules).
- If there are multiple Group-specific rules then access is granted if ANY of the conditions are satisfied.
- This can make Group-specific rules more difficult to understand, and care needs to be taken when using them.
Example
The access group “Sales / User: Own Documents Only” has a Record Rule on Sales Orders (and Quotations) with this domain:
['|', ('user_id','=',user.id), ('user_id','=',False) ]
This will only allow access to:
- the user’s own orders / quotations (where salesman = current user)
- orders with no salesman (
user_id
) specified).
Alongside this, the group “Sales / User: All Documents” has a Record Rule with this domain:
[(1,'=',1)]
This will grant access to ALL Sales Orders / Quotations.
Note: there are identical Record Rules for Leads (the field names are the same).
Group Record Rules are almost always in sets of two, one to restrict access, one to grant full access (a set of three or more rules is also possible).
Permissions
Record Rules grant permission for one or all of the following actions:
- Read
- Write (update)
- Create
- Delete
Note that Read access is required in order to have any access!
There are several possible types of access, including:
- Read-Only
- Read and Write (but not create and delete)
- Read, Write and Create but not delete
- Full access
This can be done either through Model access or Record Rules, and there is an important difference between the two:
- If Read Access is not specified for a Model and user group, the user(s) will not have Read Access to that Model*
- If Read Access is not specified for a Record Rule (for a user group), the domain in that Rule will not apply, and so will not restrict user access*.
- However, if there are other Record Rules for Read access they would apply.
* Note that in both the above examples, users may be members of other user groups that will either grant or restrict access.
Using Sales Order and Quotations (sale.order
) as an example:
- As standard, only the Sales Manager can delete Sales Orders (this is from the Model Access)
- As explained above, some sales users can only access their own orders (through Record Rules)
- You could add record rules so that:
- Only supervisors or managers can cancel confirmed Sales Orders
- All sales users can cancel Quotations (draft Sales Orders)
- A cancelled Sales Order is still in the Odoo database, and a manager would be able to delete it.
Challenges
It’s easy to have problems with Record Rules because of the way they interact with each other. These can be in either direction:
- access is allowed when it should not be,
- users are not allowed do something they should be able to do
Here’s one example:
Private addresses
Odoo 12 introduced a Record Rule that was designed to limit access to “private addresses”. It’s on the Contacts model (res.partner
).
Just like the above example, there are a pair of Record Rules:
1. Allow access to “private addresses” for selected users
[('type', '=', 'private')]
2. Allow access for all users to other “non-private addresses”
['|',
('type', '!=', 'private'),
('type', '=', False)
]
This Record Rule grants access to all internal users through the “Internal User” access group (“Employee” in earlier versions). This group is inherited by all application access groups.
The problem is that the second Record Rule would effectively override other Record Rules for Contacts.
- For example, you might have used Record Rules to limit access to vendors (suppliers), but:
- a user who had not had access to vendors would now be granted access (because
type
will be blank).- They would also be able to access private addresses for customers and other types of contact!
- a user who had not had access to vendors would now be granted access (because
That’s because access is granted if the conditions for ANY of the Group-specific rules are satisfied – and these can come from multiple access groups.
The solution is either to remove the two “private address” rules or to replace them with several rules that cover all the combinations.
Alternatives
It is also possible to restrict access without using Record Rules.
- Domains can be added to restrict access to fields in views (easy to do in Odoo Studio).
- Changes can be made to menus:
- Other options are available by doing development.
The disadvantage of these methods is that it will normally require the restrictions to be applied in multiple places (which, of course, is what makes it more flexible). But it is easy to miss one or more views and then the user has access they should not have!
List of Record Rules for a user (Odoo 13)
Navigate to Settings / Users & Companies / Users

These “smart buttons” can be useful for troubleshooting, and you can use Filters to show information for one or more Models:

This shows us that the user has full access to their own sales order lines (from the “Sales / User: Own Documents Only” group) plus Read-Only access to Sales Order lines for projects (as the “Project Administrator”).
This is the domain for the second Record Rule:
['&', '&',
('state', 'in', ['sale', 'done']),
('is_service', '=', True),
'|', ('project_id','!=', False), ('task_id','!=', False)]
This selects Sales Order Lines that are:
- confirmed or locked, and
- service items and
- with either a project or task id
This will be used when billing from timesheets, so it logical that this access is available for a Project Administrator.
Note: there should be no conflict between these two Record Rules (sometimes the combination produces undesirable results, as explained above).
Hi there,
I want to setup record rule for sales men to only see his customers in contact model which identified in sales person field.
but the sales manager can see all customers in contact model.
I tried to change the record rule for res.partner but end up with huge bug as no one can sign in any more but this is not my problem because I tried it in the test database.
please need your help.
LikeLiked by 2 people
Remember that contact (res.partner) includes customers, suppliers and users. Limiting access could certainly cause problems.
LikeLike
Hi Ahmer here you go… this works for Odoo 14 Enterprise and Odoo 15 Enterprise. I suspect it works for community but I’ve never tested it.
Salesperson own contacts
[‘|’, ‘|’, (‘create_uid’, ‘=’, user.partner_id.id), (‘user_id’, ‘=’, user.partner_id.id), (‘user_id’, ‘=’, user.id)]
LikeLiked by 1 person
Hi Steven,
I was looking for a similar rule. I tried the rule by assigning it to the group_sale_saleman group (See Own Documents) and created a test user in v15 Enterprise. However I can still see all contacts where the test user doesn’t meet the conditions. Any ideas?
LikeLike
Could be the “private addresses” record rule, as explained above.
LikeLike
Thanks!!
LikeLike
Yes, it’s most likely the private address rule. I went another route entirely since I ran into random issues with this rule I posted her a while ago.
I’ll look for it and post the new one today.
LikeLike
I don’t use that code I posted before because it started to become burdensome to manage when multiple contractors needed access to the same records.
I threw together a module so you can see what I use now. Basically a tag on contacts that corresponds to res.users and provides access to each record. I only have it setup in contacts right now but it could be expanded on. It’s a lot easier for me to manage contacts this way.
Let me know if you have any questions and I will try to help you out.
https://github.com/netfxtech/misc_odoo_addons/tree/master/access_res_partner_contractor
LikeLike
yeah that what I figured out.
I tried to make filter in window actions but it doesn’t work.
[(‘user_id’, ‘=’, user.id) ]
please I need help.
LikeLiked by 1 person
You should find filters like that in standard Odoo (from CRM) as per this example:
Filters and search views
LikeLiked by 1 person
Hello, how to use “Record Rules” to assign permissions in location/warehouse in the inventory module.
LikeLike
The same way that we use Record Rules for any other Model? If you have a specific question about it, maybe someone will offer some advice (not me, as I am quite busy!).
LikeLike
How I can limit users to see only sales order made by sale team members? I have team which ID = 6 and I have tried like below but not succeed
[(‘team_id’, ‘=’, 6)]
LikeLike
Try team_id.id (not sure this is correct)
LikeLike
i created those record rule to edit Purchase order at RFQ state only
but it didn’t work
Purchase Order [(‘state’, ‘in’,[False, ‘RFQ’])]
Purchase Order Line [(‘order_id.state’, ‘in’,[False, ‘RFQ’])]
LikeLike
Hi, I want to display PO and Stock Picking based on allowed branch in odoo. So if you log in as user Ana with allowed branch = Singapore, then the PO/Stock Picking that appear are only PO/Stock picking with the Singapore branch. if it’s like that, can it use ir.rule?
LikeLike
The problem here is that you need to have the Branch for a user available in the same way as company information. I have not used this app but I suppose it will provide that functionality: https://apps.odoo.com/apps/modules/15.0/multi_branch_base/
LikeLike
I have Managers that have access to edit attendance. I want to restrict them to only editing attendance for their team and not themselves. There is a user: modify own attendance only record rule but how would I configure that to achieve my goal?
LikeLike
I would probably look at the security groups in the sale module and replicate it. That would probably be the best way forward if you use sales teams or something equivalent.
LikeLike