Ejemplo n.º 1
0
def close_cases_assigned_to_checkin(checkin_case, rule):
    if checkin_case.type != "checkin":
        return CaseRuleActionResult()

    blank_properties = {
        "assigned_to_primary_checkin_case_id": "",
        "is_assigned_primary": "",
        "assigned_to_primary_name": "",
        "assigned_to_primary_username": "",
    }
    num_related_updates = 0
    for assigned_case in _get_assigned_cases(checkin_case):
        num_related_updates += 1
        (submission, cases) = update_case(
            assigned_case.domain,
            assigned_case.case_id,
            case_properties=blank_properties,
            xmlns=AUTO_UPDATE_XMLNS,
            device_id=__name__ + ".close_cases_assigned_to_checkin",
        )
        rule.log_submission(submission.form_id)

    (close_checkin_submission, cases) = update_case(
        checkin_case.domain,
        checkin_case.case_id,
        close=True,
        xmlns=AUTO_UPDATE_XMLNS,
        device_id=__name__ + ".close_cases_assigned_to_checkin",
    )
    rule.log_submission(close_checkin_submission.form_id)

    return CaseRuleActionResult(
        num_closes=1,
        num_related_updates=num_related_updates,
    )
Ejemplo n.º 2
0
    def test_case_time_zone(self):
        reminder = (CaseReminderHandler
            .create(self.domain, 'test')
            .set_case_criteria_start_condition('participant', 'status', MATCH_EXACT, 'green')
            .set_case_criteria_start_date()
            .set_case_recipient()
            .set_sms_content_type('en')
            .set_daily_schedule(fire_time=time(12, 0),
                message={'en': 'Hello {case.name}, your test result was normal.'})
            .set_stop_condition(max_iteration_count=REPEAT_SCHEDULE_INDEFINITELY)
            .set_advanced_options())
        reminder.save()

        self.assertEqual(self.get_reminders(), [])

        with create_test_case(self.domain, 'participant', 'bob', drop_signals=False) as case, \
                patch('corehq.apps.reminders.models.CaseReminderHandler.get_now') as now_mock:
            self.assertEqual(self.get_reminders(), [])

            now_mock.return_value = datetime(2016, 1, 1, 10, 0)
            update_case(self.domain, case.case_id,
                case_properties={'status': 'green', 'time_zone': 'America/New_York'})

            reminder_instance = self.assertOneReminder()
            self.assertEqual(reminder_instance.domain, self.domain)
            self.assertEqual(reminder_instance.handler_id, reminder.get_id)
            self.assertTrue(reminder_instance.active)
            self.assertEqual(reminder_instance.start_date, date(2016, 1, 1))
            self.assertIsNone(reminder_instance.start_condition_datetime)
            self.assertEqual(reminder_instance.next_fire, datetime(2016, 1, 1, 17, 0))
            self.assertEqual(reminder_instance.case_id, case.case_id)
            self.assertEqual(reminder_instance.schedule_iteration_num, 1)
            self.assertEqual(reminder_instance.current_event_sequence_num, 0)
            self.assertEqual(reminder_instance.callback_try_count, 0)
Ejemplo n.º 3
0
    def test_agency_user_case_from_voucher_fulfilled_by_id(self):
        prescription = self.create_prescription_case()
        voucher = self.create_voucher_case(prescription.case_id)

        self.assertIsNone(
            agency_user_case_from_voucher_fulfilled_by_id(
                None,
                CaseReminder(domain=self.domain)
            )
        )

        self.assertIsNone(
            agency_user_case_from_voucher_fulfilled_by_id(
                None,
                CaseReminder(domain=self.domain, case_id=voucher.case_id)
            )
        )

        user = CommCareUser.create(self.domain, 'mobile', 'password')
        update_case(self.domain, voucher.case_id, case_properties={'voucher_fulfilled_by_id': user.get_id})

        with create_user_case(user) as user_case:
            self.assertEqual(
                agency_user_case_from_voucher_fulfilled_by_id(
                    None,
                    CaseReminder(domain=self.domain, case_id=voucher.case_id)
                ).case_id,
                user_case.case_id
            )
Ejemplo n.º 4
0
    def test_one_way_numbers(self):
        user1 = CommCareUser.create(self.domain, uuid.uuid4().hex, 'abc')
        user2 = CommCareUser.create(self.domain, uuid.uuid4().hex, 'abc')
        user3 = CommCareUser.create(self.domain, uuid.uuid4().hex, 'abc')
        self.addCleanup(user1.delete)
        self.addCleanup(user2.delete)
        self.addCleanup(user3.delete)

        self.assertIsNone(user1.memoized_usercase)
        self.assertIsNone(Content.get_two_way_entry_or_phone_number(user1))

        with self.create_user_case(user2) as case:
            self.assertIsNotNone(user2.memoized_usercase)
            self.assertIsNone(Content.get_two_way_entry_or_phone_number(user2))
            self.assertIsNone(Content.get_two_way_entry_or_phone_number(case))

        with self.create_user_case(user3) as case:
            # If the user has no number, the user case's number is used
            update_case(self.domain, case.case_id, case_properties={'contact_phone_number': '12345678'})
            case = CaseAccessors(self.domain).get_case(case.case_id)
            self.assertPhoneEntryCount(1)
            self.assertPhoneEntryCount(0, only_count_two_way=True)
            self.assertIsNotNone(user3.memoized_usercase)
            self.assertEqual(Content.get_two_way_entry_or_phone_number(user3), '12345678')

            # If the user has a number, it is used before the user case's number
            user3.add_phone_number('87654321')
            user3.save()
            self.assertPhoneEntryCount(2)
            self.assertPhoneEntryCount(0, only_count_two_way=True)
            self.assertEqual(Content.get_two_way_entry_or_phone_number(user3), '87654321')

            # Referencing the case directly uses the case's phone number
            self.assertEqual(Content.get_two_way_entry_or_phone_number(case), '12345678')
Ejemplo n.º 5
0
    def test_host_case_owner_location(self):
        with create_test_case(self.domain, 'test-extension-case',
                              'name') as extension_case:
            with create_test_case(self.domain, 'test-host-case',
                                  'name') as host_case:

                update_case(self.domain,
                            host_case.case_id,
                            case_properties={
                                'owner_id': self.city_location.location_id
                            })
                set_parent_case(self.domain,
                                extension_case,
                                host_case,
                                relationship='extension')

                # Test the recipient is returned correctly
                instance = CaseTimedScheduleInstance(
                    domain=self.domain,
                    case_id=extension_case.case_id,
                    recipient_type=CaseScheduleInstanceMixin.
                    RECIPIENT_TYPE_CUSTOM,
                    recipient_id='HOST_CASE_OWNER_LOCATION',
                )
                self.assertIsInstance(instance.recipient, SQLLocation)
                self.assertEqual(instance.recipient.location_id,
                                 self.city_location.location_id)

                # Test location that does not exist
                update_case(self.domain,
                            host_case.case_id,
                            case_properties={'owner_id': 'does-not-exist'})
                instance = CaseTimedScheduleInstance(
                    domain=self.domain,
                    case_id=extension_case.case_id,
                    recipient_type=CaseScheduleInstanceMixin.
                    RECIPIENT_TYPE_CUSTOM,
                    recipient_id='HOST_CASE_OWNER_LOCATION',
                )
                self.assertIsNone(instance.recipient)

                # Test on a case that is not an extension case
                instance = CaseTimedScheduleInstance(
                    domain=self.domain,
                    case_id=host_case.case_id,
                    recipient_type=CaseScheduleInstanceMixin.
                    RECIPIENT_TYPE_CUSTOM,
                    recipient_id='HOST_CASE_OWNER_LOCATION',
                )
                self.assertIsNone(instance.recipient)

                # Test with case id that doesn't exist
                instance = CaseTimedScheduleInstance(
                    domain=self.domain,
                    case_id='does-not-exist',
                    recipient_type=CaseScheduleInstanceMixin.
                    RECIPIENT_TYPE_CUSTOM,
                    recipient_id='HOST_CASE_OWNER_LOCATION',
                )
                self.assertIsNone(instance.recipient)
Ejemplo n.º 6
0
    def test_close_case(self):
        with create_test_case(self.domain, 'participant', 'test1', drop_signals=False) as case:
            case = self.set_case_property(case, 'contact_phone_number', '99987658765')
            case = self.set_case_property(case, 'contact_phone_number_is_verified', '1')
            self.assertIsNotNone(self.get_case_verified_number(case))

            update_case(self.domain, case.case_id, close=True)
            self.assertIsNone(self.get_case_verified_number(case))
Ejemplo n.º 7
0
def update_single_episode(domain, episode_case):
    updater = EpisodeAdherenceUpdate(domain, episode_case)
    update_json = updater.update_json()
    ledger_updates = updater.ledger_updates()
    if update_json:
        update_case(domain, episode_case.case_id, update_json,
                    device_id="%s.%s" % (__name__, 'update_single_episode'))
    if ledger_updates:
        bulk_update_ledger_cases(domain, ledger_updates)
Ejemplo n.º 8
0
 def update_single_case(self, episode_case):
     # updates a single episode_case.
     assert episode_case.domain == self.domain
     update_json = EpisodeAdherenceUpdate(self.domain,
                                          episode_case).update_json()
     if update_json:
         update_case(self.domain,
                     episode_case.case_id,
                     update_json,
                     device_id="%s.%s" % (__name__, type(self).__name__))
