Skip to content

Commit af1512e

Browse files
authored
Merge branch 'main' into feature/eja-eli-759-removing-reliance-on-PAT-for-regression-tests
2 parents 0d77a17 + df56379 commit af1512e

2 files changed

Lines changed: 182 additions & 0 deletions

File tree

src/eligibility_signposting_api/services/calculators/eligibility_calculator.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ def get_eligibility_status(
102102
include_actions_flag=include_actions_flag,
103103
)
104104

105+
if matched_action_detail.status_text_override:
106+
iteration_result_summary.iteration_result.status_text = matched_action_detail.status_text_override
107+
105108
iteration_result_summary = TokenProcessor.find_and_replace_tokens(self.person, iteration_result_summary)
106109
matched_action_detail = TokenProcessor.find_and_replace_tokens(self.person, matched_action_detail)
107110

tests/unit/services/calculators/test_eligibility_calculator.py

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import datetime
22
import logging
33
from typing import Any
4+
from unittest.mock import MagicMock
45

56
import pytest
67
from faker import Faker
@@ -33,6 +34,7 @@
3334
DateOfBirth,
3435
InternalActionCode,
3536
IterationResult,
37+
MatchedActionDetail,
3638
NHSNumber,
3739
Postcode,
3840
Reason,
@@ -53,6 +55,183 @@
5355
)
5456

5557

