[REF] crm(_*): improve code of methods used in lead/opp convert/merge wizards

PURPOSE

As CRM is going to be updated (onchange -> compute, code improvements, better
management of sales teams) cleaning and improving code is a necessary first
step.

SPECIFICATIONS

Purpose of this commit is to rewrite code located and/or used in convert or
merge wizards. Indeed it holds unnecessary variables, dictionaries manipulation
that hides the real business flow, badly named variables, unclear methods, ...
Logic of those wizards seem quite simple but is hidden behind a wall of
bloated code.

Notably for wizards

  * try to set explicit arguments in methods;
  * less use of context values, replaced by arguments when possible;
  * try to make better use of lead2opportunity wizard in its mass wizard that
    inherit from it, notably by correctly calling super;

Notably for tools

  * ``get_duplicated_leads`` was just a shortcut to ``_get_duplicated_leads_by
    _emails``;
  * ``_get_duplicated_leads_by_emails`` is renamed to ``_get_lead_duplicates``
    because email is not the only way of finding duplicates;
  * try to make better use of record sets instead of propagating ids, notably
    for partner. For example input of ``_get_lead_duplicates`` or output of
    ``_find_matching_partner``;
  * ``_create_lead_partner`` rename to ``_create_customer``, and its sub
    method ``_create_lead_partner_data`` to ``_prepare_customer_values``;
  * ``handle_partner_assignation`` was difficult as its use is not documented
    and its docstring was not updated. Parameter have been renamed to be more
    explicit about what it does. Method is renamed to ``handle_partner_
    assignment`` as assignation has other meaning in English;
  * ``allocate_salesman`` is renamed to ``handle_salesmen_assignment`` to match
    the partner assignement and code is slightly cleaned;

No functional change should occur with this commit. Tests have been gradually
added to try to ensure behavior does not change.

LINKS

