Пример #1
0
    def test_migration(self):
        xform = self.get_xml("form")
        form_bad_tz = self.get_json("form")
        case_bad_tz = self.get_json("case")
        form_good_tz = self.get_json("form-tz")
        case_good_tz = self.get_json("case-tz")
        with override_settings(PHONE_TIMEZONES_HAVE_BEEN_PROCESSED=False, PHONE_TIMEZONES_SHOULD_BE_PROCESSED=False):
            submit_form_locally(xform, self.domain)

        # Form before
        xform_instance, = get_forms_by_type(self.domain, "XFormInstance", limit=10)
        xform_json = xform_instance.to_json()
        self._compare_forms(xform_json, form_bad_tz, "Form before migration does not match")

        # Case before
        case, = get_cases_in_domain(self.domain)
        self._compare_cases(case.to_json(), case_bad_tz, "Case before migration does not match")
        run_timezone_migration_for_domain(self.domain)

        # Form after
        xform_instance, = get_forms_by_type(self.domain, "XFormInstance", limit=10)
        xform_json = xform_instance.to_json()
        self._compare_forms(xform_json, form_good_tz, "Form after migration does not match")

        # Case after
        case, = get_cases_in_domain(self.domain)
        self._compare_cases(case.to_json(), case_good_tz, "Case after migration does not match")
    def test_migration(self):
        xform = self.get_xml('form')
        form_bad_tz = self.get_json('form')
        case_bad_tz = self.get_json('case')
        form_good_tz = self.get_json('form-tz')
        case_good_tz = self.get_json('case-tz')
        with override_settings(PHONE_TIMEZONES_HAVE_BEEN_PROCESSED=False,
                               PHONE_TIMEZONES_SHOULD_BE_PROCESSED=False):
            submit_form_locally(xform, self.domain)

        # Form before
        xform_instance, = get_forms_by_type(self.domain, 'XFormInstance', limit=10)
        xform_json = xform_instance.to_json()
        self._compare_forms(xform_json, form_bad_tz,
                            "Form before migration does not match")

        # Case before
        case, = get_cases_in_domain(self.domain)
        self._compare_cases(case.to_json(), case_bad_tz,
                            "Case before migration does not match")
        run_timezone_migration_for_domain(self.domain)

        # Form after
        xform_instance, = get_forms_by_type(self.domain, 'XFormInstance', limit=10)
        xform_json = xform_instance.to_json()
        self._compare_forms(xform_json, form_good_tz,
                            "Form after migration does not match")

        # Case after
        case, = get_cases_in_domain(self.domain)
        self._compare_cases(case.to_json(), case_good_tz,
                            "Case after migration does not match")
Пример #3
0
    def testLocationOwner(self):
        # This is actually testing several different things, but I figure it's
        # worth it, as each of these tests takes a non-trivial amount of time.
        non_case_sharing = LocationType.objects.create(
            domain=self.domain, name='lt1', shares_cases=False
        )
        case_sharing = LocationType.objects.create(
            domain=self.domain, name='lt2', shares_cases=True
        )
        location = make_loc('loc-1', 'Loc 1', self.domain, case_sharing)
        make_loc('loc-2', 'Loc 2', self.domain, case_sharing)
        duplicate_loc = make_loc('loc-3', 'Loc 2', self.domain, case_sharing)
        improper_loc = make_loc('loc-4', 'Loc 4', self.domain, non_case_sharing)

        res = self.import_mock_file([
            ['case_id', 'name', 'owner_id', 'owner_name'],
            ['', 'location-owner-id', location.group_id, ''],
            ['', 'location-owner-code', '', location.site_code],
            ['', 'location-owner-name', '', location.name],
            ['', 'duplicate-location-name', '', duplicate_loc.name],
            ['', 'non-case-owning-name', '', improper_loc.name],
        ])
        cases = {c.name: c for c in list(get_cases_in_domain(self.domain))}

        self.assertEqual(cases['location-owner-id'].owner_id, location.group_id)
        self.assertEqual(cases['location-owner-code'].owner_id, location.group_id)
        self.assertEqual(cases['location-owner-name'].owner_id, location.group_id)

        error_message = ImportErrors.DuplicateLocationName
        self.assertIn(error_message, res['errors'])
        self.assertEqual(res['errors'][error_message]['rows'], [4])

        error_message = ImportErrors.InvalidOwnerId
        self.assertIn(error_message, res['errors'])
        self.assertEqual(res['errors'][error_message]['rows'], [5])
 def handle(self, *args, **options):
     domain = 'care-bihar'
     root_types = ('cc_bihar_pregnancy', 'cc_bihar_newborn')
     TASK_TYPE = 'task'
     # loop through all mother cases, then all child cases
     # for each case get all associated tasks
     # if any duplicates found, clean up / print them
     with open('bihar-duplicate-tasks.csv', 'wb') as f:
         writer = csv.writer(f, dialect=csv.excel)
         _dump_headings(writer)
         for case_type in root_types:
             for parent_case in get_cases_in_domain(domain, case_type):
                 try:
                     tasks = filter(lambda subcase: subcase.type == TASK_TYPE, parent_case.get_subcases())
                     if tasks:
                         types = [_task_id(t) for t in tasks]
                         unique_types = set(types)
                         if len(unique_types) != len(tasks):
                             for type_being_checked in unique_types:
                                 matching_cases = [t for t in tasks if _task_id(t) == type_being_checked]
                                 if len(matching_cases) > 1:
                                     for row, case in _get_rows(parent_case, matching_cases):
                                         keep = row[-1]
                                         writer.writerow(row)
                                         if options['cleanup'] and not keep:
                                             _purge(case)
                 except Exception, e:
                     print 'error with case %s (%s)' % (parent_case._id, e)
    def handle(self, *args, **options):
        domain = 'care-bihar'

        # forward all cases that were last modified between these dates
        def should_forward_case(case):
            min_date = datetime(2013, 9, 10)
            max_date = datetime(2013, 11, 7)
            return (case.server_modified_on
                    and min_date < case.server_modified_on < max_date)

        prod_repeater = CaseRepeater.get('a478a5a3d8964338cb3124de77e3ec58')
        success_count = 0
        fail_count = 0
        for case in get_cases_in_domain(domain):
            try:
                if should_forward_case(case):
                    prod_repeater.register(case)
                    success_count += 1
            except Exception:
                fail_count += 1
                logging.exception(
                    'problem creating repeater stub for case %s' % case._id)

        print 'successfully forwarded %s cases. %s were not processed' % (
            success_count, fail_count)
