def test_at_noon(self): # at_noon returns a datetime with the right values dt = datetime.datetime(1970, 2, 3, 4, 5, 6, 7) result = at_noon(dt) self.assertEqual(12, result.hour) self.assertEqual(0, result.minute) self.assertEqual(0, result.second) self.assertEqual(0, result.microsecond)
def get_reminders(self): """ Return a list of all the reminders that should be sent about this election. They are in date order. The times are all computed from the start of polling. Each item is a dictionary with these fields: when: when the reminder should be sent (datetime) audience: 'whitelist' or 'registered' message_number: 1-7 reminder_number: 1-3 for messages 1-6, 1-4 for message 7 (if a recipient has already sent the report for a message, they are not sent reminders) sent: True if this reminder has been queued already """ polling_start = self.polling_start_time # Messages 1-6, the times around which we'll schedule reminders, and who to send them to messages = { 1: {"time": at_noon(polling_start - timedelta(hours=48)), "audience": "whitelist"}, 2: {"time": at_noon(polling_start - timedelta(hours=24)), "audience": "whitelist"}, 3: {"time": polling_start, "audience": "whitelist"}, 4: {"time": polling_start.replace(hour=12, minute=0), "audience": "registered"}, 5: {"time": polling_start.replace(hour=16, minute=0), "audience": "registered"}, 6: {"time": polling_start.replace(hour=20, minute=15), "audience": "registered"}, } # Send reminders 30 minutes before, 5 minutes before, and 30 minutes after each # message time (for messages 1-6) reminder_offsets = {1: timedelta(minutes=-30), 2: timedelta(minutes=-5), 3: timedelta(minutes=30)} # Compute all the reminder times # reminder_time[message_number][reminder_number] is the reminder datetime reminder_time = { message_number: { reminder_number: messages[message_number]["time"] + reminder_offsets[reminder_number] for reminder_number in sorted(reminder_offsets.keys()) } for message_number in sorted(messages.keys()) } # What tasks do we need to add? reminders = [ { "when": reminder_time[message_number][reminder_number], "message_number": message_number, "reminder_number": reminder_number, "audience": messages[message_number]["audience"], } for reminder_number in sorted(reminder_offsets.keys()) for message_number in sorted(messages.keys()) ] # Message 7 is kind of its own thing next_day = polling_start + timedelta(days=1) message_7_times = { 1: polling_start.replace(hour=21, minute=30), 2: polling_start.replace(hour=22, minute=30), 3: polling_start.replace(hour=23, minute=30), 4: next_day.replace(hour=8, minute=0), } message_number = 7 reminders += [ { "when": message_7_times[reminder_number], "message_number": message_number, "reminder_number": reminder_number, "audience": "registered", } for reminder_number in sorted(message_7_times.keys()) ] sent_already = set( [(item.message_number, item.reminder_number) for item in ReminderQueued.objects.filter(election=self)] ) for reminder in reminders: key = (reminder["message_number"], reminder["reminder_number"]) reminder["sent"] = key in sent_already return sorted(reminders, key=itemgetter("when"))
def get_reminders(self): """ Return a list of all the reminders that should be sent about this election. They are in date order. The times are all computed from the start of polling. Each item is a dictionary with these fields: when: when the reminder should be sent (datetime) audience: 'whitelist' or 'registered' message_number: 1-7 reminder_number: 1-3 for messages 1-6, 1-4 for message 7 (if a recipient has already sent the report for a message, they are not sent reminders) sent: True if this reminder has been queued already """ polling_start = self.polling_start_time # Messages 1-6, the times around which we'll schedule reminders, and who to send them to messages = { 1: { 'time': at_noon(polling_start - timedelta(hours=48)), 'audience': 'whitelist' }, 2: { 'time': at_noon(polling_start - timedelta(hours=24)), 'audience': 'whitelist' }, 3: { 'time': polling_start, 'audience': 'whitelist' }, 4: { 'time': polling_start.replace(hour=12, minute=0), 'audience': 'registered' }, 5: { 'time': polling_start.replace(hour=16, minute=0), 'audience': 'registered' }, 6: { 'time': polling_start.replace(hour=20, minute=15), 'audience': 'registered' }, } # Send reminders 30 minutes before, 5 minutes before, and 30 minutes after each # message time (for messages 1-6) reminder_offsets = { 1: timedelta(minutes=-30), 2: timedelta(minutes=-5), 3: timedelta(minutes=30), } # Compute all the reminder times # reminder_time[message_number][reminder_number] is the reminder datetime reminder_time = { message_number: { reminder_number: messages[message_number]['time'] + reminder_offsets[reminder_number] for reminder_number in sorted(reminder_offsets.keys()) } for message_number in sorted(messages.keys()) } # What tasks do we need to add? reminders = [{ 'when': reminder_time[message_number][reminder_number], 'message_number': message_number, 'reminder_number': reminder_number, 'audience': messages[message_number]['audience'] } for reminder_number in sorted(reminder_offsets.keys()) for message_number in sorted(messages.keys())] # Message 7 is kind of its own thing next_day = polling_start + timedelta(days=1) message_7_times = { 1: polling_start.replace(hour=21, minute=30), 2: polling_start.replace(hour=22, minute=30), 3: polling_start.replace(hour=23, minute=30), 4: next_day.replace(hour=8, minute=0), } message_number = 7 reminders += [{ 'when': message_7_times[reminder_number], 'message_number': message_number, 'reminder_number': reminder_number, 'audience': 'registered', } for reminder_number in sorted(message_7_times.keys())] sent_already = set([ (item.message_number, item.reminder_number) for item in ReminderQueued.objects.filter(election=self) ]) for reminder in reminders: key = (reminder['message_number'], reminder['reminder_number']) reminder['sent'] = key in sent_already return sorted(reminders, key=itemgetter('when'))