示例#1
0
 def tearDownClass(cls):
     CaseAccessorSQL.hard_delete_cases(
         cls.domain,
         cls.created_case_ids
     )
     cls.domain_obj.delete()
     super(BaseICDSTest, cls).tearDownClass()
示例#2
0
    def test_deleted_case_migration(self):
        parent_case_id = uuid.uuid4().hex
        child_case_id = uuid.uuid4().hex
        parent_case = create_and_save_a_case(self.domain_name, case_id=parent_case_id, case_name='test parent')
        child_case = create_and_save_a_case(self.domain_name, case_id=child_case_id, case_name='test child')
        set_parent_case(self.domain_name, child_case, parent_case)

        form_ids = self._get_form_ids()
        self.assertEqual(3, len(form_ids))
        FormAccessors(self.domain.name).soft_delete_forms(
            form_ids, datetime.utcnow(), 'test-deletion-with-cases'
        )
        CaseAccessors(self.domain.name).soft_delete_cases(
            [parent_case_id, child_case_id], datetime.utcnow(), 'test-deletion-with-cases'
        )
        self.assertEqual(2, len(get_doc_ids_in_domain_by_type(
            self.domain_name, "CommCareCase-Deleted", XFormInstance.get_db())
        ))
        self._do_migration_and_assert_flags(self.domain_name)
        self.assertEqual(2, len(CaseAccessorSQL.get_deleted_case_ids_in_domain(self.domain_name)))
        self._compare_diffs([])
        parent_transactions = CaseAccessorSQL.get_transactions(parent_case_id)
        self.assertEqual(2, len(parent_transactions))
        self.assertTrue(parent_transactions[0].is_case_create)
        self.assertTrue(parent_transactions[1].is_form_transaction)
        child_transactions = CaseAccessorSQL.get_transactions(child_case_id)
        self.assertEqual(2, len(child_transactions))
        self.assertTrue(child_transactions[0].is_case_create)
        self.assertTrue(child_transactions[1].is_case_index)
def _create_case_transactions(case):
    case.track_create(CaseTransaction(
        case=case,
        form_id=uuid.uuid4().hex,
        server_date=datetime.utcnow(),
        type=CaseTransaction.TYPE_FORM,
        revoked=False
    ))
    # exclude revoked
    case.track_create(CaseTransaction(
        case=case,
        form_id=uuid.uuid4().hex,
        server_date=datetime.utcnow(),
        type=CaseTransaction.TYPE_FORM,
        revoked=True
    ))
    # exclude based on type
    case.track_create(CaseTransaction(
        case=case,
        form_id=uuid.uuid4().hex,
        server_date=datetime.utcnow(),
        type=CaseTransaction.TYPE_REBUILD_FORM_ARCHIVED,
        revoked=False
    ))
    form_ids = [t.form_id for t in case.get_tracked_models_to_create(CaseTransaction)]
    CaseAccessorSQL.save_case(case)
    return form_ids
    def test_get_attachments(self):
        case = _create_case()

        case.track_create(CaseAttachmentSQL(
            case=case,
            attachment_id=uuid.uuid4().hex,
            name='pic.jpg',
            content_type='image/jpeg',
            blob_id='125',
            identifier='pic1',
            md5='123',
        ))
        case.track_create(CaseAttachmentSQL(
            case=case,
            attachment_id=uuid.uuid4().hex,
            name='doc',
            content_type='text/xml',
            blob_id='126',
            identifier='doc1',
            md5='123',
        ))
        CaseAccessorSQL.save_case(case)

        with self.assertNumQueries(1, using=db_for_read_write(CaseAttachmentSQL)):
            attachments = CaseAccessorSQL.get_attachments(case.case_id)

        self.assertEqual(2, len(attachments))
        sorted_attachments = sorted(attachments, key=lambda x: x.name)
        for att in attachments:
            self.assertEqual(case.case_id, att.case_id)
        self.assertEqual('doc', sorted_attachments[0].name)
        self.assertEqual('pic.jpg', sorted_attachments[1].name)
示例#5
0
    def test_archive_unarchive_form(self):
        case_id = uuid.uuid4().hex
        form = create_form_for_test(DOMAIN, case_id=case_id)
        self.assertEqual(XFormInstanceSQL.NORMAL, form.state)
        self.assertEqual(0, len(form.history))

        transactions = CaseAccessorSQL.get_transactions(case_id)
        self.assertEqual(1, len(transactions))
        self.assertFalse(transactions[0].revoked)

        FormAccessorSQL.archive_form(form, 'user1')
        form = FormAccessorSQL.get_form(form.form_id)
        self.assertEqual(XFormInstanceSQL.ARCHIVED, form.state)
        operations = form.history
        self.assertEqual(1, len(operations))
        self.assertEqual(form.form_id, operations[0].form_id)
        self.assertEqual('user1', operations[0].user_id)

        transactions = CaseAccessorSQL.get_transactions(case_id)
        self.assertEqual(1, len(transactions))
        self.assertTrue(transactions[0].revoked)

        FormAccessorSQL.unarchive_form(form, 'user2')
        form = FormAccessorSQL.get_form(form.form_id)
        self.assertEqual(XFormInstanceSQL.NORMAL, form.state)
        operations = form.history
        self.assertEqual(2, len(operations))
        self.assertEqual(form.form_id, operations[1].form_id)
        self.assertEqual('user2', operations[1].user_id)

        transactions = CaseAccessorSQL.get_transactions(case_id)
        self.assertEqual(1, len(transactions))
        self.assertFalse(transactions[0].revoked)
    def test_get_attachment_by_name(self):
        case = _create_case()

        case.track_create(CaseAttachmentSQL(
            case=case,
            attachment_id=uuid.uuid4().hex,
            name='pic.jpg',
            content_type='image/jpeg',
            blob_id='123',
            identifier='pic1',
            md5='123'
        ))
        case.track_create(CaseAttachmentSQL(
            case=case,
            attachment_id=uuid.uuid4().hex,
            name='my_doc',
            content_type='text/xml',
            blob_id='124',
            identifier='doc1',
            md5='123'
        ))
        CaseAccessorSQL.save_case(case)

        with self.assertRaises(AttachmentNotFound):
            CaseAccessorSQL.get_attachment_by_identifier(case.case_id, 'missing')

        with self.assertNumQueries(1, using=db_for_read_write(CaseAttachmentSQL)):
            attachment_meta = CaseAccessorSQL.get_attachment_by_identifier(case.case_id, 'pic1')

        self.assertEqual(case.case_id, attachment_meta.case_id)
        self.assertEqual('pic.jpg', attachment_meta.name)
        self.assertEqual('image/jpeg', attachment_meta.content_type)
    def test_get_extension_case_ids(self):
        # Create case and index
        referenced_id = uuid.uuid4().hex
        case = _create_case()
        extension_index = CommCareCaseIndexSQL(
            case=case,
            identifier="task",
            referenced_type="task",
            referenced_id=referenced_id,
            relationship_id=CommCareCaseIndexSQL.EXTENSION
        )
        case.track_create(extension_index)
        CaseAccessorSQL.save_case(case)

        # Create irrelevant case
        other_case = _create_case()
        child_index = CommCareCaseIndexSQL(
            case=other_case,
            identifier='parent',
            referenced_type='mother',
            referenced_id=referenced_id,
            relationship_id=CommCareCaseIndexSQL.CHILD
        )
        case.track_create(child_index)
        CaseAccessorSQL.save_case(other_case)

        self.assertEqual(
            CaseAccessorSQL.get_extension_case_ids(DOMAIN, [referenced_id]),
            [case.case_id]
        )
