Exemple #1
0
 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])
Exemple #2
0
    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)
Exemple #3
0
 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)
Exemple #4
0
    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)
Exemple #7
0
    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))
Exemple #9
0
    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))
Exemple #10
0
    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))
Exemple #11
0
    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},
        )
Exemple #12
0
 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)
Exemple #13
0
 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]))
Exemple #14
0
 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}
Exemple #15
0
    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
Exemple #17
0
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)
Exemple #21
0
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])}
Exemple #22
0
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)
Exemple #24
0
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
        ])
Exemple #25
0
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')
Exemple #27
0
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!')
Exemple #32
0
    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])
Exemple #34
0
    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])
Exemple #37
0
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]
Exemple #38
0
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])
        )
Exemple #39
0
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])
        )
Exemple #40
0
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)
Exemple #41
0
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]
Exemple #42
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)
Exemple #43
0
 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])
Exemple #44
0
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
        ])
Exemple #45
0
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
        ])
Exemple #46
0
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
            )
        ])