[IMP] mail: add a default heuristic to find a partner on a document
RATIONALE Simplify field management for mail / phone / sms flows. Make it working out of the box, easier to use and tweak. SPECIFICATIONS In addition to finding the customer, sometimes we just want any partner on a record, notably for VOIP. For that purpose we improve heuristic for finding partner (fields or records). It introspects the model to find any relational field towards res.partner. Note that as it is generic it does not ensure the partner is a customer, just some partner. Task-3422449 (Mail, Phone: Move and improve field helpers) Prepares Task-36879 (Mail: Support MultiCompany Aliases) Part-of: odoo/odoo#130468
This commit is contained in:
@@ -23,20 +23,36 @@ class BaseModel(models.AbstractModel):
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@api.model
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
""" This method returns the fields to use to find the contact to link
|
||||
when sending emails or notifications. Having partner is not always
|
||||
necessary but gives more flexibility to notifications management. """
|
||||
return [fname for fname in ('partner_id', 'partner_ids')
|
||||
if fname in self]
|
||||
necessary but gives more flexibility to notifications management.
|
||||
|
||||
def _mail_get_partners(self):
|
||||
""" Give the default partners associated to customers.
|
||||
:param bool introspect_fields: if no field is found by default
|
||||
heuristics, introspect model to find relational fields towards
|
||||
res.partner model. This is used notably when partners are
|
||||
mandatory like in voip;
|
||||
|
||||
:return list: list of valid field names that can be used to retrieve
|
||||
a partner (customer) on the record;
|
||||
"""
|
||||
partner_fnames = [fname for fname in ('partner_id', 'partner_ids') if fname in self]
|
||||
if not partner_fnames and introspect_fields:
|
||||
partner_fnames = [
|
||||
fname for fname, fvalue in self._fields.items()
|
||||
if fvalue.type == 'many2one' and fvalue.comodel_name == 'res.partner'
|
||||
]
|
||||
return partner_fnames
|
||||
|
||||
def _mail_get_partners(self, introspect_fields=False):
|
||||
""" Give the default partners (customers) associated to customers.
|
||||
|
||||
:param bool introspect_fields: see '_mail_get_partner_fields';
|
||||
|
||||
:return dict: for each record ID, a res.partner recordsets being default
|
||||
customers to contact;
|
||||
"""
|
||||
partner_fields = self._mail_get_partner_fields()
|
||||
partner_fields = self._mail_get_partner_fields(introspect_fields=introspect_fields)
|
||||
return dict(
|
||||
(record.id, self.env['res.partner'].union(*[record[fname] for fname in partner_fields]))
|
||||
for record in self
|
||||
|
||||
@@ -64,7 +64,7 @@ class Partner(models.Model):
|
||||
# MESSAGING
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def _mail_get_partners(self):
|
||||
def _mail_get_partners(self, introspect_fields=False):
|
||||
return dict((partner.id, partner) for partner in self)
|
||||
|
||||
def _message_get_suggested_recipients(self):
|
||||
|
||||
@@ -1142,17 +1142,8 @@ class MailCommon(common.TransactionCase, MailCase):
|
||||
} for idx in range(count)
|
||||
]
|
||||
|
||||
partner_fname = False
|
||||
if 'partner_id' in cls.env[model]:
|
||||
partner_fname = 'partner_id'
|
||||
elif hasattr(cls.env[model], '_mail_get_partner_fields'):
|
||||
partner_fnames = cls.env[model]._mail_get_partner_fields()
|
||||
if partner_fnames:
|
||||
partner_fname = partner_fnames[0]
|
||||
elif 'customer_id' in cls.env[model]:
|
||||
partner_fname = 'customer_id'
|
||||
|
||||
if partner_fname:
|
||||
partner_fnames = cls.env[model]._mail_get_partner_fields(introspect_fields=True)
|
||||
if partner_fname := partner_fnames[0] if partner_fnames else False:
|
||||
partners = cls.env['res.partner'].with_context(**cls._test_context).create([{
|
||||
'name': f'Partner_{idx}',
|
||||
'email': f'{prefix}test_partner_{idx}@example.com',
|
||||
|
||||
@@ -27,7 +27,7 @@ class MailThread(models.AbstractModel):
|
||||
if not portal_enabled:
|
||||
return groups
|
||||
|
||||
customer = self._mail_get_partners()[self.id]
|
||||
customer = self._mail_get_partners(introspect_fields=False)[self.id]
|
||||
if customer:
|
||||
access_token = self._portal_ensure_token()
|
||||
local_msg_vals = dict(msg_vals or {})
|
||||
|
||||
@@ -53,7 +53,7 @@ class MailTestFieldType(models.Model):
|
||||
self = self.with_context(default_type='first')
|
||||
return super(MailTestFieldType, self).create(vals_list)
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ class MailTestLang(models.Model):
|
||||
customer_id = fields.Many2one('res.partner')
|
||||
lang = fields.Char('Lang')
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
def _notify_get_recipients_groups(self, message, model_description, msg_vals=None):
|
||||
|
||||
@@ -86,7 +86,7 @@ class MailTestGatewayGroups(models.Model):
|
||||
values['alias_parent_thread_id'] = self.id
|
||||
return values
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
def _message_get_default_recipients(self):
|
||||
@@ -157,7 +157,7 @@ class MailTestTicket(models.Model):
|
||||
user_id = fields.Many2one('res.users', 'Responsible', tracking=1)
|
||||
container_id = fields.Many2one('mail.test.container', tracking=True)
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
def _message_compute_subject(self):
|
||||
@@ -314,7 +314,7 @@ class MailTestContainer(models.Model):
|
||||
'mail.alias', 'Alias',
|
||||
delegate=True)
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
def _message_get_default_recipients(self):
|
||||
@@ -395,7 +395,7 @@ class MailTestComposerSource(models.Model):
|
||||
for source in self.filtered(lambda r: r.customer_id and not r.email_from):
|
||||
source.email_from = source.customer_id.email_formatted
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
|
||||
@@ -407,3 +407,6 @@ class MailTestMailTrackingDuration(models.Model):
|
||||
|
||||
name = fields.Char()
|
||||
customer_id = fields.Many2one('res.partner', 'Customer', tracking=True)
|
||||
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
@@ -87,7 +87,7 @@ class MailTestRating(models.Model):
|
||||
elif not rating.phone_nbr:
|
||||
rating.phone_nbr = False
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
def _phone_get_number_fields(self):
|
||||
@@ -116,7 +116,7 @@ class MailTestRatingThread(models.Model):
|
||||
customer_id = fields.Many2one('res.partner', 'Customer')
|
||||
user_id = fields.Many2one('res.users', 'Responsible', tracking=1)
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
def _rating_get_partner(self):
|
||||
|
||||
@@ -48,7 +48,7 @@ class TestMailThreadInternals(TestMailThreadInternalsCommon):
|
||||
with self.subTest(test_record=test_record):
|
||||
is_portal = test_record._name != 'mail.test.simple'
|
||||
has_customer = test_record._name != 'mail.test.portal.no.partner'
|
||||
partner_fnames = test_record._mail_get_partner_fields()
|
||||
partner_fnames = test_record._mail_get_partner_fields(introspect_fields=False)
|
||||
|
||||
if is_portal:
|
||||
self.assertFalse(
|
||||
|
||||
@@ -20,7 +20,7 @@ class MailTestSMS(models.Model):
|
||||
mobile_nbr = fields.Char()
|
||||
customer_id = fields.Many2one('res.partner', 'Customer')
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
def _sms_get_partner_fields(self):
|
||||
@@ -56,7 +56,7 @@ class MailTestSMSBL(models.Model):
|
||||
for phone_record in self.filtered(lambda rec: not rec.phone_nbr and rec.customer_id):
|
||||
phone_record.phone_nbr = phone_record.customer_id.phone
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
def _sms_get_partner_fields(self):
|
||||
@@ -96,7 +96,7 @@ class MailTestSMSOptout(models.Model):
|
||||
customer_id = fields.Many2one('res.partner', 'Customer')
|
||||
opt_out = fields.Boolean()
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
def _mailing_get_opt_out_list_sms(self, mailing):
|
||||
@@ -126,7 +126,7 @@ class MailTestSMSPartner(models.Model):
|
||||
customer_id = fields.Many2one('res.partner', 'Customer')
|
||||
opt_out = fields.Boolean()
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
def _mailing_get_opt_out_list_sms(self, mailing):
|
||||
@@ -155,8 +155,8 @@ class MailTestSMSPartner2Many(models.Model):
|
||||
customer_ids = fields.Many2many('res.partner', string='Customers')
|
||||
opt_out = fields.Boolean()
|
||||
|
||||
def _mail_get_partner_fields(self):
|
||||
return ['customer_ids']
|
||||
def _mail_get_partner_fields(self, introspect_fields=False):
|
||||
return ['customer_id']
|
||||
|
||||
def _mailing_get_opt_out_list_sms(self, mailing):
|
||||
res_ids = mailing._get_recipients()
|
||||
|
||||
Reference in New Issue
Block a user