示例#8
0
    def hard_rebuild_case(domain, case_id, detail, lock=True):
        if lock:
            # only record metric if locking since otherwise it has been
            # (most likley) recorded elsewhere
            case_load_counter("rebuild_case", domain)()
        case, lock_obj = FormProcessorSQL.get_case_with_lock(case_id, lock=lock)
        found = bool(case)
        if not found:
            case = CommCareCaseSQL(case_id=case_id, domain=domain)
            if lock:
                lock_obj = CommCareCaseSQL.get_obj_lock_by_id(case_id)
                acquire_lock(lock_obj, degrade_gracefully=False)

        try:
            assert case.domain == domain, (case.domain, domain)
            case, rebuild_transaction = FormProcessorSQL._rebuild_case_from_transactions(case, detail)
            if case.is_deleted and not case.is_saved():
                return None

            case.server_modified_on = rebuild_transaction.server_date
            CaseAccessorSQL.save_case(case)
            publish_case_saved(case)
            return case
        finally:
            release_lock(lock_obj, degrade_gracefully=True)
    def test_reconcile_transactions_within_fudge_factor(self, soft_assert_mock):
        """ tests a transanction with an early client date and late server date """
        with freeze_time("2018-10-10"):
            case = self._create_case()

        with freeze_time("2018-10-11 06:00"):
            new_old_xform = self._create_form()
        with freeze_time("2018-10-10 18:00"):
            new_old_trans = self._create_case_transaction(case, new_old_xform)
        with freeze_time("2018-10-11 06:00"):
            case.track_create(new_old_trans)
            FormProcessorSQL.save_processed_models(ProcessedForms(new_old_xform, []), [case])

        with freeze_time("2018-10-11"):
            new_old_xform = self._create_form()
            new_old_trans = self._create_case_transaction(case, new_old_xform)
            case.track_create(new_old_trans)
            FormProcessorSQL.save_processed_models(ProcessedForms(new_old_xform, []), [case])

        case = CaseAccessorSQL.get_case(case.case_id)
        update_strategy = SqlCaseUpdateStrategy(case)
        self.assertTrue(update_strategy.reconcile_transactions_if_necessary())
        self._check_for_reconciliation_error_soft_assert(soft_assert_mock)

        CaseAccessorSQL.save_case(case)

        case = CaseAccessorSQL.get_case(case.case_id)
        update_strategy = SqlCaseUpdateStrategy(case)
        self.assertFalse(update_strategy.reconcile_transactions_if_necessary())
        self._check_for_reconciliation_error_soft_assert(soft_assert_mock)
示例#10
0
def _create_ledger(domain, entry_id, balance, case_id=None, section_id='stock'):
    user_id = 'user1'
    utcnow = datetime.utcnow()

    case_id = case_id or uuid.uuid4().hex
    case = CommCareCaseSQL(
        case_id=case_id,
        domain=domain,
        type='',
        owner_id=user_id,
        opened_on=utcnow,
        modified_on=utcnow,
        modified_by=user_id,
        server_modified_on=utcnow,
    )

    CaseAccessorSQL.save_case(case)

    ledger = LedgerValue(
        domain=domain,
        case_id=case_id,
        section_id=section_id,
        entry_id=entry_id,
        balance=balance,
        last_modified=utcnow
    )

    LedgerAccessorSQL.save_ledger_values([ledger])
    return ledger
示例#11
0
    def test_get_attachments(self):
        case = _create_case()

        case.track_create(CaseAttachmentSQL(
            case=case,
            attachment_id=uuid.uuid4().hex,
            name='pic.jpg',
            content_type='image/jpeg'
        ))
        case.track_create(CaseAttachmentSQL(
            case=case,
            attachment_id=uuid.uuid4().hex,
            name='doc',
            content_type='text/xml'
        ))
        CaseAccessorSQL.save_case(case)

        with self.assertRaises(AttachmentNotFound):
            CaseAccessorSQL.get_attachment_by_name(case.case_id, 'missing')

        with self.assertNumQueries(1, using=db_for_read_write(CaseAttachmentSQL)):
            attachments = CaseAccessorSQL.get_attachments(case.case_id)

        self.assertEqual(2, len(attachments))
        sorted_attachments = sorted(attachments, key=lambda x: x.name)
        for att in attachments:
            self.assertEqual(case.case_id, att.case_id)
        self.assertEqual('doc', sorted_attachments[0].name)
        self.assertEqual('pic.jpg', sorted_attachments[1].name)
示例#12
0
    def test_edit_form_that_removes_ledgers(self):
        from corehq.apps.commtrack.tests.util import get_single_balance_block
        form_id = uuid.uuid4().hex
        submit_case_blocks([
            get_single_balance_block(self.case.case_id, self.product_a._id, 100)],
            DOMAIN,
            form_id=form_id
        )

        self._assert_ledger_state(100)

        transactions = CaseAccessorSQL.get_transactions(self.case.case_id)
        self.assertEqual(2, len(transactions))
        self.assertTrue(transactions[0].is_form_transaction)
        self.assertTrue(transactions[1].is_form_transaction)
        self.assertTrue(transactions[1].is_ledger_transaction)

        submit_case_blocks([
            CaseBlock(case_id=self.case.case_id).as_string().decode('utf-8')],
            DOMAIN,
            form_id=form_id
        )

        self._assert_ledger_state(0)

        transactions = CaseAccessorSQL.get_transactions(self.case.case_id)
        self.assertEqual(3, len(transactions))
        self.assertTrue(transactions[0].is_form_transaction)
        # ordering not guaranteed since they have the same date
        self.assertTrue(transactions[1].is_form_transaction)
        self.assertFalse(transactions[1].is_ledger_transaction)  # no longer a ledger transaction
        self.assertTrue(transactions[2].is_case_rebuild)

        self._assert_transactions([])
    def test_get_case_by_location(self):
        case = _create_case(case_type=SupplyPointCaseMixin.CASE_TYPE)
        location_id = uuid.uuid4().hex
        case.location_id = location_id
        CaseAccessorSQL.save_case(case)

        fetched_case = CaseAccessorSQL.get_case_by_location(DOMAIN, location_id)
        self.assertEqual(case.id, fetched_case.id)
    def test_get_closed_case_ids(self):
        case1 = _create_case(user_id="user1")
        case2 = _create_case(user_id="user1")
        case3 = _create_case(user_id="user2")
        case2.closed = True
        CaseAccessorSQL.save_case(case2)

        self.assertEqual(CaseAccessorSQL.get_closed_case_ids_for_owner(DOMAIN, "user1"), [case2.case_id])
