From ff60189b5ff2739478296e7f419d4c5e438dd3c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 17 Jan 2024 10:15:41 +0100 Subject: [PATCH 1/6] [IMP] mail: add an helper for notification scheduled date Just extract some code we should otherwise copy in both mail_mobile and mail_enterprise. Task-3695571 Related to Task-3669738 (Mail: Web Push Models Rename and Fixes) X-original-commit: a6b0e88d00e1dcd4abbc1e37d62d65063c6956de Part-of: odoo/odoo#150011 --- addons/mail/models/mail_thread.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 2467daa741d..09c0a7eac29 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -2947,6 +2947,25 @@ class MailThread(models.AbstractModel): 'subtitles', } + @api.model + def _is_notification_scheduled(self, notify_cheduled_date): + """ Helper to check if notification are about to be scheduled. Eases + overrides. + + :param notify_scheduled_date: value of 'scheduled_date' given in + notification parameters: arbitrary datetime (as a date, datetime or + a string), may be void. See 'MailMail._parse_scheduled_datetime()'; + + :return bool: True if a valid datetime has been found and is in the + future; False otherwise. + """ + if notify_cheduled_date: + parsed_datetime = self.env['mail.mail']._parse_scheduled_datetime(notify_cheduled_date) + notify_cheduled_date = parsed_datetime.replace(tzinfo=None) if parsed_datetime else False + return ( + notify_cheduled_date and notify_cheduled_date > datetime.datetime.utcnow() + ) + def _raise_for_invalid_parameters(self, parameter_names, forbidden_names=None, restricting_names=None): """ Helper to warn about invalid parameters (or fields). From 13b80af02e9a1466f1916bcf3766f623770c1745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 12 Jan 2024 10:17:21 +0100 Subject: [PATCH 2/6] [FIX] mail: fix discuss.channel override of '_notify_get_recipients' (backport) Backport of odoo/odoo@e3125c83895259dc1a06b5ce88affd6789268d61 A lot of keys are missing compared to standard '_notify_get_recipients'. This is done in two methods that are updated to include keys defined in 'MailFollower._get_recipient_data()' that contains the reference structure to return. Task-3695571 Related to Task-3669738 (Mail: Web Push Models Rename and Fixes) X-original-commit: 7a46a957764aa5ee97a0a183fa1b747de85ff8ac Part-of: odoo/odoo#150011 --- addons/mail/models/discuss/discuss_channel.py | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/addons/mail/models/discuss/discuss_channel.py b/addons/mail/models/discuss/discuss_channel.py index b5b1260fd75..16c987dc4b3 100644 --- a/addons/mail/models/discuss/discuss_channel.py +++ b/addons/mail/models/discuss/discuss_channel.py @@ -497,8 +497,10 @@ class Channel(models.Model): self.env['res.users'].flush_model(['notification_type', 'partner_id']) sql_query = """ SELECT DISTINCT ON (partner.id) partner.id, + partner.lang, partner.partner_share, - users.notification_type + COALESCE(users.notification_type, 'email') as notif, + COALESCE(users.share, FALSE) as ushare FROM res_partner partner LEFT JOIN res_users users on partner.id = users.partner_id WHERE partner.active IS TRUE @@ -508,15 +510,19 @@ class Channel(models.Model): sql_query, (email_from or '', list(pids), [author_id] if author_id else [], ) ) - for partner_id, partner_share, notif in self._cr.fetchall(): + for partner_id, lang, partner_share, notif, ushare in self._cr.fetchall(): # ocn_client: will add partners to recipient recipient_data. more ocn notifications. We neeed to filter them maybe recipients_data.append({ - 'id': partner_id, - 'share': partner_share, 'active': True, - 'notif': notif or 'email', - 'type': 'user' if not partner_share and notif else 'customer', 'groups': [], + 'id': partner_id, + 'is_follower': False, + 'lang': lang, + 'notif': notif, + 'share': partner_share, + 'type': 'user' if not partner_share and notif else 'customer', + 'uid': False, + 'ushare': ushare, }) return recipients_data @@ -1273,12 +1279,17 @@ class Channel(models.Model): # add data into list but we do not modify item content channel_rdata = recipients_data.copy() channel_rdata += [ - {'id': partner.id, - 'share': partner.partner_share, - 'active': partner.active, - 'notif': 'web_push', - 'type': 'customer', - 'groups': [], + { + 'active': partner.active, + 'id': partner.id, + 'is_follower': False, + 'groups': [], + 'lang': partner.lang, + 'notif': 'web_push', + 'share': partner.partner_share, + 'type': 'customer', + 'uid': False, + 'ushare': False, } for partner in chat_channels.channel_member_ids.filtered(lambda member: not member.mute_until_dt).partner_id ] From e3aa094802c1777fc7052ce4d29e3a85e72dadfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 11 Jan 2024 16:36:19 +0100 Subject: [PATCH 3/6] [FIX] mail: fix discuss.channel sending two times push notification (backport) Backport of odoo/odoo@f312762c6a254ac0b399f9759bf17e5dcbb30454 '_notify_thread' calls '_notify_thread_by_web_push'. There is therefore no need to call it once again in discuss.channel override of '_notify_thread'. Task-3695571 Related to Task-3669738 (Mail: Web Push Models Rename and Fixes) Part-of: odoo/odoo#150011 --- addons/mail/models/discuss/discuss_channel.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/addons/mail/models/discuss/discuss_channel.py b/addons/mail/models/discuss/discuss_channel.py index 16c987dc4b3..ae12e035888 100644 --- a/addons/mail/models/discuss/discuss_channel.py +++ b/addons/mail/models/discuss/discuss_channel.py @@ -556,8 +556,6 @@ class Channel(models.Model): ] # sudo: bus.bus - sending on safe channel (discuss.channel) self.env["bus.bus"].sudo()._sendmany(bus_notifications) - if self.is_chat or self.channel_type == "group": - self._notify_thread_by_web_push(message, rdata, msg_vals, **kwargs) return rdata def _message_receive_bounce(self, email, partner): From 4882ef0a58da5c01ea363281ae55b2d71ebbe6f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 11 Jan 2024 16:45:17 +0100 Subject: [PATCH 4/6] [FIX] mail: fix discuss.channel notification recipients computation (backport) Backport of odoo/odoo@24ebd74dc94ec5ee4f2bd7ac3cd6e2fd8aa2a98a Recipients on a channel notification are computed twice: once using an override of '_notify_get_recipients' that fetches information of mentioned recipients; once in override of '_notify_by_web_push' to try to add recipients for push notifications. However this is not the right way to do it. Everything should be computed in '_notify_get_recipients', setting the right 'notification_type' and then let 'notify_by_MEAN' methods deal with their recipient input. In this commit we now correctly compute recipients on a given channel * mentioned partners; * unmuted members on chat channels (push); Task-3695571 Related to Task-3669738 (Mail: Web Push Models Rename and Fixes) Part-of: odoo/odoo#150011 --- addons/mail/models/discuss/discuss_channel.py | 57 ++++++++----------- addons/test_mail_full/tests/test_web_push.py | 2 +- 2 files changed, 25 insertions(+), 34 deletions(-) diff --git a/addons/mail/models/discuss/discuss_channel.py b/addons/mail/models/discuss/discuss_channel.py index ae12e035888..0a62ef8a33c 100644 --- a/addons/mail/models/discuss/discuss_channel.py +++ b/addons/mail/models/discuss/discuss_channel.py @@ -484,15 +484,11 @@ class Channel(models.Model): # notify only user input (comment or incoming / outgoing emails) if message_type not in ('comment', 'email', 'email_outgoing'): return [] - # notify only mailing lists or if mentioning recipients - if not pids: - return [] - - email_from = tools.email_normalize(msg_vals.get('email_from') or message.email_from) - author_id = msg_vals.get('author_id') or message.author_id.id recipients_data = [] if pids: + email_from = tools.email_normalize(msg_vals.get('email_from') or message.email_from) + author_id = msg_vals.get('author_id') or message.author_id.id self.env['res.partner'].flush_model(['active', 'email', 'partner_share']) self.env['res.users'].flush_model(['notification_type', 'partner_id']) sql_query = """ @@ -525,6 +521,28 @@ class Channel(models.Model): 'ushare': ushare, }) + if self.is_chat or self.channel_type == "group": + already_in_ids = [r['id'] for r in recipients_data] + recipients_data += [ + { + 'active': partner.active, + 'groups': [], + 'id': partner.id, + 'is_follower': False, + 'lang': partner.lang, + 'notif': 'web_push', + 'share': partner.partner_share, + 'type': 'customer', + 'uid': False, + 'ushare': False, + } for partner in self.channel_member_ids.filtered( + lambda member: ( + not member.mute_until_dt and + member.partner_id.id not in already_in_ids + ) + ).partner_id + ] + return recipients_data def _notify_get_recipients_groups(self, message, model_description, msg_vals=None): @@ -1269,33 +1287,6 @@ class Channel(models.Model): self._send_transient_message(self.env.user.partner_id, msg) - def _notify_thread_by_web_push(self, message, recipients_data, msg_vals=False, **kwargs): - """ Specifically handle channel members. """ - chat_channels = self.filtered(lambda channel: channel.channel_type == 'chat') - if chat_channels: - # modify rdata only for calling super. Do not deep copy as we only - # add data into list but we do not modify item content - channel_rdata = recipients_data.copy() - channel_rdata += [ - { - 'active': partner.active, - 'id': partner.id, - 'is_follower': False, - 'groups': [], - 'lang': partner.lang, - 'notif': 'web_push', - 'share': partner.partner_share, - 'type': 'customer', - 'uid': False, - 'ushare': False, - } - for partner in chat_channels.channel_member_ids.filtered(lambda member: not member.mute_until_dt).partner_id - ] - else: - channel_rdata = recipients_data - - return super()._notify_thread_by_web_push(message, channel_rdata, msg_vals=msg_vals, **kwargs) - def _notify_by_web_push_prepare_payload(self, message, msg_vals=False): payload = super()._notify_by_web_push_prepare_payload(message, msg_vals=msg_vals) payload['options']['data']['action'] = 'mail.action_discuss' diff --git a/addons/test_mail_full/tests/test_web_push.py b/addons/test_mail_full/tests/test_web_push.py index 24474c126e4..23fa04916ad 100644 --- a/addons/test_mail_full/tests/test_web_push.py +++ b/addons/test_mail_full/tests/test_web_push.py @@ -16,7 +16,7 @@ from unittest.mock import patch from types import SimpleNamespace -@tagged('post_install', '-at_install') +@tagged('post_install', '-at_install', 'mail_push') class TestWebPushNotification(SMSCommon): @classmethod From 940c168a204bf8a5b18040aea6b0c3e7bf5c05ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 11 Jan 2024 17:23:06 +0100 Subject: [PATCH 5/6] [FIX] mail: respect 'scheduled_date' for push notifications (backport) Backport of odoo/odoo@1955c55f8642cc6cabb3b18296e4cad6ef505553 Sending notifications can be delayed by giving 'scheduled_date' as parameter for notification process. This is used notably when a process in several steps should wait for some user input before sending notifications e.g. rating feedback and update done in two steps. Sending web push notifications should respect this scheduling as already done by inbox and email notifications. Task-3695571 Related to Task-3669738 (Mail: Web Push Models Rename and Fixes) Part-of: odoo/odoo#150011 --- addons/mail/models/mail_thread.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 09c0a7eac29..18ad7864f7d 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -3080,11 +3080,11 @@ class MailThread(models.AbstractModel): }) else: # generate immediately the - # and send the and the notifications + # and send the , and the notifications self._notify_thread_by_inbox(message, recipients_data, msg_vals=msg_vals, **kwargs) self._notify_thread_by_email(message, recipients_data, msg_vals=msg_vals, **kwargs) + self._notify_thread_by_web_push(message, recipients_data, msg_vals, **kwargs) - self._notify_thread_by_web_push(message, recipients_data, msg_vals, **kwargs) return recipients_data def _notify_thread_by_inbox(self, message, recipients_data, msg_vals=False, **kwargs): From 5b4cddb67ce40f7341117a837761b7a8ae3d26b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 22 Jan 2024 09:09:11 +0100 Subject: [PATCH 6/6] [FIX] mail: fix discuss channel accessing members / partners for notifications Now that code is fixed there are more access to channel members and partners to send them push notifications notably. Some tests are crashing when public users access channel pages and perform actions that send push notifications. Task-3695571 Related to Task-3669738 (Mail: Web Push Models Rename and Fixes) Part-of: odoo/odoo#150011 --- addons/mail/models/discuss/discuss_channel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/models/discuss/discuss_channel.py b/addons/mail/models/discuss/discuss_channel.py index 0a62ef8a33c..1410c86037e 100644 --- a/addons/mail/models/discuss/discuss_channel.py +++ b/addons/mail/models/discuss/discuss_channel.py @@ -535,7 +535,7 @@ class Channel(models.Model): 'type': 'customer', 'uid': False, 'ushare': False, - } for partner in self.channel_member_ids.filtered( + } for partner in self.sudo().channel_member_ids.filtered( lambda member: ( not member.mute_until_dt and member.partner_id.id not in already_in_ids