def test_legacy_support_toggle(self): restore_config = RestoreConfig(self.project, restore_user=self.user) factory = CaseFactory(domain=self.project.name, case_defaults={'owner_id': self.user_id}) # create a parent and child case (with index) from one user parent_id, child_id = [uuid.uuid4().hex for i in range(2)] factory.create_or_update_cases([ CaseStructure( case_id=child_id, attrs={'create': True}, indices=[CaseIndex( CaseStructure(case_id=parent_id, attrs={'create': True}), relationship='child', related_type='parent', )], ) ]) restore_payload = restore_config.get_payload().as_string().decode('utf-8') self.assertTrue(child_id in restore_payload) self.assertTrue(parent_id in restore_payload) sync_log = deprecated_synclog_from_restore_payload(restore_payload) self.assertEqual(SimplifiedSyncLog, type(sync_log)) # make both cases irrelevant by changing the owner ids factory.create_or_update_cases([ CaseStructure(case_id=parent_id, attrs={'owner_id': 'different'}), CaseStructure(case_id=child_id, attrs={'owner_id': 'different'}), ], form_extras={'last_sync_token': sync_log._id}) # doing it again should fail since they are no longer relevant # todo: add this back in when we add the assertion back. see SimplifiedSyncLog.prune_case # with self.assertRaises(SimplifiedSyncAssertionError): # factory.create_or_update_cases([ # CaseStructure(case_id=child_id, attrs={'owner_id': 'different'}), # CaseStructure(case_id=parent_id, attrs={'owner_id': 'different'}), # ], form_extras={'last_sync_token': sync_log._id}) # enabling the toggle should prevent the failure the second time # though we also need to hackily set the request object in the threadlocals LEGACY_SYNC_SUPPORT.set(self.domain, True, namespace='domain') request = JsonObject(domain=self.domain, path='testsubmit') set_request(request) factory.create_or_update_cases([ CaseStructure(case_id=child_id, attrs={'owner_id': 'different'}), CaseStructure(case_id=parent_id, attrs={'owner_id': 'different'}), ], form_extras={'last_sync_token': sync_log._id})
def set_parent_case(domain, child_case, parent_case): """ Creates a parent-child relationship between child_case and parent_case. """ from casexml.apps.case.mock import CaseFactory, CaseStructure, CaseIndex from casexml.apps.case.models import INDEX_RELATIONSHIP_CHILD from corehq.form_processor.abstract_models import DEFAULT_PARENT_IDENTIFIER parent = CaseStructure(case_id=parent_case.case_id) CaseFactory(domain).create_or_update_case( CaseStructure( case_id=child_case.case_id, indices=[ CaseIndex(related_structure=parent, identifier=DEFAULT_PARENT_IDENTIFIER, relationship=INDEX_RELATIONSHIP_CHILD) ], ))
def test_normal_index(self): factory = CaseFactory() parent_id = uuid.uuid4().hex [cp] = factory.create_or_update_case( CaseStructure(case_id=parent_id, attrs={'case_type': 'parent', 'create': True}) ) child_id = uuid.uuid4().hex factory.create_or_update_case(CaseStructure( case_id=child_id, attrs={'case_type': 'child', 'create': True}, indices=[CaseIndex(CaseStructure(case_id=parent_id), related_type='parent')], walk_related=False )) hierarchy = get_case_hierarchy(cp, {}) self.assertEqual(2, len(hierarchy['case_list'])) self.assertEqual(1, len(hierarchy['child_cases']))
def get_trail_case_structure(case_id, indexed_occurrence_id, extra_update=None): extra_update = extra_update or {} return CaseStructure( case_id=case_id, attrs={ "case_type": CASE_TYPE_TRAIL, "create": True, "update": extra_update, }, # Prior to 2017-08-01, the parent is a person or referral case indices=[CaseIndex( CaseStructure(case_id=indexed_occurrence_id, attrs={"create": False}), identifier='parent', relationship=CASE_INDEX_CHILD, related_type='occurrence', )], walk_related=False, )
def lab_referral(self): return CaseStructure( case_id=self.lab_referral_id, attrs={ 'create': True, 'case_type': 'lab_referral', 'owner_id': self.dmc.get_id, "update": {} }, indices=[ CaseIndex( self.test, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=self.test.attrs['case_type'], ) ], )
def test_update_cases(self): builder1 = (IntentCaseBuilder(self.registry_slug).target_case( self.target_domain, self.target_case_id_1).case_properties(new_prop="new_val_case1")) builder2 = (IntentCaseBuilder(self.registry_slug).target_case( self.target_domain, self.target_case_id_2).case_properties(new_prop="new_val_case2")) factory = CaseFactory(self.domain) host = CaseStructure(attrs={ "create": True, "case_type": "registry_case_update", "update": builder1.props }, ) extension = CaseStructure( attrs={ "create": True, "case_type": "registry_case_update", "update": builder2.props }, indices=[CaseIndex( host, relationship=CASE_INDEX_EXTENSION, )]) cases = factory.create_or_update_case(extension, user_id=self.mobile_user.get_id) repeat_records = self.repeat_records(self.domain).all() self.assertEqual(len(repeat_records), 1) payload = repeat_records[0].get_payload() host_case = cases[1] form = DataRegistryUpdateForm(payload, host_case) form.assert_case_updates({ self.target_case_id_1: { "new_prop": "new_val_case1" }, self.target_case_id_2: { "new_prop": "new_val_case2" } }) url = self.repeater.get_url(repeat_records[0]) self.assertEqual(url, f"case-repeater-url/{self.target_domain}/") # check that the synchronous attempt of the repeat record happened self.assertEqual(1, len(repeat_records[0].attempts))
def get_episode_case_structure(case_id, indexed_occurrence_case, extra_update=None): extra_update = extra_update or {} update = { 'date_of_diagnosis': '2014-09-09', 'default_adherence_confidence': 'high', 'disease_classification': 'extra_pulmonary', 'episode_type': 'confirmed_tb', 'hiv_status': 'reactive', 'name': 'Episode #1', 'occupation': 'engineer', 'opened_on': datetime(1989, 6, 11, 0, 0), 'patient_type_choice': 'treatment_after_lfu', 'person_name': u'Peregrine เՇร ค Շгคק', 'site_choice': 'pleural_effusion', 'treatment_supporter_designation': 'ngo_volunteer', 'treatment_initiated': TREATMENT_INITIATED_IN_PHI, TREATMENT_START_DATE: "2015-03-03", TREATMENT_SUPPORTER_FIRST_NAME: u"𝔊𝔞𝔫𝔡𝔞𝔩𝔣", TREATMENT_SUPPORTER_LAST_NAME: u"𝔗𝔥𝔢 𝔊𝔯𝔢𝔶", MERM_ID: "123456789", 'treatment_initiation_status': 'F', 'dst_status': 'pending', 'basis_of_diagnosis': 'clinical_other', } update.update(extra_update) return CaseStructure( case_id=case_id, attrs={ 'create': True, 'case_type': 'episode', "update": update }, indices=[ CaseIndex( indexed_occurrence_case, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=indexed_occurrence_case.attrs['case_type'], ) ], )
def test_sql_dump_load_case(self): expected_object_counts = Counter({ XFormInstance: 2, BlobMeta: 2, CommCareCase: 2, CaseTransaction: 3, CommCareCaseIndex: 1 }) pre_cases = self.factory.create_or_update_case( CaseStructure(attrs={ 'case_name': 'child', 'update': { 'age': 3, 'diabetic': False }, 'create': True }, indices=[ CaseIndex( CaseStructure( attrs={ 'case_name': 'parent', 'update': { 'age': 42 }, 'create': True })), ])) pre_cases[0] = self.factory.create_or_update_case( CaseStructure(case_id=pre_cases[0].case_id, attrs={ 'external_id': 'billie jean', 'update': { 'name': 'Billie Jean' } }))[0] self._dump_and_load(expected_object_counts) case_ids = CommCareCase.objects.get_case_ids_in_domain( self.domain_name) self.assertEqual(set(case_ids), set(case.case_id for case in pre_cases))
def migrate_referral(self, referral, occurrence): self.total_referrals += 1 prop = referral.get_case_property props = { 'updated_by_migration': 'enikshay_2b_case_properties', 'referral_initiated_date': (prop('referral_date') or prop('date_of_referral')), 'referred_to_name': prop('referred_to_location_name'), 'referred_by_name': prop('referred_by'), 'referral_rejection_reason_other_detail': prop('reason_for_refusal_other_detail'), 'referral_rejection_reason': prop('reason_for_refusal'), 'referral_closed_date': prop('acceptance_refusal_date'), 'accepted_by_name': prop('phi'), } if occurrence: index_kwargs = { 'indices': [ CaseIndex( occurrence, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=CASE_TYPE_OCCURRENCE, ) ] } else: index_kwargs = {} return CaseStructure(case_id=referral.case_id, walk_related=False, attrs={ "create": False, "update": props, }, **index_kwargs)
def test_returns_simple_extension(self): host = CaseStructure(case_id=uuid.uuid4().hex, attrs={'owner_id': self.owner_id}) extension = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.other_owner_id}, indices=[CaseIndex(host, relationship=CASE_INDEX_EXTENSION)]) all_ids = set([host.case_id, extension.case_id]) self.factory.create_or_update_cases([host, extension]) self.assertEqual( all_ids, get_dependent_case_info(self.domain, [host.case_id]).all_ids) self.assertEqual( all_ids, get_dependent_case_info(self.domain, [extension.case_id]).all_ids) self.assertEqual( set([extension.case_id]), get_dependent_case_info(self.domain, [host.case_id]).extension_ids)
def test_recursive_indexes(self): factory = CaseFactory() [case] = factory.create_or_update_case( CaseStructure(case_id='infinite-recursion', attrs={ 'case_type': 'bug', 'create': True }, indices=[ CaseIndex(CaseStructure( case_id='infinite-recursion', attrs={'create': True}), related_type='bug') ], walk_related=False)) # this call used to fail with infinite recursion hierarchy = get_case_hierarchy(case, {}) self.assertEqual(1, len(hierarchy['case_list']))
def test_cross_domain_on_submission(self): """create a form that makes a dirty owner with the same ID but in a different domain make sure the original owner stays clean""" new_domain = uuid.uuid4().hex # initialize the new cleanliness flag OwnershipCleanlinessFlag.objects.create(domain=new_domain, owner_id=self.owner_id, is_clean=True) self.factory.domain = new_domain self.factory.create_or_update_case( CaseStructure( indices=[ CaseIndex(CaseStructure(attrs={'owner_id': uuid.uuid4().hex})) ] ) ) self.assert_owner_clean() self.assertEqual( False, OwnershipCleanlinessFlag.objects.get(owner_id=self.owner_id, domain=new_domain).is_clean, )
def test_hint_invalidation_extensions(self): other_owner_id = uuid.uuid4().hex [extension, host] = self.factory.create_or_update_case( CaseStructure( case_id='extension', attrs={'owner_id': other_owner_id}, indices=[ CaseIndex( CaseStructure(case_id="host"), relationship=CASE_INDEX_EXTENSION ) ] ) ) self.assert_owner_dirty() self.assertTrue(hint_still_valid(self.domain, self.owner_cleanliness.hint)) self._set_owner(extension.case_id, UNOWNED_EXTENSION_OWNER_ID) self.assertFalse(hint_still_valid(self.domain, self.owner_cleanliness.hint))
def test_simple_extension_returned(self): """ Should return extension if it exists """ host_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id, attrs={'create': True}) self.factory.create_or_update_case( CaseStructure( case_id=extension_id, indices=[CaseIndex(host, relationship=CASE_INDEX_EXTENSION)], attrs={'create': True})) returned_cases = CommCareCaseIndex.objects.get_extension_case_ids( self.domain, [host_id]) self.assertItemsEqual(returned_cases, [extension_id]) # exclude_for_case_type should exclude the result self.assertEqual( CommCareCaseIndex.objects.get_extension_case_ids( self.domain, [host_id], exclude_for_case_type=CaseIndex.DEFAULT_RELATED_CASE_TYPE), [])
def test_owned_extension(self): """Extension owned by another owner should be dirty""" other_owner_id = uuid.uuid4().hex self._owner_cleanliness_for_id(other_owner_id) [extension, host] = self.factory.create_or_update_case( CaseStructure(case_id='extension', attrs={'owner_id': other_owner_id}, indices=[ CaseIndex(CaseStructure(case_id="host"), relationship=CASE_INDEX_EXTENSION) ])) self.assert_owner_dirty() self.assertFalse( self._owner_cleanliness_for_id(other_owner_id).is_clean) self.assertEqual(host.case_id, self.owner_cleanliness.hint) self.assertEqual(extension.case_id, self._owner_cleanliness_for_id(other_owner_id).hint) self._verify_set_cleanliness_flags(self.owner_id) self._verify_set_cleanliness_flags(other_owner_id)
def get_test_case_structure(self, labtest, occurrence_structure): kwargs = { 'attrs': { 'case_type': TEST_CASE_TYPE, 'close': False, 'create': True, 'owner_id': '-', 'update': { 'migration_created_case': 'true', } }, 'indices': [CaseIndex( occurrence_structure, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=OCCURRENCE_CASE_TYPE, )], } return CaseStructure(**kwargs)
def test_extension_index(self): factory = CaseFactory() [case] = factory.create_or_update_case( CaseStructure(case_id="standard_case", attrs={'case_type': "standard_type"})) factory.create_or_update_case( CaseStructure(case_id="extension_case", attrs={'case_type': "extension_type"}, indices=[ CaseIndex(CaseStructure(case_id="standard_case"), related_type='standard_type', relationship=CASE_INDEX_EXTENSION) ], walk_related=False)) hierarchy = get_case_hierarchy(case, {}) self.assertEqual(2, len(hierarchy['case_list'])) self.assertEqual(1, len(hierarchy['child_cases']))
def set_up_cases(factory, with_dhis2_id=True): child_id = str(uuid4()) parent_id = str(uuid4()) child, parent = factory.create_or_update_case( CaseStructure( case_id=child_id, attrs={ 'create': True, 'case_type': 'child', 'case_name': 'Johnny APPLESEED', 'owner_id': 'b0b', 'external_id': 'johnny12345' if with_dhis2_id else '', 'update': { 'first_name': 'Johnny', 'last_name': 'Appleseed', 'date_of_birth': '2021-08-27', 'dhis2_org_unit_id': 'abcdef12345', }, }, indices=[CaseIndex( CaseStructure( case_id=parent_id, attrs={ 'create': True, 'case_type': 'mother', 'case_name': 'Alice APPLESEED', 'owner_id': 'b0b', 'external_id': 'alice123456' if with_dhis2_id else '', 'update': { 'first_name': 'Alice', 'last_name': 'Appleseed', 'dhis2_org_unit_id': 'abcdef12345', }, }, ), relationship='child', related_type='mother', identifier='parent', )], ) ) return child, parent
def get_occurrence_case_structure(self, person_structure): """ This gets the occurrence case structure with a nested person case structure. """ kwargs = { 'attrs': { 'case_type': OCCURRENCE_CASE_TYPE, 'owner_id': '-', 'update': { 'current_episode_type': 'confirmed_tb', 'ihv_date': self.patient_detail.ihv_date, 'initial_home_visit_status': self.patient_detail.initial_home_visit_status, 'name': 'Occurrence #1', 'occurrence_episode_count': 1, 'occurrence_id': get_human_friendly_id(), 'migration_created_case': 'true', 'migration_created_from_record': self.patient_detail.PregId, }, }, 'indices': [ CaseIndex( person_structure, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=PERSON_CASE_TYPE, ) ], } if self._outcome: if self._outcome.is_treatment_ended: kwargs['attrs']['close'] = True if self.existing_occurrence_case: kwargs['case_id'] = self.existing_occurrence_case.case_id kwargs['attrs']['create'] = False else: kwargs['attrs']['create'] = True return CaseStructure(**kwargs)
def set_parent_case(domain, child_case, parent_case, relationship='child', identifier='parent'): """ Creates a parent-child relationship between child_case and parent_case. """ from casexml.apps.case.mock import CaseFactory, CaseStructure, CaseIndex parent = CaseStructure(case_id=parent_case.case_id) CaseFactory(domain).create_or_update_case( CaseStructure( case_id=child_case.case_id, indices=[ CaseIndex(related_structure=parent, identifier=identifier, relationship=relationship) ], ))
def test_full_ancestry(self): """get_case_hierarchy should return the full parentage tree for any case """ factory = CaseFactory('baggins-of-hobbiton') bagginses = ['balbo', 'mungo', 'bungo', 'bilbo'] cases = {} for level, baggins in enumerate(bagginses): cases[baggins] = factory.create_or_update_case( CaseStructure( case_id=baggins, attrs={ 'case_type': 'baggins', 'update': {'name': baggins}, 'create': True}, indices=[CaseIndex(CaseStructure(case_id=bagginses[level - 1]))] if level != 0 else None, walk_related=False, ) )[0] hierarchy = get_case_hierarchy(cases['bungo'], {}) self.assertEqual(4, len(hierarchy['case_list']))
def _get_drtb_hiv_referral_structure(self, episode): return CaseStructure( case_id=episode.case_id + '-drtb_hiv_referral', attrs={ "case_type": CASE_TYPE_DRTB_HIV_REFERRAL, "owner_id": "drtb_hiv_referral_owner", "create": True, "update": {}, }, indices=[ CaseIndex( CaseStructure(case_id=episode.case_id, attrs={"create": False}), identifier='host', relationship=CASE_INDEX_EXTENSION, related_type='episode', ) ], walk_related=False, )
def _case_structure(name, parent, case_type): if parent: indices = [CaseIndex( parent, identifier='parent', relationship=CASE_INDEX_CHILD, related_type=parent.attrs['case_type'], )] else: indices = [] return CaseStructure( case_id=uuid.uuid4().hex, attrs={ "case_type": case_type, "create": True, "update": {"name": name}, }, indices=indices, walk_related=True, )
def get_referral_case_structure(case_id, indexed_person_id, extra_update=None): extra_update = extra_update or {} return CaseStructure( case_id=case_id, attrs={ "case_type": CASE_TYPE_REFERRAL, "create": True, "update": extra_update }, indices=[ CaseIndex( CaseStructure(case_id=indexed_person_id, attrs={"create": False}), identifier='host', relationship=CASE_INDEX_EXTENSION, related_type='episode', ) ], walk_related=False, )
def create_adherence_cases(self, adherence_points, adherence_source): return self.case_factory.create_or_update_cases([ CaseStructure( case_id=uuid.uuid4().hex, attrs={ "case_type": self.ADHERENCE_CASE_TYPE, "owner_id": UNOWNED_EXTENSION_OWNER_ID, "create": True, "update": self._get_adherence_case_properties(adherence_point, adherence_source), }, indices=[CaseIndex( CaseStructure(case_id=self._episode_case.case_id, attrs={"create": False}), identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=self._episode_case.type, )], walk_related=False, ) for adherence_point in adherence_points ])
def test_sql_dump_load_case(self): expected_object_counts = Counter({ XFormInstanceSQL: 2, XFormAttachmentSQL: 2, CommCareCaseSQL: 2, CaseTransaction: 3, CommCareCaseIndexSQL: 1 }) register_cleanup(self, list(expected_object_counts), self.domain_name) pre_cases = self.factory.create_or_update_case( CaseStructure(attrs={ 'case_name': 'child', 'update': { 'age': 3, 'diabetic': False } }, indices=[ CaseIndex( CaseStructure(attrs={ 'case_name': 'parent', 'update': { 'age': 42 } })), ])) pre_cases[0] = self.factory.create_or_update_case( CaseStructure(case_id=pre_cases[0].case_id, attrs={ 'external_id': 'billie jean', 'update': { 'name': 'Billie Jean' } }))[0] self._dump_and_load(expected_object_counts) case_ids = self.case_accessors.get_case_ids_in_domain() self.assertEqual(set(case_ids), set(case.case_id for case in pre_cases))
def open_secondary_owners(self, drtb_hiv, person, occurrences): if not occurrences: return None self.total_secondary_owners += 1 occurrence = max((case.opened_on, case) for case in occurrences)[1] index_kwargs = { 'indices': [ CaseIndex( occurrence, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=CASE_TYPE_OCCURRENCE, ) ] } location = self.locations.get(person.owner_id) props = { 'updated_by_migration': 'enikshay_2b_case_properties', 'secondary_owner_type': 'drtb-hiv', 'secondary_owner_name': location.name if location else "", } return CaseStructure(case_id=uuid.uuid4().hex, walk_related=False, attrs={ 'create': True, 'case_type': CASE_TYPE_SECONDARY_OWNER, 'owner_id': drtb_hiv.owner_id, 'case_name': person.get_case_property('person_id') + "-drtb-hiv", 'update': props, }, **index_kwargs)
def test_parent_child(self): self.user.loadtest_factor = 3 self.user.save() child, parent = self.factory.create_or_update_case( CaseStructure(attrs={ 'case_name': 'parent', 'create': True }, indices=[ CaseIndex( CaseStructure(attrs={ 'case_name': 'child', 'create': True })), ])) restore_config = RestoreConfig( project=self.domain, restore_user=self.user.to_ota_restore_user(), params=RestoreParams(version=V2)) payload_string = restore_config.get_payload().as_string() caseblocks = extract_caseblocks_from_xml(payload_string) self.assertEqual(6, len(caseblocks)) self.assertEqual( 1, len( filter(lambda cb: cb.get_case_id() == child.case_id, caseblocks))) self.assertEqual( 1, len( filter(lambda cb: cb.get_case_id() == parent.case_id, caseblocks))) self.assertEqual( 3, len(filter(lambda cb: child.name in cb.get_case_name(), caseblocks))) self.assertEqual( 3, len( filter(lambda cb: parent.name in cb.get_case_name(), caseblocks)))
def get_test_case_structure(case_id, indexed_occurrence_id, extra_update=None): extra_update = extra_update or {} update = dict( date_reported=datetime(2016, 8, 6).date(), ) update.update(extra_update) return CaseStructure( case_id=case_id, attrs={ "case_type": "test", "create": True, "update": update }, indices=[CaseIndex( CaseStructure(case_id=indexed_occurrence_id, attrs={"create": False}), identifier='host', relationship=CASE_INDEX_EXTENSION, related_type='occurrence', )], walk_related=False, )
def test_footprint_with_parent(self): """ should return open cases with parents """ parent = CaseStructure(case_id=uuid.uuid4().hex, attrs={ 'owner_id': self.other_owner_id, 'close': True, 'create': True }) child = CaseStructure(case_id=uuid.uuid4().hex, attrs={ 'owner_id': self.owner_id, 'create': True }, indices=[CaseIndex(parent)]) self.factory.create_or_update_cases([parent, child]) footprint_info = get_case_footprint_info(self.domain, self.owner_id) self.assertEqual(footprint_info.all_ids, set([child.case_id, parent.case_id])) self.assertEqual(footprint_info.base_ids, set([child.case_id]))