Skip to content

Commit 402189a

Browse files
wip-2
1 parent 0b86fb2 commit 402189a

2 files changed

Lines changed: 55 additions & 48 deletions

File tree

src/eligibility_signposting_api/model/eligibility.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from functools import total_ordering
77
from typing import NewType, Self
88

9+
from eligibility_signposting_api.model import rules
10+
911
NHSNumber = NewType("NHSNumber", str)
1012
DateOfBirth = NewType("DateOfBirth", date)
1113
Postcode = NewType("Postcode", str)
@@ -69,6 +71,13 @@ class Condition:
6971
status: Status
7072
reasons: list[Reason]
7173

74+
@dataclass
75+
class CohortStatus:
76+
cohort: rules.IterationCohort
77+
status: Status
78+
reasons: list[Reason]
79+
80+
7281

7382
@dataclass
7483
class EligibilityStatus:

src/eligibility_signposting_api/services/calculators/eligibility_calculator.py

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@
88
from itertools import groupby
99
from typing import Any
1010

11-
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map import iteration
1211
from wireup import service
1312

1413
from eligibility_signposting_api.model import eligibility, rules
15-
from eligibility_signposting_api.model.eligibility import Status
14+
from eligibility_signposting_api.model.eligibility import Status, CohortStatus
1615
from eligibility_signposting_api.services.calculators.rule_calculator import RuleCalculator
1716

1817
Row = Collection[Mapping[str, Any]]
@@ -73,76 +72,76 @@ def evaluate_eligibility_back_up(self) -> eligibility.EligibilityStatus:
7372
from collections import defaultdict
7473

7574
# Assuming cohort_results contains tuples of (IterationCohort, Status, list[Reason])
76-
def get_best_cohort(self,
77-
cohort_results: dict[
78-
str, tuple[rules.IterationCohort, eligibility.Status, list[eligibility.Reason]]]) -> tuple[
79-
rules.IterationCohort, eligibility.Status,
80-
list[
81-
eligibility.Reason]] | None:
82-
83-
84-
if not cohort_results:
85-
return None
75+
def get_best_cohort(
76+
self, cohort_results: dict[str, CohortStatus]
77+
) -> tuple[Status, list[CohortStatus]]:
8678

8779
# Find the best status across cohorts
88-
best_status = eligibility.Status.best(*[result[1] for result in cohort_results.values()])
80+
best_status = eligibility.Status.best(*[result.status for result in cohort_results.values()])
8981

9082
# Filter cohorts that match the best status
9183
best_cohorts = [result for result in cohort_results.values() if result[1] == best_status]
92-
93-
# Pick the cohort with the highest priority
94-
#TODO return the appropriate result
95-
# Actionable,Actionable, not-actionable, not-actionable, not eligible,not eligible
96-
return max(best_cohorts, key=lambda cohort: cohort[0].priority) if best_cohorts else None
84+
return best_status, best_cohorts
9785

9886
def evaluate_eligibility(self):
9987
"""Iterates over campaign groups, evaluates eligibility, and returns a consolidated status."""
10088
priority_getter = attrgetter("priority")
101-
results: dict[
102-
str, tuple[rules.IterationCohort, eligibility.Status, list[eligibility.Reason]]] = defaultdict()
89+
results: dict[str, tuple[Status, list[CohortStatus]]] = defaultdict()
10390
for condition_name, campaign_group in self.campaigns_grouped_by_condition_name:
104-
iteration_results: dict[
105-
str, tuple[rules.IterationCohort, eligibility.Status, list[eligibility.Reason]]] = defaultdict()
91+
iteration_results: dict[str, tuple[Status, list[CohortStatus]]] = defaultdict()
10692
for active_iteration in [cc.current_iteration for cc in campaign_group]:
107-
cohort_results: dict[
108-
str, tuple[rules.IterationCohort, eligibility.Status, list[eligibility.Reason]]] = defaultdict()
109-
rules_by_type = {rule_type: tuple(
110-
rule for rule in active_iteration.iteration_rules if attrgetter("type")(rule) == rule_type)
111-
for rule_type in {"F", "R", "S"}}
93+
cohort_results: dict[str, CohortStatus] = defaultdict()
94+
rules_by_type = {
95+
rule_type: tuple(
96+
rule for rule in active_iteration.iteration_rules if attrgetter("type")(rule) == rule_type
97+
)
98+
for rule_type in ("F", "R", "S")
99+
}
112100

