[REF] mail: get rid of thread_model context key

message_post and various mail.thread related code still support a thread_model
context key allowing to redirect message post on another model. Purpose of
this commit is to get rid of that context key and support model / res_id
fields coming from either the record on which we run, either parameters of
message_post. Indeed those parameter match the one used as fields on mail
message. It makes sense to support them for customization if necessary
instead of using a context key.

This context key exists since a lot of time. It is difficult to find the
source as history is quite complex when the mail was refactored in 2012.
See notably 6aa4f80b2d and 2c4ed841b9 for example.
This commit is contained in:
Thibault Delavallée
2018-05-07 11:00:03 +02:00
parent 282733cf8d
commit 324ae5ed8f
3 changed files with 18 additions and 24 deletions
+10 -15
View File
@@ -1274,8 +1274,6 @@ class MailThread(models.AbstractModel):
if thread_id:
raise ValueError("Posting a message without model should be with a null res_id, to create a private message.")
thread = self.env['mail.thread']
if not hasattr(thread, 'message_post'):
thread = self.env['mail.thread'].with_context(thread_model=model)
# replies to internal message are considered as notes, but parent message
# author is added in recipients to ensure he is notified of a private answer
@@ -1287,7 +1285,11 @@ class MailThread(models.AbstractModel):
partner_ids = [(4, parent_message.author_id.id)]
else:
subtype = 'mail.mt_comment'
new_msg = thread.message_post(subtype=subtype, partner_ids=partner_ids, **message_dict)
post_params = dict(subtype=subtype, partner_ids=partner_ids, **message_dict)
if not hasattr(thread, 'message_post'):
post_params['model'] = model
new_msg = thread.message_post(**post_params)
if original_partner_ids:
# postponed after message_post, because this is an external message and we don't want to create
@@ -1379,23 +1381,17 @@ class MailThread(models.AbstractModel):
when creating the new thread record.
Be careful, these values may override
any other values coming from the message.
:param dict context: if a ``thread_model`` value is present
in the context, its value will be used
to determine the model of the record
to create (instead of the current model).
:rtype: int
:return: the id of the newly created thread object
"""
data = {}
if isinstance(custom_values, dict):
data = custom_values.copy()
model = self._context.get('thread_model') or self._name
RecordModel = self.env[model]
fields = RecordModel.fields_get()
name_field = RecordModel._rec_name or 'name'
fields = self.fields_get()
name_field = self._rec_name or 'name'
if name_field in fields and not data.get('name'):
data[name_field] = msg_dict.get('subject', '')
return RecordModel.create(data)
return self.create(data)
@api.multi
def message_update(self, msg_dict, update_vals=None):
@@ -1887,10 +1883,9 @@ class MailThread(models.AbstractModel):
model = False
if self.ids:
self.ensure_one()
model = self._context.get('thread_model', False) if self._name == 'mail.thread' else self._name
model = kwargs.get('model', False) if self._name == 'mail.thread' else self._name
if model and model != self._name and hasattr(self.env[model], 'message_post'):
RecordModel = self.env[model].with_context(thread_model=None) # TDE: was removing the key ?
return RecordModel.browse(self.ids).message_post(
return self.env[model].browse(self.ids).message_post(
body=body, subject=subject, message_type=message_type,
subtype=subtype, parent_id=parent_id, attachments=attachments,
notif_layout=notif_layout, notif_values=notif_values, **kwargs)
+5 -4
View File
@@ -216,9 +216,7 @@ class MailComposer(models.TransientModel):
mass_mode = wizard.composition_mode in ('mass_mail', 'mass_post')
Mail = self.env['mail.mail']
ActiveModel = self.env[wizard.model if wizard.model else 'mail.thread']
if not hasattr(ActiveModel, 'message_post'):
ActiveModel = self.env['mail.thread'].with_context(thread_model=wizard.model)
ActiveModel = self.env[wizard.model] if wizard.model and hasattr(self.env[wizard.model], 'message_post') else self.env['mail.thread']
if wizard.composition_mode == 'mass_post':
# do not send emails directly but use the queue instead
# add context key to avoid subscribing the author
@@ -248,7 +246,7 @@ class MailComposer(models.TransientModel):
if wizard.composition_mode == 'mass_mail':
batch_mails |= Mail.create(mail_values)
else:
ActiveModel.browse(res_id).message_post(
post_params = dict(
message_type=wizard.message_type,
subtype_id=subtype_id,
notif_layout=notif_layout,
@@ -257,6 +255,9 @@ class MailComposer(models.TransientModel):
'mail_auto_delete': wizard.template_id.auto_delete if wizard.template_id else False,
},
**mail_values)
if ActiveModel._name == 'mail.thread' and wizard.model:
post_params['model'] = wizard.model
ActiveModel.browse(res_id).message_post(**post_params)
if wizard.composition_mode == 'mass_mail':
batch_mails.send(auto_commit=auto_commit)
+3 -5
View File
@@ -475,17 +475,15 @@ class TestMailgateway(BaseFunctionalTest, MockEmails):
""" Testing private discussion between partners. """
msg1_pids = [self.env.user.partner_id.id, self.partner_1.id]
# Do: Raoul writes to Bert and Administrator, with a thread_model in context that should not be taken into account
msg1 = self.env['mail.thread'].with_context({
'thread_model': 'mail.test'
}).sudo(self.user_employee).message_post(partner_ids=msg1_pids, subtype='mail.mt_comment')
# Do: Raoul writes to Bert and Administrator, with a model specific by parameter that should not be taken into account
msg1 = self.env['mail.thread'].sudo(self.user_employee).message_post(partner_ids=msg1_pids, subtype='mail.mt_comment', model='mail.test')
# Test: message recipients
msg = self.env['mail.message'].browse(msg1.id)
self.assertEqual(msg.partner_ids, self.env.user.partner_id | self.partner_1,
'message_post: private discussion: incorrect recipients')
self.assertEqual(msg.model, False,
'message_post: private discussion: context key "thread_model" not correctly ignored when having no res_id')
'message_post: private discussion: parameter model not correctly ignored when having no res_id')
# Test: message-id
self.assertIn('openerp-private', msg.message_id, 'message_post: private discussion: message-id should contain the private keyword')