Example #1
0
    def test_custom_tag_1(self):
        # make a new tagset
        TagSet.objects_by_account(self.account).get_or_create(account=self.account,name="new test tagset")
        populate_rule_components_for_an_account(self.account)
        left_side = LeftSide.objects_by_account(self.account).get(display_name="have a new test tagset tag that")
        self.assertEqual(left_side.query_string_partial, "taggeditem__tag__in=Tag.objects_by_account(self.account).filter(tagset__name='new test tagset',name")
        self.assertEqualQuerySets(left_side.operators,  self._tag_operators )
        self.assertEqualQuerySets(left_side.right_side_types, self._text_right_side_types)
        self.assertEqual(left_side.add_closing_paren, True)

        return left_side
Example #2
0
    def test_invalid_rule_missing_operator_side(self):
        right_hand_term="test"
        # operator_name="contains"
        group = Factory.group(self.account)
        left_side = LeftSide.objects_by_account(self.account).get(display_name="have a General tag that")
        # icontains = Operator.objects_by_account(self.account).get(display_name=operator_name)
        icontains = None
        rst = self._text_right_side_types[0]
        rsv = right_hand_term
        GroupRule.raw_objects.create(account=self.account, group=group, left_side=left_side, operator=icontains, right_side_value=rsv, right_side_type=rst)

        self.assertEqual(group.has_a_valid_rule, False)
Example #3
0
    def test_populate_cleans_up_unused_rules(self):
        # create a custom tag
        from generic_tags.models import TagSet
        ts1 = TagSet.objects_by_account(self.account).get_or_create(account=self.account,name="new test tagset")[0]
        
        # repopulate
        populate_rule_components_for_an_account(self.account)
        
        # make sure it's there
        left_side = LeftSide.objects_by_account(self.account).get(display_name="have a new test tagset tag that")
        self.assertEqual(left_side.query_string_partial, "taggeditem__tag__in=Tag.objects_by_account(self.account).filter(tagset__name='new test tagset',name")
        self.assertEqualQuerySets(left_side.operators,  self._tag_operators )
        self.assertEqualQuerySets(left_side.right_side_types, self._text_right_side_types)

        # delete it
        ts1.delete()

        # repopulate
        populate_rule_components_for_an_account(self.account)
        
        # make sure it's gone
        self.assertEqual(LeftSide.objects_by_account(self.account).filter(display_name="have a new test tagset tag that").count(), 0)
Example #4
0
    def grouprule(cls, account, left_side_str, operator_str, right_side_str, group=None, **kwargs):
        if not group:
            group = cls.group()

        left_side = LeftSide.objects_by_account(account).get(display_name__iexact=left_side_str)
        operator = Operator.objects_by_account(account).get(display_name__iexact=operator_str)
        right_side_type = left_side.first_right_side_type
        right_side_value = right_side_str

        return GroupRule.raw_objects.get_or_create(account=account,
                                               left_side=left_side,
                                               operator=operator,
                                               right_side_type=right_side_type,
                                               right_side_value=right_side_value,
                                               group=group,
                                               )[0]
Example #5
0
    def test_create_new_group_rule_for_general_tag_contains(self, right_hand_term="test", operator_name="contains"):
        # create a new group rule
        group = Factory.group(self.account)
        left_side = LeftSide.objects_by_account(self.account).get(display_name="have a General tag that")
        icontains = Operator.objects_by_account(self.account).get(display_name=operator_name)
        rst = self._text_right_side_types[0]
        rsv = right_hand_term
        group_rule = GroupRule.raw_objects.create(account=self.account, group=group, left_side=left_side, operator=icontains, right_side_value=rsv, right_side_type=rst)
        new_group_rule = GroupRule.objects_by_account(self.account).get(pk=group_rule.pk)

        # assert the correct models exist
        self.assertEqual(new_group_rule.group, group)
        self.assertEqual(new_group_rule.left_side, left_side)
        self.assertEqual(new_group_rule.operator, icontains)
        self.assertEqual(new_group_rule.right_side_value, rsv)
        self.assertEqual(new_group_rule.group, group)

        return group, new_group_rule
