def get_referral_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_REFERRAL, "create": True, "update": extra_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_deleted_index(self): hierarchy = self.test_normal_index() parent, child = hierarchy['case_list'] factory = CaseFactory() ref = CaseStructure() ref.case_id = "" # reset case_id to empty factory.create_or_update_case( CaseStructure(case_id=child.case_id, indices=[CaseIndex(ref, related_type='parent')], walk_related=False), ) # re-fetch case to clear memoized properties parent = CommCareCase.objects.get_case(parent.case_id, parent.domain) hierarchy = get_case_hierarchy(parent, {}) self.assertEqual(1, len(hierarchy['case_list'])) self.assertEqual(0, len(hierarchy['child_cases']))
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_walk_ids(self): case_id = uuid.uuid4().hex parent_case_id = uuid.uuid4().hex grandparent_case_id = uuid.uuid4().hex structure = CaseStructure( case_id=case_id, indices=[ CaseIndex( CaseStructure( case_id=parent_case_id, indices=[ CaseIndex( CaseStructure(case_id=grandparent_case_id)) ])) ]) self.assertEqual([case_id, parent_case_id, grandparent_case_id], list(structure.walk_ids()))
def test_delete_with_related(self): factory = CaseFactory() parent = factory.create_case() [child] = factory.create_or_update_case( CaseStructure(attrs={'create': True}, walk_related=False, indices=[ CaseIndex(CaseStructure(case_id=parent.case_id)) ]), ) # deleting the parent should not be allowed because the child still references it with self.assertRaises(CommCareCaseError): safe_hard_delete(parent) # deleting the child is ok safe_hard_delete(child) self.assertIsNotNone(self.casedb.get_case(parent.case_id, TEST_DOMAIN_NAME)) with self.assertRaises(CaseNotFound): self.casedb.get_case(child.case_id, TEST_DOMAIN_NAME)
def test_trigger_multiple_cases(self): """Submitting a form with noop case blocks was throwing an exception """ self.create_case_structure() self._create_99dots_registered_case() empty_case = CaseStructure(case_id=self.episode_id, ) person_case = CaseStructure(case_id=self.person_id, attrs={ 'case_type': 'person', 'update': { PRIMARY_PHONE_NUMBER: '9999999999' } }) self.factory.create_or_update_cases([empty_case, person_case]) self.assertEqual(1, len(self.repeat_records().all()))
def handle(self, domain, log_path, **options): commit = options['commit'] factory = CaseFactory(domain) logger.info("Starting {} migration on {} at {}".format( "real" if commit else "fake", domain, datetime.datetime.utcnow())) cases = (CaseSearchES().domain(domain).case_type("episode").scroll()) with open(log_path, "w") as f: for case in cases: case_props = { prop['key']: prop['value'] for prop in case['case_properties'] } treatment_status = None treatment_initiated = case_props.get('treatment_initiated') diagnosing_facility_id = case_props.get( 'diagnosing_facility_id') treatment_initiating_facility_id = case_props.get( 'treatment_initiating_facility_id') if treatment_initiated == 'yes_phi' and \ diagnosing_facility_id and treatment_initiating_facility_id and \ diagnosing_facility_id != treatment_initiating_facility_id: treatment_status = 'initiated_outside_facility' elif treatment_initiated == 'yes_phi' and \ diagnosing_facility_id and treatment_initiating_facility_id: treatment_status = 'initiated_first_line_treatment' elif treatment_initiated == 'yes_private': treatment_status = 'initiated_outside_rntcp' if treatment_status: case_id = case['_id'] f.write(case_id + "\n") logger.info(case_id) case_structure = CaseStructure( case_id=case_id, walk_related=False, attrs={ "create": False, "update": { "treatment_status": treatment_status, "updated_by_migration": "enikshay_2b_treatment_status_fix", }, }, ) if commit: try: factory.create_or_update_case(case_structure) except NikshayLocationNotFound: pass logger.info("Migration finished at {}".format( datetime.datetime.utcnow()))
def _update_case(self, case_id, case_properties): return self.create_case( CaseStructure( case_id=case_id, attrs={ "update": case_properties, } ) )
def test_delete_with_related(self): factory = CaseFactory() parent = factory.create_case() [child] = factory.create_or_update_case( CaseStructure(attrs={'create': True}, walk_related=False, relationships=[ CaseRelationship( CaseStructure(case_id=parent._id)) ]), ) # deleting the parent should not be allowed because the child still references it with self.assertRaises(CommCareCaseError): safe_hard_delete(parent) # deleting the child is ok safe_hard_delete(child) self.assertTrue(CommCareCase.get_db().doc_exist(parent._id)) self.assertFalse(CommCareCase.get_db().doc_exist(child._id))
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 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_form_extras(self): domain = uuid.uuid4().hex token_id = uuid.uuid4().hex factory = CaseFactory(domain=domain) [case] = factory.create_or_update_case( CaseStructure(attrs={'create': True}), form_extras={'last_sync_token': token_id}) form = FormAccessors(domain).get_form(case.xform_ids[0]) self.assertEqual(token_id, form.last_sync_token)
def _create_99dots_registered_case(self): dots_registered_case = CaseStructure( case_id=self.episode_id, attrs={ 'create': True, 'case_type': 'episode', "update": dict(dots_99_registered='true', ) }) self.create_case(dots_registered_case)
def test_form_extras(self): domain = uuid.uuid4().hex LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace='domain') token_id = uuid.uuid4().hex factory = CaseFactory(domain=domain) [case] = factory.create_or_update_case( CaseStructure(), form_extras={'last_sync_token': token_id}) form = FormAccessors(domain).get_form(case.xform_ids[0]) self.assertEqual(token_id, form.last_sync_token)
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 migrate_episode(self, episode, episodes): self.total_episodes += 1 latest_episode_id = self._get_last_episode_id(episode.indices, episodes) test_type = episode.get_case_property('test_confirming_diagnosis') props = { 'updated_by_migration': 'enikshay_2b_case_properties', 'is_active': 'yes' if episode.case_id == latest_episode_id and not episode.closed else 'no', 'dosage_display': episode.get_case_property('full_dosage'), 'dosage_summary': episode.get_case_property('full_dosage'), 'rft_general': 'diagnosis_dstb', 'diagnosis_test_type': test_type, 'diagnosis_test_type_label': TEST_TO_LABEL.get(test_type, ""), } treatment_status = episode.get_case_property('treatment_status') treatment_initiated = episode.get_case_property('treatment_initiated') diagnosing_facility_id = episode.get_case_property( 'diagnosing_facility_id') treatment_initiating_facility_id = episode.get_case_property( 'treatment_initiating_facility_id') if treatment_status == 'second_line_treatment': props['treatment_status'] = 'initiated_second_line_treatment' # skipping patients who don't have a diagnosing and treatment IDs (so we don't set the wrong status) elif treatment_initiated == 'yes_phi' and diagnosing_facility_id and treatment_initiating_facility_id \ and diagnosing_facility_id != treatment_initiating_facility_id: props['treatment_status'] = 'initiated_outside_facility' # skipping patients who don't have a diagnosing and treatment IDs (so we don't set the wrong status) elif treatment_initiated == 'yes_phi' and diagnosing_facility_id and treatment_initiating_facility_id: props['treatment_status'] = 'initiated_first_line_treatment' elif treatment_initiated == 'yes_private': props['treatment_status'] = 'initiated_outside_rntcp' if treatment_status and treatment_status != 'yes_phi' and treatment_status != 'yes_private': props['treatment_initiated'] = 'no' if not episode.get_case_property('date_of_diagnosis'): props['date_of_diagnosis'] = episode.get_case_property( 'date_reported') return CaseStructure( case_id=episode.case_id, walk_related=False, attrs={ "create": False, "update": props, }, )
def test_get_ush_custom_extension_chain(self): # test USH specific tree of where only extension(2) should be included # patient (host) # / \ # contact(id=1) extension(id=2) # / # extension(id=3) host = CaseStructure(case_id=self.host_id, attrs={'create': True, 'case_type': 'patient'}) contact_extension = CaseStructure( case_id=self.extension_ids[0], indices=[CaseIndex( related_structure=host, relationship="extension", )], attrs={'create': True, 'case_type': 'contact'} ) extensions_1 = CaseStructure( case_id=self.extension_ids[1], indices=[CaseIndex( related_structure=host, relationship="extension", )], attrs={'create': True} ) ext_of_contact = CaseStructure( case_id=self.extension_ids[2], indices=[CaseIndex( related_structure=contact_extension, relationship="extension", )], attrs={'create': True} ) created_cases = self.factory.create_or_update_cases([ext_of_contact]) self.factory.create_or_update_cases([extensions_1]) created_cases[-1].closed = True self.assertEqual( set(self.extension_ids), get_extensions_to_close(self.domain, [created_cases[-1]]) ) # contact and its extensions shouldn't be included in USH case self.assertEqual( {self.extension_ids[1]}, get_ush_extension_cases_to_close(self.domain, [created_cases[-1]]) )
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 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 test_footprint_with_extension_of_child(self): """ Extensions of children should be included """ parent = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.other_owner_id, 'create': True, 'close': True} ) child = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.owner_id, 'create': True}, indices=[CaseIndex(parent)] ) extension = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.other_owner_id, 'create': True}, indices=[CaseIndex(child, relationship=CASE_INDEX_EXTENSION)] ) self.factory.create_or_update_cases([parent, child, extension]) footprint_info = get_case_footprint_info(self.domain, self.owner_id) self.assertEqual(footprint_info.all_ids, set([extension.case_id, parent.case_id, child.case_id]))
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_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_long_extension_chain_with_branches(self): """An extension chain of unowned extensions that ends at an owned case is dirty""" owner_1 = uuid.uuid4().hex self._owner_cleanliness_for_id(owner_1) owner_2 = uuid.uuid4().hex self._owner_cleanliness_for_id(owner_2) host = CaseStructure(case_id=self.sample_case.case_id, attrs={'create': False}) host_2 = CaseStructure( case_id="host_with_other_owner", attrs={'owner_id': owner_1} ) extension_1 = CaseStructure( case_id="extension1", attrs={'owner_id': UNOWNED_EXTENSION_OWNER_ID}, indices=[ CaseIndex( host, relationship=CASE_INDEX_EXTENSION, identifier="host_1", ), CaseIndex( host_2, relationship=CASE_INDEX_EXTENSION, identifier="host_2", ) ] ) extension_2 = CaseStructure( case_id="extension2", attrs={'owner_id': owner_2}, indices=[ CaseIndex( extension_1, relationship=CASE_INDEX_EXTENSION, ) ] ) self.factory.create_or_update_case(extension_2) self.assert_owner_dirty() self.assertFalse(self._owner_cleanliness_for_id(owner_1).is_clean) self.assertFalse(self._owner_cleanliness_for_id(owner_2).is_clean) self.assertEqual(host.case_id, self.owner_cleanliness.hint) self._verify_set_cleanliness_flags()
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_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 _update_person(self, case_properties): return self.create_case( CaseStructure( case_id=self.person_id, attrs={ "case_type": "person", "update": case_properties, } ) )
def test_form_extras_override_defaults(self): domain = uuid.uuid4().hex LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace='domain') token_id = uuid.uuid4().hex factory = CaseFactory(domain=domain, form_extras={'last_sync_token': token_id}) [case] = factory.create_or_update_case( CaseStructure(), form_extras={'last_sync_token': 'differenttoken'}) form = XFormInstance.get(case.xform_ids[0]) self.assertEqual('differenttoken', form.last_sync_token)
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 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_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']))