[REF] website(_crm): improve code about contacting visitors

Purpose of this commit is to clean mail and SMS composer calls in website_crm
and website_crm_sms by separating composer preparation (context, values) from
customer preparation (check valid data exists, creating partner).

Indeed most of message composer code is based on records having a partner_id
correctly set, unless some templates are used that dynamically creates the
partner. SMS composer is more tolerant and check for phone / mobile numbers to
use.

By the way we make the action name translatable, because why not.

LINKS

Spotted when working on task ID 2056759 (remove crm.partner.binding mixin)
Community PR odoo/odoo#44970
Enterprise PR odoo/enterprise#8307
This commit is contained in:
Thibault Delavallée
2020-02-13 15:29:40 +00:00
parent 1508705ab4
commit 3a7b08e5cf
4 changed files with 77 additions and 62 deletions
+19 -18
View File
@@ -121,38 +121,39 @@ class WebsiteVisitor(models.Model):
visitor.time_since_last_action = _format_time_ago(self.env, (datetime.now() - visitor.last_connection_datetime))
visitor.is_connected = (datetime.now() - visitor.last_connection_datetime) < timedelta(minutes=5)
def _prepare_visitor_send_mail_values(self):
if self.partner_id.email:
return {
'res_model': 'res.partner',
'res_id': self.partner_id.id,
'partner_ids': [self.partner_id.id],
}
return {}
def _check_for_message_composer(self):
""" Purpose of this method is to actualize visitor model prior to contacting
him. Used notably for inheritance purpose, when dealing with leads that
could update the visitor model. """
return bool(self.partner_id and self.partner_id.email)
def _prepare_message_composer_context(self):
return {
'default_model': 'res.partner',
'default_res_id': self.partner_id.id,
'default_partner_ids': [self.partner_id.id],
}
def action_send_mail(self):
self.ensure_one()
visitor_mail_values = self._prepare_visitor_send_mail_values()
if not visitor_mail_values:
raise UserError(_("There is no email linked this visitor."))
if not self._check_for_message_composer():
raise UserError(_("There is no contact and/or no email linked this visitor."))
visitor_composer_ctx = self._prepare_message_composer_context()
compose_form = self.env.ref('mail.email_compose_message_wizard_form', False)
ctx = dict(
default_model=visitor_mail_values.get('res_model'),
default_res_id=visitor_mail_values.get('res_id'),
compose_ctx = dict(
default_use_template=False,
default_partner_ids=[(6, 0, visitor_mail_values.get('partner_ids'))],
default_composition_mode='comment',
default_reply_to=self.env.user.partner_id.email,
)
compose_ctx.update(**visitor_composer_ctx)
return {
'name': _('Compose Email'),
'name': _('Contact Visitor'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'mail.compose.message',
'views': [(compose_form.id, 'form')],
'view_id': compose_form.id,
'target': 'new',
'context': ctx,
'context': compose_ctx,
}
def _get_visitor_from_request(self, force_create=False):
+25 -15
View File
@@ -44,19 +44,29 @@ class WebsiteVisitor(models.Model):
visitor.email = email[:-1] if email else False
visitor.mobile = mapped_data.get(visitor.id, {}).get('mobile')
def _prepare_visitor_send_mail_values(self):
visitor_mail_values = super(WebsiteVisitor, self)._prepare_visitor_send_mail_values()
if self.lead_ids:
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(action='create')[lead.id]
if not lead.partner_id:
lead.partner_id = partner_id
def _check_for_message_composer(self):
check = super(WebsiteVisitor, self)._check_for_message_composer()
if not check and self.lead_ids:
sorted_leads = self.lead_ids._sort_by_confidence_level(reverse=True)
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
return {
'res_model': 'crm.lead',
'res_id': lead.id,
'partner_ids': [partner_id],
}
return visitor_mail_values
return True
return check
def _prepare_message_composer_context(self):
if not self.partner_id and self.lead_ids:
sorted_leads = self.lead_ids._sort_by_confidence_level(reverse=True)
lead_partners = sorted_leads.mapped('partner_id')
partner = lead_partners[0] if lead_partners else False
if partner:
return {
'default_model': 'crm.lead',
'default_res_id': sorted_leads[0].id,
'default_partner_ids': partner.ids,
}
return super(WebsiteVisitor, self)._prepare_message_composer_context()
@@ -7,16 +7,22 @@ from odoo import models
class WebsiteVisitor(models.Model):
_inherit = 'website.visitor'
def _prepare_visitor_send_sms_values(self):
visitor_sms_values = super(WebsiteVisitor, self)._prepare_visitor_send_sms_values()
if not visitor_sms_values:
def _check_for_sms_composer(self):
check = super(WebsiteVisitor, self)._check_for_sms_composer()
if not check and self.lead_ids:
sorted_leads = self.lead_ids.filtered(lambda l: l.mobile == self.mobile or l.phone == self.mobile)._sort_by_confidence_level(reverse=True)
if sorted_leads:
return True
return check
def _prepare_sms_composer_context(self):
if not self.partner_id and self.lead_ids:
leads_with_number = self.lead_ids.filtered(lambda l: l.mobile == self.mobile or l.phone == self.mobile)._sort_by_confidence_level(reverse=True)
if leads_with_number:
lead = leads_with_number[0]
return {
'res_model': 'crm.lead',
'res_id': lead.id,
'partner_ids': [lead.id],
'default_res_model': 'crm.lead',
'default_res_id': lead.id,
'number_field_name': 'mobile' if lead.mobile == self.mobile else 'phone',
}
return visitor_sms_values
return super(WebsiteVisitor, self)._prepare_sms_composer_context()
+20 -22
View File
@@ -8,35 +8,33 @@ from odoo.exceptions import UserError
class WebsiteVisitor(models.Model):
_inherit = 'website.visitor'
def _prepare_visitor_send_sms_values(self):
if self.partner_id.mobile:
return {
'res_model': 'res.partner',
'res_id': self.partner_id.id,
'partner_ids': [self.partner_id.id],
'number_field_name': 'mobile',
}
return {}
def _check_for_sms_composer(self):
""" Purpose of this method is to actualize visitor model prior to contacting
him. Used notably for inheritance purpose, when dealing with leads that
could update the visitor model. """
return bool(self.partner_id and (self.partner_id.mobile or self.partner_id.phone))
def _prepare_sms_composer_context(self):
return {
'default_res_model': 'res.partner',
'default_res_id': self.partner_id.id,
'default_composition_mode': 'comment',
'default_number_field_name': 'mobile' if self.partner_id.mobile else 'phone',
}
def action_send_sms(self):
self.ensure_one()
visitor_sms_values = self._prepare_visitor_send_sms_values()
if not visitor_sms_values:
raise UserError(_("There is no mobile phone number linked to this visitor."))
context = dict(self.env.context)
context.update({
'default_res_model': visitor_sms_values['res_model'],
'default_res_id': visitor_sms_values['res_id'],
'default_composition_mode': 'comment',
'default_number_field_name': visitor_sms_values['number_field_name'],
})
if not self._check_for_sms_composer():
raise UserError(_("There is no contact and/or no phone or mobile numbers linked this visitor."))
visitor_composer_ctx = self._prepare_sms_composer_context()
compose_ctx = dict(self.env.context)
compose_ctx.update(**visitor_composer_ctx)
return {
"name": _("Send SMS Text Message"),
"type": "ir.actions.act_window",
"res_model": "sms.composer",
"view_mode": 'form',
"context": context,
"name": "Send SMS Text Message",
"context": compose_ctx,
"target": "new",
}