[FW][MERGE] sales, sales_team: set lead team when creating quotation
Steps to reproduce:
-Install sales and crm
-Apply multiteam option in crm settings
-Create a user with two teams A and B
-Create with this user a lead with team B
-From this lead create a quotation
Current behavior:
The quotation could have team A (the team of the lead is ignored)
Expected behavior:
The quotation always has team B
Problem when creating the quotation the team id is not propagated
in the context to the final function _get_default_team_id and in
this function the default context team is only check if no teams
have been found for the user, so the function always selects the
first team of the user. To solve the issue we propagate the team
id to the default function and we change it so that if the context
default team is in the user teams it is this one that is going to
be selected and no other.
Small behavior change:
Two cases are added in the _get_default_team_id function that slightly change
the current behavior. For the two first cases instead of just choosing any team in
the list we add a case so that IF there is a default team in the context AND that this
team is in the list then its going to be this one that's gonna be selected. See function
comments:
1- any of my teams (member OR responsible) matching domain
2- any of my teams (member OR responsible)
becomes
1- default from context if in my teams (member OR responsible) matching domain
2- any of my teams (member OR responsible) matching domain
3- default from context if in any of my teams (member OR responsible)
4- any of my teams (member OR responsible)
opw-2830913
Task-2852947
closes odoo/odoo#94045
Forward-port-of: odoo/odoo#93896
Forward-port-of: odoo/odoo#90289
Signed-off-by: Fockedey Martin (mafo) <mafo@odoo.com>
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user