def close_cases_assigned_to_checkin(checkin_case, rule): if checkin_case.type != "checkin": return CaseRuleActionResult() blank_properties = { "assigned_to_primary_checkin_case_id": "", "is_assigned_primary": "", "assigned_to_primary_name": "", "assigned_to_primary_username": "", } num_related_updates = 0 for assigned_case in _get_assigned_cases(checkin_case): num_related_updates += 1 (submission, cases) = update_case( assigned_case.domain, assigned_case.case_id, case_properties=blank_properties, xmlns=AUTO_UPDATE_XMLNS, device_id=__name__ + ".close_cases_assigned_to_checkin", ) rule.log_submission(submission.form_id) (close_checkin_submission, cases) = update_case( checkin_case.domain, checkin_case.case_id, close=True, xmlns=AUTO_UPDATE_XMLNS, device_id=__name__ + ".close_cases_assigned_to_checkin", ) rule.log_submission(close_checkin_submission.form_id) return CaseRuleActionResult( num_closes=1, num_related_updates=num_related_updates, )
def close_cases_assigned_to_checkin(checkin_case, rule): """ For any associated checkin case that matches the rule criteria, the following occurs: 1. For all cases of a given type, find all assigned cases. \ An assigned case is a case for which all of the following are true: - Case type patient or contact - Exists in the same domain as the user case - The case property assigned_to_primary_checkin_case_id equals an associated checkin case's case_id 2. For every assigned case, the following case properties are blanked out (set to ""): - assigned_to_primary_checkin_case_id - is_assigned_primary - assigned_to_primary_name - assigned_to_primary_username """ if checkin_case.type != "checkin": return CaseRuleActionResult() blank_properties = { "assigned_to_primary_checkin_case_id": "", "is_assigned_primary": "", "assigned_to_primary_name": "", "assigned_to_primary_username": "", } num_related_updates = 0 for assigned_case_domain, assigned_case_id in _get_assigned_cases( checkin_case): num_related_updates += 1 (submission, cases) = update_case( assigned_case_domain, assigned_case_id, case_properties=blank_properties, xmlns=AUTO_UPDATE_XMLNS, device_id=__name__ + ".close_cases_assigned_to_checkin", ) rule.log_submission(submission.form_id) (close_checkin_submission, cases) = update_case( checkin_case.domain, checkin_case.case_id, close=True, xmlns=AUTO_UPDATE_XMLNS, device_id=__name__ + ".close_cases_assigned_to_checkin", ) rule.log_submission(close_checkin_submission.form_id) return CaseRuleActionResult( num_closes=1, num_related_updates=num_related_updates, )
def close_cases_assigned_to_checkin(checkin_case, rule): """ For any associated checkin case that matches the rule criteria, the following occurs: 1) For all cases of type [x] find all fields where [assigned_to_primary_checkin_case_id] is set to the case ID of the associated checkin case. These are the assigned cases. 2) For every assigned case, the following case properties are blanked out (set to ""): - assigned_to_primary_checkin_case_id - is_assigned_primary - assigned_to_primary_name - assigned_to_primary_username """ if checkin_case.type != "checkin": return CaseRuleActionResult() blank_properties = { "assigned_to_primary_checkin_case_id": "", "is_assigned_primary": "", "assigned_to_primary_name": "", "assigned_to_primary_username": "", } num_related_updates = 0 for assigned_case in _get_assigned_cases(checkin_case): num_related_updates += 1 (submission, cases) = update_case( assigned_case.domain, assigned_case.case_id, case_properties=blank_properties, xmlns=AUTO_UPDATE_XMLNS, device_id=__name__ + ".close_cases_assigned_to_checkin", ) rule.log_submission(submission.form_id) (close_checkin_submission, cases) = update_case( checkin_case.domain, checkin_case.case_id, close=True, xmlns=AUTO_UPDATE_XMLNS, device_id=__name__ + ".close_cases_assigned_to_checkin", ) rule.log_submission(close_checkin_submission.form_id) return CaseRuleActionResult( num_closes=1, num_related_updates=num_related_updates, )
def run_case_update_rules_for_domain_and_db(domain, now, run_id, db=None): domain_obj = Domain.get_by_name(domain) max_allowed_updates = domain_obj.auto_case_update_limit or settings.MAX_RULE_UPDATES_IN_ONE_RUN start_run = datetime.utcnow() last_migration_check_time = None cases_checked = 0 case_update_result = CaseRuleActionResult() all_rules = list( AutomaticUpdateRule.by_domain( domain, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE)) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type( all_rules) for case_type, rules in six.iteritems(rules_by_case_type): boundary_date = AutomaticUpdateRule.get_boundary_date(rules, now) case_ids = list( AutomaticUpdateRule.get_case_ids(domain, case_type, boundary_date, db=db)) for case in CaseAccessors(domain).iter_cases(case_ids): migration_in_progress, last_migration_check_time = check_data_migration_in_progress( domain, last_migration_check_time) time_elapsed = datetime.utcnow() - start_run if (time_elapsed.seconds > HALT_AFTER or case_update_result.total_updates >= max_allowed_updates or migration_in_progress): DomainCaseRuleRun.done(run_id, DomainCaseRuleRun.STATUS_HALTED, cases_checked, case_update_result, db=db) notify_error("Halting rule run for domain %s." % domain) return case_update_result.add_result(run_rules_for_case(case, rules, now)) cases_checked += 1 run = DomainCaseRuleRun.done(run_id, DomainCaseRuleRun.STATUS_FINISHED, cases_checked, case_update_result, db=db) if run.status == DomainCaseRuleRun.STATUS_FINISHED: for rule in all_rules: AutomaticUpdateRule.objects.filter(pk=rule.pk).update(last_run=now)
def sanitize_session_peer_rating(session_case, rule): """ For any session case sanitize the peer_rating metrics based on child cases of type peer_rating """ if session_case.type != SESSION_CASE_TYPE: return CaseRuleActionResult() peer_rating_cases = _get_peer_rating_cases(session_case) num_updates = 0 if peer_rating_cases: case_updates = _get_case_updates(peer_rating_cases) (submission, cases) = update_case( session_case.domain, session_case.case_id, case_properties=case_updates, xmlns=AUTO_UPDATE_XMLNS, device_id=__name__ + ".sanitize_session_peer_rating", ) num_updates = 1 rule.log_submission(submission.form_id) return CaseRuleActionResult(num_updates=num_updates, )
def run_case_update_rules_for_domain(domain, now=None): domain_obj = Domain.get_by_name(domain) max_allowed_updates = domain_obj.auto_case_update_limit or settings.MAX_RULE_UPDATES_IN_ONE_RUN now = now or datetime.utcnow() start_run = datetime.utcnow() last_migration_check_time = None run_record = DomainCaseRuleRun.objects.create( domain=domain, started_on=start_run, status=DomainCaseRuleRun.STATUS_RUNNING, ) cases_checked = 0 case_update_result = CaseRuleActionResult() all_rules = AutomaticUpdateRule.by_domain( domain, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type( all_rules) for case_type, rules in six.iteritems(rules_by_case_type): boundary_date = AutomaticUpdateRule.get_boundary_date(rules, now) case_ids = list( AutomaticUpdateRule.get_case_ids(domain, case_type, boundary_date)) for case in CaseAccessors(domain).iter_cases(case_ids): migration_in_progress, last_migration_check_time = check_data_migration_in_progress( domain, last_migration_check_time) time_elapsed = datetime.utcnow() - start_run if (time_elapsed.seconds > HALT_AFTER or case_update_result.total_updates >= max_allowed_updates or migration_in_progress): run_record.done(DomainCaseRuleRun.STATUS_HALTED, cases_checked, case_update_result) notify_error("Halting rule run for domain %s." % domain) return case_update_result.add_result(run_rules_for_case(case, rules, now)) cases_checked += 1 for rule in rules: rule.last_run = now rule.save() run_record.done(DomainCaseRuleRun.STATUS_FINISHED, cases_checked, case_update_result)
def iter_cases_and_run_rules(domain, case_iterator, rules, now, run_id, case_type, db=None, progress_helper=None): from corehq.apps.data_interfaces.models import ( CaseRuleActionResult, DomainCaseRuleRun, ) HALT_AFTER = 23 * 60 * 60 domain_obj = Domain.get_by_name(domain) max_allowed_updates = domain_obj.auto_case_update_limit or settings.MAX_RULE_UPDATES_IN_ONE_RUN start_run = datetime.utcnow() case_update_result = CaseRuleActionResult() cases_checked = 0 last_migration_check_time = None for case in case_iterator: migration_in_progress, last_migration_check_time = _check_data_migration_in_progress( domain, last_migration_check_time) time_elapsed = datetime.utcnow() - start_run if (time_elapsed.seconds > HALT_AFTER or case_update_result.total_updates >= max_allowed_updates or migration_in_progress): notify_error("Halting rule run for domain %s and case type %s." % (domain, case_type)) return DomainCaseRuleRun.done(run_id, cases_checked, case_update_result, db=db, halted=True) case_update_result.add_result(run_rules_for_case(case, rules, now)) if progress_helper is not None: progress_helper.increment_current_case_count() cases_checked += 1 return DomainCaseRuleRun.done(run_id, cases_checked, case_update_result, db=db)
def run_case_update_rules_for_domain(domain, now=None): now = now or datetime.utcnow() start_run = datetime.utcnow() run_record = DomainCaseRuleRun.objects.create( domain=domain, started_on=start_run, status=DomainCaseRuleRun.STATUS_RUNNING, ) cases_checked = 0 case_update_result = CaseRuleActionResult() all_rules = AutomaticUpdateRule.by_domain(domain) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(all_rules) for case_type, rules in rules_by_case_type.iteritems(): boundary_date = AutomaticUpdateRule.get_boundary_date(rules, now) case_id_chunks = AutomaticUpdateRule.get_case_ids(domain, case_type, boundary_date) for case_ids in case_id_chunks: for case in CaseAccessors(domain).iter_cases(case_ids): time_elapsed = datetime.utcnow() - start_run if ( time_elapsed.seconds > HALT_AFTER or case_update_result.total_updates >= settings.MAX_RULE_UPDATES_IN_ONE_RUN ): run_record.done(DomainCaseRuleRun.STATUS_HALTED, cases_checked, case_update_result) notify_error("Halting rule run for domain %s." % domain) return case_update_result.add_result(run_rules_for_case(case, rules, now)) cases_checked += 1 for rule in rules: rule.last_run = now rule.save() run_record.done(DomainCaseRuleRun.STATUS_FINISHED, cases_checked, case_update_result)
ignore_result=True ) def run_case_update_rules(now=None): domains = (AutomaticUpdateRule .objects .filter(active=True, deleted=False) .values_list('domain', flat=True) .distinct() .order_by('domain')) for domain in domains: if not DATA_MIGRATION.enabled(domain): run_case_update_rules_for_domain.delay(domain, now) def run_rules_for_case(case, rules, now): aggregated_result = CaseRuleActionResult() last_result = None for rule in rules: if last_result: if ( last_result.num_updates > 0 or last_result.num_related_updates > 0 or last_result.num_related_closes > 0 ): case = CaseAccessors(case.domain).get_case(case.case_id) last_result = rule.run_rule(case, now) aggregated_result.add_result(last_result) if last_result.num_closes > 0: break
device_id=__name__ + "._update_tech_issue_for_escalation", ) def _get_escalated_tech_issue_delegate(tech_issue, location_id): for subcase in tech_issue.get_subcases(index_identifier='parent'): if (subcase.type == 'tech_issue_delegate' and subcase.owner_id == location_id and not subcase.closed): return subcase return None def escalate_tech_issue(case, rule): if case.type != 'tech_issue': return CaseRuleActionResult() escalated_ticket_level_map = { 'supervisor': 'block', 'block': 'district', 'district': 'state', } current_location_id_map = { 'supervisor': case.get_case_property('supervisor_location_id'), 'block': case.get_case_property('block_location_id'), 'district': case.get_case_property('district_location_id'), } escalated_location_id_map = { 'supervisor': case.get_case_property('block_location_id'),
from corehq.apps.domain.models import Domain from corehq.apps.es.case_search import CaseSearchES from corehq.apps.es.cases import case_type from corehq.apps.data_interfaces.models import CaseRuleActionResult, AUTO_UPDATE_XMLNS from corehq.apps.hqcase.utils import update_case from corehq.apps.es import filters def set_all_activity_complete_date_to_today(case, rule): """ For any case matching the criteria, set the all_activity_complete_date property to today's date, in YYYY-MM-DD format, based on the domain's default time zone. """ if case.get_case_property("all_activity_complete_date"): return CaseRuleActionResult() from dimagi.utils.parsing import ISO_DATE_FORMAT domain_obj = Domain.get_by_name(case.domain) today = datetime.now( domain_obj.get_default_timezone()).strftime(ISO_DATE_FORMAT) (submission, cases) = update_case( case.domain, case.case_id, case_properties={ "all_activity_complete_date": today, }, xmlns=AUTO_UPDATE_XMLNS, device_id=__name__ + ".set_all_activity_complete_date_to_today", ) rule.log_submission(submission.form_id)
case_update_result, db=db) def _check_data_migration_in_progress(domain, last_migration_check_time): utcnow = datetime.utcnow() if last_migration_check_time is None or ( utcnow - last_migration_check_time) > timedelta(minutes=1): return any_migrations_in_progress(domain), utcnow return False, last_migration_check_time def run_rules_for_case(case, rules, now): from corehq.apps.data_interfaces.models import CaseRuleActionResult aggregated_result = CaseRuleActionResult() last_result = None for rule in rules: if last_result: if (last_result.num_updates > 0 or last_result.num_related_updates > 0 or last_result.num_related_closes > 0): case = CommCareCase.objects.get_case(case.case_id, case.domain) try: last_result = rule.run_rule(case, now) except Exception: last_result = CaseRuleActionResult(num_errors=1) notify_exception( None, "Error applying case update rule", { 'domain': case.domain,