diff --git a/addons/calendar/data/calendar_cron.xml b/addons/calendar/data/calendar_cron.xml
index 6502fffde90..abc885058dd 100644
--- a/addons/calendar/data/calendar_cron.xml
+++ b/addons/calendar/data/calendar_cron.xml
@@ -6,7 +6,7 @@
Calendar: Event Reminder
code
- model._send_reminder_email()
+ model._send_reminder()
1
diff --git a/addons/calendar/models/calendar_alarm_manager.py b/addons/calendar/models/calendar_alarm_manager.py
index 2503245aede..bcebf12992a 100644
--- a/addons/calendar/models/calendar_alarm_manager.py
+++ b/addons/calendar/models/calendar_alarm_manager.py
@@ -135,9 +135,16 @@ class AlarmManager(models.AbstractModel):
})
return result
- @api.model
- def _send_reminder_email(self, partners=None):
- # Executed via cron
+ def _get_events_to_notify(self, ttype):
+ """
+ Get the events with an alarm of the given type between the cron
+ last call and now.
+
+ Please note that all new reminders created since the cron last
+ call with an alarm prior to the cron last call are skipped by
+ design. The attendees receive an invitation for any new event
+ already.
+ """
self.env.cr.execute('''
SELECT "event"."id"
FROM "calendar_event" AS "event"
@@ -146,20 +153,20 @@ class AlarmManager(models.AbstractModel):
JOIN "calendar_alarm" AS "alarm"
ON "event_alarm_rel"."calendar_alarm_id" = "alarm"."id"
WHERE (
- "alarm"."alarm_type" = 'email'
+ "alarm"."alarm_type" = %s
AND "event"."active"
AND "event"."start" - CAST("alarm"."duration" || ' ' || "alarm"."interval" AS Interval) >= %s
AND "event"."start" - CAST("alarm"."duration" || ' ' || "alarm"."interval" AS Interval) < now() at time zone 'utc'
- )''', [self.env.context['lastcall']])
+ )''', [ttype, self.env.context['lastcall']])
- domain = [
- ("event_id", "in", self.env.cr.fetchall()),
- ("state", "!=", "declined"),
- ]
- if partners is not None:
- domain.append(("partner_id", "in", partners.ids))
+ ids = [row[0] for row in self.env.cr.fetchall()]
+ return self.env['calendar.event'].browse(ids)
- attendees = self.env["calendar.attendee"].search(domain)
+ @api.model
+ def _send_reminder(self):
+ # Executed via cron
+ events = self._get_events_to_notify('email')
+ attendees = events.attendee_ids.filtered(lambda a: a.state != 'declined')
attendees._send_mail_to_attendees(
'calendar.calendar_template_meeting_reminder',
force_send=True,
diff --git a/addons/calendar/models/calendar_event.py b/addons/calendar/models/calendar_event.py
index 3a48a8c314e..703fb6a4e94 100644
--- a/addons/calendar/models/calendar_event.py
+++ b/addons/calendar/models/calendar_event.py
@@ -688,14 +688,23 @@ class Meeting(models.Model):
return True
+ def _get_trigger_alarm_types(self):
+ return ['email']
+
def _setup_alarms(self):
- """ Trigger the cron in the future for every email reminder """
+ """ Schedule cron triggers for future events """
cron = self.env.ref('calendar.ir_cron_scheduler_alarm')
+ alarm_manager = self.env['calendar.alarm_manager']
+ alarm_types = self._get_trigger_alarm_types()
+
for event in self:
- for alarm in (alarm for alarm in event.alarm_ids if alarm.alarm_type == 'email'):
- cron._trigger(at=event.start-timedelta(minutes=alarm.duration_minutes))
+ for alarm in (alarm for alarm in event.alarm_ids if alarm.alarm_type in alarm_types):
+ at = event.start - timedelta(minutes=alarm.duration_minutes)
+ if not cron.lastcall or at > cron.lastcall:
+ # Don't trigger for past alarms, they would be skipped by design
+ cron._trigger(at=at)
if any(alarm.alarm_type == 'notification' for alarm in event.alarm_ids):
- self.env['calendar.alarm_manager']._notify_next_alarm(event.partner_ids.ids)
+ alarm_manager._notify_next_alarm(event.partner_ids.ids)
@api.model_create_multi
def create(self, vals_list):
diff --git a/addons/calendar/tests/test_event_notifications.py b/addons/calendar/tests/test_event_notifications.py
index 611b4b36630..c13d71fa28c 100644
--- a/addons/calendar/tests/test_event_notifications.py
+++ b/addons/calendar/tests/test_event_notifications.py
@@ -169,4 +169,4 @@ class TestEventNotifications(TransactionCase, MailCase):
'message_type': 'user_notification',
'subtype': 'mail.mt_note',
}):
- self.env['calendar.alarm_manager'].with_context(lastcall=now - relativedelta(minutes=15))._send_reminder_email(self.partner)
+ self.env['calendar.alarm_manager'].with_context(lastcall=now - relativedelta(minutes=15))._send_reminder()
diff --git a/addons/calendar_sms/models/calendar.py b/addons/calendar_sms/models/calendar.py
index 433c72184ef..5c42e2754a2 100644
--- a/addons/calendar_sms/models/calendar.py
+++ b/addons/calendar_sms/models/calendar.py
@@ -27,6 +27,9 @@ class CalendarEvent(models.Model):
put_in_queue=False
)
+ def _get_trigger_alarm_types(self):
+ return super()._get_trigger_alarm_types() + ['sms']
+
class CalendarAlarm(models.Model):
_inherit = 'calendar.alarm'
@@ -40,33 +43,8 @@ class AlarmManager(models.AbstractModel):
_inherit = 'calendar.alarm_manager'
@api.model
- def get_next_mail(self):
+ def _send_reminder(self):
""" Cron method, overridden here to send SMS reminders as well
"""
- result = super(AlarmManager, self).get_next_mail()
-
- cron = self.env.ref('calendar.ir_cron_scheduler_alarm', raise_if_not_found=False)
- if not cron:
- # Like the super method, do nothing if cron doesn't exist anymore
- return result
-
- now = fields.Datetime.to_string(fields.Datetime.now())
- last_sms_cron = cron.lastcall
-
- interval_to_second = {
- "weeks": 7 * 24 * 60 * 60,
- "days": 24 * 60 * 60,
- "hours": 60 * 60,
- "minutes": 60,
- "seconds": 1
- }
-
- cron_interval = cron.interval_number * interval_to_second[cron.interval_type]
- events_data = self._get_next_potential_limit_alarm('sms', seconds=cron_interval)
-
- for event in self.env['calendar.event'].browse(events_data):
- max_delta = events_data[event.id]['max_duration']
- event_start = fields.Datetime.from_string(event.start)
- for alert in self.do_check_alarm_for_one_date(event_start, event, max_delta, 0, 'sms', after=last_sms_cron, missing=True):
- event.browse(alert['event_id'])._do_sms_reminder()
- return result
+ super()._send_reminder()
+ self._get_events_to_notify(ttype='sms')._do_sms_reminder()