[IMP] crm: add more tests about lead / opportunity convert and merge wizards
PURPOSE
As crm will soon evolve (onchange -> compute, code improvements, better
management of sales teams) cleaning and improving tests is necessary to avoid
regressions.
SPECIFICATIONS
After ff6b35f759 that added some first tests, this commit will add more tests
notably about convert wizards.
Notably
* add tests for crm.lead2opportunity.partner wizard, notably options about
action (do nothing, exist or create partner), as well as some corner cases
like stage update, lost leads, ...
* rewrite and improve tests about crm.lead2opportunity.partner.mass, aka the
mass converted wizard that implements some random behavior on top of the
crm.lead2opportunity.partner wizard;
Some strange behaviors spotted
* partner action works on lost leads, but not the convert;
* user_id / team_id / stage_id coherency is not enforced during convert
as it relies mainly on onchanges that are not called;
LINKS
Task ID 2180521 (add tests for crm wizards)
Task ID 2056759 (remove crm.partner.binding mixin)
Task ID 2088565 (crm onchange -> compute)
Community PR odoo/odoo#43473
This commit is contained in:
+147
-2
@@ -1,7 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from odoo.addons.mail.tests.common import MailCase, mail_new_test_user
|
||||
from odoo.fields import Datetime
|
||||
from odoo.tests.common import SavepointCase
|
||||
|
||||
INCOMING_EMAIL = """Return-Path: {return_path}
|
||||
@@ -88,18 +91,24 @@ class TestCrmCommon(MailCase, SavepointCase):
|
||||
})
|
||||
cls.stage_team1_won = cls.env['crm.stage'].create({
|
||||
'name': 'Won',
|
||||
'sequence': 70,
|
||||
'team_id': cls.sales_team_1.id,
|
||||
'is_won': True,
|
||||
'sequence': 70,
|
||||
})
|
||||
cls.stage_gen_1 = cls.env['crm.stage'].create({
|
||||
'name': 'Generic stage',
|
||||
'sequence': 3,
|
||||
'team_id': False,
|
||||
})
|
||||
cls.stage_gen_won = cls.env['crm.stage'].create({
|
||||
'name': 'Generic Won',
|
||||
'sequence': 30,
|
||||
'team_id': False,
|
||||
'is_won': True,
|
||||
})
|
||||
|
||||
cls.lead_1 = cls.env['crm.lead'].create({
|
||||
'name': 'Club Office Furnitures',
|
||||
'name': 'Nibbler Spacecraft Request',
|
||||
'type': 'lead',
|
||||
'user_id': cls.user_sales_leads.id,
|
||||
'team_id': cls.sales_team_1.id,
|
||||
@@ -119,6 +128,8 @@ class TestCrmCommon(MailCase, SavepointCase):
|
||||
cls.contact_1 = cls.env['res.partner'].create({
|
||||
'name': 'Philip J Fry',
|
||||
'email': 'philip.j.fry@test.example.com',
|
||||
'mobile': '+1 202 555 0122',
|
||||
'phone': False,
|
||||
'parent_id': cls.contact_company_1.id,
|
||||
'is_company': False,
|
||||
'street': 'Actually the sewers',
|
||||
@@ -136,3 +147,137 @@ class TestCrmCommon(MailCase, SavepointCase):
|
||||
'country_id': cls.env.ref('base.us').id,
|
||||
'zip': '97648',
|
||||
})
|
||||
|
||||
def _create_duplicates(self, lead, count=2):
|
||||
leads = self.env['crm.lead']
|
||||
for x in range(count):
|
||||
leads |= self.env['crm.lead'].create({
|
||||
'name': 'Dup-%02d-%s' % (x+1, lead.name),
|
||||
'type': 'lead',
|
||||
'user_id': False,
|
||||
'team_id': lead.team_id.id,
|
||||
'contact_name': 'Duplicate %02d of %s' % (x+1, lead.contact_name),
|
||||
'email_from': lead.email_from,
|
||||
})
|
||||
return leads
|
||||
|
||||
|
||||
class TestLeadConvertCommon(TestCrmCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestLeadConvertCommon, cls).setUpClass()
|
||||
# Sales Team organization
|
||||
# Role: M (team member) R (team manager)
|
||||
# SALESMAN---------------sales_team_1-----sales_team_convert
|
||||
# admin------------------M----------------/
|
||||
# user_sales_manager-----R----------------R
|
||||
# user_sales_leads-------M----------------/
|
||||
# user_sales_salesman----/----------------M
|
||||
|
||||
# Stages Team organization
|
||||
# Name-------------------ST-------------------Sequ
|
||||
# stage_team1_1----------sales_team_1---------1
|
||||
# stage_team1_2----------sales_team_1---------5
|
||||
# stage_team1_won--------sales_team_1---------70
|
||||
# stage_gen_1------------/--------------------3
|
||||
# stage_gen_won----------/--------------------30
|
||||
# stage_team_convert_1---sales_team_convert---1
|
||||
|
||||
cls.sales_team_convert = cls.env['crm.team'].create({
|
||||
'name': 'Convert Sales Team',
|
||||
'alias_name': False,
|
||||
'use_leads': True,
|
||||
'use_opportunities': True,
|
||||
'company_id': False,
|
||||
'user_id': cls.user_sales_manager.id,
|
||||
'member_ids': [(4, cls.user_sales_salesman.id)],
|
||||
})
|
||||
cls.stage_team_convert_1 = cls.env['crm.stage'].create({
|
||||
'name': 'New',
|
||||
'sequence': 1,
|
||||
'team_id': cls.sales_team_convert.id,
|
||||
})
|
||||
|
||||
cls.lead_1.write({'date_open': Datetime.from_string('2020-01-15 11:30:00')})
|
||||
|
||||
cls.crm_lead_dt_patcher = patch('odoo.addons.crm.models.crm_lead.fields.Datetime', wraps=Datetime)
|
||||
cls.crm_lead_dt_mock = cls.crm_lead_dt_patcher.start()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.crm_lead_dt_patcher.stop()
|
||||
super(TestLeadConvertCommon, cls).tearDownClass()
|
||||
|
||||
|
||||
class TestLeadConvertMassCommon(TestLeadConvertCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestLeadConvertMassCommon, cls).setUpClass()
|
||||
# Sales Team organization
|
||||
# Role: M (team member) R (team manager)
|
||||
# SALESMAN-------------------sales_team_1-----sales_team_convert
|
||||
# admin----------------------M----------------/
|
||||
# user_sales_manager---------R----------------R
|
||||
# user_sales_leads-----------M----------------/
|
||||
# user_sales_leads_convert---/----------------M <-- NEW
|
||||
# user_sales_salesman--------/----------------M
|
||||
|
||||
cls.user_sales_leads_convert = mail_new_test_user(
|
||||
cls.env, login='user_sales_leads_convert',
|
||||
name='Lucien Sales Leads Convert', email='crm_leads_2@test.example.com',
|
||||
company_id=cls.env.ref("base.main_company").id,
|
||||
notification_type='inbox',
|
||||
groups='sales_team.group_sale_salesman_all_leads,base.group_partner_manager,crm.group_use_lead',
|
||||
)
|
||||
cls.sales_team_convert.write({
|
||||
'member_ids': [(4, cls.user_sales_leads_convert.id)]
|
||||
})
|
||||
|
||||
cls.lead_w_partner = cls.env['crm.lead'].create({
|
||||
'name': 'New1',
|
||||
'type': 'lead',
|
||||
'probability': 10,
|
||||
'user_id': cls.user_sales_manager.id,
|
||||
'stage_id': False,
|
||||
'partner_id': cls.contact_1.id,
|
||||
})
|
||||
cls.lead_w_partner_company = cls.env['crm.lead'].create({
|
||||
'name': 'New1',
|
||||
'type': 'lead',
|
||||
'probability': 15,
|
||||
'user_id': cls.user_sales_manager.id,
|
||||
'stage_id': cls.stage_team1_1.id,
|
||||
'partner_id': cls.contact_company_1.id,
|
||||
'contact_name': 'Hermes Conrad',
|
||||
'email_from': 'hermes.conrad@test.example.com',
|
||||
})
|
||||
cls.lead_w_contact = cls.env['crm.lead'].create({
|
||||
'name': 'LeadContact',
|
||||
'type': 'lead',
|
||||
'probability': 15,
|
||||
'contact_name': 'TestContact',
|
||||
'user_id': cls.user_sales_salesman.id,
|
||||
'stage_id': cls.stage_gen_1.id,
|
||||
})
|
||||
cls.lead_w_email = cls.env['crm.lead'].create({
|
||||
'name': 'LeadEmailAsContact',
|
||||
'type': 'lead',
|
||||
'probability': 15,
|
||||
'email_from': 'contact.email@test.example.com',
|
||||
'user_id': cls.user_sales_salesman.id,
|
||||
'stage_id': cls.stage_gen_1.id,
|
||||
})
|
||||
cls.lead_w_email_lost = cls.env['crm.lead'].create({
|
||||
'name': 'Lost',
|
||||
'type': 'lead',
|
||||
'probability': 15,
|
||||
'email_from': 'strange.from@test.example.com',
|
||||
'user_id': cls.user_sales_leads.id,
|
||||
'stage_id': cls.stage_team1_2.id,
|
||||
'active': False,
|
||||
})
|
||||
for l in (cls.lead_w_partner | cls.lead_w_partner_company | cls.lead_w_contact | cls.lead_w_email | cls.lead_w_email_lost):
|
||||
l._onchange_user_id()
|
||||
l.flush()
|
||||
|
||||
@@ -41,7 +41,7 @@ class TestCRMLead(TestCrmCommon):
|
||||
|
||||
lead.action_set_won()
|
||||
self.assertEqual(lead.probability, 100.0)
|
||||
self.assertEqual(lead.stage_id, self.stage_team1_won)
|
||||
self.assertEqual(lead.stage_id, self.stage_gen_won) # generic won stage has lower sequence than team won stage
|
||||
|
||||
@users('user_sales_manager')
|
||||
def test_crm_team_alias(self):
|
||||
|
||||
@@ -1,67 +1,98 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from odoo.addons.crm.tests.common import TestCrmCommon
|
||||
from odoo.addons.crm.tests import common as crm_common
|
||||
from odoo.fields import Datetime
|
||||
from odoo.tests.common import tagged, users
|
||||
|
||||
|
||||
@tagged('lead_manage')
|
||||
class TestLeadConvertCommon(TestCrmCommon):
|
||||
class TestLeadConvert(crm_common.TestLeadConvertCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestLeadConvertCommon, cls).setUpClass()
|
||||
|
||||
cls.sales_team_convert = cls.env['crm.team'].create({
|
||||
'name': 'Convert Sales Team',
|
||||
'alias_name': False,
|
||||
'use_leads': True,
|
||||
'use_opportunities': True,
|
||||
'company_id': False,
|
||||
'user_id': cls.user_sales_manager.id,
|
||||
'member_ids': [(4, cls.user_sales_salesman.id)],
|
||||
})
|
||||
cls.lead_1.write({'date_open': Datetime.from_string('2020-01-15 11:30:00')})
|
||||
|
||||
cls.crm_lead_dt_patcher = patch('odoo.addons.crm.models.crm_lead.fields.Datetime', wraps=Datetime)
|
||||
cls.crm_lead_dt_mock = cls.crm_lead_dt_patcher.start()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.crm_lead_dt_patcher.stop()
|
||||
super(TestLeadConvertCommon, cls).tearDownClass()
|
||||
|
||||
def create_duplicates(self):
|
||||
self.lead_1_dup1 = self.env['crm.lead'].create({
|
||||
'name': 'Duplicate1',
|
||||
'type': 'lead',
|
||||
'user_id': False,
|
||||
'team_id': self.lead_1.team_id.id,
|
||||
'contact_name': 'Amy Wong Duplicate',
|
||||
'email_from': self.lead_1.email_from,
|
||||
})
|
||||
self.lead_1_dup2 = self.env['crm.lead'].create({
|
||||
'name': 'Duplicate2',
|
||||
'type': 'lead',
|
||||
'user_id': False,
|
||||
'team_id': self.lead_1.team_id.id,
|
||||
'contact_name': 'Amy Wong Duplicate Two',
|
||||
'email_from': self.lead_1.email_from,
|
||||
})
|
||||
|
||||
|
||||
class TestLeadConvert(TestLeadConvertCommon):
|
||||
super(TestLeadConvert, cls).setUpClass()
|
||||
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_lead_convert_convert(self):
|
||||
date = Datetime.from_string('2020-01-20 16:00:00')
|
||||
self.crm_lead_dt_mock.now.return_value = date
|
||||
def test_lead_convert_base(self):
|
||||
""" Test base method ``convert_opportunity`` or crm.lead model """
|
||||
lead = self.lead_1.with_user(self.env.user)
|
||||
lead.write({
|
||||
'phone': '123456789',
|
||||
})
|
||||
self.assertEqual(lead.team_id, self.sales_team_1)
|
||||
self.assertEqual(lead.stage_id, self.stage_team1_1)
|
||||
self.assertEqual(lead.email_from, 'amy.wong@test.example.com')
|
||||
lead.convert_opportunity(self.contact_2.id)
|
||||
|
||||
self.assertEqual(lead.type, 'opportunity')
|
||||
self.assertEqual(lead.partner_id, self.contact_2)
|
||||
self.assertEqual(lead.email_from, self.contact_2.email)
|
||||
self.assertEqual(lead.mobile, self.contact_2.mobile)
|
||||
self.assertEqual(lead.phone, '123456789')
|
||||
self.assertEqual(lead.team_id, self.sales_team_1)
|
||||
self.assertEqual(lead.stage_id, self.stage_team1_1)
|
||||
|
||||
@users('user_sales_manager')
|
||||
def test_lead_convert_base_corner_cases(self):
|
||||
""" Test base method ``convert_opportunity`` or crm.lead model with corner
|
||||
cases: inactive, won, stage update, ... """
|
||||
# inactive leads are not converted
|
||||
lead = self.lead_1.with_user(self.env.user)
|
||||
lead.action_archive()
|
||||
self.assertFalse(lead.active)
|
||||
lead.convert_opportunity(self.contact_2.id)
|
||||
|
||||
self.assertEqual(lead.type, 'lead')
|
||||
self.assertEqual(lead.partner_id, self.env['res.partner'])
|
||||
|
||||
lead.action_unarchive()
|
||||
self.assertTrue(lead.active)
|
||||
|
||||
# won leads are not converted
|
||||
lead.action_set_won()
|
||||
# TDE FIXME: set won does not take into account sales team when fetching a won stage
|
||||
# self.assertEqual(lead.stage_id, self.stage_team1_won)
|
||||
self.assertEqual(lead.stage_id, self.stage_gen_won)
|
||||
self.assertEqual(lead.probability, 100)
|
||||
|
||||
lead.convert_opportunity(self.contact_2.id)
|
||||
self.assertEqual(lead.type, 'lead')
|
||||
self.assertEqual(lead.partner_id, self.env['res.partner'])
|
||||
|
||||
@users('user_sales_manager')
|
||||
def test_lead_convert_base_w_salesmen(self):
|
||||
""" Test base method ``convert_opportunity`` while forcing salesmen, as it
|
||||
should also force sales team """
|
||||
lead = self.lead_1.with_user(self.env.user)
|
||||
self.assertEqual(lead.team_id, self.sales_team_1)
|
||||
lead.convert_opportunity(False, user_ids=self.user_sales_salesman.ids)
|
||||
self.assertEqual(lead.user_id, self.user_sales_salesman)
|
||||
self.assertEqual(lead.team_id, self.sales_team_convert)
|
||||
# TDE FIXME: convert does not recompute stage based on updated team of assigned user
|
||||
# self.assertEqual(lead.stage_id, self.stage_team_convert_1)
|
||||
|
||||
@users('user_sales_manager')
|
||||
def test_lead_convert_base_w_team(self):
|
||||
""" Test base method ``convert_opportunity`` while forcing team """
|
||||
lead = self.lead_1.with_user(self.env.user)
|
||||
lead.convert_opportunity(False, team_id=self.sales_team_convert.id)
|
||||
self.assertEqual(lead.team_id, self.sales_team_convert)
|
||||
self.assertEqual(lead.user_id, self.user_sales_leads)
|
||||
# TDE FIXME: convert does not recompute stage based on team
|
||||
# self.assertEqual(lead.stage_id, self.stage_team_convert_1)
|
||||
|
||||
@users('user_sales_manager')
|
||||
def test_lead_convert_internals(self):
|
||||
""" Test internals of convert wizard """
|
||||
# ensure initial data to avoid spaghetti test update afterwards
|
||||
self.assertFalse(self.lead_1.date_conversion)
|
||||
self.assertEqual(self.lead_1.date_open, Datetime.from_string('2020-01-15 11:30:00'))
|
||||
self.assertEqual(self.lead_1.user_id, self.user_sales_leads)
|
||||
self.assertEqual(self.lead_1.team_id, self.sales_team_1)
|
||||
self.assertEqual(self.lead_1.stage_id, self.stage_team1_1)
|
||||
|
||||
convert = self.env['crm.lead2opportunity.partner'].with_context({
|
||||
'active_model': 'crm.lead',
|
||||
@@ -83,16 +114,57 @@ class TestLeadConvert(TestLeadConvertCommon):
|
||||
self.assertEqual(convert.team_id, self.sales_team_convert)
|
||||
|
||||
convert.action_apply()
|
||||
# convert test
|
||||
self.assertEqual(self.lead_1.type, 'opportunity')
|
||||
self.assertEqual(self.lead_1.user_id, self.user_sales_salesman)
|
||||
self.assertEqual(self.lead_1.team_id, self.sales_team_convert)
|
||||
# TDE FIXME: stage is linked to the old sales team and is not updated when converting, could be improved
|
||||
# self.assertEqual(self.lead_1.stage_id, self.stage_gen_1)
|
||||
# partner creation test
|
||||
new_partner = self.lead_1.partner_id
|
||||
self.assertEqual(new_partner.name, 'Amy Wong')
|
||||
self.assertEqual(new_partner.email, 'amy.wong@test.example.com')
|
||||
|
||||
@users('user_sales_manager')
|
||||
def test_lead_convert_merge(self):
|
||||
self.create_duplicates()
|
||||
def test_lead_convert_action_exist(self):
|
||||
""" Test specific use case of 'exist' action in conver wizard """
|
||||
self.lead_1.write({'partner_id': self.contact_1.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.action, 'exist')
|
||||
convert.action_apply()
|
||||
self.assertEqual(self.lead_1.type, 'opportunity')
|
||||
self.assertEqual(self.lead_1.partner_id, self.contact_1)
|
||||
|
||||
@users('user_sales_manager')
|
||||
def test_lead_convert_action_nothing(self):
|
||||
""" Test specific use case of 'nothing' action in conver wizard """
|
||||
self.lead_1.write({'contact_name': 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.action, 'nothing')
|
||||
convert.action_apply()
|
||||
self.assertEqual(self.lead_1.type, 'opportunity')
|
||||
self.assertEqual(self.lead_1.user_id, self.user_sales_leads)
|
||||
self.assertEqual(self.lead_1.team_id, self.sales_team_1)
|
||||
self.assertEqual(self.lead_1.stage_id, self.stage_team1_1)
|
||||
self.assertEqual(self.lead_1.partner_id, self.env['res.partner'])
|
||||
|
||||
@users('user_sales_manager')
|
||||
def test_lead_merge(self):
|
||||
""" Test convert wizard working in merge mode """
|
||||
date = Datetime.from_string('2020-01-20 16:00:00')
|
||||
self.crm_lead_dt_mock.now.return_value = date
|
||||
|
||||
self.assertFalse(self.lead_1.date_conversion)
|
||||
self.assertEqual(self.lead_1.date_open, Datetime.from_string('2020-01-15 11:30:00'))
|
||||
leads = self._create_duplicates(self.lead_1)
|
||||
|
||||
convert = self.env['crm.lead2opportunity.partner'].with_context({
|
||||
'active_model': 'crm.lead',
|
||||
@@ -101,7 +173,7 @@ class TestLeadConvert(TestLeadConvertCommon):
|
||||
}).create({})
|
||||
|
||||
# test internals of convert wizard
|
||||
self.assertEqual(convert.opportunity_ids, self.lead_1 | self.lead_1_dup1 | self.lead_1_dup2)
|
||||
self.assertEqual(convert.opportunity_ids, self.lead_1 | leads)
|
||||
self.assertEqual(convert.user_id, self.lead_1.user_id)
|
||||
self.assertEqual(convert.team_id, self.lead_1.team_id)
|
||||
self.assertFalse(convert.partner_id)
|
||||
@@ -116,171 +188,159 @@ class TestLeadConvert(TestLeadConvertCommon):
|
||||
convert.action_apply()
|
||||
self.assertEqual(self.lead_1.type, 'opportunity')
|
||||
|
||||
|
||||
@tagged('lead_manage')
|
||||
class TestLeadConvertBatch(crm_common.TestLeadConvertMassCommon):
|
||||
|
||||
@users('user_sales_manager')
|
||||
def test_lead_convert_various(self):
|
||||
self.lead_1.write({'contact_name': False})
|
||||
def test_lead_convert_batch_internals(self):
|
||||
""" Test internals of convert wizard, working in batch mode """
|
||||
date = Datetime.from_string('2020-01-20 16:00:00')
|
||||
self.crm_lead_dt_mock.now.return_value = date
|
||||
|
||||
lead_w_partner = self.lead_w_partner
|
||||
self.assertEqual(lead_w_partner.user_id, self.user_sales_manager)
|
||||
self.assertEqual(lead_w_partner.team_id, self.sales_team_1)
|
||||
self.assertEqual(lead_w_partner.stage_id, self.env['crm.stage'])
|
||||
lead_w_contact = self.lead_w_contact
|
||||
self.assertEqual(lead_w_contact.user_id, self.user_sales_salesman)
|
||||
self.assertEqual(lead_w_contact.team_id, self.sales_team_convert)
|
||||
self.assertEqual(lead_w_contact.stage_id, self.stage_gen_1)
|
||||
lead_w_email_lost = self.lead_w_email_lost
|
||||
self.assertEqual(lead_w_email_lost.user_id, self.user_sales_leads)
|
||||
self.assertEqual(lead_w_email_lost.team_id, self.sales_team_1)
|
||||
self.assertEqual(lead_w_email_lost.stage_id, self.stage_team1_2)
|
||||
lead_w_email_lost.action_set_lost()
|
||||
self.assertEqual(lead_w_email_lost.active, False)
|
||||
|
||||
convert = self.env['crm.lead2opportunity.partner'].with_context({
|
||||
'active_model': 'crm.lead',
|
||||
'active_id': self.lead_1.id,
|
||||
'active_ids': (self.lead_1 | lead_w_partner | lead_w_contact | lead_w_email_lost).ids,
|
||||
}).create({})
|
||||
self.assertEqual(convert.action, 'nothing')
|
||||
|
||||
self.lead_1.write({'partner_id': self.contact_1.id})
|
||||
# test internals of convert wizard
|
||||
# self.assertEqual(convert.lead_id, self.lead_1)
|
||||
self.assertEqual(convert.user_id, self.lead_1.user_id)
|
||||
self.assertEqual(convert.team_id, self.lead_1.team_id)
|
||||
self.assertFalse(convert.partner_id)
|
||||
self.assertEqual(convert.name, 'convert')
|
||||
self.assertEqual(convert.action, 'create')
|
||||
|
||||
convert = self.env['crm.lead2opportunity.partner'].with_context({
|
||||
convert.action_apply()
|
||||
self.assertEqual(convert.user_id, self.user_sales_leads)
|
||||
self.assertEqual(convert.team_id, self.sales_team_1)
|
||||
# lost leads are not converted (see crm_lead.convert_opportunity())
|
||||
self.assertFalse(lead_w_email_lost.active)
|
||||
self.assertFalse(lead_w_email_lost.date_conversion)
|
||||
self.assertEqual(lead_w_email_lost.partner_id, self.env['res.partner'])
|
||||
self.assertEqual(lead_w_email_lost.stage_id, self.stage_team1_2) # did not change
|
||||
# other leads are converted into opportunities
|
||||
for opp in (self.lead_1 | lead_w_partner | lead_w_contact):
|
||||
# team management update: opportunity linked to chosen wizard values
|
||||
self.assertEqual(opp.type, 'opportunity')
|
||||
self.assertTrue(opp.active)
|
||||
self.assertEqual(opp.user_id, convert.user_id)
|
||||
self.assertEqual(opp.team_id, convert.team_id)
|
||||
# dates update: convert set them to now
|
||||
self.assertEqual(opp.date_open, date)
|
||||
self.assertEqual(opp.date_conversion, date)
|
||||
# stage update (depends on previous value)
|
||||
if opp == self.lead_1:
|
||||
self.assertEqual(opp.stage_id, self.stage_team1_1) # did not change
|
||||
elif opp == lead_w_partner:
|
||||
self.assertEqual(opp.stage_id, self.stage_team1_1) # is set to default stage of sales_team_1
|
||||
elif opp == lead_w_contact:
|
||||
self.assertEqual(opp.stage_id, self.stage_gen_1) # did not change
|
||||
else:
|
||||
self.assertFalse(True)
|
||||
|
||||
|
||||
@tagged('lead_manage')
|
||||
class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestLeadConvertMass, cls).setUpClass()
|
||||
|
||||
cls.leads = cls.lead_1 + cls.lead_w_partner + cls.lead_w_email_lost
|
||||
# reset some assigned users to test salesmen assign
|
||||
(cls.lead_w_partner | cls.lead_w_email_lost).write({
|
||||
'user_id': False
|
||||
})
|
||||
|
||||
cls.assign_users = cls.user_sales_manager + cls.user_sales_leads_convert + cls.user_sales_salesman
|
||||
|
||||
@users('user_sales_manager')
|
||||
def test_mass_convert_internals(self):
|
||||
""" Test internals mass converted in convert mode, without duplicate management """
|
||||
leads = self.leads
|
||||
|
||||
mass_convert = self.env['crm.lead2opportunity.partner.mass'].with_context({
|
||||
'active_model': 'crm.lead',
|
||||
'active_id': self.lead_1.id,
|
||||
}).create({})
|
||||
self.assertEqual(convert.action, 'exist')
|
||||
|
||||
|
||||
class TestLeadConvertMass(TestLeadConvertCommon):
|
||||
|
||||
def test_lead2opportunity2win(self):
|
||||
""" Tests for Test Lead 2 opportunity 2 win """
|
||||
default_stage_id = self.stage_gen_1.id
|
||||
|
||||
crm_case_2 = self.env['crm.lead'].create({
|
||||
'name': 'Design Software',
|
||||
'type': 'lead',
|
||||
})
|
||||
crm_case_3 = self.env['crm.lead'].create({
|
||||
'name': 'Pricing for 25 desks',
|
||||
'type': 'lead',
|
||||
})
|
||||
crm_case_13 = self.env['crm.lead'].create({
|
||||
'name': 'Quote for 600 Chairs',
|
||||
'type': 'opportunity',
|
||||
'contact_name': 'Will McEncroe',
|
||||
})
|
||||
|
||||
# In order to test the conversion of a lead into a opportunity,
|
||||
# I set lead to open stage.
|
||||
crm_case_3.write({'stage_id': default_stage_id})
|
||||
|
||||
# I check if the lead stage is "Open".
|
||||
# self.assertEqual(crm_case_3.stage_id.sequence, 1, 'Lead stage is Open')
|
||||
|
||||
# Giving access rights of salesman to convert the lead into opportunity.
|
||||
# I convert lead into opportunity for exiting customer.
|
||||
crm_case_3.with_user(self.user_sales_manager).convert_opportunity(self.contact_2.id)
|
||||
|
||||
# I check details of converted opportunity.
|
||||
self.assertEqual(crm_case_3.type, 'opportunity', 'Lead is not converted to opportunity!')
|
||||
self.assertEqual(crm_case_3.partner_id.id, self.contact_2.id, 'Partner mismatch!')
|
||||
self.assertEqual(crm_case_3.stage_id.id, default_stage_id, 'Stage of opportunity is incorrect!')
|
||||
|
||||
# I convert mass lead into opportunity customer.
|
||||
mass = self.env['crm.lead2opportunity.partner.mass'].with_user(self.user_sales_manager).with_context({
|
||||
'active_model': 'crm.lead',
|
||||
'active_ids': [crm_case_13.id, crm_case_2.id],
|
||||
'active_id': crm_case_13.id}
|
||||
).create({
|
||||
'user_ids': [(6, 0, self.env.ref('base.user_root').ids)],
|
||||
'team_id': self.env.ref("sales_team.team_sales_department").id
|
||||
})
|
||||
mass.with_user(self.user_sales_manager).mass_convert()
|
||||
|
||||
# Now I check first lead converted on opportunity.
|
||||
self.assertEqual(crm_case_13.name, "Quote for 600 Chairs", "Opportunity name not correct")
|
||||
self.assertEqual(crm_case_13.type, 'opportunity', "Lead is not converted to opportunity!")
|
||||
expected_partner = "Will McEncroe"
|
||||
self.assertEqual(crm_case_13.partner_id.name, expected_partner, "Partner mismatch! %s vs %s" % (crm_case_13.partner_id.name, expected_partner))
|
||||
self.assertEqual(crm_case_13.stage_id.id, default_stage_id, "Stage of probability is incorrect!")
|
||||
|
||||
# Then check for second lead converted on opportunity.
|
||||
self.assertEqual(crm_case_2.name, "Design Software", "Opportunity name not correct")
|
||||
self.assertEqual(crm_case_2.type, "opportunity", "Lead is not converted to opportunity!")
|
||||
self.assertEqual(crm_case_2.stage_id.id, default_stage_id, "Stage of probability is incorrect!")
|
||||
|
||||
# I loose the second opportunity
|
||||
crm_case_2.action_set_lost()
|
||||
|
||||
# I check details of the opportunity after the loose
|
||||
self.assertEqual(crm_case_2.probability, 0.0, "Revenue probability should be 0.0!")
|
||||
|
||||
def test_lead2opportunity_assign_salesmen(self):
|
||||
""" Tests for Test Lead2opportunity Assign Salesmen """
|
||||
LeadSaleman = self.env['crm.lead'].with_user(self.user_sales_manager)
|
||||
default_stage_id = self.stage_gen_1.id
|
||||
|
||||
# During a lead to opp conversion, salesmen should be assigned to leads following the round-robin method. Start by creating 4 salesmen (A to D) and 6 leads (1 to 6).
|
||||
test_res_user_01 = self.env['res.users'].create({
|
||||
'name': 'Test user A',
|
||||
'login': 'tua@example.com',
|
||||
})
|
||||
test_res_user_02 = self.env['res.users'].create({
|
||||
'name': 'Test user B',
|
||||
'login': 'tub@example.com',
|
||||
})
|
||||
test_res_user_03 = self.env['res.users'].create({
|
||||
'name': 'Test user C',
|
||||
'login': 'tuc@example.com',
|
||||
})
|
||||
test_res_user_04 = self.env['res.users'].create({
|
||||
'name': 'Test user D',
|
||||
'login': 'tud@example.com',
|
||||
})
|
||||
|
||||
# Salesman also creates lead so giving access rights of salesman.
|
||||
test_crm_lead_01 = LeadSaleman.create({
|
||||
'type': 'lead',
|
||||
'name': 'Test lead 1',
|
||||
'email_from': 'Raoul Grosbedon <raoul@grosbedon.fr>',
|
||||
'stage_id': default_stage_id
|
||||
})
|
||||
test_crm_lead_02 = LeadSaleman.create({
|
||||
'type': 'lead',
|
||||
'name': 'Test lead 2',
|
||||
'email_from': 'Raoul Grosbedon <raoul@grosbedon.fr>',
|
||||
'stage_id': default_stage_id
|
||||
})
|
||||
test_crm_lead_03 = LeadSaleman.create({
|
||||
'type': 'lead',
|
||||
'name': 'Test lead 3',
|
||||
'email_from': 'Raoul Grosbedon <raoul@grosbedon.fr>',
|
||||
'stage_id': default_stage_id
|
||||
})
|
||||
test_crm_lead_04 = LeadSaleman.create({
|
||||
'type': 'lead',
|
||||
'name': 'Test lead 4',
|
||||
'email_from': 'Fabrice Lepoilu',
|
||||
'stage_id': default_stage_id
|
||||
})
|
||||
test_crm_lead_05 = LeadSaleman.create({
|
||||
'type': 'lead',
|
||||
'name': 'Test lead 5',
|
||||
'email_from': 'Fabrice Lepoilu',
|
||||
'stage_id': default_stage_id
|
||||
})
|
||||
test_crm_lead_06 = LeadSaleman.create({
|
||||
'type': 'lead',
|
||||
'name': 'Test lead 6',
|
||||
'email_from': 'Agrolait SuperSeed SA',
|
||||
'stage_id': default_stage_id
|
||||
})
|
||||
|
||||
lead_ids = [test_crm_lead_01.id, test_crm_lead_02.id, test_crm_lead_03.id, test_crm_lead_04.id, test_crm_lead_05.id, test_crm_lead_06.id]
|
||||
salesmen_ids = [test_res_user_01.id, test_res_user_02.id, test_res_user_03.id, test_res_user_04.id]
|
||||
|
||||
# Salesman create a mass convert wizard and convert all the leads.
|
||||
mass = self.env['crm.lead2opportunity.partner.mass'].with_user(self.user_sales_manager).with_context({
|
||||
'active_model': 'crm.lead',
|
||||
'active_ids': lead_ids,
|
||||
'active_id': test_crm_lead_01.id}
|
||||
).create({
|
||||
'user_ids': [(6, 0, salesmen_ids)],
|
||||
'team_id': self.env.ref("sales_team.team_sales_department").id,
|
||||
'active_ids': leads.ids,
|
||||
'active_id': leads.ids[0]
|
||||
}).create({
|
||||
'deduplicate': False,
|
||||
'force_assignation': True
|
||||
'user_id': self.user_sales_salesman.id,
|
||||
'force_assignation': False,
|
||||
})
|
||||
mass.with_user(self.user_sales_manager).mass_convert()
|
||||
mass_convert.onchange_action()
|
||||
mass_convert._onchange_user()
|
||||
|
||||
# The leads should now be opps with a salesman and a salesteam. Also, salesmen should have been assigned following a round-robin method.
|
||||
opps = self.env['crm.lead'].with_user(self.user_sales_manager).browse(lead_ids)
|
||||
i = 0
|
||||
for opp in opps:
|
||||
self.assertEqual(opp.type, 'opportunity', 'Type mismatch: this should be an opp, not a lead')
|
||||
self.assertEqual(opp.user_id.id, salesmen_ids[i], 'Salesman mismatch: expected salesman %r, got %r' % (salesmen_ids[i], opp.user_id.id))
|
||||
i = i + 1 if (i < len(salesmen_ids) - 1) else 0
|
||||
# default values
|
||||
self.assertEqual(mass_convert.name, 'convert')
|
||||
self.assertEqual(mass_convert.action, 'each_exist_or_create')
|
||||
# depending on options
|
||||
self.assertEqual(mass_convert.partner_id, self.env['res.partner'])
|
||||
self.assertEqual(mass_convert.deduplicate, False)
|
||||
self.assertEqual(mass_convert.user_id, self.user_sales_salesman)
|
||||
self.assertEqual(mass_convert.team_id, self.sales_team_convert)
|
||||
|
||||
mass_convert.mass_convert()
|
||||
for lead in self.lead_1 | self.lead_w_partner:
|
||||
self.assertEqual(lead.type, 'opportunity')
|
||||
if lead == self.lead_w_partner:
|
||||
self.assertEqual(lead.user_id, self.env['res.users']) # user_id is bypassed
|
||||
self.assertEqual(lead.partner_id, self.contact_1)
|
||||
elif lead == self.lead_1:
|
||||
self.assertEqual(lead.user_id, self.user_sales_leads) # existing value not forced
|
||||
new_partner = lead.partner_id
|
||||
self.assertEqual(new_partner.name, 'Amy Wong')
|
||||
self.assertEqual(new_partner.email, 'amy.wong@test.example.com')
|
||||
|
||||
# test unforced assignation
|
||||
mass_convert.write({
|
||||
'user_ids': self.user_sales_salesman.ids,
|
||||
})
|
||||
mass_convert.mass_convert()
|
||||
self.assertEqual(self.lead_w_partner.user_id, self.user_sales_salesman)
|
||||
self.assertEqual(self.lead_1.user_id, self.user_sales_leads) # existing value not forced
|
||||
|
||||
# lost leads are untouched
|
||||
self.assertEqual(self.lead_w_email_lost.type, 'lead')
|
||||
self.assertFalse(self.lead_w_email_lost.active)
|
||||
self.assertFalse(self.lead_w_email_lost.date_conversion)
|
||||
# TDE FIXME: partner creation is done even on lost leads because not checked in wizard
|
||||
# self.assertEqual(self.lead_w_email_lost.partner_id, self.env['res.partner'])
|
||||
|
||||
def test_mass_convert_w_salesmen(self):
|
||||
leads = self.leads
|
||||
|
||||
mass_convert = self.env['crm.lead2opportunity.partner.mass'].with_context({
|
||||
'active_model': 'crm.lead',
|
||||
'active_ids': leads.ids,
|
||||
'active_id': leads.ids[0]
|
||||
}).create({
|
||||
'deduplicate': False,
|
||||
'user_ids': self.assign_users.ids,
|
||||
'force_assignation': True,
|
||||
})
|
||||
|
||||
# TDE FIXME: what happens if we mix people from different sales team ? currently nothing, to check
|
||||
mass_convert.mass_convert()
|
||||
|
||||
for idx, lead in enumerate(self.leads - self.lead_w_email_lost):
|
||||
self.assertEqual(lead.type, 'opportunity')
|
||||
assigned_user = self.assign_users[idx % len(self.assign_users)]
|
||||
self.assertEqual(lead.user_id, assigned_user)
|
||||
|
||||
Reference in New Issue
Block a user