Ejemplo n.º 9
0
    def test_case_property_start_date_with_start_day_of_week(self):
        reminder = (CaseReminderHandler
            .create(self.domain, 'test')
            .set_case_criteria_start_condition('participant', 'status', MATCH_EXACT, 'green')
            .set_case_criteria_start_date(start_date='start_date', start_day_of_week=DAY_MON)
            .set_case_recipient()
            .set_sms_content_type('en')
            .set_daily_schedule(fire_time=time(12, 0),
                message={'en': 'Hello {case.name}, your test result was normal.'})
            .set_stop_condition(max_iteration_count=30)
            .set_advanced_options(use_today_if_start_date_is_blank=False))
        reminder.save()

        self.assertEqual(self.get_reminders(), [])

        with create_test_case(self.domain, 'participant', 'bob', drop_signals=False) as case, \
                patch('corehq.apps.reminders.models.CaseReminderHandler.get_now') as now_mock:
            self.assertEqual(self.get_reminders(), [])

            now_mock.return_value = datetime(2016, 1, 1, 10, 0)
            update_case(self.domain, case.case_id,
                case_properties={'status': 'green', 'start_date': '2016-01-08'})

            reminder_instance = self.assertOneReminder()
            self.assertEqual(reminder_instance.domain, self.domain)
            self.assertEqual(reminder_instance.case_id, case.case_id)
            self.assertEqual(reminder_instance.handler_id, reminder.get_id)
            self.assertIsNone(reminder_instance.user_id)
            self.assertEqual(reminder_instance.next_fire, datetime(2016, 1, 11, 12, 0))
            self.assertTrue(reminder_instance.active)
            self.assertEqual(reminder_instance.start_date, date(2016, 1, 8))
            self.assertEqual(reminder_instance.schedule_iteration_num, 1)
            self.assertEqual(reminder_instance.current_event_sequence_num, 0)
            self.assertEqual(reminder_instance.callback_try_count, 0)
            self.assertEqual(reminder_instance.start_condition_datetime, datetime(2016, 1, 8))
            self.assertEqual(reminder_instance.callback_try_count, 0)

            # update start day of week and the schedule should be recalculated
            prev_definition = reminder
            reminder.set_case_criteria_start_date(start_date='start_date', start_day_of_week=DAY_TUE)
            reminder.save(schedule_changed=True, prev_definition=prev_definition)

            reminder_instance = self.assertOneReminder()
            self.assertEqual(reminder_instance.domain, self.domain)
            self.assertEqual(reminder_instance.case_id, case.case_id)
            self.assertEqual(reminder_instance.handler_id, reminder.get_id)
            self.assertIsNone(reminder_instance.user_id)
            self.assertEqual(reminder_instance.next_fire, datetime(2016, 1, 12, 12, 0))
            self.assertTrue(reminder_instance.active)
            self.assertEqual(reminder_instance.start_date, date(2016, 1, 8))
            self.assertEqual(reminder_instance.schedule_iteration_num, 1)
            self.assertEqual(reminder_instance.current_event_sequence_num, 0)
            self.assertEqual(reminder_instance.callback_try_count, 0)
            self.assertEqual(reminder_instance.start_condition_datetime, datetime(2016, 1, 8))
            self.assertEqual(reminder_instance.callback_try_count, 0)
Ejemplo n.º 10
0
    def apply_actions(self, case):
        properties = {}
        close = False

        for action in self.automaticupdateaction_set.all():
            if action.action == AutomaticUpdateAction.ACTION_UPDATE:
                properties[action.property_name] = action.property_value
            elif action.action == AutomaticUpdateAction.ACTION_CLOSE:
                close = True

        update_case(case.domain, case.get_id, case_properties=properties, close=close)
Ejemplo n.º 11
0
def close_cases_assigned_to_checkin(checkin_case, rule):
    """
    For any associated checkin case that matches the rule criteria, the following occurs:

    1. For all cases of a given type, find all assigned cases. \
       An assigned case is a case for which all of the following are true:

       - Case type patient or contact
       - Exists in the same domain as the user case
       - The case property assigned_to_primary_checkin_case_id equals an associated checkin case's case_id

    2. For every assigned case, the following case properties are blanked out (set to ""):

       - assigned_to_primary_checkin_case_id
       - is_assigned_primary
       - assigned_to_primary_name
       - assigned_to_primary_username

    """
    if checkin_case.type != "checkin":
        return CaseRuleActionResult()

    blank_properties = {
        "assigned_to_primary_checkin_case_id": "",
        "is_assigned_primary": "",
        "assigned_to_primary_name": "",
        "assigned_to_primary_username": "",
    }
    num_related_updates = 0
    for assigned_case_domain, assigned_case_id in _get_assigned_cases(
            checkin_case):
        num_related_updates += 1
        (submission, cases) = update_case(
            assigned_case_domain,
            assigned_case_id,
            case_properties=blank_properties,
            xmlns=AUTO_UPDATE_XMLNS,
            device_id=__name__ + ".close_cases_assigned_to_checkin",
        )
        rule.log_submission(submission.form_id)

    (close_checkin_submission, cases) = update_case(
        checkin_case.domain,
        checkin_case.case_id,
        close=True,
        xmlns=AUTO_UPDATE_XMLNS,
        device_id=__name__ + ".close_cases_assigned_to_checkin",
    )
    rule.log_submission(close_checkin_submission.form_id)

    return CaseRuleActionResult(
        num_closes=1,
        num_related_updates=num_related_updates,
    )
Ejemplo n.º 12
0
def _update_case_from_request(request, domain, update_model):
    try:
        update = _get_case_update(request, domain, update_model)
    except ApiError as e:
        if not settings.UNIT_TESTING:
            notify_exception(request,
                             "BETS sent the eNikshay API a bad request.")
        return json_response({"error": e.message}, status_code=e.status_code)

    update_case(domain, update.case_id, case_properties=update.properties)

    return json_response({'status': "success"})
Ejemplo n.º 13
0
    def test_user_recipient(self):
        reminder = (CaseReminderHandler
            .create(self.domain, 'test')
            .set_case_criteria_start_condition('participant', 'status', MATCH_EXACT, 'green')
            .set_case_criteria_start_date()
            .set_last_submitting_user_recipient()
            .set_sms_content_type('en')
            .set_daily_schedule(fire_time=time(12, 0), message={'en': "{case.name}'s test result was normal."})
            .set_stop_condition(max_iteration_count=REPEAT_SCHEDULE_INDEFINITELY)
            .set_advanced_options())
        reminder.save()

        self.assertEqual(self.get_reminders(), [])

        with create_test_case(self.domain, 'participant', 'bob', drop_signals=False) as case, \
                patch('corehq.apps.reminders.models.CaseReminderHandler.get_now') as now_mock:
            self.assertEqual(self.get_reminders(), [])

            now_mock.return_value = datetime(2016, 1, 1, 10, 0)

            # There should still be no reminder instance since this is submitted by the system user
            update_case(self.domain, case.case_id, case_properties={'status': 'green'})
            self.assertEqual(self.get_reminders(), [])

            # Update the user id on the case
            CaseFactory(self.domain).create_or_update_case(
                CaseStructure(
                    case_id=case.case_id,
                    attrs={'user_id': self.user.get_id}
                )
            )

            reminder_instance = self.assertOneReminder()
            self.assertEqual(reminder_instance.domain, self.domain)
            self.assertEqual(reminder_instance.handler_id, reminder.get_id)
            self.assertTrue(reminder_instance.active)
            self.assertEqual(reminder_instance.start_date, date(2016, 1, 1))
            self.assertIsNone(reminder_instance.start_condition_datetime)
            self.assertEqual(reminder_instance.next_fire, datetime(2016, 1, 1, 12, 0))
            self.assertEqual(reminder_instance.case_id, case.case_id)
            self.assertEqual(reminder_instance.schedule_iteration_num, 1)
            self.assertEqual(reminder_instance.current_event_sequence_num, 0)
            self.assertEqual(reminder_instance.user_id, self.user.get_id)
            self.assertEqual(reminder_instance.callback_try_count, 0)

            # Set a user_id that does not exist
            CaseFactory(self.domain).create_or_update_case(
                CaseStructure(
                    case_id=case.case_id,
                    attrs={'user_id': 'this-user-id-does-not-exist'}
                )
            )
            self.assertEqual(self.get_reminders(), [])
Ejemplo n.º 14
0
    def test_when_delegate_exists(self):
        rule = create_empty_rule(self.domain,
                                 AutomaticUpdateRule.WORKFLOW_CASE_UPDATE)
        rule.add_action(CustomActionDefinition,
                        name='ICDS_ESCALATE_TECH_ISSUE')

        with create_case(
                self.domain,
                'tech_issue',
                case_name='New Issue',
                update={
                    'ticket_level': 'block',
                    'touch_case_date': '2017-06-01',
                    'block_location_id': 'block_id',
                    'district_location_id': 'district_id',
                    'state_location_id': 'state_id',
                },
        ) as tech_issue:
            result = rule.run_actions_when_case_matches(tech_issue)
            self.assertEqual(result.num_updates, 1)
            self.assertEqual(result.num_creates, 1)
            self.assertEqual(result.num_related_updates, 0)

            tech_issue = CaseAccessors(self.domain).get_case(
                tech_issue.case_id)
            subcases = tech_issue.get_subcases(index_identifier='parent')
            self.assertEqual(len(subcases), 1)
            [tech_issue_delegate] = subcases
            self.assertEqual(
                tech_issue_delegate.get_case_property('change_in_level'), '1')

            update_case(self.domain,
                        tech_issue.case_id,
                        case_properties={'ticket_level': 'block'})
            tech_issue = CaseAccessors(self.domain).get_case(
                tech_issue.case_id)

            result = rule.run_actions_when_case_matches(tech_issue)
            self.assertEqual(result.num_updates, 1)
            self.assertEqual(result.num_creates, 0)
            self.assertEqual(result.num_related_updates, 1)

            tech_issue = CaseAccessors(self.domain).get_case(
                tech_issue.case_id)
            subcases = tech_issue.get_subcases(index_identifier='parent')
            self.assertEqual(len(subcases), 1)
            [tech_issue_delegate] = subcases
            self.assertEqual(
                tech_issue_delegate.get_case_property('change_in_level'), '2')
