Skip to content

Commit 03d4cfb

Browse files
Bugfix to change response grouping from name to priority (#286)
* changed grouping from name to priority * changed grouping from name to priority, type * sonar code complexity fix * sonar code complexity fix * updated names in the code for better clarity * regroup the suitability tests * fix - ordering regroup the suitability tests * test for cohort groups --------- Co-authored-by: karthikeyannhs <174426205+Karthikeyannhs@users.noreply.github.com>
1 parent 754b6a3 commit 03d4cfb

5 files changed

Lines changed: 258 additions & 51 deletions

File tree

src/eligibility_signposting_api/model/eligibility_status.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class Condition:
113113
condition_name: ConditionName
114114
status: Status
115115
cohort_results: list[CohortGroupResult]
116+
suitability_rules: list[Reason]
116117
status_text: StatusText
117118
actions: list[SuggestedAction] | None = None
118119

src/eligibility_signposting_api/services/calculators/eligibility_calculator.py

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import logging
44
from collections import defaultdict
55
from dataclasses import dataclass, field
6+
from itertools import chain
67
from typing import TYPE_CHECKING
78

89
from wireup import service
@@ -16,6 +17,7 @@
1617
ConditionName,
1718
EligibilityStatus,
1819
IterationResult,
20+
Reason,
1921
Status,
2022
)
2123
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
100102
condition_results[condition_name] = best_iteration_result.iteration_result
101103
condition_results[condition_name].actions = matched_action_detail.actions
102104

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)
105109

106110
AuditContext.append_audit_condition(
107111
condition_name,
@@ -150,39 +154,61 @@ def get_iteration_results(self, campaign_group: list[CampaignConfig]) -> dict[It
150154
return iteration_results
151155

152156
@staticmethod
153-
def build_condition_results(iteration_result: IterationResult, condition_name: ConditionName) -> Condition:
157+
def build_condition(iteration_result: IterationResult, condition_name: ConditionName) -> Condition:
154158
grouped_cohort_results = defaultdict(list)
155159

156160
for cohort_result in iteration_result.cohort_results:
157161
if iteration_result.status == cohort_result.status:
158162
grouped_cohort_results[cohort_result.cohort_code].append(cohort_result)
159163

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+
)
181171

182172
return Condition(
183173
condition_name=condition_name,
184174
status=iteration_result.status,
185175
cohort_results=list(deduplicated_cohort_results),
176+
suitability_rules=list(overall_deduplicated_reasons_for_condition),
186177
actions=iteration_result.actions,
187178
status_text=iteration_result.status.get_status_text(condition_name),
188179
)
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())

src/eligibility_signposting_api/views/eligibility.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -158,22 +158,15 @@ def build_eligibility_cohorts(condition: Condition) -> list[eligibility_response
158158

159159

160160
def build_suitability_results(condition: Condition) -> list[eligibility_response.SuitabilityRule]:
161-
"""Make only one entry if there are duplicate rules"""
162161
if condition.status != Status.not_actionable:
163162
return []
164163

165-
suitability_results = []
166-
167-
for cohort_result in condition.cohort_results:
168-
if cohort_result.status == Status.not_actionable:
169-
suitability_results.extend(
170-
eligibility_response.SuitabilityRule(
171-
ruleType=eligibility_response.RuleType(reason.rule_type.value),
172-
ruleCode=eligibility_response.RuleCode(reason.rule_name),
173-
ruleText=eligibility_response.RuleText(reason.rule_description),
174-
)
175-
for reason in cohort_result.reasons
176-
if reason.rule_description
177-
)
178-
179-
return suitability_results
164+
return [
165+
eligibility_response.SuitabilityRule(
166+
ruleType=eligibility_response.RuleType(reason.rule_type.value),
167+
ruleCode=eligibility_response.RuleCode(reason.rule_name),
168+
ruleText=eligibility_response.RuleText(reason.rule_description),
169+
)
170+
for reason in condition.suitability_rules
171+
if reason.rule_description
172+
]

tests/fixtures/builders/model/eligibility.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class CohortResultFactory(DataclassFactory[eligibility_status.CohortGroupResult]
3333
class ConditionFactory(DataclassFactory[eligibility_status.Condition]):
3434
actions = Use(SuggestedActionFactory.batch, size=2)
3535
cohort_results = Use(CohortResultFactory.batch, size=2)
36+
suitability_rules = Use(ReasonFactory.batch, size=2)
3637

3738

3839
class EligibilityStatusFactory(DataclassFactory[eligibility_status.EligibilityStatus]):

0 commit comments

Comments
 (0)