Example #6
0
 def test_left_side_ordering(self):
     list_of_names = [l.display_name for l in LeftSide.objects_by_account(self.account).all()]
     target_list_of_names = [
         "have any tag that",
         "have a General tag that",
         "have a Volunteer tag that",
         "have a Donor tag that",
         "volunteer status",
         "last donation",
         # "total donations in the last 12 months",
         "last volunteer shift",
         # "total volunteer hours in the last 12 months"
         "last conversation",
         "birthday",
         "age",
         "have a donation that",
     ]
     self.assertEqual(list_of_names,target_list_of_names)
Example #7
0
    def test_create_new_group_rule_for_volunteer_status_is_inactive(self, right_hand_term="inactive", operator_name="is"):
        # create a new group 
        group = Factory.group(self.account)
        
        # create a new group rule
        left_side = LeftSide.objects_by_account(self.account).get(display_name="volunteer status")
        icontains = Operator.objects_by_account(self.account).get(display_name=operator_name)
        rst = self._choices_right_side_types[0]
        rsv = right_hand_term
        group_rule = GroupRule.raw_objects.create(account=self.account, group=group, left_side=left_side, operator=icontains, right_side_value=rsv, right_side_type=rst)
        new_group_rule = GroupRule.objects_by_account(self.account).get(pk=group_rule.pk)

        # assert the correct models exist
        self.assertEqual(new_group_rule.group, group)
        self.assertEqual(new_group_rule.left_side, left_side)
        self.assertEqual(new_group_rule.operator, icontains)
        self.assertEqual(new_group_rule.right_side_value, rsv)
        self.assertEqual(new_group_rule.group, group)

        return group, new_group_rule
Example #8
0
    def test_create_new_group_rule_for_last_donation_is_after(self, right_hand_term="2/12/2009", operator_name="is after"):
       # create a new group 
        group = Factory.group(self.account)
        
        # create a new group rule
        left_side = LeftSide.objects_by_account(self.account).get(display_name="last donation")
        op = Operator.objects_by_account(self.account).get(display_name=operator_name)
        rst = self._date_right_side_types[0]
        rsv = right_hand_term
        group_rule = GroupRule.raw_objects.create(account=self.account, group=group, left_side=left_side, operator=op, right_side_value=rsv, right_side_type=rst)
        new_group_rule = GroupRule.objects_by_account(self.account).get(pk=group_rule.pk)

        # assert the correct models exist
        self.assertEqual(new_group_rule.group, group)
        self.assertEqual(new_group_rule.left_side, left_side)
        self.assertEqual(new_group_rule.operator, op)
        self.assertEqual(new_group_rule.right_side_value, rsv)
        self.assertEqual(new_group_rule.group, group)

        return group, new_group_rule
Example #9
0
    def test_create_new_group_rule_for_custom_tag_is_exactly(self, right_hand_term="test", operator_name="is exactly"):
        # create a new group 
        group = Factory.group(self.account)
        
        # make the custom tag
        TagSet.raw_objects.get_or_create(account=self.account, name="new test tagset")
        populate_rule_components_for_an_account(self.account)
        # create a new group rule
        left_side = LeftSide.objects_by_account(self.account).get(display_name="have a new test tagset tag that")
        icontains = Operator.objects_by_account(self.account).get(display_name=operator_name)
        rst = self._text_right_side_types[0]
        rsv = right_hand_term
        group_rule = GroupRule.raw_objects.create(account=self.account, group=group, left_side=left_side, operator=icontains, right_side_value=rsv, right_side_type=rst)
        new_group_rule = GroupRule.objects_by_account(self.account).get(pk=group_rule.pk)

        # assert the correct models exist
        self.assertEqual(new_group_rule.group, group)
        self.assertEqual(new_group_rule.left_side, left_side)
        self.assertEqual(new_group_rule.operator, icontains)
        self.assertEqual(new_group_rule.right_side_value, rsv)
        self.assertEqual(new_group_rule.group, group)

        return group, new_group_rule
