def setUp(self): super(GetChildCasesExpressionTest, self).setUp() self.domain = uuid.uuid4().hex factory = CaseFactory(domain=self.domain) self.test_case_id = uuid.uuid4().hex parent_case = CaseStructure( case_id='p-' + self.test_case_id, attrs={ 'case_type': 'parent_case', 'create': True, 'date_opened': datetime(2015, 1, 10), 'date_modified': datetime(2015, 3, 10), }, ) test_case = CaseStructure( case_id=self.test_case_id, attrs={ 'case_type': 'test', 'create': True, 'date_opened': datetime(2015, 1, 10), 'date_modified': datetime(2015, 3, 10), }, indices=[CaseIndex( parent_case, identifier='parent', relationship=CASE_INDEX_CHILD, related_type=parent_case.attrs['case_type'], )], ) child_case_1 = CaseStructure( case_id='c1-' + self.test_case_id, attrs={ 'case_type': 'child_1', 'create': True, 'date_opened': datetime(2015, 1, 10), 'date_modified': datetime(2015, 3, 10), }, indices=[CaseIndex( test_case, identifier='parent', relationship=CASE_INDEX_CHILD, related_type=test_case.attrs['case_type'], )], ) child_case_2 = CaseStructure( case_id='c2-' + self.test_case_id, attrs={ 'case_type': 'child_2', 'create': True, 'date_opened': datetime(2015, 1, 10), 'date_modified': datetime(2015, 3, 10), }, indices=[CaseIndex( test_case, identifier='parent', relationship=CASE_INDEX_CHILD, related_type=test_case.attrs['case_type'], )], ) factory.create_or_update_cases([parent_case, test_case, child_case_1, child_case_2])
def handle(self, domain, **options): base_query = PatientDetail.objects.all() start = options['start'] limit = options['limit'] chunk_size = options['chunk_size'] if limit is not None: patient_details = base_query[start:start + limit] else: patient_details = base_query[start:] total = patient_details.count() counter = 0 num_succeeded = 0 num_failed = 0 logger.info('Starting migration of %d patient cases on domain %s.' % (total, domain)) nikshay_codes_to_location = get_nikshay_codes_to_location(domain) factory = CaseFactory(domain=domain) case_structures = [] for patient_detail in patient_details: counter += 1 try: case_factory = EnikshayCaseFactory( domain, patient_detail, nikshay_codes_to_location ) case_structures.extend(case_factory.get_case_structures_to_create()) except Exception: num_failed += 1 logger.error( 'Failed on %d of %d. Nikshay ID=%s' % ( counter, total, patient_detail.PregId ), exc_info=True, ) else: num_succeeded += 1 if num_succeeded % chunk_size == 0: logger.info('committing cases {}-{}...'.format(num_succeeded - chunk_size, num_succeeded)) factory.create_or_update_cases(case_structures) case_structures = [] logger.info('done') logger.info( 'Succeeded on %s of %d. Nikshay ID=%s' % ( counter, total, patient_detail.PregId ) ) if case_structures: logger.info('committing final cases...'.format(num_succeeded - chunk_size, num_succeeded)) factory.create_or_update_cases(case_structures) logger.info('Done creating cases for domain %s.' % domain) logger.info('Number of attempts: %d.' % counter) logger.info('Number of successes: %d.' % num_succeeded) logger.info('Number of failures: %d.' % num_failed)
def test_get_call_center_cases_all(self): factory = CaseFactory(domain=TEST_DOMAIN, case_defaults={ 'user_id': self.user_id, 'owner_id': self.user_id, 'case_type': CASE_TYPE, 'update': {'hq_user_id': self.user_id} }) factory.create_or_update_cases([ CaseStructure(attrs={'create': True}), CaseStructure(attrs={'create': True}), CaseStructure(attrs={'create': True, 'owner_id': 'another_user'}), ]) cases = get_call_center_cases(TEST_DOMAIN, CASE_TYPE) self.assertEqual(len(cases), 3)
def test_create_from_structure(self): owner_id = uuid.uuid4().hex factory = CaseFactory(case_defaults={ 'owner_id': owner_id, 'create': True, 'update': {'custom_prop': 'custom_value'} }) case_id = uuid.uuid4().hex child_case_id = uuid.uuid4().hex parent_case_id = uuid.uuid4().hex structures = [ CaseStructure(case_id=case_id, attrs={'create': True}), CaseStructure( case_id=child_case_id, indices=[ CaseIndex(CaseStructure(case_id=parent_case_id, attrs={'create': True})) ] ) ] cases = factory.create_or_update_cases(structures) for case in cases: self.assertEqual(owner_id, case.owner_id) self.assertEqual('custom_value', case.dynamic_case_properties()['custom_prop']) [regular, child, parent] = cases self.assertEqual(1, len(child.indices)) self.assertEqual(parent_case_id, child.indices[0].referenced_id) if not getattr(settings, 'TESTS_SHOULD_USE_SQL_BACKEND', False): self.assertEqual(2, len(regular.actions)) # create + update self.assertEqual(2, len(parent.actions)) # create + update self.assertEqual(3, len(child.actions)) # create + update + index
def test_create_from_structure(self): owner_id = uuid.uuid4().hex factory = CaseFactory(case_defaults={ 'owner_id': owner_id, 'create': True, 'update': {'custom_prop': 'custom_value'} }) case_id = uuid.uuid4().hex child_case_id = uuid.uuid4().hex parent_case_id = uuid.uuid4().hex structures = [ CaseStructure(case_id=case_id), CaseStructure( case_id=child_case_id, relationships=[ CaseRelationship(CaseStructure(case_id=parent_case_id)) ] ) ] cases = factory.create_or_update_cases(structures) for case in cases: self.assertEqual(owner_id, case.owner_id) self.assertEqual('custom_value', case.custom_prop) [regular, child, parent] = cases self.assertEqual(1, len(child.indices)) self.assertEqual(parent_case_id, child.indices[0].referenced_id) self.assertEqual(2, len(regular.actions)) # create + update self.assertEqual(2, len(parent.actions)) # create + update self.assertEqual(3, len(child.actions)) # create + update + index
def setUpClass(cls): super(TestFilterDslLookups, cls).setUpClass() with trap_extra_setup(ConnectionError): cls.es = get_es_new() initialize_index_and_mapping(cls.es, CASE_SEARCH_INDEX_INFO) cls.child_case_id = 'margaery' cls.parent_case_id = 'mace' cls.grandparent_case_id = 'olenna' cls.domain = "Tyrell" factory = CaseFactory(domain=cls.domain) grandparent_case = CaseStructure( case_id=cls.grandparent_case_id, attrs={ 'create': True, 'case_type': 'grandparent', 'update': { "name": "Olenna", "alias": "Queen of thorns", "house": "Tyrell", }, }) parent_case = CaseStructure( case_id=cls.parent_case_id, attrs={ 'create': True, 'case_type': 'parent', 'update': { "name": "Mace", "house": "Tyrell", }, }, indices=[CaseIndex( grandparent_case, identifier='mother', relationship='child', )]) child_case = CaseStructure( case_id=cls.child_case_id, attrs={ 'create': True, 'case_type': 'child', 'update': { "name": "Margaery", "house": "Tyrell", }, }, indices=[CaseIndex( parent_case, identifier='father', relationship='extension', )], ) for case in factory.create_or_update_cases([child_case]): send_to_elasticsearch('case_search', transform_case_for_elasticsearch(case.to_json())) cls.es.indices.refresh(CASE_SEARCH_INDEX_INFO.index)
def test_delete_sharing_form(self): factory = CaseFactory() c1, c2 = factory.create_or_update_cases([ CaseStructure(attrs={'create': True}), CaseStructure(attrs={'create': True}), ]) with self.assertRaises(CommCareCaseError): c1.hard_delete() with self.assertRaises(CommCareCaseError): c2.hard_delete() self.assertIsNotNone(self.interface.case_model.get(c1.case_id)) self.assertIsNotNone(self.interface.case_model.get(c2.case_id))
def test_delete_sharing_form(self): factory = CaseFactory() c1, c2 = factory.create_or_update_cases([ CaseStructure(attrs={'create': True}), CaseStructure(attrs={'create': True}), ]) with self.assertRaises(CommCareCaseError): safe_hard_delete(c1) with self.assertRaises(CommCareCaseError): safe_hard_delete(c2) self.assertTrue(CommCareCase.get_db().doc_exist(c1._id)) self.assertTrue(CommCareCase.get_db().doc_exist(c2._id))
def test_delete_sharing_form(self): factory = CaseFactory() c1, c2 = factory.create_or_update_cases([ CaseStructure(attrs={'create': True}), CaseStructure(attrs={'create': True}), ]) with self.assertRaises(CommCareCaseError): safe_hard_delete(c1) with self.assertRaises(CommCareCaseError): safe_hard_delete(c2) self.assertIsNotNone(self.casedb.get_case(c1.case_id)) self.assertIsNotNone(self.casedb.get_case(c2.case_id))
def test_delete_sharing_form(self): factory = CaseFactory() c1, c2 = factory.create_or_update_cases([ CaseStructure(attrs={'create': True}), CaseStructure(attrs={'create': True}), ]) with self.assertRaises(CommCareCaseError): FormProcessorInterface.hard_delete_case(c1) with self.assertRaises(CommCareCaseError): FormProcessorInterface.hard_delete_case(c2) self.assertIsNotNone(FormProcessorInterface.get_case(c1.id)) self.assertIsNotNone(FormProcessorInterface.get_case(c2.id))
def test_legacy_support_toggle(self): restore_config = RestoreConfig(self.project, 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() self.assertTrue(child_id in restore_payload) self.assertTrue(parent_id in restore_payload) sync_log = 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) 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 test_call_center_not_default_case_owner(self): """ call center case owner should not change on sync """ factory = CaseFactory(domain=TEST_DOMAIN, case_defaults={ 'user_id': self.user_id, 'owner_id': 'another_user', 'case_type': CASE_TYPE, 'update': {'hq_user_id': self.user_id} }) cases = factory.create_or_update_cases([ CaseStructure(attrs={'create': True}) ]) sync_call_center_user_case(self.user) case = self._get_user_case() self.assertEqual(case.owner_id, cases[0].owner_id)
def test_get_call_center_cases_for_user(self): factory = CaseFactory(domain=TEST_DOMAIN, case_defaults={ 'user_id': self.user_id, 'owner_id': self.user_id, 'case_type': CASE_TYPE, 'update': {'hq_user_id': self.user_id} }) c1, c2, c3 = factory.create_or_update_cases([ CaseStructure(attrs={'create': True}), CaseStructure(attrs={'create': True}), CaseStructure(attrs={'create': True, 'owner_id': 'another_user'}), ]) cases = get_call_center_cases(TEST_DOMAIN, CASE_TYPE, self.user) self.assertEqual(len(cases), 2) case_ids = {case.case_id for case in cases} user_ids = {case.hq_user_id for case in cases} self.assertEqual(case_ids, set([c1.case_id, c2.case_id])) self.assertEqual(user_ids, set([self.user_id]))
def test_get_call_center_cases_for_user(self): factory = CaseFactory(domain=TEST_DOMAIN, case_defaults={ 'user_id': self.user_id, 'owner_id': self.user_id, 'case_type': CASE_TYPE, 'update': { 'hq_user_id': self.user_id } }) c1, c2, c3 = factory.create_or_update_cases([ CaseStructure(attrs={'create': True}), CaseStructure(attrs={'create': True}), CaseStructure(attrs={ 'create': True, 'owner_id': 'another_user' }), ]) cases = get_call_center_cases(TEST_DOMAIN, CASE_TYPE, self.user) self.assertEqual(len(cases), 2) case_ids = {case.case_id for case in cases}
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 test_create_from_structure(self): owner_id = uuid.uuid4().hex factory = CaseFactory( case_defaults={"owner_id": owner_id, "create": True, "update": {"custom_prop": "custom_value"}} ) case_id = uuid.uuid4().hex child_case_id = uuid.uuid4().hex parent_case_id = uuid.uuid4().hex structures = [ CaseStructure(case_id=case_id), CaseStructure(case_id=child_case_id, indices=[CaseIndex(CaseStructure(case_id=parent_case_id))]), ] cases = factory.create_or_update_cases(structures) for case in cases: self.assertEqual(owner_id, case.owner_id) self.assertEqual("custom_value", case.dynamic_case_properties()["custom_prop"]) [regular, child, parent] = cases self.assertEqual(1, len(child.indices)) self.assertEqual(parent_case_id, child.indices[0].referenced_id) if not settings.TESTS_SHOULD_USE_SQL_BACKEND: self.assertEqual(2, len(regular.actions)) # create + update self.assertEqual(2, len(parent.actions)) # create + update self.assertEqual(3, len(child.actions)) # create + update + index
class ReprocessSubmissionStubTests(TestCase): def setUp(self): super(ReprocessSubmissionStubTests, self).setUp() self.domain = uuid.uuid4().hex self.factory = CaseFactory(domain=self.domain) def tearDown(self): FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) super(ReprocessSubmissionStubTests, self).tearDown() def test_reprocess_unfinished_submission_case_create(self): case_id = uuid.uuid4().hex transaction_patch = patch( 'corehq.form_processor.backends.sql.processor.transaction') case_save_patch = patch( 'corehq.form_processor.backends.sql.dbaccessors.CaseAccessorSQL.save_case', side_effect=InternalError) with transaction_patch, case_save_patch, self.assertRaises( InternalError): self.factory.create_or_update_cases([ CaseStructure(case_id=case_id, attrs={ 'case_type': 'parent', 'create': True }) ]) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) # form that was saved before case error raised normal_form_ids = FormAccessorSQL.get_form_ids_in_domain_by_state( self.domain, XFormInstanceSQL.NORMAL) self.assertEqual(1, len(normal_form_ids)) self.assertEqual(stubs[0].xform_id, normal_form_ids[0]) # shows error form (duplicate of form that was saved before case error) # this is saved becuase the saving was assumed to be atomic so if there was any error it's assumed # the form didn't get saved # we don't really care about this form in this test error_forms = FormAccessorSQL.get_forms_by_type( self.domain, 'XFormError', 10) self.assertEqual(1, len(error_forms)) self.assertEqual(error_forms[0].orig_id, normal_form_ids[0]) self.assertEqual( 0, len(CaseAccessorSQL.get_case_ids_in_domain(self.domain))) result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(1, len(result.cases)) self.assertEqual(0, len(result.ledgers)) case_ids = CaseAccessorSQL.get_case_ids_in_domain(self.domain) self.assertEqual(1, len(case_ids)) self.assertEqual(case_id, case_ids[0]) with self.assertRaises(UnfinishedSubmissionStub.DoesNotExist): UnfinishedSubmissionStub.objects.get(pk=stubs[0].pk) def test_reprocess_unfinished_submission_case_update(self): case_id = uuid.uuid4().hex form_ids = [] form_ids.append( submit_case_blocks( CaseBlock(case_id=case_id, create=True, case_type='box').as_string(), self.domain)[0].form_id) transaction_patch = patch( 'corehq.form_processor.backends.sql.processor.transaction') case_save_patch = patch( 'corehq.form_processor.backends.sql.dbaccessors.CaseAccessorSQL.save_case', side_effect=InternalError) with transaction_patch, case_save_patch, self.assertRaises( InternalError): submit_case_blocks( CaseBlock(case_id=case_id, update={ 'prop': 'a' }).as_string(), self.domain) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) form_ids.append(stubs[0].xform_id) # submit second form with case update form_ids.append( submit_case_blocks( CaseBlock(case_id=case_id, update={ 'prop': 'b' }).as_string(), self.domain)[0].form_id) case = CaseAccessorSQL.get_case(case_id) self.assertEqual(2, len(case.transactions)) self.assertEqual('b', case.get_case_property('prop')) result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(1, len(result.cases)) self.assertEqual(0, len(result.ledgers)) case = CaseAccessorSQL.get_case(case_id) self.assertEqual('b', case.get_case_property( 'prop')) # should be property value from most recent form self.assertEqual(4, len(case.transactions)) self.assertEqual(form_ids + [None], [trans.form_id for trans in case.transactions]) with self.assertRaises(UnfinishedSubmissionStub.DoesNotExist): UnfinishedSubmissionStub.objects.get(pk=stubs[0].pk) def test_reprocess_unfinished_submission_ledger_create(self): from corehq.apps.commtrack.tests.util import get_single_balance_block case_id = uuid.uuid4().hex self.factory.create_or_update_cases([ CaseStructure(case_id=case_id, attrs={ 'case_type': 'parent', 'create': True }) ]) transaction_patch = patch( 'corehq.form_processor.backends.sql.processor.transaction') ledger_save_patch = patch( 'corehq.form_processor.backends.sql.dbaccessors.LedgerAccessorSQL.save_ledger_values', side_effect=InternalError) with transaction_patch, ledger_save_patch, self.assertRaises( InternalError): submit_case_blocks( get_single_balance_block(case_id, 'product1', 100), self.domain) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) ledgers = LedgerAccessorSQL.get_ledger_values_for_case(case_id) self.assertEqual(0, len(ledgers)) # case transaction got saved case = CaseAccessorSQL.get_case(case_id) self.assertEqual(2, len(case.transactions)) self.assertTrue(case.transactions[0].is_case_create) self.assertTrue(case.transactions[1].is_ledger_transaction) ledger_transactions = LedgerAccessorSQL.get_ledger_transactions_for_case( case_id) self.assertEqual(0, len(ledger_transactions)) result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(0, len(result.cases)) self.assertEqual(1, len(result.ledgers)) ledgers = LedgerAccessorSQL.get_ledger_values_for_case(case_id) self.assertEqual(1, len(ledgers)) ledger_transactions = LedgerAccessorSQL.get_ledger_transactions_for_case( case_id) self.assertEqual(1, len(ledger_transactions)) # case still only has 2 transactions case = CaseAccessorSQL.get_case(case_id) self.assertEqual(2, len(case.transactions)) def test_reprocess_unfinished_submission_ledger_rebuild(self): from corehq.apps.commtrack.tests.util import get_single_balance_block case_id = uuid.uuid4().hex form_ids = [] form_ids.append( submit_case_blocks([ CaseBlock(case_id=case_id, create=True, case_type='shop').as_string(), get_single_balance_block(case_id, 'product1', 100), ], self.domain)[0].form_id) transaction_patch = patch( 'corehq.form_processor.backends.sql.processor.transaction') ledger_save_patch = patch( 'corehq.form_processor.backends.sql.dbaccessors.LedgerAccessorSQL.save_ledger_values', side_effect=InternalError) with transaction_patch, ledger_save_patch, self.assertRaises( InternalError): submit_case_blocks( get_single_balance_block(case_id, 'product1', 50), self.domain) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) form_ids.append(stubs[0].xform_id) # submit another form afterwards form_ids.append( submit_case_blocks( get_single_balance_block(case_id, 'product1', 25), self.domain)[0].form_id) ledgers = LedgerAccessorSQL.get_ledger_values_for_case(case_id) self.assertEqual(1, len(ledgers)) self.assertEqual(25, ledgers[0].balance) ledger_transactions = LedgerAccessorSQL.get_ledger_transactions_for_case( case_id) self.assertEqual(2, len(ledger_transactions)) # should rebuild ledger transactions result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(0, len(result.cases)) self.assertEqual(1, len(result.ledgers)) ledgers = LedgerAccessorSQL.get_ledger_values_for_case(case_id) self.assertEqual(1, len(ledgers)) # still only 1 self.assertEqual(25, ledgers[0].balance) ledger_transactions = LedgerAccessorSQL.get_ledger_transactions_for_case( case_id) self.assertEqual(3, len(ledger_transactions)) # make sure transactions are in correct order self.assertEqual(form_ids, [trans.form_id for trans in ledger_transactions]) self.assertEqual(100, ledger_transactions[0].updated_balance) self.assertEqual(100, ledger_transactions[0].delta) self.assertEqual(50, ledger_transactions[1].updated_balance) self.assertEqual(-50, ledger_transactions[1].delta) self.assertEqual(25, ledger_transactions[2].updated_balance) self.assertEqual(-25, ledger_transactions[2].delta)
class TestExtensionCaseIds(TestCase): @classmethod def setUpClass(cls): delete_all_cases() def setUp(self): self.domain = 'domain' self.factory = CaseFactory(self.domain) def test_no_extensions(self): """ Returns empty when there are other index types """ parent_id = uuid.uuid4().hex child_id = uuid.uuid4().hex parent = CaseStructure(case_id=parent_id) self.factory.create_or_update_case( CaseStructure( case_id=child_id, indices=[ CaseIndex(parent, relationship=CASE_INDEX_CHILD) ] ) ) returned_cases = get_extension_case_ids(self.domain, [parent_id]) self.assertEqual(returned_cases, []) 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) self.factory.create_or_update_case( CaseStructure( case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION) ] ) ) returned_cases = get_extension_case_ids(self.domain, [host_id]) self.assertItemsEqual(returned_cases, [extension_id]) def test_extension_of_multiple_hosts_returned(self): """ Should return an extension from any host if there are multiple indices """ host_id = uuid.uuid4().hex host_2_id = uuid.uuid4().hex parent_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id) host_2 = CaseStructure(case_id=host_2_id) parent = CaseStructure(case_id=parent_id) self.factory.create_or_update_case( CaseStructure( case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), CaseIndex(host_2, relationship=CASE_INDEX_EXTENSION, identifier="host_2"), CaseIndex(parent, relationship=CASE_INDEX_CHILD), ] ) ) returned_cases = get_extension_case_ids(self.domain, [host_2_id]) self.assertItemsEqual(returned_cases, [extension_id]) returned_cases = get_extension_case_ids(self.domain, [host_id]) self.assertItemsEqual(returned_cases, [extension_id]) def test_host_with_multiple_extensions(self): """ Return all extensions from a single host """ host_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex extension_2_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id) self.factory.create_or_update_cases([ CaseStructure( case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), ] ), CaseStructure( case_id=extension_2_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), ] ), ] ) returned_cases = get_extension_case_ids(self.domain, [host_id]) self.assertItemsEqual(returned_cases, [extension_id, extension_2_id]) def test_extensions_from_list(self): """ Given a list of hosts, should return all extensions """ host_id = uuid.uuid4().hex host_2_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex extension_2_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id) host_2 = CaseStructure(case_id=host_2_id) self.factory.create_or_update_case( CaseStructure( case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), ] ) ) self.factory.create_or_update_case( CaseStructure( case_id=extension_2_id, indices=[ CaseIndex(host_2, relationship=CASE_INDEX_EXTENSION, identifier="host"), ] ) ) returned_cases = get_extension_case_ids(self.domain, [host_id, host_2_id]) self.assertItemsEqual(returned_cases, [extension_id, extension_2_id])
class AutoCloseExtensionsTest(SyncBaseTest): def setUp(self): FormProcessorTestUtils.delete_all_cases() FormProcessorTestUtils.delete_all_xforms() self.domain = "domain" self.project = Domain(name=self.domain) self.user = User(user_id='user', username='******', password="******", date_joined=datetime(2011, 6, 9)) self.factory = CaseFactory() self.extension_ids = ['1', '2', '3'] self.host = CaseStructure(case_id='host') self.extension = CaseStructure( case_id=self.extension_ids[0], indices=[CaseIndex( related_structure=self.host, relationship="extension", )], ) self.extension_2 = CaseStructure( case_id=self.extension_ids[1], indices=[CaseIndex( related_structure=self.extension, relationship="extension", )], ) self.extension_3 = CaseStructure( case_id=self.extension_ids[2], indices=[CaseIndex( related_structure=self.extension_2, relationship="extension", )], ) def test_get_extension_chain_simple(self): self.factory.create_or_update_cases([self.extension]) self.assertEqual(set(self.extension_ids[0]), get_extension_chain([self.host], self.domain)) def test_get_extension_chain_multiple(self): self.factory.create_or_update_cases([self.extension_3]) self.assertEqual(set(self.extension_ids), get_extension_chain([self.host], self.domain)) @flag_enabled('EXTENSION_CASES_SYNC_ENABLED') def test_get_extension_to_close(self): """should return empty if case is not a host, otherwise should return full chain""" created_cases = self.factory.create_or_update_cases([self.extension_3]) # host open, should be empty no_cases = get_extensions_to_close(created_cases[-1], self.domain) self.assertEqual(set(), no_cases) created_cases[-1] = self.factory.create_or_update_case(CaseStructure( case_id=self.host.case_id, attrs={'close': True} ))[0] # host closed, should get full chain full_chain = get_extensions_to_close(created_cases[-1], self.domain) self.assertEqual(set(self.extension_ids), full_chain) # extension (not a host), should be empty no_cases = get_extensions_to_close(created_cases[2], self.domain) self.assertEqual(set(), no_cases) @flag_enabled('EXTENSION_CASES_SYNC_ENABLED') def test_close_cases(self): """Closing a host should close all the extensions""" self.factory.create_or_update_cases([self.extension_3]) self.assertFalse(CommCareCase.get(self.extension.case_id).closed) self.assertFalse(CommCareCase.get(self.extension_2.case_id).closed) self.assertFalse(CommCareCase.get(self.extension_3.case_id).closed) self.factory.create_or_update_case(CaseStructure( case_id=self.extension.case_id, attrs={'close': True} )) self.assertFalse(CommCareCase.get(self.host.case_id).closed) self.assertTrue(CommCareCase.get(self.extension.case_id).closed) self.assertFalse(CommCareCase.get(self.extension_2.case_id).closed) self.assertFalse(CommCareCase.get(self.extension_3.case_id).closed) self.factory.create_or_update_case(CaseStructure( case_id=self.host.case_id, attrs={'close': True} )) self.assertTrue(CommCareCase.get(self.host.case_id).closed) self.assertTrue(CommCareCase.get(self.extension.case_id).closed) self.assertTrue(CommCareCase.get(self.extension_2.case_id).closed) self.assertTrue(CommCareCase.get(self.extension_3.case_id).closed)
class ReprocessSubmissionStubTests(TestCase): @classmethod def setUpClass(cls): super(ReprocessSubmissionStubTests, cls).setUpClass() cls.domain = uuid.uuid4().hex cls.product = SQLProduct.objects.create(domain=cls.domain, product_id='product1', name='product1') @classmethod def tearDownClass(cls): cls.product.delete() super(ReprocessSubmissionStubTests, cls).tearDownClass() def setUp(self): super(ReprocessSubmissionStubTests, self).setUp() self.factory = CaseFactory(domain=self.domain) self.formdb = XFormInstance.objects self.ledgerdb = LedgerAccessors(self.domain) def tearDown(self): FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) super(ReprocessSubmissionStubTests, self).tearDown() def test_reprocess_unfinished_submission_case_create(self): case_id = uuid.uuid4().hex with _patch_save_to_raise_error(self): self.factory.create_or_update_cases([ CaseStructure(case_id=case_id, attrs={ 'case_type': 'parent', 'create': True }) ]) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) # form that was saved before case error raised normal_form_ids = XFormInstance.objects.get_form_ids_in_domain( self.domain, 'XFormInstance') self.assertEqual(0, len(normal_form_ids)) # shows error form (duplicate of form that was saved before case error) # this is saved becuase the saving was assumed to be atomic so if there was any error it's assumed # the form didn't get saved # we don't really care about this form in this test error_forms = XFormInstance.objects.get_forms_by_type( self.domain, 'XFormError', 10) self.assertEqual(1, len(error_forms)) self.assertIsNone(error_forms[0].orig_id) self.assertEqual(error_forms[0].form_id, stubs[0].xform_id) self.assertEqual( 0, len(CommCareCase.objects.get_case_ids_in_domain(self.domain))) result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(1, len(result.cases)) case_ids = CommCareCase.objects.get_case_ids_in_domain(self.domain) self.assertEqual(1, len(case_ids)) self.assertEqual(case_id, case_ids[0]) with self.assertRaises(UnfinishedSubmissionStub.DoesNotExist): UnfinishedSubmissionStub.objects.get(pk=stubs[0].pk) def test_reprocess_unfinished_submission_case_update(self): case_id = uuid.uuid4().hex form_ids = [] form_ids.append( submit_case_blocks( CaseBlock(case_id=case_id, create=True, case_type='box').as_text(), self.domain)[0].form_id) with _patch_save_to_raise_error(self): submit_case_blocks( CaseBlock(case_id=case_id, update={ 'prop': 'a' }).as_text(), self.domain) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) form_ids.append(stubs[0].xform_id) # submit second form with case update form_ids.append( submit_case_blocks( CaseBlock(case_id=case_id, update={ 'prop': 'b' }).as_text(), self.domain)[0].form_id) case = CommCareCase.objects.get_case(case_id, self.domain) self.assertEqual(2, len(case.xform_ids)) self.assertEqual('b', case.get_case_property('prop')) result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(1, len(result.cases)) self.assertEqual(0, len(result.ledgers)) case = CommCareCase.objects.get_case(case_id, self.domain) self.assertEqual('b', case.get_case_property( 'prop')) # should be property value from most recent form self.assertEqual(3, len(case.xform_ids)) self.assertEqual(form_ids, case.xform_ids) with self.assertRaises(UnfinishedSubmissionStub.DoesNotExist): UnfinishedSubmissionStub.objects.get(pk=stubs[0].pk) def test_reprocess_unfinished_submission_ledger_create(self): from corehq.apps.commtrack.tests.util import get_single_balance_block case_id = uuid.uuid4().hex self.factory.create_or_update_cases([ CaseStructure(case_id=case_id, attrs={ 'case_type': 'parent', 'create': True }) ]) with _patch_save_to_raise_error(self): submit_case_blocks( get_single_balance_block(case_id, 'product1', 100), self.domain) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) ledgers = self.ledgerdb.get_ledger_values_for_case(case_id) self.assertEqual(0, len(ledgers)) case = CommCareCase.objects.get_case(case_id, self.domain) self.assertEqual(1, len(case.xform_ids)) ledger_transactions = self.ledgerdb.get_ledger_transactions_for_case( case_id) self.assertEqual(0, len(ledger_transactions)) result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(1, len(result.cases)) self.assertEqual(1, len(result.ledgers)) ledgers = self.ledgerdb.get_ledger_values_for_case(case_id) self.assertEqual(1, len(ledgers)) ledger_transactions = self.ledgerdb.get_ledger_transactions_for_case( case_id) self.assertEqual(1, len(ledger_transactions)) # case still only has 2 transactions case = CommCareCase.objects.get_case(case_id, self.domain) self.assertEqual(2, len(case.xform_ids)) self.assertTrue(case.actions[1].is_ledger_transaction) def test_reprocess_unfinished_submission_ledger_rebuild(self): from corehq.apps.commtrack.tests.util import get_single_balance_block case_id = uuid.uuid4().hex form_ids = [] form_ids.append( submit_case_blocks([ CaseBlock(case_id=case_id, create=True, case_type='shop').as_text(), get_single_balance_block(case_id, 'product1', 100), ], self.domain)[0].form_id) with _patch_save_to_raise_error(self): submit_case_blocks( get_single_balance_block(case_id, 'product1', 50), self.domain) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) form_ids.append(stubs[0].xform_id) # submit another form afterwards form_ids.append( submit_case_blocks( get_single_balance_block(case_id, 'product1', 25), self.domain)[0].form_id) ledgers = self.ledgerdb.get_ledger_values_for_case(case_id) self.assertEqual(1, len(ledgers)) self.assertEqual(25, ledgers[0].balance) ledger_transactions = self.ledgerdb.get_ledger_transactions_for_case( case_id) self.assertEqual(2, len(ledger_transactions)) # should rebuild ledger transactions result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(1, len(result.cases)) self.assertEqual(1, len(result.ledgers)) ledgers = self.ledgerdb.get_ledger_values_for_case(case_id) self.assertEqual(1, len(ledgers)) # still only 1 self.assertEqual(25, ledgers[0].balance) ledger_transactions = self.ledgerdb.get_ledger_transactions_for_case( case_id) self.assertEqual(3, len(ledger_transactions)) # make sure transactions are in correct order self.assertEqual(form_ids, [trans.form_id for trans in ledger_transactions]) self.assertEqual(100, ledger_transactions[0].updated_balance) self.assertEqual(100, ledger_transactions[0].delta) self.assertEqual(50, ledger_transactions[1].updated_balance) self.assertEqual(-50, ledger_transactions[1].delta) self.assertEqual(25, ledger_transactions[2].updated_balance) self.assertEqual(-25, ledger_transactions[2].delta) def test_fire_signals(self): from corehq.apps.receiverwrapper.tests.test_submit_errors import failing_signal_handler case_id = uuid.uuid4().hex form_id = uuid.uuid4().hex with failing_signal_handler('signal death'): submit_case_blocks(CaseBlock(case_id=case_id, create=True, case_type='box').as_text(), self.domain, form_id=form_id) form = self.formdb.get_form(form_id) with catch_signal(successful_form_received) as form_handler, \ catch_signal(sql_case_post_save) as case_handler: submit_form_locally( instance=form.get_xml(), domain=self.domain, ) case = CommCareCase.objects.get_case(case_id, self.domain) self.assertEqual(form, form_handler.call_args[1]['xform']) self.assertEqual(case, case_handler.call_args[1]['case']) def test_reprocess_normal_form(self): case_id = uuid.uuid4().hex form, cases = submit_case_blocks( CaseBlock(case_id=case_id, create=True, case_type='box').as_text(), self.domain) self.assertTrue(form.is_normal) result = reprocess_form(form, save=True, lock_form=False) self.assertIsNone(result.error) case = CommCareCase.objects.get_case(case_id, self.domain) transactions = case.actions self.assertEqual([trans.form_id for trans in transactions], [form.form_id]) def test_processing_skipped_when_migrations_are_in_progress(self): case_id = uuid.uuid4().hex with _patch_save_to_raise_error(self): self.factory.create_or_update_cases([ CaseStructure(case_id=case_id, attrs={ 'case_type': 'parent', 'create': True }) ]) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) with patch( 'corehq.form_processor.reprocess.any_migrations_in_progress', return_value=True): result = reprocess_unfinished_stub(stubs[0]) self.assertIsNone(result) result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(1, len(result.cases)) def test_processing_retuns_error_for_missing_form(self): case_id = uuid.uuid4().hex with _patch_save_to_raise_error(self): self.factory.create_or_update_cases([ CaseStructure(case_id=case_id, attrs={ 'case_type': 'parent', 'create': True }) ]) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) with self.assertRaises(XFormNotFound): self.formdb.get_form(stubs[0].xform_id) result = reprocess_unfinished_stub(stubs[0]) self.assertIsNotNone(result.error)
class TestAdherenceUpdater(TestCase): _call_center_domain_mock = mock.patch( 'corehq.apps.callcenter.data_source.call_center_data_source_configuration_provider' ) @classmethod def setUpClass(cls): super(TestAdherenceUpdater, cls).setUpClass() cls._call_center_domain_mock.start() cls.domain = 'enikshay' cls.user = CommCareUser.create( cls.domain, "jon-snow@user", "123", ) cls.setupFixtureData() def setUp(self): super(TestAdherenceUpdater, self).setUp() self.factory = CaseFactory(domain=self.domain) self.person_id = u"person" self.occurrence_id = u"occurrence" self.episode_id = u"episode" self.case_updater = EpisodeUpdater(self.domain) self.data_store = get_datastore(self.domain) @classmethod def setupFixtureData(cls): cls.fixture_data = { 'schedule1': '7', 'schedule2': '14', 'schedule3': '21', } cls.data_type = FixtureDataType( domain=cls.domain, tag=DAILY_SCHEDULE_FIXTURE_NAME, name=DAILY_SCHEDULE_FIXTURE_NAME, fields=[ FixtureTypeField( field_name=SCHEDULE_ID_FIXTURE, properties=[] ), FixtureTypeField( field_name="doses_per_week", properties=[] ), ], item_attributes=[], ) cls.data_type.save() cls.data_items = [] for _id, value in cls.fixture_data.iteritems(): data_item = FixtureDataItem( domain=cls.domain, data_type_id=cls.data_type.get_id, fields={ SCHEDULE_ID_FIXTURE: FieldList( field_list=[ FixtureItemField( field_value=_id, ) ] ), "doses_per_week": FieldList( field_list=[ FixtureItemField( field_value=value, ) ] ) }, item_attributes={}, ) data_item.save() cls.data_items.append(data_item) @classmethod def tearDownClass(cls): cls.user.delete() cls.data_type.delete() for data_item in cls.data_items: data_item.delete() super(TestAdherenceUpdater, cls).tearDownClass() cls._call_center_domain_mock.stop() def tearDown(self): get_datastore.reset_cache() self.data_store.adapter.clear_table() FormProcessorTestUtils.delete_all_cases() def _create_episode_case(self, adherence_schedule_date_start=None, adherence_schedule_id=None): person = get_person_case_structure( self.person_id, self.user.user_id, ) occurrence = get_occurrence_case_structure( self.occurrence_id, person ) episode_structure = get_episode_case_structure( self.episode_id, occurrence, extra_update={ 'adherence_schedule_date_start': adherence_schedule_date_start, 'adherence_schedule_id': adherence_schedule_id } ) cases = {case.case_id: case for case in self.factory.create_or_update_cases([episode_structure])}
class TestCreateEnikshayCases(TestCase): domain = 'enikshay-2b-migration' def setUp(self): self.project = Domain(name=self.domain) self.project.save() self.location_types, self.locations = setup_enikshay_locations( self.domain) self.factory = CaseFactory(domain=self.domain) self.cases = self.setup_cases() def tearDown(self): self.project.delete() def setup_cases(self): private_person = self._get_person_structure( 'susanna-dean', self.locations['PHI'].location_id) private_person.attrs['update'][ ENROLLED_IN_PRIVATE] = 'true' # should be excluded person = self._get_person_structure('roland-deschain', self.locations['PHI'].location_id) occurrence = self._get_occurrence_structure(person) episode = self._get_episode_structure(occurrence) test = self._get_test_structure(occurrence) referral = self._get_referral_structure(person) trail = self._get_trail_structure(referral) drtb_hiv_referral = self._get_drtb_hiv_referral_structure(episode) cases = { c.case_id: c for c in self.factory.create_or_update_cases([ private_person, occurrence, test, referral, episode, trail, drtb_hiv_referral, ]) } cases[test.case_id] = self._update_test(test) return cases def _get_person_structure(self, person_id, owner_id): person_fields = {ENROLLED_IN_PRIVATE: ""} person = get_person_case_structure(person_id, owner_id, extra_update=person_fields) person.attrs['owner_id'] = owner_id person.attrs['update'].update({ 'person_id': 'person_id', 'phi_area': 'phi_area', 'date_referred_out': 'date_referred_out', 'referred_by_id': 'referred_by_id', 'phone_number': '1234567890', }) return person def _get_occurrence_structure(self, person): case_id = person.case_id + '-occurrence' return get_occurrence_case_structure(case_id, person) def _get_episode_structure(self, occurrence): case_id = occurrence.case_id + '-episode' episode = get_episode_case_structure(case_id, occurrence) episode.attrs['update'].update({ 'episode_type': "confirmed_tb", 'alcohol_history': "alcohol_history", 'alcohol_deaddiction': "alcohol_deaddiction", 'tobacco_user': "******", 'occupation': "occupation", 'phone_number_other': "phone_number_other", 'disease_classification': 'disease_classification', 'site_choice': 'site_choice', 'site_detail': 'site_detail', 'key_population_status': 'key_population_status', 'key_populations': 'key_populations', 'treatment_status': 'second_line_treatment', 'date_of_diagnosis': '', 'date_reported': 'date_reported', 'full_dosage': 'full_dosage', 'test_confirming_diagnosis': 'chest_x-ray', }) return episode def _get_test_structure(self, occurrence): case_id = occurrence.case_id + '-test' test = get_test_case_structure(case_id, occurrence.case_id) test.attrs['update'].update({ 'diagnostic_drtb_test_reason': 'diagnostic_drtb_test_reason', 'follow_up_test_reason': 'definitely_not_private_ntm', 'diagnostic_test_reason': 'diagnostic_test_reason', 'purpose_of_testing': 'diagnostic', 'max_bacilli_count': '11', 'clinical_remarks': 'that looks infected', 'result': 'tb_detected', 'test_type_value': 'cbnaat', }) return test def _update_test(self, test): form_xml = """ <data xmlns="http://commcarehq.org/case"> <case case_id="{case_id}" xmlns="http://commcarehq.org/case/transaction/v2"> <update> <result_recorded>yes</result_recorded> </update> </case> <update_test_result> <cbnaat> <ql_sample_a> <sample_a_rif_resistance_result>detected</sample_a_rif_resistance_result> </ql_sample_a> </cbnaat> </update_test_result> </data> """.format(case_id=test.case_id) submit_form_locally(form_xml, self.domain) def _get_referral_structure(self, person): case_id = person.case_id + '-referral' referral = get_referral_case_structure(case_id, person.case_id) referral.attrs['update'].update({ 'referral_date': 'referral_date', 'referred_to_location_name': 'referred_to_location_name', 'reason_for_refusal_other_detail': 'reason_for_refusal_other_detail', 'reason_for_refusal': 'reason_for_refusal', 'acceptance_refusal_date': 'acceptance_refusal_date', 'phi': 'phi', }) return referral def _get_trail_structure(self, referral): case_id = referral.case_id + '-trail' trail = get_trail_case_structure(case_id, "overriding this anyways") trail.indices = [ CaseIndex( CaseStructure(case_id=referral.case_id, attrs={"create": False}), identifier='parent', relationship=CASE_INDEX_CHILD, related_type='referral', ) ] return trail 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 test(self): migrator = ENikshay2BMigrator(self.domain, commit=True) # first check some utils person_case_ids = migrator.get_relevant_person_case_ids() person_case_sets = list( migrator.get_relevant_person_case_sets(person_case_ids)) self.assertEqual(1, len(person_case_sets)) person = person_case_sets[0] self.assertEqual('roland-deschain', person.person.case_id) self.assertItemsEqual(['roland-deschain-occurrence'], [c.case_id for c in person.occurrences]) self.assertItemsEqual(['roland-deschain-occurrence-episode'], [c.case_id for c in person.episodes]) self.assertItemsEqual(['roland-deschain-occurrence-test'], [c.case_id for c in person.tests]) self.assertItemsEqual(['roland-deschain-referral'], [c.case_id for c in person.referrals]) self.assertItemsEqual(['roland-deschain-referral-trail'], [c.case_id for c in person.trails]) self.assertItemsEqual( ['roland-deschain-occurrence-episode-drtb_hiv_referral'], [c.case_id for c in person.drtb_hiv]) # run the actual migration migrator.migrate() # check the results accessor = CaseAccessors(self.domain) new_person = accessor.get_case(person.person.case_id) self.assertDictContainsSubset( { 'area': 'phi_area', 'referred_outside_enikshay_date': 'date_referred_out', 'referred_outside_enikshay_by_id': 'referred_by_id', 'contact_phone_number': '911234567890', 'current_episode_type': "confirmed_tb", 'alcohol_history': "alcohol_history", 'alcohol_deaddiction': "alcohol_deaddiction", 'tobacco_user': "******", 'occupation': "occupation", 'phone_number_other': "phone_number_other", 'phi_name': 'PHI', 'tu_name': 'TU', 'tu_id': self.locations['TU'].location_id, 'dto_name': 'DTO', 'dto_id': self.locations['DTO'].location_id, 'dataset': 'real', 'updated_by_migration': 'enikshay_2b_case_properties', }, new_person.dynamic_case_properties()) new_occurrence = accessor.get_case(person.occurrences[0].case_id) self.assertDictContainsSubset( { 'current_episode_type': 'confirmed_tb', 'disease_classification': 'disease_classification', 'site_choice': 'site_choice', 'site_detail': 'site_detail', 'key_population_status': 'key_population_status', 'key_populations': 'key_populations', }, new_occurrence.dynamic_case_properties()) new_episode = accessor.get_case(person.episodes[0].case_id) self.assertDictContainsSubset( { 'treatment_status': 'initiated_second_line_treatment', 'date_of_diagnosis': 'date_reported', 'dosage_display': 'full_dosage', 'dosage_summary': 'full_dosage', 'rft_general': 'diagnosis_dstb', 'diagnosis_test_type': 'chest_x-ray', 'diagnosis_test_type_label': "Chest X-ray", 'is_active': 'yes', }, new_episode.dynamic_case_properties()) new_test = accessor.get_case(person.tests[0].case_id) self.assertDictContainsSubset( { 'is_direct_test_entry': 'no', 'rft_drtb_diagnosis': 'diagnostic_drtb_test_reason', 'dataset': 'real', 'rft_general': 'diagnosis_dstb', 'rft_dstb_diagnosis': 'diagnostic_test_reason', 'rft_dstb_followup': 'definitely_not_private_ntm', 'episode_case_id': 'roland-deschain-occurrence-episode', 'result_summary_display': "TB Detected\nR: Res\nCount of bacilli: 11\nthat looks infected", 'drug_resistance_list': 'r', }, new_test.dynamic_case_properties()) new_referral = accessor.get_case(person.referrals[0].case_id) self.assertDictContainsSubset( { 'referral_initiated_date': 'referral_date', 'referred_to_name': 'referred_to_location_name', 'referred_by_name': '', 'referral_rejection_reason_other_detail': 'reason_for_refusal_other_detail', 'referral_rejection_reason': 'reason_for_refusal', 'referral_closed_date': 'acceptance_refusal_date', 'accepted_by_name': 'phi', }, new_referral.dynamic_case_properties()) parent = get_parent_of_case(self.domain, new_referral, 'occurrence') self.assertEqual(new_occurrence.case_id, parent.case_id) new_trail = accessor.get_case(person.trails[0].case_id) parent = get_parent_of_case(self.domain, new_trail, 'occurrence') self.assertEqual(new_occurrence.case_id, parent.case_id) new_drtb_hiv = accessor.get_case(person.drtb_hiv[0].case_id) self.assertTrue(new_drtb_hiv.closed) secondary_owner_id = accessor.get_case_ids_in_domain( type='secondary_owner')[0] new_secondary_owner = accessor.get_case(secondary_owner_id) self.assertEqual('person_id-drtb-hiv', new_secondary_owner.name) self.assertDictContainsSubset({ 'secondary_owner_type': 'drtb-hiv', }, new_secondary_owner.dynamic_case_properties()) self.assertEqual("drtb_hiv_referral_owner", new_secondary_owner.owner_id) parent = get_parent_of_case(self.domain, new_secondary_owner, 'occurrence') self.assertEqual(new_occurrence.case_id, parent.case_id)
class ReprocessSubmissionStubTests(TestCase): @classmethod def setUpClass(cls): super(ReprocessSubmissionStubTests, cls).setUpClass() cls.domain = uuid.uuid4().hex cls.product = SQLProduct.objects.create(domain=cls.domain, product_id='product1', name='product1') @classmethod def tearDownClass(cls): cls.product.delete() super(ReprocessSubmissionStubTests, cls).tearDownClass() def setUp(self): super(ReprocessSubmissionStubTests, self).setUp() self.factory = CaseFactory(domain=self.domain) self.formdb = FormAccessors(self.domain) self.casedb = CaseAccessors(self.domain) self.ledgerdb = LedgerAccessors(self.domain) def tearDown(self): FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) super(ReprocessSubmissionStubTests, self).tearDown() def test_reprocess_unfinished_submission_case_create(self): case_id = uuid.uuid4().hex with _patch_save_to_raise_error(self): self.factory.create_or_update_cases([ CaseStructure(case_id=case_id, attrs={'case_type': 'parent', 'create': True}) ]) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) # form that was saved before case error raised normal_form_ids = self.formdb.get_all_form_ids_in_domain('XFormInstance') self.assertEqual(0, len(normal_form_ids)) # shows error form (duplicate of form that was saved before case error) # this is saved becuase the saving was assumed to be atomic so if there was any error it's assumed # the form didn't get saved # we don't really care about this form in this test error_forms = self.formdb.get_forms_by_type('XFormError', 10) self.assertEqual(1, len(error_forms)) self.assertIsNone(error_forms[0].orig_id) self.assertEqual(error_forms[0].form_id, stubs[0].xform_id) self.assertEqual(0, len(self.casedb.get_case_ids_in_domain(self.domain))) result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(1, len(result.cases)) case_ids = self.casedb.get_case_ids_in_domain() self.assertEqual(1, len(case_ids)) self.assertEqual(case_id, case_ids[0]) with self.assertRaises(UnfinishedSubmissionStub.DoesNotExist): UnfinishedSubmissionStub.objects.get(pk=stubs[0].pk) def test_reprocess_unfinished_submission_case_update(self): case_id = uuid.uuid4().hex form_ids = [] form_ids.append(submit_case_blocks( CaseBlock(case_id=case_id, create=True, case_type='box').as_string().decode('utf-8'), self.domain )[0].form_id) with _patch_save_to_raise_error(self): submit_case_blocks( CaseBlock(case_id=case_id, update={'prop': 'a'}).as_string().decode('utf-8'), self.domain ) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) form_ids.append(stubs[0].xform_id) # submit second form with case update form_ids.append(submit_case_blocks( CaseBlock(case_id=case_id, update={'prop': 'b'}).as_string().decode('utf-8'), self.domain )[0].form_id) case = self.casedb.get_case(case_id) self.assertEqual(2, len(case.xform_ids)) self.assertEqual('b', case.get_case_property('prop')) result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(1, len(result.cases)) self.assertEqual(0, len(result.ledgers)) case = self.casedb.get_case(case_id) self.assertEqual('b', case.get_case_property('prop')) # should be property value from most recent form self.assertEqual(3, len(case.xform_ids)) self.assertEqual(form_ids, case.xform_ids) with self.assertRaises(UnfinishedSubmissionStub.DoesNotExist): UnfinishedSubmissionStub.objects.get(pk=stubs[0].pk) def test_reprocess_unfinished_submission_ledger_create(self): from corehq.apps.commtrack.tests.util import get_single_balance_block case_id = uuid.uuid4().hex self.factory.create_or_update_cases([ CaseStructure(case_id=case_id, attrs={'case_type': 'parent', 'create': True}) ]) with _patch_save_to_raise_error(self): submit_case_blocks( get_single_balance_block(case_id, 'product1', 100), self.domain ) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) ledgers = self.ledgerdb.get_ledger_values_for_case(case_id) self.assertEqual(0, len(ledgers)) case = self.casedb.get_case(case_id) self.assertEqual(1, len(case.xform_ids)) ledger_transactions = self.ledgerdb.get_ledger_transactions_for_case(case_id) self.assertEqual(0, len(ledger_transactions)) result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(1, len(result.cases)) self.assertEqual(1, len(result.ledgers)) ledgers = self.ledgerdb.get_ledger_values_for_case(case_id) self.assertEqual(1, len(ledgers)) ledger_transactions = self.ledgerdb.get_ledger_transactions_for_case(case_id) self.assertEqual(1, len(ledger_transactions)) # case still only has 2 transactions case = self.casedb.get_case(case_id) self.assertEqual(2, len(case.xform_ids)) if should_use_sql_backend(self.domain): self.assertTrue(case.actions[1].is_ledger_transaction) def test_reprocess_unfinished_submission_ledger_rebuild(self): from corehq.apps.commtrack.tests.util import get_single_balance_block case_id = uuid.uuid4().hex form_ids = [] form_ids.append(submit_case_blocks( [ CaseBlock(case_id=case_id, create=True, case_type='shop').as_string().decode('utf-8'), get_single_balance_block(case_id, 'product1', 100), ], self.domain )[0].form_id) with _patch_save_to_raise_error(self): submit_case_blocks( get_single_balance_block(case_id, 'product1', 50), self.domain ) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) form_ids.append(stubs[0].xform_id) # submit another form afterwards form_ids.append(submit_case_blocks( get_single_balance_block(case_id, 'product1', 25), self.domain )[0].form_id) ledgers = self.ledgerdb.get_ledger_values_for_case(case_id) self.assertEqual(1, len(ledgers)) self.assertEqual(25, ledgers[0].balance) ledger_transactions = self.ledgerdb.get_ledger_transactions_for_case(case_id) if should_use_sql_backend(self.domain): self.assertEqual(2, len(ledger_transactions)) else: # includes extra consumption transaction self.assertEqual(3, len(ledger_transactions)) # should rebuild ledger transactions result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(1, len(result.cases)) self.assertEqual(1, len(result.ledgers)) ledgers = self.ledgerdb.get_ledger_values_for_case(case_id) self.assertEqual(1, len(ledgers)) # still only 1 self.assertEqual(25, ledgers[0].balance) ledger_transactions = self.ledgerdb.get_ledger_transactions_for_case(case_id) if should_use_sql_backend(self.domain): self.assertEqual(3, len(ledger_transactions)) # make sure transactions are in correct order self.assertEqual(form_ids, [trans.form_id for trans in ledger_transactions]) self.assertEqual(100, ledger_transactions[0].updated_balance) self.assertEqual(100, ledger_transactions[0].delta) self.assertEqual(50, ledger_transactions[1].updated_balance) self.assertEqual(-50, ledger_transactions[1].delta) self.assertEqual(25, ledger_transactions[2].updated_balance) self.assertEqual(-25, ledger_transactions[2].delta) else: self.assertEqual(3, len(ledger_transactions)) self.assertEqual(form_ids, [trans.report.form_id for trans in ledger_transactions]) self.assertEqual(100, ledger_transactions[0].stock_on_hand) self.assertEqual(50, ledger_transactions[1].stock_on_hand) self.assertEqual(25, ledger_transactions[2].stock_on_hand) def test_fire_signals(self): from corehq.apps.receiverwrapper.tests.test_submit_errors import failing_signal_handler case_id = uuid.uuid4().hex form_id = uuid.uuid4().hex with failing_signal_handler('signal death'): submit_case_blocks( CaseBlock(case_id=case_id, create=True, case_type='box').as_string().decode('utf-8'), self.domain, form_id=form_id ) form = self.formdb.get_form(form_id) with catch_signal(successful_form_received) as form_handler, catch_signal(case_post_save) as case_handler: submit_form_locally( instance=form.get_xml(), domain=self.domain, ) case = self.casedb.get_case(case_id) if should_use_sql_backend(self.domain): self.assertEqual(form, form_handler.call_args[1]['xform']) self.assertEqual(case, case_handler.call_args[1]['case']) else: signal_form = form_handler.call_args[1]['xform'] self.assertEqual(form.form_id, signal_form.form_id) self.assertEqual(form.get_rev, signal_form.get_rev) signal_case = case_handler.call_args[1]['case'] self.assertEqual(case.case_id, signal_case.case_id) self.assertEqual(case.get_rev, signal_case.get_rev)
class ENikshayCaseStructureMixin(object): def setUp(self): super(ENikshayCaseStructureMixin, self).setUp() self.domain = getattr(self, 'domain', 'fake-domain-from-mixin') self.factory = CaseFactory(domain=self.domain) self.person_id = u"person" self.occurrence_id = u"occurrence" self.episode_id = u"episode" self.primary_phone_number = "0123456789" self.secondary_phone_number = "0999999999" @property def person(self): return CaseStructure( case_id=self.person_id, attrs={ "case_type": "person", "create": True, "update": { 'name': "Pippin", 'aadhaar_number': "499118665246", PRIMARY_PHONE_NUMBER: self.primary_phone_number, BACKUP_PHONE_NUMBER: self.secondary_phone_number, 'merm_id': "123456789", 'dob': "1987-08-15", } }, ) @property def occurrence(self): return CaseStructure( case_id=self.occurrence_id, attrs={ 'create': True, 'case_type': 'occurrence', "update": dict( name="Occurrence #1", ) }, indices=[CaseIndex( self.person, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=self.person.attrs['case_type'], )], ) @property def episode(self): return CaseStructure( case_id=self.episode_id, attrs={ 'create': True, 'case_type': 'episode', "update": dict( person_name="Pippin", opened_on=datetime(1989, 6, 11, 0, 0), patient_type="new", hiv_status="reactive", episode_type="confirmed_tb", default_adherence_confidence="high", ) }, indices=[CaseIndex( self.occurrence, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=self.occurrence.attrs['case_type'], )], ) def create_case(self, case): return self.factory.create_or_update_cases([case]) def create_case_structure(self): return {case.case_id: case for case in self.factory.create_or_update_cases([self.episode])} def create_adherence_cases(self, adherence_dates): return self.factory.create_or_update_cases([ CaseStructure( case_id=adherence_date.strftime('%Y-%m-%d'), attrs={ "case_type": "adherence", "create": True, "update": { "name": adherence_date, "adherence_value": "unobserved_dose", "adherence_source": "99DOTS", "adherence_date": adherence_date, "person_name": "Pippin", "adherence_confidence": "medium", "shared_number_99_dots": False, }, }, indices=[CaseIndex( CaseStructure(case_id=self.episode_id, attrs={"create": False}), identifier='host', relationship=CASE_INDEX_EXTENSION, related_type='episode', )], walk_related=False, ) for adherence_date in adherence_dates ])
class ENikshayCaseStructureMixin(object): def setUp(self): super(ENikshayCaseStructureMixin, self).setUp() delete_all_users() self.domain = getattr(self, 'domain', 'fake-domain-from-mixin') self.factory = CaseFactory(domain=self.domain) self.user = CommCareUser.create( self.domain, "jon-snow@user", "123", ) self.person_id = u"person" self.occurrence_id = u"occurrence" self.episode_id = u"episode" self.primary_phone_number = "0123456789" self.secondary_phone_number = "0999999999" self.treatment_supporter_phone = "066000666" def tearDown(self): delete_all_users() super(ENikshayCaseStructureMixin, self).tearDown() @property def person(self): return CaseStructure( case_id=self.person_id, attrs={ "case_type": "person", "user_id": self.user.user_id, "create": True, "owner_id": uuid.uuid4().hex, "update": { 'name': "Peregrine Took", PERSON_FIRST_NAME: "Peregrine", PERSON_LAST_NAME: "Took", 'aadhaar_number': "499118665246", PRIMARY_PHONE_NUMBER: self.primary_phone_number, BACKUP_PHONE_NUMBER: self.secondary_phone_number, MERM_ID: "123456789", 'dob': "1987-08-15", 'age': '20', 'sex': 'male', 'current_address': 'Mr. Everest', 'secondary_contact_name_address': 'Mrs. Everestie', 'previous_tb_treatment': 'yes', 'nikshay_registered': "false", } }, ) @property def occurrence(self): return CaseStructure( case_id=self.occurrence_id, attrs={ 'create': True, 'case_type': 'occurrence', "update": dict(name="Occurrence #1", ) }, indices=[ CaseIndex( self.person, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=self.person.attrs['case_type'], ) ], ) @property def episode(self): return CaseStructure( case_id=self.episode_id, attrs={ 'create': True, 'case_type': 'episode', "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': 'Peregrine Took', 'site_choice': 'pleural_effusion', 'treatment_supporter_designation': 'ngo_volunteer', TREATMENT_START_DATE: "2015-03-03", TREATMENT_SUPPORTER_FIRST_NAME: "Gandalf", TREATMENT_SUPPORTER_LAST_NAME: "The Grey", TREATMENT_SUPPORTER_PHONE: self.treatment_supporter_phone, WEIGHT_BAND: "adult_55-69" } }, indices=[ CaseIndex( self.occurrence, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=self.occurrence.attrs['case_type'], ) ], ) def create_case(self, case): return self.factory.create_or_update_cases([case]) def create_case_structure(self): return { case.case_id: case for case in self.factory.create_or_update_cases([self.episode]) } def create_adherence_cases(self, adherence_dates, adherence_source='99DOTS'): return self.factory.create_or_update_cases([ CaseStructure( case_id=adherence_date.strftime('%Y-%m-%d'), attrs={ "case_type": "adherence", "create": True, "update": { "name": adherence_date, "adherence_value": "unobserved_dose", "adherence_source": adherence_source, "adherence_date": adherence_date, "person_name": "Pippin", "adherence_confidence": "medium", "shared_number_99_dots": False, }, }, indices=[ CaseIndex( CaseStructure(case_id=self.episode_id, attrs={"create": False}), identifier='host', relationship=CASE_INDEX_EXTENSION, related_type='episode', ) ], walk_related=False, ) for adherence_date in adherence_dates ])
class TestCasePropertyChanged(TestCase): def setUp(self): self.domain = "isildur" self.factory = CaseFactory(self.domain) self.case = self.factory.create_case(owner_id='owner', case_name="Aragorn", update={"sword": "Narsil"}) self.other_case = self.factory.create_case() def tearDown(self): delete_all_xforms() delete_all_cases() @run_with_all_backends def test_date_case_property_changed(self): updated_on = datetime(2015, 5, 3, 12, 11) # submit 2 updates self.factory.create_or_update_case( CaseStructure( self.case.case_id, attrs={ "update": { 'abc': "updated" }, "date_modified": updated_on }), ) self.factory.create_or_update_case( CaseStructure( self.case.case_id, attrs={ "update": { 'bcd': "updated" }, }), ) case = CaseAccessors(self.domain).get_case(self.case.case_id) self.assertEqual( updated_on.replace(tzinfo=pytz.UTC), get_datetime_case_property_changed(case, "abc", "updated") ) @run_with_all_backends def test_multiple_cases_in_update(self): day_1 = datetime(2015, 5, 1, 12, 11) day_2 = datetime(2015, 5, 2, 12, 11) # Submit two updates TOGETHER, one for this case, but irrelevant, # and one for another case, but touching the same property self.factory.create_or_update_cases([ CaseStructure( self.case.case_id, attrs={ "update": { 'not_relevant': "updated" }, "date_modified": day_1, }), CaseStructure( self.other_case.case_id, attrs={ "update": { 'relevant_property': "updated" }, "date_modified": day_1, }), ]) # Submit an update that DOES modify the relevant property self.factory.create_or_update_case( CaseStructure( self.case.case_id, attrs={ "update": { 'relevant_property': "updated" }, "date_modified": day_2, }), ) case = CaseAccessors(self.domain).get_case(self.case.case_id) self.assertEqual( day_2.replace(tzinfo=pytz.UTC), get_datetime_case_property_changed(case, "relevant_property", "updated") ) @run_with_all_backends def test_owner_id_changed(self): changes, _ = get_paged_changes_to_case_property(self.case, 'owner_id') self.assertEqual(len(changes), 1) self.assertEqual(changes[0].new_value, 'owner') self.factory.create_or_update_case( CaseStructure( self.case.case_id, attrs={ "update": { 'owner_id': 'new_owner' }, }), ) case = CaseAccessors(self.domain).get_case(self.case.case_id) changes, _ = get_paged_changes_to_case_property(case, 'owner_id') self.assertEqual(len(changes), 2) self.assertEqual(changes[0].new_value, 'new_owner') self.assertEqual(changes[1].new_value, 'owner') @run_with_all_backends def test_name_changed(self): self.factory.create_or_update_case( CaseStructure( self.case.case_id, attrs={ "update": { 'name': 'Strider' }, }), ) case = CaseAccessors(self.domain).get_case(self.case.case_id) changes, _ = get_paged_changes_to_case_property(case, 'name') self.assertEqual(len(changes), 2) self.assertEqual(changes[0].new_value, 'Strider') self.assertEqual(changes[1].new_value, 'Aragorn') @run_with_all_backends def test_blank_change(self): self.factory.create_or_update_case( CaseStructure( self.case.case_id, attrs={ "update": { 'sword': '' }, }), ) case = CaseAccessors(self.domain).get_case(self.case.case_id) changes, _ = get_paged_changes_to_case_property(case, 'sword') self.assertEqual(len(changes), 2) self.assertEqual(changes[0].new_value, '') self.assertEqual(changes[1].new_value, 'Narsil') @run_with_all_backends def test_case_rebuild(self): # Cases with rebuild actions were failing because rebuild actions have no form # https://manage.dimagi.com/default.asp?276216#1494409 self.factory.create_or_update_case( CaseStructure( self.case.case_id, attrs={ "update": { 'sword': '' }, }), ) rebuild_case_from_forms(self.domain, self.case.case_id, RebuildWithReason()) case = CaseAccessors(self.domain).get_case(self.case.case_id) changes, _ = get_paged_changes_to_case_property(case, 'sword') self.assertEqual(len(changes), 2) self.assertEqual(changes[0].new_value, '') self.assertEqual(changes[1].new_value, 'Narsil')
class AdherenceCaseFactory(object): """ Creates and updates adherence cases for a given person Only for use by the 99DOTS integration with eNikshay """ DEFAULT_ADHERENCE_CONFIDENCE = "medium" ADHERENCE_CASE_TYPE = "adherence" DEFAULT_ADHERENCE_VALUE = "unobserved_dose" def __init__(self, domain, person_id): self.domain = domain self.person_id = person_id self.case_accessor = CaseAccessors(domain) self.case_factory = CaseFactory(domain) @property @memoized def _person_case(self): try: return self.case_accessor.get_case(self.person_id) except CaseNotFound: raise AdherenceException( "No patient exists with this beneficiary ID") @property @memoized def _default_adherence_confidence(self): return self._episode_case.dynamic_case_properties().get( 'default_adherence_confidence', self.DEFAULT_ADHERENCE_CONFIDENCE) @property @memoized def _episode_case(self): try: return get_open_episode_case_from_person(self.domain, self._person_case.case_id) except ENikshayCaseNotFound as e: raise AdherenceException(e.message) def create_adherence_cases(self, adherence_points): case_structures = [] for adherence_point in adherence_points: if adherence_point.get('MERM_TypeOfEvent') == "HEARTBEAT": continue case_structures.append( 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), }, 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, )) return self.case_factory.create_or_update_cases(case_structures) def _get_adherence_case_properties(self, adherence_point): return { "name": adherence_point.get("timestamp", None), "adherence_value": self.DEFAULT_ADHERENCE_VALUE, "adherence_source": adherence_point.get('adherenceSource', '99DOTS'), "adherence_date": self._parse_adherence_date(adherence_point["timestamp"]), "person_name": self._person_case.name, "adherence_confidence": self._default_adherence_confidence, "shared_number_99_dots": adherence_point.get("sharedNumber"), "merm_imei": adherence_point.get("MERM_IMEI"), "merm_extra_info": adherence_point.get("MERM_ExtraInformation"), } def _parse_adherence_date(self, iso_datestring): tz = timezone(ENIKSHAY_TIMEZONE) try: datetime_from_adherence = parser.parse(iso_datestring) datetime_in_india = datetime_from_adherence.astimezone(tz) except ValueError: raise AdherenceException( "Adherence date should be an ISO8601 formated string with timezone information." ) return datetime_in_india.date() def update_adherence_cases(self, start_date, end_date, confidence_level): try: adherence_cases = get_adherence_cases_between_dates( self.domain, self.person_id, start_date, end_date) except ENikshayCaseNotFound as e: raise AdherenceException(e.message) adherence_case_ids = [case.case_id for case in adherence_cases]
def handle(self, domain, migration_comment, **options): if not settings.UNIT_TESTING: raise CommandError( 'must migrate case data from phone_number to contact_phone_number before running' ) base_query = PatientDetail.objects.order_by('scode', 'Dtocode', 'Tbunitcode', 'PHI') if options['location_codes']: location_filter = Q() for location_code in options['location_codes']: codes = location_code.split('-') assert 1 <= len(codes) <= 4 q = Q(scode=codes[0]) if len(codes) > 1: q = q & Q(Dtocode=codes[1]) if len(codes) > 2: q = q & Q(Tbunitcode=int(codes[2])) if len(codes) > 3: q = q & Q(PHI=int(codes[3])) location_filter = location_filter | q base_query = base_query.filter(location_filter) if options['nikshay_ids']: base_query = base_query.filter(PregId__in=options['nikshay_ids']) start = options['start'] limit = options['limit'] chunk_size = options['chunk_size'] test_phi = options['test_phi'] if test_phi: logger.warning("** USING TEST PHI ID **") if limit is not None: patient_details = base_query[start:start + limit] else: patient_details = base_query[start:] total = patient_details.count() counter = 0 num_succeeded = 0 num_failed = 0 num_matching_case_not_migrated = 0 logger.info('Starting migration of %d patient cases on domain %s.' % (total, domain)) nikshay_codes_to_location = get_nikshay_codes_to_location(domain) factory = CaseFactory(domain=domain) case_structures = [] for patient_detail in patient_details: counter += 1 try: case_factory = EnikshayCaseFactory(domain, migration_comment, patient_detail, nikshay_codes_to_location, test_phi) case_structures.extend( case_factory.get_case_structures_to_create()) except MatchingNikshayIdCaseNotMigrated: num_matching_case_not_migrated += 1 logger.error( 'Matching case not migrated for %d of %d. Nikshay ID=%s' % (counter, total, patient_detail.PregId)) except Exception: num_failed += 1 logger.error( 'Failed on %d of %d. Nikshay ID=%s' % (counter, total, patient_detail.PregId), exc_info=True, ) else: num_succeeded += 1 if num_succeeded % chunk_size == 0: logger.info('committing cases {}-{}...'.format( num_succeeded - chunk_size, num_succeeded)) factory.create_or_update_cases(case_structures) case_structures = [] logger.info('done') logger.info('Succeeded on %s of %d. Nikshay ID=%s' % (counter, total, patient_detail.PregId)) if case_structures: logger.info('committing final cases...'.format( num_succeeded - chunk_size, num_succeeded)) factory.create_or_update_cases(case_structures) logger.info('Done creating cases for domain %s.' % domain) logger.info('Number of attempts: %d.' % counter) logger.info('Number of successes: %d.' % num_succeeded) logger.info('Number of failures: %d.' % num_failed) logger.info('Number of cases matched but not migrated: %d.' % num_matching_case_not_migrated) # since we circumvented cleanliness checks just call this at the end logger.info('Setting cleanliness flags') set_cleanliness_flags_for_domain(domain, force_full=True, raise_soft_assertions=False) logger.info('Done!')
class AutoCloseExtensionsTest(TestCase): def setUp(self): FormProcessorTestUtils.delete_all_cases() FormProcessorTestUtils.delete_all_xforms() delete_all_users() self.domain = "domain" self.project = Domain(name=self.domain) self.user = create_restore_user(self.domain, username='******', password="******") self.factory = CaseFactory(domain=self.domain) self.extension_ids = ['1', '2', '3'] self.host_id = 'host' def tearDown(self): FormProcessorTestUtils.delete_all_cases() FormProcessorTestUtils.delete_all_xforms() delete_all_users() def _create_extension_chain(self): host = CaseStructure(case_id=self.host_id) extension = CaseStructure( case_id=self.extension_ids[0], indices=[CaseIndex( related_structure=host, relationship="extension", )], ) extension_2 = CaseStructure( case_id=self.extension_ids[1], indices=[CaseIndex( related_structure=extension, relationship="extension", )], ) extension_3 = CaseStructure( case_id=self.extension_ids[2], indices=[CaseIndex( related_structure=extension_2, relationship="extension", )], ) return self.factory.create_or_update_cases([extension_3]) def _create_extension_loop(self): extension_3 = CaseStructure(case_id=self.extension_ids[2]) host = CaseStructure( case_id=self.host_id, indices=[CaseIndex( related_structure=extension_3, relationship="extension", )], ) return self.factory.create_or_update_cases([host]) def _create_host_is_subcase_chain(self): parent = CaseStructure(case_id='parent') host = CaseStructure( case_id=self.host_id, indices=[CaseIndex( related_structure=parent, relationship="child", )], ) extension = CaseStructure( case_id=self.extension_ids[0], indices=[CaseIndex( related_structure=host, relationship="extension", )], ) extension_2 = CaseStructure( case_id=self.extension_ids[1], indices=[CaseIndex( related_structure=extension, relationship="extension", )], ) return self.factory.create_or_update_cases([extension_2]) @run_with_all_backends def test_get_extension_chain_simple(self): host = CaseStructure(case_id=self.host_id) extension = CaseStructure( case_id=self.extension_ids[0], indices=[CaseIndex( related_structure=host, relationship="extension", )], ) self.factory.create_or_update_cases([extension]) self.assertEqual( set(self.extension_ids[0]), CaseAccessors(self.domain).get_extension_chain([self.host_id]) ) @run_with_all_backends def test_get_extension_chain_multiple(self): created_cases = self._create_extension_chain() self.assertEqual( set(self.extension_ids), CaseAccessors(self.domain).get_extension_chain([created_cases[-1].case_id]) ) @run_with_all_backends def test_get_extension_chain_circular_ref(self): """If there is a circular reference, this should not hang forever """ self._create_extension_chain() self._create_extension_loop() self.assertEqual( set([self.host_id] + self.extension_ids), CaseAccessors(self.domain).get_extension_chain([self.extension_ids[2]]) ) @flag_enabled('EXTENSION_CASES_SYNC_ENABLED') @run_with_all_backends def test_get_extension_to_close(self): """should return empty if case is not a host, otherwise should return full chain""" created_cases = self._create_extension_chain() # host open, should be empty no_cases = get_extensions_to_close(created_cases[-1], self.domain) self.assertEqual(set(), no_cases) created_cases[-1] = self.factory.create_or_update_case(CaseStructure( case_id=self.host_id, attrs={'close': True} ))[0] # host closed, should get full chain full_chain = get_extensions_to_close(created_cases[-1], self.domain) self.assertEqual(set(self.extension_ids), full_chain) # extension (not a host), should be empty no_cases = get_extensions_to_close(created_cases[2], self.domain) self.assertEqual(set(), no_cases) @flag_enabled('EXTENSION_CASES_SYNC_ENABLED') @run_with_all_backends def test_get_extension_to_close_child_host(self): """should still return extension chain if outgoing index is a child index""" created_cases = self._create_host_is_subcase_chain() # host open, should be empty no_cases = get_extensions_to_close(created_cases[-1], self.domain) self.assertEqual(set(), no_cases) # close parent, shouldn't get extensions created_cases[-1] = self.factory.create_or_update_case(CaseStructure( case_id='parent', attrs={'close': True} ))[0] no_cases = get_extensions_to_close(created_cases[-1], self.domain) self.assertEqual(set(), no_cases) # close host that is also a child created_cases[-2] = self.factory.create_or_update_case(CaseStructure( case_id=self.host_id, attrs={'close': True} ))[0] full_chain = get_extensions_to_close(created_cases[-2], self.domain) self.assertEqual(set(self.extension_ids[0:2]), full_chain) @flag_enabled('EXTENSION_CASES_SYNC_ENABLED') @run_with_all_backends def test_close_cases_host(self): """Closing a host should close all the extensions""" self._create_extension_chain() cases = CaseAccessors(self.domain).get_cases(self.extension_ids) self.assertFalse(cases[0].closed) self.assertFalse(cases[1].closed) self.assertFalse(cases[2].closed) self.factory.create_or_update_case(CaseStructure( case_id=self.extension_ids[0], attrs={'close': True} )) cases = { case.case_id: case.closed for case in CaseAccessors(self.domain).get_cases([self.host_id] + self.extension_ids) } self.assertFalse(cases[self.host_id]) self.assertTrue(cases[self.extension_ids[0]]) self.assertFalse(cases[self.extension_ids[1]]) self.assertFalse(cases[self.extension_ids[2]]) self.factory.create_or_update_case(CaseStructure( case_id=self.host_id, attrs={'close': True} )) cases = { case.case_id: case.closed for case in CaseAccessors(self.domain).get_cases([self.host_id] + self.extension_ids) } self.assertTrue(cases[self.host_id]) self.assertTrue(cases[self.extension_ids[0]]) self.assertTrue(cases[self.extension_ids[1]]) self.assertTrue(cases[self.extension_ids[2]]) @flag_enabled('EXTENSION_CASES_SYNC_ENABLED') @run_with_all_backends def test_close_cases_child(self): """Closing a host that is also a child should close all the extensions""" self._create_host_is_subcase_chain() cases = { case.case_id: case.closed for case in CaseAccessors(self.domain).get_cases([self.host_id] + self.extension_ids) } self.assertFalse(cases[self.host_id]) self.assertFalse(cases[self.extension_ids[0]]) self.assertFalse(cases[self.extension_ids[1]]) self.factory.create_or_update_case(CaseStructure( case_id=self.host_id, attrs={'close': True} )) cases = { case.case_id: case.closed for case in CaseAccessors(self.domain).get_cases(['parent', self.host_id] + self.extension_ids) } self.assertFalse(cases['parent']) self.assertTrue(cases[self.host_id]) self.assertTrue(cases[self.extension_ids[0]]) self.assertTrue(cases[self.extension_ids[1]])
class AutoCloseExtensionsTest(TestCase): def setUp(self): super(AutoCloseExtensionsTest, self).setUp() FormProcessorTestUtils.delete_all_cases() FormProcessorTestUtils.delete_all_xforms() delete_all_users() self.domain = "domain" self.project = Domain(name=self.domain) self.user = create_restore_user(self.domain, username='******', password="******") self.factory = CaseFactory(domain=self.domain) self.extension_ids = ['1', '2', '3'] self.host_id = 'host' def tearDown(self): FormProcessorTestUtils.delete_all_cases() FormProcessorTestUtils.delete_all_xforms() delete_all_users() super(AutoCloseExtensionsTest, self).tearDown() def _create_extension_chain(self): host = CaseStructure(case_id=self.host_id) extension = CaseStructure( case_id=self.extension_ids[0], indices=[CaseIndex( related_structure=host, relationship="extension", )], ) extension_2 = CaseStructure( case_id=self.extension_ids[1], indices=[CaseIndex( related_structure=extension, relationship="extension", )], ) extension_3 = CaseStructure( case_id=self.extension_ids[2], indices=[CaseIndex( related_structure=extension_2, relationship="extension", )], ) return self.factory.create_or_update_cases([extension_3]) def _create_extension_loop(self): extension_3 = CaseStructure(case_id=self.extension_ids[2]) host = CaseStructure( case_id=self.host_id, indices=[CaseIndex( related_structure=extension_3, relationship="extension", )], ) return self.factory.create_or_update_cases([host]) def _create_host_is_subcase_chain(self): parent = CaseStructure(case_id='parent') host = CaseStructure( case_id=self.host_id, indices=[CaseIndex( related_structure=parent, relationship="child", )], ) extension = CaseStructure( case_id=self.extension_ids[0], indices=[CaseIndex( related_structure=host, relationship="extension", )], ) extension_2 = CaseStructure( case_id=self.extension_ids[1], indices=[CaseIndex( related_structure=extension, relationship="extension", )], ) return self.factory.create_or_update_cases([extension_2]) @run_with_all_backends def test_get_extension_chain_simple(self): host = CaseStructure(case_id=self.host_id) extension = CaseStructure( case_id=self.extension_ids[0], indices=[CaseIndex( related_structure=host, relationship="extension", )], ) self.factory.create_or_update_cases([extension]) self.assertEqual( set(self.extension_ids[0]), CaseAccessors(self.domain).get_extension_chain([self.host_id]) ) @run_with_all_backends def test_get_extension_chain_multiple(self): created_cases = self._create_extension_chain() self.assertEqual( set(self.extension_ids), CaseAccessors(self.domain).get_extension_chain([created_cases[-1].case_id]) ) @run_with_all_backends def test_get_extension_chain_circular_ref(self): """If there is a circular reference, this should not hang forever """ self._create_extension_chain() self._create_extension_loop() self.assertEqual( set([self.host_id] + self.extension_ids), CaseAccessors(self.domain).get_extension_chain([self.extension_ids[2]]) ) @flag_enabled('EXTENSION_CASES_SYNC_ENABLED') @run_with_all_backends def test_get_extension_to_close(self): """should return empty if case is not a host, otherwise should return full chain""" created_cases = self._create_extension_chain() # host open, should be empty no_cases = get_extensions_to_close(created_cases[-1], self.domain) self.assertEqual(set(), no_cases) created_cases[-1] = self.factory.create_or_update_case(CaseStructure( case_id=self.host_id, attrs={'close': True} ))[0] # host closed, should get full chain full_chain = get_extensions_to_close(created_cases[-1], self.domain) self.assertEqual(set(self.extension_ids), full_chain) # extension (not a host), should be empty no_cases = get_extensions_to_close(created_cases[2], self.domain) self.assertEqual(set(), no_cases) @flag_enabled('EXTENSION_CASES_SYNC_ENABLED') @run_with_all_backends def test_get_extension_to_close_child_host(self): """should still return extension chain if outgoing index is a child index""" created_cases = self._create_host_is_subcase_chain() # host open, should be empty no_cases = get_extensions_to_close(created_cases[-1], self.domain) self.assertEqual(set(), no_cases) # close parent, shouldn't get extensions created_cases[-1] = self.factory.create_or_update_case(CaseStructure( case_id='parent', attrs={'close': True} ))[0] no_cases = get_extensions_to_close(created_cases[-1], self.domain) self.assertEqual(set(), no_cases) # close host that is also a child created_cases[-2] = self.factory.create_or_update_case(CaseStructure( case_id=self.host_id, attrs={'close': True} ))[0] full_chain = get_extensions_to_close(created_cases[-2], self.domain) self.assertEqual(set(self.extension_ids[0:2]), full_chain) @flag_enabled('EXTENSION_CASES_SYNC_ENABLED') @run_with_all_backends def test_close_cases_host(self): """Closing a host should close all the extensions""" self._create_extension_chain() cases = CaseAccessors(self.domain).get_cases(self.extension_ids) self.assertFalse(cases[0].closed) self.assertFalse(cases[1].closed) self.assertFalse(cases[2].closed) self.factory.create_or_update_case(CaseStructure( case_id=self.extension_ids[0], attrs={'close': True} )) cases = { case.case_id: case.closed for case in CaseAccessors(self.domain).get_cases([self.host_id] + self.extension_ids) }
def migrate_to_enikshay(domain, migration_comment, beneficiaries, skip_adherence, chunk_size, location_owner, default_location_owner, dry_run): total = beneficiaries.count() counter = 0 num_succeeded = 0 num_failed = 0 num_failed_chunks = 0 logger.info('Starting migration of %d patients in domain %s.' % (total, domain)) if dry_run: logger.info('Dry run, exiting...') return factory = CaseFactory(domain=domain) case_structures = [] for beneficiary in beneficiaries: counter += 1 try: case_factory = BeneficiaryCaseFactory( domain, migration_comment, beneficiary, location_owner, default_location_owner ) case_structures.extend(case_factory.get_case_structures_to_create(skip_adherence)) except Exception: num_failed += 1 logger.error( 'Failed on %d of %d. Case ID=%s' % ( counter, total, beneficiary.caseId ), exc_info=True, ) else: num_succeeded += 1 if num_succeeded % chunk_size == 0: logger.info('%d cases to save.' % len(case_structures)) logger.info('committing beneficiaries {}-{}...'.format( num_succeeded - chunk_size + 1, num_succeeded )) try: factory.create_or_update_cases(case_structures) except Exception: num_failed_chunks += 1 logger.error( 'Failure writing case structures', exc_info=True, ) case_structures = [] logger.info('done') logger.info( 'Succeeded on %s of %d. Case ID=%s' % ( counter, total, beneficiary.caseId ) ) if case_structures: logger.info('committing final cases...'.format(num_succeeded - chunk_size, num_succeeded)) factory.create_or_update_cases(case_structures) logger.info('Done creating cases for domain %s.' % domain) logger.info('Number of attempts: %d.' % counter) logger.info('Number of successes: %d.' % num_succeeded) logger.info('Number of failures: %d.' % num_failed) logger.info('Number of chunks to fail writing: %d' % num_failed_chunks) # since we circumvented cleanliness checks just call this at the end logger.info('Setting cleanliness flags') set_cleanliness_flags_for_domain(domain, force_full=True, raise_soft_assertions=False) logger.info('Done!')
def handle(self, domain, **options): base_query = Beneficiary.objects.filter( caseStatus__in=['suspect', 'patient', 'patient '], ) if options['nikshayId']: base_query = base_query.filter(nikshayId=options['nikshayId']) start = options['start'] limit = options['limit'] chunk_size = options['chunk_size'] if limit is not None: beneficiaries = base_query[start:start + limit] else: beneficiaries = base_query[start:] # Assert never null assert not beneficiaries.filter(firstName__isnull=True).exists() assert not beneficiaries.filter(lastName__isnull=True).exists() assert not beneficiaries.filter(phoneNumber__isnull=True).exists() assert not Episode.objects.filter( dateOfDiagnosis__isnull=True).exists() assert not Episode.objects.filter(patientWeight__isnull=True).exists() assert not Episode.objects.filter(rxStartDate__isnull=True).exists() assert not Episode.objects.filter(site__isnull=True).exists() assert not Adherence.objects.filter(creationDate__isnull=True).exists() # Assert always null assert not beneficiaries.filter(mdrTBSuspected__isnull=False).exists() assert not beneficiaries.filter(middleName__isnull=False).exists() assert not beneficiaries.filter(nikshayId__isnull=False).exists() assert not beneficiaries.filter(symptoms__isnull=False).exists() assert not beneficiaries.filter(tsType__isnull=False).exists() assert not Episode.objects.filter(phoneNumber__isnull=False).exists() total = beneficiaries.count() counter = 0 num_succeeded = 0 num_failed = 0 logger.info('Starting migration of %d patients in domain %s.' % (total, domain)) factory = CaseFactory(domain=domain) case_structures = [] for beneficiary in beneficiaries: counter += 1 try: case_factory = BeneficiaryCaseFactory(domain, beneficiary) case_structures.extend( case_factory.get_case_structures_to_create()) except Exception: num_failed += 1 logger.error( 'Failed on %d of %d. Nikshay ID=%s' % (counter, total, beneficiary.nikshayId), exc_info=True, ) else: num_succeeded += 1 if num_succeeded % chunk_size == 0: logger.info('committing cases {}-{}...'.format( num_succeeded - chunk_size, num_succeeded)) factory.create_or_update_cases(case_structures) case_structures = [] logger.info('done') logger.info('Succeeded on %s of %d. Nikshay ID=%s' % (counter, total, beneficiary.nikshayId)) if case_structures: logger.info('committing final cases...'.format( num_succeeded - chunk_size, num_succeeded)) factory.create_or_update_cases(case_structures) logger.info('Done creating cases for domain %s.' % domain) logger.info('Number of attempts: %d.' % counter) logger.info('Number of successes: %d.' % num_succeeded) logger.info('Number of failures: %d.' % num_failed) # since we circumvented cleanliness checks just call this at the end logger.info('Setting cleanliness flags') set_cleanliness_flags_for_domain(domain, force_full=True, raise_soft_assertions=False) logger.info('Done!')
class TestExtensionCaseIds(TestCase): def setUp(self): super(TestExtensionCaseIds, self).setUp() self.domain = 'domain' FormProcessorTestUtils.delete_all_cases() self.factory = CaseFactory(self.domain) def tearDown(self): if settings.USE_PARTITIONED_DATABASE: FormProcessorTestUtils.delete_all_cases() FormProcessorTestUtils.delete_all_xforms() super(TestExtensionCaseIds, self).tearDown() def test_no_extensions(self): """ Returns empty when there are other index types """ parent_id = uuid.uuid4().hex child_id = uuid.uuid4().hex parent = CaseStructure(case_id=parent_id, attrs={'create': True}) self.factory.create_or_update_case( CaseStructure( case_id=child_id, indices=[CaseIndex(parent, relationship=CASE_INDEX_CHILD)], attrs={'create': True})) returned_cases = CommCareCaseIndex.objects.get_extension_case_ids( self.domain, [parent_id]) self.assertEqual(returned_cases, []) 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_extension_of_multiple_hosts_returned(self): """ Should return an extension from any host if there are multiple indices """ host_id = uuid.uuid4().hex host_2_id = uuid.uuid4().hex parent_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id, attrs={'create': True}) host_2 = CaseStructure(case_id=host_2_id, attrs={'create': True}) parent = CaseStructure(case_id=parent_id, attrs={'create': True}) self.factory.create_or_update_case( CaseStructure(case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), CaseIndex(host_2, relationship=CASE_INDEX_EXTENSION, identifier="host_2"), CaseIndex(parent, relationship=CASE_INDEX_CHILD), ], attrs={'create': True})) returned_cases = CommCareCaseIndex.objects.get_extension_case_ids( self.domain, [host_2_id]) self.assertItemsEqual(returned_cases, [extension_id]) returned_cases = CommCareCaseIndex.objects.get_extension_case_ids( self.domain, [host_id]) self.assertItemsEqual(returned_cases, [extension_id]) def test_host_with_multiple_extensions(self): """ Return all extensions from a single host """ host_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex extension_2_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id, attrs={'create': True}) self.factory.create_or_update_cases([ CaseStructure(case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), ], attrs={'create': True}), CaseStructure(case_id=extension_2_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), ], attrs={'create': True}), ]) returned_cases = CommCareCaseIndex.objects.get_extension_case_ids( self.domain, [host_id]) self.assertItemsEqual(returned_cases, [extension_id, extension_2_id]) def test_extensions_from_list(self): """ Given a list of hosts, should return all extensions """ host_id = uuid.uuid4().hex host_2_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex extension_2_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id, attrs={'create': True}) host_2 = CaseStructure(case_id=host_2_id, attrs={'create': True}) self.factory.create_or_update_case( CaseStructure(case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), ], attrs={'create': True})) self.factory.create_or_update_case( CaseStructure(case_id=extension_2_id, indices=[ CaseIndex(host_2, relationship=CASE_INDEX_EXTENSION, identifier="host"), ], attrs={'create': True})) returned_cases = CommCareCaseIndex.objects.get_extension_case_ids( self.domain, [host_id, host_2_id]) self.assertItemsEqual(returned_cases, [extension_id, extension_2_id])
def handle(self, domain, **options): base_query = PatientDetail.objects.filter( PregId__startswith=options['startswith'], ).order_by('PregId') start = options['start'] limit = options['limit'] chunk_size = options['chunk_size'] test_phi = options['test_phi'] if test_phi: logger.warning("** USING TEST PHI ID **") if limit is not None: patient_details = base_query[start:start + limit] else: patient_details = base_query[start:] total = patient_details.count() counter = 0 num_succeeded = 0 num_failed = 0 logger.info('Starting migration of %d patient cases on domain %s.' % (total, domain)) nikshay_codes_to_location = get_nikshay_codes_to_location(domain) factory = CaseFactory(domain=domain) case_structures = [] for patient_detail in patient_details: counter += 1 try: case_factory = EnikshayCaseFactory( domain, patient_detail, nikshay_codes_to_location, test_phi ) case_structures.extend(case_factory.get_case_structures_to_create()) except Exception: num_failed += 1 logger.error( 'Failed on %d of %d. Nikshay ID=%s' % ( counter, total, patient_detail.PregId ), exc_info=True, ) else: num_succeeded += 1 if num_succeeded % chunk_size == 0: logger.info('committing cases {}-{}...'.format(num_succeeded - chunk_size, num_succeeded)) factory.create_or_update_cases(case_structures) case_structures = [] logger.info('done') logger.info( 'Succeeded on %s of %d. Nikshay ID=%s' % ( counter, total, patient_detail.PregId ) ) if case_structures: logger.info('committing final cases...'.format(num_succeeded - chunk_size, num_succeeded)) factory.create_or_update_cases(case_structures) logger.info('Done creating cases for domain %s.' % domain) logger.info('Number of attempts: %d.' % counter) logger.info('Number of successes: %d.' % num_succeeded) logger.info('Number of failures: %d.' % num_failed) # since we circumvented cleanliness checks just call this at the end logger.info('Setting cleanliness flags') set_cleanliness_flags_for_domain(domain, force_full=True) logger.info('Done!')
class TestExtensionCaseIds(TestCase): def setUp(self): super(TestExtensionCaseIds, self).setUp() self.domain = 'domain' FormProcessorTestUtils.delete_all_cases() self.factory = CaseFactory(self.domain) def tearDown(self): FormProcessorTestUtils.delete_all_cases() FormProcessorTestUtils.delete_all_xforms() super(TestExtensionCaseIds, self).tearDown() @run_with_all_backends def test_no_extensions(self): """ Returns empty when there are other index types """ parent_id = uuid.uuid4().hex child_id = uuid.uuid4().hex parent = CaseStructure(case_id=parent_id) self.factory.create_or_update_case( CaseStructure( case_id=child_id, indices=[CaseIndex(parent, relationship=CASE_INDEX_CHILD)])) returned_cases = CaseAccessors(self.domain).get_extension_case_ids( [parent_id]) self.assertEqual(returned_cases, []) @run_with_all_backends 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) self.factory.create_or_update_case( CaseStructure( case_id=extension_id, indices=[CaseIndex(host, relationship=CASE_INDEX_EXTENSION)])) returned_cases = CaseAccessors(self.domain).get_extension_case_ids( [host_id]) self.assertItemsEqual(returned_cases, [extension_id]) @run_with_all_backends def test_extension_of_multiple_hosts_returned(self): """ Should return an extension from any host if there are multiple indices """ host_id = uuid.uuid4().hex host_2_id = uuid.uuid4().hex parent_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id) host_2 = CaseStructure(case_id=host_2_id) parent = CaseStructure(case_id=parent_id) self.factory.create_or_update_case( CaseStructure(case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), CaseIndex(host_2, relationship=CASE_INDEX_EXTENSION, identifier="host_2"), CaseIndex(parent, relationship=CASE_INDEX_CHILD), ])) returned_cases = CaseAccessors(self.domain).get_extension_case_ids( [host_2_id]) self.assertItemsEqual(returned_cases, [extension_id]) returned_cases = CaseAccessors(self.domain).get_extension_case_ids( [host_id]) self.assertItemsEqual(returned_cases, [extension_id]) @run_with_all_backends def test_host_with_multiple_extensions(self): """ Return all extensions from a single host """ host_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex extension_2_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id) self.factory.create_or_update_cases([ CaseStructure(case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), ]), CaseStructure(case_id=extension_2_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), ]), ]) returned_cases = CaseAccessors(self.domain).get_extension_case_ids( [host_id]) self.assertItemsEqual(returned_cases, [extension_id, extension_2_id]) @run_with_all_backends def test_extensions_from_list(self): """ Given a list of hosts, should return all extensions """ host_id = uuid.uuid4().hex host_2_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex extension_2_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id) host_2 = CaseStructure(case_id=host_2_id) self.factory.create_or_update_case( CaseStructure(case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), ])) self.factory.create_or_update_case( CaseStructure(case_id=extension_2_id, indices=[ CaseIndex(host_2, relationship=CASE_INDEX_EXTENSION, identifier="host"), ])) returned_cases = CaseAccessors(self.domain).get_extension_case_ids( [host_id, host_2_id]) self.assertItemsEqual(returned_cases, [extension_id, extension_2_id])
class TestExtensionCaseIds(TestCase): def setUp(self): super(TestExtensionCaseIds, self).setUp() self.domain = 'domain' FormProcessorTestUtils.delete_all_cases() self.factory = CaseFactory(self.domain) def tearDown(self): FormProcessorTestUtils.delete_all_cases() FormProcessorTestUtils.delete_all_xforms() super(TestExtensionCaseIds, self).tearDown() def test_no_extensions(self): """ Returns empty when there are other index types """ parent_id = uuid.uuid4().hex child_id = uuid.uuid4().hex parent = CaseStructure(case_id=parent_id, attrs={'create': True}) self.factory.create_or_update_case( CaseStructure( case_id=child_id, indices=[ CaseIndex(parent, relationship=CASE_INDEX_CHILD) ], attrs={'create': True} ) ) returned_cases = CaseAccessors(self.domain).get_extension_case_ids([parent_id]) self.assertEqual(returned_cases, []) 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 = CaseAccessors(self.domain).get_extension_case_ids([host_id]) self.assertItemsEqual(returned_cases, [extension_id]) def test_extension_of_multiple_hosts_returned(self): """ Should return an extension from any host if there are multiple indices """ host_id = uuid.uuid4().hex host_2_id = uuid.uuid4().hex parent_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id, attrs={'create': True}) host_2 = CaseStructure(case_id=host_2_id, attrs={'create': True}) parent = CaseStructure(case_id=parent_id, attrs={'create': True}) self.factory.create_or_update_case( CaseStructure( case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), CaseIndex(host_2, relationship=CASE_INDEX_EXTENSION, identifier="host_2"), CaseIndex(parent, relationship=CASE_INDEX_CHILD), ], attrs={'create': True} ) ) returned_cases = CaseAccessors(self.domain).get_extension_case_ids([host_2_id]) self.assertItemsEqual(returned_cases, [extension_id]) returned_cases = CaseAccessors(self.domain).get_extension_case_ids([host_id]) self.assertItemsEqual(returned_cases, [extension_id]) def test_host_with_multiple_extensions(self): """ Return all extensions from a single host """ host_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex extension_2_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id, attrs={'create': True}) self.factory.create_or_update_cases([ CaseStructure( case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), ], attrs={'create': True} ), CaseStructure( case_id=extension_2_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), ], attrs={'create': True} ), ] ) returned_cases = CaseAccessors(self.domain).get_extension_case_ids([host_id]) self.assertItemsEqual(returned_cases, [extension_id, extension_2_id]) def test_extensions_from_list(self): """ Given a list of hosts, should return all extensions """ host_id = uuid.uuid4().hex host_2_id = uuid.uuid4().hex extension_id = uuid.uuid4().hex extension_2_id = uuid.uuid4().hex host = CaseStructure(case_id=host_id, attrs={'create': True}) host_2 = CaseStructure(case_id=host_2_id, attrs={'create': True}) self.factory.create_or_update_case( CaseStructure( case_id=extension_id, indices=[ CaseIndex(host, relationship=CASE_INDEX_EXTENSION, identifier="host"), ], attrs={'create': True} ) ) self.factory.create_or_update_case( CaseStructure( case_id=extension_2_id, indices=[ CaseIndex(host_2, relationship=CASE_INDEX_EXTENSION, identifier="host"), ], attrs={'create': True} ) ) returned_cases = CaseAccessors(self.domain).get_extension_case_ids([host_id, host_2_id]) self.assertItemsEqual(returned_cases, [extension_id, extension_2_id])
class AdherenceCaseFactory(object): """ Creates and updates adherence cases for a given person Only for use by the 99DOTS integration with eNikshay """ DEFAULT_ADHERENCE_CONFIDENCE = "medium" ADHERENCE_CASE_TYPE = "adherence" DEFAULT_ADHERENCE_VALUE = "unobserved_dose" def __init__(self, domain, person_id): self.domain = domain self.person_id = person_id self.case_accessor = CaseAccessors(domain) self.case_factory = CaseFactory(domain) @property @memoized def _person_case(self): try: return self.case_accessor.get_case(self.person_id) except CaseNotFound: raise AdherenceException(message="No patient exists with this beneficiary ID") @property @memoized def _default_adherence_confidence(self): return self._episode_case.dynamic_case_properties().get( 'default_adherence_confidence', self.DEFAULT_ADHERENCE_CONFIDENCE ) @property @memoized def _episode_case(self): return get_open_episode_case(self.domain, self._person_case.case_id) 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 _get_adherence_case_properties(self, adherence_point, adherence_source): return { "name": adherence_point["timestamp"], "adherence_value": self.DEFAULT_ADHERENCE_VALUE, "adherence_source": adherence_source, "adherence_date": adherence_point["timestamp"], "person_name": self._person_case.name, "adherence_confidence": self._default_adherence_confidence, "shared_number_99_dots": adherence_point["sharedNumber"], } def update_adherence_cases(self, start_date, end_date, confidence_level): adherence_cases = get_adherence_cases_between_dates(self.domain, self.person_id, start_date, end_date) adherence_case_ids = [case.case_id for case in adherence_cases]
class GetCaseFootprintInfoTest(TestCase): @classmethod def setUpClass(cls): super(GetCaseFootprintInfoTest, cls).setUpClass() delete_all_cases() def setUp(self): super(GetCaseFootprintInfoTest, self).setUp() self.domain = 'domain' self.owner_id = uuid.uuid4().hex self.other_owner_id = uuid.uuid4().hex self.factory = CaseFactory(self.domain) @run_with_all_backends def test_simple_footprint(self): """ should only return open cases from user """ case = CaseStructure(case_id=uuid.uuid4().hex, attrs={'owner_id': self.owner_id}) closed_case = CaseStructure(case_id=uuid.uuid4().hex, attrs={'owner_id': self.owner_id, 'close': True}) other_case = CaseStructure(case_id=uuid.uuid4().hex, attrs={'owner_id': self.other_owner_id}) self.factory.create_or_update_cases([case, other_case, closed_case]) footprint_info = get_case_footprint_info(self.domain, self.owner_id) self.assertEqual(footprint_info.all_ids, set([case.case_id])) @run_with_all_backends 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} ) child = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.owner_id}, 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])) @run_with_all_backends def test_footprint_with_extension(self): """ Extensions are brought in if the host case is owned; Host case is brought in if the extension is owned """ 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)] ) self.factory.create_or_update_cases([host, extension]) footprint_info = get_case_footprint_info(self.domain, self.owner_id) self.assertEqual(footprint_info.all_ids, set([extension.case_id, host.case_id])) self.assertEqual(footprint_info.base_ids, set([host.case_id])) footprint_info = get_case_footprint_info(self.domain, self.other_owner_id) self.assertEqual(footprint_info.all_ids, set([extension.case_id, host.case_id])) self.assertEqual(footprint_info.base_ids, set([extension.case_id])) @run_with_all_backends def test_footprint_with_extension_of_parent(self): """ Extensions of parents should be included """ parent = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.other_owner_id, 'close': True} ) child = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.owner_id}, indices=[CaseIndex(parent)] ) extension = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.other_owner_id}, indices=[CaseIndex(parent, 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])) @run_with_all_backends 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, 'close': True} ) child = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.owner_id}, indices=[CaseIndex(parent)] ) extension = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.other_owner_id}, 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])) @run_with_all_backends def test_cousins(self): """http://manage.dimagi.com/default.asp?189528 """ grandparent = CaseStructure( case_id="Steffon", attrs={'owner_id': self.other_owner_id} ) parent_1 = CaseStructure( case_id="Stannis", attrs={'owner_id': self.other_owner_id}, indices=[CaseIndex(grandparent)] ) parent_2 = CaseStructure( case_id="Robert", attrs={'owner_id': self.other_owner_id}, indices=[CaseIndex(grandparent)] ) child_1 = CaseStructure( case_id="Shireen", attrs={'owner_id': self.owner_id}, indices=[CaseIndex(parent_1)] ) child_2 = CaseStructure( case_id="Joffrey", attrs={'owner_id': self.owner_id}, indices=[CaseIndex(parent_2)] ) self.factory.create_or_update_cases([grandparent, parent_1, parent_2, child_1, child_2]) footprint_info = get_case_footprint_info(self.domain, self.owner_id) self.assertEqual( footprint_info.all_ids, set([grandparent.case_id, parent_1.case_id, parent_2.case_id, child_1.case_id, child_2.case_id]) )
class GetCaseFootprintInfoTest(TestCase): @classmethod def setUpClass(cls): super(GetCaseFootprintInfoTest, cls).setUpClass() delete_all_cases() def setUp(self): super(GetCaseFootprintInfoTest, self).setUp() self.domain = 'domain' self.owner_id = uuid.uuid4().hex self.other_owner_id = uuid.uuid4().hex self.factory = CaseFactory(self.domain) def test_simple_footprint(self): """ should only return open cases from user """ case = CaseStructure(case_id=uuid.uuid4().hex, attrs={'owner_id': self.owner_id, 'create': True}) closed_case = CaseStructure(case_id=uuid.uuid4().hex, attrs={'owner_id': self.owner_id, 'close': True, 'create': True}) other_case = CaseStructure(case_id=uuid.uuid4().hex, attrs={'owner_id': self.other_owner_id, 'create': True}) self.factory.create_or_update_cases([case, other_case, closed_case]) footprint_info = get_case_footprint_info(self.domain, self.owner_id) self.assertEqual(footprint_info.all_ids, set([case.case_id])) 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])) def test_footprint_with_extension(self): """ Extensions are brought in if the host case is owned; Host case is brought in if the extension is owned """ host = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.owner_id, 'create': True} ) extension = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.other_owner_id, 'create': True}, indices=[CaseIndex(host, relationship=CASE_INDEX_EXTENSION)] ) self.factory.create_or_update_cases([host, extension]) footprint_info = get_case_footprint_info(self.domain, self.owner_id) self.assertEqual(footprint_info.all_ids, set([extension.case_id, host.case_id])) self.assertEqual(footprint_info.base_ids, set([host.case_id])) footprint_info = get_case_footprint_info(self.domain, self.other_owner_id) self.assertEqual(footprint_info.all_ids, set([extension.case_id, host.case_id])) self.assertEqual(footprint_info.base_ids, set([extension.case_id])) def test_footprint_with_extension_of_parent(self): """ Extensions of parents should be included """ 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)] ) extension = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.other_owner_id, 'create': True}, indices=[CaseIndex(parent, 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_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_cousins(self): # http://manage.dimagi.com/default.asp?189528 grandparent = CaseStructure( case_id="Steffon", attrs={'owner_id': self.other_owner_id, 'create': True} ) parent_1 = CaseStructure( case_id="Stannis", attrs={'owner_id': self.other_owner_id, 'create': True}, indices=[CaseIndex(grandparent)] ) parent_2 = CaseStructure( case_id="Robert", attrs={'owner_id': self.other_owner_id, 'create': True}, indices=[CaseIndex(grandparent)] ) child_1 = CaseStructure( case_id="Shireen", attrs={'owner_id': self.owner_id, 'create': True}, indices=[CaseIndex(parent_1)] ) child_2 = CaseStructure( case_id="Joffrey", attrs={'owner_id': self.owner_id, 'create': True}, indices=[CaseIndex(parent_2)] ) self.factory.create_or_update_cases([grandparent, parent_1, parent_2, child_1, child_2]) footprint_info = get_case_footprint_info(self.domain, self.owner_id) self.assertEqual( footprint_info.all_ids, set([grandparent.case_id, parent_1.case_id, parent_2.case_id, child_1.case_id, child_2.case_id]) )
class GetDependentCasesTest(TestCase): @classmethod def setUpClass(cls): super(GetDependentCasesTest, cls).setUpClass() delete_all_cases() def setUp(self): super(GetDependentCasesTest, self).setUp() self.domain = 'domain' self.owner_id = uuid.uuid4().hex self.other_owner_id = uuid.uuid4().hex self.factory = CaseFactory(self.domain) @run_with_all_backends def test_returns_nothing_with_no_dependencies(self): case = CaseStructure() self.factory.create_or_update_case(case) self.assertEqual(set(), get_dependent_case_info(self.domain, [case.case_id]).all_ids) @run_with_all_backends 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) @run_with_all_backends def test_returns_extension_of_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)] ) extension_2 = CaseStructure( case_id=uuid.uuid4().hex, indices=[CaseIndex(extension, relationship=CASE_INDEX_EXTENSION)] ) all_ids = set([host.case_id, extension.case_id, extension_2.case_id]) self.factory.create_or_update_cases([extension_2]) 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(all_ids, get_dependent_case_info(self.domain, [extension_2.case_id]).all_ids) self.assertEqual(set([extension.case_id, extension_2.case_id]), get_dependent_case_info(self.domain, [host.case_id]).extension_ids) @run_with_all_backends def test_children_and_extensions(self): parent = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.other_owner_id, 'close': True} ) child = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.owner_id}, indices=[CaseIndex(parent)] ) extension = CaseStructure( case_id=uuid.uuid4().hex, attrs={'owner_id': self.other_owner_id}, indices=[CaseIndex(child, relationship=CASE_INDEX_EXTENSION)] ) self.factory.create_or_update_cases([parent, child, extension]) all_ids = set([parent.case_id, child.case_id, extension.case_id]) self.assertEqual(all_ids, get_dependent_case_info(self.domain, [child.case_id]).all_ids) self.assertEqual(set([]), get_dependent_case_info(self.domain, [parent.case_id]).all_ids) self.assertEqual(set([extension.case_id]), get_dependent_case_info(self.domain, [child.case_id]).extension_ids) self.assertEqual(set([]), get_dependent_case_info(self.domain, [parent.case_id]).extension_ids)
class ENikshayCaseStructureMixin(object): def setUp(self): super(ENikshayCaseStructureMixin, self).setUp() delete_all_users() self.domain = getattr(self, 'domain', 'fake-domain-from-mixin') self.factory = CaseFactory(domain=self.domain) self.username = "******" self.password = "******" self.user = CommCareUser.create( self.domain, username=self.username, password=self.password, first_name="Jon", last_name="Snow", ) self.person_id = u"person" self.occurrence_id = u"occurrence" self.episode_id = u"episode" self.test_id = u"test" self.lab_referral_id = u"lab_referral" self.prescription_id = "prescription_id" self._prescription_created = False self.primary_phone_number = "0123456789" self.secondary_phone_number = "0999999999" self.treatment_supporter_phone = "066000666" self.other_number = "0123456666" self._episode = None self._person = None def tearDown(self): delete_all_users() super(ENikshayCaseStructureMixin, self).tearDown() @property def person(self): if not self._person: self._person = get_person_case_structure( self.person_id, self.user.user_id, extra_update={ PRIMARY_PHONE_NUMBER: self.primary_phone_number, BACKUP_PHONE_NUMBER: self.secondary_phone_number, ENROLLED_IN_PRIVATE: 'false', }) return self._person @property def occurrence(self): return get_occurrence_case_structure(self.occurrence_id, self.person) @property def episode(self): if not self._episode: self._episode = get_episode_case_structure( self.episode_id, self.occurrence, extra_update={ OTHER_NUMBER: self.other_number, TREATMENT_SUPPORTER_PHONE: self.treatment_supporter_phone, WEIGHT_BAND: "adult_55-69" }) return self._episode def create_case(self, case): return self.factory.create_or_update_cases([case]) def create_case_structure(self): return { case.case_id: case for case in self.factory.create_or_update_cases([self.episode]) } @property def test(self): return CaseStructure( case_id=self.test_id, attrs={ 'create': True, 'case_type': 'test', "update": dict( date_reported=datetime(2016, 8, 6).date(), lab_serial_number=19, test_type_value="microscopy-zn", purpose_of_testing="diagnostic", result_grade="1plus", testing_facility_id=self.dmc.get_id, ) }, indices=[ CaseIndex( self.occurrence, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=self.occurrence.attrs['case_type'], ) ], ) @property 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 create_adherence_cases(self, adherence_dates, adherence_source='99DOTS'): return self.factory.create_or_update_cases([ get_adherence_case_structure( adherence_date.strftime('%Y-%m-%d-%H-%M'), self.episode_id, adherence_date, extra_update={ "name": adherence_date, "adherence_source": adherence_source, "adherence_value": "unobserved_dose", }) for adherence_date in adherence_dates ]) def create_adherence_case(self, adherence_date, adherence_source="99DOTS", adherence_value="unobserved_dose", case_id=None): return self.factory.create_or_update_cases([ get_adherence_case_structure(case_id, self.episode_id, adherence_date, extra_update={ "adherence_source": adherence_source, "adherence_value": adherence_value, }) ]) def create_prescription_case(self, extra_update=None): return self.factory.create_or_update_case( get_prescription_case_structure(uuid.uuid4().hex, self.episode_id, extra_update))[0] def create_voucher_case(self, prescription_id, extra_update=None): return self.factory.create_or_update_case( get_voucher_case_structure(uuid.uuid4().hex, prescription_id, extra_update))[0] def create_referral_case(self, case_id): return self.factory.create_or_update_cases( [get_referral_case_structure(case_id, self.person_id)]) @nottest def create_test_case(self, occurrence_id, extra_update=None): return self.factory.create_or_update_case( get_test_case_structure(uuid.uuid4().hex, occurrence_id, extra_update))[0]
def setUpClass(cls): super(TestFilterDslLookups, cls).setUpClass() with trap_extra_setup(ConnectionError): cls.es = get_es_new() initialize_index_and_mapping(cls.es, CASE_SEARCH_INDEX_INFO) cls.child_case_id = 'margaery' cls.parent_case_id = 'mace' cls.grandparent_case_id = 'olenna' cls.domain = "Tyrell" factory = CaseFactory(domain=cls.domain) grandparent_case = CaseStructure(case_id=cls.grandparent_case_id, attrs={ 'create': True, 'case_type': 'grandparent', 'update': { "name": "Olenna", "alias": "Queen of thorns", "house": "Tyrell", }, }) parent_case = CaseStructure(case_id=cls.parent_case_id, attrs={ 'create': True, 'case_type': 'parent', 'update': { "name": "Mace", "house": "Tyrell", }, }, indices=[ CaseIndex( grandparent_case, identifier='mother', relationship='child', ) ]) child_case = CaseStructure( case_id=cls.child_case_id, attrs={ 'create': True, 'case_type': 'child', 'update': { "name": "Margaery", "house": "Tyrell", }, }, indices=[ CaseIndex( parent_case, identifier='father', relationship='extension', ) ], ) for case in factory.create_or_update_cases([child_case]): send_to_elasticsearch( 'case_search', transform_case_for_elasticsearch(case.to_json())) cls.es.indices.refresh(CASE_SEARCH_INDEX_INFO.index)
def setUp(self): super(GetChildCasesExpressionTest, self).setUp() self.domain = uuid.uuid4().hex factory = CaseFactory(domain=self.domain) self.test_case_id = uuid.uuid4().hex parent_case = CaseStructure( case_id='p-' + self.test_case_id, attrs={ 'case_type': 'parent_case', 'create': True, 'date_opened': datetime(2015, 1, 10), 'date_modified': datetime(2015, 3, 10), }, ) test_case = CaseStructure( case_id=self.test_case_id, attrs={ 'case_type': 'test', 'create': True, 'date_opened': datetime(2015, 1, 10), 'date_modified': datetime(2015, 3, 10), }, indices=[ CaseIndex( parent_case, identifier='parent', relationship=CASE_INDEX_CHILD, related_type=parent_case.attrs['case_type'], ) ], ) child_case_1 = CaseStructure( case_id='c1-' + self.test_case_id, attrs={ 'case_type': 'child_1', 'create': True, 'date_opened': datetime(2015, 1, 10), 'date_modified': datetime(2015, 3, 10), }, indices=[ CaseIndex( test_case, identifier='parent', relationship=CASE_INDEX_CHILD, related_type=test_case.attrs['case_type'], ) ], ) child_case_2 = CaseStructure( case_id='c2-' + self.test_case_id, attrs={ 'case_type': 'child_2', 'create': True, 'date_opened': datetime(2015, 1, 10), 'date_modified': datetime(2015, 3, 10), }, indices=[ CaseIndex( test_case, identifier='parent', relationship=CASE_INDEX_CHILD, related_type=test_case.attrs['case_type'], ) ], ) factory.create_or_update_cases( [parent_case, test_case, child_case_1, child_case_2])
class ENikshayCaseStructureMixin(object): def setUp(self): super(ENikshayCaseStructureMixin, self).setUp() delete_all_users() self.domain = getattr(self, 'domain', 'fake-domain-from-mixin') self.factory = CaseFactory(domain=self.domain) self.user = CommCareUser.create( self.domain, "jon-snow@user", "123", ) self.person_id = u"person" self.occurrence_id = u"occurrence" self.episode_id = u"episode" self.primary_phone_number = "0123456789" self.secondary_phone_number = "0999999999" def tearDown(self): delete_all_users() super(ENikshayCaseStructureMixin, self).tearDown() @property def person(self): return CaseStructure( case_id=self.person_id, attrs={ "case_type": "person", "user_id": self.user.user_id, "create": True, "owner_id": uuid.uuid4().hex, "update": { 'name': "Pippin", 'aadhaar_number': "499118665246", PRIMARY_PHONE_NUMBER: self.primary_phone_number, BACKUP_PHONE_NUMBER: self.secondary_phone_number, 'merm_id': "123456789", 'dob': "1987-08-15", 'age': '20', 'sex': 'male', 'current_address': 'Mr. Everest', 'secondary_contact_name_address': 'Mrs. Everestie', 'previous_tb_treatment': 'yes', 'nikshay_registered': "false", } }, ) @property def occurrence(self): return CaseStructure( case_id=self.occurrence_id, attrs={ 'create': True, 'case_type': 'occurrence', "update": dict( name="Occurrence #1", ) }, indices=[CaseIndex( self.person, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=self.person.attrs['case_type'], )], ) @property def episode(self): return CaseStructure( case_id=self.episode_id, attrs={ 'create': True, 'case_type': 'episode', "update": dict( name="Episode #1", person_name="Pippin", opened_on=datetime(1989, 6, 11, 0, 0), patient_type_choice="treatment_after_lfu", hiv_status="reactive", episode_type="confirmed_tb", default_adherence_confidence="high", occupation='engineer', date_of_diagnosis='2014-09-09', treatment_initiation_date='2015-03-03', disease_classification='extra_pulmonary', treatment_supporter_first_name='awesome', treatment_supporter_last_name='dot', treatment_supporter_mobile_number='123456789', treatment_supporter_designation='ngo_volunteer', site_choice='pleural_effusion', ) }, indices=[CaseIndex( self.occurrence, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=self.occurrence.attrs['case_type'], )], ) def create_case(self, case): return self.factory.create_or_update_cases([case]) def create_case_structure(self): return {case.case_id: case for case in self.factory.create_or_update_cases([self.episode])} def create_adherence_cases(self, adherence_dates): return self.factory.create_or_update_cases([ CaseStructure( case_id=adherence_date.strftime('%Y-%m-%d'), attrs={ "case_type": "adherence", "create": True, "update": { "name": adherence_date, "adherence_value": "unobserved_dose", "adherence_source": "99DOTS", "adherence_date": adherence_date, "person_name": "Pippin", "adherence_confidence": "medium", "shared_number_99_dots": False, }, }, indices=[CaseIndex( CaseStructure(case_id=self.episode_id, attrs={"create": False}), identifier='host', relationship=CASE_INDEX_EXTENSION, related_type='episode', )], walk_related=False, ) for adherence_date in adherence_dates ])
class ENikshayCaseStructureMixin(object): def setUp(self): super(ENikshayCaseStructureMixin, self).setUp() self.domain = getattr(self, 'domain', 'fake-domain-from-mixin') self.factory = CaseFactory(domain=self.domain) self.person_id = u"person" self.occurrence_id = u"occurrence" self.episode_id = u"episode" @property def person(self): return CaseStructure( case_id=self.person_id, attrs={ "case_type": "person", "create": True, "update": dict( name="Pippin", aadhaar_number="499118665246", phone_number="0123456789", backup_number="0999999999", merm_id="123456789", dob="1987-08-15", ) }, ) @property def occurrence(self): return CaseStructure( case_id=self.occurrence_id, attrs={ 'create': True, 'case_type': 'occurrence', "update": dict( name="Occurrence #1", ) }, indices=[CaseIndex( self.person, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=self.person.attrs['case_type'], )], ) @property def episode(self): return CaseStructure( case_id=self.episode_id, attrs={ 'create': True, 'case_type': 'episode', "update": dict( person_name="Pippin", opened_on=datetime(1989, 6, 11, 0, 0), patient_type="new", hiv_status="reactive", episode_type="confirmed_tb", default_adherence_confidence="high", ) }, indices=[CaseIndex( self.occurrence, identifier='host', relationship=CASE_INDEX_EXTENSION, related_type=self.occurrence.attrs['case_type'], )], ) def create_case(self, case): return self.factory.create_or_update_cases([case]) def create_case_structure(self): return {case.case_id: case for case in self.factory.create_or_update_cases([self.episode])} def create_adherence_cases(self, adherence_dates): return self.factory.create_or_update_cases([ CaseStructure( case_id=adherence_date.strftime('%Y-%m-%d'), attrs={ "case_type": "adherence", "create": True, "update": { "name": adherence_date, "adherence_value": "unobserved_dose", "adherence_source": "99DOTS", "adherence_date": adherence_date, "person_name": "Pippin", "adherence_confidence": "medium", "shared_number_99_dots": False, }, }, indices=[CaseIndex( CaseStructure(case_id=self.episode_id, attrs={"create": False}), identifier='host', relationship=CASE_INDEX_EXTENSION, related_type='episode', )], walk_related=False, ) for adherence_date in adherence_dates ])
class AdherenceCaseFactory(object): """ Creates and updates adherence cases for a given person Only for use by the 99DOTS integration with eNikshay """ DEFAULT_ADHERENCE_CONFIDENCE = "medium" ADHERENCE_CASE_TYPE = "adherence" DEFAULT_ADHERENCE_VALUE = "unobserved_dose" def __init__(self, domain, person_id): self.domain = domain self.person_id = person_id self.case_accessor = CaseAccessors(domain) self.case_factory = CaseFactory(domain) @property @memoized def _person_case(self): try: return self.case_accessor.get_case(self.person_id) except CaseNotFound: raise AdherenceException("No patient exists with this beneficiary ID") @property @memoized def _default_adherence_confidence(self): return self._episode_case.dynamic_case_properties().get( 'default_adherence_confidence', self.DEFAULT_ADHERENCE_CONFIDENCE ) @property @memoized def _episode_case(self): try: return get_open_episode_case_from_person(self.domain, self._person_case.case_id) except ENikshayCaseNotFound as e: raise AdherenceException(e.message) def create_adherence_cases(self, adherence_points): 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), }, 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 _get_adherence_case_properties(self, adherence_point): return { "name": adherence_point.get("timestamp", None), "adherence_value": self.DEFAULT_ADHERENCE_VALUE, "adherence_source": adherence_point.get('adherenceSource', '99DOTS'), "adherence_date": self._parse_adherence_date(adherence_point["timestamp"]), "person_name": self._person_case.name, "adherence_confidence": self._default_adherence_confidence, "shared_number_99_dots": adherence_point["sharedNumber"], } def _parse_adherence_date(self, iso_datestring): tz = timezone('Asia/Kolkata') try: datetime_from_adherence = parser.parse(iso_datestring) datetime_in_india = datetime_from_adherence.astimezone(tz) except ValueError: raise AdherenceException( "Adherence date should be an ISO8601 formated string with timezone information." ) return datetime_in_india.date() def update_adherence_cases(self, start_date, end_date, confidence_level): try: adherence_cases = get_adherence_cases_between_dates(self.domain, self.person_id, start_date, end_date) except ENikshayCaseNotFound as e: raise AdherenceException(e.message) adherence_case_ids = [case.case_id for case in adherence_cases] return self.case_factory.create_or_update_cases([ CaseStructure( case_id=adherence_case_id, attrs={ "create": False, "update": { "adherence_confidence": confidence_level }, }, walk_related=False ) for adherence_case_id in adherence_case_ids ]) def update_default_confidence_level(self, confidence_level): return self.case_factory.create_or_update_cases([ CaseStructure( case_id=self._episode_case.case_id, attrs={ "create": False, "update": { "default_adherence_confidence": confidence_level }, }, walk_related=False ) ])