Skip to content

Commit 2f94da2

Browse files
committed
Added appointment selection criteria and joins to query builder
1 parent 26ed942 commit 2f94da2

File tree

3 files changed

+116
-22
lines changed

3 files changed

+116
-22
lines changed

utils/oracle/mock_selection_builder.py

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,38 +30,69 @@ def __init__(self, criteria_key, criteria_value, criteria_comparator=">="):
3030

3131
# Don't delete this method; it is used to inspect the SQL fragments
3232
def dump_sql(self):
33-
return "\n".join(self.sql_where)
34-
33+
parts = []
34+
35+
if self.sql_from:
36+
parts.append("-- FROM clause --")
37+
parts.extend(self.sql_from)
38+
39+
if self.sql_where:
40+
parts.append("-- WHERE clause --")
41+
parts.extend(self.sql_where)
42+
43+
return "\n".join(parts)
44+
3545
def _add_join_to_latest_episode(self) -> None:
3646
"""
3747
Mock stub for adding latest episode join. No-op for test harness.
3848
"""
3949
self.sql_from.append("-- JOIN to latest episode placeholder")
4050

41-
4251
# === Example testable method below ===
4352
# Replace this with the one you want to test,
4453
# then use utils/oracle/test_subject_criteria_dev.py to run your scenarios
4554

46-
def _add_criteria_kit_has_analyser_result_code(self) -> None:
55+
def _add_join_to_appointments(self) -> None:
4756
"""
48-
Filters kits based on whether they have an analyser error code.
49-
Requires prior join to tk_items_t as alias 'tk' (via WHICH_TEST_KIT).
57+
Adds join to appointment_t table based on appointment selection strategy.
58+
Requires prior join to latest episode (ep). Aliases the appointment table as 'ap'.
5059
5160
Accepts values:
52-
- "yes" → analyser_error_code IS NOT NULL
53-
- "no" → analyser_error_code IS NULL
61+
- "any_appointment_in_latest_episode"
62+
- "latest_appointment_in_latest_episode"
63+
- "earlier_appointment_in_latest_episode"
64+
- "later_appointment_in_latest_episode"
5465
"""
5566
try:
5667
value = self.criteria_value.strip().lower()
68+
ap_alias = "ap"
69+
apr_alias = "ap_prev" # Simulated prior alias for test support
70+
71+
self._add_join_to_latest_episode()
72+
self.sql_from.append(
73+
f"INNER JOIN appointment_t {ap_alias} ON {ap_alias}.subject_epis_id = ep.subject_epis_id"
74+
)
5775

58-
if value == "yes":
59-
self.sql_where.append("AND tk.analyser_error_code IS NOT NULL")
60-
elif value == "no":
61-
self.sql_where.append("AND tk.analyser_error_code IS NULL")
76+
if value == "any_appointment_in_latest_episode":
77+
return
78+
elif value == "latest_appointment_in_latest_episode":
79+
self.sql_from.append(
80+
f"AND {ap_alias}.appointment_id = ("
81+
f" SELECT MAX(apx.appointment_id)"
82+
f" FROM appointment_t apx"
83+
f" WHERE apx.subject_epis_id = ep.subject_epis_id"
84+
f" AND apx.void = 'N')"
85+
)
86+
elif value == "earlier_appointment_in_latest_episode":
87+
self.sql_from.append(
88+
f"AND {ap_alias}.appointment_id < {apr_alias}.appointment_id"
89+
)
90+
elif value == "later_appointment_in_latest_episode":
91+
self.sql_from.append(
92+
f"AND {ap_alias}.appointment_id > {apr_alias}.appointment_id"
93+
)
6294
else:
63-
raise ValueError(f"Invalid value for analyser result code presence: {value}")
95+
raise ValueError(f"Invalid appointment selection value: {value}")
6496

6597
except Exception:
6698
raise SelectionBuilderException(self.criteria_key_name, self.criteria_value)
67-

utils/oracle/subject_selection_query_builder.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,51 @@ def _add_criteria_kit_has_analyser_result_code(self) -> None:
15171517
except Exception:
15181518
raise SelectionBuilderException(self.criteria_key_name, self.criteria_value)
15191519

