diff --git a/addons/mail/models/mail_notification.py b/addons/mail/models/mail_notification.py index fcd5834c56d..0a9fc951a0a 100644 --- a/addons/mail/models/mail_notification.py +++ b/addons/mail/models/mail_notification.py @@ -16,6 +16,7 @@ class MailNotification(models.Model): _description = 'Message Notifications' # origin + author_id = fields.Many2one('res.partner', 'Author', ondelete='set null') mail_message_id = fields.Many2one('mail.message', 'Message', index=True, ondelete='cascade', required=True) mail_mail_id = fields.Many2one('mail.mail', 'Mail', index=True, help='Optional mail_mail ID. Used mainly to optimize searches.') # recipient @@ -57,7 +58,10 @@ class MailNotification(models.Model): def init(self): self._cr.execute(""" CREATE INDEX IF NOT EXISTS mail_notification_res_partner_id_is_read_notification_status_mail_message_id - ON mail_notification (res_partner_id, is_read, notification_status, mail_message_id) + ON mail_notification (res_partner_id, is_read, notification_status, mail_message_id); + CREATE INDEX IF NOT EXISTS mail_notification_author_id_notification_status_failure + ON mail_notification (author_id, notification_status) + WHERE notification_status IN ('bounce', 'exception'); """) self.env.cr.execute( """CREATE UNIQUE INDEX IF NOT EXISTS unique_mail_message_id_res_partner_id_if_set diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 2b3ba2337ea..60acd6b7416 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -219,12 +219,18 @@ class MailThread(models.AbstractModel): def _compute_message_has_error(self): res = {} if self.ids: - self._cr.execute(""" SELECT msg.res_id, COUNT(msg.res_id) FROM mail_message msg - RIGHT JOIN mail_notification rel - ON rel.mail_message_id = msg.id AND rel.notification_status in ('exception','bounce') - WHERE msg.author_id = %s AND msg.model = %s AND msg.res_id in %s AND msg.message_type != 'user_notification' - GROUP BY msg.res_id""", - (self.env.user.partner_id.id, self._name, tuple(self.ids),)) + self.env.cr.execute(""" + SELECT msg.res_id, COUNT(msg.res_id) + FROM mail_message msg + INNER JOIN mail_notification notif + ON notif.mail_message_id = msg.id + WHERE notif.notification_status in ('exception', 'bounce') + AND notif.author_id = %(author_id)s + AND msg.model = %(model_name)s + AND msg.res_id in %(res_ids)s + AND msg.message_type != 'user_notification' + GROUP BY msg.res_id + """, {'author_id': self.env.user.partner_id.id, 'model_name': self._name, 'res_ids': tuple(self.ids)}) res.update(self._cr.fetchall()) for record in self: @@ -2187,6 +2193,7 @@ class MailThread(models.AbstractModel): inbox_pids = [r['id'] for r in recipients_data if r['notif'] == 'inbox'] if inbox_pids: notif_create_values = [{ + 'author_id': message.author_id.id, 'mail_message_id': message.id, 'res_partner_id': pid, 'notification_type': 'inbox', @@ -2313,6 +2320,7 @@ class MailThread(models.AbstractModel): 'mail_mail_id': new_email.id, }) notif_create_values += [{ + 'author_id': message.author_id.id, 'mail_message_id': message.id, 'res_partner_id': recipient_id, 'notification_type': 'email', diff --git a/addons/mail/models/res_partner.py b/addons/mail/models/res_partner.py index 2907006766c..88eb7184bb6 100644 --- a/addons/mail/models/res_partner.py +++ b/addons/mail/models/res_partner.py @@ -126,14 +126,14 @@ class Partner(models.Model): """Returns all messages, sent by the current partner, that have errors, in the format expected by the web client.""" self.ensure_one() - messages = self.env['mail.message'].search([ - ('has_error', '=', True), + notifications = self.env['mail.notification'].search([ ('author_id', '=', self.id), - ('res_id', '!=', 0), - ('model', '!=', False), - ('message_type', '!=', 'user_notification') + ('notification_status', 'in', ('bounce', 'exception')), + ('mail_message_id.message_type', '!=', 'user_notification'), + ('mail_message_id.model', '!=', False), + ('mail_message_id.res_id', '!=', 0), ]) - return messages._message_notification_format() + return notifications.mail_message_id._message_notification_format() def _get_channels_as_member(self): """Returns the channels of the partner.""" diff --git a/addons/mail/tests/common.py b/addons/mail/tests/common.py index d8331d8de05..2fe5f1bcb1b 100644 --- a/addons/mail/tests/common.py +++ b/addons/mail/tests/common.py @@ -737,6 +737,7 @@ class MailCase(MockEmail): n.is_read == nis_read ) self.assertTrue(partner_notif, 'Mail: not found notification for %s (type: %s, state: %s, message: %s)' % (partner, ntype, nstatus, message.id)) + self.assertEqual(partner_notif.author_id, partner_notif.mail_message_id.author_id, 'Mail: Message and notification should have the same author') # prepare further asserts if ntype == 'email': diff --git a/addons/mail/wizard/mail_resend_cancel.py b/addons/mail/wizard/mail_resend_cancel.py index ee919e2d7b1..3d454694b9e 100644 --- a/addons/mail/wizard/mail_resend_cancel.py +++ b/addons/mail/wizard/mail_resend_cancel.py @@ -24,10 +24,11 @@ class MailResendCancel(models.TransientModel): FROM mail_notification notif JOIN mail_message mes ON notif.mail_message_id = mes.id - WHERE notif.notification_type = 'email' AND notif.notification_status IN ('bounce', 'exception') - AND mes.model = %s - AND mes.author_id = %s - """, (wizard.model, author_id)) + WHERE notif.notification_type = 'email' + AND notif.author_id = %(author_id)s + AND notif.notification_status IN ('bounce', 'exception') + AND mes.model = %(model_name)s + """, {'model_name': wizard.model, 'author_id': author_id}) res = self._cr.fetchall() notif_ids = [row[0] for row in res] messages_ids = list(set([row[1] for row in res])) diff --git a/addons/sms/models/mail_thread.py b/addons/sms/models/mail_thread.py index 7954b523dba..9cdffa9a825 100644 --- a/addons/sms/models/mail_thread.py +++ b/addons/sms/models/mail_thread.py @@ -20,12 +20,19 @@ class MailThread(models.AbstractModel): def _compute_message_has_sms_error(self): res = {} if self.ids: - self._cr.execute(""" SELECT msg.res_id, COUNT(msg.res_id) FROM mail_message msg - RIGHT JOIN mail_notification rel - ON rel.mail_message_id = msg.id AND rel.notification_type = 'sms' AND rel.notification_status in ('exception') - WHERE msg.author_id = %s AND msg.model = %s AND msg.res_id in %s AND msg.message_type != 'user_notification' - GROUP BY msg.res_id""", - (self.env.user.partner_id.id, self._name, tuple(self.ids),)) + self.env.cr.execute(""" + SELECT msg.res_id, COUNT(msg.res_id) + FROM mail_message msg + INNER JOIN mail_notification notif + ON notif.mail_message_id = msg.id + WHERE notif.notification_type = 'sms' + AND notif.notification_status = 'exception' + AND notif.author_id = %(author_id)s + AND msg.model = %(model_name)s + AND msg.res_id in %(res_ids)s + AND msg.message_type != 'user_notification' + GROUP BY msg.res_id + """, {'author_id': self.env.user.partner_id.id, 'model_name': self._name, 'res_ids': tuple(self.ids)}) res.update(self._cr.fetchall()) for record in self: @@ -331,6 +338,7 @@ class MailThread(models.AbstractModel): existing_numbers.append(n.sms_number) notif_create_values = [{ + 'author_id': message.author_id.id, 'mail_message_id': message.id, 'res_partner_id': sms.partner_id.id, 'sms_number': sms.number, diff --git a/addons/sms/tests/common.py b/addons/sms/tests/common.py index e3cfa7eb817..86d9f82945c 100644 --- a/addons/sms/tests/common.py +++ b/addons/sms/tests/common.py @@ -218,6 +218,7 @@ class SMSCase(MockSMS): notif = notifications.filtered(lambda n: n.res_partner_id == partner and n.sms_number == number and n.notification_status == state) self.assertTrue(notif, 'SMS: not found notification for %s (number: %s, state: %s)' % (partner, number, state)) + self.assertEqual(notif.author_id, notif.mail_message_id.author_id, 'SMS: Message and notification should have the same author') if state not in ('sent', 'ready', 'canceled'): self.assertEqual(notif.failure_type, recipient_info['failure_type']) diff --git a/addons/snailmail/models/snailmail_letter.py b/addons/snailmail/models/snailmail_letter.py index 95ae0a08aa1..5531dc3125d 100644 --- a/addons/snailmail/models/snailmail_letter.py +++ b/addons/snailmail/models/snailmail_letter.py @@ -100,6 +100,7 @@ class SnailmailLetter(models.Model): notification_vals = [] for letter in letters: notification_vals.append({ + 'author_id': letter.message_id.author_id.id, 'mail_message_id': letter.message_id.id, 'res_partner_id': letter.partner_id.id, 'notification_type': 'snail', diff --git a/addons/test_mail_full/tests/test_sms_management.py b/addons/test_mail_full/tests/test_sms_management.py index af7602d62a8..4c23005bafb 100644 --- a/addons/test_mail_full/tests/test_sms_management.py +++ b/addons/test_mail_full/tests/test_sms_management.py @@ -26,6 +26,7 @@ class TestSMSActionsCommon(TestMailFullCommon, TestMailFullRecipients): 'state': 'error', }) cls.notif_p1 = cls.env['mail.notification'].create({ + 'author_id': cls.msg.author_id.id, 'mail_message_id': cls.msg.id, 'res_partner_id': cls.partner_1.id, 'sms_id': cls.sms_p1.id, @@ -43,6 +44,7 @@ class TestSMSActionsCommon(TestMailFullCommon, TestMailFullRecipients): 'state': 'error', }) cls.notif_p2 = cls.env['mail.notification'].create({ + 'author_id': cls.msg.author_id.id, 'mail_message_id': cls.msg.id, 'res_partner_id': cls.partner_2.id, 'sms_id': cls.sms_p2.id,