示例#15
0
 def hard_delete_case_and_forms(cls, domain, case, xforms):
     form_ids = [xform.form_id for xform in xforms]
     FormAccessorSQL.hard_delete_forms(domain, form_ids)
     CaseAccessorSQL.hard_delete_cases(domain, [case.case_id])
     for form in xforms:
         form.state |= XFormInstanceSQL.DELETED
         publish_form_saved(form)
     case.deleted = True
     publish_case_saved(case)
 def test_case_has_transactions_since_sync(self):
     case1 = _create_case()
     _create_case_transactions(case1)
     self.assertTrue(
         CaseAccessorSQL.case_has_transactions_since_sync(case1.case_id, "foo", datetime(1992, 01, 30))
     )
     self.assertFalse(
         CaseAccessorSQL.case_has_transactions_since_sync(case1.case_id, "foo", datetime.utcnow())
     )
示例#17
0
    def test_get_deleted_case_ids_by_owner(self):
        user_id = uuid.uuid4().hex
        case1 = _create_case(user_id=user_id)
        case2 = _create_case(user_id=user_id)
        case3 = _create_case(user_id=user_id)

        CaseAccessorSQL.soft_delete_cases(DOMAIN, [case1.case_id, case2.case_id])

        case_ids = CaseAccessorSQL.get_deleted_case_ids_by_owner(DOMAIN, user_id)
        self.assertEqual(set(case_ids), {case1.case_id, case2.case_id})
示例#18
0
    def test_get_deleted_case_ids(self):
        case1 = _create_case()
        case2 = _create_case()
        CaseAccessorSQL.soft_delete_cases(DOMAIN, [case1.case_id])

        case_ids = CaseAccessorSQL.get_case_ids_in_domain(DOMAIN)
        self.assertEqual(case_ids, [case2.case_id])

        deleted = CaseAccessorSQL.get_deleted_case_ids_in_domain(DOMAIN)
        self.assertEquals(deleted, [case1.case_id])
示例#19
0
def create_case(domain, case_type, **kwargs):
    case = CaseFactory(domain).create_case(case_type=case_type, **kwargs)

    try:
        yield case
    finally:
        if should_use_sql_backend(domain):
            CaseAccessorSQL.hard_delete_cases(domain, [case.case_id])
        else:
            case.delete()
    def test_get_transaction_by_form_id(self):
        form_id = uuid.uuid4().hex
        case = _create_case(form_id=form_id)

        transaction = CaseAccessorSQL.get_transaction_by_form_id(case.case_id, form_id)
        self.assertEqual(form_id, transaction.form_id)
        self.assertEqual(case.case_id, transaction.case_id)

        transaction = CaseAccessorSQL.get_transaction_by_form_id(case.case_id, 'wrong')
        self.assertIsNone(transaction)
    def test_hard_delete_case(self):
        case1 = _create_case()
        case2 = _create_case(domain='other_domain')
        self.addCleanup(lambda: CaseAccessorSQL.hard_delete_cases('other_domain', [case2.case_id]))

        case1.track_create(CommCareCaseIndexSQL(
            case=case1,
            identifier='parent',
            referenced_type='mother',
            referenced_id=uuid.uuid4().hex,
            relationship_id=CommCareCaseIndexSQL.CHILD
        ))
        case1.track_create(CaseAttachmentSQL(
            case=case1,
            attachment_id=uuid.uuid4().hex,
            name='pic.jpg',
            content_type='image/jpeg',
            blob_id='122',
            md5='123',
            identifier='pic.jpg',
        ))
        CaseAccessorSQL.save_case(case1)

        num_deleted = CaseAccessorSQL.hard_delete_cases(DOMAIN, [case1.case_id, case2.case_id])
        self.assertEqual(1, num_deleted)
        with self.assertRaises(CaseNotFound):
            CaseAccessorSQL.get_case(case1.case_id)

        self.assertEqual([], CaseAccessorSQL.get_indices(case1.domain, case1.case_id))
        self.assertEqual([], CaseAccessorSQL.get_attachments(case1.case_id))
        self.assertEqual([], CaseAccessorSQL.get_transactions(case1.case_id))
    def print_stats(self, domain, short=True, diffs_only=False):
        status = get_couch_sql_migration_status(domain)
        print("Couch to SQL migration status for {}: {}".format(domain, status))
        db = get_diff_db(domain)
        try:
            diff_stats = db.get_diff_stats()
        except OperationalError:
            diff_stats = {}

        has_diffs = False
        for doc_type in doc_types():
            form_ids_in_couch = set(get_form_ids_by_type(domain, doc_type))
            form_ids_in_sql = set(FormAccessorSQL.get_form_ids_in_domain_by_type(domain, doc_type))
            diff_count, num_docs_with_diffs = diff_stats.pop(doc_type, (0, 0))
            has_diffs |= self._print_status(
                doc_type, form_ids_in_couch, form_ids_in_sql, diff_count, num_docs_with_diffs, short, diffs_only
            )

        form_ids_in_couch = set(get_doc_ids_in_domain_by_type(
            domain, "XFormInstance-Deleted", XFormInstance.get_db())
        )
        form_ids_in_sql = set(FormAccessorSQL.get_deleted_form_ids_in_domain(domain))
        diff_count, num_docs_with_diffs = diff_stats.pop("XFormInstance-Deleted", (0, 0))
        has_diffs |= self._print_status(
            "XFormInstance-Deleted", form_ids_in_couch, form_ids_in_sql,
            diff_count, num_docs_with_diffs, short, diffs_only
        )

        case_ids_in_couch = set(get_case_ids_in_domain(domain))
        case_ids_in_sql = set(CaseAccessorSQL.get_case_ids_in_domain(domain))
        diff_count, num_docs_with_diffs = diff_stats.pop("CommCareCase", (0, 0))
        has_diffs |= self._print_status(
            'CommCareCase', case_ids_in_couch, case_ids_in_sql, diff_count, num_docs_with_diffs, short, diffs_only
        )

        case_ids_in_couch = set(get_doc_ids_in_domain_by_type(
            domain, "CommCareCase-Deleted", XFormInstance.get_db())
        )
        case_ids_in_sql = set(CaseAccessorSQL.get_deleted_case_ids_in_domain(domain))
        diff_count, num_docs_with_diffs = diff_stats.pop("CommCareCase-Deleted", (0, 0))
        has_diffs |= self._print_status(
            'CommCareCase-Deleted', case_ids_in_couch, case_ids_in_sql,
            diff_count, num_docs_with_diffs, short, diffs_only
        )

        if diff_stats:
            for key, counts in diff_stats.items():
                diff_count, num_docs_with_diffs = counts
                has_diffs |= self._print_status(
                    key, set(), set(), diff_count, num_docs_with_diffs, short, diffs_only
                )

        if diffs_only and not has_diffs:
            print(shell_green("No differences found between old and new docs!"))
        return has_diffs
    def test_save_case_update_transaction(self):
        case = _create_case()

        [transaction] = CaseAccessorSQL.get_transactions(case.case_id)
        transaction.revoked = True

        # hack to call the sql function with an already saved transaction
        case.track_create(transaction)

        with self.assertRaises(CaseSaveError):
            CaseAccessorSQL.save_case(case)
