Skip to content

Commit 01622c9

Browse files
committed
Added latest episode type and sub-type logic to subject_selection_query_builder
1 parent 84e5713 commit 01622c9

File tree

3 files changed

+64
-29
lines changed

3 files changed

+64
-29
lines changed

utils/oracle/mock_selection_builder.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,30 +27,43 @@ def __init__(self, criteria_key, criteria_value, criteria_comparator=">="):
2727
self.criteria_comparator = criteria_comparator
2828
self.sql_where = []
2929

30+
# Don't delete this method; it is used to inspect the SQL fragments
3031
def dump_sql(self):
3132
return "\n".join(self.sql_where)
3233

3334
# === Example testable method below ===
3435
# Replace this with the one you want to test,
3536
# then use utils/oracle/test_subject_criteria_dev.py to run your scenarios
3637

37-
def _add_criteria_subject_lower_lynch_age(self) -> None:
38+
def _add_criteria_latest_episode_sub_type(self) -> None:
3839
"""
39-
Adds a SQL constraint for Lynch syndrome lower-age eligibility.
40+
Adds a SQL condition that filters based on the episode_subtype_id of a subject's latest episode.
4041
41-
If value is 'default', it's replaced with '35'.
42-
Uses comparator to build the WHERE clause.
42+
Translates a human-readable episode sub-type string into an internal numeric ID.
4343
"""
4444
try:
45-
value = self.criteria_value
45+
value = self.criteria_value.lower()
4646
comparator = self.criteria_comparator
4747

48-
if value.lower() == "default":
49-
value = "35"
48+
# Simulated EpisodeSubType enum mapping
49+
episode_subtype_map = {
50+
"routine screening": 10,
51+
"urgent referral": 11,
52+
"pre-assessment": 12,
53+
"follow-up": 13,
54+
"surveillance": 14,
55+
# Add more mappings as needed
56+
}
5057

58+
if value not in episode_subtype_map:
59+
raise ValueError(f"Unknown episode sub-type: {value}")
60+
61+
episode_subtype_id = episode_subtype_map[value]
62+
63+
# Add SQL condition using the mapped ID
5164
self.sql_where.append(
52-
f"AND pkg_bcss_common.f_get_lynch_lower_age_limit (ss.screening_subject_id) "
53-
f"{comparator} {value}"
65+
f"AND ep.episode_subtype_id {comparator} {episode_subtype_id}"
5466
)
67+
5568
except Exception:
5669
raise SelectionBuilderException(self.criteria_key_name, self.criteria_value)

utils/oracle/subject_selection_query_builder.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,40 @@ def _add_criteria_subject_lower_lynch_age(self) -> None:
664664
except Exception:
665665
raise SelectionBuilderException(self.criteria_key_name, self.criteria_value)
666666

667+
def _add_criteria_latest_episode_type(self) -> None:
668+
"""
669+
Adds a SQL condition that restricts subjects based on the episode_type_id of their latest episode.
670+
671+
Translates a human-readable episode type string into an internal numeric ID.
672+
"""
673+
try:
674+
value = self.criteria_value.lower()
675+
comparator = self.criteria_comparator
676+
677+
# Simulate EpisodeType enum mapping
678+
episode_type_map = {
679+
"referral": 1,
680+
"invitation": 2,
681+
"test_kit_sent": 3,
682+
"reminder": 4,
683+
"episode_end": 5,
684+
# Add more mappings as needed
685+
}
686+
687+
if value not in episode_type_map:
688+
raise ValueError(f"Unknown episode type: {value}")
689+
690+
episode_type_id = episode_type_map[value]
691+
692+
# Simulate the required join (docs only—no real SQL execution here)
693+
# In real builder this would ensure join to 'latest_episode' alias (ep)
694+
self.sql_where.append(
695+
f"AND ep.episode_type_id {comparator} {episode_type_id}"
696+
)
697+
698+
except Exception:
699+
raise SelectionBuilderException(self.criteria_key_name, self.criteria_value)
700+
667701
def _add_criteria_subject_hub_code(self, user: "User") -> None:
668702
hub_code = None
669703
try:

utils/oracle/test_subject_criteria_dev.py

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,30 +30,18 @@
3030
# === Example usage ===
3131
# Replace the examples below with the method you want to test
3232

33-
# === Test: SUBJECT_HAS_AN_OPEN_EPISODEyes ===
33+
# === Test: LATEST_EPISODE_SUB_TYPERoutine Screening ===
3434
builder = MockSelectionBuilder(
35-
SubjectSelectionCriteriaKey.SUBJECT_HAS_AN_OPEN_EPISODE, "yes"
35+
SubjectSelectionCriteriaKey.LATEST_EPISODE_SUB_TYPE, "routine screening"
3636
)
37-
builder._add_criteria_subject_has_episodes()
38-
print("=== SUBJECT_HAS_AN_OPEN_EPISODEyes ===")
37+
builder._add_criteria_latest_episode_sub_type()
38+
print("=== LATEST_EPISODE_SUB_TYPEroutine screening ===")
3939
print(builder.dump_sql(), end="\n\n")
4040

41-
# === Test: SUBJECT_HAS_EPISODES — yes ===
42-
builder = MockSelectionBuilder(SubjectSelectionCriteriaKey.SUBJECT_HAS_EPISODES, "yes")
43-
builder._add_criteria_subject_has_episodes()
44-
print("=== SUBJECT_HAS_EPISODES — yes ===")
45-
print(builder.dump_sql(), end="\n\n")
46-
47-
# === Test: SUBJECT_HAS_EPISODES — no ===
48-
builder = MockSelectionBuilder(SubjectSelectionCriteriaKey.SUBJECT_HAS_EPISODES, "no")
49-
builder._add_criteria_subject_has_episodes()
50-
print("=== SUBJECT_HAS_EPISODES — no ===")
51-
print(builder.dump_sql(), end="\n\n")
52-
53-
# === Test: SUBJECT_HAS_FOBT_EPISODES — yes ===
41+
# === Test: LATEST_EPISODE_SUB_TYPE — Follow-up with custom comparator ===
5442
builder = MockSelectionBuilder(
55-
SubjectSelectionCriteriaKey.SUBJECT_HAS_FOBT_EPISODES, "yes"
43+
SubjectSelectionCriteriaKey.LATEST_EPISODE_SUB_TYPE, "follow-up", "!="
5644
)
57-
builder._add_criteria_subject_has_episodes(EpisodeType.FOBT)
58-
print("=== SUBJECT_HAS_FOBT_EPISODESyes with episode_type ===")
45+
builder._add_criteria_latest_episode_sub_type()
46+
print("=== LATEST_EPISODE_SUB_TYPEfollow-up (!=) ===")
5947
print(builder.dump_sql(), end="\n\n")

0 commit comments

Comments
 (0)