Ejemplo n.º 15
0
    def apply_actions(self, case):
        cases_to_update = defaultdict(dict)
        close = False

        def _get_case_property_value(current_case, name):
            result = current_case.resolve_case_property(name)
            if result:
                return result[0].value

            return None

        def _add_update_property(name, value, current_case):
            while name.startswith("parent/"):
                name = name[7:]
                # uses first parent if there are multiple
                parent_cases = current_case.get_parent(identifier=DEFAULT_PARENT_IDENTIFIER)
                if parent_cases:
                    current_case = parent_cases[0]
                else:
                    return
            cases_to_update[current_case.case_id][name] = value

        for action in self.automaticupdateaction_set.all():
            if action.action == AutomaticUpdateAction.ACTION_UPDATE:
                if action.property_value_type == AutomaticUpdateAction.CASE_PROPERTY:
                    value = _get_case_property_value(case, action.property_value)
                    if value is None:
                        continue
                else:
                    value = action.property_value

                if value != _get_case_property_value(case, action.property_name):
                    _add_update_property(action.property_name, value, case)
            elif action.action == AutomaticUpdateAction.ACTION_CLOSE:
                close = True

        # Update any referenced parent cases
        for id, properties in cases_to_update.items():
            if id == case.case_id:
                continue
            update_case(case.domain, id, case_properties=properties, close=False, xmlns=AUTO_UPDATE_XMLNS)

        # Update / close the case
        properties = cases_to_update[case.case_id]
        if close or properties:
            update_case(case.domain, case.case_id, case_properties=properties, close=close, xmlns=AUTO_UPDATE_XMLNS)

        return close
    def handle(self, domain, episode_case_ids, **options):
        case_accessor = CaseAccessors(domain)

        if not episode_case_ids:
            episode_case_ids = case_accessor.get_case_ids_in_domain(type='episode')

        for episode_case_id in episode_case_ids:
            print(episode_case_id)
            episode_case = case_accessor.get_case(episode_case_id)
            try:
                updater = EpisodeFacilityIDMigration(domain, episode_case)
            except ENikshayCaseNotFound:
                continue
            update_json = updater.update_json()
            if update_json:
                update_case(domain, episode_case_id, update_json)
Ejemplo n.º 17
0
def close_cases_assigned_to_checkin(checkin_case, rule):
    """
    For any associated checkin case that matches the rule criteria, the following occurs:
        1) For all cases of type [x] find all fields where [assigned_to_primary_checkin_case_id] is set
           to the case ID of the associated checkin case. These are the assigned cases.
        2) For every assigned case, the following case properties are blanked out (set to ""):
            - assigned_to_primary_checkin_case_id
            - is_assigned_primary
            - assigned_to_primary_name
            - assigned_to_primary_username
    """
    if checkin_case.type != "checkin":
        return CaseRuleActionResult()

    blank_properties = {
        "assigned_to_primary_checkin_case_id": "",
        "is_assigned_primary": "",
        "assigned_to_primary_name": "",
        "assigned_to_primary_username": "",
    }
    num_related_updates = 0
    for assigned_case in _get_assigned_cases(checkin_case):
        num_related_updates += 1
        (submission, cases) = update_case(
            assigned_case.domain,
            assigned_case.case_id,
            case_properties=blank_properties,
            xmlns=AUTO_UPDATE_XMLNS,
            device_id=__name__ + ".close_cases_assigned_to_checkin",
        )
        rule.log_submission(submission.form_id)

    (close_checkin_submission, cases) = update_case(
        checkin_case.domain,
        checkin_case.case_id,
        close=True,
        xmlns=AUTO_UPDATE_XMLNS,
        device_id=__name__ + ".close_cases_assigned_to_checkin",
    )
    rule.log_submission(close_checkin_submission.form_id)

    return CaseRuleActionResult(
        num_closes=1,
        num_related_updates=num_related_updates,
    )
Ejemplo n.º 18
0
    def test_host_case_owner_location(self):
        with create_test_case(self.domain, 'test-extension-case', 'name') as extension_case:
            with create_test_case(self.domain, 'test-host-case', 'name') as host_case:

                update_case(self.domain, host_case.case_id,
                    case_properties={'owner_id': self.city_location.location_id})
                set_parent_case(self.domain, extension_case, host_case, relationship='extension')

                # Test the recipient is returned correctly
                instance = CaseTimedScheduleInstance(
                    domain=self.domain,
                    case_id=extension_case.case_id,
                    recipient_type=CaseScheduleInstanceMixin.RECIPIENT_TYPE_CUSTOM,
                    recipient_id='HOST_CASE_OWNER_LOCATION',
                )
                self.assertIsInstance(instance.recipient, SQLLocation)
                self.assertEqual(instance.recipient.location_id, self.city_location.location_id)

                # Test location that does not exist
                update_case(self.domain, host_case.case_id, case_properties={'owner_id': 'does-not-exist'})
                instance = CaseTimedScheduleInstance(
                    domain=self.domain,
                    case_id=extension_case.case_id,
                    recipient_type=CaseScheduleInstanceMixin.RECIPIENT_TYPE_CUSTOM,
                    recipient_id='HOST_CASE_OWNER_LOCATION',
                )
                self.assertIsNone(instance.recipient)

                # Test on a case that is not an extension case
                instance = CaseTimedScheduleInstance(
                    domain=self.domain,
                    case_id=host_case.case_id,
                    recipient_type=CaseScheduleInstanceMixin.RECIPIENT_TYPE_CUSTOM,
                    recipient_id='HOST_CASE_OWNER_LOCATION',
                )
                self.assertIsNone(instance.recipient)

                # Test with case id that doesn't exist
                instance = CaseTimedScheduleInstance(
                    domain=self.domain,
                    case_id='does-not-exist',
                    recipient_type=CaseScheduleInstanceMixin.RECIPIENT_TYPE_CUSTOM,
                    recipient_id='HOST_CASE_OWNER_LOCATION',
                )
                self.assertIsNone(instance.recipient)
Ejemplo n.º 19
0
    def test_prescription_voucher_alert(self):
        prescription = self.create_prescription_case()
        voucher = self.create_voucher_case(prescription.case_id)

        update_case(self.domain, voucher.case_id, {'voucher_id': '012345'})
        update_case(self.domain, self.person_id, {
            'name': 'Joe',
            'person_id': '123-456-789'
        })

        self._test_prescription_voucher_alert_with_language(
            voucher, None,
            "Drug Voucher ID 012345 issued to Joe with Beneficiary ID 123-456-789."
        )
        self._test_prescription_voucher_alert_with_language(
            voucher, "en",
            "Drug Voucher ID 012345 issued to Joe with Beneficiary ID 123-456-789."
        )
        self._test_prescription_voucher_alert_with_language(
            voucher, "bho",
            "\u0921\u094d\u0930\u0917 \u0935\u093e\u0909\u091a\u0930 \u0906\u0908\u0921\u0940 012345"
            " \u092f\u0947 \u0932\u093e\u092d\u093e\u0930\u094d\u0925\u0940 \u0906\u0908\u0921\u0940 "
            "123-456-789  \u0915\u0947 \u0938\u0902\u0917\u0947 Joe \u0915\u0947 \u091c\u093e\u0930\u0940 "
            "\u0915 \u0926\u0947\u0939\u0932 \u0917\u0908\u0932 \u092c\u093e")
        self._test_prescription_voucher_alert_with_language(
            voucher, "guj",
            "\u0ab2\u0abe\u0aad\u0abe\u0ab0\u0acd\u0aa5\u0ac0 \u0a86\u0a88\u0aa1\u0ac0  123-456-789"
            "  \u0aa7\u0ab0\u0abe\u0ab5\u0aa4\u0abe Joe \u0aa8\u0ac7 \u0aa1\u0acd\u0ab0\u0a97 "
            "\u0ab5\u0abe\u0a89\u0a9a\u0ab0 \u0a86\u0a88\u0aa1\u0ac0   012345 \u0a88\u0ab6\u0acd\u0aaf\u0ac1 "
            "\u0a95\u0ab0\u0ab5\u0abe\u0aae\u0abe\u0a82 \u0a86\u0ab5\u0acd\u0aaf\u0ac1\u0a82 \u0a9b\u0ac7."
        )
        self._test_prescription_voucher_alert_with_language(
            voucher, "hin",
            "\u0926\u0935\u093e \u0935\u093e\u0909\u091a\u0930 \u0906\u0908\u0921\u0940 012345"
            " \u0932\u093e\u092d\u093e\u0930\u094d\u0925\u0940 \u0906\u0908\u0921\u0940 123-456-789  "
            "\u0915\u0947 \u0938\u093e\u0925 Joe \u0915\u094b \u091c\u093e\u0930\u0940 \u0915\u093f\u092f\u093e "
            "\u0917\u092f\u093e \u0939\u0948\u0964")
        self._test_prescription_voucher_alert_with_language(
            voucher, "mar",
            "123-456-789 \u0939\u093e \u0932\u093e\u092d\u0927\u093e\u0930\u0915\u0906\u092f\u0921\u0940 "
            "\u0905\u0938\u0932\u0947\u0932\u094d\u092f\u093e Joe \u0935\u094d\u092f\u0915\u094d\u0924\u0940"
            "\u0932\u093e\u0921\u094d\u0930\u0917\u0935\u094d\u0939\u093e\u090a\u091a\u0930\u0906\u092f\u0921"
            "\u0940 012345 \u0926\u0947\u0923\u094d\u092f\u093e\u0924 \u0906\u0932\u093e \u0906\u0939\u0947."
        )
Ejemplo n.º 20
0
 def handle_response(self, response, repeat_record):
     attempt = super().handle_response(response, repeat_record)
     # successful response is always 204
     if response.status_code == 204:
         cowin_api_data_vaccination_case = repeat_record.repeater.payload_doc(
             repeat_record)
         person_case_id = cowin_api_data_vaccination_case.get_case_property(
             "person_case_id")
         dose_number = cowin_api_data_vaccination_case.get_case_property(
             "dose")
         # Ideally person case id should always be present
         # Simply ignore cases that don't have that and don't try again
         if person_case_id:
             update_case(
                 self.domain,
                 person_case_id,
                 case_properties={f'dose_{dose_number}_notified': True},
                 device_id=__name__ + '.BeneficiaryVaccinationRepeater')
     return attempt
Ejemplo n.º 21
0
    def test_ignoring_entries(self):
        with create_case(self.domain, 'person') as case:
            update_case(self.domain, case.case_id,
                case_properties={'contact_phone_number': '12345', 'contact_phone_number_is_verified': '1'})

            self.assertPhoneEntryCount(1)
            self.assertPhoneEntryCount(1, only_count_two_way=True)

            with patch('corehq.apps.sms.tasks.use_phone_entries') as patch1, \
                    patch('corehq.messaging.tasks.use_phone_entries') as patch2, \
                    patch('corehq.messaging.scheduling.models.abstract.use_phone_entries') as patch3:

                patch1.return_value = patch2.return_value = patch3.return_value = False
                update_case(self.domain, case.case_id, case_properties={'contact_phone_number': '23456'})
                case = CaseAccessors(self.domain).get_case(case.case_id)

                self.assertPhoneEntryCount(1)
                self.assertPhoneEntryCount(1, only_count_two_way=True)
                self.assertTwoWayEntry(PhoneNumber.objects.get(owner_id=case.case_id), '12345')
                self.assertEqual(Content.get_two_way_entry_or_phone_number(case), '23456')