def _update_case(domain, case_id, server_modified_on, last_visit_date=None):
    accessors = CaseAccessors(domain)
    case = accessors.get_case(case_id)
    case.server_modified_on = server_modified_on
    if last_visit_date:
        set_case_property_directly(case, 'last_visit_date', last_visit_date.strftime('%Y-%m-%d'))
    if should_use_sql_backend(domain):
        CaseAccessorSQL.save_case(case)
    else:
        # can't call case.save() since it overrides the server_modified_on property
        CommCareCase.get_db().save_doc(case.to_json())
示例#25
0
    def test_get_case_owner_ids(self):
        _create_case(user_id='user1', case_id='123')  # get's sharded to p1
        _create_case(user_id='user2', case_id='125')  # get's sharded to p2
        _create_case(user_id='user1')
        _create_case(domain='other_domain', user_id='user3')

        owners = CaseAccessorSQL.get_case_owner_ids('other_domain')
        self.assertEqual({'user3'}, owners)

        owners = CaseAccessorSQL.get_case_owner_ids(DOMAIN)
        self.assertEqual({'user1', 'user2'}, owners)
    def test_get_all_reverse_indices_info(self):
        # Create case and indexes
        case = _create_case()
        referenced_id1 = uuid.uuid4().hex
        referenced_id2 = uuid.uuid4().hex
        extension_index = CommCareCaseIndexSQL(
            case=case,
            identifier="task",
            referenced_type="task",
            referenced_id=referenced_id1,
            relationship_id=CommCareCaseIndexSQL.EXTENSION
        )
        case.track_create(extension_index)
        child_index = CommCareCaseIndexSQL(
            case=case,
            identifier='parent',
            referenced_type='mother',
            referenced_id=referenced_id2,
            relationship_id=CommCareCaseIndexSQL.CHILD
        )
        case.track_create(child_index)
        CaseAccessorSQL.save_case(case)

        # Create irrelevant case and index
        other_case = _create_case()
        other_child_index = CommCareCaseIndexSQL(
            case=other_case,
            identifier='parent',
            referenced_type='mother',
            referenced_id=case.case_id,
            relationship_id=CommCareCaseIndexSQL.CHILD
        )
        other_case.track_create(other_child_index)
        CaseAccessorSQL.save_case(other_case)

        self.assertEqual(
            set(CaseAccessorSQL.get_all_reverse_indices_info(DOMAIN, [referenced_id1, referenced_id2])),
            {
                CaseIndexInfo(
                    case_id=case.case_id,
                    identifier=u'task',
                    referenced_id=referenced_id1,
                    referenced_type=u'task',
                    relationship=CommCareCaseIndexSQL.EXTENSION,
                ),
                CaseIndexInfo(
                    case_id=case.case_id,
                    identifier=u'parent',
                    referenced_id=referenced_id2,
                    referenced_type=u'mother',
                    relationship=CommCareCaseIndexSQL.CHILD
                ),
            }
        )
    def test_get_transactions(self):
        form_id = uuid.uuid4().hex
        case = _create_case(form_id=form_id)
        transactions = CaseAccessorSQL.get_transactions(case.case_id)
        self.assertEqual(1, len(transactions))
        self.assertEqual(form_id, transactions[0].form_id)

        form_ids = _create_case_transactions(case)

        transactions = CaseAccessorSQL.get_transactions(case.case_id)
        self.assertEqual(6, len(transactions))
        self.assertEqual([form_id] + form_ids, [t.form_id for t in transactions])
示例#28
0
    def get_case_with_lock(case_id, lock=False, strip_history=False, wrap=False):
        try:
            if lock:
                try:
                    return CommCareCaseSQL.get_locked_obj(_id=case_id)
                except redis.RedisError:
                    case = CaseAccessorSQL.get_case(case_id)
            else:
                case = CaseAccessorSQL.get_case(case_id)
        except CaseNotFound:
            return None, None

        return case, None
示例#29
0
    def hard_rebuild_case(domain, case_id, detail):
        try:
            case = CaseAccessorSQL.get_case(case_id)
            assert case.domain == domain
            found = True
        except CaseNotFound:
            case = CommCareCaseSQL(case_id=case_id, domain=domain)
            found = False

        case = FormProcessorSQL._rebuild_case_from_transactions(case, detail)
        if case.is_deleted and not found:
            return None
        CaseAccessorSQL.save_case(case)
        def _create_case_with_index(referenced_case_id):
            case = _create_case()

            index1 = CommCareCaseIndexSQL(
                case=case,
                identifier='parent',
                referenced_type='mother',
                referenced_id=referenced_case_id,
                relationship_id=CommCareCaseIndexSQL.CHILD
            )
            case.track_create(index1)

            CaseAccessorSQL.save_case(case)
            return case.case_id
示例#31
0
    def test_get_reverse_indexed_cases(self):
        referenced_case_ids = [uuid.uuid4().hex, uuid.uuid4().hex]
        _create_case_with_index(uuid.uuid4().hex, case_is_deleted=True)  # case shouldn't be included in results
        expected_case_ids = [
            _create_case_with_index(referenced_case_ids[0], case_type='bambino')[0].case_id,
            _create_case_with_index(referenced_case_ids[1], case_type='child')[0].case_id,
        ]

        cases = CaseAccessorSQL.get_reverse_indexed_cases(DOMAIN, referenced_case_ids)
        self.assertEqual(2, len(cases))
        self.assertEqual(set(expected_case_ids), {c.case_id for c in cases})

        cases = CaseAccessorSQL.get_reverse_indexed_cases(
            DOMAIN, referenced_case_ids, case_types=['child'], is_closed=False)
        self.assertEqual(1, len(cases))

        cases[0].closed = True
        CaseAccessorSQL.save_case(cases[0])
        cases = CaseAccessorSQL.get_reverse_indexed_cases(DOMAIN, referenced_case_ids, is_closed=True)
        self.assertEqual(1, len(cases))
