[IMP] crm: add comments in code about crm lead to opportunity
Try to understand a bit this code with comments. Some unnecessary code is removed, and some parameters are added to try to understand the various flows, but main purpose is to understand that mighty spaghetti, not destroy it. LINKS Side effect of Task ID 2056759 (remove crm.partner.binding mixin) Side effect of Task ID 2088565 (crm onchange -> compute) Community PR #43127 Enterprise PR odoo/enterpreise#7656 Related: odoo/enterprise#7656 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -664,15 +664,8 @@ class Lead(models.Model):
|
||||
|
||||
def _merge_get_result_type(self):
|
||||
""" Define the type of the result of the merge. If at least one of the
|
||||
element to merge is an opp, the resulting new element will be an opp.
|
||||
Otherwise it will be a lead.
|
||||
We'll directly use a list of browse records instead of a list of ids
|
||||
for performances' sake: it will spare a second browse of the
|
||||
leads/opps.
|
||||
|
||||
:param list opps: list of browse records containing the leads/opps to process
|
||||
:return string type: the type of the final element
|
||||
"""
|
||||
element to merge is an opp, the resulting new element will be an opp.
|
||||
Otherwise it will be a lead. """
|
||||
if any(record.type == 'opportunity' for record in self):
|
||||
return 'opportunity'
|
||||
return 'lead'
|
||||
@@ -719,19 +712,20 @@ class Lead(models.Model):
|
||||
data['type'] = self._merge_get_result_type()
|
||||
return data
|
||||
|
||||
def _mail_body(self, fields):
|
||||
""" generate the message body with the changed values
|
||||
:param fields : list of fields to track
|
||||
:returns a list of message bodies for the corresponding leads
|
||||
def _merge_notify_get_merged_fields_message(self, fields):
|
||||
""" Generate the message body with the changed values
|
||||
|
||||
:param fields : list of fields to track
|
||||
:returns a list of message bodies for the corresponding leads
|
||||
"""
|
||||
bodies = []
|
||||
for lead in self:
|
||||
title = "%s : %s\n" % (_('Merged opportunity') if lead.type == 'opportunity' else _('Merged lead'), lead.name)
|
||||
body = [title]
|
||||
_fields = self.env['ir.model.fields'].search([
|
||||
('name', 'in', fields or []),
|
||||
('model_id.model', '=', lead._name),
|
||||
])
|
||||
('name', 'in', fields or []),
|
||||
('model_id.model', '=', lead._name),
|
||||
])
|
||||
for field in _fields:
|
||||
value = getattr(lead, field.name, False)
|
||||
if field.ttype == 'selection':
|
||||
@@ -751,11 +745,11 @@ class Lead(models.Model):
|
||||
return bodies
|
||||
|
||||
def _merge_notify(self, opportunities):
|
||||
""" Create a message gathering merged leads/opps informations. Using message_post, send a
|
||||
message explaining which fields has been merged and their new value. `self` is the
|
||||
resulting merge crm.lead record.
|
||||
:param opportunities : recordset of merged crm.lead
|
||||
:returns mail.message posted on resulting crm.lead
|
||||
""" Post a message gathering merged leads/opps informations. It explains
|
||||
which fields has been merged and their new value. `self` is the resulting
|
||||
merge crm.lead record.
|
||||
|
||||
:param opportunities: see ``merge_dependences``
|
||||
"""
|
||||
# TODO JEM: mail template should be used instead of fix body, subject text
|
||||
self.ensure_one()
|
||||
@@ -764,14 +758,15 @@ class Lead(models.Model):
|
||||
merge_message = _('Merged leads') if result_type == 'lead' else _('Merged opportunities')
|
||||
subject = merge_message + ": " + ", ".join(opportunities.mapped('name'))
|
||||
# message bodies
|
||||
message_bodies = opportunities._mail_body(list(CRM_LEAD_FIELDS_TO_MERGE))
|
||||
message_bodies = opportunities._merge_notify_get_merged_fields_message(list(CRM_LEAD_FIELDS_TO_MERGE))
|
||||
message_body = "\n\n".join(message_bodies)
|
||||
return self.message_post(body=message_body, subject=subject)
|
||||
|
||||
def _merge_opportunity_history(self, opportunities):
|
||||
""" Move mail.message from the given opportunities to the current one. `self` is the
|
||||
crm.lead record destination for message of `opportunities`.
|
||||
:param opportunities : recordset of crm.lead to move the messages
|
||||
|
||||
:param opportunities: see ``merge_dependences``
|
||||
"""
|
||||
self.ensure_one()
|
||||
for opportunity in opportunities:
|
||||
@@ -785,7 +780,8 @@ class Lead(models.Model):
|
||||
def _merge_opportunity_attachments(self, opportunities):
|
||||
""" Move attachments of given opportunities to the current one `self`, and rename
|
||||
the attachments having same name than native ones.
|
||||
:param opportunities : recordset of merged crm.lead
|
||||
|
||||
:param opportunities: see ``merge_dependences``
|
||||
"""
|
||||
self.ensure_one()
|
||||
|
||||
@@ -810,8 +806,9 @@ class Lead(models.Model):
|
||||
def merge_dependences(self, opportunities):
|
||||
""" Merge dependences (messages, attachments, ...). These dependences will be
|
||||
transfered to `self`, the most important lead.
|
||||
:param opportunities : recordset of opportunities to transfert. Does
|
||||
not include `self`.
|
||||
|
||||
:param opportunities : recordset of opportunities to transfer. Does not
|
||||
include `self` which is the target crm.lead being the result of the merge.
|
||||
"""
|
||||
self.ensure_one()
|
||||
self._merge_notify(opportunities)
|
||||
@@ -940,16 +937,18 @@ class Lead(models.Model):
|
||||
|
||||
return True
|
||||
|
||||
def _create_lead_partner_data(self, name, is_company, parent_id=False):
|
||||
""" extract data from lead to create a partner
|
||||
:param name : furtur name of the partner
|
||||
:param is_company : True if the partner is a company
|
||||
:param parent_id : id of the parent partner (False if no parent)
|
||||
:returns res.partner record
|
||||
def _create_lead_partner_data(self, partner_name, is_company=False, parent_id=False):
|
||||
""" Extract data from lead to create a partner.
|
||||
|
||||
:param name : furtur name of the partner
|
||||
:param is_company : True if the partner is a company
|
||||
:param parent_id : id of the parent partner (False if no parent)
|
||||
|
||||
:return: dictionary of values to give at res_partner.create()
|
||||
"""
|
||||
email_split = tools.email_split(self.email_from)
|
||||
return {
|
||||
'name': name,
|
||||
'name': partner_name,
|
||||
'user_id': self.env.context.get('default_user_id') or self.user_id.id,
|
||||
'comment': self.description,
|
||||
'team_id': self.team_id.id,
|
||||
@@ -980,28 +979,30 @@ class Lead(models.Model):
|
||||
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, True))
|
||||
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, False, partner_company.id if partner_company else False))
|
||||
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, False))
|
||||
return Partner.create(self._create_lead_partner_data(self.name, is_company=False))
|
||||
|
||||
def handle_partner_assignation(self, action='create', partner_id=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
|
||||
|
||||
:param list ids: leads/opportunities ids to process
|
||||
: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: dictionary organized as followed: {lead_id: partner_assigned_id}
|
||||
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)
|
||||
"""
|
||||
partner_ids = {}
|
||||
for lead in self:
|
||||
@@ -1042,6 +1043,10 @@ class Lead(models.Model):
|
||||
lead.write(value)
|
||||
return True
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# TOOLS
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def redirect_lead_opportunity_view(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
|
||||
@@ -78,7 +78,7 @@ 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()[new_lead.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)
|
||||
|
||||
@@ -7,7 +7,6 @@ from odoo.tools.translate import _
|
||||
|
||||
|
||||
class Lead2OpportunityPartner(models.TransientModel):
|
||||
|
||||
_name = 'crm.lead2opportunity.partner'
|
||||
_description = 'Convert Lead to Opportunity (not in mass)'
|
||||
_inherit = 'crm.partner.binding'
|
||||
@@ -26,7 +25,7 @@ class Lead2OpportunityPartner(models.TransientModel):
|
||||
lead = self.env['crm.lead'].browse(self._context['active_id'])
|
||||
email = lead.partner_id.email if lead.partner_id else lead.email_from
|
||||
|
||||
tomerge.update(self._get_duplicated_leads(partner_id, email, include_lost=True).ids)
|
||||
tomerge.update(self.env['crm.lead']._get_duplicated_leads_by_emails(partner_id, email, include_lost=True).ids)
|
||||
|
||||
if 'action' in fields and not result.get('action'):
|
||||
result['action'] = 'exist' if partner_id else 'create'
|
||||
@@ -73,11 +72,6 @@ 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)
|
||||
|
||||
@api.model
|
||||
def _get_duplicated_leads(self, partner_id, email, include_lost=False):
|
||||
""" Search for opportunities that have the same partner and that arent done or cancelled """
|
||||
return self.env['crm.lead']._get_duplicated_leads_by_emails(partner_id, email, include_lost=include_lost)
|
||||
|
||||
# NOTE JEM : is it the good place to test this ?
|
||||
@api.model
|
||||
def view_init(self, fields):
|
||||
|
||||
@@ -43,7 +43,7 @@ class Lead2OpportunityMassConvert(models.TransientModel):
|
||||
partner_ids = [(lead.partner_id.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._get_duplicated_leads(partner_id, email)
|
||||
duplicated_leads = self.env['crm.lead']._get_duplicated_leads_by_emails(partner_id, email, include_lost=False)
|
||||
if len(duplicated_leads) > 1:
|
||||
partners_duplicated_leads.setdefault((partner_id, email), []).extend(duplicated_leads)
|
||||
|
||||
@@ -77,7 +77,7 @@ 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._get_duplicated_leads(lead.partner_id.id, lead.partner_id.email if lead.partner_id else lead.email_from)
|
||||
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)
|
||||
if len(duplicated_leads) > 1:
|
||||
lead = duplicated_leads.merge_opportunity()
|
||||
merged_lead_ids.update(duplicated_leads.ids)
|
||||
|
||||
@@ -50,7 +50,7 @@ class WebsiteVisitor(models.Model):
|
||||
lead = self.lead_ids._sort_by_confidence_level(reverse=True)[0]
|
||||
partner_id = self.partner_id.id
|
||||
if not self.partner_id:
|
||||
partner_id = lead.handle_partner_assignation()[lead.id]
|
||||
partner_id = lead.handle_partner_assignation(action='create')[lead.id]
|
||||
if not lead.partner_id:
|
||||
lead.partner_id = partner_id
|
||||
self.partner_id = partner_id
|
||||
|
||||
Reference in New Issue
Block a user