From 502e89ed6aed0553773fe552085b7950004a542a Mon Sep 17 00:00:00 2001 From: "Qiuyu (QHO)" Date: Fri, 19 Mar 2021 14:57:01 +0000 Subject: [PATCH] [FIX] mail: unfollow only if the partner is in the channel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before the commit, `_action_unfollow()` can be called by `_message_receive_bounce()` and then multiple leave notifications can be sent even if the partner has been removed from the channel, when the partner is a follower of the channel and without a valid email address. Unfollow action should also remove the partner from the followers, and only be processed if the partner is still a member of the channel. Task id: 2456233 closes odoo/odoo#68314 X-original-commit: 5cf22425eb68f15d94a8b283c50198561bbc240a Signed-off-by: Thibault Delavallee (tde) Signed-off-by: Sébastien Theys (seb) --- addons/mail/models/mail_channel.py | 3 ++ addons/mail/tests/test_mail_channel.py | 40 ++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py index d3f6100afe3..f82a73304c4 100644 --- a/addons/mail/models/mail_channel.py +++ b/addons/mail/models/mail_channel.py @@ -331,6 +331,9 @@ class Channel(models.Model): return self._action_unfollow(self.env.user.partner_id) def _action_unfollow(self, partner): + self.message_unsubscribe(partner.ids) + if partner not in self.with_context(active_test=False).channel_partner_ids: + return True channel_info = self.channel_info('unsubscribe')[0] # must be computed before leaving the channel (access rights) result = self.write({'channel_partner_ids': [Command.unlink(partner.id)]}) # side effect of unsubscribe that wasn't taken into account because diff --git a/addons/mail/tests/test_mail_channel.py b/addons/mail/tests/test_mail_channel.py index 2c3b138e965..99f4f3ac9e2 100644 --- a/addons/mail/tests/test_mail_channel.py +++ b/addons/mail/tests/test_mail_channel.py @@ -385,6 +385,46 @@ class TestChannelInternals(MailCommon): self.assertEqual(self.test_channel.channel_partner_ids, self.user_employee.partner_id | test_partner) self.assertEqual(test_chat.channel_partner_ids, self.user_employee.partner_id | test_partner) + def test_channel_unfollow_should_not_post_message_if_the_partner_has_been_removed(self): + ''' + When a partner leaves a channel, the system will help post a message under + that partner's name in the channel to notify others if `email_sent` is set `False`. + The message should only be posted when the partner is still a member of the channel + before method `_action_unfollow()` is called. + If the partner has been removed earlier, no more messages will be posted + even if `_action_unfollow()` is called again. + ''' + channel = self.env['mail.channel'].browse(self.test_channel.id) + channel.write({'email_send': False}) + channel._action_add_members(self.test_partner) + + # no message should be posted under test_partner's name + messages_0 = self.env['mail.message'].search([ + ('model', '=', 'mail.channel'), + ('res_id', '=', channel.id), + ('author_id', '=', self.test_partner.id) + ]) + self.assertEqual(len(messages_0), 0) + + # a message should be posted to notify others when a partner is about to leave + channel._action_unfollow(self.test_partner) + messages_1 = self.env['mail.message'].search([ + ('model', '=', 'mail.channel'), + ('res_id', '=', channel.id), + ('author_id', '=', self.test_partner.id) + ]) + self.assertEqual(len(messages_1), 1) + + # no more messages should be posted if the partner has been removed before. + channel._action_unfollow(self.test_partner) + messages_2 = self.env['mail.message'].search([ + ('model', '=', 'mail.channel'), + ('res_id', '=', channel.id), + ('author_id', '=', self.test_partner.id) + ]) + self.assertEqual(len(messages_2), 1) + self.assertEqual(messages_1, messages_2) + def test_multi_company_chat(self): self._activate_multi_company() self.assertEqual(self.env.user.company_id, self.company_admin)