* = auth_signup, calendar, im_livechat, snailmail_account, survey, test_mail,
web_editor, website_crm_iap_reveal, website_livechat
The aim of this PR is to improve/fix various flaws and limitation of the current
API, to make it easier to use and more efficient.
Notification are now defined with 3 distinct parts:
- the channel determines which client(s) should receive it
- the type determines how it should be handled
- the payload determines any extra information helpful for handling it
Channel
=======
Business code
-------------
- Record channel is introduced for ease of subscribing to and sending
notifications to specific partners, channels, documents, ...
- String channel is still supported (but it is converted internally to the tuple
channel).
- Tuple channel is still supported without any change (but should be avoided
whenever possible due to its complex syntax).
The channel is no longer sent to the client. When the channel was used for
business purpose, the information it contained has been moved into either the
new type, or the payload itself.
Technical note
--------------
All channels are now internally converted to the tuple (db, ...) channel, which
is necessary for the platform code (saas/sh).
Internally, the bus.bus table is not changed, type and payload are grouped
together into what was (and still is) called message.
Type
====
Type is introduced to uniformize the way notifications are sent and handled.
All existing notifications already had some kind of manually-built type in them.
This is now officially supported at the bus API.
In client code this will allow (to be done in future commits) to register one
handler per specific type, instead of having to iterate and to filter all
received notifications on every handler.
Payload
=======
Payload (ex message) did not change, it can still be anything depending on
business needs.
Few adaptations:
- When the type was included on the payload, the type has been moved to the new
type parameter.
- When the channel was used in business code, its data has been copied into the
payload.
task-1891151
closes odoo/odoo#79201
X-original-commit: 543af27c7d6836ffac9e80ff8490b6ddbd849221
Related: odoo/enterprise#21998
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
173 lines
6.7 KiB
Python
173 lines
6.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from unittest.mock import patch
|
|
from datetime import datetime, date
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
from odoo import fields
|
|
from odoo.tests.common import TransactionCase, new_test_user
|
|
from odoo.addons.base.tests.test_ir_cron import CronMixinCase
|
|
from odoo.addons.mail.tests.common import MailCase
|
|
|
|
|
|
class TestEventNotifications(TransactionCase, MailCase, CronMixinCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.event = cls.env['calendar.event'].create({
|
|
'name': "Doom's day",
|
|
'start': datetime(2019, 10, 25, 8, 0),
|
|
'stop': datetime(2019, 10, 27, 18, 0),
|
|
}).with_context(mail_notrack=True)
|
|
cls.user = new_test_user(cls.env, 'xav', email='em@il.com', notification_type='inbox')
|
|
cls.partner = cls.user.partner_id
|
|
|
|
def test_message_invite(self):
|
|
with self.assertSinglePostNotifications([{'partner': self.partner, 'type': 'inbox'}], {
|
|
'message_type': 'user_notification',
|
|
'subtype': 'mail.mt_note',
|
|
}):
|
|
self.event.partner_ids = self.partner
|
|
|
|
def test_message_invite_self(self):
|
|
with self.assertNoNotifications():
|
|
self.event.with_user(self.user).partner_ids = self.partner
|
|
|
|
def test_message_inactive_invite(self):
|
|
self.event.active = False
|
|
with self.assertNoNotifications():
|
|
self.event.partner_ids = self.partner
|
|
|
|
def test_message_set_inactive_invite(self):
|
|
self.event.active = False
|
|
with self.assertNoNotifications():
|
|
self.event.write({
|
|
'partner_ids': [(4, self.partner.id)],
|
|
'active': False,
|
|
})
|
|
|
|
def test_message_datetime_changed(self):
|
|
self.event.partner_ids = self.partner
|
|
"Invitation to Presentation of the new Calendar"
|
|
with self.assertSinglePostNotifications([{'partner': self.partner, 'type': 'inbox'}], {
|
|
'message_type': 'user_notification',
|
|
'subtype': 'mail.mt_note',
|
|
}):
|
|
self.event.start = fields.Datetime.now() + relativedelta(days=1)
|
|
|
|
def test_message_date_changed(self):
|
|
self.event.write({
|
|
'allday': True,
|
|
'start_date': fields.Date.today() + relativedelta(days=7),
|
|
'stop_date': fields.Date.today() + relativedelta(days=8),
|
|
})
|
|
self.event.partner_ids = self.partner
|
|
with self.assertSinglePostNotifications([{'partner': self.partner, 'type': 'inbox'}], {
|
|
'message_type': 'user_notification',
|
|
'subtype': 'mail.mt_note',
|
|
}):
|
|
self.event.start_date += relativedelta(days=-1)
|
|
|
|
def test_message_date_changed_past(self):
|
|
self.event.write({
|
|
'allday': True,
|
|
'start_date': fields.Date.today(),
|
|
'stop_date': fields.Date.today() + relativedelta(days=1),
|
|
})
|
|
self.event.partner_ids = self.partner
|
|
with self.assertNoNotifications():
|
|
self.event.write({'start': date(2019, 1, 1)})
|
|
|
|
def test_message_set_inactive_date_changed(self):
|
|
self.event.write({
|
|
'allday': True,
|
|
'start_date': date(2019, 10, 15),
|
|
'stop_date': date(2019, 10, 15),
|
|
})
|
|
self.event.partner_ids = self.partner
|
|
with self.assertNoNotifications():
|
|
self.event.write({
|
|
'start_date': self.event.start_date - relativedelta(days=1),
|
|
'active': False,
|
|
})
|
|
|
|
def test_message_inactive_date_changed(self):
|
|
self.event.write({
|
|
'allday': True,
|
|
'start_date': date(2019, 10, 15),
|
|
'stop_date': date(2019, 10, 15),
|
|
'active': False,
|
|
})
|
|
self.event.partner_ids = self.partner
|
|
with self.assertNoNotifications():
|
|
self.event.start_date += relativedelta(days=-1)
|
|
|
|
def test_message_add_and_date_changed(self):
|
|
self.event.partner_ids -= self.partner
|
|
with self.assertSinglePostNotifications([{'partner': self.partner, 'type': 'inbox'}], {
|
|
'message_type': 'user_notification',
|
|
'subtype': 'mail.mt_note',
|
|
}):
|
|
self.event.write({
|
|
'start': self.event.start - relativedelta(days=1),
|
|
'partner_ids': [(4, self.partner.id)],
|
|
})
|
|
|
|
def test_bus_notif(self):
|
|
alarm = self.env['calendar.alarm'].create({
|
|
'name': 'Alarm',
|
|
'alarm_type': 'notification',
|
|
'interval': 'minutes',
|
|
'duration': 30,
|
|
})
|
|
now = fields.Datetime.now()
|
|
with patch.object(fields.Datetime, 'now', lambda: now):
|
|
with self.assertBus([(self.env.cr.dbname, 'res.partner', self.partner.id)], [
|
|
{
|
|
"type": "calendar.alarm",
|
|
"payload": [{
|
|
"alarm_id": alarm.id,
|
|
"event_id": self.event.id,
|
|
"title": "Doom's day",
|
|
"message": self.event.display_time,
|
|
"timer": 20 * 60,
|
|
"notify_at": fields.Datetime.to_string(now + relativedelta(minutes=20)),
|
|
}],
|
|
},
|
|
]):
|
|
self.event.with_context(no_mail_to_attendees=True).write({
|
|
'start': now + relativedelta(minutes=50),
|
|
'stop': now + relativedelta(minutes=55),
|
|
'partner_ids': [(4, self.partner.id)],
|
|
'alarm_ids': [(4, alarm.id)]
|
|
})
|
|
|
|
def test_email_alarm(self):
|
|
now = fields.Datetime.now()
|
|
with self.capture_triggers('calendar.ir_cron_scheduler_alarm') as capt:
|
|
alarm = self.env['calendar.alarm'].create({
|
|
'name': 'Alarm',
|
|
'alarm_type': 'email',
|
|
'interval': 'minutes',
|
|
'duration': 20,
|
|
})
|
|
self.event.write({
|
|
'name': 'test event',
|
|
'start': now + relativedelta(minutes=15),
|
|
'stop': now + relativedelta(minutes=18),
|
|
'partner_ids': [fields.Command.link(self.partner.id)],
|
|
'alarm_ids': [fields.Command.link(alarm.id)],
|
|
})
|
|
|
|
capt.records.ensure_one()
|
|
self.assertLessEqual(capt.records.call_at, now)
|
|
|
|
with patch.object(fields.Datetime, 'now', lambda: now):
|
|
with self.assertSinglePostNotifications([{'partner': self.partner, 'type': 'inbox'}], {
|
|
'message_type': 'user_notification',
|
|
'subtype': 'mail.mt_note',
|
|
}):
|
|
self.env['calendar.alarm_manager'].with_context(lastcall=now - relativedelta(minutes=15))._send_reminder()
|