Exemple #1
0
 def get_matching_owner(case):
     if by_user_id:
         if case.user_id in by_user_id:
             return case.user_id
         elif get_owner_id(case) in by_user_id:
             return get_owner_id(case)
     else:
         return get_owner_id(case)
 def _to_fields(transaction):
     ret = {"requisition_status": RequisitionStatus.by_action_type(transaction.action_config.action_type)}
     if transaction.action_config.action_type == RequisitionActions.REQUEST:
         ret.update(
             {
                 "create": True,
                 "owner_id": get_owner_id(product_stock_case) or user_id,
                 "amount_requested": transaction.value,
                 "product_id": product_stock_case.product,
                 "requested_by": user_id,
                 "requested_on": datetime.utcnow(),
             }
         )
     elif transaction.action_config.action_type == RequisitionActions.APPROVAL:
         ret.update(
             {"amount_approved": transaction.value, "approved_by": user_id, "approved_on": datetime.utcnow()}
         )
     elif transaction.action_config.action_type == RequisitionActions.PACK:
         ret.update({"amount_packed": transaction.value, "packed_by": user_id, "packed_on": datetime.utcnow()})
     elif transaction.action_config.action_type == RequisitionActions.RECEIPTS:
         ret.update(
             {
                 "amount_received": transaction.value,
                 "received_by": user_id,
                 "received_on": datetime.utcnow(),
                 "close": True,
             }
         )
     else:
         raise ValueError("the type %s isn't yet supported." % transaction.action_config.action_type)
     return ret
    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)
Exemple #4
0
def make_supply_point_product(supply_point_case, product_uuid, owner_id=None):
    domain = supply_point_case.domain
    id = uuid.uuid4().hex
    user_id = get_commtrack_user_id(domain)
    owner_id = owner_id or get_owner_id(supply_point_case) or user_id
    username = const.COMMTRACK_USERNAME
    product_name = Product.get(product_uuid).name
    caseblock = CaseBlock(case_id=id,
                          create=True,
                          version=V2,
                          case_name=product_name,
                          user_id=user_id,
                          owner_id=owner_id,
                          case_type=const.SUPPLY_POINT_PRODUCT_CASE_TYPE,
                          update={"product": product_uuid},
                          index={
                              const.PARENT_CASE_REF:
                              (const.SUPPLY_POINT_CASE_TYPE,
                               supply_point_case._id),
                          })
    casexml = ElementTree.tostring(caseblock.as_xml())
    submit_case_blocks(casexml,
                       domain,
                       username,
                       user_id,
                       xmlns=const.COMMTRACK_SUPPLY_POINT_PRODUCT_XMLNS)
    return SupplyPointProductCase.get(id)
Exemple #5
0
def make_supply_point_product(supply_point_case, product_uuid, owner_id=None):
    domain = supply_point_case.domain
    id = uuid.uuid4().hex
    user_id = const.get_commtrack_user_id(domain)
    owner_id = owner_id or get_owner_id(supply_point_case) or user_id
    username = const.COMMTRACK_USERNAME
    product_name = Product.get(product_uuid).name
    caseblock = CaseBlock(
        case_id=id,
        create=True,
        version=V2,
        case_name=product_name,
        user_id=user_id,
        owner_id=owner_id,
        case_type=const.SUPPLY_POINT_PRODUCT_CASE_TYPE,
        update={
            "product": product_uuid
        },
        index={
            const.PARENT_CASE_REF: (const.SUPPLY_POINT_CASE_TYPE,
                                    supply_point_case._id),
        }
    )
    casexml = ElementTree.tostring(caseblock.as_xml())
    submit_case_blocks(casexml, domain, username, user_id,
                       xmlns=const.COMMTRACK_SUPPLY_POINT_PRODUCT_XMLNS)
    sppc = SupplyPointProductCase.get(id)
    sppc.bind_to_location(supply_point_case.location)
    sppc.save()
    return sppc
