예제 #1
0
class Command(BaseCommand):

    def add_arguments(self, parser):
        parser.add_argument(
            'domain',
            help="File path for log file",
        )
        parser.add_argument(
            'log_file',
            help="File path for log file",
        )

    def handle(self, domain, log_file, **options):
        total_cases = CaseES().domain(domain).case_type('household').is_closed().count()
        self.case_accessor = CaseAccessors(domain)
        failed_updates = []
        with open(log_file, "w", encoding='utf-8') as fh:
            fh.write('--------Successful Form Ids----------\n')
            for cases in chunked(with_progress_bar(self._get_cases_to_process(domain), total_cases), 100):
                related_cases = self._get_related_cases(cases)
                case_tupes = [(case_id, {}, True) for case_id in related_cases]
                try:
                    xform, cases = bulk_update_cases(
                        domain, case_tupes, self.__module__)
                    fh.write(xform.form_id + '\n')
                except LocalSubmissionError as e:
                    print('submission error')
                    print(six.text_type(e))
                    failed_updates.extend(related_cases)
                except Exception as e:
                    print('unexpected error')
                    print(six.text_type(e))
                    failed_updates.extend(related_cases)
            fh.write('--------Failed Cases--------------\n')
            for case_id in failed_updates:
                fh.write(case_id)
            print('-------------COMPLETE--------------')

    def _get_cases_to_process(self, domain):
        from corehq.sql_db.util import get_db_aliases_for_partitioned_query
        dbs = get_db_aliases_for_partitioned_query()
        for db in dbs:
            cases = CommCareCaseSQL.objects.using(db).filter(domain=domain, type='household', closed=True)
            for case in cases:
                yield case.case_id

    def _get_related_cases(self, cases):
        related_cases = {case.case_id for case in self.case_accessor.get_all_reverse_indices_info(list(cases))
                         if case.relationship == CommCareCaseIndexSQL.CHILD}
        related_cases |= {case.case_id for case in
                          self.case_accessor.get_all_reverse_indices_info(list(related_cases))
                         if case.relationship == CommCareCaseIndexSQL.CHILD}
        return related_cases
예제 #2
0
def get_cleanliness_flag_from_scratch(domain, owner_id):
    casedb = CaseAccessors(domain)
    footprint_info = get_case_footprint_info(domain, owner_id)
    owned_cases = footprint_info.base_ids
    cases_to_check = footprint_info.all_ids - owned_cases
    if cases_to_check:
        closed_owned_case_ids = set(casedb.get_closed_case_ids_for_owner(owner_id))
        cases_to_check = cases_to_check - closed_owned_case_ids - footprint_info.extension_ids
        # check extension cases that are unowned or owned by others
        extension_cases_to_check = footprint_info.extension_ids - closed_owned_case_ids - owned_cases
        while extension_cases_to_check:
            extension_case = extension_cases_to_check.pop()
            dependent_cases = set(get_dependent_case_info(domain, [extension_case]).all_ids)
            unowned_dependent_cases = dependent_cases - owned_cases
            extension_cases_to_check = extension_cases_to_check - dependent_cases
            dependent_cases_owned_by_other_owners = {
                dependent_case.case_id
                for dependent_case in casedb.get_cases(list(unowned_dependent_cases))
                if dependent_case.owner_id != UNOWNED_EXTENSION_OWNER_ID
            }
            if dependent_cases_owned_by_other_owners:
                hint_id = dependent_cases & owned_cases
                # can't get back from extension case to owned case e.g. host is a child of owned case
                if hint_id:
                    return CleanlinessFlag(False, hint_id.pop())

        if cases_to_check:
            # it wasn't in any of the open or closed IDs - it must be dirty
            reverse_index_infos = casedb.get_all_reverse_indices_info(list(cases_to_check))
            reverse_index_ids = set([r.case_id for r in reverse_index_infos])
            indexed_with_right_owner = (reverse_index_ids & (owned_cases | closed_owned_case_ids))
            found_deleted_cases = False
            while indexed_with_right_owner:
                hint_id = indexed_with_right_owner.pop()
                infos_for_this_owner = _get_info_by_case_id(reverse_index_infos, hint_id)
                for info in infos_for_this_owner:
                    try:
                        case = CaseAccessors(domain).get_case(info.referenced_id)
                        if not case.is_deleted:
                            return CleanlinessFlag(False, hint_id)
                        else:
                            found_deleted_cases = True
                    except ResourceNotFound:
                        # the case doesn't exist - don't use it as a dirty flag
                        found_deleted_cases = True

            if found_deleted_cases:
                # if we made it all the way to the end of the loop without returning anything
                # then the owner was only flagged as dirty due to missing cases,
                # This implies the owner is still clean.
                return CleanlinessFlag(True, None)
            else:
                # I don't believe code can ever be hit, but if it is we should fail hard
                # until we can better understand it.
                raise IllegalCaseId('Owner {} in domain {} has an invalid index reference chain!!'.format(
                    owner_id, domain
                ))

    return CleanlinessFlag(True, None)
