Purpose
=======
The method _name_search and _search add support to search as another user.
All the overrides of name_search and search redefine the behavior of the search.
This bring inconsistencies as the result of a call to _name_search and name_search
could differ on certain modules, which is not acceptable.
Specification
=============
Example:
~~~~~~~~
If the name_search method is overridden to search also on the driver name,
then calling name_search with a label 'JF' will return all the cars with a name containing
'JF' or all the cars with a driver name containing 'JF'. Let's say that we have a ir.rule
preventing a user to read the cars of another company. Then the call to name search only returns
the cars satisfying the previous condition AND belonging to his company.
Now, we want to overpass this constraint. We call _name_search with the attribute name_get_uid=1.
Then the call to _name_search returns all the cars from all the companies with a name like 'JF',
but nothing is done about the driver_name.
Example of wrong search redefinition on a model
-----------------------------------------------
@api.model
def name_search(self, name, args=None, operator='ilike', limit=100):
domain = args or []
domain = expression.AND([domain, [('name', 'ilike', name)]])
partners = self.env['res.partner'].search([('name', operator, name)])
if partners and name:
domain = expression.OR([domain, ['|', ('driver_id', 'in', partners.ids), ('driver_id', '=', False)]])
rec = self.search(domain, limit=limit)
return rec.name_get()
Example of correct search redefinition on a model
-------------------------------------------------
@api.model
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
domain = args or []
domain = expression.AND([domain, [('name', operator, name)]])
partner_ids = self.env['res.partner']._search([('name', operator, name)], access_rights_uid=name_get_uid)
if partner_ids:
domain = expression.OR([domain, ['|', ('driver_id', 'in', partner_ids), ('driver_id', '=', False)]])
rec = self._search(domain, limit=limit, access_rights_uid=name_get_uid)
return self.browse(rec).name_get()
The same logic should be applied on the overrides of the search method.
The reified view on the res users will be dropped in the following commit.
The previous commit adds support to define each group as a computed field on the res users.
This commit defines:
- A boolean field for each 'isolated' res.group, i.e. a group in the hidden category.
- A selection field for each 'Application' res.group, i.e. a group in a application category.
Example:
- The group to manage pricelist in sales becomes a boolean field
- The groups project user/manager become a selection field
When creating a timesheet, several fields need to be recomputed:
- `currency_id`
- `group_id`
- `department_id`
- `is_timesheet`
- `validated`
When `validated` is computed before the other fields, the recomputation
will lead to an `AccessError` because of the rule
`hr_timesheet.timesheet_line_rule_user`.
Since the test `test_timesheet_validation_user` expects an
`AccessError`, the test succeeds. However, from time to time,
`validated` is computed last => the `AccessError` is not raised.
Actually, a `ValidationError` should be raised in this case (from the
`create` override in `timesheet_grid`).
This commit is a cherry-pick of 802339c12d
and dcca2e8b9d
When creating a timesheet, several fields need to be recomputed:
- `currency_id`
- `group_id`
- `department_id`
- `is_timesheet`
- `validated`
When `validated` is computed before the other fields, the recomputation
will lead to an `AccessError` because of the rule
`hr_timesheet.timesheet_line_rule_user`.
Since the test `test_timesheet_validation_user` expects an
`AccessError`, the test succeeds. However, from time to time,
`validated` is computed last => the `AccessError` is not raised.
Actually, a `ValidationError` should be raised in this case (from the
`create` override in `timesheet_grid`).
This replaces the former modified preorder tree traversal (MPTT) with the
fields `parent_left`/`parent_right`. Each record is associated to a string
`parent_path`, that represents the path from its root node to itself. The path
is made of the node ids suffixed with a slash:
a node | id | parent_path
/ \ a | 42 | 42/
... b b | 63 | 42/63/
/ \ c | 84 | 42/63/84/
c d d | 85 | 42/63/85/
This field provides an efficient implementation for parent_of/child_of queries:
the nodes in the subtree of record are the ones where `parent_path` starts with
the `parent_path` of record. It is also more efficient to maintain than the
MPTT fields, and less sensitive to concurrent updates, because the value of
`parent_path` does not depend on sibling nodes.