示例#32
0
 def _transactions_by_type(self, transaction_type):
     from corehq.form_processor.backends.sql.dbaccessors import CaseAccessorSQL
     if self.is_saved():
         transactions = CaseAccessorSQL.get_transactions_by_type(self.case_id, transaction_type)
     else:
         transactions = []
     transactions += filter(
         lambda t: (t.type & transaction_type) == transaction_type,
         self.get_tracked_models_to_create(CaseTransaction)
     )
     return transactions
    def test_hard_delete_cases_none_to_delete(self):
        for domain_name in [self.domain.name, self.domain2.name]:
            CaseFactory(domain_name).create_case()
            self.assertEqual(len(CaseAccessors(domain_name).get_case_ids_in_domain()), 1)

        self.domain.delete()

        self.assertEqual(len(CaseAccessors(self.domain.name).get_case_ids_in_domain()), 0)
        self.assertEqual(len(CaseAccessors(self.domain2.name).get_case_ids_in_domain()), 1)

        self.assertEqual(len(CaseAccessorSQL.get_deleted_case_ids_in_domain(self.domain.name)), 1)
        self.assertEqual(len(CaseAccessorSQL.get_deleted_case_ids_in_domain(self.domain2.name)), 0)

        call_command('hard_delete_forms_and_cases_in_domain', self.domain2.name, noinput=True)

        self.assertEqual(len(CaseAccessors(self.domain.name).get_case_ids_in_domain()), 0)
        self.assertEqual(len(CaseAccessors(self.domain2.name).get_case_ids_in_domain()), 1)

        self.assertEqual(len(CaseAccessorSQL.get_deleted_case_ids_in_domain(self.domain.name)), 1)
        self.assertEqual(len(CaseAccessorSQL.get_deleted_case_ids_in_domain(self.domain2.name)), 0)
    def _copy_unprocessed_case(self, change):
        couch_case = CommCareCase.wrap(change.get_document())
        self.log_debug('Processing doc: {}({})'.format(couch_case['doc_type'], change.id))
        try:
            first_action = couch_case.actions[0]
        except IndexError:
            first_action = CommCareCaseAction()

        sql_case = CommCareCaseSQL(
            case_id=couch_case.case_id,
            domain=self.domain,
            type=couch_case.type or '',
            name=couch_case.name,
            owner_id=couch_case.owner_id or couch_case.user_id or '',
            opened_on=couch_case.opened_on or first_action.date,
            opened_by=couch_case.opened_by or first_action.user_id,
            modified_on=couch_case.modified_on,
            modified_by=couch_case.modified_by or couch_case.user_id or '',
            server_modified_on=couch_case.server_modified_on,
            closed=couch_case.closed,
            closed_on=couch_case.closed_on,
            closed_by=couch_case.closed_by,
            deleted=True,
            deletion_id=couch_case.deletion_id,
            deleted_on=couch_case.deletion_date,
            external_id=couch_case.external_id,
            case_json=couch_case.dynamic_case_properties()
        )
        _migrate_case_actions(couch_case, sql_case)
        _migrate_case_indices(couch_case, sql_case)
        _migrate_case_attachments(couch_case, sql_case)
        try:
            CaseAccessorSQL.save_case(sql_case)
        except IntegrityError:
            # case re-created by form processing so just mark the case as deleted
            CaseAccessorSQL.soft_delete_cases(
                self.domain,
                [sql_case.case_id],
                sql_case.deleted_on,
                sql_case.deletion_id
            )
示例#35
0
 def _assert_case_revision(self,
                           rev_number,
                           last_modified,
                           expect_modified=False):
     if should_use_sql_backend(self.domain):
         modified_on = CaseAccessorSQL.get_last_modified_dates(
             self.domain, [self.case_id])[self.case_id]
         has_been_modified = modified_on != last_modified
         self.assertEqual(expect_modified, has_been_modified)
     else:
         doc = self._get_case()
         self.assertTrue(doc['_rev'].startswith('%s-' % rev_number))
    def test_hard_delete_case(self):
        case1 = _create_case()
        case2 = _create_case(domain='other_domain')
        self.addCleanup(lambda: CaseAccessorSQL.hard_delete_cases('other_domain', [case2.case_id]))

        case1.track_create(CommCareCaseIndexSQL(
            case=case1,
            identifier='parent',
            referenced_type='mother',
            referenced_id=uuid.uuid4().hex,
            relationship_id=CommCareCaseIndexSQL.CHILD
        ))
示例#37
0
    def get_case(self, case_id):
        try:
            return CaseAccessorSQL.get_case(case_id)
        except CaseNotFound:
            pass

        try:
            return CaseAccessorCouch.get_case(case_id)
        except ResourceNotFound:
            pass

        return None
示例#38
0
    def get_transaction_by_form_id(self, form_id):
        from corehq.form_processor.backends.sql.dbaccessors import CaseAccessorSQL
        transactions = filter(
            lambda t: t.form_id == form_id,
            self.get_tracked_models_to_create(CaseTransaction)
        )
        assert len(transactions) <= 1
        transaction = transactions[0] if transactions else None

        if not transaction:
            transaction = CaseAccessorSQL.get_transaction_by_form_id(self.case_id, form_id)
        return transaction
    def test_get_open_case_ids_in_domain_by_type(self):
        case1 = _create_case(user_id="user1", case_type='t1')
        case2 = _create_case(user_id="user1", case_type='t1')
        _create_case(user_id="user1", case_type='t1', closed=True)
        _create_case(user_id="user2", case_type='t1')
        _create_case(user_id="user1", case_type='t2')

        case_ids = CaseAccessorSQL.get_open_case_ids_in_domain_by_type(DOMAIN, 't1', ["user1"])
        self.assertEqual(
            set(case_ids),
            {case1.case_id, case2.case_id}
        )
示例#40
0
 def _assert_case_revision(self,
                           rev_number,
                           last_modified,
                           expect_modified=False):
     if should_use_sql_backend(self.domain):
         self.assertEqual(
             expect_modified,
             CaseAccessorSQL.case_modified_since(self.case_id,
                                                 last_modified))
     else:
         doc = self._get_case()
         self.assertTrue(doc['_rev'].startswith('%s-' % rev_number))
示例#41
0
    def _copy_unprocessed_cases(self):
        doc_types = ['CommCareCase-Deleted']
        changes = _get_case_iterator(self.domain,
                                     doc_types=doc_types).iter_all_changes()
        for change in self._with_progress(doc_types, changes):
            couch_case = CommCareCase.wrap(change.get_document())
            self.log_debug('Processing doc: {}({})'.format(
                couch_case['doc_type'], change.id))
            try:
                first_action = couch_case.actions[0]
            except IndexError:
                first_action = CommCareCaseAction()

            sql_case = CommCareCaseSQL(
                case_id=couch_case.case_id,
                domain=self.domain,
                type=couch_case.type or '',
                name=couch_case.name,
                owner_id=couch_case.owner_id or couch_case.user_id or '',
                opened_on=couch_case.opened_on or first_action.date,
                opened_by=couch_case.opened_by or first_action.user_id,
                modified_on=couch_case.modified_on,
                modified_by=couch_case.modified_by or couch_case.user_id or '',
                server_modified_on=couch_case.server_modified_on,
                closed=couch_case.closed,
                closed_on=couch_case.closed_on,
                closed_by=couch_case.closed_by,
                deleted=True,
                deletion_id=couch_case.deletion_id,
                deleted_on=couch_case.deletion_date,
                external_id=couch_case.external_id,
                case_json=couch_case.dynamic_case_properties())
            _migrate_case_actions(couch_case, sql_case)
            _migrate_case_indices(couch_case, sql_case)
            _migrate_case_attachments(couch_case, sql_case)
            try:
                CaseAccessorSQL.save_case(sql_case)
            except IntegrityError as e:
                self.log_error("Unable to migrate case:\n{}\n{}".format(
                    couch_case.case_id, e))
