def handle(self, *args, **options): domain = options["domain"] case_id = options["case_id"] case_accessor = CaseAccessors(domain=domain) case = case_accessor.get_case(case_id) if ( not case.is_deleted and raw_input( "\n".join(["Case {} is not already deleted. Are you sure you want to delete it? (y/N)".format(case_id)]) ).lower() != "y" ): sys.exit(0) dependent_case_ids = get_entire_case_network(domain, [case_id]) cases_to_delete = filter(lambda case: not case.is_deleted, case_accessor.get_cases(dependent_case_ids)) if cases_to_delete: with open(options["filename"], "w") as csvfile: writer = csv.writer(csvfile) headers = ["case id", "case type", "owner", "opened by", "app version"] writer.writerow(headers) print headers for case in cases_to_delete: form = FormAccessors(domain=domain).get_form(case.xform_ids[0]) app_version_info = get_app_version_info( domain, form.build_id, form.form_data["@version"], form.metadata ) row = [ case.case_id, case.type, cached_owner_id_to_display(case.owner_id) or case.owner_id, cached_owner_id_to_display(case.opened_by), app_version_info.build_version, ] writer.writerow(row) print row if ( cases_to_delete and raw_input("\n".join(["Delete these {} cases? (y/N)".format(len(cases_to_delete))])).lower() == "y" ): case_accessor.soft_delete_cases([c.case_id for c in cases_to_delete]) print "deleted {} cases".format(len(cases_to_delete)) if cases_to_delete: print "details here: {}".format(options["filename"]) else: print "didn't find any cases to delete"
def related_cases_columns(self): return [ { 'name': _('Status'), 'expr': "status" }, { 'name': _('Case Type'), 'expr': "type", }, { 'name': _('Owner'), 'expr': lambda c: cached_owner_id_to_display(c.get('owner_id')), }, { 'name': _('Date Opened'), 'expr': "opened_on", 'parse_date': True, "is_phone_time": True, }, { 'name': _('Date Modified'), 'expr': "modified_on", 'parse_date': True, "is_phone_time": True, } ]
def related_cases_columns(self): return [ { 'name': _('Status'), 'expr': "status" }, { 'name': _('Case Type'), 'expr': "type", }, { 'name': _('Owner'), 'expr': lambda c: cached_owner_id_to_display(c.get('owner_id')), }, { 'name': _('Date Opened'), 'expr': "opened_on", 'parse_date': True, "is_phone_time": True, }, { 'name': _('Date Modified'), 'expr': "modified_on", 'parse_date': True, "is_phone_time": True, } ]
def related_cases_columns(self): return [ DisplayConfig(name=_('Status'), expr='status'), DisplayConfig(name=_('Case Type'), expr='type'), DisplayConfig( name=_('Owner'), expr=lambda c: cached_owner_id_to_display(c.get('owner_id'))), DisplayConfig(name=_('Date Opened'), expr='opened_on', process="date", is_phone_time=True), DisplayConfig(name=_('Date Modified'), expr='modified_on', process="date", is_phone_time=True), ]
def owner_id_to_display(owner_id, doc): return cached_owner_id_to_display(owner_id)
def handle(self, **options): domain = options['domain'] debug = options['debug'] cleanup = options['cleanup'] domain_query = CaseES().domain(domain) valid_case_ids = set(domain_query.get_ids()) referenced_case_ids = { index['referenced_id'] for hit in domain_query.source('indices.referenced_id').run().hits for index in hit['indices'] } invalid_referenced_ids = referenced_case_ids - valid_case_ids if len(invalid_referenced_ids) > ES_MAX_CLAUSE_COUNT: print("there's a lot of invalid ids here. ES queries may not handle this well") cases_with_invalid_references = ( domain_query .term('indices.referenced_id', invalid_referenced_ids) .source(['_id', 'type', 'indices', 'owner_id', 'opened_by', 'xform_ids']) .run().hits ) with open(options['filename'], 'w', encoding='utf-8') as csvfile: writer = csv.writer(csvfile) headers = [ 'case id', 'case type', 'creating form id', 'referenced id', 'referenced_type', 'index relationship', 'index identifier', 'owner id', 'owner name', 'opened by id', 'opened by name', ] if debug: headers.append('app version') writer.writerow(headers) for case in cases_with_invalid_references: for index in case['indices']: if index['referenced_id'] in invalid_referenced_ids: form_id = case['xform_ids'][0] row = [ case['_id'], case['type'], form_id, index['referenced_id'], index['referenced_type'], index['relationship'], index['identifier'], case['owner_id'], cached_owner_id_to_display(case['owner_id']), case['opened_by'], cached_owner_id_to_display(case['opened_by']), ] if debug: form = FormAccessors(domain=domain).get_form(form_id) app_version_info = get_app_version_info( domain, form.build_id, form.form_data['@version'], form.metadata, ) row.append(app_version_info.build_version) writer.writerow(row) if cleanup: missing = set() deleted = set() exists = set() for invalid_id in invalid_referenced_ids: try: case = CaseAccessors(domain).get_case(invalid_id) except CaseNotFound: missing.add(invalid_id) else: if case.is_deleted: deleted.add(case) else: exists.add(case) for case_to_resync in exists: # if the case actually exists resync it to fix the es search resave_case(domain, case_to_resync, send_post_save_signal=False) if exists: print('resynced {} cases that were actually not deleted'.format(len(exists))) for case in deleted: # delete the deleted case's entire network in one go call_command('delete_related_cases', domain, case.case_id) for case in cases_with_invalid_references: for index in case['indices']: if index['referenced_id'] in missing: # this is just an invalid reference. no recourse but to delete the case itself call_command('delete_related_cases', domain, case['_id'])
def owner_id_to_display(owner_id, doc): return cached_owner_id_to_display(owner_id)