Task ID 2088565 (crm: from onchange to compute)
This commit is contained in:
Thibault Delavallée
2020-03-23 11:42:11 +00:00
parent 8b94dc17bf
commit d8b6b35cb3
9 changed files with 177 additions and 220 deletions
+90 -116
View File
@@ -870,34 +870,6 @@ class Lead(models.Model):
return self.sorted(key=opps_key, reverse=reverse)
def get_duplicated_leads(self, partner_id, include_lost=False):
""" Search for opportunities that have the same partner and that arent done or cancelled
:param partner_id : partner to search
"""
self.ensure_one()
email = self.partner_id.email or self.email_from
return self._get_duplicated_leads_by_emails(partner_id, email, include_lost=include_lost)
@api.model
def _get_duplicated_leads_by_emails(self, partner_id, email, include_lost=False):
""" Search for opportunities that have the same partner and that arent done or cancelled """
if not email:
return self.env['crm.lead']
partner_match_domain = []
for email in set(email_split(email) + [email]):
partner_match_domain.append(('email_from', '=ilike', email))
if partner_id:
partner_match_domain.append(('partner_id', '=', partner_id))
partner_match_domain = ['|'] * (len(partner_match_domain) - 1) + partner_match_domain
if not partner_match_domain:
return self.env['crm.lead']
domain = partner_match_domain
if not include_lost:
domain += ['&', ('active', '=', True), ('probability', '<', 100)]
else:
domain += ['|', '&', ('type', '=', 'lead'), ('active', '=', True), ('type', '=', 'opportunity')]
return self.search(domain)
def _convert_opportunity_data(self, customer, team_id=False):
""" Extract the data from a lead to create the opportunity
:param customer : res.partner record
@@ -931,11 +903,61 @@ class Lead(models.Model):
lead.write(vals)
if user_ids or team_id:
self.allocate_salesman(user_ids, team_id)
self.handle_salesmen_assignment(user_ids, team_id)
return True
def _create_lead_partner_data(self, partner_name, is_company=False, parent_id=False):
def _get_lead_duplicates(self, partner=None, email=None, include_lost=False):
""" Search for leads that seem duplicated based on partner / email.
: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;
"""
if not email:
return self.env['crm.lead']
partner_match_domain = []
for email in set(email_split(email) + [email]):
partner_match_domain.append(('email_from', '=ilike', email))
if partner:
partner_match_domain.append(('partner_id', '=', partner.id))
partner_match_domain = ['|'] * (len(partner_match_domain) - 1) + partner_match_domain
if not partner_match_domain:
return self.env['crm.lead']
domain = partner_match_domain
if not include_lost:
domain += ['&', ('active', '=', True), ('probability', '<', 100)]
else:
domain += ['|', '&', ('type', '=', 'lead'), ('active', '=', True), ('type', '=', 'opportunity')]
return self.search(domain)
def _create_customer(self):
""" Create a partner from lead data and link it to the lead.
:return: newly-created partner browse record
"""
Partner = self.env['res.partner']
contact_name = self.contact_name
if not contact_name:
contact_name = Partner._parse_partner_name(self.email_from)[0] if self.email_from else False
if self.partner_name:
partner_company = Partner.create(self._prepare_customer_values(self.partner_name, is_company=True))
elif self.partner_id:
partner_company = self.partner_id
else:
partner_company = None
if contact_name:
return Partner.create(self._prepare_customer_values(contact_name, is_company=False, parent_id=partner_company.id if partner_company else False))
if partner_company:
return partner_company
return Partner.create(self._prepare_customer_values(self.name, is_company=False))
def _prepare_customer_values(self, partner_name, is_company=False, parent_id=False):
""" Extract data from lead to create a partner.
:param name : furtur name of the partner
@@ -967,107 +989,59 @@ class Lead(models.Model):
'type': 'contact'
}
def _create_lead_partner(self):
""" Create a partner from lead data
:returns res.partner record
"""
Partner = self.env['res.partner']
contact_name = self.contact_name
if not contact_name:
contact_name = Partner._parse_partner_name(self.email_from)[0] if self.email_from else False
if self.partner_name:
partner_company = Partner.create(self._create_lead_partner_data(self.partner_name, is_company=True))
elif self.partner_id:
partner_company = self.partner_id
else:
partner_company = None
if contact_name:
return Partner.create(self._create_lead_partner_data(contact_name, is_company=False, parent_id=partner_company.id if partner_company else False))
if partner_company:
return partner_company
return Partner.create(self._create_lead_partner_data(self.name, is_company=False))
def _find_matching_partner(self):
""" Try to find a matching partner with available information on the Lead.
Like the customer's name, email, phone number, etc.
:return int partner_id if any, False otherwise
""" Try to find a matching partner with available information on the
lead, using notably customer's name, email, phone, ...
:return: partner browse record
"""
self.ensure_one()
partner = self.partner_id
# find the best matching partner
Partner = self.env['res.partner']
if self.partner_id: # a partner is set already
return self.partner_id.id
if not partner and self.email_from:
partner = self.env['res.partner'].search([('email', '=', self.email_from)], limit=1)
if self.email_from: # search through the existing partners based on the lead's email
return Partner.search([('email', '=', self.email_from)], limit=1).id
if not partner:
# search through the existing partners based on the lead's partner or contact name
# to be aligned with _create_customer, search on lead's name as last possibility
for customer_potential_name in [self[field_name] for field_name in ['partner_name', 'contact_name', 'name'] if self[field_name]]:
partner = self.env['res.partner'].search([('name', 'ilike', '%' + customer_potential_name + '%')], limit=1)
if partner:
break
search_criteria = False
if self.partner_name: # search through the existing partners based on the lead's partner or contact name
search_criteria = self.partner_name
elif self.contact_name:
search_criteria = self.contact_name
elif self.name: # to be aligned with _create_lead_partner, search on lead's name as last possibility
search_criteria = self.name
return partner
if search_criteria:
return Partner.search([('name', 'ilike', '%' + search_criteria + '%')], limit=1).id
def handle_partner_assignment(self, force_partner_id=False, create_missing=True):
""" Update customer (partner_id) of leads. Purpose is to set the same
partner on most leads; either through a newly created partner either
through a given partner_id.
return False
def handle_partner_assignation(self, action='create', partner_id=False):
""" Handle partner assignation during a lead conversion.
If action is 'create', create new partner with contact and assign lead to
new partner_id. Otherwise assign lead to the specified partner_id
TDE FIXME: docstring does not match code... code seems a bit random.
:param string action: what has to be done regarding partners (create it, assign an existing one, or nothing)
:param int partner_id: partner to assign if any
:return: dict(lead_id: partner_id)
:param int force_partner_id: if set, update all leads to that customer;
:param create_missing: for leads without customer, create a new one
based on lead information;
"""
partner_ids = {}
for lead in self:
if partner_id:
lead.partner_id = partner_id
if lead.partner_id:
partner_ids[lead.id] = lead.partner_id.id
continue
if action == 'create':
partner = lead._create_lead_partner()
partner_id = partner.id
partner.team_id = lead.team_id
partner_ids[lead.id] = partner_id
return partner_ids
if force_partner_id:
lead.partner_id = force_partner_id
if not lead.partner_id and create_missing:
partner = lead._create_customer()
lead.partner_id = partner.id
def allocate_salesman(self, user_ids=None, team_id=False):
def handle_salesmen_assignment(self, user_ids=None, team_id=False):
""" Assign salesmen and salesteam to a batch of leads. If there are more
leads than salesmen, these salesmen will be assigned in round-robin.
E.g.: 4 salesmen (S1, S2, S3, S4) for 6 leads (L1, L2, ... L6). They
will be assigned as followed: L1 - S1, L2 - S2, L3 - S3, L4 - S4,
L5 - S1, L6 - S2.
leads than salesmen, these salesmen will be assigned in round-robin. E.g.
4 salesmen (S1, S2, S3, S4) for 6 leads (L1, L2, ... L6) will assigned as
following: L1 - S1, L2 - S2, L3 - S3, L4 - S4, L5 - S1, L6 - S2.
:param list ids: leads/opportunities ids to process
:param list user_ids: salesmen to assign
:param int team_id: salesteam to assign
:return bool
:param list user_ids: salesmen to assign
:param int team_id: salesteam to assign
"""
index = 0
for lead in self:
value = {}
if team_id:
value['team_id'] = team_id
update_vals = {'team_id': team_id} if team_id else {}
for index, lead in enumerate(self):
if user_ids:
value['user_id'] = user_ids[index]
# Cycle through user_ids
index = (index + 1) % len(user_ids)
if value:
lead.write(value)
return True
update_vals['user_id'] = user_ids[index % len(user_ids)]
if update_vals:
lead.write(update_vals)
# ------------------------------------------------------------
# TOOLS
+3 -4
View File
@@ -78,7 +78,6 @@ class TestCRMLead(TestCrmCommon):
subtype_xmlid='mail.mt_comment')
self.assertEqual(message.author_id, self.user_sales_manager.partner_id)
new_partner_id = new_lead.handle_partner_assignation(action='create')[new_lead.id]
new_partner = self.env['res.partner'].with_user(self.user_sales_manager).browse(new_partner_id)
self.assertEqual(new_partner.email, 'unknown.sender@test.example.com')
self.assertEqual(new_partner.team_id, self.sales_team_1)
new_lead.handle_partner_assignment(create_missing=True)
self.assertEqual(new_lead.partner_id.email, 'unknown.sender@test.example.com')
self.assertEqual(new_lead.partner_id.team_id, self.sales_team_1)
+10 -6
View File
@@ -8,6 +8,10 @@ from odoo.tests.common import tagged, users
@tagged('lead_manage')
class TestLeadConvert(crm_common.TestLeadConvertCommon):
"""
TODO: created partner (handle assignation) has team of lead
TODO: create partner has user_id coming from wizard
"""
@classmethod
def setUpClass(cls):
@@ -244,7 +248,7 @@ class TestLeadConvert(crm_common.TestLeadConvertCommon):
@users('user_sales_manager')
def test_lead_merge_duplicates(self):
""" Test Lead._get_duplicated_leads_by_emails() """
""" Test Lead._get_lead_duplicates() """
# Check: partner / email fallbacks
self._create_duplicates(self.lead_1)
@@ -280,7 +284,7 @@ class TestLeadConvert(crm_common.TestLeadConvertCommon):
@users('user_sales_manager')
def test_lead_merge_duplicates_flow(self):
""" Test Lead._get_duplicated_leads_by_emails() + merge with active_test """
""" Test Lead._get_lead_duplicates() + merge with active_test """
# Check: email formatting
self.lead_1.write({
@@ -431,7 +435,7 @@ class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon):
self.assertEqual(mass_convert.user_id, self.user_sales_salesman)
self.assertEqual(mass_convert.team_id, self.sales_team_convert)
mass_convert.mass_convert()
mass_convert.action_mass_convert()
for lead in self.lead_1 | self.lead_w_partner:
self.assertEqual(lead.type, 'opportunity')
if lead == self.lead_w_partner:
@@ -447,7 +451,7 @@ class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon):
mass_convert.write({
'user_ids': self.user_sales_salesman.ids,
})
mass_convert.mass_convert()
mass_convert.action_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
@@ -481,7 +485,7 @@ class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon):
self.assertEqual(mass_convert.name, 'convert')
self.assertEqual(mass_convert.opportunity_ids, self.lead_1 | self.lead_w_partner)
mass_convert.mass_convert()
mass_convert.action_mass_convert()
self.assertEqual(
(lead_1_dups | lead_w_partner_dups).exists(),
@@ -508,7 +512,7 @@ class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon):
})
# TDE FIXME: what happens if we mix people from different sales team ? currently nothing, to check
mass_convert.mass_convert()
mass_convert.action_mass_convert()
for idx, lead in enumerate(self.leads - self.lead_w_email_lost):
self.assertEqual(lead.type, 'opportunity')
+47 -63
View File
@@ -23,15 +23,15 @@ class Lead2OpportunityPartner(models.TransientModel):
lead = self.env['crm.lead'].browse(self._context['active_id'])
result['lead_id'] = lead.id
partner_id = lead._find_matching_partner()
partner = lead._find_matching_partner()
email = lead.partner_id.email if lead.partner_id else lead.email_from
tomerge.update(self.env['crm.lead']._get_duplicated_leads_by_emails(partner_id, email, include_lost=True).ids)
tomerge.update(self.env['crm.lead']._get_lead_duplicates(partner, email, include_lost=True).ids)
if 'action' in fields and not result.get('action'):
result['action'] = 'exist' if partner_id else 'create'
result['action'] = 'exist' if partner else 'create'
if 'partner_id' in fields:
result['partner_id'] = partner_id
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:
@@ -40,7 +40,7 @@ class Lead2OpportunityPartner(models.TransientModel):
result['user_id'] = lead.user_id.id
if lead.team_id:
result['team_id'] = lead.team_id.id
if not partner_id and not lead.contact_name:
if not partner and not lead.contact_name:
result['action'] = 'nothing'
return result
@@ -63,7 +63,7 @@ class Lead2OpportunityPartner(models.TransientModel):
@api.onchange('action')
def onchange_action(self):
if self.action == 'exist':
self.partner_id = self.lead_id._find_matching_partner()
self.partner_id = self.lead_id._find_matching_partner().id
else:
self.partner_id = False
@@ -81,79 +81,63 @@ class Lead2OpportunityPartner(models.TransientModel):
values = self.env['crm.lead']._onchange_user_values(self.user_id.id if self.user_id else False)
self.team_id = values.get('team_id', False)
# NOTE JEM : is it the good place to test this ?
@api.model
def view_init(self, fields):
# JEM TDE FIXME: clean that brol
""" Check some preconditions before the wizard executes. """
for lead in self.env['crm.lead'].browse(self._context.get('active_ids', [])):
if lead.probability == 100:
raise UserError(_("Closed/Dead leads cannot be converted into opportunities."))
return False
def _convert_opportunity(self, vals):
def action_apply(self):
if self.name == 'merge':
result_opportunity = self._action_merge()
else:
result_opportunity = self._action_convert()
return result_opportunity.redirect_lead_opportunity_view()
def _action_merge(self):
result_opportunity = self.with_context(active_test=False).opportunity_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,
})
return result_opportunity
def _action_convert(self):
""" """
result_opportunities = self.env['crm.lead'].browse(self._context.get('active_ids', []))
self._convert_and_allocate(result_opportunities, [self.user_id.id], team_id=self.team_id.id)
return result_opportunities[0]
def _convert_and_allocate(self, leads, user_ids, team_id=False):
self.ensure_one()
res = False
leads = self.env['crm.lead'].browse(vals.get('lead_ids'))
for lead in leads:
self_def_user = self.with_context(default_user_id=self.user_id.id)
if lead.active and self.action != 'nothing':
self._convert_handle_partner(
lead, self.action, self.partner_id.id or lead.partner_id.id)
partner_id = False
if self.action != 'nothing':
partner_id = self_def_user._create_partner(
lead.id, self.action, vals.get('partner_id') or lead.partner_id.id)
res = lead.convert_opportunity(partner_id, [], False)
user_ids = vals.get('user_ids')
lead.convert_opportunity(lead.partner_id.id, [], False)
leads_to_allocate = leads
if self._context.get('no_force_assignation'):
leads_to_allocate = leads_to_allocate.filtered(lambda lead: not lead.user_id)
if user_ids:
leads_to_allocate.allocate_salesman(user_ids, team_id=(vals.get('team_id')))
leads_to_allocate.handle_salesmen_assignment(user_ids, team_id=team_id)
return res
def action_apply(self):
""" Convert lead to opportunity or merge lead and opportunity and open
the freshly created opportunity view.
"""
self.ensure_one()
values = {
'team_id': self.team_id.id,
}
if self.partner_id:
values['partner_id'] = self.partner_id.id
if self.name == 'merge':
leads = self.with_context(active_test=False).opportunity_ids.merge_opportunity()
if not leads.active:
leads.write({'active': True, 'activity_type_id': False, 'lost_reason': False})
if leads.type == "lead":
values.update({'lead_ids': leads.ids, 'user_ids': [self.user_id.id]})
self.with_context(active_ids=leads.ids)._convert_opportunity(values)
elif not self._context.get('no_force_assignation') or not leads.user_id:
values['user_id'] = self.user_id.id
leads.write(values)
else:
leads = self.env['crm.lead'].browse(self._context.get('active_ids', []))
values.update({'lead_ids': leads.ids, 'user_ids': [self.user_id.id]})
self._convert_opportunity(values)
return leads[0].redirect_lead_opportunity_view()
def _create_partner(self, lead_id, action, partner_id):
""" Create partner based on action.
:return dict: dictionary organized as followed: {lead_id: partner_assigned_id}
"""
#TODO this method in only called by Lead2OpportunityPartner
#wizard and would probably diserve to be refactored or at least
#moved to a better place
if action == 'each_exist_or_create':
partner_id = self.env['crm.lead'].browse(lead_id)._find_matching_partner()
action = 'create'
result = self.env['crm.lead'].browse(lead_id).handle_partner_assignation(action, partner_id)
return result.get(lead_id)
def _convert_handle_partner(self, lead, action, partner_id):
# used to propagate user_id (salesman) on created partners during conversion
lead.with_context(default_user_id=self.user_id.id).handle_partner_assignment(
force_partner_id=partner_id,
create_missing=(action == 'create')
)
@@ -39,12 +39,12 @@ class Lead2OpportunityMassConvert(models.TransientModel):
@api.onchange('deduplicate')
def _onchange_deduplicate(self):
active_leads = self.env['crm.lead'].browse(self._context['active_ids'])
partner_ids = [(lead.partner_id.id, lead.partner_id and lead.partner_id.email or lead.email_from) for lead in active_leads]
partner_ids = [(lead.partner_id, lead.partner_id and lead.partner_id.email or lead.email_from) for lead in active_leads]
partners_duplicated_leads = {}
for partner_id, email in partner_ids:
duplicated_leads = self.env['crm.lead']._get_duplicated_leads_by_emails(partner_id, email, include_lost=False)
for partner, email in partner_ids:
duplicated_leads = self.env['crm.lead']._get_lead_duplicates(partner=partner, email=email, include_lost=False)
if len(duplicated_leads) > 1:
partners_duplicated_leads.setdefault((partner_id, email), []).extend(duplicated_leads)
partners_duplicated_leads.setdefault((partner.id, email), []).extend(duplicated_leads)
leads_with_duplicates = []
for lead in active_leads:
@@ -54,20 +54,18 @@ class Lead2OpportunityMassConvert(models.TransientModel):
self.opportunity_ids = self.env['crm.lead'].browse(leads_with_duplicates)
def _convert_opportunity(self, vals):
def _convert_and_allocate(self, leads, user_ids, team_id=False):
""" When "massively" (more than one at a time) converting leads to
opportunities, check the salesteam_id and salesmen_ids and update
the values before calling super.
opportunities, check the salesteam_id and salesmen_ids and update
the values before calling super.
"""
self.ensure_one()
salesteam_id = self.team_id.id if self.team_id else False
salesmen_ids = []
if self.user_ids:
salesmen_ids = self.user_ids.ids
vals.update({'user_ids': salesmen_ids, 'team_id': salesteam_id})
return super(Lead2OpportunityMassConvert, self)._convert_opportunity(vals)
return super(Lead2OpportunityMassConvert, self)._convert_and_allocate(leads, salesmen_ids, team_id=team_id)
def mass_convert(self):
def action_mass_convert(self):
self.ensure_one()
if self.name == 'convert' and self.deduplicate:
merged_lead_ids = set()
@@ -76,7 +74,11 @@ class Lead2OpportunityMassConvert(models.TransientModel):
for lead_id in lead_selected:
if lead_id not in merged_lead_ids:
lead = self.env['crm.lead'].browse(lead_id)
duplicated_leads = self.env['crm.lead']._get_duplicated_leads_by_emails(lead.partner_id.id, lead.partner_id.email if lead.partner_id else lead.email_from, include_lost=False)
duplicated_leads = self.env['crm.lead']._get_lead_duplicates(
partner=lead.partner_id,
email=lead.partner_id.email or lead.email_from,
include_lost=False
)
if len(duplicated_leads) > 1:
lead = duplicated_leads.merge_opportunity()
merged_lead_ids.update(duplicated_leads.ids)
@@ -87,3 +89,9 @@ class Lead2OpportunityMassConvert(models.TransientModel):
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()
def _convert_handle_partner(self, lead, action, partner_id):
if self.action == 'each_exist_or_create':
partner_id = lead._find_matching_partner().id
action = 'create'
return super(Lead2OpportunityMassConvert, self)._convert_handle_partner(lead, action, partner_id)
@@ -42,7 +42,7 @@
</group>
</group>
<footer>
<button name="mass_convert" string="Convert to Opportunities" type="object" class="btn-primary"/>
<button string="Convert to Opportunities" name="action_mass_convert" type="object" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
@@ -55,7 +55,7 @@
res_model="crm.lead2opportunity.partner.mass"
binding_model="crm.lead" binding_views="list"
view_mode="form" target="new"
context="{'mass_convert' : True}"
context="{}"
view_id="view_crm_lead2opportunity_partner_mass"
/>
</odoo>
@@ -24,7 +24,7 @@ class Opportunity2Quotation(models.TransientModel):
lead = self.env['crm.lead'].browse(self._context['active_id'])
if lead:
result['lead_id'] = lead.id
partner_id = result.get('partner_id') or lead._find_matching_partner()
partner_id = result.get('partner_id') or lead._find_matching_partner().id
if 'action' in fields and not result.get('action'):
result['action'] = 'exist' if partner_id else 'create'
if 'partner_id' in fields and not result.get('partner_id'):
@@ -46,16 +46,6 @@ class Opportunity2Quotation(models.TransientModel):
"""
self.ensure_one()
if self.action != 'nothing':
self.lead_id.write({
'partner_id': self.partner_id.id if self.action == 'exist' else self._create_partner()
})
self.lead_id.handle_partner_assignment(force_partner_id=self.partner_id.id, create_missing=(self.action == 'create'))
self.lead_id._onchange_partner_id()
return self.lead_id.action_new_quotation()
def _create_partner(self):
""" Create partner based on action.
:return int: created res.partner id
"""
self.ensure_one()
result = self.lead_id.handle_partner_assignation(action='create')
return result.get(self.lead_id.id)
+2 -4
View File
@@ -51,10 +51,8 @@ class WebsiteVisitor(models.Model):
partners = sorted_leads.mapped('partner_id')
if not partners:
main_lead = self.lead_ids[0]
partner_id = main_lead.handle_partner_assignation(action='create')[main_lead.id]
if not main_lead.partner_id:
main_lead.partner_id = partner_id
self.partner_id = partner_id
main_lead.handle_partner_assignment(create_missing=True)
self.partner_id = main_lead.partner_id.id
return True
return check
@@ -64,7 +64,7 @@ class CrmLead(models.Model):
lead.assign_geo_localize(lead.partner_latitude, lead.partner_longitude)
partner = self.env['res.partner'].browse(partner_id)
if partner.user_id:
lead.allocate_salesman(partner.user_id.ids, team_id=partner.team_id.id)
lead.handle_salesmen_assignment(partner.user_id.ids, team_id=partner.team_id.id)
values = {'date_assign': fields.Date.context_today(lead), 'partner_assigned_id': partner_id}
lead.write(values)
return res