[REF] crm: cleanup test environment to prepare changes in assignment process

This commit contains two main preparatory changes in tests

  * 1) lead_month_count will be changed to count lost lead as well. So
    archiving leads before running the test doesn't reset the counter.
    Lead needs to be unlinked in order to make tests reproducible;

  * 2) assertMemberAssign checked the validity of the team domain. Normally
    all lead assigned to the member should match the domain of its team.
    This assert is not always verified since we force the team after a
    merge of duplicated leads. Final merged lead may not match team domain
    anymore as final properties depend on all merged leads.

Some tests are also added :

  * add tests for master lead team_id and user_id values when merging leads
    in assign process;
  * add tests using email_normalized check in duplicate finding to ensure that
    normalized emails are used for duplicates and not only exact match;
  * add tests for won / lost inclusion in ``_get_lead_duplicates``, as well
    as different between probability=100 and stage.is_won = True . This is
    going to change in upcoming commits, hence some test to highlight it;
  * add tests counting existing leads for assignment purpose;
  * add tests for assignment_max maximum leads allocation as well as max=0
    meaning salesperson is opt-outed from assign;
  * add tests for default user / team / stage computation for leads;
  * add tests about leads taken into account in assign process (currently
    failing with won unassigned leads);

We also add some flush to ensure some fields notably related to probabilities
are flushed before counting queries.

LINKS

Task ID-2444908 (assign fixes)
Task ID-2489951 (assign process improvements)
COM PR odoo/odoo#70172

