Use Celery for RB notifications
[cds-indico.git] / indico / modules / rb / tasks.py
blob03c5fb841ed1de410b49afb762f945183a57ae03
1 # This file is part of Indico.
2 # Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
4 # Indico is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3 of the
7 # License, or (at your option) any later version.
9 # Indico is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Indico; if not, see <http://www.gnu.org/licenses/>.
17 from collections import defaultdict
18 from datetime import datetime, date
20 from celery.schedules import crontab
22 from indico.core.celery import celery
23 from indico.core.config import Config
24 from indico.core.db import db
25 from indico.modules.rb import settings as rb_settings
26 from indico.modules.rb import logger
27 from indico.modules.rb.models.reservation_occurrences import ReservationOccurrence
28 from indico.modules.rb.models.reservations import Reservation, RepeatFrequency
29 from indico.modules.rb.models.rooms import Room
30 from indico.modules.rb.notifications.reservation_occurrences import (notify_upcoming_occurrence,
31 notify_reservation_digest)
32 from indico.util.date_time import get_month_end, round_up_month
35 def _build_notification_window_filter():
36 if datetime.now().hour >= rb_settings.get('notification_hour'):
37 # Both today and delayed notifications
38 return ReservationOccurrence.is_in_notification_window()
39 else:
40 # Delayed notifications only
41 return ReservationOccurrence.is_in_notification_window(exclude_first_day=True)
44 def _build_digest_window_filter():
45 if datetime.now().hour >= rb_settings.get('notification_hour'):
46 # Both today and delayed digests
47 return Room.is_in_digest_window()
48 else:
49 # Delayed digests only
50 return Room.is_in_digest_window(exclude_first_day=True)
53 @celery.periodic_task(name='roombooking_occurrences_digest', run_every=crontab(minute='15', hour='8'))
54 def roombooking_occurrences_digest():
55 if not Config.getInstance().getIsRoomBookingActive():
56 logger.info('Digest not sent because room booking is disabled')
57 return
58 if not rb_settings.get('notifications_enabled'):
59 logger.info('Digest not sent because notifications are globally disabled')
60 return
62 digest_start = round_up_month(date.today(), from_day=2)
63 digest_end = get_month_end(digest_start)
65 occurrences = ReservationOccurrence.find(
66 Room.notifications_enabled,
67 Reservation.is_accepted,
68 Reservation.repeat_frequency == RepeatFrequency.WEEK,
69 ReservationOccurrence.is_valid,
70 ReservationOccurrence.start_dt >= digest_start,
71 ReservationOccurrence.start_dt <= digest_end,
72 ~ReservationOccurrence.notification_sent,
73 _build_digest_window_filter(),
74 _join=[Reservation, Room]
77 digests = defaultdict(list)
78 for occurrence in occurrences:
79 digests[occurrence.reservation].append(occurrence)
81 try:
82 for reservation, occurrences in digests.iteritems():
83 notify_reservation_digest(reservation, occurrences)
84 for occurrence in occurrences:
85 occurrence.notification_sent = True
86 finally:
87 db.session.commit()
90 @celery.periodic_task(name='roombooking_occurrences', run_every=crontab(minute='15', hour='8'))
91 def roombooking_occurrences():
92 if not Config.getInstance().getIsRoomBookingActive():
93 logger.info('Notifications not sent because room booking is disabled')
94 return
95 if not rb_settings.get('notifications_enabled'):
96 logger.info('Notifications not sent because they are globally disabled')
97 return
99 occurrences = ReservationOccurrence.find(
100 Room.notifications_enabled,
101 Reservation.is_accepted,
102 Reservation.repeat_frequency != RepeatFrequency.WEEK,
103 ReservationOccurrence.is_valid,
104 ReservationOccurrence.start_dt >= datetime.now(),
105 ~ReservationOccurrence.notification_sent,
106 _build_notification_window_filter(),
107 _join=[Reservation, Room]
110 try:
111 for occ in occurrences:
112 notify_upcoming_occurrence(occ)
113 occ.notification_sent = True
114 if occ.reservation.repeat_frequency == RepeatFrequency.DAY:
115 occ.reservation.occurrences.update({'notification_sent': True})
116 finally:
117 db.session.commit()