示例#42
0
    def _copy_unprocessed_case(self, doc):
        couch_case = CommCareCase.wrap(doc)
        log.debug('Processing doc: %(doc_type)s(%(_id)s)', doc)
        try:
            first_action = couch_case.actions[0]
        except IndexError:
            first_action = CommCareCaseAction()

        opened_on = couch_case.opened_on or first_action.date
        sql_case = CommCareCaseSQL(
            case_id=couch_case.case_id,
            domain=self.domain,
            type=couch_case.type or '',
            name=couch_case.name,
            owner_id=couch_case.owner_id or couch_case.user_id or '',
            opened_on=opened_on,
            opened_by=couch_case.opened_by or first_action.user_id,
            modified_on=couch_case.modified_on or opened_on,
            modified_by=couch_case.modified_by or couch_case.user_id or '',
            server_modified_on=couch_case.server_modified_on,
            closed=couch_case.closed,
            closed_on=couch_case.closed_on,
            closed_by=couch_case.closed_by,
            deleted=True,
            deletion_id=couch_case.deletion_id,
            deleted_on=couch_case.deletion_date,
            external_id=couch_case.external_id,
            case_json=couch_case.dynamic_case_properties())
        _migrate_case_actions(couch_case, sql_case)
        _migrate_case_indices(couch_case, sql_case)
        _migrate_case_attachments(couch_case, sql_case)
        try:
            CaseAccessorSQL.save_case(sql_case)
        except IntegrityError:
            # case re-created by form processing so just mark the case as deleted
            CaseAccessorSQL.soft_delete_cases(self.domain, [sql_case.case_id],
                                              sql_case.deleted_on,
                                              sql_case.deletion_id)
        finally:
            self.case_diff_queue.enqueue(couch_case.case_id)
示例#43
0
    def test_deleted_case_migration(self):
        parent_case_id = uuid.uuid4().hex
        child_case_id = uuid.uuid4().hex
        parent_case = create_and_save_a_case(self.domain_name,
                                             case_id=parent_case_id,
                                             case_name='test parent')
        child_case = create_and_save_a_case(self.domain_name,
                                            case_id=child_case_id,
                                            case_name='test child')
        set_parent_case(self.domain_name, child_case, parent_case)

        form_ids = self._get_form_ids()
        self.assertEqual(3, len(form_ids))
        FormAccessors(self.domain.name).soft_delete_forms(
            form_ids, datetime.utcnow(), 'test-deletion-with-cases')
        CaseAccessors(self.domain.name).soft_delete_cases(
            [parent_case_id, child_case_id], datetime.utcnow(),
            'test-deletion-with-cases')
        self.assertEqual(
            2,
            len(
                get_doc_ids_in_domain_by_type(self.domain_name,
                                              "CommCareCase-Deleted",
                                              XFormInstance.get_db())))
        self._do_migration_and_assert_flags(self.domain_name)
        self.assertEqual(
            2,
            len(
                CaseAccessorSQL.get_deleted_case_ids_in_domain(
                    self.domain_name)))
        self._compare_diffs([])
        parent_transactions = CaseAccessorSQL.get_transactions(parent_case_id)
        self.assertEqual(2, len(parent_transactions))
        self.assertTrue(parent_transactions[0].is_case_create)
        self.assertTrue(parent_transactions[1].is_form_transaction)
        child_transactions = CaseAccessorSQL.get_transactions(child_case_id)
        self.assertEqual(2, len(child_transactions))
        self.assertTrue(child_transactions[0].is_case_create)
        self.assertTrue(child_transactions[1].is_case_index)
示例#44
0
 def test_get_reverse_indexed_cases(self):
     referenced_case_ids = [uuid.uuid4().hex, uuid.uuid4().hex]
     _create_case_with_index(
         referenced_case_ids[0],
         case_is_deleted=True)  # case shouldn't be included in results
     expected_case_ids = [
         _create_case_with_index(case_id)[0].case_id
         for case_id in referenced_case_ids
     ]
     cases = CaseAccessorSQL.get_reverse_indexed_cases(
         DOMAIN, referenced_case_ids)
     self.assertEqual(2, len(cases))
     self.assertEqual(set(expected_case_ids), {c.case_id for c in cases})
示例#45
0
    def get_diff_stats(self, domain):
        db = get_diff_db(domain)
        diff_stats = db.get_diff_stats()

        stats = {}

        def _update_stats(doc_type, couch_count, sql_count):
            diff_count, num_docs_with_diffs = diff_stats.pop(doc_type, (0, 0))
            if diff_count or couch_count != sql_count:
                stats[doc_type] = (couch_count, sql_count, diff_count, num_docs_with_diffs)

        for doc_type in doc_types():
            form_ids_in_couch = len(set(get_form_ids_by_type(domain, doc_type)))
            form_ids_in_sql = len(set(FormAccessorSQL.get_form_ids_in_domain_by_type(domain, doc_type)))
            _update_stats(doc_type, form_ids_in_couch, form_ids_in_sql)

        form_ids_in_couch = len(set(get_doc_ids_in_domain_by_type(
            domain, "XFormInstance-Deleted", XFormInstance.get_db())
        ))
        form_ids_in_sql = len(set(FormAccessorSQL.get_deleted_form_ids_in_domain(domain)))
        _update_stats("XFormInstance-Deleted", form_ids_in_couch, form_ids_in_sql)

        case_ids_in_couch = len(set(get_case_ids_in_domain(domain)))
        case_ids_in_sql = len(set(CaseAccessorSQL.get_case_ids_in_domain(domain)))
        _update_stats("CommCareCase", case_ids_in_couch, case_ids_in_sql)

        if self.strict:
            # only care about these in strict mode
            case_ids_in_couch = len(set(get_doc_ids_in_domain_by_type(
                domain, "CommCareCase-Deleted", XFormInstance.get_db())
            ))
            case_ids_in_sql = len(set(CaseAccessorSQL.get_deleted_case_ids_in_domain(domain)))
            _update_stats("CommCareCase-Deleted", case_ids_in_couch, case_ids_in_sql)

        if diff_stats:
            for key in diff_stats.keys():
                _update_stats(key, 0, 0)

        return stats
示例#46
0
def check_for_sql_cases_without_existing_domain():
    missing_domains_with_cases = set()
    for domain in set(
            _get_all_domains_that_have_ever_had_subscriptions()) - set(
                Domain.get_all_names()):
        if CaseAccessorSQL.get_case_ids_in_domain(domain):
            missing_domains_with_cases |= {domain}

    if missing_domains_with_cases:
        mail_admins_async.delay(
            'There exist SQL cases belonging to a missing domain',
            six.text_type(missing_domains_with_cases))
    elif _is_monday():
        mail_admins_async.delay('All SQL cases belong to valid domains', '')
示例#47
0
    def test_get_case_by_external_id(self):
        case1 = _create_case(domain=DOMAIN)
        case1.external_id = '123'
        CaseAccessorSQL.save_case(case1)
        case2 = _create_case(domain='d2', case_type='t1')
        case2.external_id = '123'
        CaseAccessorSQL.save_case(case2)
        self.addCleanup(lambda: CaseAccessorSQL.delete_all_cases('d2'))

        [case] = CaseAccessorSQL.get_cases_by_external_id(DOMAIN, '123')
        self.assertEqual(case.case_id, case1.case_id)

        [case] = CaseAccessorSQL.get_cases_by_external_id('d2', '123')
        self.assertEqual(case.case_id, case2.case_id)

        self.assertEqual([], CaseAccessorSQL.get_cases_by_external_id('d2', '123', case_type='t2'))