X-original-commit: bd3444085974f4e12287c2f5da4fb33308cd6180
Co-authored-by: Thibault François <tfr@odoo.com>
Co-authored-by: Thibault Delavallée <tde@odoo.com>
This commit is contained in:
Thibault Francois
2021-05-12 14:00:58 +00:00
committed by Thibault Delavallée
co-authored by Thibault François Thibault Delavallée
parent 71f19d55fa
commit 2f829b0e28
7 changed files with 299 additions and 70 deletions
+1 -1
View File
@@ -198,7 +198,7 @@ class Team(models.Model):
(member_info["team_member"], {"assigned": member_info["assigned"]})
for member_id, member_info in members_data.items()
)
_logger.info('Assigned %s leads to %s salesmen' % (len(leads_done_ids), len(self)))
_logger.info('Assigned %s leads to %s salesmen' % (len(leads_done_ids), len(members)))
for member, member_info in result_data.items():
_logger.info('-> member %s: assigned %d leads (%s)' % (member.id, len(member_info["assigned"]), member_info["assigned"]))
return result_data
+32 -31
View File
@@ -74,7 +74,7 @@ class TestCrmCommon(TestSalesCommon, MailCase):
'assignment_domain': False,
})
(cls.user_sales_manager | cls.user_sales_leads | cls.user_sales_salesman).write({
(cls.user_sales_manager + cls.user_sales_leads + cls.user_sales_salesman).write({
'groups_id': [(4, cls.env.ref('crm.group_use_lead').id)]
})
@@ -139,7 +139,7 @@ class TestCrmCommon(TestSalesCommon, MailCase):
'team_id': cls.sales_team_1.id,
})
cls.lead_team_1_lost.action_set_lost()
(cls.lead_team_1_won | cls.lead_team_1_lost).flush()
(cls.lead_team_1_won + cls.lead_team_1_lost).flush()
# email / phone data
cls.test_email_data = [
@@ -212,7 +212,7 @@ class TestCrmCommon(TestSalesCommon, MailCase):
def _create_leads_batch(self, lead_type='lead', count=10, email_dup_count=0,
partner_count=0, partner_ids=None, user_ids=None,
country_ids=None):
country_ids=None, probabilities=None):
""" Helper tool method creating a batch of leads, useful when dealing
with batch processes. Please update me.
@@ -280,6 +280,11 @@ class TestCrmCommon(TestSalesCommon, MailCase):
for idx, lead_data in enumerate(leads_data):
lead_data['user_id'] = user_ids[idx % len(user_ids)]
# probabilities
if probabilities:
for idx, lead_data in enumerate(leads_data):
lead_data['probability'] = probabilities[idx % len(probabilities)]
# duplicates (currently only with email)
dups_data = []
if email_dup_count and not partner_ids:
@@ -303,49 +308,44 @@ class TestCrmCommon(TestSalesCommon, MailCase):
* a lead with customer but another email
* a lost opportunity with same email_from
"""
self.customer = self.env['res.partner'].create({
customer = self.env['res.partner'].create({
'name': 'Lead1 Email Customer',
'email': lead.email_from,
})
self.lead_email_from = self.env['crm.lead'].create({
lead_email_from = self.env['crm.lead'].create({
'name': 'Duplicate: same email_from',
'type': 'lead',
'team_id': lead.team_id.id,
'email_from': lead.email_from,
})
# self.lead_email_normalized = self.env['crm.lead'].create({
# 'name': 'Duplicate: email_normalize comparison',
# 'type': 'lead',
# 'team_id': lead.team_id.id,
# 'stage_id': lead.stage_id.id,
# 'email_from': 'CUSTOMER WITH NAME <%s>' % lead.email_normalized.upper(),
# })
self.lead_partner = self.env['crm.lead'].create({
lead_email_normalized = self.env['crm.lead'].create({
'name': 'Duplicate: email_normalize comparison',
'type': 'lead',
'team_id': lead.team_id.id,
'stage_id': lead.stage_id.id,
'email_from': 'CUSTOMER WITH NAME <%s>' % lead.email_normalized.upper(),
})
lead_partner = self.env['crm.lead'].create({
'name': 'Duplicate: customer ID',
'type': 'lead',
'team_id': lead.team_id.id,
'partner_id': self.customer.id,
'partner_id': customer.id,
})
if create_opp:
self.opp_lost = self.env['crm.lead'].create({
opp_lost = self.env['crm.lead'].create({
'name': 'Duplicate: lost opportunity',
'type': 'opportunity',
'team_id': lead.team_id.id,
'stage_id': lead.stage_id.id,
'email_from': lead.email_from,
})
self.opp_lost.action_set_lost()
opp_lost.action_set_lost()
else:
self.opp_lost = self.env['crm.lead']
opp_lost = self.env['crm.lead']
# self.assertEqual(self.lead_email_from.email_normalized, self.lead_email_normalized.email_normalized)
# self.assertTrue(lead.email_from != self.lead_email_normalized.email_from)
# self.assertFalse(self.opp_lost.active)
# new_lead = self.lead_email_from | self.lead_email_normalized | self.lead_partner | self.opp_lost
new_leads = self.lead_email_from | self.lead_partner | self.opp_lost
new_leads = lead_email_from + lead_email_normalized + lead_partner + opp_lost
new_leads.flush() # compute notably probability
return new_leads
return customer, new_leads
@contextmanager
def assertLeadMerged(self, opportunity, leads, **expected):
@@ -532,12 +532,13 @@ class TestLeadConvertCommon(TestCrmCommon):
member_leads.filtered_domain(literal_eval(member.assignment_domain)),
member_leads
)
if member.crm_team_id.assignment_domain:
self.assertEqual(
member_leads.filtered_domain(literal_eval(member.crm_team_id.assignment_domain)),
member_leads,
'Assign domain not matching: %s' % member.crm_team_id.assignment_domain
)
# TODO this condition is not fulfilled in case of merge, need to change merge/assignment process
# if member.crm_team_id.assignment_domain:
# self.assertEqual(
# member_leads.filtered_domain(literal_eval(member.crm_team_id.assignment_domain)),
# member_leads,
# 'Assign domain not matching: %s' % member.crm_team_id.assignment_domain
# )
class TestLeadConvertMassCommon(TestLeadConvertCommon):
@@ -611,4 +612,4 @@ class TestLeadConvertMassCommon(TestLeadConvertCommon):
'stage_id': cls.stage_team1_2.id,
'active': False,
})
(cls.lead_w_partner | cls.lead_w_partner_company | cls.lead_w_contact | cls.lead_w_email | cls.lead_w_email_lost).flush()
(cls.lead_w_partner + cls.lead_w_partner_company + cls.lead_w_contact + cls.lead_w_email + cls.lead_w_email_lost).flush()
+26
View File
@@ -201,6 +201,32 @@ class TestCRMLead(TestCrmCommon):
self.assertEqual(lead.function, empty_partner.function, "Function from partner should be set on the lead")
self.assertEqual(lead.website, lead_data['website'], "Website should keep its initial value")
@users('user_sales_manager')
def test_crm_lead_create_pipe_data(self):
""" Test creation pipe data: user, team, stage, depending on some default
configuration. """
# gateway-like creation: no user, no team, generic stage
lead = self.env['crm.lead'].with_context(default_user_id=False).create({
'name': 'Test',
'contact_name': 'Test Contact',
'email_from': self.test_email,
'phone': self.test_phone,
})
self.assertEqual(lead.user_id, self.env['res.users'])
self.assertEqual(lead.team_id, self.env['crm.team'])
self.assertEqual(lead.stage_id, self.stage_gen_1)
# pipe creation: current user's best team and default stage
lead = self.env['crm.lead'].create({
'name': 'Test',
'contact_name': 'Test Contact',
'email_from': self.test_email,
'phone': self.test_phone,
})
self.assertEqual(lead.user_id, self.user_sales_manager)
self.assertEqual(lead.team_id, self.sales_team_1)
self.assertEqual(lead.stage_id, self.stage_team1_1)
@users('user_sales_manager')
def test_crm_lead_partner_sync(self):
lead, partner = self.lead_1.with_user(self.env.user), self.contact_2
+153 -4
View File
@@ -22,11 +22,12 @@ class TestLeadAssignCommon(TestLeadConvertCommon):
# don't mess with existing teams, deactivate them to make tests repeatable
cls.sales_teams = cls.sales_team_1 + cls.sales_team_convert
cls.members = cls.sales_team_1_m1 | cls.sales_team_1_m2 | cls.sales_team_1_m3 | cls.sales_team_convert_m1 | cls.sales_team_convert_m2
cls.members = cls.sales_team_1_m1 + cls.sales_team_1_m2 + cls.sales_team_1_m3 + cls.sales_team_convert_m1 + cls.sales_team_convert_m2
cls.env['crm.team'].search([('id', 'not in', cls.sales_teams.ids)]).write({'active': False})
# don't mess with existing leads, deactivate those assigned to users used here to make tests repeatable
cls.env['crm.lead'].search(['|', ('team_id', '=', False), ('user_id', 'in', cls.sales_teams.member_ids.ids)]).write({'active': False})
# don't mess with existing leads, unlink those assigned to users used here to make tests
# repeatable (archive is not sufficient because of lost leads)
cls.env['crm.lead'].with_context(active_test=False).search(['|', ('team_id', '=', False), ('user_id', 'in', cls.sales_teams.member_ids.ids)]).unlink()
cls.bundle_size = 5
cls.env['ir.config_parameter'].set_param('crm.assignment.bundle', '%s' % cls.bundle_size)
cls.env['ir.config_parameter'].set_param('crm.assignment.delay', '0')
@@ -103,6 +104,66 @@ class TestLeadAssign(TestLeadAssignCommon):
self.assertFalse(self.assign_cron.active)
self.assertEqual(self.assign_cron.nextcall, datetime(2020, 11, 1, 10, 0, 0))
def test_assign_count(self):
""" Test number of assigned leads when dealing with some existing data (leads
or opportunities) as well as with opt-out management. """
leads = self._create_leads_batch(
lead_type='lead',
user_ids=[False],
partner_ids=[False, False, False, self.contact_1.id],
probabilities=[30],
count=8
)
# commit probability and related fields
leads.flush()
self.assertInitialData()
# archived members should not be taken into account
self.sales_team_1_m1.action_archive()
# assignment_max = 0 means opt_out
self.sales_team_1_m2.assignment_max = 0
# assign probability to leads (bypass auto probability as purpose is not to test pls)
leads = self.env['crm.lead'].search([('id', 'in', leads.ids)]) # ensure order
for idx, lead in enumerate(leads):
lead.probability = idx * 10
# commit probability and related fields
leads.flush()
self.assertEqual(leads[0].probability, 0)
# create exiting leads for user_sales_salesman (sales_team_1_m3, sales_team_convert_m1)
existing_leads = self._create_leads_batch(
lead_type='lead', user_ids=[self.user_sales_salesman.id],
probabilities=[10],
count=14)
self.assertEqual(existing_leads.team_id, self.sales_team_1, "Team should have lower sequence")
existing_leads[0].active = False # lost
existing_leads[1].probability = 100 # not won
existing_leads[2].probability = 0 # not lost
existing_leads.flush()
self.members.invalidate_cache(fnames=['lead_month_count'])
self.assertEqual(self.sales_team_1_m3.lead_month_count, 12)
self.assertEqual(self.sales_team_convert_m1.lead_month_count, 0)
with self.with_user('user_sales_manager'):
self.env['crm.team'].browse(self.sales_team_1.ids)._action_assign_leads(work_days=4)
# salespersons assign
self.members.invalidate_cache(fnames=['lead_month_count'])
self.assertEqual(self.sales_team_1_m1.lead_month_count, 0) # archived do not get leads
self.assertEqual(self.sales_team_1_m2.lead_month_count, 0) # opt-out through assignment_max = 0
self.assertEqual(self.sales_team_1_m3.lead_month_count, 14) # 15 max on 4 days (2) + existing 12
with self.with_user('user_sales_manager'):
self.env['crm.team'].browse(self.sales_team_1.ids)._action_assign_leads(work_days=4)
# salespersons assign
self.members.invalidate_cache(fnames=['lead_month_count'])
self.assertEqual(self.sales_team_1_m1.lead_month_count, 0) # archived do not get leads
self.assertEqual(self.sales_team_1_m2.lead_month_count, 0) # opt-out through assignment_max = 0
self.assertEqual(self.sales_team_1_m3.lead_month_count, 15) # 15 max on 4 days (2) + existing 14 but capped at 15
@mute_logger('odoo.models.unlink')
def test_assign_duplicates(self):
""" Test assign process with duplicates on partner. Allow to ensure notably
@@ -113,6 +174,8 @@ class TestLeadAssign(TestLeadAssignCommon):
partner_ids=[self.contact_1.id, self.contact_2.id, False, False, False],
count=50
)
# commit probability and related fields
leads.flush()
self.assertInitialData()
# assign probability to leads (bypass auto probability as purpose is not to test pls)
@@ -121,6 +184,8 @@ class TestLeadAssign(TestLeadAssignCommon):
sliced_leads = leads[idx:len(leads):5]
for lead in sliced_leads:
lead.probability = (idx + 1) * 10 * ((int(lead.priority) + 1) / 2)
# commit probability and related fields
leads.flush()
with self.with_user('user_sales_manager'):
self.env['crm.team'].browse(self.sales_teams.ids)._action_assign_leads(work_days=2)
@@ -146,7 +211,7 @@ class TestLeadAssign(TestLeadAssignCommon):
# teams assign: everything should be done due to duplicates
leads = self.env['crm.lead'].search([('id', 'in', leads.ids)]) # ensure order
self.assertTrue(len(leads.filtered_domain([('team_id', '=', False)])) == 0)
self.assertEqual(len(leads.filtered_domain([('team_id', '=', False)])), 0)
# deduplicate should have removed all duplicated linked to contact_1 and contact_2
new_assigned_leads_wpartner = self.env['crm.lead'].search([
@@ -163,6 +228,8 @@ class TestLeadAssign(TestLeadAssignCommon):
partner_ids=[False],
count=50
)
# commit probability and related fields
leads.flush()
self.assertInitialData()
# assign probability to leads (bypass auto probability as purpose is not to test pls)
@@ -171,6 +238,8 @@ class TestLeadAssign(TestLeadAssignCommon):
sliced_leads = leads[idx:len(leads):5]
for lead in sliced_leads:
lead.probability = (idx + 1) * 10 * ((int(lead.priority) + 1) / 2)
# commit probability and related fields
leads.flush()
with self.with_user('user_sales_manager'):
self.env['crm.team'].browse(self.sales_teams.ids)._action_assign_leads(work_days=2)
@@ -203,7 +272,10 @@ class TestLeadAssign(TestLeadAssignCommon):
country_ids=[self.env.ref('base.be').id, self.env.ref('base.fr').id, False],
count=_lead_count,
email_dup_count=_email_dup_count)
# commit probability and related fields
leads.flush()
self.assertInitialData()
# assign for one month, aka a lot
self.env.ref('crm.ir_cron_crm_lead_assign').write({'interval_type': 'days', 'interval_number': 30})
self.env['ir.config_parameter'].set_param('crm.assignment.bundle', '20')
@@ -246,6 +318,8 @@ class TestLeadAssign(TestLeadAssignCommon):
sliced_leads = leads[idx:len(leads):5]
for lead in sliced_leads:
lead.probability = (idx + 1) * 10 * ((int(lead.priority) + 1) / 2)
# commit probability and related fields
leads.flush()
with self.with_user('user_sales_manager'):
self.env['crm.team'].browse(sales_teams.ids)._action_assign_leads(work_days=30)
@@ -259,3 +333,78 @@ class TestLeadAssign(TestLeadAssignCommon):
self.assertMemberAssign(sales_team_3_m1, 60) # 60 max on one month
self.assertMemberAssign(sales_team_3_m2, 60) # 60 max on one month
self.assertMemberAssign(sales_team_3_m3, 15) # 15 max on one month
def test_assign_specific_won_lost(self):
""" Test leads taken into account in assign process: won, lost, stage
configuration. """
leads = self._create_leads_batch(
lead_type='lead',
user_ids=[False],
partner_ids=[False, False, False, self.contact_1.id],
probabilities=[30],
count=6
)
leads[0].stage_id = self.stage_gen_won.id # is won -> should not be taken into account
leads[1].stage_id = False
leads[2].update({'stage_id': False, 'probability': 0})
leads[3].update({'stage_id': False, 'probability': False})
leads[4].active = False # is lost -> should not be taken into account
leads[5].update({'team_id': self.sales_team_convert.id, 'user_id': self.user_sales_manager.id}) # assigned lead should not be re-assigned
# commit probability and related fields
leads.flush()
with self.with_user('user_sales_manager'):
self.env['crm.team'].browse(self.sales_team_1.ids)._action_assign_leads(work_days=4)
# self.assertEqual(leads[0].team_id, self.env['crm.team'], 'Won lead should not be assigned')
# self.assertEqual(leads[0].user_id, self.env['res.users'], 'Won lead should not be assigned')
for lead in leads[1:4]:
self.assertIn(lead.user_id, self.sales_team_1.member_ids)
self.assertEqual(lead.team_id, self.sales_team_1)
self.assertEqual(leads[4].team_id, self.env['crm.team'], 'Lost lead should not be assigned')
self.assertEqual(leads[4].user_id, self.env['res.users'], 'Lost lead should not be assigned')
self.assertEqual(leads[5].team_id, self.sales_team_convert, 'Assigned lead should not be reassigned')
self.assertEqual(leads[5].user_id, self.user_sales_manager, 'Assigned lead should not be reassigned')
@mute_logger('odoo.models.unlink')
def test_merge_assign_keep_master_team(self):
""" Check existing opportunity keep its team and salesman when merged with a new lead """
sales_team_dupe = self.env['crm.team'].create({
'name': 'Sales Team Dupe',
'sequence': 15,
'alias_name': False,
'use_leads': True,
'use_opportunities': True,
'company_id': False,
'user_id': False,
'assignment_domain': "[]",
})
self.env['crm.team.member'].create({
'user_id': self.user_sales_salesman.id,
'crm_team_id': sales_team_dupe.id,
'assignment_max': 10,
'assignment_domain': "[]",
})
master_opp = self.env['crm.lead'].create({
'name': 'Master',
'type': 'opportunity',
'probability': 50,
'partner_id': self.contact_1.id,
'team_id': self.sales_team_1.id,
'user_id': self.user_sales_manager.id,
})
dupe_lead = self.env['crm.lead'].create({
'name': 'Dupe',
'type': 'lead',
'email_from': 'Duplicate Email <%s>' % master_opp.email_normalized,
'probability': 10,
'team_id': False,
'user_id': False,
})
sales_team_dupe._action_assign_leads(work_days=2)
self.assertFalse(dupe_lead.exists())
self.assertEqual(master_opp.team_id, sales_team_dupe, 'Opportunity: current team wins lead even if was on duplicated lead')
self.assertEqual(master_opp.user_id, self.user_sales_manager, 'Opportunity: should keep its salesman')
+68 -19
View File
@@ -69,6 +69,56 @@ class TestLeadConvert(crm_common.TestLeadConvertCommon):
date = Datetime.from_string('2020-01-20 16:00:00')
cls.crm_lead_dt_mock.now.return_value = date
@users('user_sales_manager')
def test_duplicates_computation(self):
""" Test Lead._get_lead_duplicates() and check won / probability usage """
test_lead = self.env['crm.lead'].browse(self.lead_1.ids)
customer, dup_leads = self._create_duplicates(test_lead)
dup_leads += self.env['crm.lead'].create([
{'name': 'Duplicate lead: same email_from, lost',
'type': 'lead',
'email_from': test_lead.email_from,
'probability': 0, 'active': False,
},
{'name': 'Duplicate lead: same email_from, proba 0 but not lost',
'type': 'lead',
'email_from': test_lead.email_from,
'probability': 0, 'active': True,
},
{'name': 'Duplicate opp: same email_from, won',
'type': 'opportunity',
'email_from': test_lead.email_from,
'probability': 100, 'stage_id': self.stage_team1_won.id,
},
{'name': 'Duplicate opp: same email_from, proba 100 but not won',
'type': 'opportunity',
'email_from': test_lead.email_from,
'probability': 100, 'stage_id': self.stage_team1_2.id,
}
])
lead_lost = dup_leads.filtered(lambda lead: lead.name == 'Duplicate lead: same email_from, lost')
opp_proba100 = dup_leads.filtered(lambda lead: lead.name == 'Duplicate opp: same email_from, proba 100 but not won')
opp_won = dup_leads.filtered(lambda lead: lead.name == 'Duplicate opp: same email_from, won')
opp_lost = dup_leads.filtered(lambda lead: lead.name == 'Duplicate: lost opportunity')
test_lead.write({'partner_id': customer.id})
# not include_lost = remove archived leads as well as 'won' opportunities
result = test_lead._get_lead_duplicates(
partner=test_lead.partner_id,
email=test_lead.email_from,
include_lost=False
)
self.assertEqual(result, test_lead + dup_leads - (lead_lost + opp_proba100 + opp_won + opp_lost))
# include_lost = remove archived opp only
result = test_lead._get_lead_duplicates(
partner=test_lead.partner_id,
email=test_lead.email_from,
include_lost=True
)
self.assertEqual(result, test_lead + dup_leads - (lead_lost))
def test_initial_data(self):
""" Ensure initial data to avoid spaghetti test update afterwards """
self.assertFalse(self.lead_1.date_conversion)
@@ -341,35 +391,35 @@ class TestLeadConvert(crm_common.TestLeadConvertCommon):
@users('user_sales_manager')
def test_lead_merge_duplicates(self):
""" Test Lead._get_lead_duplicates() """
""" Test Lead._get_lead_duplicates() and check: partner / email fallbacks """
customer, dup_leads = self._create_duplicates(self.lead_1)
lead_partner = dup_leads.filtered(lambda lead: lead.name == 'Duplicate: customer ID')
self.assertTrue(bool(lead_partner))
# Check: partner / email fallbacks
self._create_duplicates(self.lead_1)
self.lead_1.write({
'partner_id': self.customer.id,
'partner_id': customer.id,
})
convert = self.env['crm.lead2opportunity.partner'].with_context({
'active_model': 'crm.lead',
'active_id': self.lead_1.id,
'active_ids': self.lead_1.ids,
}).create({})
self.assertEqual(convert.partner_id, self.customer)
# self.assertEqual(convert.duplicated_lead_ids, self.lead_1 | self.lead_email_from | self.lead_email_normalized | self.lead_partner | self.opp_lost)
self.assertEqual(convert.duplicated_lead_ids, self.lead_1 | self.lead_email_from | self.lead_partner | self.opp_lost)
self.assertEqual(convert.partner_id, customer)
self.assertEqual(convert.duplicated_lead_ids, self.lead_1 | dup_leads)
# Check: partner fallbacks
self.lead_1.write({
'email_from': False,
'partner_id': self.customer.id,
'partner_id': customer.id,
})
self.customer.write({'email': False})
customer.write({'email': False})
convert = self.env['crm.lead2opportunity.partner'].with_context({
'active_model': 'crm.lead',
'active_id': self.lead_1.id,
'active_ids': self.lead_1.ids,
}).create({})
self.assertEqual(convert.partner_id, self.customer)
self.assertEqual(convert.duplicated_lead_ids, self.lead_1 | self.lead_partner)
self.assertEqual(convert.partner_id, customer)
self.assertEqual(convert.duplicated_lead_ids, self.lead_1 | lead_partner)
@users('user_sales_manager')
def test_lead_merge_duplicates_flow(self):
@@ -379,23 +429,22 @@ class TestLeadConvert(crm_common.TestLeadConvertCommon):
self.lead_1.write({
'email_from': 'Amy Wong <amy.wong@test.example.com>'
})
self._create_duplicates(self.lead_1)
customer, dup_leads = self._create_duplicates(self.lead_1)
opp_lost = dup_leads.filtered(lambda lead: lead.name == 'Duplicate: lost opportunity')
self.assertTrue(bool(opp_lost))
convert = self.env['crm.lead2opportunity.partner'].with_context({
'active_model': 'crm.lead',
'active_id': self.lead_1.id,
'active_ids': self.lead_1.ids,
}).create({})
self.assertEqual(convert.partner_id, self.customer)
# TDE FIXME: should check for email_normalized -> lead_email_normalized not correctly found
# self.assertEqual(convert.duplicated_lead_ids, self.lead_1 | lead_email_from | lead_email_normalized | lead_partner | opp_lost)
self.assertEqual(convert.duplicated_lead_ids, self.lead_1 | self.lead_email_from | self.lead_partner | self.opp_lost)
self.assertEqual(convert.partner_id, customer)
self.assertEqual(convert.duplicated_lead_ids, self.lead_1 | dup_leads)
convert.action_apply()
self.assertEqual(
# (self.lead_1 | self.lead_email_from | self.lead_email_normalized | self.lead_partner | self.opp_lost).exists(),
(self.lead_1 | self.lead_email_from | self.lead_partner | self.opp_lost).exists(),
self.opp_lost)
(self.lead_1 | dup_leads).exists(),
opp_lost)
@tagged('lead_manage')
@@ -109,10 +109,10 @@ class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon):
""" Test duplicated_lead_ids fields having another behavior in mass convert
because why not. Its use is: among leads under convert, store those with
duplicates if deduplicate is set to True. """
lead_1_dups = self._create_duplicates(self.lead_1, create_opp=False)
_customer, lead_1_dups = self._create_duplicates(self.lead_1, create_opp=False)
lead_1_final = self.lead_1 # after merge: same but with lower ID
lead_w_partner_dups = self._create_duplicates(self.lead_w_partner, create_opp=False)
_customer2, lead_w_partner_dups = self._create_duplicates(self.lead_w_partner, create_opp=False)
lead_w_partner_final = lead_w_partner_dups[0] # lead_w_partner has no stage -> lower in sort by confidence
lead_w_partner_dups_partner = lead_w_partner_dups[1] # copy with a partner_id (with the same email)
@@ -166,7 +166,7 @@ class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon):
test_leads = self._create_leads_batch(count=50, user_ids=[False])
user_ids = self.assign_users.ids
with self.assertQueryCount(user_sales_manager=1367): # still some randomness (1366 spotted) - crm only: 1357
with self.assertQueryCount(user_sales_manager=1368): # still some randomness (1366 spotted) - crm only: ??
mass_convert = self.env['crm.lead2opportunity.partner.mass'].with_context({
'active_model': 'crm.lead',
'active_ids': test_leads.ids,
+16 -12
View File
@@ -36,6 +36,8 @@ class TestLeadAssignPerf(TestLeadAssignCommon):
partner_ids=[self.contact_1.id, self.contact_2.id, False, False, False],
count=50
)
# commit probability and related fields
leads.flush()
self.assertInitialData()
# assign probability to leads (bypass auto probability as purpose is not to test pls)
@@ -44,9 +46,11 @@ class TestLeadAssignPerf(TestLeadAssignCommon):
sliced_leads = leads[idx:len(leads):5]
for lead in sliced_leads:
lead.probability = (idx + 1) * 10 * ((int(lead.priority) + 1) / 2)
# commit probability and related fields
leads.flush()
with self.with_user('user_sales_manager'):
with self.assertQueryCount(user_sales_manager=477): # crm only: 466
with self.assertQueryCount(user_sales_manager=483): # crm only: ??
self.env['crm.team'].browse(self.sales_teams.ids)._action_assign_leads(work_days=2)
# teams assign
@@ -66,19 +70,12 @@ class TestLeadAssignPerf(TestLeadAssignCommon):
# run a second round to finish leads
with self.with_user('user_sales_manager'):
with self.assertQueryCount(user_sales_manager=137): # crm only: 128
with self.assertQueryCount(user_sales_manager=137): # crm only: ??
self.env['crm.team'].browse(self.sales_teams.ids)._action_assign_leads(work_days=2)
# teams assign: everything should be done due to duplicates
leads = self.env['crm.lead'].search([('id', 'in', leads.ids)]) # ensure order
self.assertTrue(len(leads.filtered_domain([('team_id', '=', False)])) == 0)
# deduplicate should have removed all duplicated linked to contact_1 and contact_2
new_assigned_leads_wpartner = self.env['crm.lead'].search([
('partner_id', 'in', (self.contact_1 | self.contact_2).ids),
('id', 'in', leads.ids)
])
self.assertEqual(len(new_assigned_leads_wpartner), 2)
self.assertEqual(len(leads.filtered_domain([('team_id', '=', False)])), 0)
@mute_logger('odoo.models.unlink', 'odoo.addons.crm.models.crm_team', 'odoo.addons.crm.models.crm_team_member')
def test_assign_perf_no_duplicates(self):
@@ -88,6 +85,8 @@ class TestLeadAssignPerf(TestLeadAssignCommon):
partner_ids=[False],
count=50
)
# commit probability and related fields
leads.flush()
self.assertInitialData()
# assign probability to leads (bypass auto probability as purpose is not to test pls)
@@ -98,7 +97,7 @@ class TestLeadAssignPerf(TestLeadAssignCommon):
lead.probability = (idx + 1) * 10 * ((int(lead.priority) + 1) / 2)
with self.with_user('user_sales_manager'):
with self.assertQueryCount(user_sales_manager=211): # crm only: 206
with self.assertQueryCount(user_sales_manager=209): # crm only: 209 (seems reproducible)
self.env['crm.team'].browse(self.sales_teams.ids)._action_assign_leads(work_days=2)
# teams assign
@@ -129,7 +128,10 @@ class TestLeadAssignPerf(TestLeadAssignCommon):
country_ids=[self.env.ref('base.be').id, self.env.ref('base.fr').id, False],
count=_lead_count,
email_dup_count=_email_dup_count)
# commit probability and related fields
leads.flush()
self.assertInitialData()
# assign for one month, aka a lot
self.env.ref('crm.ir_cron_crm_lead_assign').write({'interval_type': 'days', 'interval_number': 30})
self.env['ir.config_parameter'].set_param('crm.assignment.bundle', '20')
@@ -172,9 +174,11 @@ class TestLeadAssignPerf(TestLeadAssignCommon):
sliced_leads = leads[idx:len(leads):5]
for lead in sliced_leads:
lead.probability = (idx + 1) * 10 * ((int(lead.priority) + 1) / 2)
# commit probability and related fields
leads.flush()
with self.with_user('user_sales_manager'):
with self.assertQueryCount(user_sales_manager=6290): # crm only: 6287
with self.assertQueryCount(user_sales_manager=6293): # crm only: ??
self.env['crm.team'].browse(sales_teams.ids)._action_assign_leads(work_days=30)
self.members.invalidate_cache(fnames=['lead_month_count'])