diff --git a/sales_team_security/models/ir_rule.py b/sales_team_security/models/ir_rule.py index 17bd7e6f115..0f12fdc8755 100644 --- a/sales_team_security/models/ir_rule.py +++ b/sales_team_security/models/ir_rule.py @@ -28,17 +28,35 @@ def _compute_domain(self, model_name, mode="read"): user = self.env.user group_my_records = "sales_team.group_sale_salesman" group_all_records = "sales_team.group_sale_salesman_all_leads" + group1 = "sales_team.group_sale_salesman" + group2 = "sales_team_security.group_sale_team_manager" + group3 = "sales_team.group_sale_salesman_all_leads" if model_name == "res.partner" and not self.env.su: - if user.has_group(group_my_records) and not user.has_group( - group_all_records - ): - domain_followers = [ + # if user.has_group(group_my_records) and not user.has_group( + # group_all_records + # ): + # domain_followers = [ + if user.has_group(group1) and not user.has_group(group3): + extra_domain = [ "|", ("message_partner_ids", "in", user.partner_id.ids), + "|", ("id", "=", user.partner_id.id), ] - domain_user = [("user_id", "in", [user.id, False])] - extra_domain = expression.OR([domain_followers, domain_user]) + # domain_user = [("user_id", "in", [user.id, False])] + # extra_domain = expression.OR([domain_followers, domain_user]) + if user.has_group(group2): + # Ver todos los contactos de su equipo + team_user_ids = user.sale_team_id.member_ids.ids + extra_domain += [ + ("user_id", "in", team_user_ids + [False]), + ] + else: + # Ver solo propios y sin asignar + extra_domain += [ + ("user_id", "in", [user.id, False]), + ] + extra_domain = expression.normalize_domain(extra_domain) res = expression.AND([extra_domain] + [res]) return res diff --git a/sales_team_security/models/res_partner.py b/sales_team_security/models/res_partner.py index d2ac484ad4b..d8b54fc4fb8 100644 --- a/sales_team_security/models/res_partner.py +++ b/sales_team_security/models/res_partner.py @@ -3,6 +3,8 @@ # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from lxml import etree + from odoo import api, fields, models @@ -11,6 +13,62 @@ class ResPartner(models.Model): # add indexes for better performance on record rules user_id = fields.Many2one(index=True) + # team_id = fields.Many2one( + # "crm.team", + # string="Sales Team", + # compute="_compute_team_id", + # precompute=True, # avoid queries post-create + # ondelete="set null", + # readonly=False, + # store=True, + # index=True, + # ) + + @api.model + def get_view(self, view_id=None, view_type="form", **options): + """ + Patch view to inject the default value for the team_id and user_id. + """ + # FIXME: Use base_view_inheritance_extension when available + res = super().get_view(view_id, view_type, **options) + if view_type == "form": + eview = etree.fromstring(res["arch"]) + xml_fields = eview.xpath("//field[@name='child_ids']") + if xml_fields: + context_str = ( + xml_fields[0] + .get("context", "{}") + .replace( + "{", + "{'default_user_id': user_id,", + 1, + ) + ) + xml_fields[0].set("context", context_str) + res["arch"] = etree.tostring(eview) + return res + + @api.onchange("parent_id") + def _onchange_parent_id_sales_team_security(self): + """If assigning a parent partner and the contact doesn't have + team or salesman, we put the parent's one (if any). + """ + if self.parent_id and self.parent_id.user_id and not self.user_id: + self.user_id = self.parent_id.user_id.id + + # @api.onchange("user_id") + # def _onchange_user_id_sales_team_security(self): + # if self.user_id.sale_team_id: + # self.team_id = self.user_id.sale_team_id + + # @api.depends("parent_id") + # def _compute_team_id(self): + # for partner in self.filtered( + # lambda partner: not partner.team_id + # and partner.company_type == "person" + # and partner.parent_id.team_id + # ): + # partner.team_id = partner.parent_id.team_id def _remove_key_followers(self, partner): for record in self.mapped("commercial_partner_id"): @@ -23,7 +81,7 @@ def _remove_key_followers(self, partner): def _add_followers_from_salesmen(self): """Sync followers in commercial partner + delivery/invoice contacts.""" for record in self.commercial_partner_id: - followers = (record.child_ids + record).user_id.partner_id + followers = (record.child_ids + record).mapped("user_id.partner_id") # Look for delivery and invoice addresses childrens = record.child_ids.filtered( lambda x: x.type in {"invoice", "delivery"} @@ -35,6 +93,7 @@ def create(self, vals_list): """Sync followers on contact creation.""" records = super().create(vals_list) records._add_followers_from_salesmen() + # records._sync_team_id_to_children() return records def write(self, vals): @@ -50,4 +109,14 @@ def write(self, vals): result = super().write(vals) if "user_id" in vals or vals.get("type") in {"invoice", "delivery"}: self._add_followers_from_salesmen() + # if "user_id" in vals or "team_id" in vals: + # self._sync_team_id_to_children() return result + + # def _sync_team_id_to_children(self): + # for parent in self: + # if parent.child_ids: + # for child in parent.child_ids: + # child.team_id = parent.team_id + # if parent.user_id: + # child.user_id = parent.user_id diff --git a/sales_team_security/tests/common.py b/sales_team_security/tests/common.py index b3786c04b4f..4c30a9207df 100644 --- a/sales_team_security/tests/common.py +++ b/sales_team_security/tests/common.py @@ -25,7 +25,9 @@ def setUpClass(cls): "crm_team_id": cls.team.id, } ) - cls.partner = cls.env["res.partner"].create({"name": "Test partner"}) + cls.partner = cls.env["res.partner"].create( + {"name": "Test partner", "team_id": cls.team.id} + ) cls.partner_child_1 = cls.env["res.partner"].create( {"name": "Child 1", "parent_id": cls.partner.id} ) @@ -51,13 +53,12 @@ def setUpClass(cls): cls.check_permission_subscribe = False def _check_permission(self, salesman, team, expected): - vals = {"user_id": salesman.id if salesman else salesman} - # Check if the record has a team_id field - # This is needed for the test to work with different models - # such as sales_team_security_crm and sales_team_security_sale modules. - if "team_id" in self.record._fields: - vals["team_id"] = team.id if team else team - self.record.write(vals) + self.record.write( + { + "user_id": salesman.id if salesman else salesman, + "team_id": team.id if team else team, + } + ) domain = [("id", "=", self.record.id)] if ( self.check_permission_subscribe @@ -70,11 +71,12 @@ def _check_permission(self, salesman, team, expected): @mute_logger("odoo.models.unlink") def _check_whole_permission_set(self, extra_checks=True): - is_res_partner = self.record._name == "res.partner" self._check_permission(False, False, True) self._check_permission(self.user, False, True) self._check_permission(self.user2, False, False) self._check_permission(False, self.team, True) + if extra_checks: + self._check_permission(False, self.team2, False) self._check_permission(self.user, self.team, True) self._check_permission(self.user, self.team2, True) self._check_permission(self.user2, self.team2, False) @@ -85,19 +87,19 @@ def _check_whole_permission_set(self, extra_checks=True): ] self._check_permission(False, False, True) self._check_permission(self.user, False, True) - if not is_res_partner: - self._check_permission(self.user2, False, True) + self._check_permission(self.user2, False, True) self._check_permission(False, self.team, True) + if extra_checks: + self._check_permission(False, self.team2, False) self._check_permission(self.user, self.team, True) - if is_res_partner: + if self.record._name == "res.partner": self.check_permission_subscribe = True self._check_permission(self.user, self.team2, True) self.check_permission_subscribe = False else: self._check_permission(self.user, self.team2, True) self._check_permission(self.user2, self.team2, False) - if not is_res_partner: - self._check_permission(self.user2, self.team, True) + self._check_permission(self.user2, self.team, True) # Add to group "See all leads" self.user.groups_id = [ (4, self.env.ref("sales_team.group_sale_salesman_all_leads").id) @@ -112,7 +114,7 @@ def _check_whole_permission_set(self, extra_checks=True): self._check_permission(self.user2, self.team2, True) self._check_permission(self.user2, self.team, True) # Regular internal user - if extra_checks and is_res_partner: + if extra_checks: self.user.groups_id = [(6, 0, [self.env.ref("base.group_user").id])] self._check_permission(False, False, True) self._check_permission(self.user, False, True) diff --git a/sales_team_security/tests/test_sales_team_security.py b/sales_team_security/tests/test_sales_team_security.py index 4594724b293..32e378d39d1 100644 --- a/sales_team_security/tests/test_sales_team_security.py +++ b/sales_team_security/tests/test_sales_team_security.py @@ -2,7 +2,9 @@ # Copyright 2021 Tecnativa - Víctor Martínez # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from lxml import etree +from ..hooks import post_init_hook from .common import TestCommon @@ -15,11 +17,35 @@ def setUpClass(cls): cls.record = cls.partner def test_onchange_parent_id(self): + contact = self.env["res.partner"].create( + {"name": "Test contact", "parent_id": self.partner.id} + ) + contact._onchange_parent_id_sales_team_security() + self.assertEqual(contact.team_id, self.team) contact2 = self.env["res.partner"].create( {"name": "Test contact", "parent_id": self.partner2.id} ) + contact2._onchange_parent_id_sales_team_security() self.assertEqual(contact2.user_id, self.user) + def test_onchange_user_id(self): + contact = self.env["res.partner"].create( + { + "name": "Test contact", + "user_id": self.user.id, + } + ) + contact._onchange_user_id_sales_team_security() + self.assertEqual(contact.team_id, self.team) + + def test_assign_contacts_team(self): + contact = self.env["res.partner"].create( + {"name": "Test contact", "parent_id": self.partner.id, "team_id": False} + ) + post_init_hook(self.env) + contact.env.invalidate_all() + self.assertEqual(contact.team_id, self.partner.team_id) + def test_change_user_id_partner(self): self.partner.write({"user_id": self.user.id}) self.assertIn(self.user_partner, self.partner.message_partner_ids) @@ -43,6 +69,15 @@ def test_change_user_id_partner_child_1(self): self.assertNotIn(self.user_partner, self.partner_child_2.message_partner_ids) self.assertIn(self.user2_partner, self.partner_child_2.message_partner_ids) + def test_partner_fields_view_get(self): + res = self.env["res.partner"].get_view( + view_id=self.ref("base.view_partner_form") + ) + eview = etree.fromstring(res["arch"]) + xml_fields = eview.xpath("//field[@name='child_ids']") + self.assertTrue(xml_fields) + self.assertTrue("default_team_id" in xml_fields[0].get("context", "")) + def test_partner_permissions(self): self._check_whole_permission_set() diff --git a/sales_team_security/views/res_partner_view.xml b/sales_team_security/views/res_partner_view.xml new file mode 100644 index 00000000000..29225636131 --- /dev/null +++ b/sales_team_security/views/res_partner_view.xml @@ -0,0 +1,13 @@ + + + + Partner form (with sales info in contacts) + res.partner + + + + + + + +