|
8 | 8 | from eligibility_signposting_api.model import rules |
9 | 9 | from eligibility_signposting_api.model import rules as rules_model |
10 | 10 | from eligibility_signposting_api.model.eligibility import ConditionName, DateOfBirth, NHSNumber, Postcode, Status |
| 11 | +from eligibility_signposting_api.model.rules import IterationRule |
11 | 12 | from eligibility_signposting_api.services.calculators.eligibility_calculator import EligibilityCalculator |
12 | 13 | from tests.fixtures.builders.model import rule as rule_builder |
13 | 14 | from tests.fixtures.builders.repos.person import person_rows_builder |
@@ -811,3 +812,65 @@ def test_status_if_iteration_rules_contains_cohort_label_field( |
811 | 812 | ), |
812 | 813 | test_comment, |
813 | 814 | ) |
| 815 | + |
| 816 | + |
| 817 | +@pytest.mark.parametrize( |
| 818 | + ("rule_stop", "expected_status", "test_comment"), |
| 819 | + [ |
| 820 | + ("Y", Status.not_actionable, "Stops at the first rule"), |
| 821 | + ("N", Status.not_eligible, "Both the rules are executed"), |
| 822 | + ("", Status.not_eligible, "Both the rules are executed"), |
| 823 | + (None, Status.not_eligible, "Both the rules are executed"), |
| 824 | + ], |
| 825 | +) |
| 826 | +def test_rules_stop_behavior(rule_stop: str | None, expected_status: Status, test_comment: str, faker: Faker) -> None: |
| 827 | + # Given |
| 828 | + nhs_number = NHSNumber(faker.nhs_number()) |
| 829 | + date_of_birth = DateOfBirth(faker.date_of_birth(minimum_age=18, maximum_age=74)) |
| 830 | + person_rows = person_rows_builder(nhs_number, date_of_birth=date_of_birth, cohorts=["cohort1"]) |
| 831 | + |
| 832 | + # Base rule template |
| 833 | + # Not using model factory to create Iteration rules since it sets boolean values for "Y"/"N" |
| 834 | + simple_age_data = { |
| 835 | + "Name": "Exclude too young less than 75", |
| 836 | + "Description": "Exclude too young less than 75", |
| 837 | + "AttributeLevel": "PERSON", |
| 838 | + "AttributeName": "DATE_OF_BIRTH", |
| 839 | + "Operator": "Y>", |
| 840 | + "Comparator": "-75", |
| 841 | + } |
| 842 | + |
| 843 | + # Build rule variations |
| 844 | + rule_variants = [ |
| 845 | + {"Type": "S", "Priority": 10, "RuleStop": rule_stop}, |
| 846 | + {"Type": "S", "Priority": 10}, |
| 847 | + {"Type": "F", "Priority": 15}, |
| 848 | + ] |
| 849 | + |
| 850 | + iteration_rules = [IterationRule.model_validate({**simple_age_data, **variant}) for variant in rule_variants] |
| 851 | + |
| 852 | + # Build campaign configuration |
| 853 | + campaign_config = rule_builder.CampaignConfigFactory.build( |
| 854 | + target="RSV", |
| 855 | + iterations=[ |
| 856 | + rule_builder.IterationFactory.build( |
| 857 | + iteration_rules=[], |
| 858 | + iteration_cohorts=[rule_builder.IterationCohortFactory.build(cohort_label="cohort1")], |
| 859 | + ) |
| 860 | + ], |
| 861 | + ) |
| 862 | + campaign_config.iterations[0].iteration_rules.extend(iteration_rules) |
| 863 | + |
| 864 | + calculator = EligibilityCalculator(person_rows, [campaign_config]) |
| 865 | + |
| 866 | + # When |
| 867 | + actual = calculator.evaluate_eligibility() |
| 868 | + |
| 869 | + # Then |
| 870 | + assert_that( |
| 871 | + actual, |
| 872 | + is_eligibility_status().with_conditions( |
| 873 | + has_item(is_condition().with_condition_name(ConditionName("RSV")).and_status(expected_status)) |
| 874 | + ), |
| 875 | + test_comment, |
| 876 | + ) |
0 commit comments