summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlen-odoo <len@odoo.com>2018-04-25 15:38:20 +0200
committerYannick Tivisse <yti@odoo.com>2018-04-26 15:13:38 +0200
commitab179bb2d7b8f890e04ea79e70d7bc0898e7599f (patch)
tree55d47b9a2422e8f430eded44f1ed013faa2b1cc6
parente67b61811bc01fad467545dc8896d754dc39506a (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.py106
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
#