diff options
| author | len-odoo <len@odoo.com> | 2018-04-25 15:38:20 +0200 |
|---|---|---|
| committer | Yannick Tivisse <yti@odoo.com> | 2018-04-26 15:13:38 +0200 |
| commit | ab179bb2d7b8f890e04ea79e70d7bc0898e7599f (patch) | |
| tree | 55d47b9a2422e8f430eded44f1ed013faa2b1cc6 | |
| parent | e67b61811bc01fad467545dc8896d754dc39506a (diff) | |
[IMP] base: Add compute/inverse methods to manage user groups
Purpose
=======
Allow to define users groups on a res.user with computed fields based on the 'groups_id' field.
Specification
=============
Add compute/inverse methods to manage specific groups on a res.users.
These methods should be used on fields defined like one the following cases:
1. A boolean field with the compute/inverse method and an attribute group_xml_id.
Example:
has_group_discount_per_so_line = fields.Boolean(
"Discount on lines",
compute='_compute_groups_id', inverse='_inverse_groups_id',
group_xml_id='sale.group_discount_per_so_line')
2. A selection field with the compute/inverse method, the selection got from '_get_group_selection'
and an attribute 'category_xml_id'
Example:
group_sales_team_user = fields.Selection(
selection=lambda self: self._get_group_selection('base.module_category_sales_management'),
string="Sales", compute='_compute_groups_id', inverse='_inverse_groups_id',
category_xml_id='base.module_category_sales_management')
The fields will be set according to the groups defined in the 'groups_id' field, and the 'groups_id'
field will be modified according to the modifications made on theses fields when saving the users's
form.
| -rw-r--r-- | odoo/addons/base/models/res_users.py | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py index efcf203edf0..05c154bc466 100644 --- a/odoo/addons/base/models/res_users.py +++ b/odoo/addons/base/models/res_users.py @@ -624,6 +624,112 @@ class Users(models.Model): def get_company_currency_id(self): return self.env.user.company_id.currency_id.id + def _add_missing_default_values(self, vals): + # Remove the default values of 'group_' and 'has_group' fields at the user creation if + # 'groups_id' is provided in vals and if the fields value is not explicitely given. + res = super(Users, self)._add_missing_default_values(vals) + return { + key: value for (key, value) in res.items() + if 'groups_id' not in vals or key in vals or (not is_boolean_group(key) or not is_selection_groups(key)) + } + + def _get_group_selection(self, category_xml_id): + """Returns the ordered selection for the given ir.module.category xmlid""" + category = self.env.ref(category_xml_id, raise_if_not_found=False) + selections = [] + if category: + groups = self.env['res.groups'].search([('category_id', '=', category.id)]) + order = {group: len(group.trans_implied_ids & groups) for group in groups} + groups = groups.sorted(key=order.get) + selections = [(group.id, group.name) for group in groups] + return selections + + @api.depends('groups_id') + def _compute_groups_id(self): + """Set the value for the group field (Selection of Boolean) + according to the user's groups, defined by the field 'groups_id'. + + These methods should be used on fields defined like one the + following cases: + 1. A boolean field with the compute/inverse method and an attribute + group_xml_id. + Example: + has_group_discount_per_so_line = fields.Boolean( + "Discount on lines", + compute='_compute_groups_id', inverse='_inverse_groups_id', + group_xml_id='sale.group_discount_per_so_line') + 2. A selection field with the compute/inverse method, the selection + got from '_get_group_selection' and an attribute + 'category_xml_id' + Example: + group_sales_team_user = fields.Selection( + selection=lambda self: self._get_group_selection('base.module_category_sales_management'), + string="Sales", compute='_compute_groups_id', inverse='_inverse_groups_id', + category_xml_id='base.module_category_sales_management') + The fields will be set according to the groups defined in the 'groups_id' + field, and the 'groups_id' field will be modified according to the + modifications made on theses fields when saving the users's form. + """ + computed_group_fields = [field for field in self._field_computed.keys() if field.compute == '_compute_groups_id'] + all_groups = self.env['res.groups'].search([]) + category_data = {} + # Retrieve groups order for selection fields + for field in computed_group_fields: + if getattr(field, 'category_xml_id', None): + category = self.env.ref(getattr(field, 'category_xml_id')) + category_groups = all_groups.filtered(lambda group: group.category_id == category) + order = {group: len(group.trans_implied_ids & category_groups) for group in category_groups} + category_data[field] = category_groups.sorted(key=order.get, reverse=True) + # Set group fields values according to groups_id + for user in self: + for field in computed_group_fields: + # Checkbox group + if getattr(field, 'group_xml_id', None): + group = self.env.ref(getattr(field, 'group_xml_id')) + user[field.name] = group in user.groups_id + # Selection group + elif getattr(field, 'category_xml_id', None): + # Take the highest level group the user belongs to + user_groups = [group for group in category_data[field] if group in user.groups_id] + user[field.name] = user_groups[0].id if user_groups else False + else: + _logger.warning(_("No 'group_xml_id' or 'category_xml_id' is set on the computed field %s linked to the method _compute_groups_id") % (field.name)) + + def _inverse_groups_id(self): + """Update 'groups_id' according the group fields values in cache.""" + computed_group_fields = [field for field in self._field_computed.keys() if field.compute == '_compute_groups_id'] + all_groups = self.env['res.groups'].search([]) + for user in self: + # we need to read all values in cache before any prefetch + field_values = {field: user[field.name] for field in computed_group_fields if field.name in user._cache} + groups_id_vals = [] + for field, value in field_values.items(): + # Checkbox group + if getattr(field, 'group_xml_id', None): + selected_group = self.env.ref(getattr(field, 'group_xml_id')) + if value: + groups_id_vals.append((4, selected_group.id)) + else: + groups_id_vals.append((3, selected_group.id)) + for group in selected_group.trans_implied_ids: + groups_id_vals.append((4, group.id)) + # Selection group + elif getattr(field, 'category_xml_id', None): + category = self.env.ref(getattr(field, 'category_xml_id')) + category_groups = [group for group in all_groups if group.category_id == category] + selected_group = [group for group in all_groups if group.id == value] + selected_group = selected_group and selected_group[0] or self.env['res.groups'] + for group in category_groups: + if group in (selected_group.trans_implied_ids | selected_group): + groups_id_vals.append((4, group.id)) + else: + groups_id_vals.append((3, group.id)) + else: + _logger.warning(_("No 'group_xml_id' or 'category_xml_id' is set on the computed field %s linked to the method _compute_groups_id") % (field.name)) + if groups_id_vals: + user.write({'groups_id': groups_id_vals}) + + # # Implied groups # |
