diff --git a/addons/mail/models/models.py b/addons/mail/models/models.py index a757ab10b4d..02ea0a9016a 100644 --- a/addons/mail/models/models.py +++ b/addons/mail/models/models.py @@ -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 diff --git a/addons/mail/models/res_partner.py b/addons/mail/models/res_partner.py index 418731f5c5f..6d5f2057bc2 100644 --- a/addons/mail/models/res_partner.py +++ b/addons/mail/models/res_partner.py @@ -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): diff --git a/addons/mail/tests/common.py b/addons/mail/tests/common.py index 41a53e887db..2757ef48099 100644 --- a/addons/mail/tests/common.py +++ b/addons/mail/tests/common.py @@ -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', diff --git a/addons/portal/models/mail_thread.py b/addons/portal/models/mail_thread.py index 6f020cb6bd7..7edb329b0f7 100644 --- a/addons/portal/models/mail_thread.py +++ b/addons/portal/models/mail_thread.py @@ -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 {}) diff --git a/addons/test_mail/models/test_mail_corner_case_models.py b/addons/test_mail/models/test_mail_corner_case_models.py index 1159cc3c19a..eaee9705070 100644 --- a/addons/test_mail/models/test_mail_corner_case_models.py +++ b/addons/test_mail/models/test_mail_corner_case_models.py @@ -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): diff --git a/addons/test_mail/models/test_mail_models.py b/addons/test_mail/models/test_mail_models.py index 4bcfc74d502..f0227892689 100644 --- a/addons/test_mail/models/test_mail_models.py +++ b/addons/test_mail/models/test_mail_models.py @@ -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'] diff --git a/addons/test_mail_full/models/test_mail_models_mail.py b/addons/test_mail_full/models/test_mail_models_mail.py index ea3e3bf8e5c..f7ed26bb362 100644 --- a/addons/test_mail_full/models/test_mail_models_mail.py +++ b/addons/test_mail_full/models/test_mail_models_mail.py @@ -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): diff --git a/addons/test_mail_full/tests/test_mail_thread_internals.py b/addons/test_mail_full/tests/test_mail_thread_internals.py index d7423e61916..faa2f277af8 100644 --- a/addons/test_mail_full/tests/test_mail_thread_internals.py +++ b/addons/test_mail_full/tests/test_mail_thread_internals.py @@ -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( diff --git a/addons/test_mail_sms/models/test_mail_sms_models.py b/addons/test_mail_sms/models/test_mail_sms_models.py index fe47cfcb8a2..c01630b42c8 100644 --- a/addons/test_mail_sms/models/test_mail_sms_models.py +++ b/addons/test_mail_sms/models/test_mail_sms_models.py @@ -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()