예제 #3
0
def get_cleanliness_flag_from_scratch(domain, owner_id):
    casedb = CaseAccessors(domain)
    footprint_info = get_case_footprint_info(domain, owner_id)
    owned_cases = footprint_info.base_ids
    cases_to_check = footprint_info.all_ids - owned_cases
    if cases_to_check:
        closed_owned_case_ids = set(casedb.get_closed_case_ids_for_owner(owner_id))
        cases_to_check = cases_to_check - closed_owned_case_ids - footprint_info.extension_ids
        # check extension cases that are unowned or owned by others
        extension_cases_to_check = footprint_info.extension_ids - closed_owned_case_ids - owned_cases
        while extension_cases_to_check:
            extension_case = extension_cases_to_check.pop()
            dependent_cases = set(get_dependent_case_info(domain, [extension_case]).all_ids)
            unowned_dependent_cases = dependent_cases - owned_cases
            extension_cases_to_check = extension_cases_to_check - dependent_cases
            dependent_cases_owned_by_other_owners = {
                dependent_case.case_id
                for dependent_case in casedb.get_cases(list(unowned_dependent_cases))
                if dependent_case.owner_id != UNOWNED_EXTENSION_OWNER_ID
            }
            if dependent_cases_owned_by_other_owners:
                hint_id = dependent_cases & owned_cases
                # can't get back from extension case to owned case e.g. host is a child of owned case
                if hint_id:
                    return CleanlinessFlag(False, hint_id.pop())

        if cases_to_check:
            # it wasn't in any of the open or closed IDs - it must be dirty
            reverse_index_infos = casedb.get_all_reverse_indices_info(list(cases_to_check))
            reverse_index_ids = set([r.case_id for r in reverse_index_infos])
            indexed_with_right_owner = (reverse_index_ids & (owned_cases | closed_owned_case_ids))
            found_deleted_cases = False
            while indexed_with_right_owner:
                hint_id = indexed_with_right_owner.pop()
                infos_for_this_owner = _get_info_by_case_id(reverse_index_infos, hint_id)
                for info in infos_for_this_owner:
                    try:
                        case = CaseAccessors(domain).get_case(info.referenced_id)
                        if not case.is_deleted:
                            return CleanlinessFlag(False, hint_id)
                        else:
                            found_deleted_cases = True
                    except ResourceNotFound:
                        # the case doesn't exist - don't use it as a dirty flag
                        found_deleted_cases = True

            if found_deleted_cases:
                # if we made it all the way to the end of the loop without returning anything
                # then the owner was only flagged as dirty due to missing cases,
                # This implies the owner is still clean.
                return CleanlinessFlag(True, None)
            else:
                # I don't believe code can ever be hit, but if it is we should fail hard
                # until we can better understand it.
                raise IllegalCaseId('Owner {} in domain {} has an invalid index reference chain!!'.format(
                    owner_id, domain
                ))
예제 #4
0
class Command(BaseCommand):
    def add_arguments(self, parser):
        parser.add_argument(
            'domain',
            help="File path for log file",
        )
        parser.add_argument(
            'log_file',
            help="File path for log file",
        )

    def handle(self, domain, log_file, **options):
        total_cases = CaseES().domain(domain).case_type(
            'household').is_closed().count()
        self.case_accessor = CaseAccessors(domain)
        failed_updates = []
        with open(log_file, "w", encoding='utf-8') as fh:
            fh.write('--------Successful Form Ids----------\n')
            for cases in chunked(
                    with_progress_bar(self._get_cases_to_process(domain),
                                      total_cases), 100):
                related_cases = self._get_related_cases(cases)
                case_tupes = [(case_id, {}, True) for case_id in related_cases]
                try:
                    xform, cases = bulk_update_cases(domain, case_tupes,
                                                     self.__module__)
                    fh.write(xform.form_id + '\n')
                except LocalSubmissionError as e:
                    print('submission error')
                    print(six.text_type(e))
                    failed_updates.extend(related_cases)
                except Exception as e:
                    print('unexpected error')
                    print(six.text_type(e))
                    failed_updates.extend(related_cases)
            fh.write('--------Failed Cases--------------\n')
            for case_id in failed_updates:
                fh.write(case_id)
            print('-------------COMPLETE--------------')

    def _get_cases_to_process(self, domain):
        from corehq.sql_db.util import get_db_aliases_for_partitioned_query
        dbs = get_db_aliases_for_partitioned_query()
        for db in dbs:
            cases = CommCareCaseSQL.objects.using(db).filter(domain=domain,
                                                             type='household',
                                                             closed=True)
            for case in cases:
                yield case.case_id

    def _get_related_cases(self, cases):
        related_cases = {
            case.case_id
            for case in self.case_accessor.get_all_reverse_indices_info(
                list(cases)) if case.relationship == CommCareCaseIndexSQL.CHILD
        }