Skip to content

Commit 039d79c

Browse files
ELI-615 | wip
1 parent f8d4987 commit 039d79c

3 files changed

Lines changed: 37 additions & 23 deletions

File tree

src/eligibility_signposting_api/services/calculators/eligibility_calculator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,13 @@ def get_the_best_cohort_memberships(
8181

8282
return best_status, best_cohorts
8383

84-
def get_eligibility_status(self, include_actions: str, conditions: list[str], category: str) -> EligibilityStatus:
84+
def get_eligibility_status(self, include_actions: str, conditions: list[str], requested_category: str) -> EligibilityStatus:
8585
include_actions_flag = include_actions.upper() == "Y"
8686
condition_results: dict[ConditionName, IterationResult] = {}
8787
final_result = []
8888

89-
requested_grouped_campaigns = self.campaign_evaluator.get_requested_grouped_campaigns(
90-
self.campaign_configs, conditions, category
89+
requested_grouped_campaigns = self.campaign_evaluator.get_campaign_with_latest_active_iteration_per_target(
90+
self.campaign_configs, conditions, requested_category
9191
)
9292
for condition_name, campaign_group in requested_grouped_campaigns:
9393
best_iteration_result = self.get_best_iteration_result(campaign_group)

src/eligibility_signposting_api/services/processors/campaign_evaluator.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,43 @@ class CampaignEvaluator:
1515
def get_active_campaigns(self, campaign_configs: Collection[CampaignConfig]) -> list[CampaignConfig]:
1616
return [cc for cc in campaign_configs if cc.campaign_live]
1717

18-
def get_requested_grouped_campaigns(
19-
self, campaign_configs: Collection[CampaignConfig], conditions: list[str], category: str
20-
) -> Iterator[tuple[eligibility_status.ConditionName, list[CampaignConfig]]]:
18+
def get_latest_campaign(self, campaign_group: list[CampaignConfig]):
19+
if not campaign_group:
20+
return None
21+
22+
latest_date = max(c.start_date for c in campaign_group)
23+
24+
latest = [c for c in campaign_group if c.start_date == latest_date]
25+
26+
if len(latest) == 1:
27+
return latest[0]
28+
29+
if len(latest) > 1:
30+
raise ValueError(
31+
f"Multiple campaigns share the latest start_date: {latest_date}") # TODO handle it in FHIR format
32+
33+
return None
34+
35+
def get_campaign_with_latest_active_iteration_per_target(
36+
self, campaign_configs: Collection[CampaignConfig], conditions: list[str], requested_category: str
37+
) -> Iterator[tuple[eligibility_status.ConditionName, CampaignConfig]]:
2138
mapping = {
2239
"ALL": {"V", "S"},
2340
"VACCINATIONS": {"V"},
2441
"SCREENING": {"S"},
2542
}
2643

27-
allowed_types = mapping.get(category, set())
44+
allowed_types = mapping.get(requested_category, set())
2845

2946
filter_all_conditions = "ALL" in conditions
3047

31-
active_campaigns = self.get_active_campaigns(campaign_configs)
48+
allowed_campaigns = [c for c in campaign_configs if c.type in allowed_types]
49+
active_campaigns = self.get_active_campaigns(allowed_campaigns)
3250

3351
for condition_name, campaign_group in groupby(
3452
sorted(active_campaigns, key=attrgetter("target")),
3553
key=attrgetter("target"),
3654
):
37-
campaigns = list(campaign_group)
38-
if (
39-
campaigns
40-
and campaigns[0].type in allowed_types
41-
and (filter_all_conditions or str(condition_name) in conditions)
42-
):
43-
yield condition_name, campaigns
55+
campaigns = [c for c in allowed_campaigns if filter_all_conditions or str(condition_name) in conditions]
56+
57+
yield condition_name, self.get_latest_campaign(campaigns)

tests/unit/services/processors/test_campaign_evaluator.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ def test_campaigns_grouped_by_condition_name_filters_correctly( # noqa: PLR0913
3333
):
3434
campaign = rule.CampaignConfigFactory.build(target=campaign_target, type=campaign_type)
3535

36-
result = campaign_evaluator.get_requested_grouped_campaigns([campaign], conditions_filter, category_filter)
36+
result = campaign_evaluator.get_campaign_with_latest_active_iteration_per_target([campaign], conditions_filter, category_filter)
3737
assert_that([(str(name), group[0].type) for name, group in result], is_(expected_result))
3838

3939

4040
def test_campaigns_grouped_by_condition_name_with_no_campaigns(campaign_evaluator):
41-
result = campaign_evaluator.get_requested_grouped_campaigns([], ["RSV"], "VACCINATIONS")
41+
result = campaign_evaluator.get_campaign_with_latest_active_iteration_per_target([], ["RSV"], "VACCINATIONS")
4242
assert_that(list(result), is_([]))
4343

4444

@@ -47,7 +47,7 @@ def test_campaigns_grouped_by_condition_name_with_no_active_campaigns(campaign_e
4747
target="RSV", type="V", start_date=datetime.date(2025, 4, 20), end_date=datetime.date(2025, 4, 21)
4848
)
4949

50-
result = campaign_evaluator.get_requested_grouped_campaigns([campaign], ["RSV"], "VACCINATIONS")
50+
result = campaign_evaluator.get_campaign_with_latest_active_iteration_per_target([campaign], ["RSV"], "VACCINATIONS")
5151
assert_that(list(result), is_([]))
5252

5353

@@ -63,15 +63,15 @@ def test_campaigns_grouped_by_condition_name_with_various_categories(
6363
campaign_evaluator, category_filter, campaign_type, expected_count
6464
):
6565
campaign = rule.CampaignConfigFactory.build(target="COVID", type=campaign_type)
66-
result = list(campaign_evaluator.get_requested_grouped_campaigns([campaign], ["COVID"], category_filter))
66+
result = list(campaign_evaluator.get_campaign_with_latest_active_iteration_per_target([campaign], ["COVID"], category_filter))
6767
assert_that(len(result), is_(expected_count))
6868
if expected_count > 0:
6969
assert_that(str(result[0][0]), is_("COVID"))
7070

7171

7272
def test_campaigns_grouped_by_condition_name_with_empty_conditions_filter(campaign_evaluator):
7373
campaign = rule.CampaignConfigFactory.build(target="RSV", type="V")
74-
result = campaign_evaluator.get_requested_grouped_campaigns([campaign], [], "VACCINATIONS")
74+
result = campaign_evaluator.get_campaign_with_latest_active_iteration_per_target([campaign], [], "VACCINATIONS")
7575
assert_that(list(result), is_([]))
7676

7777

@@ -84,7 +84,7 @@ def test_campaigns_grouped_by_condition_name_groups_multiple_campaigns_for_same_
8484
)
8585

8686
all_campaigns = [campaign1, campaign2, campaign3, inactive_campaign]
87-
result = list(campaign_evaluator.get_requested_grouped_campaigns(all_campaigns, ["COVID", "FLU"], "VACCINATIONS"))
87+
result = list(campaign_evaluator.get_campaign_with_latest_active_iteration_per_target(all_campaigns, ["COVID", "FLU"], "VACCINATIONS"))
8888

8989
assert_that(len(result), is_(2))
9090

@@ -105,13 +105,13 @@ def test_campaign_grouping_is_affected_by_order_for_mixed_types(campaign_evaluat
105105

106106
evaluator_s_first = campaign_evaluator
107107
result_s_first = list(
108-
evaluator_s_first.get_requested_grouped_campaigns([campaign_s, campaign_v], ["RSV"], "VACCINATIONS")
108+
evaluator_s_first.get_campaign_with_latest_active_iteration_per_target([campaign_s, campaign_v], ["RSV"], "VACCINATIONS")
109109
)
110110
assert_that(result_s_first, is_([]))
111111

112112
evaluator_v_first = campaign_evaluator
113113
result_v_first = list(
114-
evaluator_v_first.get_requested_grouped_campaigns([campaign_v, campaign_s], ["RSV"], "VACCINATIONS")
114+
evaluator_v_first.get_campaign_with_latest_active_iteration_per_target([campaign_v, campaign_s], ["RSV"], "VACCINATIONS")
115115
)
116116
assert_that(len(result_v_first), is_(1))
117117
assert_that(len(result_v_first[0][1]), is_(2))

0 commit comments

Comments
 (0)