def get_notification_recipients(next_action, requisition):
    # given a status and list of requisitions, get the exhaustive list of
    # people to notify about the requisition entering that status.
    users = get_owning_users(get_owner_id(requisition))
    if len(users) == 1:
        return users
    return [u for u in users if should_notify_user(u, next_action.action_type)]
def get_notification_recipients(next_action, requisition):
    # given a status and list of requisitions, get the exhaustive list of
    # people to notify about the requisition entering that status.
    users = get_owning_users(get_owner_id(requisition))
    if len(users) == 1:
        return users
    return [u for u in users if should_notify_user(u, next_action.action_type)]
 def _to_fields(transaction):
     ret = {'requisition_status': RequisitionStatus.by_action_type(transaction.action_config.action_type)}
     if transaction.action_config.action_type == RequisitionActions.REQUEST:
         ret.update({
             'create': True,
             'owner_id': get_owner_id(product_stock_case) or user_id,
             'amount_requested': transaction.value,
             'product_id': product_stock_case.product,
             'requested_by': user_id,
             'requested_on': datetime.utcnow(),
         })
     elif transaction.action_config.action_type == RequisitionActions.APPROVAL:
         ret.update({
             'amount_approved': transaction.value,
             'approved_by': user_id,
             'approved_on': datetime.utcnow(),
         })
     elif transaction.action_config.action_type == RequisitionActions.PACK:
         ret.update({
             'amount_packed': transaction.value,
             'packed_by': user_id,
             'packed_on': datetime.utcnow(),
         })
     elif transaction.action_config.action_type == RequisitionActions.RECEIPTS:
         ret.update({
             'amount_received': transaction.value,
             'received_by': user_id,
             'received_on': datetime.utcnow(),
             'close': True,
         })
     else:
         raise ValueError("the type %s isn't yet supported." % transaction.action_config.action_type)
     return ret
Exemple #9
0
 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
Exemple #10
0
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
            )
Exemple #11
0
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
Exemple #12
0
 def get_root_element(self):
     from corehq.apps.users.cases import get_owner_id
     root = safe_element("case")
     root.attrib = {
         "case_id": self.case.case_id,
         "case_type": self.case.type,
         "owner_id": get_owner_id(self.case),
         "status": "closed" if self.case.closed else "open",
     }
     return root
 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)
Exemple #14
0
    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
Exemple #15
0
    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 _to_fields(transaction):
     ret = {
         'requisition_status':
         RequisitionStatus.by_action_type(
             transaction.action_config.action_type)
     }
     if transaction.action_config.action_type == RequisitionActions.REQUEST:
         ret.update({
             'create': True,
             'owner_id': get_owner_id(product_stock_case) or user_id,
             'amount_requested': transaction.value,
             'product_id': product_stock_case.product,
             'requested_by': user_id,
             'requested_on': datetime.utcnow(),
         })
     elif transaction.action_config.action_type == RequisitionActions.APPROVAL:
         ret.update({
             'amount_approved': transaction.value,
             'approved_by': user_id,
             'approved_on': datetime.utcnow(),
         })
     elif transaction.action_config.action_type == RequisitionActions.PACK:
         ret.update({
             'amount_packed': transaction.value,
             'packed_by': user_id,
             'packed_on': datetime.utcnow(),
         })
     elif transaction.action_config.action_type == RequisitionActions.RECEIPTS:
         ret.update({
             'amount_received': transaction.value,
             'received_by': user_id,
             'received_on': datetime.utcnow(),
             'close': True,
         })
     else:
         raise ValueError("the type %s isn't yet supported." %
                          transaction.action_config.action_type)
     return ret
Exemple #17
0
def _is_live(case, restore_state):
    """
    Given a case and a restore state object, return whether or not the case is "live"
    (direclty owned by this sync and open), or "dependent" (needed by another case)
    """
    return not case.closed and get_owner_id(case) in restore_state.owner_ids
Exemple #18
0
            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
