def test_get_wrapped_user(self): user = CommCareUser.create(self.domain, 'wrapped-user-test', 'password') user.save() self.addCleanup(user.delete) wrapped = get_wrapped_owner(user._id) self.assertTrue(isinstance(wrapped, CommCareUser))
def is_valid_id(uploaded_id, domain, cache): if uploaded_id in cache: return cache[uploaded_id] owner = get_wrapped_owner(uploaded_id) return owner and is_user_or_case_sharing_group( owner) and owner.is_member_of(domain)
def id_to_choice_tuple(self, id_): for static_id, text in self.static_options: if (id_ == static_id[3:] and static_id[:3] == "t__") or id_ == static_id: return (static_id, text) owner = get_wrapped_owner(id_, support_deleted=True) if isinstance(owner, Group): ret = self._group_to_choice_tuple(owner) elif isinstance(owner, SQLLocation): ret = self.location_tuple(owner) elif isinstance(owner, (CommCareUser, WebUser)): ret = self.user_tuple(owner) elif owner is None: return None else: raise Exception("Unexpcted id: {}".format(id_)) if hasattr(owner, 'is_deleted'): if (callable(owner.is_deleted) and owner.is_deleted()) or owner.is_deleted == True: # is_deleted may be an attr or callable depending on owner type ret = (ret[0], 'Deleted - ' + ret[1]) return ret
def is_valid_owner(owner_id): owner = get_wrapped_owner(owner_id) if not owner: return False if isinstance(owner, Group) and not owner.case_sharing: return False return True
def testRecursiveUpdates(self): parent_case = self._make_case(self.other_user._id, self.other_user._id) case = self._make_case(self.other_user._id, self.other_user._id, index={'parent': ('parent-case', parent_case._id)}) subcase1 = self._make_case(self.other_user._id, self.other_user._id, index={'parent': ('parent-case', case._id)}) subcase2 = self._make_case(self.other_user._id, self.other_user._id, index={'parent': ('parent-case', case._id)}) subsub1 = self._make_case(self.other_user._id, self.other_user._id, index={'parent': ('parent-case', subcase1._id)}) subsub2 = self._make_case(self.other_user._id, self.other_user._id, index={'parent': ('parent-case', subcase1._id)}) cases = [case, subcase1, subcase2, subsub1, subsub2] for c in cases: self.assertEqual(self.other_user._id, c.owner_id) reconcile_ownership(case, self.user, recursive=True) case = CommCareCase.get(case._id) owner = get_wrapped_owner(get_owner_id(case)) self.assertTrue(isinstance(owner, Group)) self.assertTrue(self.other_user._id in owner.users) self.assertTrue(self.user._id in owner.users) self.assertTrue(owner.case_sharing) self.assertFalse(owner.reporting) for c in cases: c = CommCareCase.get(c._id) self.assertEqual(owner._id, c.owner_id) parent_case = CommCareCase.get(parent_case._id) self.assertEqual(self.other_user._id, parent_case.owner_id)
def recipient(self): handler = self.handler if handler.recipient == RECIPIENT_USER: return self.user elif handler.recipient == RECIPIENT_CASE: return CommConnectCase.get(self.case_id) elif handler.recipient == RECIPIENT_SURVEY_SAMPLE: return SurveySample.get(self.sample_id) elif handler.recipient == RECIPIENT_OWNER: return get_wrapped_owner(get_owner_id(self.case)) elif handler.recipient == RECIPIENT_PARENT_CASE: indices = self.case.indices for index in indices: # TODO: The data model allows for more than one parent. # For now, send to the first parent, but need to decide how to handle multiple ones. if index.identifier == "parent": return CommConnectCase.get(index.referenced_id) return None elif handler.recipient == RECIPIENT_SUBCASE: indices = self.case.reverse_indices recipients = [] for index in indices: if index.identifier == "parent": subcase = CommConnectCase.get(index.referenced_id) if case_matches_criteria(subcase, handler.recipient_case_match_type, handler.recipient_case_match_property, handler.recipient_case_match_value): recipients.append(subcase) return recipients else: return None
def get_owner_location(domain, owner_id): owner = get_wrapped_owner(owner_id) if not owner: return None if isinstance(owner, SQLLocation): return owner location_id = owner.get_location_id(domain) return SQLLocation.by_location_id(location_id) if location_id else None
def process_survey_keyword_actions(verified_number, survey_keyword, text, msg=None): from corehq.apps.reminders.models import ( RECIPIENT_SENDER, RECIPIENT_OWNER, RECIPIENT_USER_GROUP, METHOD_SMS, METHOD_SMS_SURVEY, METHOD_STRUCTURED_SMS, REMINDER_TYPE_KEYWORD_INITIATED, ) sender = verified_number.owner if sender.doc_type == "CommCareCase": case = sender else: case = None for survey_keyword_action in survey_keyword.actions: if survey_keyword_action.recipient == RECIPIENT_SENDER: contact = sender elif survey_keyword_action.recipient == RECIPIENT_OWNER: if sender.doc_type == "CommCareCase": contact = get_wrapped_owner(get_owner_id(sender)) else: contact = None elif survey_keyword_action.recipient == RECIPIENT_USER_GROUP: try: contact = Group.get(survey_keyword_action.recipient_id) assert contact.doc_type == "Group" assert contact.domain == verified_number.domain except Exception: contact = None else: contact = None if contact is None: continue if survey_keyword_action.action == METHOD_SMS: create_immediate_reminder( contact, METHOD_SMS, reminder_type=REMINDER_TYPE_KEYWORD_INITIATED, message=survey_keyword_action.message_content, case=case, ) elif survey_keyword_action.action == METHOD_SMS_SURVEY: create_immediate_reminder( contact, METHOD_SMS_SURVEY, reminder_type=REMINDER_TYPE_KEYWORD_INITIATED, form_unique_id=survey_keyword_action.form_unique_id, case=case, ) elif survey_keyword_action.action == METHOD_STRUCTURED_SMS: handle_structured_sms( survey_keyword, survey_keyword_action, sender, verified_number, text, send_response=True, msg=msg )
def _check_owner_id(self, owner_id): """ Raises InvalidOwner if the owner cannot own cases. Raises InvalidLocation if a location-restricted user tries to assign an owner outside their location hierarchy. Returns True if owner ID is valid. """ owner = get_wrapped_owner(owner_id) self._check_owner(owner, 'owner_id')
def get_user_from_usercase(usercase): if usercase.type != USERCASE_TYPE: raise ValueError(f"Expected '{USERCASE_TYPE}' case, got {usercase.type}") user = get_wrapped_owner(get_owner_id(usercase)) if not isinstance(user, CommCareUser): return None return user
def _cached_owner_id_to_display(owner_id): key = 'owner_id_to_display_cache_{id}'.format(id=owner_id) ret = cache.get(key) if ret: return ret owner = get_wrapped_owner(owner_id) if owner is None: return None else: ret = raw_username(owner.username) if isinstance(owner, CouchUser) else owner.name cache.set(key, ret) return ret
def is_valid_id(uploaded_id, domain, cache): if uploaded_id in cache: return cache[uploaded_id] owner = get_wrapped_owner(uploaded_id) return ( ( owner and is_user_or_case_sharing_group(owner) and owner.is_member_of(domain) ) or is_location_group(uploaded_id, domain) )
def testUserToGroup(self): # 2. If the case has an owner that is a user create a new case sharing group, # add that user and the new user to the case sharing group make the group the owner. case = self._make_case(self.other_user._id, self.other_user._id) self.assertEqual(self.other_user._id, case.owner_id) reconcile_ownership(case, self.user) case = CommCareCase.get(case._id) self.assertNotEqual(self.other_user._id, case.owner_id) owner = get_wrapped_owner(get_owner_id(case)) self.assertTrue(isinstance(owner, Group)) self.assertTrue(self.other_user._id in owner.users) self.assertTrue(self.user._id in owner.users) self.assertTrue(owner.case_sharing) self.assertFalse(owner.reporting)
def cached_owner_id_to_display(owner_id): from corehq.apps.users.cases import get_wrapped_owner from corehq.apps.users.models import CouchUser key = 'owner_id_to_display_cache_{id}'.format(id=owner_id) ret = cache.get(key) if ret: return ret owner = get_wrapped_owner(owner_id) if owner is None: return None else: ret = raw_username(owner.username) if isinstance(owner, CouchUser) else owner.name cache.set(key, ret) return ret
def assign_cases(caselist, owner_id, acting_user=None, update=None): """ Assign all cases in a list to an owner. Won't update if the owner is already set on the case. Doesn't touch parent cases or subcases. Returns the list of ids of cases that were reassigned. """ if not caselist: return def _assert(bool, msg): if not bool: raise CaseAssignmentError(msg) from corehq.apps.users.cases import get_wrapped_owner # "security" unique_domains = set([c.domain for c in caselist]) _assert( len(unique_domains) == 1, 'case list had cases spanning multiple domains') [domain] = unique_domains _assert(domain, 'domain for cases was empty') owner = get_wrapped_owner(owner_id) _assert(owner, 'no owner with id "%s" found' % owner_id) _assert(owner.domain == domain, 'owner was not in domain %s for cases' % domain) username = acting_user.username if acting_user else 'system' user_id = acting_user._id if acting_user else 'system' filtered_cases = set([c for c in caselist if c.owner_id != owner_id]) if filtered_cases: caseblocks = [ ElementTree.tostring( CaseBlock( create=False, case_id=c.case_id, owner_id=owner_id, update=update, ).as_xml()) for c in filtered_cases ] # todo: this should check whether the submit_case_blocks call actually succeeds device_id = __name__ + ".assign_cases" submit_case_blocks(caseblocks, domain, username=username, user_id=user_id, device_id=device_id) return [c._id for c in filtered_cases]
def id_to_choice_tuple(self, id_): for static_id, text in self.static_options: if (id_ == static_id[3:] and static_id[:3] == "t__") or id_ == static_id: return (static_id, text) owner = get_wrapped_owner(id_) if isinstance(owner, Group): return self._group_to_choice_tuple(owner) elif isinstance(owner, SQLLocation): return self.location_tuple(owner) elif isinstance(owner, (CommCareUser, WebUser)): return self.user_tuple(owner) elif owner is None: return None else: raise Exception("Unexpcted id: {}".format(id_))
def convert_owner_id_to_select_choice(owner_id, domain): utils = _CallCenterOwnerOptionsUtils(domain) for id, text in utils.static_options: if owner_id == id: return (id, text) owner = get_wrapped_owner(owner_id) if isinstance(owner, Group): return utils.reporting_group_tuple(owner) elif isinstance(owner, Location): return utils.location_tuple(owner.sql_location) elif isinstance(owner, CommCareUser): return utils.user_tuple(owner) elif owner is None: return None else: raise Exception("Unexpcted owner type")
def convert_owner_id_to_select_choice(owner_id, domain): utils = _CallCenterOwnerOptionsUtils(domain) for id, text in utils.static_options: if owner_id == id: return (id, text) owner = get_wrapped_owner(owner_id) if isinstance(owner, Group): return utils.reporting_group_tuple(owner) elif isinstance(owner, SQLLocation): return utils.location_tuple(owner) elif isinstance(owner, CommCareUser): return utils.user_tuple(owner) elif owner is None: return None else: raise Exception("Unexpcted owner type")
def __get_owner_result(self): """ memoized doesn't seem to work with overriding __getattr__ at the same time, so we cache the result using a private attribute. """ if self.__owner_result: return self.__owner_result owner = get_wrapped_owner(get_owner_id(self.__case)) if isinstance(owner, CouchUser): if owner.is_member_of(self.__domain): self.__owner_result = SimpleDictTemplateParam(_get_obj_template_info(owner)) elif isinstance(owner, (Group, SQLLocation)): if owner.domain == self.__domain: self.__owner_result = SimpleDictTemplateParam(_get_obj_template_info(owner)) self.__owner_result = self.__owner_result or SimpleMessagingTemplateParam(UNKNOWN_VALUE) return self.__owner_result
def assign_cases(caselist, owner_id, acting_user=None, update=None): """ Assign all cases in a list to an owner. Won't update if the owner is already set on the case. Doesn't touch parent cases or subcases. Returns the list of ids of cases that were reassigned. """ if not caselist: return def _assert(bool, msg): if not bool: raise CaseAssignmentError(msg) from corehq.apps.users.cases import get_wrapped_owner # "security" unique_domains = set([c.domain for c in caselist]) _assert(len(unique_domains) == 1, 'case list had cases spanning multiple domains') [domain] = unique_domains _assert(domain, 'domain for cases was empty') owner = get_wrapped_owner(owner_id) _assert(owner, 'no owner with id "%s" found' % owner_id) _assert(owner.domain == domain, 'owner was not in domain %s for cases' % domain) username = acting_user.username if acting_user else 'system' user_id = acting_user._id if acting_user else 'system' filtered_cases = set([c for c in caselist if c.owner_id != owner_id]) if filtered_cases: caseblocks = [ElementTree.tostring(CaseBlock( create=False, case_id=c._id, owner_id=owner_id, version=V2, update=update, ).as_xml(format_datetime=json_format_datetime)) for c in filtered_cases ] # todo: this should check whether the submit_case_blocks call actually succeeds submit_case_blocks(caseblocks, domain, username=username, user_id=user_id) return [c._id for c in filtered_cases]
def _check_owner_id(self, owner_id): """ Raises InvalidOwnerId if the owner cannot own cases. Raises InvalidLocation if a location-restricted user tries to assign an owner outside their location hierarchy. Returns True if owner ID is valid. """ if owner_id in self.id_cache: if isinstance(self.id_cache[owner_id], CaseRowError): raise self.id_cache[owner_id] return True owner = get_wrapped_owner(owner_id) try: _check_owner(owner, self.domain, self.user_id, self.accessible_locations) except CaseRowError as err: self.id_cache[owner_id] = err raise else: self.id_cache[owner_id] = True return True
def test_get_wrapped_group(self): group = Group(domain=self.domain, name='wrapped-group-test') group.save() wrapped = get_wrapped_owner(group._id) self.assertTrue(isinstance(wrapped, Group))
def test_get_wrapped_user(self): user = CommCareUser.create(self.domain, 'wrapped-user-test', 'password') user.save() wrapped = get_wrapped_owner(user._id) self.assertTrue(isinstance(wrapped, CommCareUser))
def is_valid_id(uploaded_id, domain, cache): if uploaded_id in cache: return cache[uploaded_id] owner = get_wrapped_owner(uploaded_id) return is_valid_owner(owner, domain)
def get_user_from_usercase(usercase): user = get_wrapped_owner(get_owner_id(usercase)) if not isinstance(user, CommCareUser): return None return user
def process_survey_keyword_actions(verified_number, survey_keyword, text, msg): sender = verified_number.owner case = None args = split_args(text, survey_keyword) logged_event = MessagingEvent.create_from_keyword(survey_keyword, sender) # Log a messaging subevent for the incoming message subevent = logged_event.create_subevent_for_single_sms( msg.couch_recipient_doc_type, msg.couch_recipient ) subevent.completed() add_msg_tags(msg, MessageMetadata(messaging_subevent_id=subevent.pk)) # Close any open sessions even if it's just an sms that we're # responding with. SQLXFormsSession.close_all_open_sms_sessions(verified_number.domain, verified_number.owner_id) if sender.doc_type == "CommCareCase": case = sender args = args[1:] elif sender.doc_type == "CommCareUser": if keyword_uses_form_that_requires_case(survey_keyword): if len(args) > 1: external_id = args[1] case, matches = get_case_by_external_id(verified_number.domain, external_id, sender) if matches == 0: send_keyword_response(verified_number, MSG_CASE_NOT_FOUND, logged_event) logged_event.error(MessagingEvent.ERROR_CASE_EXTERNAL_ID_NOT_FOUND) return elif matches > 1: send_keyword_response(verified_number, MSG_MULTIPLE_CASES_FOUND, logged_event) logged_event.error(MessagingEvent.ERROR_MULTIPLE_CASES_WITH_EXTERNAL_ID_FOUND) return else: send_keyword_response(verified_number, MSG_MISSING_EXTERNAL_ID, logged_event) logged_event.error(MessagingEvent.ERROR_NO_EXTERNAL_ID_GIVEN) return args = args[2:] else: args = args[1:] def cmp_fcn(a1, a2): a1_ss = (a1.action == METHOD_STRUCTURED_SMS) a2_ss = (a2.action == METHOD_STRUCTURED_SMS) if a1_ss and a2_ss: return 0 elif a1_ss: return -1 elif a2_ss: return 1 else: return 0 if case: subevent.case_id = case.get_id subevent.save() # Process structured sms actions first actions = sorted(survey_keyword.actions, cmp=cmp_fcn) for survey_keyword_action in actions: if survey_keyword_action.recipient == RECIPIENT_SENDER: contact = sender elif survey_keyword_action.recipient == RECIPIENT_OWNER: if sender.doc_type == "CommCareCase": contact = get_wrapped_owner(get_owner_id(sender)) else: contact = None elif survey_keyword_action.recipient == RECIPIENT_USER_GROUP: try: contact = Group.get(survey_keyword_action.recipient_id) assert contact.doc_type == "Group" assert contact.domain == verified_number.domain except Exception: contact = None else: contact = None if contact is None: continue if survey_keyword_action.action == METHOD_SMS: create_immediate_reminder(contact, METHOD_SMS, reminder_type=REMINDER_TYPE_KEYWORD_INITIATED, message=survey_keyword_action.message_content, case=case, logged_event=logged_event) elif survey_keyword_action.action == METHOD_SMS_SURVEY: create_immediate_reminder(contact, METHOD_SMS_SURVEY, reminder_type=REMINDER_TYPE_KEYWORD_INITIATED, form_unique_id=survey_keyword_action.form_unique_id, case=case, logged_event=logged_event) elif survey_keyword_action.action == METHOD_STRUCTURED_SMS: res = handle_structured_sms(survey_keyword, survey_keyword_action, sender, verified_number, text, send_response=True, msg=msg, case=case, text_args=args, logged_event=logged_event) if not res: # If the structured sms processing wasn't successful, don't # process any of the other actions return logged_event.completed()
def test_invalid_ids(self, invalid_id): self.assertEqual(None, get_wrapped_owner(invalid_id)) self.assertEqual(None, user_id_to_username(invalid_id))
def test_get_wrapped_group(self): group = Group(domain=self.domain, name='wrapped-group-test') group.save() self.addCleanup(group.delete) wrapped = get_wrapped_owner(group._id) self.assertTrue(isinstance(wrapped, Group))
def case_owner(self): if self.case: return get_wrapped_owner(get_owner_id(self.case)) return None
def process_survey_keyword_actions(verified_number, survey_keyword, text, msg): sender = verified_number.owner case = None args = split_args(text, survey_keyword) logged_event = MessagingEvent.create_from_keyword(survey_keyword, sender) # Log a messaging subevent for the incoming message subevent = logged_event.create_subevent_for_single_sms( msg.couch_recipient_doc_type, msg.couch_recipient, completed=True ) add_msg_tags(msg, MessageMetadata(messaging_subevent_id=subevent.pk)) # Close any open sessions even if it's just an sms that we're # responding with. SQLXFormsSession.close_all_open_sms_sessions(verified_number.domain, verified_number.owner_id) if is_commcarecase(sender): case = sender args = args[1:] elif isinstance(sender, CommCareUser): if keyword_uses_form_that_requires_case(survey_keyword): if len(args) > 1: external_id = args[1] case, matches = get_case_by_external_id(verified_number.domain, external_id, sender) if matches == 0: send_keyword_response(verified_number, MSG_CASE_NOT_FOUND, logged_event) logged_event.error(MessagingEvent.ERROR_CASE_EXTERNAL_ID_NOT_FOUND) return elif matches > 1: send_keyword_response(verified_number, MSG_MULTIPLE_CASES_FOUND, logged_event) logged_event.error(MessagingEvent.ERROR_MULTIPLE_CASES_WITH_EXTERNAL_ID_FOUND) return else: send_keyword_response(verified_number, MSG_MISSING_EXTERNAL_ID, logged_event) logged_event.error(MessagingEvent.ERROR_NO_EXTERNAL_ID_GIVEN) return args = args[2:] else: args = args[1:] def cmp_fcn(a1, a2): a1_ss = (a1.action == KeywordAction.ACTION_STRUCTURED_SMS) a2_ss = (a2.action == KeywordAction.ACTION_STRUCTURED_SMS) if a1_ss and a2_ss: return 0 elif a1_ss: return -1 elif a2_ss: return 1 else: return 0 if case: subevent.case_id = case.case_id subevent.save() # Process structured sms actions first actions = sorted(survey_keyword.keywordaction_set.all(), cmp=cmp_fcn) for survey_keyword_action in actions: if survey_keyword_action.recipient == KeywordAction.RECIPIENT_SENDER: contact = sender elif survey_keyword_action.recipient == KeywordAction.RECIPIENT_OWNER: if is_commcarecase(sender): contact = get_wrapped_owner(get_owner_id(sender)) else: contact = None elif survey_keyword_action.recipient == KeywordAction.RECIPIENT_USER_GROUP: try: contact = Group.get(survey_keyword_action.recipient_id) assert contact.doc_type == "Group" assert contact.domain == verified_number.domain except Exception: contact = None else: contact = None if contact is None: continue # contact can be either a user, case, group, or location if survey_keyword_action.action in (KeywordAction.ACTION_SMS, KeywordAction.ACTION_SMS_SURVEY): if isinstance(contact, Group): recipients = list(ScheduleInstance.expand_group(contact)) elif isinstance(contact, SQLLocation): recipients = list(ScheduleInstance.expand_location_ids(contact.domain, [contact.location_id])) else: recipients = [contact] recipient_is_sender = survey_keyword_action.recipient == KeywordAction.RECIPIENT_SENDER if survey_keyword_action.action == KeywordAction.ACTION_SMS: content = SMSContent(message={'*': survey_keyword_action.message_content}) content.set_context(case=case) elif survey_keyword_action.action == KeywordAction.ACTION_SMS_SURVEY: content = SMSSurveyContent( form_unique_id=survey_keyword_action.form_unique_id, expire_after=SQLXFormsSession.MAX_SESSION_LENGTH, ) content.set_context( case=case, critical_section_already_acquired=recipient_is_sender, ) else: raise ValueError("Unexpected action %s" % survey_keyword_action.action) for recipient in recipients: phone_entry = verified_number if recipient_is_sender else None content.send(recipient, logged_event, phone_entry=phone_entry) elif survey_keyword_action.action == KeywordAction.ACTION_STRUCTURED_SMS: res = handle_structured_sms(survey_keyword, survey_keyword_action, sender, verified_number, text, send_response=True, msg=msg, case=case, text_args=args, logged_event=logged_event) if not res: # If the structured sms processing wasn't successful, don't # process any of the other actions return logged_event.completed()
return 1 else: return 0 if case: subevent.case_id = case.case_id subevent.save() # Process structured sms actions first actions = sorted(survey_keyword.keywordaction_set.all(), cmp=cmp_fcn) for survey_keyword_action in actions: if survey_keyword_action.recipient == KeywordAction.RECIPIENT_SENDER: contact = sender elif survey_keyword_action.recipient == KeywordAction.RECIPIENT_OWNER: if is_commcarecase(sender): contact = get_wrapped_owner(get_owner_id(sender)) else: contact = None elif survey_keyword_action.recipient == KeywordAction.RECIPIENT_USER_GROUP: try: contact = Group.get(survey_keyword_action.recipient_id) assert contact.doc_type == "Group" assert contact.domain == verified_number.domain except Exception: contact = None else: contact = None if contact is None: continue
def _add_owner_to_template_params(case, result): owner = get_wrapped_owner(get_owner_id(case)) if owner: result['case']['owner'] = _get_obj_template_info(owner)
def process_survey_keyword_actions(verified_number, survey_keyword, text, msg): sender = verified_number.owner case = None args = split_args(text, survey_keyword) # Close any open sessions even if it's just an sms that we're # responding with. XFormsSession.close_all_open_sms_sessions(verified_number.domain, verified_number.owner_id) if sender.doc_type == "CommCareCase": case = sender args = args[1:] elif sender.doc_type == "CommCareUser": if keyword_uses_form_that_requires_case(survey_keyword): if len(args) > 1: external_id = args[1] case = get_case_by_external_id(verified_number.domain, external_id) if case is None or not user_can_access_case(sender, case): send_keyword_response(verified_number, MSG_CASE_NOT_FOUND) return else: send_keyword_response(verified_number, MSG_MISSING_EXTERNAL_ID) return args = args[2:] else: args = args[1:] def cmp_fcn(a1, a2): a1_ss = (a1.action == METHOD_STRUCTURED_SMS) a2_ss = (a2.action == METHOD_STRUCTURED_SMS) if a1_ss and a2_ss: return 0 elif a1_ss: return -1 elif a2_ss: return 1 else: return 0 # Process structured sms actions first actions = sorted(survey_keyword.actions, cmp=cmp_fcn) for survey_keyword_action in actions: if survey_keyword_action.recipient == RECIPIENT_SENDER: contact = sender elif survey_keyword_action.recipient == RECIPIENT_OWNER: if sender.doc_type == "CommCareCase": contact = get_wrapped_owner(get_owner_id(sender)) else: contact = None elif survey_keyword_action.recipient == RECIPIENT_USER_GROUP: try: contact = Group.get(survey_keyword_action.recipient_id) assert contact.doc_type == "Group" assert contact.domain == verified_number.domain except Exception: contact = None else: contact = None if contact is None: continue if survey_keyword_action.action == METHOD_SMS: create_immediate_reminder(contact, METHOD_SMS, reminder_type=REMINDER_TYPE_KEYWORD_INITIATED, message=survey_keyword_action.message_content, case=case) elif survey_keyword_action.action == METHOD_SMS_SURVEY: create_immediate_reminder(contact, METHOD_SMS_SURVEY, reminder_type=REMINDER_TYPE_KEYWORD_INITIATED, form_unique_id=survey_keyword_action.form_unique_id, case=case) elif survey_keyword_action.action == METHOD_STRUCTURED_SMS: res = handle_structured_sms(survey_keyword, survey_keyword_action, sender, verified_number, text, send_response=True, msg=msg, case=case, text_args=args) if not res: # If the structured sms processing wasn't successful, don't # process any of the other actions return