Пример #6
0
 def handle(self, *args, **options):
     domain = 'care-bihar'
     root_types = ('cc_bihar_pregnancy', 'cc_bihar_newborn')
     TASK_TYPE = 'task'
     # loop through all mother cases, then all child cases
     # for each case get all associated tasks
     # if any duplicates found, clean up / print them
     with open('bihar-duplicate-tasks.csv', 'wb') as f:
         writer = csv.writer(f, dialect=csv.excel)
         _dump_headings(writer)
         for case_type in root_types:
             for parent_case in get_cases_in_domain(domain, case_type):
                 try:
                     tasks = filter(
                         lambda subcase: subcase.type == TASK_TYPE,
                         parent_case.get_subcases())
                     if tasks:
                         types = [_task_id(t) for t in tasks]
                         unique_types = set(types)
                         if len(unique_types) != len(tasks):
                             for type_being_checked in unique_types:
                                 matching_cases = [
                                     t for t in tasks
                                     if _task_id(t) == type_being_checked
                                 ]
                                 if len(matching_cases) > 1:
                                     for row, case in _get_rows(
                                             parent_case, matching_cases):
                                         keep = row[-1]
                                         writer.writerow(row)
                                         if options['cleanup'] and not keep:
                                             _purge(case)
                 except Exception, e:
                     print 'error with case %s (%s)' % (parent_case._id, e)
Пример #7
0
 def test_get_cases_in_domain__type(self):
     self.assert_doc_list_equal(
         get_cases_in_domain(self.domain, type='type1'),
         [
             case for case in self.cases
             if case.domain == self.domain and case.type == 'type1'
         ],
     )
Пример #8
0
    def handle(self, *args, **options):
        if len(args) == 0:
            raise CommandError("Usage: python manage.py check_case_verified_numbers <domain1 domain2 ...>")

        make_fixes = options["fix"]

        for domain in args:
            print "*** Processing Domain %s ***" % domain
            for case in get_cases_in_domain(domain):
                contact_phone_number = case.get_case_property("contact_phone_number")
                contact_phone_number_is_verified = case.get_case_property("contact_phone_number_is_verified")
                contact_backend_id = case.get_case_property("contact_backend_id")
                contact_ivr_backend_id = case.get_case_property("contact_ivr_backend_id")
                
                contact = case
                verified_numbers = contact.get_verified_numbers(include_pending=True)
                
                should_have_entry = contact_phone_number_is_verified and contact_phone_number is not None and contact_phone_number != "" and str(contact_phone_number) != "0" and not case.closed
                has_entry = len(verified_numbers) > 0
                
                if len(verified_numbers) > 1:
                    print "skipping case %s, multiple verified number entries found" % case._id
                    continue
                
                if has_entry:
                    verified_number = sorted(verified_numbers.iteritems())[0][1]
                    if not verified_number.verified:
                        print "skipping case %s, unverified number found" % case._id
                        continue
                
                if has_entry and should_have_entry:
                    if verified_number.phone_number != contact_phone_number or verified_number.backend_id != contact_backend_id or verified_number.ivr_backend_id != contact_ivr_backend_id:
                        print "DISCREPANCY: case %s case properties don't match the verified number entry" % case._id
                        if make_fixes:
                            try:
                                contact.save_verified_number(contact.domain, contact_phone_number, True, contact_backend_id, ivr_backend_id=contact_ivr_backend_id, only_one_number_allowed=True)
                            except (InvalidFormatException, PhoneNumberInUseException):
                                contact.delete_verified_number()
                elif has_entry and not should_have_entry:
                    print "DISCREPANCY: case %s has a verified number but should not" % case._id
                    if make_fixes:
                        contact.delete_verified_number()
                elif not has_entry and should_have_entry:
                    try:
                        contact.verify_unique_number(contact_phone_number)
                    except InvalidFormatException:
                        print "DISCREPANCY: case %s does not have a verified number because number format is invalid" % case._id
                    except PhoneNumberInUseException:
                        print "DISCREPANCY: case %s does not have a verified number because number is already in use" % case._id
                    else:
                        print "DISCREPANCY: case %s does not have a verified number but should" % case._id
                        if make_fixes:
                            contact.save_verified_number(contact.domain, contact_phone_number, True, contact_backend_id, ivr_backend_id=contact_ivr_backend_id, only_one_number_allowed=True)
                else:
                    # Doesn't have an entry, and shouldn't have an entry
                    pass
Пример #9
0
    def get_participants(self):
        result = get_cases_in_domain(self.domain, 'participant')
        survey_report_date = parse(self.survey_report_date).date()

        def filter_function(case):
            registration_date = get_date(case, "start_date")
            if registration_date is None:
                return False
            first_tuesday = self.get_first_tuesday(registration_date)
            last_tuesday = first_tuesday + timedelta(days=49)
            return first_tuesday <= survey_report_date <= last_tuesday

        result = filter(filter_function, result)
        return result
Пример #10
0
    def get_participants(self):
        result = get_cases_in_domain(self.domain, 'participant')
        survey_report_date = parse(self.survey_report_date).date()

        def filter_function(case):
            registration_date = get_date(case, "start_date")
            if registration_date is None:
                return False
            first_tuesday = self.get_first_tuesday(registration_date)
            last_tuesday = first_tuesday + timedelta(days=49)
            return first_tuesday <= survey_report_date <= last_tuesday

        result = filter(filter_function, result)
        return result
Пример #11
0
 def test_simple(self):
     caseblock = CaseBlock(create=True,
                           case_id=uuid.uuid4().hex,
                           user_id=self.user_id,
                           owner_id=self.user_id,
                           case_type='exploder-type',
                           version=V2).as_string()
     submit_case_blocks([caseblock], self.domain.name)
     self.assertEqual(1, len(get_case_ids_in_domain(self.domain.name)))
     explode_cases(self.user_id, self.domain.name, 10)
     cases_back = list(get_cases_in_domain(self.domain.name))
     self.assertEqual(10, len(cases_back))
     for case in cases_back:
         self.assertEqual(self.user_id, case.owner_id)
Пример #12
0
def get_interactive_participants(domain):
    cases = get_cases_in_domain(domain, 'participant')
    result = []
    timezone = get_timezone_for_user(None, domain)  # Use project timezone only
    current_date = datetime.now(tz=timezone).date()
    for case in cases:
        study_arm = case.get_case_property("study_arm")
        if isinstance(study_arm, six.string_types) and study_arm.upper() == "A" and not case.closed:
            start_date = get_date(case, "start_date")
            if start_date is None:
                continue
            end_date = start_date + timedelta(days=55)
            if start_date <= current_date <= end_date:
                result.append(case)
    return result
Пример #13
0
def get_interactive_participants(domain):
    cases = get_cases_in_domain(domain, 'participant')
    result = []
    timezone = get_timezone_for_user(None, domain)  # Use project timezone only
    current_date = datetime.now(tz=timezone).date()
    for case in cases:
        study_arm = case.get_case_property("study_arm")
        if isinstance(study_arm, basestring) and study_arm.upper() == "A" and not case.closed:
            start_date = get_date(case, "start_date")
            if start_date is None:
                continue
            end_date = start_date + timedelta(days=55)
            if start_date <= current_date <= end_date:
                result.append(case)
    return result
Пример #14
0
 def test_skip_user_case(self):
     caseblock = CaseBlock(
         create=True,
         case_id=uuid.uuid4().hex,
         user_id=self.user_id,
         owner_id=self.user_id,
         case_type='commcare-user',
     ).as_string()
     submit_case_blocks([caseblock], self.domain.name)
     self.assertEqual(1, len(get_case_ids_in_domain(self.domain.name)))
     explode_cases(self.user_id, self.domain.name, 10)
     cases_back = list(get_cases_in_domain(self.domain.name))
     self.assertEqual(1, len(cases_back))
     for case in cases_back:
         self.assertEqual(self.user_id, case.owner_id)
