def setUp(self):
        self.domain = 'auto-update-test'
        self.case_db = CaseAccessors(self.domain)
        self.factory = CaseFactory(self.domain)
        self.rule = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule',
            case_type='test-case-type',
            active=True,
            server_modified_boundary=30,
        )
        self.rule.save()
        self.rule.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='last_visit_date',
                property_value='30',
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
            ),
        ]
        self.rule.automaticupdateaction_set = [
            AutomaticUpdateAction(
                action=AutomaticUpdateAction.ACTION_UPDATE,
                property_name='update_flag',
                property_value='Y',
            ),
            AutomaticUpdateAction(action=AutomaticUpdateAction.ACTION_CLOSE, ),
        ]

        self.rule2 = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule-2',
            case_type='test-case-type-2',
            active=True,
            server_modified_boundary=30,
        )
        self.rule2.save()
        self.rule2.automaticupdateaction_set = [
            AutomaticUpdateAction(action=AutomaticUpdateAction.ACTION_CLOSE, ),
        ]

        self.rule3 = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule-3',
            case_type='test-case-type-2',
            active=True,
            server_modified_boundary=50,
        )
        self.rule3.save()
        self.rule3.automaticupdateaction_set = [
            AutomaticUpdateAction(action=AutomaticUpdateAction.ACTION_CLOSE, ),
        ]

        with drop_connected_signals(case_post_save):
            case = self.factory.create_case(case_type='test-case-type')
Exemplo n.º 2
0
    def post(self, request, *args, **kwargs):
        rule_form_valid = self.rule_form.is_valid()
        criteria_form_valid = self.criteria_form.is_valid()
        actions_form_valid = self.actions_form.is_valid()

        if self.read_only_mode:
            # Don't allow making changes to rules that have custom
            # criteria/actions unless the user has permission to
            return HttpResponseBadRequest()

        if rule_form_valid and criteria_form_valid and actions_form_valid:
            if not self.is_system_admin and (
                self.criteria_form.requires_system_admin_to_save or
                self.actions_form.requires_system_admin_to_save
            ):
                # Don't allow adding custom criteria/actions to rules
                # unless the user has permission to
                return HttpResponseBadRequest()

            with transaction.atomic():
                if self.initial_rule:
                    rule = self.initial_rule
                else:
                    rule = AutomaticUpdateRule(
                        domain=self.domain,
                        active=True,
                        workflow=AutomaticUpdateRule.WORKFLOW_CASE_UPDATE,
                    )

                rule.name = self.rule_form.cleaned_data['name']
                self.criteria_form.save_criteria(rule)
                self.actions_form.save_actions(rule)
            return HttpResponseRedirect(reverse(AutomaticUpdateRuleListView.urlname, args=[self.domain]))

        return self.get(request, *args, **kwargs)
Exemplo n.º 3
0
    def test_parent_cases(self):
        with _with_case(self.domain, 'test-child-case-type', datetime(2016, 1, 1)) as child, \
                _with_case(self.domain, 'test-parent-case-type', datetime(2016, 1, 1), case_name='abc') as parent:

            # Set the parent case relationship
            child = set_parent_case(self.domain, child, parent)

            # Create a rule that references parent/name which should match
            rule = AutomaticUpdateRule(
                domain=self.domain,
                name='test-parent-rule',
                case_type='test-child-case-type',
                active=True,
                server_modified_boundary=30,
            )
            rule.save()
            self.addCleanup(rule.delete)
            AutomaticUpdateRuleCriteria.objects.create(
                property_name='parent/name',
                property_value='abc',
                match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                rule=rule,
            )
            AutomaticUpdateAction.objects.create(
                action=AutomaticUpdateAction.ACTION_UPDATE,
                property_name='parent/update_flag',
                property_value='P',
                rule=rule,
            )
            AutomaticUpdateAction.objects.create(
                action=AutomaticUpdateAction.ACTION_UPDATE,
                property_name='parent_name',
                property_value='parent/name',
                property_value_type=AutomaticUpdateAction.CASE_PROPERTY,
                rule=rule,
            )

            # rule should match on parent case property and update parent case
            rule.apply_rule(child, datetime(2016, 3, 1))
            updated_parent = self.case_db.get_case(parent.case_id)
            updated_child = self.case_db.get_case(child.case_id)
            self.assertEqual(updated_parent.get_case_property('update_flag'),
                             'P')
            self.assertEqual(updated_child.get_case_property('parent_name'),
                             'abc')

            # Update the rule to match on a different name and now it shouldn't match
            rule.automaticupdaterulecriteria_set.all().delete()
            AutomaticUpdateRuleCriteria.objects.create(
                property_name='parent/name',
                property_value='def',
                match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                rule=rule,
            )

            self.assertFalse(
                rule.rule_matches_case(child, datetime(2016, 3, 1)))
