diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py index 5184113c26c..c08e29e6da3 100644 --- a/addons/crm/__openerp__.py +++ b/addons/crm/__openerp__.py @@ -79,18 +79,6 @@ Dashboard for CRM will include: 'data/crm_activity_demo.xml', 'data/base_action_rule_demo.xml', ], - 'test': [ - 'test/crm_access_group_users.yml', - 'test/crm_lead_message.yml', - 'test/lead2opportunity2win.yml', - 'test/lead2opportunity_assign_salesmen.yml', - 'test/crm_lead_merge.yml', - 'test/crm_lead_cancel.yml', - 'test/crm_lead_onchange.yml', - 'test/crm_lead_copy.yml', - 'test/crm_lead_unlink.yml', - 'test/crm_lead_find_stage.yml', - ], 'css': ['static/src/css/crm.css'], 'installable': True, 'application': True, diff --git a/addons/crm/test/crm_access_group_users.yml b/addons/crm/test/crm_access_group_users.yml deleted file mode 100644 index 176283592b7..00000000000 --- a/addons/crm/test/crm_access_group_users.yml +++ /dev/null @@ -1,29 +0,0 @@ -- - Create a user as 'Crm Salesmanager' -- - !record {model: res.users, id: crm_res_users_salesmanager, view: False}: - company_id: base.main_company - name: Crm Sales manager - login: csm - email: crmmanager@yourcompany.com -- - I added groups for Crm Salesmanager. -- - !record {model: res.users, id: crm_res_users_salesmanager}: - groups_id: - - sales_team.group_sale_manager -- - Create a user as 'Crm Salesman' -- - !record {model: res.users, id: crm_res_users_salesman, view: False}: - company_id: base.main_company - name: Crm Salesman - login: csu - email: crmuser@yourcompany.com -- - I added groups for Crm Salesman. -- - !record {model: res.users, id: crm_res_users_salesman}: - groups_id: - - sales_team.group_sale_salesman_all_leads - - base.group_partner_manager diff --git a/addons/crm/test/crm_lead_cancel.yml b/addons/crm/test/crm_lead_cancel.yml deleted file mode 100644 index 0ddb0c78932..00000000000 --- a/addons/crm/test/crm_lead_cancel.yml +++ /dev/null @@ -1,14 +0,0 @@ -- - I set a new sale team giving access rights of salesman. -- - !context - uid: 'crm_res_users_salesmanager' -- - !python {model: crm.lead}: | - team_id = self.pool.get('crm.team').create(cr, uid, {'name': "Phone Marketing"}) - self.write(cr, uid, [ref("crm_case_1")], {'team_id': team_id}) -- - Salesman check unqualified lead . -- - !assert {model: crm.lead, id: crm.crm_case_1, string: Lead is in new stage}: - - stage_id.sequence == 1 diff --git a/addons/crm/test/crm_lead_copy.yml b/addons/crm/test/crm_lead_copy.yml deleted file mode 100644 index b6071ae9f9d..00000000000 --- a/addons/crm/test/crm_lead_copy.yml +++ /dev/null @@ -1,5 +0,0 @@ -- - I make duplicate the Lead. -- - !python {model: crm.lead}: | - self.copy(cr, uid, ref("crm_case_4")) diff --git a/addons/crm/test/crm_lead_find_stage.yml b/addons/crm/test/crm_lead_find_stage.yml deleted file mode 100644 index 040b29a2317..00000000000 --- a/addons/crm/test/crm_lead_find_stage.yml +++ /dev/null @@ -1,33 +0,0 @@ -- - I create a new lead. -- - !record {model: crm.lead, id: test_crm_lead_new}: - type: 'lead' - name: 'Test lead new' - partner_id: base.res_partner_1 - description: This is the description of the test new lead. - team_id: sales_team.team_sales_department -- - I change type from lead to opportunity. -- - !python {model: crm.lead}: | - self.convert_opportunity(cr, uid ,[ref("test_crm_lead_new")], ref("base.res_partner_2")) -- - I check default stage of opportunity. -- - !python {model: crm.lead}: | - lead = self.browse(cr, uid, ref('test_crm_lead_new')) - assert lead.stage_id.sequence <= 1, "Default stage of lead is incorrect!" -- - Now I change the stage of opportunity to won. -- - !python {model: crm.lead}: | - self.action_set_won(cr, uid, [ref("test_crm_lead_new")]) -- - I check statge of opp should won, after change stage. -- - !python {model: crm.lead}: | - opp = self.browse(cr, uid, ref('test_crm_lead_new')) - stage_id = opp.stage_find(opp.team_id.id or False,[('probability','=',100.0)]) - assert stage_id == opp.stage_id.id, "Stage of opportunity is incorrect!" - diff --git a/addons/crm/test/crm_lead_merge.yml b/addons/crm/test/crm_lead_merge.yml deleted file mode 100644 index e3c043a7fe4..00000000000 --- a/addons/crm/test/crm_lead_merge.yml +++ /dev/null @@ -1,128 +0,0 @@ -- - During a mixed merge (involving leads and opps), data should be handled a certain way following their type (m2o, m2m, text, ...) Start by creating two leads and an opp and giving the rights of Sales manager. -- - !context - uid: 'crm_res_users_salesmanager' -- - !record {model: crm.lead, id: test_crm_opp_1}: - type: 'opportunity' - name: 'Test opportunity 1' - partner_id: base.res_partner_3 - stage_id: stage_lead1 - description: This is the description of the test opp 1. -- - !record {model: crm.lead, id: test_crm_lead_first}: - type: 'lead' - name: 'Test lead first' - partner_id: base.res_partner_1 - stage_id: stage_lead1 - description: This is the description of the test lead first. -- - !record {model: crm.lead, id: test_crm_lead_second}: - type: 'lead' - name: 'Test lead second' - partner_id: base.res_partner_1 - stage_id: stage_lead1 - description: This is the description of the test lead second. -- - !python {model: crm.lead}: | - lead_ids = [ref('test_crm_opp_1'), ref('test_crm_lead_first'), ref('test_crm_lead_second')] - context.update({'active_model': 'crm.lead', 'active_ids': lead_ids, 'active_id': lead_ids[0]}) -- - I create a merge wizard and merge the leads and opp together in the first item of the list. -- - !record {model: crm.merge.opportunity, id: merge_opp_wizard_01}: -- - !python {model: crm.merge.opportunity}: | - self.action_merge(cr, uid, [ref("merge_opp_wizard_01")], context=context) -- - I check for the resulting merged opp (based on name and partner). -- - !python {model: crm.lead}: | - merge_id = self.search(cr, uid, [('name', '=', 'Test opportunity 1'), ('partner_id','=', ref("base.res_partner_3"))]) - - assert merge_id, 'Fail to create merge opportunity wizard' - merge_result = self.browse(cr, uid, merge_id)[0] - assert merge_result.description == 'This is the description of the test opp 1.\n\nThis is the description of the test lead first.\n\nThis is the description of the test lead second.', 'Description mismatch: when merging leads/opps with different text values, these values should get concatenated and separated with line returns' - assert merge_result.type == 'opportunity', 'Type mismatch: when at least one opp in involved in the merge, the result should be a new opp (instead of %s)' % merge_result.type -- - The other (tailing) leads/opps shouldn't exist anymore. -- - !python {model: crm.lead}: | - tailing_lead = self.search(cr, uid, [('id', '=', ref('test_crm_lead_first'))]) - assert not tailing_lead, 'This tailing lead (id %s) should not exist anymore' % ref('test_crm_lead_second') - - tailing_opp = self.search(cr, uid, [('id', '=', ref('test_crm_lead_second'))]) - assert not tailing_opp, 'This tailing opp (id %s) should not exist anymore' % ref('test_crm_opp_01') -- - I want to test leads merge. Start by creating two leads (with the same partner). -- - !record {model: crm.lead, id: test_crm_lead_03}: - type: 'lead' - name: 'Test lead 3' - partner_id: base.res_partner_1 - stage_id: stage_lead1 -- - !record {model: crm.lead, id: test_crm_lead_04}: - type: 'lead' - name: 'Test lead 4' - partner_id: base.res_partner_1 - stage_id: stage_lead1 -- - !python {model: crm.lead}: | - lead_ids = [ref('test_crm_lead_03'), ref('test_crm_lead_04')] - context.update({'active_model': 'crm.lead', 'active_ids': lead_ids, 'active_id': lead_ids[0]}) -- - I create a merge wizard and merge the leads together. -- - !record {model: crm.merge.opportunity, id: merge_opp_wizard_02}: -- - !python {model: crm.merge.opportunity}: | - self.action_merge(cr, uid, [ref("merge_opp_wizard_02")], context=context) -- - I check for the resulting merged lead (based on name and partner). -- - !python {model: crm.lead}: | - merge_id = self.search(cr, uid, [('name', '=', 'Test lead 3'), ('partner_id','=', ref("base.res_partner_1"))]) - assert merge_id, 'Fail to create merge opportunity wizard' - merge_result = self.browse(cr, uid, merge_id)[0] - assert merge_result.partner_id.id == ref("base.res_partner_1"), 'Partner mismatch' - assert merge_result.type == 'lead', 'Type mismatch: when leads get merged together, the result should be a new lead (instead of %s)' % merge_result.type - tailing_lead = self.search(cr, uid, [('id', '=', ref('test_crm_lead_04'))]) - assert not tailing_lead, 'This tailing lead (id %s) should not exist anymore' % ref('test_crm_lead_04') -- - I want to test opps merge. Start by creating two opportunities (with the same partner). -- - !record {model: crm.lead, id: test_crm_opp_02}: - type: 'opportunity' - name: 'Test opportunity 2' - partner_id: base.res_partner_3 - stage_id: stage_lead1 -- - !record {model: crm.lead, id: test_crm_opp_03}: - type: 'opportunity' - name: 'Test opportunity 3' - partner_id: base.res_partner_3 - stage_id: stage_lead1 -- - !python {model: crm.lead}: | - opp_ids = [ref('test_crm_opp_02'), ref('test_crm_opp_03')] - context.update({'active_model': 'crm.lead', 'active_ids': opp_ids, 'active_id': opp_ids[0]}) -- - I create a merge wizard and merge the opps together. -- - !record {model: crm.merge.opportunity, id: merge_opp_wizard_03}: -- - !python {model: crm.merge.opportunity}: | - self.action_merge(cr, uid, [ref("merge_opp_wizard_03")], context=context) -- - I check for the resulting merged opp (based on name and partner). -- - !python {model: crm.lead}: | - merge_id = self.search(cr, uid, [('name', '=', 'Test opportunity 2'), ('partner_id','=', ref("base.res_partner_3"))]) - assert merge_id, 'Fail to create merge opportunity wizard' - merge_result = self.browse(cr, uid, merge_id)[0] - assert merge_result.partner_id.id == ref("base.res_partner_3"), 'Partner mismatch' - assert merge_result.type == 'opportunity', 'Type mismatch: when opps get merged together, the result should be a new opp (instead of %s)' % merge_result.type - tailing_opp = self.search(cr, uid, [('id', '=', ref('test_crm_opp_03'))]) - assert not tailing_opp, 'This tailing opp (id %s) should not exist anymore' % ref('test_crm_opp_03') diff --git a/addons/crm/test/crm_lead_message.yml b/addons/crm/test/crm_lead_message.yml deleted file mode 100644 index fcfe658a8f5..00000000000 --- a/addons/crm/test/crm_lead_message.yml +++ /dev/null @@ -1,40 +0,0 @@ -- - Give the access rights of Salesman to communicate with customer. -- - !context - uid: 'crm_res_users_salesman' -- - Customer interested in our product, so he sends request by email to get more details. -- - Mail script will fetch his request from mail server. Then I process that mail after read EML file. -- - !python {model: mail.thread}: | - request_file = open(openerp.modules.module.get_module_resource('crm','test', 'customer_request.eml'),'rb') - request_message = request_file.read() - self.message_process(cr, uid, 'crm.lead', request_message) -- - After getting the mail, I check details of new lead of that customer. -- - !python {model: crm.lead}: | - lead_ids = self.search(cr, uid, [('email_from','=', 'Mr. John Right ')]) - assert lead_ids and len(lead_ids), "Lead is not created after getting request" - lead = self.browse(cr, uid, lead_ids[0], context=context) - assert not lead.partner_id, "Customer should be a new one" - assert lead.name == "Fournir votre devis avec le meilleur prix.", "Subject does not match" -- - I reply his request with welcome message. TODO revert mail.mail to mail.compose.message (conversion to customer should be automatic). -- - !python {model: mail.mail}: | - lead_ids = self.pool.get('crm.lead').search(cr, uid, [('email_from','=', 'Mr. John Right ')]) - context.update({'active_model': 'crm.lead','active_id': lead_ids[0]}) - id = self.create(cr, uid, {'body': "Merci de votre intérêt pour notre produit, nous vous contacterons bientôt. Bien à vous", 'email_from': 'sales@mycompany.com'}, context=context) - try: - self.send_mail(cr, uid, [id], context=context) - except: - pass -- - Now, I convert him into customer and put him into regular customer list. -- - !python {model: crm.lead}: | - lead_ids = self.search(cr, uid, [('email_from','=', 'Mr. John Right ')]) - self.handle_partner_assignation(cr, uid, lead_ids, context=context) diff --git a/addons/crm/test/crm_lead_onchange.yml b/addons/crm/test/crm_lead_onchange.yml deleted file mode 100644 index d2580fde999..00000000000 --- a/addons/crm/test/crm_lead_onchange.yml +++ /dev/null @@ -1,19 +0,0 @@ -- - Sales manager create a lead record to call a partner onchange, stage onchange and mailing opt-in onchange method. -- - !context - uid: 'crm_res_users_salesmanager' -- - !record {model: crm.lead, id: crm_case_25}: - name: 'Need more info about your pc2' - partner_id: base.res_partner_2 - type: opportunity - stage_id: crm.stage_lead1 -- - Sales manager create a lead record to call a mailing opt-out onchange method. -- - !record {model: crm.lead, id: crm_case_18}: - name: 'Need 20 Days of Consultancy' - type: opportunity - stage_id: crm.stage_lead1 - opt_out: True diff --git a/addons/crm/test/crm_lead_unlink.yml b/addons/crm/test/crm_lead_unlink.yml deleted file mode 100644 index be545e53773..00000000000 --- a/addons/crm/test/crm_lead_unlink.yml +++ /dev/null @@ -1,8 +0,0 @@ -- - Only Sales manager Unlink the Lead so test with Manager's access rights'. -- - !context - uid: 'crm_res_users_salesmanager' -- - !python {model: crm.lead}: | - self.unlink(cr, uid, [ref("crm_case_4")]) diff --git a/addons/crm/test/lead2opportunity2win.yml b/addons/crm/test/lead2opportunity2win.yml deleted file mode 100644 index 882c65e05ad..00000000000 --- a/addons/crm/test/lead2opportunity2win.yml +++ /dev/null @@ -1,88 +0,0 @@ -- - Giving access rights of salesman to convert the lead into opportunity. -- - !context - uid: 'crm_res_users_salesman' -- - In order to test the conversion of a lead into a opportunity, -- - I set lead to open stage. -- - !python {model: crm.lead}: | - self.write(cr, uid, [ref("crm_case_3")],{'stage_id':ref("stage_lead1")}) -- - I check if the lead stage is "Open". -- - !assert {model: crm.lead, id: crm.crm_case_3, string: Lead stage is Open}: - - stage_id.sequence == 1 -- - I convert lead into opportunity for exiting customer. -- - !python {model: crm.lead}: | - self.convert_opportunity(cr, uid ,[ref("crm_case_3")], ref("base.res_partner_2")) -- - I check details of converted opportunity. -- - !python {model: crm.lead}: | - lead = self.browse(cr, uid, ref('crm_case_3')) - assert lead.type == 'opportunity', 'Lead is not converted to opportunity!' - assert lead.partner_id.id == ref("base.res_partner_2"), 'Partner mismatch!' - assert lead.stage_id.id == ref("stage_lead1"), 'Stage of opportunity is incorrect!' -- - Now I schedule meeting with customer. -- - !python {model: crm.lead}: | - self.action_schedule_meeting(cr, uid, [ref('crm_case_3')]) -- - After communicated with customer, I put some notes with contract details. -- - !python {model: crm.lead}: | - self.message_post(cr, uid, [ref('crm_case_3')], subject='Test note', body='Détails envoyés par le client sur ​​le FAX pour la qualité') -- - I convert mass lead into opportunity customer. -- - !python {model: crm.lead2opportunity.partner.mass}: | - context.update({'active_model': 'crm.lead', 'active_ids': [ref("crm_case_13"), ref("crm_case_2")], 'active_id': ref("crm_case_13")}) - id = self.create(cr, uid, {'user_ids': [(6, 0, [ref('base.user_root')])], 'team_id': ref('sales_team.team_sales_department')}, context=context) - self.mass_convert(cr, uid, [id], context=context) -- - Now I check first lead converted on opportunity. -- - !python {model: crm.lead}: | - opp = self.browse(cr, uid, ref('crm_case_13')) - assert opp.name == "Plan to buy 60 keyboards and mouses", "Opportunity name not correct" - assert opp.type == 'opportunity', 'Lead is not converted to opportunity!' - expected_partner = "Will McEncroe" - assert opp.partner_id.name == expected_partner, 'Partner mismatch! %s vs %s' % (opp.partner_id.name, expected_partner) - assert opp.stage_id.id == ref("stage_lead1"), 'Stage of probability is incorrect!' -- - Then check for second lead converted on opportunity. -- - !python {model: crm.lead}: | - opp = self.browse(cr, uid, ref('crm_case_2')) - assert opp.name == "Interest in Your New Software", "Opportunity name not correct" - assert opp.type == 'opportunity', 'Lead is not converted to opportunity!' - assert opp.stage_id.id == ref("stage_lead1"), 'Stage of probability is incorrect!' -- - I loose the second opportunity -- - !python {model: crm.lead}: | - self.case_mark_lost(cr, uid, [ref("crm_case_2")]) -- - I check details of the opportunity after the loose -- - !python {model: crm.lead}: | - lead = self.browse(cr, uid, ref('crm_case_2')) - assert lead.probability == 0.0, "Revenue probability should be 0.0!" -- - I confirm review needs meeting. -- - !python {model: calendar.event}: | - context.update({'active_model': 'calendar.event'}) - self.write(cr, uid, [ref('calendar.calendar_event_4')], {'state': 'open'}) -- - I invite a user for meeting. -- - !python {model: calendar.attendee}: | - meeting_id = self.create(cr, uid, {'partner_id': ref('base.partner_root'), 'email': 'user@meeting.com' }) - self.do_accept(cr, uid, [meeting_id]) diff --git a/addons/crm/test/lead2opportunity_assign_salesmen.yml b/addons/crm/test/lead2opportunity_assign_salesmen.yml deleted file mode 100644 index ddc587e846d..00000000000 --- a/addons/crm/test/lead2opportunity_assign_salesmen.yml +++ /dev/null @@ -1,77 +0,0 @@ -- - 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). -- - !record {model: res.users, id: test_res_user_01}: - name: 'Test user A' - login: 'tua@example.com' -- - !record {model: res.users, id: test_res_user_02}: - name: 'Test user B' - login: 'tub@example.com' -- - !record {model: res.users, id: test_res_user_03}: - name: 'Test user C' - login: 'tuc@example.com' -- - !record {model: res.users, id: test_res_user_04}: - name: 'Test user D' - login: 'tud@example.com' -- - Salesman also creates lead so giving access rights of salesman. -- - !context - uid: 'crm_res_users_salesman' -- - !record {model: crm.lead, id: test_crm_lead_01}: - type: 'lead' - name: 'Test lead 1' - email_from: 'Raoul Grosbedon ' - stage_id: stage_lead1 -- - !record {model: crm.lead, id: test_crm_lead_02}: - type: 'lead' - name: 'Test lead 2' - email_from: 'Raoul Grosbedon ' - stage_id: stage_lead1 -- - !record {model: crm.lead, id: test_crm_lead_03}: - type: 'lead' - name: 'Test lead 3' - email_from: 'Raoul Grosbedon ' - stage_id: stage_lead1 -- - !record {model: crm.lead, id: test_crm_lead_04}: - type: 'lead' - name: 'Test lead 4' - contact_name: 'Fabrice Lepoilu' - stage_id: stage_lead1 -- - !record {model: crm.lead, id: test_crm_lead_05}: - type: 'lead' - name: 'Test lead 5' - contact_name: 'Fabrice Lepoilu' - stage_id: stage_lead1 -- - !record {model: crm.lead, id: test_crm_lead_06}: - type: 'lead' - name: 'Test lead 6' - partner_name: 'Agrolait SuperSeed SA' - stage_id: stage_lead1 -- - Salesman create a mass convert wizard and convert all the leads. -- - !python {model: crm.lead2opportunity.partner.mass}: | - context.update({'active_model': 'crm.lead', 'active_ids': [ref("test_crm_lead_01"), ref("test_crm_lead_02"), ref("test_crm_lead_03"), ref("test_crm_lead_04"), ref("test_crm_lead_05"), ref("test_crm_lead_06")], 'active_id': ref("test_crm_lead_01")}) - id = self.create(cr, uid, {'user_ids': [(6, 0, [ref('test_res_user_01'), ref('test_res_user_02'), ref('test_res_user_03'), ref('test_res_user_04')])], 'team_id': ref('sales_team.team_sales_department'), 'deduplicate': False, 'force_assignation': True}, context=context) - self.mass_convert(cr, uid, [id], context=context) -- - The leads should now be opps with a salesman and a salesteam. Also, salesmen should have been assigned following a round-robin method. -- - !python {model: crm.lead}: | - opps = self.browse(cr, uid, [ref("test_crm_lead_01"), ref("test_crm_lead_02"), ref("test_crm_lead_03"), ref("test_crm_lead_04"), ref("test_crm_lead_05"), ref("test_crm_lead_06")], context) - salesmen_ids = [ref('test_res_user_01'), ref('test_res_user_02'), ref('test_res_user_03'), ref('test_res_user_04')] - i = 0 - for opp in opps: - assert opp.type == 'opportunity', 'Type mismatch: this should be an opp, not a lead' - assert 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 diff --git a/addons/crm/tests/__init__.py b/addons/crm/tests/__init__.py index 69d299aea81..b6e7a816642 100644 --- a/addons/crm/tests/__init__.py +++ b/addons/crm/tests/__init__.py @@ -1,3 +1,5 @@ # -*- coding: utf-8 -*- +import test_crm_lead import test_new_lead_notification +import test_lead2opportunity diff --git a/addons/crm/tests/common.py b/addons/crm/tests/common.py index b59be71bada..7a04e27ddb9 100644 --- a/addons/crm/tests/common.py +++ b/addons/crm/tests/common.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. -from openerp.addons.mail.tests.common import TestMail - +from odoo.tests.common import TransactionCase +from odoo.addons.mail.tests.common import TestMail class TestCrm(TestMail): @@ -19,9 +20,34 @@ class TestCrm(TestMail): 'login': 'riton', 'alias_name': 'riton', 'email': 'riton.salesman_all@example.com', - 'groups_id': [(6, 0, [user_group_employee.id, user_group_salesman_all.id])]}) + 'groups_id': [(6, 0, [user_group_employee.id, user_group_salesman_all.id])] + }) cls.sales_team_1 = cls.env['crm.team'].create({ 'name': 'Test Sales Team', 'alias_name': 'test_sales_team', }) + + +class TestCrmCases(TransactionCase): + + def setUp(self): + super(TestCrmCases, self).setUp() + + # Create a user as 'Crm Salesmanager' and added the `sales manager` group + self.crm_salemanager = self.env['res.users'].create({ + 'company_id': self.env.ref("base.main_company").id, + 'name': "Crm Sales manager", + 'login': "csm", + 'email': "crmmanager@yourcompany.com", + 'groups_id': [(6, 0, [self.ref('sales_team.group_sale_manager')])] + }) + + # Create a user as 'Crm Salesman' and added few groups + self.crm_salesman = self.env['res.users'].create({ + 'company_id': self.env.ref("base.main_company").id, + 'name': "Crm Salesman", + 'login': "csu", + 'email': "crmuser@yourcompany.com", + 'groups_id': [(6, 0, [self.env.ref('sales_team.group_sale_salesman_all_leads').id, self.env.ref('base.group_partner_manager').id])] + }) diff --git a/addons/crm/test/customer_request.eml b/addons/crm/tests/customer_request.eml similarity index 100% rename from addons/crm/test/customer_request.eml rename to addons/crm/tests/customer_request.eml diff --git a/addons/crm/tests/test_crm_lead.py b/addons/crm/tests/test_crm_lead.py new file mode 100644 index 00000000000..7ff20c4ab5e --- /dev/null +++ b/addons/crm/tests/test_crm_lead.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from .common import TestCrmCases +from odoo.modules.module import get_module_resource + + +class TestCRMLead(TestCrmCases): + + def test_crm_lead_cancel(self): + # I set a new sale team giving access rights of salesman. + team = self.env['crm.team'].sudo(self.crm_salemanager.id).create({'name': "Phone Marketing"}) + lead = self.env.ref('crm.crm_case_1') + lead.sudo(self.crm_salemanager.id).write({'team_id': team.id}) + # Salesmananger check unqualified lead + self.assertEqual(lead.stage_id.sequence, 1, 'Lead is in new stage') + + def test_crm_lead_copy(self): + # I make duplicate the Lead + self.env.ref('crm.crm_case_4').copy() + + def test_crm_lead_unlink(self): + # Only Sales manager Unlink the Lead so test with Manager's access rights + self.env.ref('crm.crm_case_4').sudo(self.crm_salemanager.id).unlink() + + def test_find_stage(self): + # I create a new lead + lead = self.env['crm.lead'].create({ + 'type': "lead", + 'name': "Test lead new", + 'partner_id': self.env.ref("base.res_partner_1").id, + 'description': "This is the description of the test new lead.", + 'team_id': self.env.ref("sales_team.team_sales_department").id + }) + # I change type from lead to opportunity + lead.convert_opportunity(self.env.ref("base.res_partner_2").id) + # I check default stage of opportunity + self.assertLessEqual(lead.stage_id.sequence, 1, "Default stage of lead is incorrect!") + + # Now I change the stage of opportunity to won. + lead.action_set_won() + # I check stage of opp should won, after change stage. + stage_id = lead._stage_find(domain=[('probability', '=', 100.0)]) + self.assertEqual(stage_id, lead.stage_id, "Stage of opportunity is incorrect!") + + def test_crm_lead_message(self): + # Give the access rights of Salesman to communicate with customer + # Customer interested in our product, so he sends request by email to get more details. + # Mail script will fetch his request from mail server. Then I process that mail after read EML file. + request_file = open(get_module_resource('crm', 'tests', 'customer_request.eml'), 'rb') + request_message = request_file.read() + self.env['mail.thread'].sudo(self.crm_salesman).message_process('crm.lead', request_message) + + # After getting the mail, I check details of new lead of that customer + lead = self.env['crm.lead'].sudo(self.crm_salesman).search([('email_from', '=', 'Mr. John Right ')], limit=1) + self.assertTrue(lead.ids, 'Fail to create merge opportunity wizard') + self.assertFalse(lead.partner_id, 'Customer should be a new one') + self.assertEqual(lead.name, 'Fournir votre devis avec le meilleur prix.', 'Subject does not match') + + # I reply his request with welcome message. + # TODO revert mail.mail to mail.compose.message (conversion to customer should be automatic). + lead = self.env['crm.lead'].search([('email_from', '=', 'Mr. John Right ')], limit=1) + mail = self.env['mail.compose.message'].with_context(active_model='crm.lead', active_id=lead.id).create({ + 'body': "Merci de votre intérêt pour notre produit, nous vous contacterons bientôt. Bien à vous", + 'email_from': 'sales@mycompany.com' + }) + try: + mail.send_mail() + except: + pass + + # Now, I convert him into customer and put him into regular customer list + lead = self.env['crm.lead'].search([('email_from', '=', 'Mr. John Right ')], limit=1) + lead.handle_partner_assignation() + + def test_crm_lead_merge(self): + # During a mixed merge (involving leads and opps), data should be handled a certain way following their type (m2o, m2m, text, ...) Start by creating two leads and an opp and giving the rights of Sales manager. + default_stage_id = self.ref("crm.stage_lead1") + LeadSalesmanager = self.env['crm.lead'].sudo(self.crm_salemanager.id) + + # TEST CASE 1 + test_crm_opp_01 = LeadSalesmanager.create({ + 'type': 'opportunity', + 'name': 'Test opportunity 1', + 'partner_id': self.env.ref("base.res_partner_3").id, + 'stage_id': default_stage_id, + 'description': 'This is the description of the test opp 1.' + }) + + test_crm_lead_01 = LeadSalesmanager.create({ + 'type': 'lead', + 'name': 'Test lead first', + 'partner_id': self.env.ref("base.res_partner_1").id, + 'stage_id': default_stage_id, + 'description': 'This is the description of the test lead first.' + }) + + test_crm_lead_02 = LeadSalesmanager.create({ + 'type': 'lead', + 'name': 'Test lead second', + 'partner_id': self.env.ref("base.res_partner_1").id, + 'stage_id': default_stage_id, + 'description': 'This is the description of the test lead second.' + }) + + lead_ids = [test_crm_opp_01.id, test_crm_lead_01.id, test_crm_lead_02.id] + additionnal_context = {'active_model': 'crm.lead', 'active_ids': lead_ids, 'active_id': lead_ids[0]} + + # I create a merge wizard and merge the leads and opp together in the first item of the list. + merge_opp_wizard_01 = self.env['crm.merge.opportunity'].sudo(self.crm_salemanager.id).with_context(**additionnal_context).create({}) + merge_opp_wizard_01.action_merge() + + # I check for the resulting merged opp (based on name and partner) + merged_lead = self.env['crm.lead'].search([('name', '=', 'Test opportunity 1'), ('partner_id', '=', self.env.ref("base.res_partner_3").id)], limit=1) + self.assertTrue(merged_lead, 'Fail to create merge opportunity wizard') + self.assertEqual(merged_lead.description, 'This is the description of the test opp 1.\n\nThis is the description of the test lead first.\n\nThis is the description of the test lead second.', 'Description mismatch: when merging leads/opps with different text values, these values should get concatenated and separated with line returns') + self.assertEqual(merged_lead.type, 'opportunity', 'Type mismatch: when at least one opp in involved in the merge, the result should be a new opp (instead of %s)' % merged_lead.type) + + # The other (tailing) leads/opps shouldn't exist anymore + self.assertFalse(test_crm_lead_01.exists(), 'This tailing lead (id %s) should not exist anymore' % test_crm_lead_02.id) + self.assertFalse(test_crm_lead_02.exists(), 'This tailing opp (id %s) should not exist anymore' % test_crm_opp_01.id) + + # TEST CASE 2 + # I want to test leads merge. Start by creating two leads (with the same partner) + test_crm_lead_03 = LeadSalesmanager.create({ + 'type': 'lead', + 'name': 'Test lead 3', + 'partner_id': self.env.ref("base.res_partner_1").id, + 'stage_id': default_stage_id + }) + + test_crm_lead_04 = LeadSalesmanager.create({ + 'type': 'lead', + 'name': 'Test lead 4', + 'partner_id': self.env.ref("base.res_partner_1").id, + 'stage_id': default_stage_id + }) + + lead_ids = [test_crm_lead_03.id, test_crm_lead_04.id] + additionnal_context = {'active_model': 'crm.lead', 'active_ids': lead_ids, 'active_id': lead_ids[0]} + + # I create a merge wizard and merge the leads together. + merge_opp_wizard_02 = self.env['crm.merge.opportunity'].sudo(self.crm_salemanager.id).with_context(**additionnal_context).create({}) + merge_opp_wizard_02.action_merge() + + # I check for the resulting merged lead (based on name and partner) + merged_lead = self.env['crm.lead'].search([('name', '=', 'Test lead 3'), ('partner_id', '=', self.env.ref("base.res_partner_1").id)], limit=1) + self.assertTrue(merged_lead, 'Fail to create merge opportunity wizard') + self.assertEqual(merged_lead.partner_id.id, self.env.ref("base.res_partner_1").id, 'Partner mismatch') + self.assertEqual(merged_lead.type, 'lead', 'Type mismatch: when leads get merged together, the result should be a new lead (instead of %s)' % merged_lead.type) + self.assertFalse(test_crm_lead_04.exists(), 'This tailing lead (id %s) should not exist anymore' % test_crm_lead_04.id) + + # TEST CASE 3 + # I want to test opps merge. Start by creating two opportunities (with the same partner). + test_crm_opp_02 = LeadSalesmanager.create({ + 'type': 'opportunity', + 'name': 'Test opportunity 2', + 'partner_id': self.env.ref("base.res_partner_3").id, + 'stage_id': default_stage_id + }) + + test_crm_opp_03 = LeadSalesmanager.create({ + 'type': 'opportunity', + 'name': 'Test opportunity 3', + 'partner_id': self.env.ref("base.res_partner_3").id, + 'stage_id': default_stage_id + }) + + opportunity_ids = [test_crm_opp_02.id, test_crm_opp_03.id] + additionnal_context = {'active_model': 'crm.lead', 'active_ids': opportunity_ids, 'active_id': opportunity_ids[0]} + + # I create a merge wizard and merge the opps together. + merge_opp_wizard_03 = self.env['crm.merge.opportunity'].sudo(self.crm_salemanager.id).with_context(**additionnal_context).create({}) + merge_opp_wizard_03.action_merge() + + merged_opportunity = self.env['crm.lead'].search([('name', '=', 'Test opportunity 2'), ('partner_id', '=', self.env.ref("base.res_partner_3").id)], limit=1) + self.assertTrue(merged_opportunity, 'Fail to create merge opportunity wizard') + self.assertEqual(merged_opportunity.partner_id.id, self.env.ref("base.res_partner_3").id, 'Partner mismatch') + self.assertEqual(merged_opportunity.type, 'opportunity', 'Type mismatch: when opps get merged together, the result should be a new opp (instead of %s)' % merged_opportunity.type) + self.assertFalse(test_crm_opp_03.exists(), 'This tailing opp (id %s) should not exist anymore' % test_crm_opp_03.id) diff --git a/addons/crm/tests/test_lead2opportunity.py b/addons/crm/tests/test_lead2opportunity.py new file mode 100644 index 00000000000..d69e58e7fb9 --- /dev/null +++ b/addons/crm/tests/test_lead2opportunity.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- + +from .common import TestCrmCases + + +class TestLead2opportunity2win(TestCrmCases): + + def test_lead2opportunity2win(self): + """ Tests for Test Lead 2 opportunity 2 win """ + CrmLead2OpportunityPartnerMass = self.env['crm.lead2opportunity.partner.mass'] + CalendarAttendee = self.env['calendar.attendee'] + default_stage_id = self.ref("crm.stage_lead1") + + crm_case_2 = self.env.ref('crm.crm_case_2') + crm_case_3 = self.env.ref('crm.crm_case_3') + crm_case_13 = self.env.ref('crm.crm_case_13') + + # 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.sudo(self.crm_salemanager.id).convert_opportunity(self.env.ref("base.res_partner_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.env.ref("base.res_partner_2").id, 'Partner mismatch!') + self.assertEqual(crm_case_3.stage_id.id, default_stage_id, 'Stage of opportunity is incorrect!') + + # Now I schedule meeting with customer. + crm_case_3.action_schedule_meeting() + + # After communicated with customer, I put some notes with contract details. + crm_case_3.message_post(subject='Test note', body='Détails envoyés par le client sur ​​le FAX pour la qualité') + + # I convert mass lead into opportunity customer. + mass = CrmLead2OpportunityPartnerMass.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.sudo(self.crm_salemanager.id).mass_convert() + + # Now I check first lead converted on opportunity. + self.assertEqual(crm_case_13.name, "Plan to buy 60 keyboards and mouses", "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, "Interest in Your New 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.case_mark_lost() + + # I check details of the opportunity after the loose + self.assertEqual(crm_case_2.probability, 0.0, "Revenue probability should be 0.0!") + + # I confirm review needs meeting. + self.env.ref('calendar.calendar_event_4').with_context({'active_model': 'calendar.event'}).write({'state': 'open'}) + + # I invite a user for meeting. + CalendarAttendee.create({'partner_id': self.ref('base.partner_root'), 'email': 'user@meeting.com'}).do_accept() + + def test_lead2opportunity_assign_salesmen(self): + """ Tests for Test Lead2opportunity Assign Salesmen """ + CrmLead2OpportunityPartnerMass = self.env['crm.lead2opportunity.partner.mass'] + LeadSaleman = self.env['crm.lead'].sudo(self.crm_salesman.id) + default_stage_id = self.ref("crm.stage_lead1") + + # 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', + 'new_password': 'tua' + }) + test_res_user_02 = self.env['res.users'].create({ + 'name': 'Test user B', + 'login': 'tub@example.com', + 'new_password': 'tub' + }) + test_res_user_03 = self.env['res.users'].create({ + 'name': 'Test user C', + 'login': 'tuc@example.com', + 'new_password': 'tuc' + }) + test_res_user_04 = self.env['res.users'].create({ + 'name': 'Test user D', + 'login': 'tud@example.com', + 'new_password': 'tud' + }) + + # 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 ', + 'stage_id': default_stage_id + }) + test_crm_lead_02 = LeadSaleman.create({ + 'type': 'lead', + 'name': 'Test lead 2', + 'email_from': 'Raoul Grosbedon ', + 'stage_id': default_stage_id + }) + test_crm_lead_03 = LeadSaleman.create({ + 'type': 'lead', + 'name': 'Test lead 3', + 'email_from': 'Raoul Grosbedon ', + '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. + additionnal_context = {'active_model': 'crm.lead', 'active_ids': lead_ids, 'active_id': test_crm_lead_01.id} + mass = CrmLead2OpportunityPartnerMass.sudo(self.crm_salesman.id).with_context(**additionnal_context).create({ + 'user_ids': [(6, 0, salesmen_ids)], + 'team_id': self.env.ref("sales_team.team_sales_department").id, + 'deduplicate': False, + 'force_assignation': True + }) + mass.sudo(self.crm_salesman.id).mass_convert() + + # 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'].sudo(self.crm_salesman.id).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 diff --git a/addons/crm/tests/test_new_lead_notification.py b/addons/crm/tests/test_new_lead_notification.py index 36c28767acb..819a3e70a2a 100644 --- a/addons/crm/tests/test_new_lead_notification.py +++ b/addons/crm/tests/test_new_lead_notification.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. from .common import TestCrm