Example #10
0
def delete_rule_components_for_a_tagset(sender, instance, created=None, *args, **kwargs):
    from rules.models import LeftSide
    LeftSide.objects_by_account(instance.account).using('default').filter(display_name="have a %s tag that" % (instance.name)).delete()
    johnny_cache.invalidate(LeftSide)
Example #11
0
 def test_last_donation(self):
     left_side = LeftSide.objects_by_account(self.account).get(display_name="last donation")
     self.assertEqual(left_side.query_string_partial, "donor__donation__date")
     self.assertEqualQuerySets(left_side.operators,  self._date_operators )
     self.assertEqualQuerySets(left_side.right_side_types, self._date_right_side_types)
     self.assertEqual(left_side.add_closing_paren, False)
Example #12
0
 def test_volunteer_status(self):
     left_side = LeftSide.objects_by_account(self.account).get(display_name="volunteer status")
     self.assertEqual(left_side.query_string_partial, "volunteer__status")
     self.assertEqualQuerySets(left_side.operators,  self._choices_operators )
     self.assertEqualQuerySets(left_side.right_side_types, self._choices_right_side_types)
     self.assertEqual(left_side.add_closing_paren, False)
Example #13
0
 def test_volunteer_tags(self):
     left_side = LeftSide.objects_by_account(self.account).get(display_name="have a Volunteer tag that")
     self.assertEqual(left_side.query_string_partial, "taggeditem__tag__in=Tag.objects_by_account(self.account).filter(tagset__name='Volunteer',name")
     self.assertEqualQuerySets(left_side.operators,  self._tag_operators )
     self.assertEqualQuerySets(left_side.right_side_types,  self._text_right_side_types)
     self.assertEqual(left_side.add_closing_paren, True)
Example #14
0
 def test_last_volunteer_shift(self):
     left_side = LeftSide.objects_by_account(self.account).get(display_name="last volunteer shift")
     self.assertEqual(left_side.query_string_partial, "volunteer__completedshift__date")
     self.assertEqualQuerySets(left_side.operators,  self._date_operators )
     self.assertEqualQuerySets(left_side.right_side_types, self._date_right_side_types)
     self.assertEqual(left_side.add_closing_paren, False)
Example #15
0
 def setUp(self):
     self.account = Factory.account()
     populate_rule_components_for_an_account(self.account)
     self.request = Dummy()
     self.request.account = self.account
     self.left_side = LeftSide.objects_by_account(self.account).get(display_name="have a General tag that")