Exemplo n.º 4
0
    def post(self, request, *args, **kwargs):
        if self.async_response is not None:
            return self.async_response

        basic_info_form_valid = self.basic_info_form.is_valid()
        criteria_form_valid = self.criteria_form.is_valid()
        schedule_form_valid = self.schedule_form.is_valid()

        if self.read_only_mode:
            # Don't allow making changes to rules that have custom
            # criteria/actions unless the user has permission to
            return HttpResponseBadRequest()

        if basic_info_form_valid and criteria_form_valid and schedule_form_valid:
            if not self.is_system_admin and (
                self.criteria_form.requires_system_admin_to_save or
                self.schedule_form.requires_system_admin_to_save
            ):
                # Don't allow adding custom criteria/actions to rules
                # unless the user has permission to
                return HttpResponseBadRequest()

            if not self.can_use_inbound_sms and self.schedule_form.uses_sms_survey:
                return HttpResponseBadRequest(
                    "Cannot create or edit survey reminders because subscription "
                    "does not have access to inbound SMS"
                )

            with transaction.atomic():
                if self.rule:
                    rule = self.rule
                else:
                    rule = AutomaticUpdateRule(
                        domain=self.domain,
                        active=True,
                        workflow=AutomaticUpdateRule.WORKFLOW_SCHEDULING,
                    )

                rule.name = self.basic_info_form.cleaned_data['name']
                self.criteria_form.save_criteria(rule)
                self.schedule_form.save_rule_action_and_schedule(rule)

            if not (
                self.new_reminders_migrator and
                self.schedule_form.cleaned_data['skip_running_rule_post_save']
            ):
                initiate_messaging_rule_run(rule.domain, rule.pk)
            return HttpResponseRedirect(reverse(ConditionalAlertListView.urlname, args=[self.domain]))

        return self.get(request, *args, **kwargs)
