diff options
| author | Thibault Delavallée <tde@odoo.com> | 2020-03-16 09:57:52 +0000 |
|---|---|---|
| committer | Thibault Delavallée <tde@odoo.com> | 2020-03-23 11:42:11 +0000 |
| commit | 03afd0f2a1a2bdfc8c50052eb88524f37e1e7e13 (patch) | |
| tree | 4ec5a4bdc9cad52c65da354506e68008a7726231 /addons | |
| parent | d8b6b35cb3c75b5c503b5b147fb8dd0e36e4ecfa (diff) | |
[REF] crm: improve context use and naming of fields in convert wizards
SPECIFICATIONS 1: FORCE_ASSIGNATION
Move and rename force_assignation in convert wizard. Purpose is to move the
force_assignation field from mass convert wizard to its base convert wizard
used through _inherit. It allows to avoid relying on context propagation in
some methods. This field is also renamed as assignation as other meaning in
English.
SPECIFICATIONS 2: OPPORTUNITY_IDS
Improve search of duplicate by always ensuring duplicated are computed using
active_test. Also add the active_test on the field as otherwise computed
results are actually not visible to the user.
Generic opportunity_ids field is also renamed to better indicated it is used
to store duplicates and avoid thinking it holds data related to batch convert
or merge.
LINKS
Task ID 2088565 (crm: from onchange to compute)
Upgrade PR odoo/upgrade#781
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/crm/models/crm_lead.py | 15 | ||||
| -rw-r--r-- | addons/crm/tests/test_crm_lead_convert.py | 25 | ||||
| -rw-r--r-- | addons/crm/wizard/crm_lead_to_opportunity.py | 27 | ||||
| -rw-r--r-- | addons/crm/wizard/crm_lead_to_opportunity_mass.py | 12 | ||||
| -rw-r--r-- | addons/crm/wizard/crm_lead_to_opportunity_mass_views.xml | 6 | ||||
| -rw-r--r-- | addons/crm/wizard/crm_lead_to_opportunity_views.xml | 2 |
6 files changed, 45 insertions, 42 deletions
diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index 189c651fbe2..b25e2fc7c73 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -912,9 +912,9 @@ class Lead(models.Model): :param partner : optional customer when searching duplicated :param email: email (possibly formatted) to search - :param boolean include_lost: if True, search for archived leads or - active opportunities. If False, search for active and not won leads - and opportunities; + :param boolean include_lost: if True, search includes archived opportunities + (still only active leads are considered). If False, search for active + and not won leads and opportunities; """ if not email: return self.env['crm.lead'] @@ -927,11 +927,12 @@ class Lead(models.Model): if not partner_match_domain: return self.env['crm.lead'] domain = partner_match_domain - if not include_lost: - domain += ['&', ('active', '=', True), ('probability', '<', 100)] + if include_lost: + domain += ['|', ('type', '=', 'opportunity'), ('active', '=', True)] else: - domain += ['|', '&', ('type', '=', 'lead'), ('active', '=', True), ('type', '=', 'opportunity')] - return self.search(domain) + domain += ['&', ('active', '=', True), ('probability', '<', 100)] + + return self.with_context(active_test=False).search(domain) def _create_customer(self): """ Create a partner from lead data and link it to the lead. diff --git a/addons/crm/tests/test_crm_lead_convert.py b/addons/crm/tests/test_crm_lead_convert.py index d12cb4e5ab2..382d0a00055 100644 --- a/addons/crm/tests/test_crm_lead_convert.py +++ b/addons/crm/tests/test_crm_lead_convert.py @@ -231,7 +231,7 @@ class TestLeadConvert(crm_common.TestLeadConvertCommon): }).create({}) # test internals of convert wizard - self.assertEqual(convert.opportunity_ids, self.lead_1 | leads) + self.assertEqual(convert.duplicated_lead_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) @@ -263,8 +263,8 @@ class TestLeadConvert(crm_common.TestLeadConvertCommon): }).create({}) self.assertEqual(convert.partner_id, self.customer) # TDE FIXME: should not give priority to partner email if it is void - # self.assertEqual(convert.opportunity_ids, self.lead_1 | lead_email_from | lead_email_normalized | lead_partner) - self.assertEqual(convert.opportunity_ids, self.env['crm.lead']) + # self.assertEqual(convert.duplicated_lead_ids, self.lead_1 | lead_email_from | lead_email_normalized | lead_partner) + self.assertEqual(convert.duplicated_lead_ids, self.env['crm.lead']) # Check: partner fallbacks self.lead_1.write({ @@ -278,9 +278,9 @@ class TestLeadConvert(crm_common.TestLeadConvertCommon): 'active_ids': self.lead_1.ids, }).create({}) self.assertEqual(convert.partner_id, self.customer) - # TDE FIXME: CHECKME: 2917b38f28d5c2d6c53c706e613da7b8e2ad7b52 - # self.assertEqual(convert.opportunity_ids, self.lead_1 | lead_partner) - self.assertEqual(convert.opportunity_ids, self.env['crm.lead']) + # TDE FIXME: CHECKME: 2917b38f28d5c2d6c53c706e613da7b8e2ad7b52 for lead without email + # self.assertEqual(convert.duplicated_lead_ids, self.lead_1 | lead_partner) + self.assertEqual(convert.duplicated_lead_ids, self.env['crm.lead']) @users('user_sales_manager') def test_lead_merge_duplicates_flow(self): @@ -299,9 +299,8 @@ class TestLeadConvert(crm_common.TestLeadConvertCommon): }).create({}) self.assertEqual(convert.partner_id, self.customer) # TDE FIXME: should check for email_normalized -> lead_email_normalized not correctly found - # self.assertEqual(convert.opportunity_ids, self.lead_1 | lead_email_from | lead_email_normalized | lead_partner | opp_lost) - # TDE FIXME: add a active test context on opportunity_ids fields - self.assertEqual(convert.with_context(active_test=False).opportunity_ids, self.lead_1 | self.lead_email_from | self.lead_partner | self.opp_lost) + # 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) convert.action_apply() self.assertEqual( @@ -421,7 +420,7 @@ class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon): }).create({ 'deduplicate': False, 'user_id': self.user_sales_salesman.id, - 'force_assignation': False, + 'force_assignment': False, }) mass_convert.onchange_action() mass_convert._onchange_user() @@ -463,7 +462,7 @@ class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon): # self.assertEqual(self.lead_w_email_lost.partner_id, self.env['res.partner']) def test_mass_convert_deduplicate(self): - """ Test opportunity_ids fields having another behavior in mass convert + """ 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) @@ -483,7 +482,7 @@ class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon): mass_convert._onchange_deduplicate() self.assertEqual(mass_convert.action, 'each_exist_or_create') self.assertEqual(mass_convert.name, 'convert') - self.assertEqual(mass_convert.opportunity_ids, self.lead_1 | self.lead_w_partner) + self.assertEqual(mass_convert.duplicated_lead_ids, self.lead_1 | self.lead_w_partner) mass_convert.action_mass_convert() @@ -508,7 +507,7 @@ class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon): }).create({ 'deduplicate': False, 'user_ids': self.assign_users.ids, - 'force_assignation': True, + 'force_assignment': True, }) # TDE FIXME: what happens if we mix people from different sales team ? currently nothing, to check diff --git a/addons/crm/wizard/crm_lead_to_opportunity.py b/addons/crm/wizard/crm_lead_to_opportunity.py index 22385dabe85..b66ccf3e802 100644 --- a/addons/crm/wizard/crm_lead_to_opportunity.py +++ b/addons/crm/wizard/crm_lead_to_opportunity.py @@ -12,7 +12,7 @@ class Lead2OpportunityPartner(models.TransientModel): @api.model def default_get(self, fields): - """ Default get for name, opportunity_ids. + """ Default get for name, duplicated_lead_ids. If there is an exisitng partner link to the lead, find all existing opportunities links with this partner to merge all information together """ @@ -34,8 +34,8 @@ class Lead2OpportunityPartner(models.TransientModel): result['partner_id'] = partner.id if 'name' in fields: result['name'] = 'merge' if len(tomerge) >= 2 else 'convert' - if 'opportunity_ids' in fields and len(tomerge) >= 2: - result['opportunity_ids'] = list(tomerge) + if 'duplicated_lead_ids' in fields and len(tomerge) >= 2: + result['duplicated_lead_ids'] = list(tomerge) if lead.user_id: result['user_id'] = lead.user_id.id if lead.team_id: @@ -55,10 +55,14 @@ class Lead2OpportunityPartner(models.TransientModel): ('nothing', 'Do not link to a customer') ], string='Related Customer', required=True) lead_id = fields.Many2one('crm.lead', "Associated Lead") - opportunity_ids = fields.Many2many('crm.lead', string='Opportunities') + duplicated_lead_ids = fields.Many2many( + 'crm.lead', string='Duplicates', context={'active_test': False}) partner_id = fields.Many2one('res.partner', 'Customer') user_id = fields.Many2one('res.users', 'Salesperson') team_id = fields.Many2one('crm.team', 'Sales Team') + force_assignment = fields.Boolean( + 'Force assignment', default=True, + help='If checked, forces salesman to be updated on updated opportunities even if already set.') @api.onchange('action') def onchange_action(self): @@ -99,17 +103,18 @@ class Lead2OpportunityPartner(models.TransientModel): return result_opportunity.redirect_lead_opportunity_view() def _action_merge(self): - result_opportunity = self.with_context(active_test=False).opportunity_ids.merge_opportunity() + result_opportunity = self.duplicated_lead_ids.merge_opportunity() if not result_opportunity.active: result_opportunity.write({'active': True, 'activity_type_id': False, 'lost_reason': False}) if result_opportunity.type == "lead": self._convert_and_allocate(result_opportunity, [self.user_id.id], team_id=self.team_id.id) - elif not self._context.get('no_force_assignation') or not result_opportunity.user_id: - result_opportunity.write({ - 'user_id': self.user_id.id, - 'team_id': self.team_id.id, - }) + else: + if not result_opportunity.user_id or self.force_assignment: + result_opportunity.write({ + 'user_id': self.user_id.id, + 'team_id': self.team_id.id, + }) return result_opportunity def _action_convert(self): @@ -129,7 +134,7 @@ class Lead2OpportunityPartner(models.TransientModel): lead.convert_opportunity(lead.partner_id.id, [], False) leads_to_allocate = leads - if self._context.get('no_force_assignation'): + if not self.force_assignment: leads_to_allocate = leads_to_allocate.filtered(lambda lead: not lead.user_id) if user_ids: diff --git a/addons/crm/wizard/crm_lead_to_opportunity_mass.py b/addons/crm/wizard/crm_lead_to_opportunity_mass.py index a10ef43f31a..ce1e2a0b766 100644 --- a/addons/crm/wizard/crm_lead_to_opportunity_mass.py +++ b/addons/crm/wizard/crm_lead_to_opportunity_mass.py @@ -5,7 +5,6 @@ from odoo import api, fields, models class Lead2OpportunityMassConvert(models.TransientModel): - _name = 'crm.lead2opportunity.partner.mass' _description = 'Convert Lead to Opportunity (in mass)' _inherit = 'crm.lead2opportunity.partner' @@ -19,8 +18,8 @@ class Lead2OpportunityMassConvert(models.TransientModel): res['action'] = 'each_exist_or_create' if 'name' in fields: res['name'] = 'convert' - if 'opportunity_ids' in fields: - res['opportunity_ids'] = False + if 'duplicated_lead_ids' in fields: + res['duplicated_lead_ids'] = False return res user_ids = fields.Many2many('res.users', string='Salesmen') @@ -29,7 +28,7 @@ class Lead2OpportunityMassConvert(models.TransientModel): action = fields.Selection(selection_add=[ ('each_exist_or_create', 'Use existing partner or create'), ], string='Related Customer', required=True) - force_assignation = fields.Boolean('Force assignment', help='If unchecked, this will leave the salesman of duplicated opportunities') + force_assignment = fields.Boolean(default=False) @api.onchange('action') def _onchange_action(self): @@ -52,7 +51,7 @@ class Lead2OpportunityMassConvert(models.TransientModel): if len(partners_duplicated_leads.get(lead_tuple, [])) > 1: leads_with_duplicates.append(lead.id) - self.opportunity_ids = self.env['crm.lead'].browse(leads_with_duplicates) + self.duplicated_lead_ids = self.env['crm.lead'].browse(leads_with_duplicates) def _convert_and_allocate(self, leads, user_ids, team_id=False): """ When "massively" (more than one at a time) converting leads to @@ -87,8 +86,7 @@ class Lead2OpportunityMassConvert(models.TransientModel): active_ids = (active_ids - merged_lead_ids) | remaining_lead_ids self = self.with_context(active_ids=list(active_ids)) # only update active_ids when there are set - no_force_assignation = self._context.get('no_force_assignation', not self.force_assignation) - return self.with_context(no_force_assignation=no_force_assignation).action_apply() + return self.action_apply() def _convert_handle_partner(self, lead, action, partner_id): if self.action == 'each_exist_or_create': diff --git a/addons/crm/wizard/crm_lead_to_opportunity_mass_views.xml b/addons/crm/wizard/crm_lead_to_opportunity_mass_views.xml index f5d3b4a4f1b..0d0911df92b 100644 --- a/addons/crm/wizard/crm_lead_to_opportunity_mass_views.xml +++ b/addons/crm/wizard/crm_lead_to_opportunity_mass_views.xml @@ -13,11 +13,11 @@ <group string="Assign these opportunities to"> <field name="team_id" kanban_view_ref="%(sales_team.crm_team_view_kanban)s"/> <field name="user_ids" widget="many2many_tags" domain="[('share', '=', False)]"/> - <field name="force_assignation"/> + <field name="force_assignment"/> </group> - <label for="opportunity_ids" string="Leads with existing duplicates (for information)" help="Leads that you selected that have duplicates. If the list is empty, it means that no duplicates were found" attrs="{'invisible': [('deduplicate', '=', False)]}"/> + <label for="duplicated_lead_ids" string="Leads with existing duplicates (for information)" help="Leads that you selected that have duplicates. If the list is empty, it means that no duplicates were found" attrs="{'invisible': [('deduplicate', '=', False)]}"/> <group attrs="{'invisible': [('deduplicate', '=', False)]}"> - <field name="opportunity_ids" colspan="4" nolabel="1" readonly="1"> + <field name="duplicated_lead_ids" colspan="4" nolabel="1" readonly="1"> <tree create="false" delete="false"> <field name="create_date" widget="date"/> <field name="name"/> diff --git a/addons/crm/wizard/crm_lead_to_opportunity_views.xml b/addons/crm/wizard/crm_lead_to_opportunity_views.xml index 6871a97baca..4534e4352cd 100644 --- a/addons/crm/wizard/crm_lead_to_opportunity_views.xml +++ b/addons/crm/wizard/crm_lead_to_opportunity_views.xml @@ -13,7 +13,7 @@ <field name="team_id" widget="selection"/> </group> <group string="Opportunities" attrs="{'invisible': [('name', '!=', 'merge')]}"> - <field name="opportunity_ids" nolabel="1"> + <field name="duplicated_lead_ids" nolabel="1"> <tree> <field name="create_date" widget="date"/> <field name="name"/> |