示例#48
0
    def test_archive_unarchive_form(self):
        case_id = uuid.uuid4().hex
        form = create_form_for_test(DOMAIN, case_id=case_id)
        self.assertEqual(XFormInstanceSQL.NORMAL, form.state)
        self.assertEqual(0, len(form.history))

        transactions = CaseAccessorSQL.get_transactions(case_id)
        self.assertEqual(1, len(transactions))
        self.assertFalse(transactions[0].revoked)

        # archive twice to check that it's idempotent
        for i in range(2):
            self.archive_form(form, 'user1')
            form = FormAccessorSQL.get_form(form.form_id)
            self.assertEqual(XFormInstanceSQL.ARCHIVED, form.state)
            operations = form.history
            self.assertEqual(i + 1, len(operations))
            self.assertEqual(form.form_id, operations[i].form_id)
            self.assertEqual('user1', operations[i].user_id)

            transactions = CaseAccessorSQL.get_transactions(case_id)
            self.assertEqual(1, len(transactions), transactions)
            self.assertTrue(transactions[0].revoked)

        # unarchive twice to check that it's idempotent
        for i in range(2, 4):
            self.unarchive_form(form, 'user2')
            form = FormAccessorSQL.get_form(form.form_id)
            self.assertEqual(XFormInstanceSQL.NORMAL, form.state)
            operations = form.history
            self.assertEqual(i + 1, len(operations))
            self.assertEqual(form.form_id, operations[i].form_id)
            self.assertEqual('user2', operations[i].user_id)

            transactions = CaseAccessorSQL.get_transactions(case_id)
            self.assertEqual(1, len(transactions))
            self.assertFalse(transactions[0].revoked)
示例#49
0
    def test_case_with_indices_migration(self):
        parent_case_id = uuid.uuid4().hex
        child_case_id = uuid.uuid4().hex
        parent_case = create_and_save_a_case(self.domain_name, case_id=parent_case_id, case_name='test parent')
        child_case = create_and_save_a_case(self.domain_name, case_id=child_case_id, case_name='test child')
        set_parent_case(self.domain_name, child_case, parent_case)

        self.assertEqual(2, len(self._get_case_ids()))
        self._do_migration_and_assert_flags(self.domain_name)
        self.assertEqual(2, len(self._get_case_ids()))
        self._compare_diffs([])

        indices = CaseAccessorSQL.get_indices(self.domain_name, child_case_id)
        self.assertEqual(1, len(indices))
        self.assertEqual(parent_case_id, indices[0].referenced_id)
    def test_get_extension_case_ids(self):
        # Create case and index
        referenced_id = uuid.uuid4().hex
        case, _ = _create_case_with_index(referenced_id, identifier='task', referenced_type='task',
                                relationship_id=CommCareCaseIndexSQL.EXTENSION)

        # Create irrelevant cases
        _create_case_with_index(referenced_id)
        _create_case_with_index(referenced_id, identifier='task', referenced_type='task',
                                relationship_id=CommCareCaseIndexSQL.EXTENSION, case_is_deleted=True)

        self.assertEqual(
            CaseAccessorSQL.get_extension_case_ids(DOMAIN, [referenced_id]),
            [case.case_id]
        )
示例#51
0
    def _diff_cases(self, couch_cases):
        from corehq.apps.tzmigration.timezonemigration import json_diff
        self.log_debug('Calculating case diffs for {} cases'.format(len(couch_cases)))
        case_ids = list(couch_cases)
        sql_cases = CaseAccessorSQL.get_cases(case_ids)
        for sql_case in sql_cases:
            couch_case = couch_cases[sql_case.case_id]
            sql_case_json = sql_case.to_json()
            diffs = json_diff(couch_case, sql_case_json, track_list_indices=False)
            self.diff_db.add_diffs(
                couch_case['doc_type'], sql_case.case_id,
                filter_case_diffs(couch_case, sql_case_json, diffs, self.forms_that_touch_cases_without_actions)
            )

        self._diff_ledgers(case_ids)
示例#52
0
    def handle(self, domain, **options):
        domain = options.get('domain')
        case_ids = options.get('case_id')
        db = options.get('db')

        self.log_filename = 'undo_uuid_clash.{}.log'.format(
            datetime.utcnow().isoformat())
        print('\nWriting output to log file: {}\n'.format(self.log_filename))

        if case_ids:
            form_ids = set()
            for case in CaseAccessorSQL.get_cases(case_ids):
                assert not domain or case.domain == domain, 'Case "%s" not in domain "%s"' % (
                    case.case_id, domain)
                form_ids.update(case.xform_ids)

            with self:
                check_and_process_forms(form_ids, self)
        else:
            if domain:
                domains = [domain]
            else:
                domains = iter_domains()

            for domain in domains:
                print(u"Checking domain: %s" % domain)
                form_ids_to_check = set()
                dbs = [db] if db else get_db_aliases_for_partitioned_query()
                for dbname in dbs:
                    form_ids_to_check.update(
                        XFormInstanceSQL.objects.using(dbname).filter(
                            domain=domain,
                            state=XFormInstanceSQL.DEPRECATED).values_list(
                                'orig_id', flat=True))

                print('  Found %s forms to check' % len(form_ids_to_check))
                with self:
                    for chunk in chunked(form_ids_to_check, 500):
                        check_and_process_forms(chunk, self)

        def __enter__(self):
            self._log_file = open(self.log_filename, 'w')

        def __exit__(self, exc_type, exc_val, exc_tb):
            self._log_file.close()

        def log(message):
            self._log_file.write(message)
示例#53
0
def get_case_ids_for_reassignment(domain, location_id):
    """
    :return: for cases that belong to location_id return
    a dict mapping for all case ids under a household id and
    a set of all other case ids
    """
    all_case_ids = CaseAccessorSQL.get_case_ids_in_domain_by_owners(domain, [location_id])
    other_case_ids = set(all_case_ids)
    child_case_ids_per_household_id = {}
    for household_case_id in get_household_case_ids(domain, location_id):
        household_child_case_ids = get_household_child_case_ids_by_owner(
            domain, household_case_id, location_id)
        other_case_ids.remove(household_case_id)
        other_case_ids = other_case_ids - set(household_child_case_ids)
        child_case_ids_per_household_id[household_case_id] = household_child_case_ids
    return child_case_ids_per_household_id, other_case_ids
示例#54
0
    def handle(self, domain, *, state_dir, commit, debug, **options):
        if not should_use_sql_backend(domain):
            raise CommandError(
                f'Cannot unsort commits on couch domain: {domain}')

        assert Domain.get_by_name(domain), f'Unknown domain "{domain}"'
        setup_logging(state_dir, "unsort_sql_cases", debug)

        if commit:
            log.info("COMMIT MODE: show and save unsorted transactions...")
        else:
            log.info("DRY RUN: show but do not save unsorted transactions...")
        case_ids = iter_sql_cases_with_sorted_transactions(domain)
        for batch in chunked(case_ids, 100, list):
            for sql_case in CaseAccessorSQL.get_cases(batch):
                unsort_transactions(sql_case, commit)
