[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.
This commit is contained in:
committed by
Yannick Tivisse
parent
e67b61811b
commit
ab179bb2d7
@@ -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
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user