Ejemplo n.º 22
0
    def setUpClass(cls):
        super(CustomContentTest, cls).setUpClass()
        cls.mother_person_case = cls.create_case('person')
        cls.child_person_case = cls.create_case('person',
                                                cls.mother_person_case.case_id,
                                                cls.mother_person_case.type,
                                                'mother',
                                                'child',
                                                case_name="Joe")
        cls.child_health_extension_case = cls.create_case(
            'child_health', cls.child_person_case.case_id,
            cls.child_person_case.type, 'parent', 'extension')

        update_case(
            cls.domain,
            cls.mother_person_case.case_id,
            {'language_code': 'en'},
        )

        cls.mother_person_case = CaseAccessors(cls.domain).get_case(
            cls.mother_person_case.case_id)
Ejemplo n.º 23
0
    def test_parent_case_property_criteria(self):
        reminder = (CaseReminderHandler
            .create(self.domain, 'test')
            .set_case_criteria_start_condition('participant', 'parent/status', MATCH_EXACT, 'green')
            .set_case_criteria_start_date()
            .set_case_recipient()
            .set_sms_content_type('en')
            .set_daily_schedule(fire_time=time(12, 0),
                message={'en': 'Hello {case.name}, your test result was normal.'})
            .set_stop_condition(max_iteration_count=REPEAT_SCHEDULE_INDEFINITELY)
            .set_advanced_options())
        reminder.active = False
        reminder.save()

        self.assertEqual(self.get_reminders(), [])

        with create_test_case(self.domain, 'participant', 'bob', drop_signals=False) as child_case, \
                create_test_case(self.domain, 'parent-case', 'jim', drop_signals=False) as parent_case, \
                patch('corehq.apps.reminders.models.CaseReminderHandler.get_now') as now_mock:
            process_handlers_for_case_changed(self.domain, child_case.case_id, [reminder._id])
            self.assertEqual(self.get_reminders(), [])

            set_parent_case(self.domain, child_case, parent_case)
            process_handlers_for_case_changed(self.domain, child_case.case_id, [reminder._id])
            self.assertEqual(self.get_reminders(), [])

            now_mock.return_value = datetime(2016, 1, 1, 10, 0)
            update_case(self.domain, child_case.case_id, case_properties={'status': 'green'})
            self.assertEqual(self.get_reminders(), [])

            update_case(self.domain, child_case.case_id, case_properties={'status': ''})
            self.assertEqual(self.get_reminders(), [])

            update_case(self.domain, parent_case.case_id, case_properties={'status': 'green'})
            process_handlers_for_case_changed(self.domain, child_case.case_id, [reminder._id])
            reminder_instance = self.assertOneReminder()
            self.assertEqual(reminder_instance.domain, self.domain)
            self.assertEqual(reminder_instance.handler_id, reminder.get_id)
            self.assertFalse(reminder_instance.active)
            self.assertEqual(reminder_instance.start_date, date(2016, 1, 1))
            self.assertIsNone(reminder_instance.start_condition_datetime)
            self.assertEqual(reminder_instance.next_fire, datetime(2016, 1, 1, 12, 0))
            self.assertEqual(reminder_instance.case_id, child_case.case_id)
            self.assertEqual(reminder_instance.schedule_iteration_num, 1)
            self.assertEqual(reminder_instance.current_event_sequence_num, 0)
            self.assertEqual(reminder_instance.callback_try_count, 0)

            update_case(self.domain, parent_case.case_id, case_properties={'status': 'red'})
            process_handlers_for_case_changed(self.domain, child_case.case_id, [reminder._id])
            self.assertEqual(self.get_reminders(), [])
Ejemplo n.º 24
0
    def test_beneficiary_registration_recipients(self):
        located_in_mehsana.clear(self.phi)
        self.dto.site_code = LOCATION_SITE_CODE_MEHSANA
        self.dto.save()
        self.assign_person_to_location(self.phi.location_id)

        update_case(self.domain, self.person_id, case_properties={'fo': self.pcc.location_id})
        user = CommCareUser.create(self.domain, 'mobile', 'password', location=self.pcc)

        # No user case created yet
        result = beneficiary_registration_recipients(
            None,
            CaseReminder(domain=self.domain, case_id=self.person_id)
        )
        self.assertTrue(isinstance(result, CommCareCaseSQL))
        self.assertEqual(result.case_id, self.person_id)

        # Create user case
        with create_user_case(user) as user_case:
            result = beneficiary_registration_recipients(
                None,
                CaseReminder(domain=self.domain, case_id=self.person_id)
            )
            self.assertTrue(isinstance(result, list))
            self.assertEqual(
                [case.case_id for case in result],
                [self.person_id, user_case.case_id]
            )

            # Test location outside Mehsana
            located_in_mehsana.clear(self.phi)
            self.dto.site_code = 'dto-other'
            self.dto.save()

            result = beneficiary_registration_recipients(
                None,
                CaseReminder(domain=self.domain, case_id=self.person_id)
            )
            self.assertTrue(isinstance(result, CommCareCaseSQL))
            self.assertEqual(result.case_id, self.person_id)
Ejemplo n.º 25
0
def _update_existing_tech_issue_delegate(tech_issue_delegate):
    if tech_issue_delegate.get_case_property('change_in_level') == '1':
        change_in_level = '2'
    else:
        change_in_level = '1'

    return update_case(
        tech_issue_delegate.domain,
        tech_issue_delegate.case_id,
        case_properties={'change_in_level': change_in_level},
        close=False,
        xmlns=AUTO_UPDATE_XMLNS,
    )
Ejemplo n.º 26
0
 def handle_response(self, response, repeat_record):
     attempt = super().handle_response(response, repeat_record)
     # successful response is always 200. 40x and 500 are errors
     if response.status_code == 200:
         cowin_api_data_registration_case = repeat_record.repeater.payload_doc(
             repeat_record)
         person_case_id = cowin_api_data_registration_case.get_case_property(
             "person_case_id")
         # Ideally person case id should always be present
         # Simply ignore cases that don't have that and don't try again
         if person_case_id:
             beneficiary_reference_id = response.json(
             )['beneficiary_reference_id']
             update_case(self.domain,
                         person_case_id,
                         case_properties={
                             'cowin_beneficiary_reference_id':
                             beneficiary_reference_id
                         },
                         device_id=__name__ +
                         '.BeneficiaryRegistrationRepeater')
     return attempt
Ejemplo n.º 27
0
    def test_not_using_phone_entries(self):
        with patch('corehq.apps.sms.tasks.use_phone_entries') as patch1, \
                patch('corehq.messaging.tasks.use_phone_entries') as patch2, \
                patch('corehq.messaging.scheduling.models.abstract.use_phone_entries') as patch3:

            patch1.return_value = patch2.return_value = patch3.return_value = False

            user1 = CommCareUser.create(self.domain, uuid.uuid4().hex, 'abc')
            user2 = CommCareUser.create(self.domain, uuid.uuid4().hex, 'abc')
            user3 = CommCareUser.create(self.domain, uuid.uuid4().hex, 'abc')
            self.addCleanup(user1.delete)
            self.addCleanup(user2.delete)
            self.addCleanup(user3.delete)

            self.assertIsNone(user1.memoized_usercase)
            self.assertIsNone(Content.get_two_way_entry_or_phone_number(user1))

            with self.create_user_case(user2) as case:
                self.assertIsNotNone(user2.memoized_usercase)
                self.assertIsNone(Content.get_two_way_entry_or_phone_number(user2))
                self.assertIsNone(Content.get_two_way_entry_or_phone_number(case))

            with self.create_user_case(user3) as case:
                # If the user has no number, the user case's number is used
                update_case(self.domain, case.case_id, case_properties={'contact_phone_number': '12345678'})
                case = CaseAccessors(self.domain).get_case(case.case_id)
                self.assertPhoneEntryCount(0)
                self.assertIsNotNone(user3.memoized_usercase)
                self.assertEqual(Content.get_two_way_entry_or_phone_number(user3), '12345678')

                # If the user has a number, it is used before the user case's number
                user3.add_phone_number('87654321')
                user3.save()
                self.assertPhoneEntryCount(0)
                self.assertEqual(Content.get_two_way_entry_or_phone_number(user3), '87654321')

                # Referencing the case directly uses the case's phone number
                self.assertEqual(Content.get_two_way_entry_or_phone_number(case), '12345678')
Ejemplo n.º 28
0
def _update_existing_tech_issue_delegate(tech_issue_delegate):
    if tech_issue_delegate.get_case_property('change_in_level') == '1':
        change_in_level = '2'
    else:
        change_in_level = '1'

    return update_case(
        tech_issue_delegate.domain,
        tech_issue_delegate.case_id,
        case_properties={'change_in_level': change_in_level},
        close=False,
        xmlns=AUTO_UPDATE_XMLNS,
        device_id=__name__ + "._update_existing_tech_issue_delegate",
    )
Ejemplo n.º 29
0
    def test_close_case(self):
        extra_number = PhoneNumber.objects.create(
            domain=self.domain,
            owner_doc_type='X',
            owner_id='X',
            phone_number='999123',
            verified=True,
            pending_verification=False,
            is_two_way=True
        )
        self.assertEqual(PhoneNumber.count_by_domain(self.domain), 1)

        with create_test_case(self.domain, 'participant', 'test1', drop_signals=False) as case:
            case = self.set_case_property(case, 'contact_phone_number', '99987658765')
            case = self.set_case_property(case, 'contact_phone_number_is_verified', '1')
            self.assertIsNotNone(self.get_case_phone_number(case))
            self.assertEqual(PhoneNumber.count_by_domain(self.domain), 2)

            update_case(self.domain, case.case_id, close=True)
            self.assertIsNone(self.get_case_phone_number(case))
            self.assertEqual(PhoneNumber.count_by_domain(self.domain), 1)

        self.assertEqual(PhoneNumber.get_two_way_number('999123'), extra_number)
