diff --git a/addons/sale/models/sale_order.py b/addons/sale/models/sale_order.py index 28f79b0c3a9..ba3362fe7fa 100644 --- a/addons/sale/models/sale_order.py +++ b/addons/sale/models/sale_order.py @@ -409,7 +409,7 @@ class SaleOrder(models.Model): def _compute_team_id(self): cached_teams = {} for order in self: - default_team_id = (order.team_id or order.partner_id.team_id).id + default_team_id = self.env.context.get('default_team_id', False) or order.team_id.id or order.partner_id.team_id.id user_id = order.user_id.id company_id = order.company_id.id key = (default_team_id, user_id, company_id) diff --git a/addons/sales_team/models/crm_team.py b/addons/sales_team/models/crm_team.py index 8dc485d4873..ad28f94ffe2 100644 --- a/addons/sales_team/models/crm_team.py +++ b/addons/sales_team/models/crm_team.py @@ -17,7 +17,7 @@ class CrmTeam(models.Model): _name = "crm.team" _inherit = ['mail.thread'] _description = "Sales Team" - _order = "sequence" + _order = "sequence ASC, create_date DESC, id DESC" _check_company_auto = True def _get_default_team_id(self, user_id=None, domain=None): @@ -25,13 +25,16 @@ class CrmTeam(models.Model): method is not called by default_get as it takes some additional parameters and is meant to be called by other default methods. - Heuristic (when multiple match: take first sequence ordered) + Heuristic (when multiple match: take from default context value or first + sequence ordered) - 1- any of my teams (member OR responsible) matching domain - 2- any of my teams (member OR responsible) + 1- any of my teams (member OR responsible) matching domain, either from + context or based on _order; + 2- any of my teams (member OR responsible), either from context or based + on _order; 3- default from context - 4- any team matching my company and domain - 5- any team matching my company + 4- any team matching my company and domain (based on company rule) + 5- any team matching my company (based on company rule) Note: ResPartner.team_id field is explicitly not taken into account. We think this field causes a lot of noises compared to its added value. @@ -45,6 +48,9 @@ class CrmTeam(models.Model): user = self.env.user else: user = self.env['res.users'].sudo().browse(user_id) + default_team = self.env['crm.team'].browse( + self.env.context['default_team_id'] + ) if self.env.context.get('default_team_id') else self.env['crm.team'] valid_cids = [False] + [c for c in user.company_ids.ids if c in self.env.companies.ids] # 1- find in user memberships - note that if current user in C1 searches @@ -52,23 +58,32 @@ class CrmTeam(models.Model): team = self.env['crm.team'] teams = self.env['crm.team'].search([ ('company_id', 'in', valid_cids), - '|', ('user_id', '=', user.id), ('member_ids', 'in', [user.id]), + '|', ('user_id', '=', user.id), ('member_ids', 'in', [user.id]) ]) if teams and domain: - team = teams.filtered_domain(domain)[:1] + filtered_teams = teams.filtered_domain(domain) + if default_team and default_team in filtered_teams: + team = default_team + else: + team = filtered_teams[:1] + # 2- any of my teams if not team: - team = teams[:1] + if default_team and default_team in teams: + team = default_team + else: + team = teams[:1] # 3- default: context - if not team and 'default_team_id' in self.env.context: - team = self.env['crm.team'].browse(self.env.context.get('default_team_id')) + if not team and default_team: + team = default_team - # 4- default: first one matching domain, then first one if not team: teams = self.env['crm.team'].search([('company_id', 'in', valid_cids)]) + # 4- default: based on company rule, first one matching domain if teams and domain: team = teams.filtered_domain(domain)[:1] + # 5- default: based on company rule, first one if not team: team = teams[:1] diff --git a/addons/sales_team/tests/test_sales_team.py b/addons/sales_team/tests/test_sales_team.py index 3556f5ade6c..06953959e31 100644 --- a/addons/sales_team/tests/test_sales_team.py +++ b/addons/sales_team/tests/test_sales_team.py @@ -13,6 +13,26 @@ class TestDefaultTeam(TestSalesCommon): def setUpClass(cls): """Set up data for default team tests.""" super(TestDefaultTeam, cls).setUpClass() + cls.env['ir.config_parameter'].set_param('sales_team.membership_multi', True) + + # Salesmen organization + # ------------------------------------------------------------ + # Role: M (team member) R (team manager) + # SALESMAN---------------sales_team_1---C2Team1---LowSequ---Team3 + # admin------------------M-------------- --------- --------- + # user_sales_manager-----R-------------- --------- ---------R + # user_sales_leads-------M-------------- ---------M--------- + # user_sales_salesman----/-------------- --------- --------- + + # Sales teams organization + # ------------------------------------------------------------ + # SALESTEAM-----------SEQU-----COMPANY + # LowSequence---------0--------False + # C2Team1-------------1--------C2 + # Team3---------------3--------Main + # sales_team_1--------5--------False + # data----------------9999-----?? + cls.company_2 = cls.env['res.company'].create({ 'name': 'New Test Company', 'email': 'company.2@test.example.com', @@ -22,35 +42,31 @@ class TestDefaultTeam(TestSalesCommon): 'name': 'C2 Team1', 'sequence': 1, 'company_id': cls.company_2.id, + 'user_id': False, }) cls.team_sequence = cls.env['crm.team'].create({ - 'name': 'Team LowSequence', - 'sequence': 0, 'company_id': False, + 'name': 'Team LowSequence', + 'member_ids': [(4, cls.user_sales_leads.id)], + 'sequence': 0, + 'user_id': False, }) cls.team_responsible = cls.env['crm.team'].create({ + 'company_id': cls.company_main.id, 'name': 'Team 3', 'user_id': cls.user_sales_manager.id, 'sequence': 3, - 'company_id': cls.company_main.id }) - def test_default_team_member(self): - with self.with_user('user_sales_leads'): - team = self.env['crm.team']._get_default_team_id() - self.assertEqual(team, self.sales_team_1) - - # responsible with lower sequence better than member with higher sequence - self.team_responsible.user_id = self.user_sales_leads.id - with self.with_user('user_sales_leads'): - team = self.env['crm.team']._get_default_team_id() - self.assertEqual(team, self.team_responsible) - def test_default_team_fallback(self): - """ Test fallback: domain, order """ + """ Test fallbacks when computing default team without any memberships: + domain, order """ self.sales_team_1.member_ids = [(5,)] - self.sales_team_1.flush_model() + self.team_sequence.member_ids = [(5,)] + (self.sales_team_1 + self.team_sequence).flush_model() + self.assertFalse(self.env['crm.team.member'].search([('user_id', '=', self.user_sales_leads.id)])) + # default is better sequence matching company criterion with self.with_user('user_sales_leads'): team = self.env['crm.team']._get_default_team_id() self.assertEqual(team, self.team_sequence) @@ -66,11 +82,70 @@ class TestDefaultTeam(TestSalesCommon): 'company_id': self.company_2.id, }) # multi company: switch company - self.user_sales_leads.write({'company_id': self.company_2.id}) + self.user_sales_leads.write({ + 'company_id': self.company_2.id, + 'company_ids': [(4, self.company_2.id)], + }) with self.with_user('user_sales_leads'): team = self.env['crm.team']._get_default_team_id() self.assertEqual(team, self.team_c2) + def test_default_team_member(self): + """ Test default team choice based on sequence, when having several + possible choices due to membership """ + with self.with_user('user_sales_leads'): + team = self.env['crm.team']._get_default_team_id() + self.assertEqual(team, self.team_sequence) + + self.team_sequence.member_ids = [(5,)] + self.team_sequence.flush_model() + with self.with_user('user_sales_leads'): + team = self.env['crm.team']._get_default_team_id() + self.assertEqual(team, self.sales_team_1) + + # responsible with lower sequence better than member with higher sequence + self.team_responsible.user_id = self.user_sales_leads.id + with self.with_user('user_sales_leads'): + team = self.env['crm.team']._get_default_team_id() + self.assertEqual(team, self.team_responsible) + + # in case of same sequence: take latest team + self.team_responsible.sequence = self.sales_team_1.sequence + with self.with_user('user_sales_leads'): + team = self.env['crm.team']._get_default_team_id() + self.assertEqual(team, self.team_responsible) + + def test_default_team_wcontext(self): + """ Test default team choice when having a value in context """ + with self.with_user('user_sales_leads'): + team = self.env['crm.team']._get_default_team_id() + self.assertEqual(team, self.team_sequence) + + team = self.env['crm.team'].with_context( + default_team_id=self.sales_team_1.id + )._get_default_team_id() + self.assertEqual( + team, self.sales_team_1, + 'SalesTeam: default takes over ordering when member / responsible' + ) + + # remove all memberships + self.sales_team_1.member_ids = [(5,)] + self.team_sequence.member_ids = [(5,)] + (self.sales_team_1 + self.team_sequence).flush_model() + self.assertFalse(self.env['crm.team.member'].search([('user_id', '=', self.user_sales_leads.id)])) + + with self.with_user('user_sales_leads'): + team = self.env['crm.team']._get_default_team_id() + self.assertEqual(team, self.team_sequence) + + team = self.env['crm.team'].with_context( + default_team_id=self.sales_team_1.id + )._get_default_team_id() + self.assertEqual( + team, self.sales_team_1, + 'SalesTeam: default taken into account when no member / responsible' + ) class TestMultiCompany(TestSalesMC): """Tests to check multi company management with sales team and their