def start_session_with_error_handling(domain, contact, app, module, form, case_id, keyword, logged_subevent=None): """ Returns (session, responses, error, error_code) """ try: session, responses = start_session(domain, contact, app, module, form, case_id=case_id, yield_responses=True) if logged_subevent: logged_subevent.xforms_session_id = session.pk logged_subevent.save() return (session, responses, False, None) except TouchformsError as e: human_readable_message = e.response_data.get('human_readable_message', None) logged_subevent.error(MessagingEvent.ERROR_TOUCHFORMS_ERROR, additional_error_text=human_readable_message) if touchforms_error_is_config_error(e): error_code = MSG_FORM_ERROR else: notify_exception(None, message=('Could not process structured sms for' 'contact %s, domain %s, keyword %s' % (contact.get_id, domain, keyword))) error_code = MSG_TOUCHFORMS_ERROR return (None, None, True, error_code)
def start_session_with_error_handling(domain, contact, app, module, form, case_id, keyword, logged_subevent=None): """ Returns (session, responses, error, error_code) """ try: session, responses = start_session(domain, contact, app, module, form, case_id=case_id, yield_responses=True) if logged_subevent: logged_subevent.xforms_session_id = session.pk logged_subevent.save() return (session, responses, False, None) except TouchformsError as e: human_readable_message = e.response_data.get('human_readable_message', None) logged_subevent.error(MessagingEvent.ERROR_TOUCHFORMS_ERROR, additional_error_text=human_readable_message) if touchforms_error_is_config_error(e): error_code = MSG_FORM_ERROR else: notify_exception(None, message=('Could not process structured sms for' 'contact %s, domain %s, keyword %s' % (contact._id, domain, keyword))) error_code = MSG_TOUCHFORMS_ERROR return (None, None, True, error_code)
def start_smsforms_session(self, domain, recipient, case_id, phone_entry_or_number, logged_subevent, workflow, app, module, form): # Close all currently open sessions SQLXFormsSession.close_all_open_sms_sessions(domain, recipient.get_id) # Start the new session try: session, responses = start_session( SQLXFormsSession.create_session_object( domain, recipient, (phone_entry_or_number.phone_number if isinstance(phone_entry_or_number, PhoneNumber) else phone_entry_or_number), app, form, expire_after=self.expire_after, reminder_intervals=self.reminder_intervals, submit_partially_completed_forms=self.submit_partially_completed_forms, include_case_updates_in_partial_submissions=self.include_case_updates_in_partial_submissions ), domain, recipient, app, module, form, case_id, yield_responses=True ) except TouchformsError as e: logged_subevent.error( MessagingEvent.ERROR_TOUCHFORMS_ERROR, additional_error_text=get_formplayer_exception(domain, e) ) if touchforms_error_is_config_error(domain, e): # Don't reraise the exception because this means there are configuration # issues with the form that need to be fixed. The error is logged in the # above lines. return None, None # Reraise the exception so that the framework retries it again later raise except: logged_subevent.error(MessagingEvent.ERROR_TOUCHFORMS_ERROR) # Reraise the exception so that the framework retries it again later raise session.workflow = workflow session.save() return session, responses
def start_smsforms_session(self, domain, recipient, case_id, phone_entry_or_number, logged_subevent, workflow, app, module, form): # Close all currently open sessions SQLXFormsSession.close_all_open_sms_sessions(domain, recipient.get_id) # Start the new session try: session, responses = start_session( SQLXFormsSession.create_session_object( domain, recipient, (phone_entry_or_number.phone_number if isinstance(phone_entry_or_number, PhoneNumber) else phone_entry_or_number), app, form, expire_after=self.expire_after, reminder_intervals=self.reminder_intervals, submit_partially_completed_forms=self.submit_partially_completed_forms, include_case_updates_in_partial_submissions=self.include_case_updates_in_partial_submissions ), domain, recipient, app, module, form, case_id, ) except TouchformsError as e: logged_subevent.error( MessagingEvent.ERROR_TOUCHFORMS_ERROR, additional_error_text=get_formplayer_exception(domain, e) ) if touchforms_error_is_config_error(domain, e): # Don't reraise the exception because this means there are configuration # issues with the form that need to be fixed. The error is logged in the # above lines. return None, None # Reraise the exception so that the framework retries it again later raise except: logged_subevent.error(MessagingEvent.ERROR_TOUCHFORMS_ERROR) # Reraise the exception so that the framework retries it again later raise session.workflow = workflow session.save() return session, responses
def start_session_for_structured_sms(domain, contact, phone_number, app, module, form, case_id, keyword, logged_subevent=None): """ Returns (session, responses, error, error_code) """ try: session, responses = start_session( SQLXFormsSession.create_session_object( domain, contact, phone_number.phone_number, app, form, expire_after=0, ), domain, contact, app, module, form, case_id=case_id, yield_responses=True) if logged_subevent: logged_subevent.xforms_session_id = session.pk logged_subevent.save() return (session, responses, False, None) except TouchformsError as e: human_readable_message = get_formplayer_exception(domain, e) logged_subevent.error(MessagingEvent.ERROR_TOUCHFORMS_ERROR, additional_error_text=human_readable_message) if touchforms_error_is_config_error(domain, e): error_code = MSG_FORM_ERROR else: notify_exception(None, message=('Could not process structured sms for' 'contact %s, domain %s, keyword %s' % (contact.get_id, domain, keyword))) error_code = MSG_TOUCHFORMS_ERROR return (None, None, True, error_code)
def start_session_for_structured_sms(domain, contact, phone_number, app, module, form, case_id, keyword, logged_subevent=None): """ Returns (session, responses, error, error_code) """ try: session, responses = start_session( SQLXFormsSession.create_session_object( domain, contact, phone_number.phone_number, app, form, expire_after=0, ), domain, contact, app, module, form, case_id=case_id, yield_responses=True ) if logged_subevent: logged_subevent.xforms_session_id = session.pk logged_subevent.save() return (session, responses, False, None) except TouchformsError as e: human_readable_message = get_formplayer_exception(domain, e) logged_subevent.error(MessagingEvent.ERROR_TOUCHFORMS_ERROR, additional_error_text=human_readable_message) if touchforms_error_is_config_error(domain, e): error_code = MSG_FORM_ERROR else: notify_exception(None, message=('Could not process structured sms for' 'contact %s, domain %s, keyword %s' % (contact.get_id, domain, keyword))) error_code = MSG_TOUCHFORMS_ERROR return (None, None, True, error_code)
def fire_sms_survey_event(reminder, handler, recipients, verified_numbers, logged_event): if reminder.callback_try_count > 0: # Handle timeouts if handler.submit_partial_forms and ( reminder.callback_try_count == len(reminder.current_event.callback_timeout_intervals) ): # Submit partial form completions for session_id in reminder.xforms_session_ids: submit_unfinished_form(session_id, handler.include_case_side_effects) else: # Resend current question for session_id in reminder.xforms_session_ids: session = get_session_by_session_id(session_id) if session.end_time is None: vn = VerifiedNumber.view( "sms/verified_number_by_owner_id", key=session.connection_id, include_docs=True ).first() if vn is not None: metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id, ) resp = current_question(session_id) send_sms_to_verified_number(vn, resp.event.text_prompt, metadata) else: reminder.xforms_session_ids = [] domain_obj = Domain.get_by_name(reminder.domain, strict=True) # Get the app, module, and form 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: logged_event.error(MessagingEvent.ERROR_CANNOT_FIND_FORM) return # Start a touchforms session for each recipient for recipient in recipients: logged_subevent = logged_event.create_subevent(handler, reminder, recipient) verified_number, unverified_number = get_recipient_phone_number(reminder, recipient, verified_numbers) no_verified_number = verified_number is None cant_use_unverified_number = ( unverified_number is None or not domain_obj.send_to_duplicated_case_numbers or form_requires_input(form) ) if no_verified_number and cant_use_unverified_number: logged_subevent.error(MessagingEvent.ERROR_NO_TWO_WAY_PHONE_NUMBER) continue key = "start-sms-survey-for-contact-%s" % recipient.get_id with CriticalSection([key], timeout=60): # Get the case to submit the form against, if any if isinstance(recipient, CommCareCase) and not handler.force_surveys_to_use_triggered_case: case_id = recipient.get_id else: case_id = reminder.case_id if form.requires_case() and not case_id: logged_subevent.error(MessagingEvent.ERROR_NO_CASE_GIVEN) continue # Close all currently open sessions SQLXFormsSession.close_all_open_sms_sessions(reminder.domain, recipient.get_id) # Start the new session try: session, responses = start_session( reminder.domain, recipient, app, module, form, case_id, case_for_case_submission=handler.force_surveys_to_use_triggered_case, ) except TouchformsError as e: human_readable_message = e.response_data.get("human_readable_message", None) logged_subevent.error( MessagingEvent.ERROR_TOUCHFORMS_ERROR, additional_error_text=human_readable_message ) if touchforms_error_is_config_error(e): # Don't reraise the exception because this means there are configuration # issues with the form that need to be fixed continue else: # Reraise the exception so that the framework retries it again later raise except Exception as e: logged_subevent.error(MessagingEvent.ERROR_TOUCHFORMS_ERROR) # Reraise the exception so that the framework retries it again later raise session.survey_incentive = handler.survey_incentive session.workflow = get_workflow(handler) session.reminder_id = reminder._id session.save() reminder.xforms_session_ids.append(session.session_id) logged_subevent.xforms_session = session logged_subevent.save() # Send out first message if len(responses) > 0: message = format_message_list(responses) metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id ) if verified_number: send_sms_to_verified_number(verified_number, message, metadata) else: send_sms(reminder.domain, recipient, unverified_number, message, metadata) logged_subevent.completed()
def fire_sms_survey_event(reminder, handler, recipients, verified_numbers, logged_event): if reminder.callback_try_count > 0: # Handle timeouts if handler.submit_partial_forms and ( reminder.callback_try_count == len( reminder.current_event.callback_timeout_intervals)): # Submit partial form completions for session_id in reminder.xforms_session_ids: submit_unfinished_form(session_id, handler.include_case_side_effects) else: # Resend current question for session_id in reminder.xforms_session_ids: session = get_session_by_session_id(session_id) if session.end_time is None: vn = VerifiedNumber.view("sms/verified_number_by_owner_id", key=session.connection_id, include_docs=True).first() if vn is not None: metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id, ) resp = current_question(session_id) send_sms_to_verified_number(vn, resp.event.text_prompt, metadata) else: reminder.xforms_session_ids = [] domain_obj = Domain.get_by_name(reminder.domain, strict=True) # Get the app, module, and form 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: logged_event.error(MessagingEvent.ERROR_CANNOT_FIND_FORM) return # Start a touchforms session for each recipient for recipient in recipients: logged_subevent = logged_event.create_subevent( handler, reminder, recipient) verified_number, unverified_number = get_recipient_phone_number( reminder, recipient, verified_numbers) no_verified_number = verified_number is None cant_use_unverified_number = ( unverified_number is None or not domain_obj.send_to_duplicated_case_numbers or form_requires_input(form)) if no_verified_number and cant_use_unverified_number: logged_subevent.error( MessagingEvent.ERROR_NO_TWO_WAY_PHONE_NUMBER) continue key = "start-sms-survey-for-contact-%s" % recipient.get_id with CriticalSection([key], timeout=60): # Get the case to submit the form against, if any if (isinstance(recipient, CommCareCase) and not handler.force_surveys_to_use_triggered_case): case_id = recipient.get_id else: case_id = reminder.case_id if form.requires_case() and not case_id: logged_subevent.error(MessagingEvent.ERROR_NO_CASE_GIVEN) continue # Close all currently open sessions SQLXFormsSession.close_all_open_sms_sessions( reminder.domain, recipient.get_id) # Start the new session try: session, responses = start_session( reminder.domain, recipient, app, module, form, case_id, case_for_case_submission=handler. force_surveys_to_use_triggered_case) except TouchformsError as e: human_readable_message = e.response_data.get( 'human_readable_message', None) logged_subevent.error( MessagingEvent.ERROR_TOUCHFORMS_ERROR, additional_error_text=human_readable_message) if touchforms_error_is_config_error(e): # Don't reraise the exception because this means there are configuration # issues with the form that need to be fixed continue else: # Reraise the exception so that the framework retries it again later raise except Exception as e: logged_subevent.error( MessagingEvent.ERROR_TOUCHFORMS_ERROR) # Reraise the exception so that the framework retries it again later raise session.survey_incentive = handler.survey_incentive session.workflow = get_workflow(handler) session.reminder_id = reminder._id session.save() reminder.xforms_session_ids.append(session.session_id) logged_subevent.xforms_session = session logged_subevent.save() # Send out first message if len(responses) > 0: message = format_message_list(responses) metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id, ) if verified_number: send_sms_to_verified_number(verified_number, message, metadata) else: send_sms(reminder.domain, recipient, unverified_number, message, metadata) logged_subevent.completed()
def fire_sms_survey_event(reminder, handler, recipients, verified_numbers, logged_event): current_event = reminder.current_event if reminder.callback_try_count > 0: # Leaving this as an explicit reminder that all survey related actions now happen # in a different process. Eventually all of this code will be removed when we move # to the new reminders framework. pass else: reminder.xforms_session_ids = [] domain_obj = Domain.get_by_name(reminder.domain, strict=True) # Get the app, module, and form try: form_unique_id = current_event.form_unique_id form = Form.get_form(form_unique_id) app = form.get_app() module = form.get_module() except Exception: logged_event.error(MessagingEvent.ERROR_CANNOT_FIND_FORM) return # Start a touchforms session for each recipient for recipient in recipients: logged_subevent = logged_event.create_subevent( handler, reminder, recipient) verified_number, unverified_number = get_recipient_phone_number( reminder, recipient, verified_numbers) no_verified_number = verified_number is None cant_use_unverified_number = (unverified_number is None or form_requires_input(form)) if no_verified_number and cant_use_unverified_number: logged_subevent.error( MessagingEvent.ERROR_NO_TWO_WAY_PHONE_NUMBER) continue if verified_number: pb = PhoneBlacklist.get_by_phone_number_or_none( verified_number.phone_number) else: pb = PhoneBlacklist.get_by_phone_number_or_none( unverified_number) if pb and not pb.send_sms: logged_subevent.error(MessagingEvent.ERROR_PHONE_OPTED_OUT) continue with critical_section_for_smsforms_sessions(recipient.get_id): # Get the case to submit the form against, if any if (is_commcarecase(recipient) and not handler.force_surveys_to_use_triggered_case): case_id = recipient.case_id else: case_id = reminder.case_id if form.requires_case() and not case_id: logged_subevent.error(MessagingEvent.ERROR_NO_CASE_GIVEN) continue # Close all currently open sessions SQLXFormsSession.close_all_open_sms_sessions( reminder.domain, recipient.get_id) # Start the new session try: if current_event.callback_timeout_intervals: if handler.submit_partial_forms: expire_after = sum( current_event.callback_timeout_intervals) reminder_intervals = current_event.callback_timeout_intervals[: -1] else: expire_after = SQLXFormsSession.MAX_SESSION_LENGTH reminder_intervals = current_event.callback_timeout_intervals submit_partially_completed_forms = handler.submit_partial_forms include_case_updates_in_partial_submissions = handler.include_case_side_effects else: expire_after = SQLXFormsSession.MAX_SESSION_LENGTH reminder_intervals = [] submit_partially_completed_forms = False include_case_updates_in_partial_submissions = False session, responses = start_session( SQLXFormsSession.create_session_object( reminder.domain, recipient, verified_number.phone_number if verified_number else unverified_number, app, form, expire_after=expire_after, reminder_intervals=reminder_intervals, submit_partially_completed_forms= submit_partially_completed_forms, include_case_updates_in_partial_submissions= include_case_updates_in_partial_submissions), reminder.domain, recipient, app, module, form, case_id, case_for_case_submission=handler. force_surveys_to_use_triggered_case) except TouchformsError as e: human_readable_message = get_formplayer_exception( reminder.domain, e) logged_subevent.error( MessagingEvent.ERROR_TOUCHFORMS_ERROR, additional_error_text=human_readable_message) if touchforms_error_is_config_error(reminder.domain, e): # Don't reraise the exception because this means there are configuration # issues with the form that need to be fixed continue else: # Reraise the exception so that the framework retries it again later raise except Exception as e: logged_subevent.error( MessagingEvent.ERROR_TOUCHFORMS_ERROR) # Reraise the exception so that the framework retries it again later raise session.survey_incentive = handler.survey_incentive session.workflow = get_workflow(handler) session.reminder_id = reminder._id session.save() reminder.xforms_session_ids.append(session.session_id) logged_subevent.xforms_session = session logged_subevent.save() # Send out first message if len(responses) > 0: message = format_message_list(responses) metadata = MessageMetadata( workflow=get_workflow(handler), reminder_id=reminder._id, xforms_session_couch_id=session._id, ) if verified_number: send_sms_to_verified_number( verified_number, message, metadata, logged_subevent=logged_subevent) else: send_sms(reminder.domain, recipient, unverified_number, message, metadata) logged_subevent.completed()