[IMP] mail: update _notify API
Purpose of this commit is to allow to give additional values when rendering notification emails and to make some parameters explicit. This commit updates the _notify API. It allow to propagate a dictionary containing values given to the rendering of the notification template. This allow to have more complex templates and/or to control the rendering depending on some parameters. Indeed currently only some fixed values and values coming form the message to notify are given to the rendering context. First use will be soon when pushing notification emails not necessarily linked to documents. In this process some values will be given by the caller and not only by the message context anymore. This commit also moves some context key used to control the notification process directly in values given to the _notify method. It allows to make those parameters explicit and rely less on context. The _notify method now takes a values dictionary that may contain * add_sign: add user signature to notification email, default is True. It replaces the ``mail_notify_user_signature`` context key; * mail_auto_delete: auto delete send emails, default is True. It replaces the ``mail_auto_delete`` context key; * other values are given to the context used to render the notification template, allowing customization. It allows to remove some context switch notably in the composer. A values dictionary is computed and given to message_post and then propagated to the notification mechanism.
This commit is contained in:
@@ -1193,7 +1193,7 @@ class Lead(models.Model):
|
||||
update_vals[key] = res.group(2).lower()
|
||||
return super(Lead, self).message_update(msg_dict, update_vals=update_vals)
|
||||
|
||||
def _message_post_after_hook(self, message, values, notif_layout):
|
||||
def _message_post_after_hook(self, message, values, notif_layout, notif_values):
|
||||
if self.email_from and not self.partner_id:
|
||||
# we consider that posting a message with a specified recipient (not a follower, a specific one)
|
||||
# on a document without customer means that it was created through the chatter using
|
||||
@@ -1204,7 +1204,7 @@ class Lead(models.Model):
|
||||
('partner_id', '=', False),
|
||||
('email_from', '=', new_partner.email),
|
||||
('stage_id.fold', '=', False)]).write({'partner_id': new_partner.id})
|
||||
return super(Lead, self)._message_post_after_hook(message, values, notif_layout)
|
||||
return super(Lead, self)._message_post_after_hook(message, values, notif_layout, notif_values)
|
||||
|
||||
@api.multi
|
||||
def message_partner_info_from_emails(self, emails, link_mail=False):
|
||||
|
||||
@@ -449,7 +449,7 @@ class EventRegistration(models.Model):
|
||||
pass
|
||||
return recipients
|
||||
|
||||
def _message_post_after_hook(self, message, values, notif_layout):
|
||||
def _message_post_after_hook(self, message, values, notif_layout, notif_values):
|
||||
if self.email and not self.partner_id:
|
||||
# we consider that posting a message with a specified recipient (not a follower, a specific one)
|
||||
# on a document without customer means that it was created through the chatter using
|
||||
@@ -461,7 +461,7 @@ class EventRegistration(models.Model):
|
||||
('email', '=', new_partner.email),
|
||||
('state', 'not in', ['cancel']),
|
||||
]).write({'partner_id': new_partner.id})
|
||||
return super(EventRegistration, self)._message_post_after_hook(message, values, notif_layout)
|
||||
return super(EventRegistration, self)._message_post_after_hook(message, values, notif_layout, notif_values)
|
||||
|
||||
@api.multi
|
||||
def action_send_badge_email(self):
|
||||
|
||||
@@ -377,7 +377,7 @@ class Applicant(models.Model):
|
||||
defaults.update(custom_values)
|
||||
return super(Applicant, self).message_new(msg, custom_values=defaults)
|
||||
|
||||
def _message_post_after_hook(self, message, values, notif_layout):
|
||||
def _message_post_after_hook(self, message, values, notif_layout, notif_values):
|
||||
if self.email_from and not self.partner_id:
|
||||
# we consider that posting a message with a specified recipient (not a follower, a specific one)
|
||||
# on a document without customer means that it was created through the chatter using
|
||||
@@ -388,7 +388,7 @@ class Applicant(models.Model):
|
||||
('partner_id', '=', False),
|
||||
('email_from', '=', new_partner.email),
|
||||
('stage_id.fold', '=', False)]).write({'partner_id': new_partner.id})
|
||||
return super(Applicant, self)._message_post_after_hook(message, values, notif_layout)
|
||||
return super(Applicant, self)._message_post_after_hook(message, values, notif_layout, notif_values)
|
||||
|
||||
@api.multi
|
||||
def create_employee_from_applicant(self):
|
||||
|
||||
@@ -796,7 +796,7 @@ class Message(models.Model):
|
||||
#------------------------------------------------------
|
||||
|
||||
@api.multi
|
||||
def _notify(self, layout=False, force_send=False, send_after_commit=True, user_signature=True):
|
||||
def _notify(self, layout=False, force_send=False, send_after_commit=True, values=None):
|
||||
""" Compute recipients to notify based on specified recipients and document
|
||||
followers. Delegate notification to partners to send emails and bus notifications
|
||||
and to channels to broadcast messages on channels """
|
||||
@@ -847,7 +847,7 @@ class Message(models.Model):
|
||||
('id', 'in', (partners_sudo - notif_partners).ids),
|
||||
('channel_ids', 'in', email_channels.ids),
|
||||
('email', '!=', self_sudo.author_id.email or self_sudo.email_from),
|
||||
])._notify(self, layout=layout, force_send=force_send, send_after_commit=send_after_commit, user_signature=user_signature)
|
||||
])._notify(self, layout=layout, force_send=force_send, send_after_commit=send_after_commit, values=values)
|
||||
|
||||
notif_partners._notify_by_chat(self)
|
||||
|
||||
|
||||
@@ -67,12 +67,8 @@ class MailThread(models.AbstractModel):
|
||||
creating messages
|
||||
- ``tracking_disable``: at create and write, perform no MailThread features
|
||||
(auto subscription, tracking, post, ...)
|
||||
- ``mail_auto_delete``: auto delete mail notifications; True by default
|
||||
(technical hack for templates)
|
||||
- ``mail_notify_force_send``: if less than 50 email notifications to send,
|
||||
send them directly instead of using the queue; True by default
|
||||
- ``mail_notify_user_signature``: add the current user signature in
|
||||
email notifications; True by default
|
||||
'''
|
||||
_name = 'mail.thread'
|
||||
_description = 'Email Thread'
|
||||
@@ -1788,7 +1784,7 @@ class MailThread(models.AbstractModel):
|
||||
def message_post(self, body='', subject=None,
|
||||
message_type='notification', subtype=None,
|
||||
parent_id=False, attachments=None, content_subtype='html',
|
||||
notif_layout=False, **kwargs):
|
||||
notif_layout=False, notif_values=None, **kwargs):
|
||||
""" Post a new message in an existing thread, returning the new
|
||||
mail.message ID.
|
||||
:param int thread_id: thread ID to post into, or list with one ID;
|
||||
@@ -1913,10 +1909,10 @@ class MailThread(models.AbstractModel):
|
||||
|
||||
# Post the message
|
||||
new_message = MailMessage.create(values)
|
||||
self._message_post_after_hook(new_message, values, notif_layout)
|
||||
self._message_post_after_hook(new_message, values, notif_layout, notif_values)
|
||||
return new_message
|
||||
|
||||
def _message_post_after_hook(self, message, values, notif_layout):
|
||||
def _message_post_after_hook(self, message, values, notif_layout, notif_values):
|
||||
""" Hook to add custom behavior after having posted the message. Both
|
||||
message and computed value are given, to try to lessen query count by
|
||||
using already-computed values instead of having to rebrowse things. """
|
||||
@@ -1924,7 +1920,7 @@ class MailThread(models.AbstractModel):
|
||||
message._notify(
|
||||
layout=notif_layout,
|
||||
force_send=self.env.context.get('mail_notify_force_send', True),
|
||||
user_signature=self.env.context.get('mail_notify_user_signature', True)
|
||||
values=notif_values,
|
||||
)
|
||||
|
||||
# Post-process: subscribe author
|
||||
|
||||
@@ -37,13 +37,16 @@ class Partner(models.Model):
|
||||
return dict((res_id, {'partner_ids': [res_id], 'email_to': False, 'email_cc': False}) for res_id in self.ids)
|
||||
|
||||
@api.model
|
||||
def _notify_prepare_template_context(self, message):
|
||||
def _notify_prepare_template_context(self, message, notif_values):
|
||||
# compute signature
|
||||
signature = ""
|
||||
if message.author_id and message.author_id.user_ids and message.author_id.user_ids[0].signature:
|
||||
if not notif_values.pop('add_sign', True):
|
||||
signature = False
|
||||
elif message.author_id and message.author_id.user_ids and message.author_id.user_ids[0].signature:
|
||||
signature = message.author_id.user_ids[0].signature
|
||||
elif message.author_id:
|
||||
signature = "<p>-- <br/>%s</p>" % message.author_id.name
|
||||
else:
|
||||
signature = ""
|
||||
|
||||
# compute Sent by
|
||||
if message.author_id and message.author_id.user_ids:
|
||||
@@ -91,7 +94,7 @@ class Partner(models.Model):
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _notify_prepare_email_values(self, message):
|
||||
def _notify_prepare_email_values(self, message, notif_values):
|
||||
# compute email references
|
||||
references = message.parent_id.message_id if message.parent_id else False
|
||||
|
||||
@@ -103,7 +106,7 @@ class Partner(models.Model):
|
||||
mail_values = {
|
||||
'mail_message_id': message.id,
|
||||
'mail_server_id': message.mail_server_id.id,
|
||||
'auto_delete': self._context.get('mail_auto_delete', True),
|
||||
'auto_delete': notif_values.pop('mail_auto_delete', True),
|
||||
'references': references,
|
||||
}
|
||||
mail_values.update(custom_values)
|
||||
@@ -146,16 +149,23 @@ class Partner(models.Model):
|
||||
})
|
||||
|
||||
@api.multi
|
||||
def _notify(self, message, layout=False, force_send=False, send_after_commit=True, user_signature=True):
|
||||
def _notify(self, message, layout=False, force_send=False, send_after_commit=True, values=None):
|
||||
""" Method to send email linked to notified messages. The recipients are
|
||||
the recordset on which this method is called.
|
||||
|
||||
:param boolean force_send: send notification emails now instead of letting the scheduler handle the email queue
|
||||
:param boolean send_after_commit: send notification emails after the transaction end instead of durign the
|
||||
transaction; this option is used only if force_send is True
|
||||
:param user_signature: add current user signature to notification emails """
|
||||
:param dict values: values used to compute the notification process, containing
|
||||
|
||||
* add_sign: add user signature to notification email, default is True
|
||||
* mail_auto_delete: auto delete send emails, default is True
|
||||
* other values are given to the context used to render the notification template, allowing customization
|
||||
|
||||
"""
|
||||
if not self.ids:
|
||||
return True
|
||||
values = values if values is not None else {}
|
||||
|
||||
template_xmlid = layout if layout else 'mail.message_notification_email'
|
||||
try:
|
||||
@@ -164,10 +174,8 @@ class Partner(models.Model):
|
||||
_logger.warning('QWeb template %s not found when sending notification emails. Skipping.' % (template_xmlid))
|
||||
return False
|
||||
|
||||
base_template_ctx = self._notify_prepare_template_context(message)
|
||||
if not user_signature:
|
||||
base_template_ctx['signature'] = False
|
||||
base_mail_values = self._notify_prepare_email_values(message)
|
||||
base_template_ctx = self._notify_prepare_template_context(message, values)
|
||||
base_mail_values = self._notify_prepare_email_values(message, values)
|
||||
|
||||
# classify recipients: actions / no action
|
||||
if message.model and message.res_id and hasattr(self.env[message.model], '_notify_classify_recipients'):
|
||||
@@ -180,7 +188,7 @@ class Partner(models.Model):
|
||||
for email_type, recipient_template_values in recipients.items():
|
||||
if recipient_template_values['recipients']:
|
||||
# generate notification email content
|
||||
template_ctx = dict(base_template_ctx, **recipient_template_values) # fixme: set button_unfollow to none
|
||||
template_ctx = {**base_template_ctx, **recipient_template_values, **values} # fixme: set button_unfollow to none
|
||||
fol_values = {
|
||||
'subject': message.subject or (message.record_name and 'Re: %s' % message.record_name),
|
||||
'body': base_template.render(template_ctx, engine='ir.qweb'),
|
||||
|
||||
@@ -59,6 +59,6 @@ class Invite(models.TransientModel):
|
||||
'res_id': wizard.res_id,
|
||||
'no_auto_thread': True,
|
||||
})
|
||||
new_partners.with_context(auto_delete=True)._notify(message, force_send=True, send_after_commit=False, user_signature=True)
|
||||
new_partners.with_context(auto_delete=True)._notify(message, force_send=True, send_after_commit=False, values={'add_sign': True})
|
||||
message.unlink()
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
@@ -147,7 +147,7 @@ class MailComposer(models.TransientModel):
|
||||
return super(MailComposer, self).check_access_rule(operation)
|
||||
|
||||
@api.multi
|
||||
def _notify(self, force_send=False, user_signature=True):
|
||||
def _notify(self, layout=False, force_send=False, send_after_commit=True, values=None):
|
||||
""" Override specific notify method of mail.message, because we do
|
||||
not want that feature in the wizard. """
|
||||
return
|
||||
@@ -217,11 +217,6 @@ class MailComposer(models.TransientModel):
|
||||
|
||||
Mail = self.env['mail.mail']
|
||||
ActiveModel = self.env[wizard.model if wizard.model else 'mail.thread']
|
||||
if wizard.template_id:
|
||||
# template user_signature is added when generating body_html
|
||||
# mass mailing: use template auto_delete value -> note, for emails mass mailing only
|
||||
Mail = Mail.with_context(mail_notify_user_signature=False)
|
||||
ActiveModel = ActiveModel.with_context(mail_notify_user_signature=False, mail_auto_delete=wizard.template_id.auto_delete)
|
||||
if not hasattr(ActiveModel, 'message_post'):
|
||||
ActiveModel = self.env['mail.thread'].with_context(thread_model=wizard.model)
|
||||
if wizard.composition_mode == 'mass_post':
|
||||
@@ -257,6 +252,10 @@ class MailComposer(models.TransientModel):
|
||||
message_type=wizard.message_type,
|
||||
subtype_id=subtype_id,
|
||||
notif_layout=notif_layout,
|
||||
notif_values={
|
||||
'add_sign': not bool(wizard.template_id),
|
||||
'mail_auto_delete': wizard.template_id.auto_delete if wizard.template_id else False,
|
||||
},
|
||||
**mail_values)
|
||||
|
||||
if wizard.composition_mode == 'mass_mail':
|
||||
|
||||
@@ -998,7 +998,7 @@ class Task(models.Model):
|
||||
res['headers'] = repr(headers)
|
||||
return res
|
||||
|
||||
def _message_post_after_hook(self, message, values, notif_layout):
|
||||
def _message_post_after_hook(self, message, values, notif_layout, notif_values):
|
||||
if self.email_from and not self.partner_id:
|
||||
# we consider that posting a message with a specified recipient (not a follower, a specific one)
|
||||
# on a document without customer means that it was created through the chatter using
|
||||
@@ -1009,7 +1009,7 @@ class Task(models.Model):
|
||||
('partner_id', '=', False),
|
||||
('email_from', '=', new_partner.email),
|
||||
('stage_id.fold', '=', False)]).write({'partner_id': new_partner.id})
|
||||
return super(Task, self)._message_post_after_hook(message, values, notif_layout)
|
||||
return super(Task, self)._message_post_after_hook(message, values, notif_layout, notif_values)
|
||||
|
||||
def action_assign_to_me(self):
|
||||
self.write({'user_id': self.env.user.id})
|
||||
|
||||
@@ -63,10 +63,11 @@ class TestMessagePost(BaseFunctionalTest, MockEmails, TestRecipients):
|
||||
def test_post_notifications_keep_emails(self):
|
||||
self.test_record.message_subscribe_users(user_ids=[self.user_admin.id])
|
||||
|
||||
msg = self.test_record.sudo(self.user_employee).with_context(mail_auto_delete=False).message_post(
|
||||
msg = self.test_record.sudo(self.user_employee).message_post(
|
||||
body='Test', subject='Test',
|
||||
message_type='comment', subtype='mt_comment',
|
||||
partner_ids=[self.partner_1.id, self.partner_2.id]
|
||||
partner_ids=[self.partner_1.id, self.partner_2.id],
|
||||
notif_values={'mail_auto_delete': False}
|
||||
)
|
||||
|
||||
# notifications emails should not have been deleted: one for customers, one for user
|
||||
|
||||
@@ -159,7 +159,7 @@ class Track(models.Model):
|
||||
track._message_add_suggested_recipient(recipients, email=track.partner_email, reason=_('Speaker Email'))
|
||||
return recipients
|
||||
|
||||
def _message_post_after_hook(self, message, values, notif_layout):
|
||||
def _message_post_after_hook(self, message, values, notif_layout, notif_values):
|
||||
if self.partner_email and not self.partner_id:
|
||||
# we consider that posting a message with a specified recipient (not a follower, a specific one)
|
||||
# on a document without customer means that it was created through the chatter using
|
||||
@@ -171,7 +171,7 @@ class Track(models.Model):
|
||||
('partner_email', '=', new_partner.email),
|
||||
('stage_id.is_cancel', '=', False),
|
||||
]).write({'partner_id': new_partner.id})
|
||||
return super(Track, self)._message_post_after_hook(message, values, notif_layout)
|
||||
return super(Track, self)._message_post_after_hook(message, values, notif_layout, notif_values)
|
||||
|
||||
@api.multi
|
||||
def open_track_speakers_list(self):
|
||||
|
||||
Reference in New Issue
Block a user