def fire(self, reminder): """ Sends the message associated with the given CaseReminder's current event. reminder The CaseReminder which to fire. return True on success, False on failure """ # Get the proper recipient recipient = reminder.recipient # Retrieve the VerifiedNumber entry for the recipient try: verified_number = recipient.get_verified_number() except Exception: verified_number = None # Get the language of the recipient try: lang = recipient.get_language_code() except Exception: lang = None if reminder.method == "survey": # Close all currently open sessions sessions = XFormsSession.view("smsforms/open_sessions_by_connection", key=[reminder.domain, recipient.get_id], include_docs=True).all() for session in sessions: session.end(False) session.save() # Start the new session try: form_unique_id = reminder.current_event.form_unique_id form = Form.get_form(form_unique_id) app = form.get_app() module = form.get_module() except Exception as e: print e print "ERROR: Could not load survey form for handler " + reminder.handler_id + ", event " + str(reminder.current_event_sequence_num) return False session, responses = start_session(reminder.domain, recipient, app, module, form, reminder.case_id) # Send out first message if len(responses) > 0: message = format_message_list(responses) if verified_number is not None: return send_sms_to_verified_number(verified_number, message) else: return True else: # If it is a callback reminder and the callback has been received, skip sending the next timeout message if (reminder.method == "callback" or reminder.method == "callback_test") and len(reminder.current_event.callback_timeout_intervals) > 0 and (reminder.callback_try_count > 0): if CallLog.inbound_call_exists(recipient.doc_type, recipient._id, reminder.last_fired): reminder.callback_received = True return True elif len(reminder.current_event.callback_timeout_intervals) == reminder.callback_try_count: # On the last callback timeout, instead of sending the SMS again, log the missed callback event = EventLog( domain = reminder.domain, date = self.get_now(), event_type = MISSED_EXPECTED_CALLBACK ) if verified_number is not None: event.couch_recipient_doc_type = verified_number.owner_doc_type event.couch_recipient = verified_number.owner_id event.save() return True reminder.last_fired = self.get_now() message = reminder.current_event.message.get(lang, reminder.current_event.message[self.default_lang]) message = Message.render(message, case=reminder.case.case_properties()) if reminder.method == "sms" or reminder.method == "callback": if verified_number is not None: return send_sms_to_verified_number(verified_number, message) elif self.recipient == RECIPIENT_USER: # If there is no verified number, but the recipient is a CommCareUser, still try to send it try: phone_number = reminder.user.phone_number except Exception: # If the user has no phone number, we cannot send any SMS return False return send_sms(reminder.domain, reminder.user_id, phone_number, message) else: return False elif reminder.method == "test" or reminder.method == "callback_test": print(message) return True
def test_ok(self): self.assertEqual(self.handler.get_reminder(self.case), None) # Spawn CaseReminder CaseReminderHandler.now = datetime(year=2011, month=12, day=31, hour=23, minute=0) self.case.set_case_property('start_sending', 'ok') self.case.save() reminder = self.handler.get_reminder(self.case) self.assertNotEqual(reminder, None) self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=1, hour=7, minute=0)) self.assertEqual(reminder.start_date, date(year=2012, month=1, day=1)) self.assertEqual(reminder.schedule_iteration_num, 1) self.assertEqual(reminder.current_event_sequence_num, 0) self.assertEqual(reminder.last_fired, None) ###################### # Day1, 10:00 reminder CaseReminderHandler.now = datetime(year=2012, month=1, day=1, hour=7, minute=0) CaseReminderHandler.fire_reminders() reminder = self.handler.get_reminder(self.case) self.assertNotEqual(reminder, None) self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=1, hour=8, minute=0)) self.assertEqual(reminder.schedule_iteration_num, 1) self.assertEqual(reminder.current_event_sequence_num, 1) self.assertEqual(reminder.last_fired, CaseReminderHandler.now) # Day1, 11:00 reminder CaseReminderHandler.now = datetime(year=2012, month=1, day=1, hour=8, minute=1) CaseReminderHandler.fire_reminders() reminder = self.handler.get_reminder(self.case) self.assertNotEqual(reminder, None) self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=1, hour=8, minute=15)) self.assertEqual(reminder.schedule_iteration_num, 1) self.assertEqual(reminder.current_event_sequence_num, 1) self.assertEqual(reminder.last_fired, CaseReminderHandler.now) # Create a callback c = CallLog( couch_recipient_doc_type = "CommCareUser", couch_recipient = self.user_id, phone_number = "14445551234", direction = "I", date = datetime(year=2012, month=1, day=1, hour=8, minute=5) ) c.save() # Day1, 11:15 timeout (should move on to next day) CaseReminderHandler.now = datetime(year=2012, month=1, day=1, hour=8, minute=15) CaseReminderHandler.fire_reminders() reminder = self.handler.get_reminder(self.case) self.assertNotEqual(reminder, None) self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=2, hour=7, minute=0)) self.assertEqual(reminder.schedule_iteration_num, 2) self.assertEqual(reminder.current_event_sequence_num, 0) self.assertEqual(reminder.last_fired, datetime(year=2012, month=1, day=1, hour=8, minute=1)) ###################### # Day2, 10:00 reminder CaseReminderHandler.now = datetime(year=2012, month=1, day=2, hour=7, minute=0) CaseReminderHandler.fire_reminders() reminder = self.handler.get_reminder(self.case) self.assertNotEqual(reminder, None) self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=2, hour=8, minute=0)) self.assertEqual(reminder.schedule_iteration_num, 2) self.assertEqual(reminder.current_event_sequence_num, 1) self.assertEqual(reminder.last_fired, CaseReminderHandler.now) # Day2, 11:00 reminder CaseReminderHandler.now = datetime(year=2012, month=1, day=2, hour=8, minute=1) CaseReminderHandler.fire_reminders() reminder = self.handler.get_reminder(self.case) self.assertNotEqual(reminder, None) self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=2, hour=8, minute=15)) self.assertEqual(reminder.schedule_iteration_num, 2) self.assertEqual(reminder.current_event_sequence_num, 1) self.assertEqual(reminder.last_fired, CaseReminderHandler.now) # Day2, 11:15 timeout (should move on to next timeout) CaseReminderHandler.now = datetime(year=2012, month=1, day=2, hour=8, minute=15) CaseReminderHandler.fire_reminders() reminder = self.handler.get_reminder(self.case) self.assertNotEqual(reminder, None) self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=2, hour=8, minute=45)) self.assertEqual(reminder.schedule_iteration_num, 2) self.assertEqual(reminder.current_event_sequence_num, 1) self.assertEqual(reminder.last_fired, CaseReminderHandler.now) # Day2, 11:45 timeout (should move on to next day) CaseReminderHandler.now = datetime(year=2012, month=1, day=2, hour=8, minute=45) CaseReminderHandler.fire_reminders() reminder = self.handler.get_reminder(self.case) self.assertNotEqual(reminder, None) self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=3, hour=7, minute=0)) self.assertEqual(reminder.schedule_iteration_num, 3) self.assertEqual(reminder.current_event_sequence_num, 0) self.assertEqual(reminder.last_fired, datetime(year=2012, month=1, day=2, hour=8, minute=15)) # Ensure that a missed call was logged missed_call_datetime = json_format_datetime(CaseReminderHandler.now) missed_call = EventLog.view("sms/event_by_domain_date_recipient", key=["test", missed_call_datetime, "CommCareUser", self.user_id], include_docs=True).one() self.assertNotEqual(missed_call, None) self.assertEqual(missed_call.event_type, MISSED_EXPECTED_CALLBACK) ###################### # Day3, 10:00 reminder CaseReminderHandler.now = datetime(year=2012, month=1, day=3, hour=7, minute=0) CaseReminderHandler.fire_reminders() reminder = self.handler.get_reminder(self.case) self.assertNotEqual(reminder, None) self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=3, hour=8, minute=0)) self.assertEqual(reminder.schedule_iteration_num, 3) self.assertEqual(reminder.current_event_sequence_num, 1) self.assertEqual(reminder.last_fired, CaseReminderHandler.now) # Day3, 11:00 reminder CaseReminderHandler.now = datetime(year=2012, month=1, day=3, hour=8, minute=1) CaseReminderHandler.fire_reminders() reminder = self.handler.get_reminder(self.case) self.assertNotEqual(reminder, None) self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=3, hour=8, minute=15)) self.assertEqual(reminder.schedule_iteration_num, 3) self.assertEqual(reminder.current_event_sequence_num, 1) self.assertEqual(reminder.last_fired, CaseReminderHandler.now) # Day3, 11:15 timeout (should move on to next timeout) CaseReminderHandler.now = datetime(year=2012, month=1, day=3, hour=8, minute=15) CaseReminderHandler.fire_reminders() reminder = self.handler.get_reminder(self.case) self.assertNotEqual(reminder, None) self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=3, hour=8, minute=45)) self.assertEqual(reminder.schedule_iteration_num, 3) self.assertEqual(reminder.current_event_sequence_num, 1) self.assertEqual(reminder.last_fired, CaseReminderHandler.now) # Create a callback (with phone_number missing country code) c = CallLog( couch_recipient_doc_type = "CommCareUser", couch_recipient = self.user_id, phone_number = "4445551234", direction = "I", date = datetime(year=2012, month=1, day=3, hour=8, minute=22) ) c.save() # Day3, 11:45 timeout (should deactivate the reminder) CaseReminderHandler.now = datetime(year=2012, month=1, day=3, hour=8, minute=45) CaseReminderHandler.fire_reminders() reminder = self.handler.get_reminder(self.case) self.assertNotEqual(reminder, None) self.assertEqual(reminder.schedule_iteration_num, 4) self.assertEqual(reminder.current_event_sequence_num, 0) self.assertEqual(reminder.last_fired, datetime(year=2012, month=1, day=3, hour=8, minute=15)) self.assertEqual(reminder.active, False)