58+
def test_get_eligibility_status_uses_status_text_override_when_present(faker: Faker):
59+
"""
60+
Test: override present → statusText replaced
61+
If an override status text is provided, it replaces the original status text
62+
produced by the iteration.
63+
"""
64+
nhs_number = NHSNumber(faker.nhs_number())
65+
66+
person_rows = person_rows_builder(
67+
nhs_number,
68+
cohorts=["cohort1"],
69+
icb="QE1",
70+
)
71+
72+
campaign_configs = [
73+
rule_builder.CampaignConfigFactory.build(
74+
target="RSV",
75+
iterations=[
76+
rule_builder.IterationFactory.build(
77+
iteration_cohorts=[rule_builder.IterationCohortFactory.build(cohort_label="cohort1")],
78+
iteration_rules=[],
79+
status_text=campaign_config.StatusText(
80+
NotEligible="You are not eligible for RSV.",
81+
NotActionable="You are not currently able to book RSV.",
82+
Actionable="Original actionable text",
83+
),
84+
)
85+
],
86+
)
87+
]
88+
89+
calculator = EligibilityCalculator(person_rows, campaign_configs)
90+
calculator.action_rule_handler.get_actions = MagicMock(
91+
return_value=MatchedActionDetail(status_text_override=StatusText("Override actionable text"))
92+
)
93+
94+
actual = calculator.get_eligibility_status("Y", ["ALL"], "ALL")
95+
96+
assert len(actual.conditions) == 1
97+
assert actual.conditions[0].condition_name == ConditionName("RSV")
98+
assert actual.conditions[0].status == Status.actionable
99+
assert actual.conditions[0].status_text == StatusText("Override actionable text")
100+
assert g.audit_log.response.condition[0].status_text == "Override actionable text"
101+
102+
103+
def test_get_eligibility_status_keeps_original_status_text_when_override_absent(faker: Faker):
104+
"""
105+
Override absent → statusText unchanged
106+
If no override is provided, the calculator should keep the original
107+
status text from the iteration.
108+
"""
109+
nhs_number = NHSNumber(faker.nhs_number())
110+
111+
person_rows = person_rows_builder(
112+
nhs_number,
113+
cohorts=["cohort1"],
114+
icb="QE1",
115+
)
116+
117+
campaign_configs = [
118+
rule_builder.CampaignConfigFactory.build(
119+
target="RSV",
120+
iterations=[
121+
rule_builder.IterationFactory.build(
122+
iteration_cohorts=[rule_builder.IterationCohortFactory.build(cohort_label="cohort1")],
123+
iteration_rules=[],
124+
status_text=campaign_config.StatusText(
125+
NotEligible="You are not eligible for RSV.",
126+
NotActionable="You are not currently able to book RSV.",
127+
Actionable="Original actionable text",
128+
),
129+
)
130+
],
131+
)
132+
]
133+
134+
calculator = EligibilityCalculator(person_rows, campaign_configs)
135+
calculator.action_rule_handler.get_actions = MagicMock(return_value=MatchedActionDetail(status_text_override=None))
136+
137+
actual = calculator.get_eligibility_status("Y", ["ALL"], "ALL")
138+
139+
assert len(actual.conditions) == 1
140+
assert actual.conditions[0].condition_name == ConditionName("RSV")
141+
assert actual.conditions[0].status == Status.actionable
142+
assert actual.conditions[0].status_text == StatusText("Original actionable text")
143+
assert g.audit_log.response.condition[0].status_text == "Original actionable text"
144+
145+
146+
def test_get_eligibility_status_resolves_tokens_in_status_text_override(faker: Faker):
147+
"""
148+
Test: override with token → resolved
149+
check that a token inside the override status text gets replaced with actual person data.
150+
"""
151+
nhs_number = NHSNumber(faker.nhs_number())
152+
153+
person_rows = person_rows_builder(
154+
nhs_number,
155+
cohorts=["cohort1"],
156+
icb="ICB123",
157+
)
158+
159+
campaign_configs = [
160+
rule_builder.CampaignConfigFactory.build(
161+
target="RSV",
162+
iterations=[
163+
rule_builder.IterationFactory.build(
164+
iteration_cohorts=[rule_builder.IterationCohortFactory.build(cohort_label="cohort1")],
165+
iteration_rules=[],
166+
status_text=campaign_config.StatusText(
167+
NotEligible="You are not eligible for RSV.",
168+
NotActionable="You are not currently able to book RSV.",
169+
Actionable="Original actionable text",
170+
),
171+
)
172+
],
173+
)
174+
]
175+
176+
calculator = EligibilityCalculator(person_rows, campaign_configs)
177+
calculator.action_rule_handler.get_actions = MagicMock(
178+
return_value=MatchedActionDetail(status_text_override=StatusText("You can book via [[PERSON.ICB]]."))
179+
)
180+
181+
actual = calculator.get_eligibility_status("Y", ["ALL"], "ALL")
182+
183+
assert len(actual.conditions) == 1
184+
assert actual.conditions[0].condition_name == ConditionName("RSV")
185+
assert actual.conditions[0].status == Status.actionable
186+
assert actual.conditions[0].status_text == StatusText("You can book via ICB123.")
187+
assert g.audit_log.response.condition[0].status_text == "You can book via ICB123."
188+
189+
190+
def test_get_eligibility_status_applies_override_before_token_processing(faker: Faker):
191+
"""
192+
Test: override applied before token processing (order verification)
193+
Check if apply the override first, and only then replace tokens
194+
"""
195+
nhs_number = NHSNumber(faker.nhs_number())
196+
197+
person_rows = person_rows_builder(
198+
nhs_number,
199+
cohorts=["cohort1"],
200+
icb="ICB999",
201+
)
202+
203+
campaign_configs = [
204+
rule_builder.CampaignConfigFactory.build(
205+
target="RSV",
206+
iterations=[
207+
rule_builder.IterationFactory.build(
208+
iteration_cohorts=[rule_builder.IterationCohortFactory.build(cohort_label="cohort1")],
209+
iteration_rules=[],
210+
status_text=campaign_config.StatusText(
211+
NotEligible="You are not eligible for RSV.",
212+
NotActionable="You are not currently able to book RSV.",
213+
Actionable="ORIGINAL [[PERSON.ICB]]",
214+
),
215+
)
216+
],
217+
)
218+
]
219+
220+
calculator = EligibilityCalculator(person_rows, campaign_configs)
221+
calculator.action_rule_handler.get_actions = MagicMock(
222+
return_value=MatchedActionDetail(status_text_override=StatusText("OVERRIDE [[PERSON.ICB]]"))
223+
)
224+
225+
actual = calculator.get_eligibility_status("Y", ["ALL"], "ALL")
226+
227+
assert len(actual.conditions) == 1
228+
assert actual.conditions[0].condition_name == ConditionName("RSV")
229+
assert actual.conditions[0].status == Status.actionable
230+
assert actual.conditions[0].status_text == StatusText("OVERRIDE ICB999")
231+
assert actual.conditions[0].status_text != StatusText("ORIGINAL ICB999")
232+
assert g.audit_log.response.condition[0].status_text == "OVERRIDE ICB999"
233+
234+
56235
@pytest.fixture
57236
def app():
58237
return Flask(__name__)

0 commit comments

Comments
 (0)