Exemplo n.º 1
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.º 2
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.º 3
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])
Exemplo n.º 4
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,
        })

        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)))
class AutomaticCaseUpdateTest(TestCase):
    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')
        self.case_id = case.case_id
class AutomaticCaseUpdateTest(TestCase):
    def setUp(self):
        self.now = datetime(2015, 10, 22, 0, 0)
        self.domain = 'auto-update-test'
        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,
            ),
        ]

        case = CommCareCase(domain=self.domain, type='test-case-type')
        case.save()
        self.case_id = case.get_id

    def tearDown(self):
        AutomaticUpdateRuleCriteria.objects.all().delete()
        AutomaticUpdateAction.objects.all().delete()
        AutomaticUpdateRule.objects.all().delete()
        CommCareCase.get(self.case_id).delete()

    def _get_case_ids(self, *args, **kwargs):
        return [self.case_id]

    def _get_case(self):
        return CommCareCase.get_db().get(self.case_id)

    def _update_case(self, server_modified_on, last_visit_date):
        doc = self._get_case()
        doc['server_modified_on'] = json_format_datetime(server_modified_on)
        doc['last_visit_date'] = last_visit_date.strftime('%Y-%m-%d')
        CommCareCase.get_db().save_doc(doc)

    def _assert_case_revision(self, number):
        doc = CommCareCase.get_db().get(self.case_id)
        self.assertTrue(doc['_rev'].startswith('%s-' % number))

    def test_rule(self):
        self._assert_case_revision(1)
        with patch('corehq.apps.data_interfaces.models.AutomaticUpdateRule.get_case_ids', new=self._get_case_ids):
            # No update: both dates are 27 days away
            self._update_case(datetime(2015, 9, 25, 12, 0), date(2015, 9, 25))
            self._assert_case_revision(2)
            run_case_update_rules_for_domain(self.domain, now=self.now)
            self._assert_case_revision(2)

            # No update: server_modified_on is 32 days away but last_visit_date is 27 days away
            self._update_case(datetime(2015, 9, 20, 12, 0), date(2015, 9, 25))
            self._assert_case_revision(3)
            run_case_update_rules_for_domain(self.domain, now=self.now)
            self._assert_case_revision(3)

            # No update: last_visit_date is 32 days away but server_modified_on is 27 days away
            self._update_case(datetime(2015, 9, 25, 12, 0), date(2015, 9, 20))
            self._assert_case_revision(4)
            run_case_update_rules_for_domain(self.domain, now=self.now)
            self._assert_case_revision(4)

            # Perform update: both dates are 32 days away
            self._update_case(datetime(2015, 9, 20, 12, 0), date(2015, 9, 20))
            self._assert_case_revision(5)
            run_case_update_rules_for_domain(self.domain, now=self.now)
            self._assert_case_revision(6)

            doc = self._get_case()
            self.assertEqual(doc['update_flag'], 'Y')
            self.assertEqual(doc['closed'], True)

    def test_match_days_since(self):
        case = CommCareCase(
            domain=self.domain,
            type='test-case-type-2',
            server_modified_on=datetime(2015, 1, 1),
        )

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='last_visit_date',
                property_value='30',
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
            ),
        ]
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('last_visit_date', '2015-12-30')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('last_visit_date', '2015-12-03')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('last_visit_date', '2015-12-02')
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('last_visit_date', '2015-11-01')
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_match_equal(self):
        case = CommCareCase(
            domain=self.domain,
            type='test-case-type-2',
            server_modified_on=datetime(2015, 1, 1),
        )

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='property1',
                property_value='value1',
                match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
            ),
        ]
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property1', 'x')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property1', 'value1')
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_match_not_equal(self):
        case = CommCareCase(
            domain=self.domain,
            type='test-case-type-2',
            server_modified_on=datetime(2015, 1, 1),
        )

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='property2',
                property_value='value2',
                match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
            ),
        ]
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property2', 'value2')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property2', 'x')
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_date_case_properties_for_equality(self):
        """
        Date case properties are automatically converted from string to date
        when fetching from the db, so here we want to make sure this doesn't
        interfere with our ability to compare dates for equality.
        """
        case = CommCareCase(
            domain=self.domain,
            type='test-case-type-2',
        )

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='property1',
                property_value='2016-02-24',
                match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
            ),
        ]

        case.set_case_property('property1', '2016-02-24')
        case.save()
        case = CommCareCase.get(case.get_id)
        case.server_modified_on = datetime(2015, 1, 1)
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property1', '2016-02-25')
        case.save()
        case = CommCareCase.get(case.get_id)
        case.server_modified_on = datetime(2015, 1, 1)
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.delete()

    def test_date_case_properties_for_inequality(self):
        case = CommCareCase(
            domain=self.domain,
            type='test-case-type-2',
        )

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='property1',
                property_value='2016-02-24',
                match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
            ),
        ]

        case.set_case_property('property1', '2016-02-24')
        case.save()
        case = CommCareCase.get(case.get_id)
        case.server_modified_on = datetime(2015, 1, 1)
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property1', '2016-02-25')
        case.save()
        case = CommCareCase.get(case.get_id)
        case.server_modified_on = datetime(2015, 1, 1)
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.delete()

    def test_match_has_value(self):
        case = CommCareCase(
            domain=self.domain,
            type='test-case-type-2',
            server_modified_on=datetime(2015, 1, 1),
        )

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='property3',
                match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE,
            ),
        ]
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property3', 'x')
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property3', '')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_and_criteria(self):
        case = CommCareCase(
            domain=self.domain,
            type='test-case-type-2',
            server_modified_on=datetime(2015, 1, 1),
        )

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='last_visit_date',
                property_value='30',
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
            ),
            AutomaticUpdateRuleCriteria(
                property_name='property1',
                property_value='value1',
                match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
            ),
            AutomaticUpdateRuleCriteria(
                property_name='property2',
                property_value='value2',
                match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
            ),
            AutomaticUpdateRuleCriteria(
                property_name='property3',
                match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE,
            ),
        ]

        case.set_case_property('last_visit_date', '2015-11-01')
        case.set_case_property('property1', 'value1')
        case.set_case_property('property2', 'x')
        case.set_case_property('property3', 'x')
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('last_visit_date', '2015-12-30')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('last_visit_date', '2015-11-01')
        case.set_case_property('property1', 'x')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property1', 'value1')
        case.set_case_property('property2', 'value2')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property2', 'x')
        case.set_case_property('property3', '')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property3', 'x')
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_get_rules_from_domain(self):
        rules = AutomaticUpdateRule.by_domain(self.domain)
        rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(rules)

        expected_case_types = ['test-case-type', 'test-case-type-2']
        actual_case_types = rules_by_case_type.keys()
        self.assertEqual(set(expected_case_types), set(actual_case_types))

        expected_rule_ids = [self.rule.pk]
        actual_rule_ids = [rule.pk for rule in rules_by_case_type['test-case-type']]
        self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))

        expected_rule_ids = [self.rule2.pk, self.rule3.pk]
        actual_rule_ids = [rule.pk for rule in rules_by_case_type['test-case-type-2']]
        self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))

    def test_boundary_date(self):
        rules = AutomaticUpdateRule.by_domain(self.domain)
        rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(rules)

        boundary_date = AutomaticUpdateRule.get_boundary_date(
            rules_by_case_type['test-case-type'], datetime(2016, 1, 1))
        self.assertEqual(boundary_date, datetime(2015, 12, 2))

        boundary_date = AutomaticUpdateRule.get_boundary_date(
            rules_by_case_type['test-case-type-2'], datetime(2016, 1, 1))
        self.assertEqual(boundary_date, datetime(2015, 12, 2))
