|
3 | 3 | import logging |
4 | 4 | from collections import defaultdict |
5 | 5 | from dataclasses import dataclass, field |
| 6 | +from itertools import chain |
6 | 7 | from typing import TYPE_CHECKING |
7 | 8 |
|
8 | 9 | from wireup import service |
|
16 | 17 | ConditionName, |
17 | 18 | EligibilityStatus, |
18 | 19 | IterationResult, |
| 20 | + Reason, |
19 | 21 | Status, |
20 | 22 | ) |
21 | 23 | from eligibility_signposting_api.services.processors.action_rule_handler import ActionRuleHandler |
@@ -100,8 +102,10 @@ def get_eligibility_status(self, include_actions: str, conditions: list[str], ca |
100 | 102 | condition_results[condition_name] = best_iteration_result.iteration_result |
101 | 103 | condition_results[condition_name].actions = matched_action_detail.actions |
102 | 104 |
|
103 | | - condition_result = self.build_condition_results(condition_results[condition_name], condition_name) |
104 | | - final_result.append(condition_result) |
| 105 | + condition: Condition = self.build_condition( |
| 106 | + iteration_result=condition_results[condition_name], condition_name=condition_name |
| 107 | + ) |
| 108 | + final_result.append(condition) |
105 | 109 |
|
106 | 110 | AuditContext.append_audit_condition( |
107 | 111 | condition_name, |
@@ -150,39 +154,61 @@ def get_iteration_results(self, campaign_group: list[CampaignConfig]) -> dict[It |
150 | 154 | return iteration_results |
151 | 155 |
|
152 | 156 | @staticmethod |
153 | | - def build_condition_results(iteration_result: IterationResult, condition_name: ConditionName) -> Condition: |
| 157 | + def build_condition(iteration_result: IterationResult, condition_name: ConditionName) -> Condition: |
154 | 158 | grouped_cohort_results = defaultdict(list) |
155 | 159 |
|
156 | 160 | for cohort_result in iteration_result.cohort_results: |
157 | 161 | if iteration_result.status == cohort_result.status: |
158 | 162 | grouped_cohort_results[cohort_result.cohort_code].append(cohort_result) |
159 | 163 |
|
160 | | - deduplicated_cohort_results = [] |
161 | | - |
162 | | - for group_cohort_code, group in grouped_cohort_results.items(): |
163 | | - if group: |
164 | | - unique_rule_codes = set() |
165 | | - deduplicated_reasons = [] |
166 | | - for cohort in group: |
167 | | - for reason in cohort.reasons: |
168 | | - if reason.rule_name not in unique_rule_codes and reason.rule_description: |
169 | | - unique_rule_codes.add(reason.rule_name) |
170 | | - deduplicated_reasons.append(reason) |
171 | | - |
172 | | - non_empty_description = next((c.description for c in group if c.description), group[0].description) |
173 | | - cohort_group_result = CohortGroupResult( |
174 | | - cohort_code=group_cohort_code, |
175 | | - status=group[0].status, |
176 | | - reasons=deduplicated_reasons, |
177 | | - description=non_empty_description, |
178 | | - audit_rules=[], |
179 | | - ) |
180 | | - deduplicated_cohort_results.append(cohort_group_result) |
| 164 | + deduplicated_cohort_results: list[CohortGroupResult] = EligibilityCalculator.deduplicate_cohort_results( |
| 165 | + grouped_cohort_results |
| 166 | + ) |
| 167 | + |
| 168 | + overall_deduplicated_reasons_for_condition = EligibilityCalculator.deduplicate_reasons( |
| 169 | + deduplicated_cohort_results |
| 170 | + ) |
181 | 171 |
|
182 | 172 | return Condition( |
183 | 173 | condition_name=condition_name, |
184 | 174 | status=iteration_result.status, |
185 | 175 | cohort_results=list(deduplicated_cohort_results), |
| 176 | + suitability_rules=list(overall_deduplicated_reasons_for_condition), |
186 | 177 | actions=iteration_result.actions, |
187 | 178 | status_text=iteration_result.status.get_status_text(condition_name), |
188 | 179 | ) |
| 180 | + |
| 181 | + @staticmethod |
| 182 | + def deduplicate_cohort_results( |
| 183 | + grouped_cohort_results: dict[str, list[CohortGroupResult]], |
| 184 | + ) -> list[CohortGroupResult]: |
| 185 | + results = [] |
| 186 | + |
| 187 | + for cohort_code, group_results in grouped_cohort_results.items(): |
| 188 | + if not group_results: |
| 189 | + continue |
| 190 | + |
| 191 | + deduped_reasons: list[Reason] = EligibilityCalculator.deduplicate_reasons(group_results) |
| 192 | + |
| 193 | + description = next((c.description for c in group_results if c.description), group_results[0].description) |
| 194 | + |
| 195 | + results.append( |
| 196 | + CohortGroupResult( |
| 197 | + cohort_code=cohort_code, |
| 198 | + status=group_results[0].status, |
| 199 | + reasons=list(deduped_reasons), |
| 200 | + description=description, |
| 201 | + audit_rules=[], |
| 202 | + ) |
| 203 | + ) |
| 204 | + |
| 205 | + return results |
| 206 | + |
| 207 | + @staticmethod |
| 208 | + def deduplicate_reasons(group_results: list[CohortGroupResult]) -> list[Reason]: |
| 209 | + all_reasons = chain.from_iterable(group_result.reasons for group_result in group_results) |
| 210 | + deduped = {} |
| 211 | + for reason in all_reasons: |
| 212 | + key = (reason.rule_type, reason.rule_priority) |
| 213 | + deduped.setdefault(key, reason) |
| 214 | + return list(deduped.values()) |
0 commit comments