113101
for cohort in sorted(active_iteration.iteration_cohorts, key=priority_getter):
114102
# Check base Eligibility
115103
if cohort.cohort_label in self.person_cohorts:
116104
# Base eligible
117105
# Check Eligibility - F - Rules
118106
eli_flag: bool = True
119-
for _, rule_group in groupby(sorted(rules_by_type["F"], key=priority_getter),
120-
key=priority_getter):
107+
for _, rule_group in groupby(
108+
sorted(rules_by_type["F"], key=priority_getter), key=priority_getter
109+
):
121110
# iter F rules by priority and grouping
122111
# find first exclusion - throws
123112
status, group_actionable, group_exclusions = self.evaluate_rules_priority_group(rule_group)
124113
if status.is_exclusion:
125-
cohort_results[cohort.cohort_label] = (cohort, status, group_exclusions)
114+
cohort_results[cohort.cohort_label] = CohortStatus(cohort, status, group_exclusions)
126115
eli_flag = False
127116
break
128-
if not eli_flag: continue
129117

130-
for _, rule_group in groupby(sorted(rules_by_type["S"], key=priority_getter),
131-
key=priority_getter):
132-
status, group_actionable, group_exclusions = self.evaluate_rules_priority_group(
133-
rule_group)
134-
if status.is_exclusion:
135-
cohort_results[cohort.cohort_label] = (cohort, status, group_exclusions)
136-
break
118+
if eli_flag:
119+
for _, rule_group in groupby(
120+
sorted(rules_by_type["S"], key=priority_getter), key=priority_getter
121+
):
122+
status, group_actionable, group_exclusions = self.evaluate_rules_priority_group(
123+
rule_group
124+
)
125+
if status.is_exclusion:
126+
cohort_results[cohort.cohort_label] = CohortStatus(cohort, status, group_exclusions)
127+
break
137128
else:
138129
# Not base eligibility
139-
cohort_results[cohort.cohort_label] = (cohort, eligibility.Status.not_eligible, [])
140-
141-
# Determine Result between cohorts
142-
iteration_results[active_iteration.name] = self.get_best_cohort(cohort_results)
143-
# Determine results between iterations
144-
results[condition_name] = self.get_best_cohort(iteration_results)
130+
cohort_results[cohort.cohort_label] = CohortStatus(cohort, eligibility.Status.not_eligible, [])
131+
132+
# Determine Result between cohorts - get the best
133+
iteration_results[active_iteration.name] = self.get_best_cohort(cohort_results) # multiple
134+
# Determine results between iterations - get the best
135+
best_so_far:Status = eligibility.Status.not_eligible
136+
for name, iteration_result in iteration_results.items():
137+
best_so_far = eligibility.Status.best(best_so_far, iteration_result[0])
138+
for name, iteration_result in iteration_results.items():
139+
if iteration_result[0] is best_so_far:
140+
results[condition_name] = iteration_result
141+
break
145142
# Consolidate all the results and return
143+
# TODO
144+
#results: dict[str, tuple[Status, list[CohortStatus]]] = defaultdict()
146145

147146
return eligibility.EligibilityStatus(conditions=list(self.results))
148147

@@ -213,7 +212,7 @@ def evaluate_priority_group(
213212
ir
214213
for ir in iteration_rule_group
215214
if ir.type in (rules.RuleType.filter, rules.RuleType.suppression)
216-
and (ir.cohort_label is None or (ir.cohort_label in self.person_cohorts))
215+
and (ir.cohort_label is None or (ir.cohort_label in self.person_cohorts))
217216
]
218217

219218
best_status = eligibility.Status.not_eligible if exclude_capable_rules else eligibility.Status.actionable
@@ -234,16 +233,15 @@ def evaluate_priority_group(
234233
return worst_group_status, actionable_reasons, exclusion_reasons, is_rule_stop
235234

236235
def evaluate_rules_priority_group( # TODO refractor
237-
self,
238-
iteration_rule_group: Iterator[rules.IterationRule]
236+
self, iteration_rule_group: Iterator[rules.IterationRule]
239237
) -> tuple[eligibility.Status, list[eligibility.Reason], list[eligibility.Reason]]:
240238
status = Status.not_eligible
241239
exclusion_reasons, actionable_reasons = [], []
242240
exclude_capable_rules = [
243241
ir
244242
for ir in iteration_rule_group
245243
if ir.type in (rules.RuleType.filter, rules.RuleType.suppression)
246-
and (ir.cohort_label is None or (ir.cohort_label in self.person_cohorts))
244+
and (ir.cohort_label is None or (ir.cohort_label in self.person_cohorts))
247245
]
248246

249247
for rule in exclude_capable_rules:

0 commit comments

Comments
 (0)