class AutomaticCaseUpdateTest(TestCase):
    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')
        self.case_id = case.case_id

    def tearDown(self):
        AutomaticUpdateRuleCriteria.objects.all().delete()
        AutomaticUpdateAction.objects.all().delete()
        AutomaticUpdateRule.objects.all().delete()
        FormProcessorTestUtils.delete_all_cases(self.domain)

    def _get_case_ids(self, *args, **kwargs):
        return [self.case_id]

    def _get_case(self):
        return self.case_db.get_case(self.case_id)

    def _assert_case_revision(self, rev_number, last_modified, expect_modified=False):
        if should_use_sql_backend(self.domain):
            self.assertEqual(
                expect_modified,
                CaseAccessorSQL.case_modified_since(self.case_id, last_modified)
            )
        else:
            doc = self._get_case()
            self.assertTrue(doc['_rev'].startswith('%s-' % rev_number))

    @run_with_all_backends
    def test_rule(self):
        now = datetime(2015, 10, 22, 0, 0)
        with patch('corehq.apps.data_interfaces.models.AutomaticUpdateRule.get_case_ids', new=self._get_case_ids):
            # No update: both dates are 27 days away
            last_modified = datetime(2015, 9, 25, 12, 0)
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 25))
            self._assert_case_revision(2, last_modified)
            run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(2, last_modified)

            # No update: server_modified_on is 32 days away but last_visit_date is 27 days away
            last_modified = datetime(2015, 9, 20, 12, 0)
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 25))
            self._assert_case_revision(3, last_modified)
            run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(3, last_modified)

            # No update: last_visit_date is 32 days away but server_modified_on is 27 days away
            last_modified = datetime(2015, 9, 25, 12, 0)
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 20))
            self._assert_case_revision(4, last_modified)
            run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(4, last_modified)

            # Perform update: both dates are 32 days away
            last_modified = datetime(2015, 9, 20, 12, 0)
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 20))
            self._assert_case_revision(5, last_modified)
            with drop_connected_signals(case_post_save):
                run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(6, last_modified, True)

            case = self._get_case()
            self.assertEqual(case.get_case_property('update_flag'), 'Y')
            self.assertEqual(case.closed, True)

    @run_with_all_backends
    def test_match_days_since(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='last_visit_date',
                    property_value='30',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
                ),
            ]
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-12-30')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-12-03')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-12-02')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-11-01')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_match_equal(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='property1',
                    property_value='value1',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                ),
            ]
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', 'x')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', 'value1')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_match_not_equal(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='property2',
                    property_value='value2',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
                ),
            ]
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property2', 'value2')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property2', 'x')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_date_case_properties_for_equality(self):
        """
        Date case properties are automatically converted from string to date
        when fetching from the db, so here we want to make sure this doesn't
        interfere with our ability to compare dates for equality.
        """
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='property1',
                    property_value='2016-02-24',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                ),
            ]

            set_case_property_directly(case, 'property1', '2016-02-24')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', '2016-02-25')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_date_case_properties_for_inequality(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='property1',
                    property_value='2016-02-24',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
                ),
            ]

            set_case_property_directly(case, 'property1', '2016-02-24')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', '2016-02-25')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_match_has_value(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='property3',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE,
                ),
            ]
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property3', 'x')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property3', '')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_and_criteria(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:

            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='last_visit_date',
                    property_value='30',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
                ),
                AutomaticUpdateRuleCriteria(
                    property_name='property1',
                    property_value='value1',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                ),
                AutomaticUpdateRuleCriteria(
                    property_name='property2',
                    property_value='value2',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
                ),
                AutomaticUpdateRuleCriteria(
                    property_name='property3',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE,
                ),
            ]

            set_case_property_directly(case, 'last_visit_date', '2015-11-01')
            set_case_property_directly(case, 'property1', 'value1')
            set_case_property_directly(case, 'property2', 'x')
            set_case_property_directly(case, 'property3', 'x')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-12-30')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-11-01')
            set_case_property_directly(case, 'property1', 'x')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', 'value1')
            set_case_property_directly(case, 'property2', 'value2')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property2', 'x')
            set_case_property_directly(case, 'property3', '')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property3', 'x')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_get_rules_from_domain(self):
        rules = AutomaticUpdateRule.by_domain(self.domain)
        rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(rules)

        expected_case_types = ['test-case-type', 'test-case-type-2']
        actual_case_types = rules_by_case_type.keys()
        self.assertEqual(set(expected_case_types), set(actual_case_types))

        expected_rule_ids = [self.rule.pk]
        actual_rule_ids = [rule.pk for rule in rules_by_case_type['test-case-type']]
        self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))

        expected_rule_ids = [self.rule2.pk, self.rule3.pk]
        actual_rule_ids = [rule.pk for rule in rules_by_case_type['test-case-type-2']]
        self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))

    def test_boundary_date(self):
        rules = AutomaticUpdateRule.by_domain(self.domain)
        rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(rules)

        boundary_date = AutomaticUpdateRule.get_boundary_date(
            rules_by_case_type['test-case-type'], datetime(2016, 1, 1))
        self.assertEqual(boundary_date, datetime(2015, 12, 2))

        boundary_date = AutomaticUpdateRule.get_boundary_date(
            rules_by_case_type['test-case-type-2'], datetime(2016, 1, 1))
        self.assertEqual(boundary_date, datetime(2015, 12, 2))