Пример #15
0
def indexed_facilities():
    facility_index = {}
    for domain in DOMAINS:
        current_domain_index = {}
        facilities = get_cases_in_domain(domain, type="facility")
        for facility in facilities:
            case_sharing_group = GROUPS_BY_ID[domain].get(facility.owner_id, None)
            if case_sharing_group is None:
                continue
            cati_user = case_sharing_group.metadata.get('cati_user', None)
            fida_user = case_sharing_group.metadata.get('fida_user', None)
            current_domain_index[facility.facility_id] = {
                "cati": cati_user,
                "fida": fida_user
            }
        facility_index[domain] = current_domain_index
    return facility_index
Пример #16
0
def indexed_facilities():
    facility_index = {}
    for domain in DOMAINS:
        current_domain_index = {}
        facilities = get_cases_in_domain(domain, type="facility")
        for facility in facilities:
            case_sharing_group = GROUPS_BY_ID[domain].get(facility.owner_id, None)
            if case_sharing_group is None:
                continue
            cati_user = case_sharing_group.metadata.get('cati_user', None)
            fida_user = case_sharing_group.metadata.get('fida_user', None)
            current_domain_index[facility.facility_id] = {
                "cati": cati_user, 
                "fida": fida_user
            }
        facility_index[domain] = current_domain_index
    return facility_index
Пример #17
0
 def testImportBasic(self):
     config = self._config(self.default_headers)
     file = MockExcelFile(header_columns=self.default_headers, num_rows=5)
     res = do_import(file, config, self.domain)
     self.assertEqual(5, res['created_count'])
     self.assertEqual(0, res['match_count'])
     self.assertFalse(res['errors'])
     self.assertEqual(1, res['num_chunks'])
     cases = list(get_cases_in_domain(self.domain))
     self.assertEqual(5, len(cases))
     properties_seen = set()
     for case in cases:
         self.assertEqual(self.couch_user._id, case.user_id)
         self.assertEqual(self.couch_user._id, case.owner_id)
         self.assertEqual(self.default_case_type, case.type)
         for prop in self.default_headers[1:]:
             self.assertTrue(prop in case.get_case_property(prop))
             self.assertFalse(case.get_case_property(prop) in properties_seen)
             properties_seen.add(case.get_case_property(prop))
Пример #18
0
    def test_parent_child(self):
        parent_id = uuid.uuid4().hex
        parent_type = 'exploder-parent-type'
        parent_block = CaseBlock(create=True,
                                 case_id=parent_id,
                                 user_id=self.user_id,
                                 owner_id=self.user_id,
                                 case_type=parent_type,
                                 version=V2).as_string()

        child_id = uuid.uuid4().hex
        child_block = CaseBlock(create=True,
                                case_id=child_id,
                                user_id=self.user_id,
                                owner_id=self.user_id,
                                case_type='exploder-child-type',
                                index={
                                    'parent': (parent_type, parent_id)
                                },
                                version=V2).as_string()

        submit_case_blocks([parent_block, child_block], self.domain.name)
        self.assertEqual(2, len(get_case_ids_in_domain(self.domain.name)))

        explode_cases(self.user_id, self.domain.name, 5)
        cases_back = list(get_cases_in_domain(self.domain.name))
        self.assertEqual(10, len(cases_back))
        parent_cases = {
            p._id: p
            for p in filter(lambda case: case.type == parent_type, cases_back)
        }
        self.assertEqual(5, len(parent_cases))
        child_cases = filter(lambda case: case.type == 'exploder-child-type',
                             cases_back)
        self.assertEqual(5, len(child_cases))
        child_indices = [
            child.indices[0].referenced_id for child in child_cases
        ]
        # make sure they're different
        self.assertEqual(len(child_cases), len(set(child_indices)))
        for child in child_cases:
            self.assertEqual(1, len(child.indices))
            self.assertTrue(child.indices[0].referenced_id in parent_cases)
Пример #19
0
 def testImportBasic(self):
     config = self._config(self.default_headers)
     file = MockExcelFile(header_columns=self.default_headers, num_rows=5)
     res = do_import(file, config, self.domain)
     self.assertEqual(5, res['created_count'])
     self.assertEqual(0, res['match_count'])
     self.assertFalse(res['errors'])
     self.assertEqual(1, res['num_chunks'])
     cases = list(get_cases_in_domain(self.domain))
     self.assertEqual(5, len(cases))
     properties_seen = set()
     for case in cases:
         self.assertEqual(self.couch_user._id, case.user_id)
         self.assertEqual(self.couch_user._id, case.owner_id)
         self.assertEqual(self.default_case_type, case.type)
         for prop in self.default_headers[1:]:
             self.assertTrue(prop in case.get_case_property(prop))
             self.assertFalse(
                 case.get_case_property(prop) in properties_seen)
             properties_seen.add(case.get_case_property(prop))
Пример #20
0
    def testExternalIdChunking(self):
        # bootstrap a stub case
        external_id = 'importer-test-external-id'

        headers = ['external_id', 'age', 'sex', 'location']
        config = self._config(headers, search_field='external_id')
        file = MockExcelFile(header_columns=headers, num_rows=3,
                             row_generator=id_match_generator(external_id))

        # the first one should create the case, and the remaining two should update it
        res = do_import(file, config, self.domain)
        self.assertEqual(1, res['created_count'])
        self.assertEqual(2, res['match_count'])
        self.assertFalse(res['errors'])
        self.assertEqual(2, res['num_chunks']) # the lookup causes an extra chunk

        # should just create the one case
        self.assertEqual(1, len(get_case_ids_in_domain(self.domain)))
        [case] = get_cases_in_domain(self.domain)
        self.assertEqual(external_id, case.external_id)
        for prop in self.default_headers[1:]:
            self.assertTrue(prop in case.get_case_property(prop))
Пример #21
0
    def testCaseIdMatching(self):
        # bootstrap a stub case
        case = CommCareCase(domain=self.domain, type=self.default_case_type)
        case.importer_test_prop = 'foo'
        case.save()
        self.assertEqual(1, len(get_case_ids_in_domain(self.domain)))

        config = self._config(self.default_headers)
        file = MockExcelFile(header_columns=self.default_headers, num_rows=3, row_generator=id_match_generator(case._id))
        res = do_import(file, config, self.domain)
        self.assertEqual(0, res['created_count'])
        self.assertEqual(3, res['match_count'])
        self.assertFalse(res['errors'])

        # shouldn't create any more cases, just the one
        self.assertEqual(1, len(get_case_ids_in_domain(self.domain)))
        [case] = get_cases_in_domain(self.domain)
        for prop in self.default_headers[1:]:
            self.assertTrue(prop in case.get_case_property(prop))

        # shouldn't touch existing properties
        self.assertEqual('foo', case.importer_test_prop)