Exemplo n.º 5
0
    def test_auto_case_update_rules(self):
        from corehq.apps.data_interfaces.models import (
            AutomaticUpdateRule, AutomaticUpdateRuleCriteria,
            AutomaticUpdateAction)
        expected_object_counts = Counter({
            AutomaticUpdateRule: 1,
            AutomaticUpdateRuleCriteria: 1,
            AutomaticUpdateAction: 2,
        })
        register_cleanup(self, list(expected_object_counts), self.domain_name)

        pre_rule = AutomaticUpdateRule(
            domain=self.domain_name,
            name='test-rule',
            case_type='test-case-type',
            active=True,
            server_modified_boundary=30,
        )
        pre_rule.save()
        pre_criteria = AutomaticUpdateRuleCriteria.objects.create(
            property_name='last_visit_date',
            property_value='30',
            match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_AFTER,
            rule=pre_rule,
        )
        pre_action_update = AutomaticUpdateAction.objects.create(
            action=AutomaticUpdateAction.ACTION_UPDATE,
            property_name='update_flag',
            property_value='Y',
            rule=pre_rule,
        )
        pre_action_close = AutomaticUpdateAction.objects.create(
            action=AutomaticUpdateAction.ACTION_CLOSE,
            rule=pre_rule,
        )

        self._dump_and_load(expected_object_counts)

        post_rule = AutomaticUpdateRule.objects.get(pk=pre_rule.pk)
        post_criteria = AutomaticUpdateRuleCriteria.objects.get(
            pk=pre_criteria.pk)
        post_action_update = AutomaticUpdateAction.objects.get(
            pk=pre_action_update.pk)
        post_action_close = AutomaticUpdateAction.objects.get(
            pk=pre_action_close.pk)

        self.assertModelsEqual(
            [pre_rule, pre_criteria, pre_action_update, pre_action_close],
            [post_rule, post_criteria, post_action_update, post_action_close])
    def test_parent_case_lookup(self):
        with _with_case(self.domain, 'test-child-case-type', datetime(2016, 1, 1)) as child, \
                _with_case(self.domain, 'test-parent-case-type', datetime(2016, 1, 1), case_name='abc') as parent:

            # Set the parent case relationship
            child = set_parent_case(self.domain, child, parent)

            # Create a rule that references parent/name which should match
            rule = AutomaticUpdateRule(
                domain=self.domain,
                name='test-parent-rule',
                case_type='test-child-case-type',
                active=True,
                server_modified_boundary=30,
            )
            rule.save()
            self.addCleanup(rule.delete)
            rule.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='parent/name',
                    property_value='abc',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                ),
            ]

            self.assertTrue(rule.rule_matches_case(child, datetime(2016, 3,
                                                                   1)))

            # Update the rule to match on a different name and now it shouldn't match
            rule.automaticupdaterulecriteria_set.all().delete()
            rule.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='parent/name',
                    property_value='def',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                ),
            ]

            self.assertFalse(
                rule.rule_matches_case(child, datetime(2016, 3, 1)))
Exemplo n.º 7
0
    def setUp(self):

        test_rules = [
            AutomaticUpdateRule(
                domain=self.domain,
                active=True,
                workflow=AutomaticUpdateRule.WORKFLOW_CASE_UPDATE,
                name="Norway rule",
                case_type="person",
                filter_on_server_modified=True,
                server_modified_boundary=None),
            AutomaticUpdateRule(
                domain=self.domain,
                active=True,
                workflow=AutomaticUpdateRule.WORKFLOW_CASE_UPDATE,
                name="Is it hot enough?",
                case_type="person",
                filter_on_server_modified=False,
                server_modified_boundary=2),
            AutomaticUpdateRule(
                domain=self.domain,
                active=False,
                workflow=AutomaticUpdateRule.WORKFLOW_CASE_UPDATE,
                name="Closed parent case",
                case_type="family_member",
                filter_on_server_modified=True,
                server_modified_boundary=None),
        ]

        test_rules[0].save()
        test_rules[1].save()
        test_rules[2].save()

        # Create test rule criterias
        definition = MatchPropertyDefinition.objects.create(
            property_name="place",
            property_value="Norway",
            match_type=MatchPropertyDefinition.MATCH_EQUAL,
        )
        criteria = CaseRuleCriteria(rule=test_rules[0])
        criteria.definition = definition
        criteria.save()

        definition = MatchPropertyDefinition.objects.create(
            property_name="temperature",
            property_value="96",
            match_type=MatchPropertyDefinition.MATCH_EQUAL,
        )
        criteria = CaseRuleCriteria(rule=test_rules[1])
        criteria.definition = definition
        criteria.save()

        definition = CustomMatchDefinition.objects.create(
            name="COVID_US_ASSOCIATED_USER_CASES", )
        criteria = CaseRuleCriteria(rule=test_rules[0])
        criteria.definition = definition
        criteria.save()

        definition = ClosedParentDefinition.objects.create()
        criteria = CaseRuleCriteria(rule=test_rules[2])
        criteria.definition = definition
        criteria.save()

        # Create test rule actions
        definition = UpdateCaseDefinition(close_case=True)
        definition.save()
        action = CaseRuleAction(rule=test_rules[0])
        action.definition = definition
        action.save()

        definition = UpdateCaseDefinition(close_case=False)
        test_properties = []
        test_properties.append(
            UpdateCaseDefinition.PropertyDefinition(
                name="hot_enough",
                value_type="EXACT",
                value="true",
            ))
        test_properties.append(
            UpdateCaseDefinition.PropertyDefinition(
                name="territory_hot_enough",
                value_type="CASE_PROPERTY",
                value="current_territory",
            ))
        definition.set_properties_to_update(test_properties)
        definition.save()

        action = CaseRuleAction(rule=test_rules[1])
        action.definition = definition
        action.save()

        definition = CustomActionDefinition.objects.create(
            name="COVID_US_CLOSE_CASES_ASSIGNED_CHECKIN", )

        action = CaseRuleAction(rule=test_rules[1])
        action.definition = definition
        action.save()