Exemplo n.º 9
0
class AutomaticCaseUpdateTest(TestCase):

    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')
        self.case_id = case.case_id

    def tearDown(self):
        AutomaticUpdateRuleCriteria.objects.all().delete()
        AutomaticUpdateAction.objects.all().delete()
        AutomaticUpdateRule.objects.all().delete()
        FormProcessorTestUtils.delete_all_cases(self.domain)
        super(AutomaticCaseUpdateTest, self).tearDown()

    def _get_case_ids(self, *args, **kwargs):
        return [self.case_id]

    def _get_case(self):
        return self.case_db.get_case(self.case_id)

    def _assert_case_revision(self, rev_number, last_modified, expect_modified=False):
        if should_use_sql_backend(self.domain):
            self.assertEqual(
                expect_modified,
                CaseAccessorSQL.case_modified_since(self.case_id, last_modified)
            )
        else:
            doc = self._get_case()
            self.assertTrue(doc['_rev'].startswith('%s-' % rev_number))

    @run_with_all_backends
    def test_rule(self):
        now = datetime(2015, 10, 22, 0, 0)
        with patch('corehq.apps.data_interfaces.models.AutomaticUpdateRule.get_case_ids', new=self._get_case_ids):
            # No update: both dates are 27 days away
            last_modified = datetime(2015, 9, 25, 12, 0)
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 25))
            self._assert_case_revision(2, last_modified)
            run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(2, last_modified)

            # No update: server_modified_on is 32 days away but last_visit_date is 27 days away
            last_modified = datetime(2015, 9, 20, 12, 0)
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 25))
            self._assert_case_revision(3, last_modified)
            run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(3, last_modified)

            # No update: last_visit_date is 32 days away but server_modified_on is 27 days away
            last_modified = datetime(2015, 9, 25, 12, 0)
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 20))
            self._assert_case_revision(4, last_modified)
            run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(4, last_modified)

            # Perform update: both dates are 32 days away
            last_modified = datetime(2015, 9, 20, 12, 0)
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 20))
            self._assert_case_revision(5, last_modified)
            with drop_connected_signals(case_post_save):
                run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(6, last_modified, True)

            case = self._get_case()
            self.assertEqual(case.get_case_property('update_flag'), 'Y')

            # No update: case state matches final state
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 20))
            self._assert_case_revision(7, last_modified)
            with drop_connected_signals(case_post_save):
                run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(7, last_modified)

            # Perform update: case closed because date is 42 days away
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 10))
            with drop_connected_signals(case_post_save):
                run_case_update_rules_for_domain(self.domain, now=now)

            case = self._get_case()
            self.assertEqual(case.get_case_property('update_flag'), 'C')
            self.assertEqual(case.closed, True)

    @run_with_all_backends
    def test_match_days_after(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            AutomaticUpdateRuleCriteria.objects.create(
                property_name='last_visit_date',
                property_value='30',
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_AFTER,
                rule=self.rule2,
            )
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-12-30')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-12-03')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-12-02')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-11-01')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_match_days_before(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            AutomaticUpdateRuleCriteria.objects.create(
                property_name='last_visit_date',
                property_value='30',
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_BEFORE,
                rule=self.rule2,
            )
            # When the case property doesn't exist, it should not match
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-10-01')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2016-01-02')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2016-01-31')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2016-02-01')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2016-03-01')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_match_equal(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            AutomaticUpdateRuleCriteria.objects.create(
                property_name='property1',
                property_value='value1',
                match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                rule=self.rule2,
            )
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', 'x')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', 'value1')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_match_not_equal(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            AutomaticUpdateRuleCriteria.objects.create(
                property_name='property2',
                property_value='value2',
                match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
                rule=self.rule2,
            )
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property2', 'value2')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property2', 'x')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_date_case_properties_for_equality(self):
        """
        Date case properties are automatically converted from string to date
        when fetching from the db, so here we want to make sure this doesn't
        interfere with our ability to compare dates for equality.
        """
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            AutomaticUpdateRuleCriteria.objects.create(
                property_name='property1',
                property_value='2016-02-24',
                match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                rule=self.rule2,
            )

            set_case_property_directly(case, 'property1', '2016-02-24')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', '2016-02-25')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_date_case_properties_for_inequality(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            AutomaticUpdateRuleCriteria.objects.create(
                property_name='property1',
                property_value='2016-02-24',
                match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
                rule=self.rule2,
            )

            set_case_property_directly(case, 'property1', '2016-02-24')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', '2016-02-25')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_match_has_value(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            AutomaticUpdateRuleCriteria.objects.create(
                property_name='property3',
                match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE,
                rule=self.rule2,
            )
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property3', 'x')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property3', '')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_and_criteria(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:

            AutomaticUpdateRuleCriteria.objects.create(
                property_name='last_visit_date',
                property_value='30',
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_AFTER,
                rule=self.rule2,
            )
            AutomaticUpdateRuleCriteria.objects.create(
                property_name='property1',
                property_value='value1',
                match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                rule=self.rule2,
            )
            AutomaticUpdateRuleCriteria.objects.create(
                property_name='property2',
                property_value='value2',
                match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
                rule=self.rule2,
            )
            AutomaticUpdateRuleCriteria.objects.create(
                property_name='property3',
                match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE,
                rule=self.rule2,
            )

            set_case_property_directly(case, 'last_visit_date', '2015-11-01')
            set_case_property_directly(case, 'property1', 'value1')
            set_case_property_directly(case, 'property2', 'x')
            set_case_property_directly(case, 'property3', 'x')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-12-30')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-11-01')
            set_case_property_directly(case, 'property1', 'x')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', 'value1')
            set_case_property_directly(case, 'property2', 'value2')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property2', 'x')
            set_case_property_directly(case, 'property3', '')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property3', 'x')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_get_rules_from_domain(self):
        rules = AutomaticUpdateRule.by_domain(self.domain)
        rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(rules)

        expected_case_types = ['test-case-type', 'test-case-type-2', 'test-case-type-3']
        actual_case_types = rules_by_case_type.keys()
        self.assertEqual(set(expected_case_types), set(actual_case_types))

        expected_rule_ids = [self.rule.pk, self.rule4.pk]
        actual_rule_ids = [rule.pk for rule in rules_by_case_type['test-case-type']]
        self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))

        expected_rule_ids = [self.rule2.pk, self.rule3.pk]
        actual_rule_ids = [rule.pk for rule in rules_by_case_type['test-case-type-2']]
        self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))

        expected_rule_ids = [self.rule5.pk]
        actual_rule_ids = [rule.pk for rule in rules_by_case_type['test-case-type-3']]
        self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))

    def test_boundary_date(self):
        rules = AutomaticUpdateRule.by_domain(self.domain)
        rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(rules)

        boundary_date = AutomaticUpdateRule.get_boundary_date(
            rules_by_case_type['test-case-type'], datetime(2016, 1, 1))
        self.assertEqual(boundary_date, datetime(2015, 12, 2))

        boundary_date = AutomaticUpdateRule.get_boundary_date(
            rules_by_case_type['test-case-type-2'], datetime(2016, 1, 1))
        self.assertEqual(boundary_date, datetime(2015, 12, 2))

    @run_with_all_backends
    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)))

    @run_with_all_backends
    def test_no_server_boundary(self):
        with _with_case(self.domain, 'test-case-type-3', datetime(2016, 1, 1), case_name='signal') as case:
            # no filtering on server modified date so same day matches
            self.assertTrue(self.rule5.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_run_on_save(self):
        with _with_case(self.domain, 'test-case-type-3', datetime(2016, 1, 1), case_name='signal') as case:
            with patch('corehq.apps.data_interfaces.models.AutomaticUpdateRule.apply_rule') as apply:
                # property is updated after save signal (case update used to force save)
                update_case(self.domain, case.case_id, {})
                apply.assert_called_once()

    @run_with_all_backends
    def test_early_task_exit(self):
        with _with_case(self.domain, 'test-case-type-3', datetime(2016, 1, 1), case_name='signal') as case:
            with patch('corehq.apps.data_interfaces.models.AutomaticUpdateRule.apply_rule') as apply:
                hqcase.utils.update_case(case.domain, case.case_id, case_properties={}, xmlns=AUTO_UPDATE_XMLNS)
                apply.assert_not_called()
Exemplo n.º 10
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.º 11
0
class AutomaticCaseUpdateTest(TestCase):
    def setUp(self):
        self.now = datetime(2015, 10, 22, 0, 0)
        self.domain = "auto-update-test"
        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)]

        case = CommCareCase(domain=self.domain, type="test-case-type")
        case.save()
        self.case_id = case.get_id

    def tearDown(self):
        AutomaticUpdateRuleCriteria.objects.all().delete()
        AutomaticUpdateAction.objects.all().delete()
        AutomaticUpdateRule.objects.all().delete()
        CommCareCase.get(self.case_id).delete()

    def _get_case_ids(self, *args, **kwargs):
        return [self.case_id]

    def _get_case(self):
        return CommCareCase.get_db().get(self.case_id)

    def _update_case(self, server_modified_on, last_visit_date):
        doc = self._get_case()
        doc["server_modified_on"] = json_format_datetime(server_modified_on)
        doc["last_visit_date"] = last_visit_date.strftime("%Y-%m-%d")
        CommCareCase.get_db().save_doc(doc)

    def _assert_case_revision(self, number):
        doc = CommCareCase.get_db().get(self.case_id)
        self.assertTrue(doc["_rev"].startswith("%s-" % number))

    def test_rule(self):
        self._assert_case_revision(1)
        with patch("corehq.apps.data_interfaces.models.AutomaticUpdateRule.get_case_ids", new=self._get_case_ids):
            # No update: both dates are 27 days away
            self._update_case(datetime(2015, 9, 25, 12, 0), date(2015, 9, 25))
            self._assert_case_revision(2)
            run_case_update_rules_for_domain(self.domain, now=self.now)
            self._assert_case_revision(2)

            # No update: server_modified_on is 32 days away but last_visit_date is 27 days away
            self._update_case(datetime(2015, 9, 20, 12, 0), date(2015, 9, 25))
            self._assert_case_revision(3)
            run_case_update_rules_for_domain(self.domain, now=self.now)
            self._assert_case_revision(3)

            # No update: last_visit_date is 32 days away but server_modified_on is 27 days away
            self._update_case(datetime(2015, 9, 25, 12, 0), date(2015, 9, 20))
            self._assert_case_revision(4)
            run_case_update_rules_for_domain(self.domain, now=self.now)
            self._assert_case_revision(4)

            # Perform update: both dates are 32 days away
            self._update_case(datetime(2015, 9, 20, 12, 0), date(2015, 9, 20))
            self._assert_case_revision(5)
            run_case_update_rules_for_domain(self.domain, now=self.now)
            self._assert_case_revision(6)

            doc = self._get_case()
            self.assertEqual(doc["update_flag"], "Y")
            self.assertEqual(doc["closed"], True)

    def test_match_days_since(self):
        case = CommCareCase(domain=self.domain, type="test-case-type-2", server_modified_on=datetime(2015, 1, 1))

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name="last_visit_date",
                property_value="30",
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
            )
        ]
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("last_visit_date", "2015-12-30")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("last_visit_date", "2015-12-03")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("last_visit_date", "2015-12-02")
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("last_visit_date", "2015-11-01")
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_match_equal(self):
        case = CommCareCase(domain=self.domain, type="test-case-type-2", server_modified_on=datetime(2015, 1, 1))

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name="property1", property_value="value1", match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL
            )
        ]
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property1", "x")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property1", "value1")
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_match_not_equal(self):
        case = CommCareCase(domain=self.domain, type="test-case-type-2", server_modified_on=datetime(2015, 1, 1))

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name="property2",
                property_value="value2",
                match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
            )
        ]
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property2", "value2")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property2", "x")
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_match_has_value(self):
        case = CommCareCase(domain=self.domain, type="test-case-type-2", server_modified_on=datetime(2015, 1, 1))

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name="property3", match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE
            )
        ]
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property3", "x")
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property3", "")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_and_criteria(self):
        case = CommCareCase(domain=self.domain, type="test-case-type-2", server_modified_on=datetime(2015, 1, 1))

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name="last_visit_date",
                property_value="30",
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
            ),
            AutomaticUpdateRuleCriteria(
                property_name="property1", property_value="value1", match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL
            ),
            AutomaticUpdateRuleCriteria(
                property_name="property2",
                property_value="value2",
                match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
            ),
            AutomaticUpdateRuleCriteria(
                property_name="property3", match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE
            ),
        ]

        case.set_case_property("last_visit_date", "2015-11-01")
        case.set_case_property("property1", "value1")
        case.set_case_property("property2", "x")
        case.set_case_property("property3", "x")
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("last_visit_date", "2015-12-30")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("last_visit_date", "2015-11-01")
        case.set_case_property("property1", "x")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property1", "value1")
        case.set_case_property("property2", "value2")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property2", "x")
        case.set_case_property("property3", "")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property3", "x")
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_get_rules_from_domain(self):
        rules = AutomaticUpdateRule.by_domain(self.domain)
        rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(rules)

        expected_case_types = ["test-case-type", "test-case-type-2"]
        actual_case_types = rules_by_case_type.keys()
        self.assertEqual(set(expected_case_types), set(actual_case_types))

        expected_rule_ids = [self.rule.pk]
        actual_rule_ids = [rule.pk for rule in rules_by_case_type["test-case-type"]]
        self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))

        expected_rule_ids = [self.rule2.pk, self.rule3.pk]
        actual_rule_ids = [rule.pk for rule in rules_by_case_type["test-case-type-2"]]
        self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))

    def test_boundary_date(self):
        rules = AutomaticUpdateRule.by_domain(self.domain)
        rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(rules)

        boundary_date = AutomaticUpdateRule.get_boundary_date(
            rules_by_case_type["test-case-type"], datetime(2016, 1, 1)
        )
        self.assertEqual(boundary_date, datetime(2015, 12, 2))

        boundary_date = AutomaticUpdateRule.get_boundary_date(
            rules_by_case_type["test-case-type-2"], datetime(2016, 1, 1)
        )
        self.assertEqual(boundary_date, datetime(2015, 12, 2))
