Example #1
0
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,
    )
Example #2
0
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,
    )
Example #4
0
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)
Example #5
0
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, )
Example #6
0
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)
Example #7
0
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)
Example #8
0
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)
Example #9
0
    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'),
Example #11
0
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)
Example #12
0
                                  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,