88from itertools import groupby
99from typing import Any
1010
11- from localstack .services .stepfunctions .asl .component .state .state_execution .state_map import iteration
1211from wireup import service
1312
1413from 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
1615from eligibility_signposting_api .services .calculators .rule_calculator import RuleCalculator
1716
1817Row = 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