Exemplo n.º 12
0
class AutomaticCaseUpdateTest(TestCase):
    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')
        self.case_id = case.case_id
Exemplo n.º 13
0
class AutomaticCaseUpdateTest(TestCase):
    def setUp(self):
        self.now = datetime(2015, 10, 22, 0, 0)
        self.domain = 'auto-update-test'
        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,
            ),
        ]

        case = CommCareCase(domain=self.domain, type='test-case-type')
        case.save()
        self.case_id = case.get_id

    def tearDown(self):
        AutomaticUpdateRuleCriteria.objects.filter(rule_id=self.rule.pk).delete()
        AutomaticUpdateAction.objects.filter(rule_id=self.rule.pk).delete()
        self.rule.delete()
        CommCareCase.get(self.case_id).delete()

    def _get_case_ids(self, *args, **kwargs):
        return [self.case_id]

    def _get_case(self):
        return CommCareCase.get_db().get(self.case_id)

    def _update_case(self, server_modified_on, last_visit_date):
        doc = self._get_case()
        doc['server_modified_on'] = json_format_datetime(server_modified_on)
        doc['last_visit_date'] = last_visit_date.strftime('%Y-%m-%d')
        CommCareCase.get_db().save_doc(doc)

    def _assert_case_revision(self, number):
        doc = CommCareCase.get_db().get(self.case_id)
        self.assertTrue(doc['_rev'].startswith('%s-' % number))

    def test_rule(self):
        self._assert_case_revision(1)
        with patch('corehq.apps.data_interfaces.models.AutomaticUpdateRule.get_case_ids', new=self._get_case_ids):
            # No update: both dates are 27 days away
            self._update_case(datetime(2015, 9, 25, 12, 0), date(2015, 9, 25))
            self._assert_case_revision(2)
            run_case_update_rules_for_domain(self.domain, now=self.now)
            self._assert_case_revision(2)

            # No update: server_modified_on is 32 days away but last_visit_date is 27 days away
            self._update_case(datetime(2015, 9, 20, 12, 0), date(2015, 9, 25))
            self._assert_case_revision(3)
            run_case_update_rules_for_domain(self.domain, now=self.now)
            self._assert_case_revision(3)

            # No update: last_visit_date is 32 days away but server_modified_on is 27 days away
            self._update_case(datetime(2015, 9, 25, 12, 0), date(2015, 9, 20))
            self._assert_case_revision(4)
            run_case_update_rules_for_domain(self.domain, now=self.now)
            self._assert_case_revision(4)

            # Perform update: both dates are 32 days away
            self._update_case(datetime(2015, 9, 20, 12, 0), date(2015, 9, 20))
            self._assert_case_revision(5)
            run_case_update_rules_for_domain(self.domain, now=self.now)
            self._assert_case_revision(6)

            doc = self._get_case()
            self.assertEqual(doc['update_flag'], 'Y')
            self.assertEqual(doc['closed'], True)