示例#55
0
    def delete_all_v2_ledgers(domain=None):
        logger.debug("Deleting all V2 ledgers for domain %s", domain)

        def _delete_ledgers_for_case(case_id):
            transactions = LedgerAccessorSQL.get_ledger_transactions_for_case(case_id)
            form_ids = {tx.form_id for tx in transactions}
            for form_id in form_ids:
                LedgerAccessorSQL.delete_ledger_transactions_for_form([case_id], form_id)
            LedgerAccessorSQL.delete_ledger_values(case_id)

        if not domain:
            for ledger in iter_all_rows(LedgerReindexAccessor()):
                _delete_ledgers_for_case(ledger.case_id)
        else:
            for case_id in CaseAccessorSQL.get_case_ids_in_domain(domain):
                _delete_ledgers_for_case(case_id)
示例#56
0
 def process_bulk_docs(self, docs):
     updates = {}
     for doc in docs:
         case_id = doc['_id']
         mother_case_ids = [i.referenced_id for i in CaseAccessorSQL.get_indices(self.domain, case_id)
                            if i.identifier == MOTHER_INDEX_IDENTIFIER]
         if len(mother_case_ids) == 1:
             try:
                 mother_case = self.case_accessor.get_case(mother_case_ids[0])
             except CaseNotFound:
                 pass
             else:
                 updates[case_id] = mother_case.name
     if updates:
         submit_case_blocks(self._create_case_blocks(updates, MOTHER_NAME_PROPERTY),
                            self.domain, user_id=SYSTEM_USER_ID)
     return True
示例#57
0
    def _diff_cases(self, couch_cases):
        from corehq.apps.tzmigration.timezonemigration import json_diff
        log.debug('Calculating case diffs for {} cases'.format(
            len(couch_cases)))
        statedb = self.statedb
        counts = defaultdict(int)
        case_ids = list(couch_cases)
        sql_cases = CaseAccessorSQL.get_cases(case_ids)
        sql_case_ids = set()
        for sql_case in sql_cases:
            sql_case_ids.add(sql_case.case_id)
            couch_case = couch_cases[sql_case.case_id]
            sql_case_json = sql_case.to_json()
            diffs = json_diff(couch_case,
                              sql_case_json,
                              track_list_indices=False)
            diffs = filter_case_diffs(couch_case, sql_case_json, diffs,
                                      statedb)
            if diffs and not sql_case.is_deleted:
                try:
                    couch_case, diffs = self._rebuild_couch_case_and_re_diff(
                        couch_case, sql_case_json)
                except Exception as err:
                    log.warning('Case {} rebuild -> {}: {}'.format(
                        sql_case.case_id,
                        type(err).__name__, err))
            if diffs:
                statedb.add_diffs(couch_case['doc_type'], sql_case.case_id,
                                  diffs)
            counts[couch_case['doc_type']] += 1

        self._diff_ledgers(case_ids)

        if len(case_ids) != len(sql_case_ids):
            couch_ids = set(case_ids)
            assert not (sql_case_ids - couch_ids), sql_case_ids - couch_ids
            missing_cases = [couch_cases[x] for x in couch_ids - sql_case_ids]
            log.debug("Found %s missing SQL cases", len(missing_cases))
            for doc_type, doc_ids in self._filter_missing_cases(missing_cases):
                statedb.add_missing_docs(doc_type, doc_ids)
                counts[doc_type] += len(doc_ids)

        for doc_type, count in six.iteritems(counts):
            statedb.increment_counter(doc_type, count)
        self.processed_docs += len(case_ids)
        self._log_case_diff_count(throttled=True)
示例#58
0
def get_case_ids_for_reassignment(domain, location_id):
    """
    :return: for cases that belong to location_id return
    a dict mapping for all case ids under a household id and
    a list of all other case ids
    """
    all_case_ids = CaseAccessorSQL.get_case_ids_in_domain_by_owners(domain, [location_id])
    all_cases = CaseAccessors(domain).get_cases(all_case_ids)
    other_case_ids = set([case.case_id for case in all_cases if case.type not in CASE_TYPES_TO_IGNORE])
    child_case_ids_per_household_id = {}
    for household_case_id in get_household_case_ids(domain, location_id):
        household_child_case_ids = get_household_child_case_ids_by_owner(
            domain, household_case_id, location_id)
        other_case_ids.remove(household_case_id)
        other_case_ids = other_case_ids - set(household_child_case_ids)
        child_case_ids_per_household_id[household_case_id] = household_child_case_ids
    return child_case_ids_per_household_id, list(other_case_ids)
示例#59
0
    def delete_all_v2_ledgers(domain=None):
        logger.debug("Deleting all V2 ledgers for domain %s", domain)

        def _delete_ledgers_for_case(case_id):
            transactions = LedgerAccessorSQL.get_ledger_transactions_for_case(case_id)
            form_ids = {tx.form_id for tx in transactions}
            for form_id in form_ids:
                LedgerAccessorSQL.delete_ledger_transactions_for_form([case_id], form_id)
            LedgerAccessorSQL.delete_ledger_values(case_id)

        if not domain:
            for db in get_sql_db_aliases_in_use():
                for ledger in LedgerReindexAccessor().get_docs(db, None, limit=10000):
                    _delete_ledgers_for_case(ledger.case_id)
        else:
            for case_id in CaseAccessorSQL.get_case_ids_in_domain(domain):
                _delete_ledgers_for_case(case_id)
示例#60
0
def get_case_transactions(case_id, updated_xforms=None):
    """
    This fetches all the transactions required to rebuild the case along
    with all the forms for those transactions.

    For any forms that have been updated it replaces the old form
    with the new one.

    :param case_id: ID of case to rebuild
    :param updated_xforms: list of forms that have been changed.
    :return: list of ``CaseTransaction`` objects with their associated forms attached.
    """
    transactions = CaseAccessorSQL.get_transactions_for_case_rebuild(case_id)
    form_ids = {tx.form_id for tx in transactions}
    updated_xforms_map = {
        xform.form_id: xform
        for xform in updated_xforms if not xform.is_deprecated
    } if updated_xforms else {}

    form_ids_to_fetch = list(form_ids - set(updated_xforms_map.keys()))
    xform_map = {
        form.form_id: form
        for form in FormAccessorSQL.get_forms_with_attachments_meta(
            form_ids_to_fetch)
    }

    def get_form(form_id):
        if form_id in updated_xforms_map:
            return updated_xforms_map[form_id]

        try:
            return xform_map[form_id]
        except KeyError:
            raise XFormNotFound

    for transaction in transactions:
        if transaction.form_id:
            try:
                transaction.cached_form = get_form(transaction.form_id)
            except XFormNotFound:
                logging.error('Form not found during rebuild: %s',
                              transaction.form_id)

    return transactions