Exemplo n.º 8
0
def update_auto_update_rules(domain_link):
    if domain_link.is_remote:
        upstream_rules = remote_get_auto_update_rules(domain_link)
    else:
        upstream_rules = local_get_auto_update_rules(domain_link.master_domain)

    downstream_rules = AutomaticUpdateRule.by_domain(
        domain_link.linked_domain,
        AutomaticUpdateRule.WORKFLOW_CASE_UPDATE,
        active_only=False
    )

    for upstream_rule_def in upstream_rules:
        # Grab local rule by upstream ID (preferred) or by name
        try:
            downstream_rule = downstream_rules.get(upstream_id=upstream_rule_def['rule']['id'])
        except AutomaticUpdateRule.DoesNotExist:
            try:
                downstream_rule = downstream_rules.get(name=upstream_rule_def['rule']['name'])
            except AutomaticUpdateRule.MultipleObjectsReturned:
                # If there are multiple rules with the same name, overwrite the first.
                downstream_rule = downstream_rules.filter(name=upstream_rule_def['rule']['name']).first()
            except AutomaticUpdateRule.DoesNotExist:
                downstream_rule = None

        # If no corresponding local rule, make a new rule
        if not downstream_rule:
            downstream_rule = AutomaticUpdateRule(
                domain=domain_link.linked_domain,
                active=upstream_rule_def['rule']['active'],
                workflow=AutomaticUpdateRule.WORKFLOW_CASE_UPDATE,
                upstream_id=upstream_rule_def['rule']['id']
            )

        # Copy all the contents from old rule to new rule
        with transaction.atomic():

            downstream_rule.name = upstream_rule_def['rule']['name']
            downstream_rule.case_type = upstream_rule_def['rule']['case_type']
            downstream_rule.filter_on_server_modified = upstream_rule_def['rule']['filter_on_server_modified']
            downstream_rule.server_modified_boundary = upstream_rule_def['rule']['server_modified_boundary']
            downstream_rule.active = upstream_rule_def['rule']['active']
            downstream_rule.save()

            downstream_rule.delete_criteria()
            downstream_rule.delete_actions()

            # Largely from data_interfaces/forms.py - save_criteria()
            for criteria in upstream_rule_def['criteria']:
                definition = None

                if criteria['match_property_definition']:
                    definition = MatchPropertyDefinition.objects.create(
                        property_name=criteria['match_property_definition']['property_name'],
                        property_value=criteria['match_property_definition']['property_value'],
                        match_type=criteria['match_property_definition']['match_type'],
                    )
                elif criteria['custom_match_definition']:
                    definition = CustomMatchDefinition.objects.create(
                        name=criteria['custom_match_definition']['name'],
                    )
                elif criteria['closed_parent_definition']:
                    definition = ClosedParentDefinition.objects.create()

                new_criteria = CaseRuleCriteria(rule=downstream_rule)
                new_criteria.definition = definition
                new_criteria.save()

            # Largely from data_interfacees/forms.py - save_actions()
            for action in upstream_rule_def['actions']:
                definition = None

                if action['update_case_definition']:
                    definition = UpdateCaseDefinition(close_case=action['update_case_definition']['close_case'])
                    properties = []
                    for propertyItem in action['update_case_definition']['properties_to_update']:
                        properties.append(
                            UpdateCaseDefinition.PropertyDefinition(
                                name=propertyItem['name'],
                                value_type=propertyItem['value_type'],
                                value=propertyItem['value'],
                            )
                        )
                    definition.set_properties_to_update(properties)
                    definition.save()
                elif action['custom_action_definition']:
                    definition = CustomActionDefinition.objects.create(
                        name=action['custom_action_definition']['name'],
                    )

                action = CaseRuleAction(rule=downstream_rule)
                action.definition = definition
                action.save()