Exemple #19
0
def get_user_from_usercase(usercase):
    user = get_wrapped_owner(get_owner_id(usercase))
    if not isinstance(user, CommCareUser):
        return None

    return user
Exemple #20
0
 def might_be_relevant(case):
     if filter_group:
         return get_owner_id(case) in owner_ids
     else:
         return not users or get_matching_owner(case)
Exemple #21
0
def get_user_from_usercase(usercase):
    user = get_wrapped_owner(get_owner_id(usercase))
    if not isinstance(user, CommCareUser):
        return None

    return user
Exemple #22
0
 def might_be_relevant(case):
     return not filter_group or get_owner_id(case) in owner_ids
Exemple #23
0
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()
Exemple #24
0
def export_cases(domain, cases, workbook, filter_group=None, users=None, all_groups=None, process=None):
    by_user_id = dict([(user.user_id, user) for user in users]) if users else {}
    by_group_id = dict([(g.get_id, g) for g in all_groups]) if all_groups else {}

    owner_ids = set(by_user_id.keys())
    if filter_group:
        owner_ids.add(filter_group.get_id)
    else:
        # |= reassigns owner_ids to the union of the two sets
        owner_ids |= set(by_group_id.keys())

    case_static_keys = (
        "case_id",
        "username",
        "user_id",
        "owner_id",
        "owner_name",
        "type",
        "name",
        "opened_on",
        "modified_on",
        "closed",
        "closed_on",
        "domain",
        "external_id",
    )
    case_dynamic_keys = get_case_properties(domain)
    case_rows = []

    def render_case_attr(case, key):
        attr = getattr(case, key)
        if isinstance (attr, dict):
            return attr.get('#text', '')
        else:
            return attr

    num_cases = len(cases)

    def get_matching_owner(case):
        if by_user_id:
            if case.user_id in by_user_id:
                return case.user_id
            elif get_owner_id(case) in by_user_id:
                return get_owner_id(case)
        else:
            return get_owner_id(case)


    for i, case in enumerate(cases):
        if process:
            DownloadBase.set_progress(process, i, num_cases)
        if get_owner_id(case) in owner_ids:
            matching_owner = get_matching_owner(case)
            case_row = {'dynamic_properties': {}}
            for key in case_static_keys:
                if key == 'username':
                    try:
                        case_row[key] = by_user_id[matching_owner].raw_username
                    except (TypeError, KeyError):
                        case_row[key] = ''
                elif key == 'owner_name':
                    if users and case.owner_id in by_user_id:
                        case_row[key] = by_user_id[case.owner_id].full_name
                    elif case.owner_id in by_group_id:
                        case_row[key] = by_group_id[case.owner_id].name
                    else:
                        case_row[key] = ''
                else:
                    case_row[key] = getattr(case, key)
            for key in case.dynamic_properties():
                case_row['dynamic_properties'][key] = render_case_attr(case, key)
            case_rows.append(case_row)

    def format_dynamic_key(key):
        return "d.{key}".format(key=key)

    def tidy_up_case_row(case_row):
        row = dict([(key, case_row[key]) for key in case_static_keys])
        for key in case_dynamic_keys:
            row[format_dynamic_key(key)] = case_row['dynamic_properties'].get(key, workbook.undefined)
        return row

    case_headers = list(case_static_keys)
    case_headers.extend([format_dynamic_key(key) for key in case_dynamic_keys])
    workbook.open("Cases", case_headers)
    for case_row in case_rows:
        workbook.write_row("Cases", tidy_up_case_row(case_row))

    return workbook
Exemple #25
0
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)
Exemple #26
0
    def case_owner(self):
        if self.case:
            return get_wrapped_owner(get_owner_id(self.case))

        return None
Exemple #27
0
 def add_base_properties(self, element):
     super(V2CaseXMLGenerator, self).add_base_properties(element)
     from corehq.apps.users.cases import get_owner_id
     element.append(safe_element('owner_id', get_owner_id(self.case)))
Exemple #28
0
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()
Exemple #29
0
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