1520+
def _add_join_to_appointments(self) -> None:
1521+
"""
1522+
Adds join to appointment_t table based on appointment selection strategy.
1523+
Requires prior join to latest episode (ep). Aliases the appointment table as 'ap'.
1524+
1525+
Accepts values:
1526+
- "any_appointment_in_latest_episode"
1527+
- "latest_appointment_in_latest_episode"
1528+
- "earlier_appointment_in_latest_episode"
1529+
- "later_appointment_in_latest_episode"
1530+
"""
1531+
try:
1532+
value = self.criteria_value.strip().lower()
1533+
ap_alias = "ap"
1534+
apr_alias = "ap_prev" # Simulated prior alias for test support
1535+
1536+
self._add_join_to_latest_episode()
1537+
self.sql_from.append(
1538+
f"INNER JOIN appointment_t {ap_alias} ON {ap_alias}.subject_epis_id = ep.subject_epis_id"
1539+
)
1540+
1541+
if value == "any_appointment_in_latest_episode":
1542+
return
1543+
elif value == "latest_appointment_in_latest_episode":
1544+
self.sql_from.append(
1545+
f"AND {ap_alias}.appointment_id = ("
1546+
f" SELECT MAX(apx.appointment_id)"
1547+
f" FROM appointment_t apx"
1548+
f" WHERE apx.subject_epis_id = ep.subject_epis_id"
1549+
f" AND apx.void = 'N')"
1550+
)
1551+
elif value == "earlier_appointment_in_latest_episode":
1552+
self.sql_from.append(
1553+
f"AND {ap_alias}.appointment_id < {apr_alias}.appointment_id"
1554+
)
1555+
elif value == "later_appointment_in_latest_episode":
1556+
self.sql_from.append(
1557+
f"AND {ap_alias}.appointment_id > {apr_alias}.appointment_id"
1558+
)
1559+
else:
1560+
raise ValueError(f"Invalid appointment selection value: {value}")
1561+
1562+
except Exception:
1563+
raise SelectionBuilderException(self.criteria_key_name, self.criteria_value)
1564+
15201565
# ------------------------------------------------------------------------
15211566
# 🧬 CADS Clinical Dataset Filters
15221567
# ------------------------------------------------------------------------

utils/oracle/test_subject_criteria_dev.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,36 @@
2929
# === Example usage ===
3030
# Replace the examples below with your tests for the method you want to test
3131

32-
# === Test: KIT_HAS_ANALYSER_RESULT_CODEyes ===
32+
# === Test: WHICH_APPOINTMENTany_appointment_in_latest_episode ===
3333
builder = MockSelectionBuilder(
34-
SubjectSelectionCriteriaKey.KIT_HAS_ANALYSER_RESULT_CODE, "yes"
34+
SubjectSelectionCriteriaKey.WHICH_APPOINTMENT, "any_appointment_in_latest_episode"
3535
)
36-
builder._add_criteria_kit_has_analyser_result_code()
37-
print("=== KIT_HAS_ANALYSER_RESULT_CODEyes ===")
36+
builder._add_join_to_appointments()
37+
print("=== WHICH_APPOINTMENTany_appointment_in_latest_episode ===")
3838
print(builder.dump_sql(), end="\n\n")
3939

40-
# === Test: KIT_HAS_ANALYSER_RESULT_CODEno ===
40+
# === Test: WHICH_APPOINTMENTlatest_appointment_in_latest_episode ===
4141
builder = MockSelectionBuilder(
42-
SubjectSelectionCriteriaKey.KIT_HAS_ANALYSER_RESULT_CODE, "no"
42+
SubjectSelectionCriteriaKey.WHICH_APPOINTMENT,
43+
"latest_appointment_in_latest_episode",
4344
)
44-
builder._add_criteria_kit_has_analyser_result_code()
45-
print("=== KIT_HAS_ANALYSER_RESULT_CODE — no ===")
45+
builder._add_join_to_appointments()
46+
print("=== WHICH_APPOINTMENT — latest_appointment_in_latest_episode ===")
47+
print(builder.dump_sql(), end="\n\n")
48+
49+
# === Test: WHICH_APPOINTMENT — earlier_appointment_in_latest_episode ===
50+
builder = MockSelectionBuilder(
51+
SubjectSelectionCriteriaKey.WHICH_APPOINTMENT,
52+
"earlier_appointment_in_latest_episode",
53+
)
54+
builder._add_join_to_appointments()
55+
print("=== WHICH_APPOINTMENT — earlier_appointment_in_latest_episode ===")
56+
print(builder.dump_sql(), end="\n\n")
57+
58+
# === Test: WHICH_APPOINTMENT — later_appointment_in_latest_episode ===
59+
builder = MockSelectionBuilder(
60+
SubjectSelectionCriteriaKey.WHICH_APPOINTMENT, "later_appointment_in_latest_episode"
61+
)
62+
builder._add_join_to_appointments()
63+
print("=== WHICH_APPOINTMENT — later_appointment_in_latest_episode ===")
4664
print(builder.dump_sql(), end="\n\n")

0 commit comments

Comments
 (0)