Exemplo n.º 9
0
    def setUp(self):
        super(AutomaticCaseUpdateTest, self).setUp()
        self.domain = 'auto-update-test'
        update_toggle_cache(AUTO_CASE_UPDATE_ENHANCEMENTS.slug, self.domain,
                            True, NAMESPACE_DOMAIN)
        update_toggle_cache(RUN_AUTO_CASE_UPDATES_ON_SAVE.slug, self.domain,
                            True, NAMESPACE_DOMAIN)
        self.case_db = CaseAccessors(self.domain)
        self.factory = CaseFactory(self.domain)
        self.rule = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule',
            case_type='test-case-type',
            active=True,
            server_modified_boundary=30,
        )
        self.rule.save()
        AutomaticUpdateRuleCriteria.objects.create(
            property_name='last_visit_date',
            property_value='30',
            match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_AFTER,
            rule=self.rule,
        )
        AutomaticUpdateAction.objects.create(
            action=AutomaticUpdateAction.ACTION_UPDATE,
            property_name='update_flag',
            property_value='Y',
            rule=self.rule,
        )

        self.rule2 = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule-2',
            case_type='test-case-type-2',
            active=True,
            server_modified_boundary=30,
        )
        self.rule2.save()
        AutomaticUpdateAction.objects.create(
            action=AutomaticUpdateAction.ACTION_CLOSE,
            rule=self.rule2,
        )

        self.rule3 = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule-3',
            case_type='test-case-type-2',
            active=True,
            server_modified_boundary=50,
        )
        self.rule3.save()
        AutomaticUpdateAction.objects.create(
            action=AutomaticUpdateAction.ACTION_CLOSE,
            rule=self.rule3,
        )

        self.rule4 = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule-4',
            case_type='test-case-type',
            active=True,
            server_modified_boundary=30,
        )
        self.rule4.save()
        AutomaticUpdateRuleCriteria.objects.create(
            property_name='last_visit_date',
            property_value='40',
            match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_AFTER,
            rule=self.rule4,
        )
        AutomaticUpdateAction.objects.create(
            action=AutomaticUpdateAction.ACTION_UPDATE,
            property_name='update_flag',
            property_value='C',
            rule=self.rule4,
        )
        AutomaticUpdateAction.objects.create(
            action=AutomaticUpdateAction.ACTION_CLOSE,
            rule=self.rule4,
        )
        self.rule5 = AutomaticUpdateRule(domain=self.domain,
                                         name='test-rule-5',
                                         case_type='test-case-type-3',
                                         active=True,
                                         filter_on_server_modified=False)
        self.rule5.save()
        AutomaticUpdateRuleCriteria.objects.create(
            property_name='name',
            property_value='signal',
            match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
            rule=self.rule5,
        )
        AutomaticUpdateAction.objects.create(
            action=AutomaticUpdateAction.ACTION_UPDATE,
            property_name='after_save',
            property_value='updated',
            rule=self.rule5,
        )

        with drop_connected_signals(case_post_save):
            case = self.factory.create_case(case_type='test-case-type')