Ejemplo n.º 30
0
def _update_tech_issue_for_escalation(case, escalated_ticket_level):
    today = ServerTime(datetime.utcnow()).user_time(pytz.timezone('Asia/Kolkata')).done().date()

    return update_case(
        case.domain,
        case.case_id,
        case_properties={
            'ticket_level': escalated_ticket_level,
            'change_in_level': '1',
            'touch_case_date': today.strftime('%Y-%m-%d'),
        },
        close=False,
        xmlns=AUTO_UPDATE_XMLNS,
        device_id=__name__ + "._update_tech_issue_for_escalation",
    )
Ejemplo n.º 31
0
def sanitize_session_peer_rating(session_case, rule):
    """
    For any session case
    sanitize the peer_rating metrics based on child cases of type peer_rating
    """
    if session_case.type != SESSION_CASE_TYPE:
        return CaseRuleActionResult()

    peer_rating_cases = _get_peer_rating_cases(session_case)
    num_updates = 0

    if peer_rating_cases:
        case_updates = _get_case_updates(peer_rating_cases)
        (submission, cases) = update_case(
            session_case.domain,
            session_case.case_id,
            case_properties=case_updates,
            xmlns=AUTO_UPDATE_XMLNS,
            device_id=__name__ + ".sanitize_session_peer_rating",
        )
        num_updates = 1
        rule.log_submission(submission.form_id)

    return CaseRuleActionResult(num_updates=num_updates, )
Ejemplo n.º 32
0
    def test_host_case_owner_location(self):
        parent_location = SQLLocation.objects.create(
            domain=self.domain,
            name='parent test',
            site_code='parent',
            location_type=self.parent_location_type)
        self.addCleanup(parent_location.delete)

        child_location = SQLLocation.objects.create(
            domain=self.domain,
            name='child test',
            site_code='child',
            location_type=self.child_location_type,
            parent=parent_location)
        self.addCleanup(child_location.delete)

        with create_test_case(self.domain, 'test-extension-case',
                              'name') as extension_case:
            with create_test_case(self.domain, 'test-host-case',
                                  'name') as host_case:

                update_case(
                    self.domain,
                    host_case.case_id,
                    case_properties={'owner_id': child_location.location_id})
                set_parent_case(self.domain,
                                extension_case,
                                host_case,
                                relationship='extension')

                handler1 = CaseReminderHandler(
                    domain=self.domain, recipient='HOST_CASE_OWNER_LOCATION')
                handler2 = CaseReminderHandler(
                    domain=self.domain,
                    recipient='HOST_CASE_OWNER_LOCATION_PARENT')
                reminder = CaseReminder(domain=self.domain,
                                        case_id=extension_case.case_id)

                # Test the recipients are returned correctly
                with patch('corehq.apps.reminders.models.CaseReminder.handler',
                           new=handler1):
                    self.assertEqual(reminder.recipient, [child_location])

                with patch('corehq.apps.reminders.models.CaseReminder.handler',
                           new=handler2):
                    self.assertEqual(reminder.recipient, [parent_location])

                # Remove parent location reference
                child_location.parent = None
                child_location.save()
                with patch('corehq.apps.reminders.models.CaseReminder.handler',
                           new=handler2):
                    self.assertIsNone(reminder.recipient)

                # Test location that does not exist
                update_case(self.domain,
                            host_case.case_id,
                            case_properties={'owner_id': 'does-not-exist'})
                with patch('corehq.apps.reminders.models.CaseReminder.handler',
                           new=handler1):
                    self.assertIsNone(reminder.recipient)

                # Test on a case that is not an extension case
                reminder.case_id = host_case.case_id
                with patch('corehq.apps.reminders.models.CaseReminder.handler',
                           new=handler1):
                    self.assertIsNone(reminder.recipient)

                # Test on a blank case id
                reminder.case_id = None
                with patch('corehq.apps.reminders.models.CaseReminder.handler',
                           new=handler1):
                    self.assertIsNone(reminder.recipient)
Ejemplo n.º 33
0
 def test_is_contact_active_for_case(self):
     with create_test_case(self.domain, "contact", "test-case") as case:
         self.assertTrue(is_contact_active(self.domain, "CommCareCase", case.case_id))
         update_case(self.domain, case.case_id, close=True)
         self.assertFalse(is_contact_active(self.domain, "CommCareCase", case.case_id))
Ejemplo n.º 34
0
def update_single_episode(domain, episode_case):
    update_json = EpisodeAdherenceUpdate(domain, episode_case).update_json()
    if update_json:
        update_case(domain, episode_case.case_id, update_json,
                    device_id="%s.%s" % (__name__, 'update_single_episode'))
Ejemplo n.º 35
0
    def test_static_negative_growth_indicator(self):
        c = CustomContent(
            custom_content_id='ICDS_STATIC_NEGATIVE_GROWTH_MESSAGE')

        schedule_instance = CaseTimedScheduleInstance(
            domain=self.domain,
            case_id=self.child_health_case.case_id,
        )

        # Test when current weight is greater than previous
        submit_growth_form(self.domain, self.child_health_case.case_id, '10.1',
                           '10.4')
        self.assertEqual(
            c.get_list_of_messages(self.mother_person_case, schedule_instance),
            [])

        # Test when current weight is equal to previous
        submit_growth_form(self.domain, self.child_health_case.case_id, '10.1',
                           '10.1')
        self.assertEqual(
            c.get_list_of_messages(self.mother_person_case, schedule_instance),
            [
                "As per the latest records of your AWC, the weight of your child Joe has remained static in the last "
                "month. Please consult your AWW for necessary advice."
            ])

        # Test when current weight is less than previous
        submit_growth_form(self.domain, self.child_health_case.case_id, '10.1',
                           '9.9')
        self.assertEqual(
            c.get_list_of_messages(self.mother_person_case, schedule_instance),
            [
                "As per the latest records of your AWC, the weight of your child Joe has reduced in the last month. "
                "Please consult your AWW for necessary advice."
            ])

        # Test ignoring forms with the wrong xmlns
        update_case(self.domain, self.child_health_case.case_id,
                    {'property': 'value1'})
        update_case(self.domain, self.child_health_case.case_id,
                    {'property': 'value2'})
        update_case(self.domain, self.child_health_case.case_id,
                    {'property': 'value3'})
        update_case(self.domain, self.child_health_case.case_id,
                    {'property': 'value4'})
        update_case(self.domain, self.child_health_case.case_id,
                    {'property': 'value5'})
        update_case(self.domain, self.child_health_case.case_id,
                    {'property': 'value6'})
        update_case(self.domain, self.child_health_case.case_id,
                    {'property': 'value7'})
        update_case(self.domain, self.child_health_case.case_id,
                    {'property': 'value8'})
        update_case(self.domain, self.child_health_case.case_id,
                    {'property': 'value9'})
        update_case(self.domain, self.child_health_case.case_id,
                    {'property': 'value10'})

        self.assertEqual(
            c.get_list_of_messages(self.mother_person_case, schedule_instance),
            [
                "As per the latest records of your AWC, the weight of your child Joe has reduced in the last month. "
                "Please consult your AWW for necessary advice."
            ])
Ejemplo n.º 36
0
 def set_case_property(self, case, property_name, value):
     update_case(self.domain, case.case_id, case_properties={property_name: value})
     return CaseAccessors(self.domain).get_case(case.case_id)
