diff --git a/src/eligibility_signposting_api/model/rules.py b/src/eligibility_signposting_api/model/rules.py index 959e5eae..38f7daa3 100644 --- a/src/eligibility_signposting_api/model/rules.py +++ b/src/eligibility_signposting_api/model/rules.py @@ -35,15 +35,40 @@ class RuleType(str, Enum): class RuleOperator(str, Enum): equals = "=" - ne = "!=" - lt = "<" - lte = "<=" gt = ">" + lt = "<" + ne = "!=" gte = ">=" - year_gt = "Y>" + lte = "<=" + contains = "contains" + not_contains = "not_contains" + starts_with = "starts_with" + not_starts_with = "not_starts_with" + ends_with = "ends_with" + is_in = "in" not_in = "not_in" - date_gte = "D>=" member_of = "MemberOf" + not_member_of = "NotaMemberOf" + is_null = "is_null" + is_not_null = "is_not_null" + between = "between" + not_between = "not_between" + is_empty = "is_empty" + is_not_empty = "is_not_empty" + is_true = "is_true" + is_false = "is_false" + day_lte = "D<=" + day_lt = "D<" + day_gte = "D>=" + day_gt = "D>" + week_lte = "W<=" + week_lt = "W<" + week_gte = "W>=" + week_gt = "W>" + year_lte = "Y<=" + year_lt = "Y<" + year_gte = "Y>=" + year_gt = "Y>" class RuleAttributeLevel(str, Enum): diff --git a/src/eligibility_signposting_api/services/eligibility_services.py b/src/eligibility_signposting_api/services/eligibility_services.py index f5de4a23..1fad4b83 100644 --- a/src/eligibility_signposting_api/services/eligibility_services.py +++ b/src/eligibility_signposting_api/services/eligibility_services.py @@ -80,23 +80,126 @@ def get_attribute_value(iteration_rule: IterationRule, person_data: list[dict[st return attribute_value @staticmethod - def evaluate_rule(iteration_rule: IterationRule, attribute_value: Any) -> bool: # noqa: PLR0911, ANN401 + def evaluate_rule(iteration_rule: IterationRule, attribute_value: Any) -> bool: # noqa: PLR0911, ANN401, PLR0912, C901, PLR0915 match iteration_rule.operator: case RuleOperator.equals: return attribute_value == iteration_rule.comparator - case RuleOperator.ne: - return attribute_value != iteration_rule.comparator - case RuleOperator.lt: - return int(attribute_value or 0) < int(iteration_rule.comparator) - case RuleOperator.lte: - return int(attribute_value or 0) <= int(iteration_rule.comparator) case RuleOperator.gt: - return int(attribute_value or 0) > int(iteration_rule.comparator) + return bool(attribute_value) and int(attribute_value) > int(iteration_rule.comparator) + case RuleOperator.lt: + return bool(attribute_value) and int(attribute_value) < int(iteration_rule.comparator) + case RuleOperator.ne: + return bool(attribute_value) and attribute_value != iteration_rule.comparator case RuleOperator.gte: - return int(attribute_value or 0) >= int(iteration_rule.comparator) + return bool(attribute_value) and int(attribute_value) >= int(iteration_rule.comparator) + case RuleOperator.lte: + return bool(attribute_value) and int(attribute_value) <= int(iteration_rule.comparator) + case RuleOperator.contains: + return attribute_value and iteration_rule.comparator in str(attribute_value) + case RuleOperator.not_contains: + return iteration_rule.comparator not in str(attribute_value) + case RuleOperator.starts_with: + return str(attribute_value).startswith(iteration_rule.comparator) + case RuleOperator.not_starts_with: + return not str(attribute_value).startswith(iteration_rule.comparator) + case RuleOperator.ends_with: + return str(attribute_value).endswith(iteration_rule.comparator) + case RuleOperator.is_in: + comparators = str(iteration_rule.comparator).split(",") + return str(attribute_value) in comparators + case RuleOperator.not_in: + comparators = str(iteration_rule.comparator).split(",") + return str(attribute_value) not in comparators + case RuleOperator.member_of: + attribute_values = str(attribute_value).split(",") + return iteration_rule.comparator in attribute_values + case RuleOperator.not_member_of: + attribute_values = str(attribute_value).split(",") + return iteration_rule.comparator not in attribute_values + case RuleOperator.is_null: + return attribute_value in (None, "") + case RuleOperator.is_not_null: + return attribute_value not in (None, "") + case RuleOperator.between: + if attribute_value in (None, ""): + return False + low_comparator_str, high_comparator_str = str(iteration_rule.comparator).split(",") + low_comparator = min(int(low_comparator_str), int(high_comparator_str)) + high_comparator = max(int(low_comparator_str), int(high_comparator_str)) + return low_comparator <= int(attribute_value) <= high_comparator + case RuleOperator.not_between: + if attribute_value in (None, ""): + return False + low_comparator_str, high_comparator_str = str(iteration_rule.comparator).split(",") + low_comparator = min(int(low_comparator_str), int(high_comparator_str)) + high_comparator = max(int(low_comparator_str), int(high_comparator_str)) + return int(attribute_value) < low_comparator or int(attribute_value) > high_comparator + case RuleOperator.is_empty: + return attribute_value is None or all(item.strip() == "" for item in attribute_value.split(",")) + case RuleOperator.is_not_empty: + return attribute_value is not None and any(item.strip() != "" for item in attribute_value.split(",")) + case RuleOperator.is_true: + return attribute_value is True + case RuleOperator.is_false: + return attribute_value is False + case RuleOperator.day_lte: + attribute_date = datetime.strptime(str(attribute_value), "%Y%m%d") if attribute_value else None # noqa: DTZ007 + today_date = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) # noqa: DTZ002 + cutoff = today_date + relativedelta(days=int(iteration_rule.comparator)) + return (attribute_date <= cutoff) if attribute_date else False + case RuleOperator.day_lt: + attribute_date = datetime.strptime(str(attribute_value), "%Y%m%d") if attribute_value else None # noqa: DTZ007 + today_date = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) # noqa: DTZ002 + cutoff = today_date + relativedelta(days=int(iteration_rule.comparator)) + return (attribute_date < cutoff) if attribute_date else False + case RuleOperator.day_gte: + attribute_date = datetime.strptime(str(attribute_value), "%Y%m%d") if attribute_value else None # noqa: DTZ007 + today_date = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) # noqa: DTZ002 + cutoff = today_date + relativedelta(days=int(iteration_rule.comparator)) + return (attribute_date >= cutoff) if attribute_date else False + case RuleOperator.day_gt: + attribute_date = datetime.strptime(str(attribute_value), "%Y%m%d") if attribute_value else None # noqa: DTZ007 + today_date = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) # noqa: DTZ002 + cutoff = today_date + relativedelta(days=int(iteration_rule.comparator)) + return (attribute_date > cutoff) if attribute_date else False + case RuleOperator.week_lte: + attribute_date = datetime.strptime(str(attribute_value), "%Y%m%d") if attribute_value else None # noqa: DTZ007 + today_date = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) # noqa: DTZ002 + cutoff = today_date + relativedelta(weeks=int(iteration_rule.comparator)) + return (attribute_date <= cutoff) if attribute_date else False + case RuleOperator.week_lt: + attribute_date = datetime.strptime(str(attribute_value), "%Y%m%d") if attribute_value else None # noqa: DTZ007 + today_date = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) # noqa: DTZ002 + cutoff = today_date + relativedelta(weeks=int(iteration_rule.comparator)) + return (attribute_date < cutoff) if attribute_date else False + case RuleOperator.week_gte: + attribute_date = datetime.strptime(str(attribute_value), "%Y%m%d") if attribute_value else None # noqa: DTZ007 + today_date = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) # noqa: DTZ002 + cutoff = today_date + relativedelta(weeks=int(iteration_rule.comparator)) + return (attribute_date >= cutoff) if attribute_date else False + case RuleOperator.week_gt: + attribute_date = datetime.strptime(str(attribute_value), "%Y%m%d") if attribute_value else None # noqa: DTZ007 + today_date = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) # noqa: DTZ002 + cutoff = today_date + relativedelta(weeks=int(iteration_rule.comparator)) + return (attribute_date > cutoff) if attribute_date else False + case RuleOperator.year_lte: + attribute_date = datetime.strptime(str(attribute_value), "%Y%m%d") if attribute_value else None # noqa: DTZ007 + today_date = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) # noqa: DTZ002 + cutoff = today_date + relativedelta(years=int(iteration_rule.comparator)) + return (attribute_date <= cutoff) if attribute_date else False + case RuleOperator.year_lt: + attribute_date = datetime.strptime(str(attribute_value), "%Y%m%d") if attribute_value else None # noqa: DTZ007 + today_date = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) # noqa: DTZ002 + cutoff = today_date + relativedelta(years=int(iteration_rule.comparator)) + return (attribute_date < cutoff) if attribute_date else False + case RuleOperator.year_gte: + attribute_date = datetime.strptime(str(attribute_value), "%Y%m%d") if attribute_value else None # noqa: DTZ007 + today_date = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) # noqa: DTZ002 + cutoff = today_date + relativedelta(years=int(iteration_rule.comparator)) + return (attribute_date >= cutoff) if attribute_date else False case RuleOperator.year_gt: attribute_date = datetime.strptime(str(attribute_value), "%Y%m%d") if attribute_value else None # noqa: DTZ007 - today = datetime.today() # noqa: DTZ002 + today = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) # noqa: DTZ002 cutoff = today + relativedelta(years=int(iteration_rule.comparator)) return (attribute_date > cutoff) if attribute_date else False case _: diff --git a/tests/unit/services/test_eligibility_services.py b/tests/unit/services/test_eligibility_services.py index 749af4bc..3fdc0d74 100644 --- a/tests/unit/services/test_eligibility_services.py +++ b/tests/unit/services/test_eligibility_services.py @@ -161,17 +161,31 @@ def test_simple_rule_ineligible(faker: Faker): def test_equals_rule(): rule = IterationRuleFactory.build(operator=RuleOperator.equals, comparator="42") assert EligibilityService.evaluate_rule(rule, "42") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) assert not EligibilityService.evaluate_rule(rule, "99") + + rule = IterationRuleFactory.build(operator=RuleOperator.equals, comparator="-1") + assert EligibilityService.evaluate_rule(rule, "-1") + assert not EligibilityService.evaluate_rule(rule, "0") assert not EligibilityService.evaluate_rule(rule, "") assert not EligibilityService.evaluate_rule(rule, None) -def test_not_equals_rule(): - rule = IterationRuleFactory.build(operator=RuleOperator.ne, comparator="42") - assert EligibilityService.evaluate_rule(rule, "99") - assert not EligibilityService.evaluate_rule(rule, "42") - assert EligibilityService.evaluate_rule(rule, "") - assert EligibilityService.evaluate_rule(rule, None) +def test_greater_than_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.gt, comparator="100") + assert EligibilityService.evaluate_rule(rule, "101") + assert not EligibilityService.evaluate_rule(rule, "100") + assert not EligibilityService.evaluate_rule(rule, "99") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + rule = IterationRuleFactory.build(operator=RuleOperator.gt, comparator="-1") + assert EligibilityService.evaluate_rule(rule, "0") + assert not EligibilityService.evaluate_rule(rule, "-1") + assert not EligibilityService.evaluate_rule(rule, "-2") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) def test_less_than_rule(): @@ -180,8 +194,45 @@ def test_less_than_rule(): assert EligibilityService.evaluate_rule(rule, "99") assert not EligibilityService.evaluate_rule(rule, "100") assert not EligibilityService.evaluate_rule(rule, "101") - assert EligibilityService.evaluate_rule(rule, "") - assert EligibilityService.evaluate_rule(rule, None) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + rule = IterationRuleFactory.build(operator=RuleOperator.lt, comparator="-1") + assert EligibilityService.evaluate_rule(rule, "-2") + assert not EligibilityService.evaluate_rule(rule, "-1") + assert not EligibilityService.evaluate_rule(rule, "0") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_not_equals_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.ne, comparator="27") + assert EligibilityService.evaluate_rule(rule, "98") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + assert not EligibilityService.evaluate_rule(rule, "27") + + rule = IterationRuleFactory.build(operator=RuleOperator.ne, comparator="-1") + assert not EligibilityService.evaluate_rule(rule, "-1") + assert EligibilityService.evaluate_rule(rule, "0") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_greater_than_or_equal_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.gte, comparator="100") + assert EligibilityService.evaluate_rule(rule, "100") + assert EligibilityService.evaluate_rule(rule, "101") + assert not EligibilityService.evaluate_rule(rule, "99") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + rule = IterationRuleFactory.build(operator=RuleOperator.gte, comparator="-1") + assert EligibilityService.evaluate_rule(rule, "0") + assert EligibilityService.evaluate_rule(rule, "-1") + assert not EligibilityService.evaluate_rule(rule, "-2") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) def test_less_than_or_equal_rule(): @@ -189,34 +240,594 @@ def test_less_than_or_equal_rule(): assert EligibilityService.evaluate_rule(rule, "99") assert EligibilityService.evaluate_rule(rule, "100") assert not EligibilityService.evaluate_rule(rule, "101") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + rule = IterationRuleFactory.build(operator=RuleOperator.lte, comparator="-1") + assert EligibilityService.evaluate_rule(rule, "-2") + assert EligibilityService.evaluate_rule(rule, "-1") + assert not EligibilityService.evaluate_rule(rule, "0") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_contains_rule(): + # Check if person's postcode is contained in A12 postcode + rule = IterationRuleFactory.build(operator=RuleOperator.contains, comparator="A12") + assert EligibilityService.evaluate_rule(rule, "A12 3DC") + assert EligibilityService.evaluate_rule(rule, "A12") + assert not EligibilityService.evaluate_rule(rule, None) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, "A23") + assert not EligibilityService.evaluate_rule(rule, 23) + + +def test_not_contains_rule(): + # Check if person's postcode is not contained in A12,B12 postcode + rule = IterationRuleFactory.build(operator=RuleOperator.not_contains, comparator="A12") + assert EligibilityService.evaluate_rule(rule, "A22") + assert EligibilityService.evaluate_rule(rule, None) assert EligibilityService.evaluate_rule(rule, "") + assert EligibilityService.evaluate_rule(rule, 23) + assert not EligibilityService.evaluate_rule(rule, "A12") + + +def test_starts_with_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.starts_with, comparator="YY66") + assert EligibilityService.evaluate_rule(rule, "YY66") + assert EligibilityService.evaluate_rule(rule, "YY66095") + assert not EligibilityService.evaluate_rule(rule, "BB11") + assert not EligibilityService.evaluate_rule(rule, "BYY66095") + assert not EligibilityService.evaluate_rule(rule, " YY66") + assert not EligibilityService.evaluate_rule(rule, None) + assert not EligibilityService.evaluate_rule(rule, "") + + +def test_not_starts_with_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.not_starts_with, comparator="YY66") + assert not EligibilityService.evaluate_rule(rule, "YY66") + assert not EligibilityService.evaluate_rule(rule, "YY66095") + assert EligibilityService.evaluate_rule(rule, "BB11") + assert EligibilityService.evaluate_rule(rule, "BYY66095") + assert EligibilityService.evaluate_rule(rule, " YY66") assert EligibilityService.evaluate_rule(rule, None) + assert EligibilityService.evaluate_rule(rule, "") -def test_greater_than_rule(): - rule = IterationRuleFactory.build(operator=RuleOperator.gt, comparator="100") - assert EligibilityService.evaluate_rule(rule, "101") - assert not EligibilityService.evaluate_rule(rule, "100") - assert not EligibilityService.evaluate_rule(rule, "99") +def test_ends_with_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.ends_with, comparator="2BA") + assert EligibilityService.evaluate_rule(rule, "2BA") + assert EligibilityService.evaluate_rule(rule, "002BA") + assert not EligibilityService.evaluate_rule(rule, None) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, "2BA00") + + +def test_in_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.is_in, comparator="QH8,QJG") assert not EligibilityService.evaluate_rule(rule, "") assert not EligibilityService.evaluate_rule(rule, None) + assert not EligibilityService.evaluate_rule(rule, "AZ1") + assert EligibilityService.evaluate_rule(rule, "QH8") -def test_greater_than_or_equal_rule(): - rule = IterationRuleFactory.build(operator=RuleOperator.gte, comparator="100") - assert EligibilityService.evaluate_rule(rule, "100") - assert EligibilityService.evaluate_rule(rule, "101") - assert not EligibilityService.evaluate_rule(rule, "99") +def test_not_in_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.not_in, comparator="QH8,QJG") + assert EligibilityService.evaluate_rule(rule, "") + assert EligibilityService.evaluate_rule(rule, None) + assert EligibilityService.evaluate_rule(rule, "AZ1") + assert not EligibilityService.evaluate_rule(rule, "QH8") + + +def test_member_of_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.member_of, comparator="cohort1") + assert EligibilityService.evaluate_rule(rule, "cohort1,cohort2") + assert not EligibilityService.evaluate_rule(rule, None) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, "cohort3") + + +def test_not_member_of_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.not_member_of, comparator="cohort1") + assert not EligibilityService.evaluate_rule(rule, "cohort1,cohort2") + assert EligibilityService.evaluate_rule(rule, None) + assert EligibilityService.evaluate_rule(rule, "") + assert EligibilityService.evaluate_rule(rule, "cohort3") + + +def test_is_null_rule(): + # Check email flag is null + rule = IterationRuleFactory.build(operator=RuleOperator.is_null) + assert EligibilityService.evaluate_rule(rule, "") + assert EligibilityService.evaluate_rule(rule, None) + assert not EligibilityService.evaluate_rule(rule, "email_flag") + assert not EligibilityService.evaluate_rule(rule, 42) + + +def test_is_not_null_rule(): + # Check email flag is not null + rule = IterationRuleFactory.build(operator=RuleOperator.is_not_null) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + assert EligibilityService.evaluate_rule(rule, "email_flag") + assert EligibilityService.evaluate_rule(rule, 42) + + +def test_between_rule(): + # check if numerical value is between two give values (inclusive) + rule = IterationRuleFactory.build(operator=RuleOperator.between, comparator="1,3") + assert not EligibilityService.evaluate_rule(rule, "0") + assert EligibilityService.evaluate_rule(rule, "1") + assert EligibilityService.evaluate_rule(rule, "2") + assert EligibilityService.evaluate_rule(rule, "3") + assert not EligibilityService.evaluate_rule(rule, "4") assert not EligibilityService.evaluate_rule(rule, "") assert not EligibilityService.evaluate_rule(rule, None) + rule = IterationRuleFactory.build(operator=RuleOperator.between, comparator="3,1") + assert not EligibilityService.evaluate_rule(rule, "0") + assert EligibilityService.evaluate_rule(rule, "1") + assert EligibilityService.evaluate_rule(rule, "2") + assert EligibilityService.evaluate_rule(rule, "3") + assert not EligibilityService.evaluate_rule(rule, "4") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) -def test_year_gt_rule_future_date(): + rule = IterationRuleFactory.build(operator=RuleOperator.between, comparator="3,3") + assert not EligibilityService.evaluate_rule(rule, "2") + assert EligibilityService.evaluate_rule(rule, "3") + assert not EligibilityService.evaluate_rule(rule, "4") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + rule = IterationRuleFactory.build(operator=RuleOperator.between, comparator="20100302,20100304") + assert not EligibilityService.evaluate_rule(rule, "20100301") + assert EligibilityService.evaluate_rule(rule, "20100302") + assert EligibilityService.evaluate_rule(rule, "20100303") + assert EligibilityService.evaluate_rule(rule, "20100304") + assert not EligibilityService.evaluate_rule(rule, "20100305") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_not_between_rule(): + # check if numerical value is NOT between two give values (inclusive) + rule = IterationRuleFactory.build(operator=RuleOperator.not_between, comparator="1,3") + assert EligibilityService.evaluate_rule(rule, "0") + assert not EligibilityService.evaluate_rule(rule, "1") + assert not EligibilityService.evaluate_rule(rule, "2") + assert not EligibilityService.evaluate_rule(rule, "3") + assert EligibilityService.evaluate_rule(rule, "4") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + rule = IterationRuleFactory.build(operator=RuleOperator.not_between, comparator="3,1") + assert EligibilityService.evaluate_rule(rule, "0") + assert not EligibilityService.evaluate_rule(rule, "1") + assert not EligibilityService.evaluate_rule(rule, "2") + assert not EligibilityService.evaluate_rule(rule, "3") + assert EligibilityService.evaluate_rule(rule, "4") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + rule = IterationRuleFactory.build(operator=RuleOperator.not_between, comparator="3,3") + assert EligibilityService.evaluate_rule(rule, "2") + assert not EligibilityService.evaluate_rule(rule, "3") + assert EligibilityService.evaluate_rule(rule, "4") + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_is_empty_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.is_empty) + assert EligibilityService.evaluate_rule(rule, "") + assert EligibilityService.evaluate_rule(rule, ",") + assert EligibilityService.evaluate_rule(rule, ",,,,") + assert EligibilityService.evaluate_rule(rule, ", , , ,") + assert EligibilityService.evaluate_rule(rule, " , , , , ") + assert EligibilityService.evaluate_rule(rule, None) + assert EligibilityService.evaluate_rule(rule, " ") + + assert not EligibilityService.evaluate_rule(rule, "a") + assert not EligibilityService.evaluate_rule(rule, "this is not empty") + assert not EligibilityService.evaluate_rule(rule, "a,") + assert not EligibilityService.evaluate_rule(rule, ",a") + assert not EligibilityService.evaluate_rule(rule, "a,b,c") + + +def test_is_not_empty_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.is_not_empty) + assert EligibilityService.evaluate_rule(rule, "a") + assert EligibilityService.evaluate_rule(rule, "this is not empty") + assert EligibilityService.evaluate_rule(rule, "a,") + assert EligibilityService.evaluate_rule(rule, ",a") + assert EligibilityService.evaluate_rule(rule, "a,b,c") + + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, ",") + assert not EligibilityService.evaluate_rule(rule, ",,,,") + assert not EligibilityService.evaluate_rule(rule, ", , , ,") + assert not EligibilityService.evaluate_rule(rule, " , , , , ") + assert not EligibilityService.evaluate_rule(rule, None) + assert not EligibilityService.evaluate_rule(rule, " ") + + +def test_is_true_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.is_true) + assert EligibilityService.evaluate_rule(rule, attribute_value=True) + assert not EligibilityService.evaluate_rule(rule, attribute_value=False) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + assert not EligibilityService.evaluate_rule(rule, "True") + + +def test_is_false_rule(): + rule = IterationRuleFactory.build(operator=RuleOperator.is_false) + assert EligibilityService.evaluate_rule(rule, attribute_value=False) + assert not EligibilityService.evaluate_rule(rule, attribute_value=True) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + assert not EligibilityService.evaluate_rule(rule, "False") + + +def test_day_lte_rule_past_date(): + today = datetime.today() # noqa: DTZ002 + days_offset = 2 + offset_date = today + relativedelta(days=days_offset - 1) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.day_lte, comparator=str(days_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_day_lte_rule_present_date(): + today = datetime.today() # noqa: DTZ002 + days_offset = 2 + offset_date = today + relativedelta(days=days_offset) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.day_lte, comparator=str(days_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_day_lte_rule_future_date(): + today = datetime.today() # noqa: DTZ002 + days_offset = 2 + offset_date = today + relativedelta(days=days_offset + 1) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.day_lte, comparator=str(days_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_day_lt_rule_past_date(): + today = datetime.today() # noqa: DTZ002 + days_offset = 2 + offset_date = today + relativedelta(days=days_offset - 1) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.day_lt, comparator=str(days_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_day_lt_rule_present_date(): + today = datetime.today() # noqa: DTZ002 + days_offset = 2 + offset_date = today + relativedelta(days=days_offset) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.day_lt, comparator=str(days_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_day_lt_rule_future_date(): + today = datetime.today() # noqa: DTZ002 + days_offset = 2 + offset_date = today + relativedelta(days=days_offset + 1) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.day_lt, comparator=str(days_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_day_gte_rule_past_date(): + today = datetime.today() # noqa: DTZ002 + days_offset = 2 + past_date = today + relativedelta(days=days_offset - 1) + attribute_value = past_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.day_gte, comparator=str(days_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_day_gte_rule_present_date(): + today = datetime.today() # noqa: DTZ002 + days_offset = 2 + past_date = today + relativedelta(days=days_offset) + attribute_value = past_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.day_gte, comparator=str(days_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_day_gte_rule_future_date(): + today = datetime.today() # noqa: DTZ002 + days_offset = 2 + future_date = today + relativedelta(days=days_offset + 1) + attribute_value = future_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.day_gte, comparator=str(days_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_day_gt_rule_past_date(): + today = datetime.today() # noqa: DTZ002 + days_offset = 2 + past_date = today + relativedelta(days=days_offset - 1) + attribute_value = past_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.day_gt, comparator=str(days_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_day_gt_rule_present_date(): + today = datetime.today() # noqa: DTZ002 + days_offset = 2 + past_date = today + relativedelta(days=days_offset) + attribute_value = past_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.day_gt, comparator=str(days_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_day_gt_rule_future_date(): + today = datetime.today() # noqa: DTZ002 + days_offset = 2 + future_date = today + relativedelta(days=days_offset + 1) + attribute_value = future_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.day_gt, comparator=str(days_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_week_lte_rule_past_date(): + today = datetime.today() # noqa: DTZ002 + weeks_offset = 2 + offset_date = today + relativedelta(weeks=weeks_offset - 1) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.week_lte, comparator=str(weeks_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_week_lte_rule_present_date(): + today = datetime.today() # noqa: DTZ002 + weeks_offset = 2 + offset_date = today + relativedelta(weeks=weeks_offset) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.week_lte, comparator=str(weeks_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_week_lte_rule_future_date(): + today = datetime.today() # noqa: DTZ002 + weeks_offset = 2 + offset_date = today + relativedelta(weeks=weeks_offset + 1) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.week_lte, comparator=str(weeks_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_week_lt_rule_past_date(): + today = datetime.today() # noqa: DTZ002 + weeks_offset = 2 + offset_date = today + relativedelta(weeks=weeks_offset - 1) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.week_lt, comparator=str(weeks_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_week_lt_rule_present_date(): + today = datetime.today() # noqa: DTZ002 + weeks_offset = 2 + offset_date = today + relativedelta(weeks=weeks_offset) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.week_lt, comparator=str(weeks_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_week_lt_rule_future_date(): + today = datetime.today() # noqa: DTZ002 + weeks_offset = 2 + offset_date = today + relativedelta(weeks=weeks_offset + 1) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.week_lt, comparator=str(weeks_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_week_gte_rule_past_date(): + today = datetime.today() # noqa: DTZ002 + weeks_offset = 2 + past_date = today + relativedelta(weeks=weeks_offset - 1) + attribute_value = past_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.week_gte, comparator=str(weeks_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_week_gte_rule_present_date(): + today = datetime.today() # noqa: DTZ002 + weeks_offset = 2 + past_date = today + relativedelta(weeks=weeks_offset) + attribute_value = past_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.week_gte, comparator=str(weeks_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_week_gte_rule_future_date(): + today = datetime.today() # noqa: DTZ002 + weeks_offset = 2 + future_date = today + relativedelta(weeks=weeks_offset + 1) + attribute_value = future_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.week_gte, comparator=str(weeks_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_week_gt_rule_past_date(): + today = datetime.today() # noqa: DTZ002 + weeks_offset = 2 + past_date = today + relativedelta(weeks=weeks_offset - 1) + attribute_value = past_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.week_gt, comparator=str(weeks_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_week_gt_rule_present_date(): + today = datetime.today() # noqa: DTZ002 + weeks_offset = 2 + past_date = today + relativedelta(weeks=weeks_offset) + attribute_value = past_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.week_gt, comparator=str(weeks_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_week_gt_rule_future_date(): + today = datetime.today() # noqa: DTZ002 + weeks_offset = 2 + future_date = today + relativedelta(weeks=weeks_offset + 1) + attribute_value = future_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.week_gt, comparator=str(weeks_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_year_lte_rule_past_date(): + today = datetime.today() # noqa: DTZ002 + years_offset = 2 + offset_date = today + relativedelta(years=years_offset - 1) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.year_lte, comparator=str(years_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_year_lte_rule_present_date(): + today = datetime.today() # noqa: DTZ002 + years_offset = 2 + offset_date = today + relativedelta(years=years_offset) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.year_lte, comparator=str(years_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_year_lte_rule_future_date(): + today = datetime.today() # noqa: DTZ002 + years_offset = 2 + offset_date = today + relativedelta(years=years_offset + 1) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.year_lte, comparator=str(years_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_year_lt_rule_past_date(): + today = datetime.today() # noqa: DTZ002 + years_offset = 2 + offset_date = today + relativedelta(years=years_offset - 1) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.year_lt, comparator=str(years_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_year_lt_rule_present_date(): + today = datetime.today() # noqa: DTZ002 + years_offset = 2 + offset_date = today + relativedelta(years=years_offset) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.year_lt, comparator=str(years_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_year_lt_rule_future_date(): + today = datetime.today() # noqa: DTZ002 + years_offset = 2 + offset_date = today + relativedelta(years=years_offset + 1) + attribute_value = offset_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.year_lt, comparator=str(years_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_year_gte_rule_past_date(): + today = datetime.today() # noqa: DTZ002 + years_offset = 2 + past_date = today + relativedelta(years=years_offset - 1) + attribute_value = past_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.year_gte, comparator=str(years_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_year_gte_rule_present_date(): + today = datetime.today() # noqa: DTZ002 + years_offset = 2 + past_date = today + relativedelta(years=years_offset) + attribute_value = past_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.year_gte, comparator=str(years_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_year_gte_rule_future_date(): today = datetime.today() # noqa: DTZ002 years_offset = 2 future_date = today + relativedelta(years=years_offset + 1) attribute_value = future_date.strftime("%Y%m%d") - rule = IterationRuleFactory.build(operator=RuleOperator.year_gt, comparator=str(years_offset)) + rule = IterationRuleFactory.build(operator=RuleOperator.year_gte, comparator=str(years_offset)) assert EligibilityService.evaluate_rule(rule, attribute_value) assert not EligibilityService.evaluate_rule(rule, "") assert not EligibilityService.evaluate_rule(rule, None) @@ -233,6 +844,29 @@ def test_year_gt_rule_past_date(): assert not EligibilityService.evaluate_rule(rule, None) +def test_year_gt_rule_present_date(): + today = datetime.today() # noqa: DTZ002 + years_offset = 2 + past_date = today + relativedelta(years=years_offset) + attribute_value = past_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.year_gt, comparator=str(years_offset)) + assert not EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +def test_year_gt_rule_future_date(): + today = datetime.today() # noqa: DTZ002 + years_offset = 2 + future_date = today + relativedelta(years=years_offset + 1) + attribute_value = future_date.strftime("%Y%m%d") + rule = IterationRuleFactory.build(operator=RuleOperator.year_gt, comparator=str(years_offset)) + assert EligibilityService.evaluate_rule(rule, attribute_value) + assert not EligibilityService.evaluate_rule(rule, "") + assert not EligibilityService.evaluate_rule(rule, None) + + +@pytest.mark.skip(reason="Skipping this test since all the operators are implemented") def test_unimplemented_operator(): rule = IterationRuleFactory.build(operator=RuleOperator.member_of, comparator="something") with pytest.raises(NotImplementedError, match="not implemented"):