Пример #22
0
    def testLocationOwner(self):
        # This is actually testing several different things, but I figure it's
        # worth it, as each of these tests takes a non-trivial amount of time.
        non_case_sharing = LocationType.objects.create(domain=self.domain,
                                                       name='lt1',
                                                       shares_cases=False)
        case_sharing = LocationType.objects.create(domain=self.domain,
                                                   name='lt2',
                                                   shares_cases=True)
        location = make_loc('loc-1', 'Loc 1', self.domain, case_sharing)
        make_loc('loc-2', 'Loc 2', self.domain, case_sharing)
        duplicate_loc = make_loc('loc-3', 'Loc 2', self.domain, case_sharing)
        improper_loc = make_loc('loc-4', 'Loc 4', self.domain,
                                non_case_sharing)

        res = self.import_mock_file([
            ['case_id', 'name', 'owner_id', 'owner_name'],
            ['', 'location-owner-id', location.group_id, ''],
            ['', 'location-owner-code', '', location.site_code],
            ['', 'location-owner-name', '', location.name],
            ['', 'duplicate-location-name', '', duplicate_loc.name],
            ['', 'non-case-owning-name', '', improper_loc.name],
        ])
        cases = {c.name: c for c in list(get_cases_in_domain(self.domain))}

        self.assertEqual(cases['location-owner-id'].owner_id,
                         location.group_id)
        self.assertEqual(cases['location-owner-code'].owner_id,
                         location.group_id)
        self.assertEqual(cases['location-owner-name'].owner_id,
                         location.group_id)

        error_message = ImportErrors.DuplicateLocationName
        self.assertIn(error_message, res['errors'])
        self.assertEqual(res['errors'][error_message]['rows'], [4])

        error_message = ImportErrors.InvalidOwnerId
        self.assertIn(error_message, res['errors'])
        self.assertEqual(res['errors'][error_message]['rows'], [5])
Пример #23
0
    def test_parent_child(self):
        parent_id = uuid.uuid4().hex
        parent_type = 'exploder-parent-type'
        parent_block = CaseBlock(
            create=True,
            case_id=parent_id,
            user_id=self.user_id,
            owner_id=self.user_id,
            case_type=parent_type,
            version=V2
        ).as_string()

        child_id = uuid.uuid4().hex
        child_block = CaseBlock(
            create=True,
            case_id=child_id,
            user_id=self.user_id,
            owner_id=self.user_id,
            case_type='exploder-child-type',
            index={'parent': (parent_type, parent_id)},
            version=V2
        ).as_string()

        submit_case_blocks([parent_block, child_block], self.domain.name)
        self.assertEqual(2, len(get_case_ids_in_domain(self.domain.name)))

        explode_cases(self.user_id, self.domain.name, 5)
        cases_back = list(get_cases_in_domain(self.domain.name))
        self.assertEqual(10, len(cases_back))
        parent_cases = {p._id: p for p in filter(lambda case: case.type == parent_type, cases_back)}
        self.assertEqual(5, len(parent_cases))
        child_cases = filter(lambda case: case.type == 'exploder-child-type', cases_back)
        self.assertEqual(5, len(child_cases))
        child_indices = [child.indices[0].referenced_id for child in child_cases]
        # make sure they're different
        self.assertEqual(len(child_cases), len(set(child_indices)))
        for child in child_cases:
            self.assertEqual(1, len(child.indices))
            self.assertTrue(child.indices[0].referenced_id in parent_cases)
    def handle(self, *args, **options):
        domain = 'care-bihar'

        # forward all cases that were last modified between these dates
        def should_forward_case(case):
            min_date = datetime(2013, 9, 10)
            max_date = datetime(2013, 11, 7)
            return (case.server_modified_on
                    and min_date < case.server_modified_on < max_date)

        prod_repeater = CaseRepeater.get('a478a5a3d8964338cb3124de77e3ec58')
        success_count = 0
        fail_count = 0
        for case in get_cases_in_domain(domain):
            try:
                if should_forward_case(case):
                    prod_repeater.register(case)
                    success_count += 1
            except Exception:
                fail_count += 1
                logging.exception('problem creating repeater stub for case %s' % case._id)

        print 'successfully forwarded %s cases. %s were not processed' % (success_count, fail_count)
Пример #25
0
    def testExternalIdChunking(self):
        # bootstrap a stub case
        external_id = 'importer-test-external-id'

        headers = ['external_id', 'age', 'sex', 'location']
        config = self._config(headers, search_field='external_id')
        file = MockExcelFile(header_columns=headers,
                             num_rows=3,
                             row_generator=id_match_generator(external_id))

        # the first one should create the case, and the remaining two should update it
        res = do_import(file, config, self.domain)
        self.assertEqual(1, res['created_count'])
        self.assertEqual(2, res['match_count'])
        self.assertFalse(res['errors'])
        self.assertEqual(2,
                         res['num_chunks'])  # the lookup causes an extra chunk

        # should just create the one case
        self.assertEqual(1, len(get_case_ids_in_domain(self.domain)))
        [case] = get_cases_in_domain(self.domain)
        self.assertEqual(external_id, case.external_id)
        for prop in self.default_headers[1:]:
            self.assertTrue(prop in case.get_case_property(prop))
Пример #26
0
    def rows(self):
        group_id = None
        if self.request.couch_user.is_commcare_user():
            group_ids = self.request.couch_user.get_group_ids()
            if len(group_ids) > 0:
                group_id = group_ids[0]

        data = {}

        for case in get_cases_in_domain(self.domain, type='participant'):
            if case.closed:
                continue

            # If a site coordinator is viewing the report, only show participants from that site (group)
            if group_id is None or group_id == case.owner_id:
                timezone = pytz.timezone(case.get_case_property("time_zone"))
                data[case._id] = {
                    "name": case.name,
                    "time_zone": timezone,
                    "dates": [None] * 14,
                }

        dates = self.get_past_two_weeks()
        date_strings = [json_format_date(date) for date in dates]

        start_date = dates[0] - timedelta(days=1)
        end_date = dates[-1] + timedelta(days=2)

        expected_callback_events = ExpectedCallback.by_domain(
            self.domain,
            start_date=datetime.combine(start_date, time(0, 0)),
            end_date=datetime.combine(end_date, time(0, 0))
        ).order_by('date')

        for event in expected_callback_events:
            if event.couch_recipient in data:
                timezone = data[event.couch_recipient]["time_zone"]
                event_date = (ServerTime(event.date).user_time(timezone)
                              .ui_string("%Y-%m-%d"))
                if event_date in date_strings:
                    data[event.couch_recipient]["dates"][date_strings.index(event_date)] = event.status

        result = []
        for case_id, data_dict in data.items():
            row = [
                self._fmt(data_dict["name"]),
                None,
                None,
                None,
            ]
            
            total_no_response = 0
            total_indicated = 0
            total_pending = 0
            
            for date_status in data_dict["dates"]:
                if date_status == CALLBACK_PENDING:
                    total_indicated += 1
                    total_pending += 1
                    row.append(self._fmt(_("pending")))
                elif date_status == CALLBACK_RECEIVED:
                    total_indicated += 1
                    row.append(self._fmt(_("OK")))
                elif date_status == CALLBACK_MISSED:
                    total_indicated += 1
                    total_no_response += 1
                    row.append(self._fmt_highlight(_("No Response")))
                else:
                    row.append(self._fmt(_("not indicated")))
            
            if total_no_response > 0:
                row[1] = self._fmt_highlight(total_no_response)
            else:
                row[1] = self._fmt(total_no_response)
            row[2] = self._fmt(total_indicated)
            row[3] = self._fmt(total_pending)
            
            result.append(row)
        
        return result