Ejemplo n.º 37
0
    def test_all_inbound(self):
        # Mobile worker creates a case
        incoming("999123", "reg", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Enter Participant ID")
        incoming("999123", "pid1234", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Enter Study Arm 1:a, 2:b.")
        incoming("999123", "1", "TEST")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "participant_id", "pid1234")
        self.assertFormQuestionEquals(form, "arm", "arm_a")
        self.assertFormQuestionEquals(form, "external_id", "pid1234")
        case = self.get_case("pid1234")
        self.assertIsNotNone(case)
        self.assertCasePropertyEquals(case, "name", "pid1234")
        self.assertCasePropertyEquals(case, "arm", "arm_a")

        # Mobile worker modifies a case
        incoming("999123", "mod pid1234", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Enter Study Arm 1:a, 2:b.")
        incoming("999123", "b", "TEST")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "arm", "arm_b")
        case = self.get_case("pid1234")
        self.assertIsNotNone(case)
        self.assertCasePropertyEquals(case, "arm", "arm_b")

        # now take the case away from the user
        self.update_case_owner(case, self.user3)
        case = self.get_case("pid1234")

        # then they should no longer have access
        incoming("999123", "mod pid1234", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_message(MSG_CASE_NOT_FOUND))

        # now add access back via parent connection
        self.add_parent_access(self.user1, case)
        incoming("999123", "mod pid1234", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Enter Study Arm 1:a, 2:b.")
        incoming("999123", "a", "TEST")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "arm", "arm_a")
        case = self.get_case("pid1234")
        self.assertIsNotNone(case)
        self.assertCasePropertyEquals(case, "arm", "arm_a")

        form = self.get_last_form_submission()

        # Bad external id
        incoming("999123", "mod pid1235", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_message(MSG_CASE_NOT_FOUND))
        self.assertNoNewSubmission(form)

        # No external id
        incoming("999123", "mod", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_message(MSG_MISSING_EXTERNAL_ID))
        self.assertNoNewSubmission(form)

        # Test validation on all fields
        incoming("999123", "Validation_Test", "TEST")
        session = self.get_open_session(self.user1)
        
        sms = self.assertLastOutboundSMSEquals(self.user1, "text")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "ab", "TEST")
        self.assertTrue(sms.invalid_survey_response)
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, 'Expected "abc"')
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "abc", "TEST")
        self.assertFalse(sms.invalid_survey_response)
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "single select 1:a, 2:b, 3:c, 4:d.")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "x", "TEST")
        self.assertTrue(sms.invalid_survey_response)
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "%s single select 1:a, 2:b, 3:c, 4:d." % get_message(MSG_INVALID_CHOICE))
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "5", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "%s single select 1:a, 2:b, 3:c, 4:d." % get_message(MSG_CHOICE_OUT_OF_RANGE))
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "2", "TEST")
        self.assertFalse(sms.invalid_survey_response)
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "multi select 1:a, 2:b, 3:c, 4:d.")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "%s multi select 1:a, 2:b, 3:c, 4:d." % get_message(MSG_FIELD_REQUIRED))
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "2 x", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "%s multi select 1:a, 2:b, 3:c, 4:d." % get_message(MSG_INVALID_CHOICE))
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "1 5", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "%s multi select 1:a, 2:b, 3:c, 4:d." % get_message(MSG_INVALID_CHOICE))
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "1 c", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "int")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "x", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "%s int" % get_message(MSG_INVALID_INT))
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "50", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "float")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "x", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "%s float" % get_message(MSG_INVALID_FLOAT))
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "21.3", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)
        
        sms = self.assertLastOutboundSMSEquals(self.user1, "long")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "x", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "%s long" % get_message(MSG_INVALID_LONG))
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "-100", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "date")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "x", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "%s date" %
            get_message(MSG_INVALID_DATE, context=('YYYYMMDD',)))
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "20140101", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "time")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "x", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "%s time" % get_message(MSG_INVALID_TIME))
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "2500", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = self.assertLastOutboundSMSEquals(self.user1, "%s time" % get_message(MSG_INVALID_TIME))
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        sms = incoming("999123", "2345", "TEST")
        self.assertMetadataEqual(sms, session._id, WORKFLOW_KEYWORD)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "q_text", "abc")
        self.assertFormQuestionEquals(form, "q_single_select", "b")
        self.assertFormQuestionEquals(form, "q_multi_select", "a c")
        self.assertFormQuestionEquals(form, "q_int", 50, cast=int)
        self.assertFormQuestionEquals(form, "q_float", 21.3, cast=float)
        self.assertFormQuestionEquals(form, "q_long", -100, cast=long)
        self.assertFormQuestionEquals(form, "q_date", date(2014, 1, 1))
        self.assertFormQuestionEquals(form, "q_time", time(23, 45), cast=time_parser)

        # Mobile worker creates a case via structured sms
        incoming("999123", "reg_ss pid1235 1", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Thank you for your registration submission.")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "participant_id", "pid1235")
        self.assertFormQuestionEquals(form, "arm", "arm_a")
        self.assertFormQuestionEquals(form, "external_id", "pid1235")
        case = self.get_case("pid1235")
        self.assertIsNotNone(case)
        self.assertCasePropertyEquals(case, "name", "pid1235")
        self.assertCasePropertyEquals(case, "arm", "arm_a")

        # Mobile worker modifies a case
        incoming("999123", "mod_ss pid1235 b", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Thank you for your modification submission.")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "arm", "arm_b")
        case = self.get_case("pid1235")
        self.assertIsNotNone(case)
        self.assertCasePropertyEquals(case, "arm", "arm_b")

        # Bad external id
        incoming("999123", "mod_ss pid1236", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_message(MSG_CASE_NOT_FOUND))
        self.assertNoNewSubmission(form)

        # No external id
        incoming("999123", "mod_ss", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_message(MSG_MISSING_EXTERNAL_ID))
        self.assertNoNewSubmission(form)

        def get_field_and_message(field_name, msg_id, additional_context=None):
            msg1 = get_message(MSG_FIELD_DESCRIPTOR, context=(field_name,))
            msg2 = get_message(msg_id, context=additional_context)
            return "%s%s" % (msg1, msg2)

        # Test validation on all fields from structured sms: positional args
        incoming("999123", "validation_test_ss_1 ab 2 c 50 21.3 -100 20140101 2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, 'Expected "abc"')
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_1 abc x c 50 21.3 -100 20140101 2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_single_select", MSG_INVALID_CHOICE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_1 abc 5 c 50 21.3 -100 20140101 2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_single_select", MSG_CHOICE_OUT_OF_RANGE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_1 abc 2 x 50 21.3 -100 20140101 2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_multi_select", MSG_INVALID_CHOICE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_1 abc 2 5 50 21.3 -100 20140101 2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_multi_select", MSG_INVALID_CHOICE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_1 abc 2 c x 21.3 -100 20140101 2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_int", MSG_INVALID_INT))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_1 abc 2 c 50 x -100 20140101 2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_float", MSG_INVALID_FLOAT))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_1 abc 2 c 50 21.3 x 20140101 2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_long", MSG_INVALID_LONG))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_1 abc 2 c 50 21.3 -100 x 2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1,
            get_field_and_message("q_date", MSG_INVALID_DATE, ('YYYYMMDD',)))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_1 abc 2 c 50 21.3 -100 20140101 x", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_time", MSG_INVALID_TIME))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_1 abc 2 c 50 21.3 -100 20140101 2500", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_time", MSG_INVALID_TIME))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_1 abc 2 c 50 21.3 -100 20140101 2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Thank you for your submission.")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "q_text", "abc")
        self.assertFormQuestionEquals(form, "q_single_select", "b")
        self.assertFormQuestionEquals(form, "q_multi_select", "c")
        self.assertFormQuestionEquals(form, "q_int", 50, cast=int)
        self.assertFormQuestionEquals(form, "q_float", 21.3, cast=float)
        self.assertFormQuestionEquals(form, "q_long", -100, cast=long)
        self.assertFormQuestionEquals(form, "q_date", date(2014, 1, 1))
        self.assertFormQuestionEquals(form, "q_time", time(23, 45), cast=time_parser)

        # Test validation on all fields from structured sms: positional args with custom delimiter
        incoming("999123", "validation_test_ss_2,ab,2,1 c,50,21.3,-100,20140101,2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, 'Expected "abc"')
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_2,abc,x,1 c,50,21.3,-100,20140101,2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_single_select", MSG_INVALID_CHOICE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_2,abc,5,1 c,50,21.3,-100,20140101,2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_single_select", MSG_CHOICE_OUT_OF_RANGE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_2,abc,2,1 x,50,21.3,-100,20140101,2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_multi_select", MSG_INVALID_CHOICE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_2,abc,2,1 5,50,21.3,-100,20140101,2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_multi_select", MSG_INVALID_CHOICE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_2,abc,2,,50,21.3,-100,20140101,2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_multi_select", MSG_FIELD_REQUIRED))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_2,abc,2,1 c,x,21.3,-100,20140101,2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_int", MSG_INVALID_INT))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_2,abc,2,1 c,50,x,-100,20140101,2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_float", MSG_INVALID_FLOAT))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_2,abc,2,1 c,50,21.3,x,20140101,2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_long", MSG_INVALID_LONG))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_2,abc,2,1 c,50,21.3,-100,x,2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1,
            get_field_and_message("q_date", MSG_INVALID_DATE, ('YYYYMMDD',)))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_2,abc,2,1 c,50,21.3,-100,20140101,x", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_time", MSG_INVALID_TIME))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_2,abc,2,1 c,50,21.3,-100,20140101,2500", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("q_time", MSG_INVALID_TIME))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_2,abc,2,1 c,50,21.3,-100,20140101,2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Thank you for your submission.")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "q_text", "abc")
        self.assertFormQuestionEquals(form, "q_single_select", "b")
        self.assertFormQuestionEquals(form, "q_multi_select", "a c")
        self.assertFormQuestionEquals(form, "q_int", 50, cast=int)
        self.assertFormQuestionEquals(form, "q_float", 21.3, cast=float)
        self.assertFormQuestionEquals(form, "q_long", -100, cast=long)
        self.assertFormQuestionEquals(form, "q_date", date(2014, 1, 1))
        self.assertFormQuestionEquals(form, "q_time", time(23, 45), cast=time_parser)

        # Test validation on all fields from structured sms: named args with custom delimiter
        incoming("999123", "validation_test_ss_3,arg1ab,arg22,arg31 c,arg450,arg521.3,arg6-100,arg720140101,arg82345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, 'Expected "abc"')
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_3,arg1abc,arg2x,arg31 c,arg450,arg521.3,arg6-100,arg720140101,arg82345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG2", MSG_INVALID_CHOICE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_3,arg1abc,arg25,arg31 c,arg450,arg521.3,arg6-100,arg720140101,arg82345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG2", MSG_CHOICE_OUT_OF_RANGE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_3,arg1abc,arg22,arg31 x,arg450,arg521.3,arg6-100,arg720140101,arg82345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG3", MSG_INVALID_CHOICE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_3,arg1abc,arg22,arg31 5,arg450,arg521.3,arg6-100,arg720140101,arg82345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG3", MSG_INVALID_CHOICE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_3,arg1abc,arg22,arg3,arg450,arg521.3,arg6-100,arg720140101,arg82345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG3", MSG_FIELD_REQUIRED))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_3,arg1abc,arg22,arg31 c,arg4x,arg521.3,arg6-100,arg720140101,arg82345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG4", MSG_INVALID_INT))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_3,arg1abc,arg22,arg31 c,arg450,arg5x,arg6-100,arg720140101,arg82345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG5", MSG_INVALID_FLOAT))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_3,arg1abc,arg22,arg31 c,arg450,arg521.3,arg6x,arg720140101,arg82345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG6", MSG_INVALID_LONG))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_3,arg1abc,arg22,arg31 c,arg450,arg521.3,arg6-100,arg7x,arg82345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1,
            get_field_and_message("ARG7", MSG_INVALID_DATE, ('YYYYMMDD',)))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_3,arg1abc,arg22,arg31 c,arg450,arg521.3,arg6-100,arg720140101,arg8x", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG8", MSG_INVALID_TIME))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_3,arg1abc,arg22,arg31 c,arg450,arg521.3,arg6-100,arg720140101,arg82500", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG8", MSG_INVALID_TIME))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_3,arg1abc,arg22,arg31 c,arg450,arg521.3,arg6-100,arg720140101,arg82345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Thank you for your submission.")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "q_text", "abc")
        self.assertFormQuestionEquals(form, "q_single_select", "b")
        self.assertFormQuestionEquals(form, "q_multi_select", "a c")
        self.assertFormQuestionEquals(form, "q_int", 50, cast=int)
        self.assertFormQuestionEquals(form, "q_float", 21.3, cast=float)
        self.assertFormQuestionEquals(form, "q_long", -100, cast=long)
        self.assertFormQuestionEquals(form, "q_date", date(2014, 1, 1))
        self.assertFormQuestionEquals(form, "q_time", time(23, 45), cast=time_parser)

        # Test validation on all fields from structured sms: named args with custom delimiter and joining character
        incoming("999123", "validation_test_ss_4,arg1=ab,arg2=2,arg3=1 c,arg4=50,arg5=21.3,arg6=-100,arg7=20140101,arg8=2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, 'Expected "abc"')
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_4,arg1=abc,arg2=x,arg3=1 c,arg4=50,arg5=21.3,arg6=-100,arg7=20140101,arg8=2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG2", MSG_INVALID_CHOICE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_4,arg1=abc,arg2=5,arg3=1 c,arg4=50,arg5=21.3,arg6=-100,arg7=20140101,arg8=2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG2", MSG_CHOICE_OUT_OF_RANGE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_4,arg1=abc,arg2=2,arg3=1 x,arg4=50,arg5=21.3,arg6=-100,arg7=20140101,arg8=2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG3", MSG_INVALID_CHOICE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_4,arg1=abc,arg2=2,arg3=1 5,arg4=50,arg5=21.3,arg6=-100,arg7=20140101,arg8=2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG3", MSG_INVALID_CHOICE))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_4,arg1=abc,arg2=2,arg3=,arg4=50,arg5=21.3,arg6=-100,arg7=20140101,arg8=2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG3", MSG_FIELD_REQUIRED))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_4,arg1=abc,arg2=2,arg3=1 c,arg4=x,arg5=21.3,arg6=-100,arg7=20140101,arg8=2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG4", MSG_INVALID_INT))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_4,arg1=abc,arg2=2,arg3=1 c,arg4=50,arg5=x,arg6=-100,arg7=20140101,arg8=2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG5", MSG_INVALID_FLOAT))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_4,arg1=abc,arg2=2,arg3=1 c,arg4=50,arg5=21.3,arg6=x,arg7=20140101,arg8=2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG6", MSG_INVALID_LONG))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_4,arg1=abc,arg2=2,arg3=1 c,arg4=50,arg5=21.3,arg6=-100,arg7=x,arg8=2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1,
            get_field_and_message("ARG7", MSG_INVALID_DATE, ('YYYYMMDD',)))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_4,arg1=abc,arg2=2,arg3=1 c,arg4=50,arg5=21.3,arg6=-100,arg7=20140101,arg8=x", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG8", MSG_INVALID_TIME))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_4,arg1=abc,arg2=2,arg3=1 c,arg4=50,arg5=21.3,arg6=-100,arg7=20140101,arg8=2500", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARG8", MSG_INVALID_TIME))
        self.assertNoNewSubmission(form)
        incoming("999123", "validation_test_ss_4,arg1=abc,arg2=2,arg3=1 c,arg4=50,arg5=21.3,arg6=-100,arg7=20140101,arg8=2345", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Thank you for your submission.")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "q_text", "abc")
        self.assertFormQuestionEquals(form, "q_single_select", "b")
        self.assertFormQuestionEquals(form, "q_multi_select", "a c")
        self.assertFormQuestionEquals(form, "q_int", 50, cast=int)
        self.assertFormQuestionEquals(form, "q_float", 21.3, cast=float)
        self.assertFormQuestionEquals(form, "q_long", -100, cast=long)
        self.assertFormQuestionEquals(form, "q_date", date(2014, 1, 1))
        self.assertFormQuestionEquals(form, "q_time", time(23, 45), cast=time_parser)

        # Test leaving fields blank via structured sms
        incoming("999123", "validation_test_ss_4,arg1=abc,arg3=1 c", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Thank you for your submission.")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "q_text", "abc")
        self.assertFormQuestionEquals(form, "q_single_select", "")
        self.assertFormQuestionEquals(form, "q_multi_select", "a c")
        self.assertFormQuestionEquals(form, "q_int", "")
        self.assertFormQuestionEquals(form, "q_float", "")
        self.assertFormQuestionEquals(form, "q_long", "")
        self.assertFormQuestionEquals(form, "q_date", "")
        self.assertFormQuestionEquals(form, "q_time", "")

        incoming("999123", "validation_test_ss_1 abc b c", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Thank you for your submission.")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "q_text", "abc")
        self.assertFormQuestionEquals(form, "q_single_select", "b")
        self.assertFormQuestionEquals(form, "q_multi_select", "c")
        self.assertFormQuestionEquals(form, "q_int", "")
        self.assertFormQuestionEquals(form, "q_float", "")
        self.assertFormQuestionEquals(form, "q_long", "")
        self.assertFormQuestionEquals(form, "q_date", "")
        self.assertFormQuestionEquals(form, "q_time", "")

        incoming("999123", "mod_ss_2,pid1235", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("arm", MSG_FIELD_REQUIRED))
        self.assertNoNewSubmission(form)

        incoming("999123", "mod_ss_2,pid1235,", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("arm", MSG_FIELD_REQUIRED))
        self.assertNoNewSubmission(form)

        incoming("999123", "mod_ss_3,pid1235,arm=", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_field_and_message("ARM", MSG_FIELD_REQUIRED))
        self.assertNoNewSubmission(form)

        incoming("999123", "mod_ss_3,pid1235,arm a", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_message(MSG_EXPECTED_NAMED_ARGS_SEPARATOR, context=("=",)))
        self.assertNoNewSubmission(form)

        incoming("999123", "mod_ss_3,pid1235,arm=a,arm=b", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_message(MSG_MULTIPLE_ANSWERS_FOUND, context=("ARM",)))
        self.assertNoNewSubmission(form)

        incoming("999123", "mod_ss_3 ,  pid1235  ,  arm = a", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Thank you for your modification submission.")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "arm", "arm_a")
        case = self.get_case("pid1235")
        self.assertIsNotNone(case)
        self.assertCasePropertyEquals(case, "arm", "arm_a")

        # Test global keywords
        incoming("999123", "#start unknownkeyword", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_message(MSG_KEYWORD_NOT_FOUND, context=("UNKNOWNKEYWORD",)))
        self.assertNoNewSubmission(form)

        incoming("999123", "#start", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_message(MSG_START_KEYWORD_USAGE, context=("#START",)))
        self.assertNoNewSubmission(form)

        incoming("999123", "#unknown", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_message(MSG_UNKNOWN_GLOBAL_KEYWORD, context=("#UNKNOWN",)))
        self.assertNoNewSubmission(form)

        # Mobile worker creates a case
        incoming("999123", "#start reg", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Enter Participant ID")
        incoming("999123", "pid1237", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Enter Study Arm 1:a, 2:b.")
        incoming("999123", "1", "TEST")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "participant_id", "pid1237")
        self.assertFormQuestionEquals(form, "arm", "arm_a")
        self.assertFormQuestionEquals(form, "external_id", "pid1237")
        case = self.get_case("pid1237")
        self.assertIsNotNone(case)
        self.assertCasePropertyEquals(case, "name", "pid1237")
        self.assertCasePropertyEquals(case, "arm", "arm_a")

        # Mobile worker modifies a case
        incoming("999123", "#start mod pid1237", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Enter Study Arm 1:a, 2:b.")
        incoming("999123", "b", "TEST")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "arm", "arm_b")
        case = self.get_case("pid1237")
        self.assertIsNotNone(case)
        self.assertCasePropertyEquals(case, "arm", "arm_b")

        # Bad external id
        incoming("999123", "#start mod pid1240", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_message(MSG_CASE_NOT_FOUND))
        self.assertNoNewSubmission(form)

        # No external id
        incoming("999123", "#start mod", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, get_message(MSG_MISSING_EXTERNAL_ID))
        self.assertNoNewSubmission(form)

        # CURRENT keyword
        incoming("999123", "reg", "TEST")
        sms1 = self.assertLastOutboundSMSEquals(self.user1, "Enter Participant ID")
        incoming("999123", "#CURRENT", "TEST")
        sms2 = self.assertLastOutboundSMSEquals(self.user1, "Enter Participant ID")
        self.assertNotEqual(sms1.pk, sms2.pk)

        # STOP keyword
        session = self.get_open_session(self.user1)
        self.assertIsNotNone(session)
        incoming("999123", "#STOP", "TEST")
        session = self.get_open_session(self.user1)
        self.assertIsNone(session)
        self.assertNoNewSubmission(form)

        # One keyword overrides another
        incoming("999123", "reg", "TEST")
        sms1 = self.assertLastOutboundSMSEquals(self.user1, "Enter Participant ID")
        incoming("999123", "mod pid1237", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Enter Study Arm 1:a, 2:b.")
        self.assertNoNewSubmission(form)
        incoming("999123", "reg", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "%s Enter Study Arm 1:a, 2:b." % get_message(MSG_INVALID_CHOICE))
        incoming("999123", "a", "TEST")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "arm", "arm_a")
        case = self.get_case("pid1237")
        self.assertIsNotNone(case)
        self.assertCasePropertyEquals(case, "arm", "arm_a")

        # Test initator filters
        case = self.get_case("pid1237")
        update_case(self.domain, case.case_id,
            case_properties={'contact_phone_number': '999124', 'contact_phone_number_is_verified': '1'})
        case = CaseAccessors(self.domain).get_case(case.case_id)

        incoming("999123", "for_user", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "This message is for users")
        incoming("999123", "for_case", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Default SMS Response")

        incoming("999124", "for_case", "TEST")
        self.assertLastOutboundSMSEquals(case, "This message is for cases")
        incoming("999124", "for_user", "TEST")
        self.assertLastOutboundSMSEquals(case, "Default SMS Response")

        # Test form over sms for case
        incoming("999124", "mod", "TEST")
        self.assertLastOutboundSMSEquals(case, "Enter Study Arm 1:a, 2:b.")
        incoming("999123", "mod pid1237", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "Enter Study Arm 1:a, 2:b.")
        incoming("999124", "b", "TEST")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "arm", "arm_b")
        case = self.get_case("pid1237")
        self.assertCasePropertyEquals(case, "arm", "arm_b")

        incoming("999123", "a", "TEST")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "arm", "arm_a")
        case = self.get_case("pid1237")
        self.assertCasePropertyEquals(case, "arm", "arm_a")

        # Test structured sms for case
        incoming("999124", "mod_ss 2", "TEST")
        self.assertLastOutboundSMSEquals(case, "Thank you for your modification submission.")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "arm", "arm_b")
        case = self.get_case("pid1237")
        self.assertCasePropertyEquals(case, "arm", "arm_b")

        # Test Auth
        incoming("999122", "mod pid1237", "TEST")
        self.assertLastOutboundSMSEquals(self.user2, get_message(MSG_CASE_NOT_FOUND))

        # Test notifying others
        incoming("999124", "for_owner", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "This message is for the case owner")

        incoming("999124", "for_group", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "This message is for the group")
        self.assertLastOutboundSMSEquals(self.user2, "This message is for the group")

        case = self.get_case("pid1237")
        self.update_case_owner(case, self.group1)
        incoming("999124", "for_owner", "TEST")
        self.assertLastOutboundSMSEquals(self.user1, "This message is for the case owner")
        self.assertLastOutboundSMSEquals(self.user2, "This message is for the case owner")

        # Test case sharing auth
        incoming("999122", "mod pid1237", "TEST")
        self.assertLastOutboundSMSEquals(self.user2, "Enter Study Arm 1:a, 2:b.")
        incoming("999122", "1", "TEST")
        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "arm", "arm_a")
        case = self.get_case("pid1237")
        self.assertCasePropertyEquals(case, "arm", "arm_a")

        # Test closing open sessions on an sms reply
        incoming("999122", "reg", "TEST")
        self.assertLastOutboundSMSEquals(self.user2, "Enter Participant ID")
        incoming("999122", "for_user", "TEST")
        self.assertLastOutboundSMSEquals(self.user2, "This message is for users")
        incoming("999122", "null", "TEST")
        self.assertLastOutboundSMSEquals(self.user2, "Default SMS Response")
Ejemplo n.º 38
0
    def test_case_property_start_date_with_blank_option(self):
        reminder = (CaseReminderHandler
            .create(self.domain, 'test')
            .set_case_criteria_start_condition('participant', 'status', MATCH_EXACT, 'green')
            .set_case_criteria_start_date(start_date='start_date')
            .set_case_recipient()
            .set_sms_content_type('en')
            .set_daily_schedule(fire_time=time(12, 0),
                message={'en': 'Hello {case.name}, your test result was normal.'})
            .set_stop_condition(max_iteration_count=30)
            .set_advanced_options(use_today_if_start_date_is_blank=True))
        reminder.save()

        self.assertEqual(self.get_reminders(), [])

        with create_test_case(self.domain, 'participant', 'bob', drop_signals=False) as case, \
                patch('corehq.apps.reminders.models.CaseReminderHandler.get_now') as now_mock:
            self.assertEqual(self.get_reminders(), [])

            now_mock.return_value = datetime(2016, 1, 1, 10, 0)

            # start_date is blank, but reminder should be spawned using today's value
            update_case(self.domain, case.case_id, case_properties={'status': 'green'})

            reminder_instance = self.assertOneReminder()
            self.assertEqual(reminder_instance.domain, self.domain)
            self.assertEqual(reminder_instance.case_id, case.case_id)
            self.assertEqual(reminder_instance.handler_id, reminder.get_id)
            self.assertIsNone(reminder_instance.user_id)
            self.assertEqual(reminder_instance.next_fire, datetime(2016, 1, 1, 12, 0))
            self.assertTrue(reminder_instance.active)
            self.assertEqual(reminder_instance.start_date, date(2016, 1, 1))
            self.assertEqual(reminder_instance.schedule_iteration_num, 1)
            self.assertEqual(reminder_instance.current_event_sequence_num, 0)
            self.assertEqual(reminder_instance.callback_try_count, 0)
            self.assertIsNone(reminder_instance.start_condition_datetime)
            self.assertEqual(reminder_instance.callback_try_count, 0)

            # update start_date and the schedule should be recalculated
            update_case(self.domain, case.case_id, case_properties={'start_date': '2016-01-08'})

            reminder_instance = self.assertOneReminder()
            self.assertEqual(reminder_instance.domain, self.domain)
            self.assertEqual(reminder_instance.case_id, case.case_id)
            self.assertEqual(reminder_instance.handler_id, reminder.get_id)
            self.assertIsNone(reminder_instance.user_id)
            self.assertEqual(reminder_instance.next_fire, datetime(2016, 1, 8, 12, 0))
            self.assertTrue(reminder_instance.active)
            self.assertEqual(reminder_instance.start_date, date(2016, 1, 8))
            self.assertEqual(reminder_instance.schedule_iteration_num, 1)
            self.assertEqual(reminder_instance.current_event_sequence_num, 0)
            self.assertEqual(reminder_instance.callback_try_count, 0)
            self.assertEqual(reminder_instance.start_condition_datetime, datetime(2016, 1, 8))
            self.assertEqual(reminder_instance.callback_try_count, 0)

            # update start_date to be in the past and the schedule should be recalculated and fast-forwarded
            update_case(self.domain, case.case_id, case_properties={'start_date': '2015-12-20'})

            reminder_instance = self.assertOneReminder()
            self.assertEqual(reminder_instance.domain, self.domain)
            self.assertEqual(reminder_instance.case_id, case.case_id)
            self.assertEqual(reminder_instance.handler_id, reminder.get_id)
            self.assertIsNone(reminder_instance.user_id)
            self.assertEqual(reminder_instance.next_fire, datetime(2016, 1, 1, 12, 0))
            self.assertTrue(reminder_instance.active)
            self.assertEqual(reminder_instance.start_date, date(2015, 12, 20))
            self.assertEqual(reminder_instance.schedule_iteration_num, 13)
            self.assertEqual(reminder_instance.current_event_sequence_num, 0)
            self.assertEqual(reminder_instance.callback_try_count, 0)
            self.assertEqual(reminder_instance.start_condition_datetime, datetime(2015, 12, 20))
            self.assertEqual(reminder_instance.callback_try_count, 0)

            # update start_date to be further in the past and the reminder should be deactivated
            update_case(self.domain, case.case_id, case_properties={'start_date': '2015-12-01'})

            reminder_instance = self.assertOneReminder()
            self.assertEqual(reminder_instance.domain, self.domain)
            self.assertEqual(reminder_instance.case_id, case.case_id)
            self.assertEqual(reminder_instance.handler_id, reminder.get_id)
            self.assertIsNone(reminder_instance.user_id)
            self.assertEqual(reminder_instance.next_fire, datetime(2015, 12, 31, 12, 0))
            self.assertFalse(reminder_instance.active)
            self.assertEqual(reminder_instance.start_date, date(2015, 12, 1))
            self.assertEqual(reminder_instance.schedule_iteration_num, 31)
            self.assertEqual(reminder_instance.current_event_sequence_num, 0)
            self.assertEqual(reminder_instance.callback_try_count, 0)
            self.assertEqual(reminder_instance.start_condition_datetime, datetime(2015, 12, 1))
            self.assertEqual(reminder_instance.callback_try_count, 0)

            # set start_date to be blank and the reminder should go back to using today as start date
            update_case(self.domain, case.case_id, case_properties={'start_date': ''})

            reminder_instance = self.assertOneReminder()
            self.assertEqual(reminder_instance.domain, self.domain)
            self.assertEqual(reminder_instance.case_id, case.case_id)
            self.assertEqual(reminder_instance.handler_id, reminder.get_id)
            self.assertIsNone(reminder_instance.user_id)
            self.assertEqual(reminder_instance.next_fire, datetime(2016, 1, 1, 12, 0))
            self.assertTrue(reminder_instance.active)
            self.assertEqual(reminder_instance.start_date, date(2016, 1, 1))
            self.assertEqual(reminder_instance.schedule_iteration_num, 1)
            self.assertEqual(reminder_instance.current_event_sequence_num, 0)
            self.assertEqual(reminder_instance.callback_try_count, 0)
            self.assertIsNone(reminder_instance.start_condition_datetime)
            self.assertEqual(reminder_instance.callback_try_count, 0)
Ejemplo n.º 39
0
 def update_single_case(self, episode_case):
     # updates a single episode_case.
     assert episode_case.domain == self.domain
     update_json = EpisodeAdherenceUpdate(episode_case, self).update_json()
     if update_json:
         update_case(self.domain, episode_case.case_id, update_json)
Ejemplo n.º 40
0
    def test_static_negative_growth_indicator(self):
        c = CustomContent(custom_content_id='ICDS_STATIC_NEGATIVE_GROWTH_MESSAGE')

        schedule_instance = CaseTimedScheduleInstance(
            domain=self.domain,
            case_id=self.child_health_case.case_id,
        )

        c.set_context(schedule_instance=schedule_instance)

        # Test when current weight is greater than previous
        submit_growth_form(self.domain, self.child_health_case.case_id, '10.1', '10.4')
        self.assertEqual(
            c.get_list_of_messages(self.mother_person_case),
            []
        )

        # Test when current weight is equal to previous
        submit_growth_form(self.domain, self.child_health_case.case_id, '10.1', '10.1')
        self.assertEqual(
            c.get_list_of_messages(self.mother_person_case),
            ["As per the latest records of your AWC, the weight of your child Joe has remained static in the last "
             "month. Please consult your AWW for necessary advice."]
        )

        # Test when current weight is less than previous
        submit_growth_form(self.domain, self.child_health_case.case_id, '10.1', '9.9')
        self.assertEqual(
            c.get_list_of_messages(self.mother_person_case),
            ["As per the latest records of your AWC, the weight of your child Joe has reduced in the last month. "
             "Please consult your AWW for necessary advice."]
        )

        # Test ignoring forms with the wrong xmlns
        update_case(self.domain, self.child_health_case.case_id, {'property': 'value1'})
        update_case(self.domain, self.child_health_case.case_id, {'property': 'value2'})
        update_case(self.domain, self.child_health_case.case_id, {'property': 'value3'})
        update_case(self.domain, self.child_health_case.case_id, {'property': 'value4'})
        update_case(self.domain, self.child_health_case.case_id, {'property': 'value5'})
        update_case(self.domain, self.child_health_case.case_id, {'property': 'value6'})
        update_case(self.domain, self.child_health_case.case_id, {'property': 'value7'})
        update_case(self.domain, self.child_health_case.case_id, {'property': 'value8'})
        update_case(self.domain, self.child_health_case.case_id, {'property': 'value9'})
        update_case(self.domain, self.child_health_case.case_id, {'property': 'value10'})

        self.assertEqual(
            c.get_list_of_messages(self.mother_person_case),
            ["As per the latest records of your AWC, the weight of your child Joe has reduced in the last month. "
             "Please consult your AWW for necessary advice."]
        )