Example #16
0
def populate_rule_components_for_an_account(account):
    try:
        from accounts.models import Account
        from rules.models import LeftSide, Operator, RightSideType
        from volunteers import VOLUNTEER_STATII
        from donors import DONATION_TYPES
        account = Account.objects.using("default").get(pk=account.pk)
        """This function performs several actions, and is idempotent.

        In order, it:

        - Sets up built-in rule options (like volunteer status)
        - Sets up data-driven rule options (like custom tag sets)
        - Cleans up unused rule options

        """
        # print "populating for %s" % account

        request = Dummy()
        request.account = account

        # RightSideTypes
        all_right_side_types = []
        right_type_text     = RightSideType.raw_objects.using('default').get_or_create(account=account, name="text")[0]
        right_type_date     = RightSideType.raw_objects.using('default').get_or_create(account=account, name="date")[0]
        right_type_number   = RightSideType.raw_objects.using('default').get_or_create(account=account, name="number")[0]
        right_type_choices   = RightSideType.raw_objects.using('default').get_or_create(account=account,name="choices")[0]
        all_right_side_types = [right_type_text, right_type_date, right_type_number, right_type_choices]

        # Operators
        all_operators = []
        operator_contains =             Operator.raw_objects.using('default').get_or_create(account=account, display_name="contains"          , query_string_partial="__icontains="  , use_filter=True)[0]
        operator_contains.order         = 10
        operator_contains.save()
        operator_does_not_contain =     Operator.raw_objects.using('default').get_or_create(account=account, display_name="does not contain"  , query_string_partial="__icontains="  , use_filter=False)[0]
        operator_does_not_contain.order = 20
        operator_does_not_contain.save()
        operator_is =                   Operator.raw_objects.using('default').get_or_create(account=account, display_name="is"                , query_string_partial="="             , use_filter=True)[0]
        operator_is.order               = 30
        operator_is.save()
        operator_is_not =               Operator.raw_objects.using('default').get_or_create(account=account, display_name="is not"            , query_string_partial="="             , use_filter=False)[0]
        operator_is_not.order           = 40
        operator_is_not.save()
        operator_is_exactly =           Operator.raw_objects.using('default').get_or_create(account=account, display_name="is exactly"        , query_string_partial="__iexact="     , use_filter=True)[0]
        operator_is_exactly.order       = 50
        operator_is_exactly.save()
        operator_is_not_exactly =       Operator.raw_objects.using('default').get_or_create(account=account, display_name="is not exactly"    , query_string_partial="__iexact="     , use_filter=False)[0]
        operator_is_not_exactly.order   = 60
        operator_is_not_exactly.save()
        operator_is_on =                Operator.raw_objects.using('default').get_or_create(account=account, display_name="is on"             , query_string_partial="="             , use_filter=True)[0]
        operator_is_on.order            = 70
        operator_is_on.save()
        operator_is_before =            Operator.raw_objects.using('default').get_or_create(account=account, display_name="is before"         , query_string_partial="__lt="         , use_filter=True)[0]
        operator_is_before.order        = 80
        operator_is_before.save()
        operator_is_after =             Operator.raw_objects.using('default').get_or_create(account=account, display_name="is after"          , query_string_partial="__gt="         , use_filter=True)[0]
        operator_is_after.order         = 90
        operator_is_after.save()
        operator_is_equal =             Operator.raw_objects.using('default').get_or_create(account=account, display_name="is equal to"       , query_string_partial="="             , use_filter=True)[0]
        operator_is_equal.order         = 100
        operator_is_equal.save()
        operator_is_less_than =         Operator.raw_objects.using('default').get_or_create(account=account, display_name="is less than"      , query_string_partial="__lt="         , use_filter=True)[0]
        operator_is_less_than.order     = 110
        operator_is_less_than.save()
        operator_is_more_than =         Operator.raw_objects.using('default').get_or_create(account=account, display_name="is more than"      , query_string_partial="__gt="         , use_filter=True)[0]
        operator_is_more_than.order     = 120
        operator_is_more_than.save()
        all_operators = [   operator_is_exactly, operator_is_not_exactly, operator_contains, operator_does_not_contain, 
                            operator_is, operator_is_not,
                            operator_is_on, operator_is_before, operator_is_after,
                            operator_is_equal, operator_is_less_than, operator_is_more_than,
                        ]

        # Helper methods
        all_left_sides = []
        def _add_text_operators(ls):
            ls.allowed_operators.clear()
            ls.allowed_operators.add(operator_is_exactly)
            ls.allowed_operators.add(operator_is_not_exactly)
            ls.allowed_operators.add(operator_contains)
            ls.allowed_operators.add(operator_does_not_contain)
            ls.save()
        
        def _add_right_type_text(ls):
            ls.allowed_right_side_types.clear()
            ls.allowed_right_side_types.add(right_type_text)
            ls.save()
        
        def _add_operators_and_right_side_text(ls):
            _add_text_operators(ls)
            _add_right_type_text(ls)

        def _add_date_operators(ls):
            ls.allowed_operators.clear()
            ls.allowed_operators.add(operator_is_on)
            ls.allowed_operators.add(operator_is_before)
            ls.allowed_operators.add(operator_is_after)
            ls.save()
        
        def _add_right_type_date(ls):
            ls.allowed_right_side_types.clear()
            ls.allowed_right_side_types.add(right_type_date)
            ls.save()
        
        def _add_operators_and_right_side_date(ls):
            _add_date_operators(ls)
            _add_right_type_date(ls)

        def _add_number_operators(ls):
            ls.allowed_operators.clear()
            ls.allowed_operators.add(operator_is_equal)
            ls.allowed_operators.add(operator_is_less_than)
            ls.allowed_operators.add(operator_is_more_than)
            ls.save()
        
        def _add_right_type_number(ls):
            ls.allowed_right_side_types.clear()
            ls.allowed_right_side_types.add(right_type_number)
            ls.save()
        
        def _add_operators_and_right_side_number(ls):
            _add_number_operators(ls)
            _add_right_type_number(ls)

        def _add_tag_operators(ls):
            ls.allowed_operators.clear()
            ls.allowed_operators.add(operator_is_exactly)
            ls.allowed_operators.add(operator_contains)
            ls.save()    

        def _add_operators_and_right_side_tag(ls):
            _add_tag_operators(ls)
            _add_right_type_text(ls)

        def _add_choices_operators(ls):
            ls.allowed_operators.clear()
            ls.allowed_operators.add(operator_is)
            ls.allowed_operators.add(operator_is_not)
            ls.save()
        
        def _add_right_type_choices(ls):
            ls.allowed_right_side_types.clear()
            ls.allowed_right_side_types.add(right_type_choices)
            ls.save()
        
        def _add_operators_and_right_side_choices(ls):
            _add_choices_operators(ls)
            _add_right_type_choices(ls)


        def _add_to_all_left_sides(ls):
            all_left_sides.append(ls)

        def left_side_for_text(**kwargs):
            if not "display_name" in kwargs or not "query_string_partial" in kwargs:
                raise Exception, "display_name and query_string_partial not passed!"

            ls = LeftSide.raw_objects.using('default').get_or_create(**kwargs)[0]
            _add_operators_and_right_side_text(ls)
            _add_to_all_left_sides(ls)
            return ls

        def left_side_for_date(**kwargs):
            if not "display_name" in kwargs or not "query_string_partial" in kwargs:
                raise Exception, "display_name and query_string_partial not passed!"

            ls = LeftSide.raw_objects.using('default').get_or_create(**kwargs)[0]
            _add_operators_and_right_side_date(ls)
            _add_to_all_left_sides(ls)
            return ls

        def left_side_for_number(**kwargs):
            if not "display_name" in kwargs or not "query_string_partial" in kwargs:
                raise Exception, "display_name and query_string_partial not passed!"

            ls = LeftSide.raw_objects.using('default').get_or_create(**kwargs)[0]
            _add_operators_and_right_side_number(ls)
            _add_to_all_left_sides(ls)
            return ls
        
        def left_side_for_tag(**kwargs):
            if not "display_name" in kwargs or not "query_string_partial" in kwargs:
                raise Exception, "display_name and query_string_partial not passed!"

            ls = LeftSide.raw_objects.using('default').get_or_create(**kwargs)[0]
            _add_operators_and_right_side_tag(ls)
            _add_to_all_left_sides(ls)
            return ls

        def left_side_for_choices(**kwargs):
            if not "display_name" in kwargs or not "query_string_partial" in kwargs:
                raise Exception, "display_name and query_string_partial not passed!"
            choices = kwargs["choices"]
            del kwargs["choices"]
            ls = LeftSide.raw_objects.using('default').get_or_create(**kwargs)[0]
            if not ls.choices == choices:
                ls.choices = choices
                ls.save()
            _add_operators_and_right_side_choices(ls)
            _add_to_all_left_sides(ls)
            return ls


        # Left sides - built-ins
        ls = left_side_for_tag (account=account,          display_name="have any tag that"                           ,query_string_partial="taggeditem__tag__name"                                      )
        ls.order=10
        ls.save()

        ls = left_side_for_choices(account=account,       display_name="volunteer status"                             ,query_string_partial="volunteer__status"                        , choices=VOLUNTEER_STATII)
        ls.order=100
        ls.save()

        ls = left_side_for_date(account=account,          display_name="last donation"                                ,query_string_partial="donor__donation__date"                                    )
        ls.order=110
        ls.save()
        
        # left_side_for_number(account=account,           display_name="total donations in the last 12 months"        ,query_string_partial="donor__twelvemonth_total"                                 )
        # ls.order=120
        # ls.save()
        
        ls = left_side_for_date(account=account,          display_name="last volunteer shift"                         ,query_string_partial="volunteer__completedshift__date"                          )    
        ls.order=130
        ls.save()
        
        # left_side_for_number(account=account,           display_name="total volunteer hours in the last 12 months"  ,query_string_partial="volunteer__twelvemonth_total"                             )
        # ls.order=140
        # ls.save()

        ls = left_side_for_date (account=account,          display_name="last conversation"                            ,query_string_partial="conversation__date"                                   )
        ls.order=150
        ls.save()

        ls = left_side_for_date (account=account,          display_name="birthday"                                     ,query_string_partial="actual_birthday"                                   )
        ls.order=170
        ls.save()

        ls = left_side_for_number (account=account,        display_name="age"                                           ,query_string_partial="age"                                   )
        ls.order=190
        ls.save()


        ls = left_side_for_choices (account=account,      display_name="have a donation that"                           ,query_string_partial="donor__donation__type", choices=DONATION_TYPES                                  )
        ls.order=210
        ls.save()

        # Left sides - generateds
        from generic_tags.models import TagSet
        i = 0

        for ts in TagSet.objects_by_account(account).using('default').all():
            i = i+1
            ls = left_side_for_tag(account=account,
                                display_name="have a %s tag that" % (ts.name),
                                query_string_partial="taggeditem__tag__in=Tag.objects_by_account(self.account).filter(tagset__name='%s',name" % (ts.name), 
                                add_closing_paren=True
                                )
            ls.order=20+i
            ls.save()
                                                                                                   
                                                                                          
        # Cleanup
        for rs in RightSideType.objects_by_account(account).using('default').all():
            if rs not in all_right_side_types:
                rs.delete()
        
        for o in Operator.objects_by_account(account).using('default').all():
            if o not in all_operators:
                o.delete()
        
        for ls in LeftSide.objects_by_account(account).using('default').all():
            if ls not in all_left_sides:
                ls.delete()

        johnny_cache.invalidate(RightSideType)
        johnny_cache.invalidate(Operator)
        johnny_cache.invalidate(LeftSide)
    except:
        from django.core.mail import mail_admins
        from qi_toolkit.helpers import exception_string
        mail_admins("Exception generating group rules", exception_string(), fail_silently=True)
Example #17
0
 def test_any_tags(self):
     left_side = LeftSide.objects_by_account(self.account).get(display_name="have any tag that")
     self.assertEqual(left_side.query_string_partial, "taggeditem__tag__name")
     self.assertEqualQuerySets(left_side.operators,  self._tag_operators )
     self.assertEqualQuerySets(left_side.right_side_types, self._text_right_side_types  )
     self.assertEqual(left_side.add_closing_paren, False)
Example #18
0
def rules_logic_js(request):
    left_sides = LeftSide.objects_by_account(request.account).all()
    operators = Operator.objects_by_account(request.account).all()
    right_side_types = RightSideType.objects_by_account(request.account).all()
    return locals()