Пример #27
0
    def rows(self):
        group_id = None
        if self.request.couch_user.is_commcare_user():
            group_ids = self.request.couch_user.get_group_ids()
            if len(group_ids) > 0:
                group_id = group_ids[0]

        data = {}

        for case in get_cases_in_domain(self.domain, type='participant'):
            if case.closed:
                continue

            # If a site coordinator is viewing the report, only show participants from that site (group)
            if group_id is None or group_id == case.owner_id:
                timezone = pytz.timezone(case.get_case_property("time_zone"))
                data[case._id] = {
                    "name": case.name,
                    "time_zone": timezone,
                    "dates": [None] * 14,
                }

        dates = self.get_past_two_weeks()
        date_strings = [json_format_date(date) for date in dates]

        start_date = dates[0] - timedelta(days=1)
        end_date = dates[-1] + timedelta(days=2)

        expected_callback_events = ExpectedCallback.by_domain(
            self.domain,
            start_date=datetime.combine(start_date, time(0, 0)),
            end_date=datetime.combine(end_date, time(0, 0))).order_by('date')

        for event in expected_callback_events:
            if event.couch_recipient in data:
                timezone = data[event.couch_recipient]["time_zone"]
                event_date = (ServerTime(
                    event.date).user_time(timezone).ui_string("%Y-%m-%d"))
                if event_date in date_strings:
                    data[event.couch_recipient]["dates"][date_strings.index(
                        event_date)] = event.status

        result = []
        for case_id, data_dict in data.items():
            row = [
                self._fmt(data_dict["name"]),
                None,
                None,
                None,
            ]

            total_no_response = 0
            total_indicated = 0
            total_pending = 0

            for date_status in data_dict["dates"]:
                if date_status == CALLBACK_PENDING:
                    total_indicated += 1
                    total_pending += 1
                    row.append(self._fmt(_("pending")))
                elif date_status == CALLBACK_RECEIVED:
                    total_indicated += 1
                    row.append(self._fmt(_("OK")))
                elif date_status == CALLBACK_MISSED:
                    total_indicated += 1
                    total_no_response += 1
                    row.append(self._fmt_highlight(_("No Response")))
                else:
                    row.append(self._fmt(_("not indicated")))

            if total_no_response > 0:
                row[1] = self._fmt_highlight(total_no_response)
            else:
                row[1] = self._fmt(total_no_response)
            row[2] = self._fmt(total_indicated)
            row[3] = self._fmt(total_pending)

            result.append(row)

        return result
Пример #28
0
def iter_cases_to_modify():
    _domain = Domain.get_by_name(DOMAINS[0])
    if _domain is None:
        return
    time_zone = _domain.get_default_timezone()
    past_21_date = past_x_date(time_zone, 21)
    past_42_date = past_x_date(time_zone, 42)
    setup_indices()
    for domain in DOMAINS:
        for case in chain(get_cases_in_domain(domain, type=BIRTH_TYPE),
                          get_cases_in_domain(domain, type=CATI_FIDA_CHECK_TYPE)):
            if case.closed:
                continue
            if (
                not get_none_or_value(case, "owner_id") or
                not get_none_or_value(case, "date_admission") or
                not get_none_or_value(case, "facility_id")
            ):
                continue
            curr_assignment = get_none_or_value(case, "current_assignment")
            next_assignment = get_none_or_value(case, "next_assignment")
            facility_id = get_none_or_value(case, "facility_id")
            fida_group = get_group_id(domain, "fida", facility_id)

            # get cati_owner_username from current owner-group
            assigned_owner_group = get_none_or_value(case, "owner_id")
            if assigned_owner_group not in GROUPS_BY_ID[domain]:
                continue
            cati_owner_username = GROUPS_BY_ID[domain][assigned_owner_group].metadata.get('main_user', None)

            # Assignment Directly from Registration ##
            # Assign Cases to Call Center
            if (
                not curr_assignment and
                not next_assignment and
                past_21_date <= case.date_admission
            ):
                owner_id = get_group_id(domain, "cati", facility_id)
                if not owner_id:
                    continue
                owner_group = GROUPS_BY_ID[domain].get(owner_id, None)
                cati_name = owner_group.metadata.get('name', None) if owner_group else None
                update = {
                    "current_assignment": "cati",
                    "cati_name": cati_name
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": False,
                    "owner_id": owner_id,
                }, domain
            # Assign Cases Directly To Field
            elif (
                not curr_assignment and
                not next_assignment and
                past_42_date <= case.date_admission < past_21_date
            ):
                if not fida_group:
                    continue
                update = {
                    "current_assignment": "fida",
                    "cati_status": 'skipped',
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": False,
                    "owner_id": fida_group,
                }, domain
            # Assign Cases Directly to Lost to Follow Up
            elif (
                not curr_assignment and
                not next_assignment and
                case.date_admission < past_42_date
            ):
                update = {
                    "cati_status": 'skipped',
                    "last_assignment": '',
                    "closed_status": "timed_out_lost_to_follow_up",
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": True,
                }, domain

            ## Assignment from Call Center ##
            # Assign Cases to Field (manually by call center)
            elif (
                next_assignment == "fida" and
                past_42_date <= case.date_admission
            ):
                if not cati_owner_username or not fida_group:
                    continue
                update = {
                    "last_cati_user": cati_owner_username,
                    "current_assignment": "fida",
                    "next_assignment": '',
                    "cati_status": 'manually_assigned_to_field'
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": False,
                    "owner_id": fida_group,
                }, domain
            # Assign cases to field (automatically)
            elif (
                curr_assignment in ("cati", "cati_tl") and
                past_42_date <= case.date_admission < past_21_date
            ):
                if not cati_owner_username or not fida_group:
                    continue
                update = {
                    "last_cati_assignment": curr_assignment,
                    "last_cati_user": cati_owner_username,
                    "cati_status": 'timed_out',
                    "current_assignment": "fida",
                    "next_assignment": '',
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": False,
                    "owner_id": fida_group,
                }, domain
            # Assign Cases to Lost to Follow Up
            elif (
                curr_assignment in ("cati", "cati_tl") and
                case.date_admission < past_42_date
            ):
                if not get_owner_username(domain, curr_assignment, facility_id) or not cati_owner_username:
                    continue
                update = {
                    "last_cati_assignment": curr_assignment,
                    "last_cati_user": cati_owner_username,
                    "last_user": get_owner_username(domain, curr_assignment, facility_id),
                    "cati_status": 'timed_out',
                    "last_assignment": curr_assignment,
                    "current_assignment": '',
                    "closed_status": "timed_out_lost_to_follow_up",
                    "next_assignment": ''
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": True,
                }, domain

            ## Assignment from Field ##
            # Assign Cases to Lost to Follow Up
            elif (
                curr_assignment in ("fida", "fida_tl") and
                case.date_admission < past_42_date
            ):
                if not get_owner_username(domain, curr_assignment, facility_id):
                    continue
                update = {
                    "last_user": get_owner_username(domain, curr_assignment, facility_id),
                    "last_assignment": curr_assignment,
                    "current_assignment": '',
                    "closed_status": "timed_out_lost_to_follow_up",
                    "next_assignment": '',
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": True,
                }, domain
Пример #29
0
class ImporterTest(TestCase):
    def setUp(self):
        self.domain = create_domain("importer-test").name
        self.default_case_type = 'importer-test-casetype'
        self.default_headers = ['case_id', 'age', 'sex', 'location']

        self.couch_user = WebUser.create(None, "test", "foobar")
        self.couch_user.add_domain_membership(self.domain, is_admin=True)
        self.couch_user.save()
        delete_all_cases()

    def tearDown(self):
        self.couch_user.delete()

    def _config(self,
                col_names=None,
                search_column=None,
                case_type=None,
                search_field='case_id',
                named_columns=False,
                create_new_cases=True):
        col_names = col_names or self.default_headers
        case_type = case_type or self.default_case_type
        search_column = search_column or col_names[0]
        return ImporterConfig(
            couch_user_id=self.couch_user._id,
            case_type=case_type,
            excel_fields=col_names,
            case_fields=[''] * len(col_names),
            custom_fields=col_names,
            type_fields=['plain'] * len(col_names),
            search_column=search_column,
            search_field=search_field,
            named_columns=named_columns,
            create_new_cases=create_new_cases,
            key_column='',
            value_column='',
        )

    def testImportNone(self):
        res = do_import(None, self._config(), self.domain)
        self.assertEqual('EXPIRED', res['error'])
        self.assertEqual(0, len(get_case_ids_in_domain(self.domain)))

    def testImporterErrors(self):
        res = do_import(MockExcelFile(has_errors=True), self._config(),
                        self.domain)
        self.assertEqual('HAS_ERRORS', res['error'])
        self.assertEqual(0, len(get_case_ids_in_domain(self.domain)))

    def testImportBasic(self):
        config = self._config(self.default_headers)
        file = MockExcelFile(header_columns=self.default_headers, num_rows=5)
        res = do_import(file, config, self.domain)
        self.assertEqual(5, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertFalse(res['errors'])
        self.assertEqual(1, res['num_chunks'])
        cases = list(get_cases_in_domain(self.domain))
        self.assertEqual(5, len(cases))
        properties_seen = set()
        for case in cases:
            self.assertEqual(self.couch_user._id, case.user_id)
            self.assertEqual(self.couch_user._id, case.owner_id)
            self.assertEqual(self.default_case_type, case.type)
            for prop in self.default_headers[1:]:
                self.assertTrue(prop in case.get_case_property(prop))
                self.assertFalse(
                    case.get_case_property(prop) in properties_seen)
                properties_seen.add(case.get_case_property(prop))

    def testImportNamedColumns(self):
        config = self._config(self.default_headers, named_columns=True)
        file = MockExcelFile(header_columns=self.default_headers, num_rows=5)
        res = do_import(file, config, self.domain)
        # we create 1 less since we knock off the header column
        self.assertEqual(4, res['created_count'])
        self.assertEqual(4, len(get_case_ids_in_domain(self.domain)))

    def testImportTrailingWhitespace(self):
        cols = ['case_id', 'age', u'sex\xa0', 'location']
        config = self._config(cols, named_columns=True)
        file = MockExcelFile(header_columns=cols, num_rows=2)
        res = do_import(file, config, self.domain)
        # we create 1 less since we knock off the header column
        self.assertEqual(1, res['created_count'])
        case_ids = get_case_ids_in_domain(self.domain)
        self.assertEqual(1, len(case_ids))
        case = CommCareCase.get(case_ids[0])
        self.assertTrue(bool(
            case.sex))  # make sure the value also got properly set

    def testCaseIdMatching(self):
        # bootstrap a stub case
        case = CommCareCase(domain=self.domain, type=self.default_case_type)
        case.importer_test_prop = 'foo'
        case.save()
        self.assertEqual(1, len(get_case_ids_in_domain(self.domain)))

        config = self._config(self.default_headers)
        file = MockExcelFile(header_columns=self.default_headers,
                             num_rows=3,
                             row_generator=id_match_generator(case._id))
        res = do_import(file, config, self.domain)
        self.assertEqual(0, res['created_count'])
        self.assertEqual(3, res['match_count'])
        self.assertFalse(res['errors'])

        # shouldn't create any more cases, just the one
        self.assertEqual(1, len(get_case_ids_in_domain(self.domain)))
        [case] = get_cases_in_domain(self.domain)
        for prop in self.default_headers[1:]:
            self.assertTrue(prop in case.get_case_property(prop))

        # shouldn't touch existing properties
        self.assertEqual('foo', case.importer_test_prop)
Пример #30
0
    def test_create_fulfill_and_receive_requisition(self):
        amounts = [(p._id, 50.0 + float(i*10)) for i, p in enumerate(self.products)]

        # ----------------
        # Create a request
        # ----------------

        self.submit_xml_form(create_requisition_xml(amounts))
        req_cases = list(get_cases_in_domain(self.domain.name, type=const.REQUISITION_CASE_TYPE))
        self.assertEqual(1, len(req_cases))
        req = RequisitionCase.get(req_cases[0]._id)
        [index] = req.indices

        self.assertEqual(req.requisition_status, 'requested')
        self.assertEqual(const.SUPPLY_POINT_CASE_TYPE, index.referenced_type)
        self.assertEqual(self.sp._id, index.referenced_id)
        self.assertEqual('parent_id', index.identifier)
        # TODO: these types of tests probably belong elsewhere
        self.assertEqual(req.get_next_action().keyword, 'fulfill')
        self.assertEqual(req.get_location()._id, self.sp.location._id)
        self.assertEqual(len(RequisitionCase.open_for_location(
            self.domain.name,
            self.sp.location._id
        )), 1)
        self.assertEqual(
            get_notification_message(
                req.get_next_action(),
                [req]
            ),
            self.expected_notification_message(req, amounts)
        )

        for product, amt in amounts:
            self.check_stock_models(req, product, amt, 0, 'ct-requested')

        # ----------------
        # Mark it fulfilled
        # -----------------

        self.submit_xml_form(create_fulfillment_xml(req, amounts))

        req = RequisitionCase.get(req._id)

        self.assertEqual(req.requisition_status, 'fulfilled')
        self.assertEqual(req.get_next_action().keyword, 'rec')
        self.assertEqual(
            get_notification_message(
                req.get_next_action(),
                [req]
            ),
            self.expected_notification_message(req, amounts)
        )

        for product, amt in amounts:
            # we are expecting two separate blocks to have come with the same
            # values
            self.check_stock_models(req, product, amt, amt, 'stock')
            self.check_stock_models(req, product, amt, 0, 'ct-fulfilled')

        # ----------------
        # Mark it received
        # ----------------

        self.submit_xml_form(create_received_xml(req, amounts))

        req = RequisitionCase.get(req._id)

        self.assertEqual(req.requisition_status, 'received')
        self.assertIsNone(req.get_next_action())
        self.assertEqual(len(RequisitionCase.open_for_location(
            self.domain.name,
            self.sp.location._id
        )), 0)

        for product, amt in amounts:
            self.check_stock_models(req, product, 0, -amt, 'stock')
            self.check_stock_models(self.sp, product, amt, amt, 'stock')
Пример #31
0
def new_update_case_properties():
    _domain = Domain.get_by_name(DOMAINS[0])
    if _domain is None:
        return
    time_zone = _domain.get_default_timezone()
    past_21_date = past_x_date(time_zone, 21)
    past_42_date = past_x_date(time_zone, 42)
    setup_indices()
    for domain in DOMAINS:
        case_list = list(get_cases_in_domain(domain, type=BIRTH_TYPE))
        case_list = case_list + list(
            get_cases_in_domain(domain, type=CATI_FIDA_CHECK_TYPE))
        cases_to_modify = []
        for case in case_list:
            if case.closed:
                continue
            if not get_none_or_value(
                    case, "owner_id") or not get_none_or_value(
                        case, "date_admission") or not get_none_or_value(
                            case, "facility_id"):
                continue
            curr_assignment = get_none_or_value(case, "current_assignment")
            next_assignment = get_none_or_value(case, "next_assignment")
            facility_id = get_none_or_value(case, "facility_id")
            fida_group = get_group_id(domain, "fida", facility_id)

            # get cati_owner_username from current owner-group
            assigned_owner_group = get_none_or_value(case, "owner_id")
            if assigned_owner_group not in GROUPS_BY_ID[domain]:
                continue
            cati_owner_username = GROUPS_BY_ID[domain][
                assigned_owner_group].metadata.get('main_user', None)

            # Assignment Directly from Registration ##
            # Assign Cases to Call Center
            if case.date_admission >= past_21_date and (
                    not curr_assignment) and (not next_assignment):
                owner_id = get_group_id(domain, "cati", facility_id)
                if not owner_id:
                    continue
                owner_group = GROUPS_BY_ID[domain].get(owner_id, None)
                cati_name = owner_group.metadata.get(
                    'name', None) if owner_group else None
                update = {"current_assignment": "cati", "cati_name": cati_name}
                cases_to_modify.append({
                    "case_id": case._id,
                    "update": update,
                    "close": False,
                    "owner_id": owner_id,
                })
            # Assign Cases Directly To Field
            elif (case.date_admission >=
                  past_42_date) and (case.date_admission < past_21_date) and (
                      not curr_assignment) and (not next_assignment):
                if not fida_group:
                    continue
                update = {
                    "current_assignment": "fida",
                    "cati_status": 'skipped',
                }
                cases_to_modify.append({
                    "case_id": case._id,
                    "update": update,
                    "close": False,
                    "owner_id": fida_group,
                })
Пример #32
0
 def test_get_cases_in_domain(self):
     self.assert_doc_list_equal(
         get_cases_in_domain(self.domain),
         [case for case in self.cases if case.domain == self.domain]
     )
Пример #33
0
def new_update_case_properties():
    _domain = Domain.get_by_name(DOMAINS[0])
    if _domain is None:
        return
    time_zone = _domain.get_default_timezone()
    past_21_date = past_x_date(time_zone, 21)
    past_42_date = past_x_date(time_zone, 42)
    setup_indices()
    for domain in DOMAINS:
        case_list = list(get_cases_in_domain(domain, type=BIRTH_TYPE))
        case_list = case_list + list(get_cases_in_domain(domain, type=CATI_FIDA_CHECK_TYPE))
        cases_to_modify = []
        for case in case_list:
            if case.closed:
                continue
            if not get_none_or_value(case, "owner_id") or not get_none_or_value(case, "date_admission") or not get_none_or_value(case, "facility_id"):
                continue
            curr_assignment = get_none_or_value(case, "current_assignment")
            next_assignment = get_none_or_value(case, "next_assignment")
            facility_id = get_none_or_value(case, "facility_id")
            fida_group = get_group_id(domain, "fida", facility_id)

            # get cati_owner_username from current owner-group
            assigned_owner_group = get_none_or_value(case, "owner_id")
            if assigned_owner_group not in GROUPS_BY_ID[domain]:
                continue
            cati_owner_username = GROUPS_BY_ID[domain][assigned_owner_group].metadata.get('main_user', None)

            # Assignment Directly from Registration ##
            # Assign Cases to Call Center
            if case.date_admission >= past_21_date and (not curr_assignment) and (not next_assignment):
                owner_id = get_group_id(domain, "cati", facility_id)
                if not owner_id:
                    continue
                owner_group = GROUPS_BY_ID[domain].get(owner_id, None)
                cati_name = owner_group.metadata.get('name', None) if owner_group else None
                update = {
                    "current_assignment": "cati",
                    "cati_name": cati_name
                }
                cases_to_modify.append({
                    "case_id": case._id,
                    "update": update,
                    "close": False,
                    "owner_id": owner_id,
                })
            # Assign Cases Directly To Field
            elif (case.date_admission >= past_42_date) and (case.date_admission < past_21_date) and (not curr_assignment) and (not next_assignment):
                if not fida_group:
                    continue
                update = {
                    "current_assignment": "fida",
                    "cati_status": 'skipped',
                }
                cases_to_modify.append(
                    {
                        "case_id": case._id,
                        "update": update,
                        "close": False,
                        "owner_id": fida_group,
                    }
                )
            # Assign Cases Directly to Lost to Follow Up
            elif case.date_admission < past_42_date and (not curr_assignment) and (not next_assignment):
                update = {
                    "cati_status": 'skipped',
                    "last_assignment": '',
                    "closed_status": "timed_out_lost_to_follow_up",
                }
                cases_to_modify.append(
                    {
                        "case_id": case._id,
                        "update": update,
                        "close": True,
                    }
                )

            ## Assignment from Call Center ##
            # Assign Cases to Field (manually by call center)
            elif (case.date_admission >= past_42_date) and next_assignment == "fida":
                if not cati_owner_username or not fida_group:
                    continue
                update = {
                    "last_cati_user": cati_owner_username,
                    "current_assignment": "fida",
                    "next_assignment": '',
                    "cati_status": 'manually_assigned_to_field'
                }
                cases_to_modify.append(
                    {
                        "case_id": case._id,
                        "update": update,
                        "close": False,
                        "owner_id": fida_group,
                    }
                )
            # Assign cases to field (automatically)
            elif (case.date_admission >= past_42_date) and (case.date_admission < past_21_date) and (curr_assignment == "cati" or curr_assignment == "cati_tl"):
                if not cati_owner_username or not fida_group:
                    continue
                update = {
                    "last_cati_assignment": curr_assignment,
                    "last_cati_user": cati_owner_username,
                    "cati_status": 'timed_out',
                    "current_assignment": "fida",
                    "next_assignment": '',
                }
                cases_to_modify.append(
                    {
                        "case_id": case._id,
                        "update": update,
                        "close": False,
                        "owner_id": fida_group,
                    }
                )
            # Assign Cases to Lost to Follow Up
            elif case.date_admission < past_42_date and (curr_assignment == "cati" or curr_assignment == "cati_tl"):
                if not get_owner_username(domain, curr_assignment, facility_id) or not cati_owner_username:
                    continue
                update = {
                    "last_cati_assignment": curr_assignment,
                    "last_cati_user": cati_owner_username,
                    "last_user": get_owner_username(domain, curr_assignment, facility_id),
                    "cati_status": 'timed_out',
                    "last_assignment": curr_assignment,
                    "current_assignment": '',
                    "closed_status": "timed_out_lost_to_follow_up",
                    "next_assignment": ''
                }
                cases_to_modify.append(
                    {
                        "case_id": case._id,
                        "update": update,
                        "close": True,
                    }
                )

            ## Assignment from Field ##
            # Assign Cases to Lost to Follow Up
            elif case.date_admission < past_42_date and (curr_assignment == "fida" or curr_assignment == "fida_tl"):
                if not get_owner_username(domain, curr_assignment, facility_id):
                    continue
                update = {
                    "last_user": get_owner_username(domain, curr_assignment, facility_id),
                    "last_assignment": curr_assignment,
                    "current_assignment": '',
                    "closed_status": "timed_out_lost_to_follow_up",
                    "next_assignment": '',
                }
                cases_to_modify.append(
                    {
                        "case_id": case._id,
                        "update": update,
                        "close": True,
                    }
                )
        case_blocks = []
        for case in cases_to_modify:
            kwargs = {
                "create": False,
                "case_id": case["case_id"],
                "update": case["update"],
                "close": case["close"],
                "version": V2,
            }
            if case.get("owner_id", None):
                kwargs["owner_id"] = case["owner_id"]
            case_blocks.append(ElementTree.tostring(CaseBlock(**kwargs).as_xml()))
        submit_case_blocks(case_blocks, domain)
Пример #34
0
 def test_get_cases_in_domain__type(self):
     self.assert_doc_list_equal(
         get_cases_in_domain(self.domain, type='type1'),
         [case for case in self.cases
          if case.domain == self.domain and case.type == 'type1'],
     )
Пример #35
0
def iter_cases_to_modify():
    _domain = Domain.get_by_name(DOMAINS[0])
    if _domain is None:
        return
    time_zone = _domain.get_default_timezone()
    past_21_date = past_x_date(time_zone, 21)
    past_42_date = past_x_date(time_zone, 42)
    setup_indices()
    for domain in DOMAINS:
        for case in chain(
                get_cases_in_domain(domain, type=BIRTH_TYPE),
                get_cases_in_domain(domain, type=CATI_FIDA_CHECK_TYPE)):
            if case.closed:
                continue
            if (not get_none_or_value(case, "owner_id")
                    or not get_none_or_value(case, "date_admission")
                    or not get_none_or_value(case, "facility_id")):
                continue
            curr_assignment = get_none_or_value(case, "current_assignment")
            next_assignment = get_none_or_value(case, "next_assignment")
            facility_id = get_none_or_value(case, "facility_id")
            fida_group = get_group_id(domain, "fida", facility_id)

            # get cati_owner_username from current owner-group
            assigned_owner_group = get_none_or_value(case, "owner_id")
            if assigned_owner_group not in GROUPS_BY_ID[domain]:
                continue
            cati_owner_username = GROUPS_BY_ID[domain][
                assigned_owner_group].metadata.get('main_user', None)

            # Assignment Directly from Registration ##
            # Assign Cases to Call Center
            if (not curr_assignment and not next_assignment
                    and past_21_date <= case.date_admission):
                owner_id = get_group_id(domain, "cati", facility_id)
                if not owner_id:
                    continue
                owner_group = GROUPS_BY_ID[domain].get(owner_id, None)
                cati_name = owner_group.metadata.get(
                    'name', None) if owner_group else None
                update = {"current_assignment": "cati", "cati_name": cati_name}
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": False,
                    "owner_id": owner_id,
                }, domain
            # Assign Cases Directly To Field
            elif (not curr_assignment and not next_assignment
                  and past_42_date <= case.date_admission < past_21_date):
                if not fida_group:
                    continue
                update = {
                    "current_assignment": "fida",
                    "cati_status": 'skipped',
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": False,
                    "owner_id": fida_group,
                }, domain
            # Assign Cases Directly to Lost to Follow Up
            elif (not curr_assignment and not next_assignment
                  and case.date_admission < past_42_date):
                update = {
                    "cati_status": 'skipped',
                    "last_assignment": '',
                    "closed_status": "timed_out_lost_to_follow_up",
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": True,
                }, domain

            ## Assignment from Call Center ##
            # Assign Cases to Field (manually by call center)
            elif (next_assignment == "fida"
                  and past_42_date <= case.date_admission):
                if not cati_owner_username or not fida_group:
                    continue
                update = {
                    "last_cati_user": cati_owner_username,
                    "current_assignment": "fida",
                    "next_assignment": '',
                    "cati_status": 'manually_assigned_to_field'
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": False,
                    "owner_id": fida_group,
                }, domain
            # Assign cases to field (automatically)
            elif (curr_assignment in ("cati", "cati_tl", "cati-tl")
                  and past_42_date <= case.date_admission < past_21_date):
                if not cati_owner_username or not fida_group:
                    continue
                update = {
                    "last_cati_assignment": curr_assignment,
                    "last_cati_user": cati_owner_username,
                    "cati_status": 'timed_out',
                    "current_assignment": "fida",
                    "next_assignment": '',
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": False,
                    "owner_id": fida_group,
                }, domain
            # Assign Cases to Lost to Follow Up
            elif (curr_assignment in ("cati", "cati_tl", "cati-tl")
                  and case.date_admission < past_42_date):
                if not get_owner_username(
                        domain, curr_assignment,
                        facility_id) or not cati_owner_username:
                    continue
                update = {
                    "last_cati_assignment":
                    curr_assignment,
                    "last_cati_user":
                    cati_owner_username,
                    "last_user":
                    get_owner_username(domain, curr_assignment, facility_id),
                    "cati_status":
                    'timed_out',
                    "last_assignment":
                    curr_assignment,
                    "current_assignment":
                    '',
                    "closed_status":
                    "timed_out_lost_to_follow_up",
                    "next_assignment":
                    ''
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": True,
                }, domain

            ## Assignment from Field ##
            # Assign Cases to Lost to Follow Up
            elif (curr_assignment in ("fida", "fida_tl")
                  and case.date_admission < past_42_date):
                if not get_owner_username(domain, curr_assignment,
                                          facility_id):
                    continue
                update = {
                    "last_user":
                    get_owner_username(domain, curr_assignment, facility_id),
                    "last_assignment":
                    curr_assignment,
                    "current_assignment":
                    '',
                    "closed_status":
                    "timed_out_lost_to_follow_up",
                    "next_assignment":
                    '',
                }
                yield {
                    "case_id": case._id,
                    "update": update,
                    "close": True,
                }, domain
Пример #36
0
 def test_get_cases_in_domain(self):
     self.assert_doc_list_equal(
         get_cases_in_domain(self.domain),
         [case for case in self.cases if case.domain == self.domain])