Skip to content

Commit dd1931f

Browse files
Added more match cases, classes and methods. Updated markdown doc
1 parent 5c9f51f commit dd1931f

9 files changed

+558
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from enum import Enum
2+
from typing import Optional, Dict
3+
4+
5+
class BowelScopeDDReasonForChangeType(Enum):
6+
Ceased = (200669, "Ceased")
7+
DateOfBirthAmendment = (205266, "Date of birth amendment")
8+
EligibleToBeInvitedForFsScreening = (
9+
200685,
10+
"Eligible to be invited for FS Screening",
11+
)
12+
FsScreeningEpisodeOpened = (205002, "FS Screening episode opened")
13+
MultipleDateOfBirthChanges = (202426, "Multiple Date of Birth Changes")
14+
NoLongerEligibleToBeInvitedForFsScreening = (
15+
200668,
16+
"No longer eligible to be invited for FS Screening",
17+
)
18+
ReopenedFsEpisode = (205012, "Reopened FS Episode")
19+
SeekingFurtherData = (200670, "Seeking further data")
20+
21+
def __init__(self, valid_value_id: int, description: str):
22+
self._valid_value_id: int = valid_value_id
23+
self._description: str = description
24+
25+
@property
26+
def valid_value_id(self) -> int:
27+
return self._valid_value_id
28+
29+
@property
30+
def description(self) -> str:
31+
return self._description
32+
33+
@classmethod
34+
def _descriptions(cls) -> Dict[str, "BowelScopeDDReasonForChangeType"]:
35+
return {item.description: item for item in cls}
36+
37+
@classmethod
38+
def _lowercase_descriptions(cls) -> Dict[str, "BowelScopeDDReasonForChangeType"]:
39+
return {item.description.lower(): item for item in cls}
40+
41+
@classmethod
42+
def _valid_value_ids(cls) -> Dict[int, "BowelScopeDDReasonForChangeType"]:
43+
return {item.valid_value_id: item for item in cls}
44+
45+
@classmethod
46+
def by_description(
47+
cls, description: Optional[str]
48+
) -> Optional["BowelScopeDDReasonForChangeType"]:
49+
if description is None:
50+
return None
51+
return cls._lowercase_descriptions().get(description.lower())
52+
53+
@classmethod
54+
def by_valid_value_id(
55+
cls, valid_value_id: int
56+
) -> Optional["BowelScopeDDReasonForChangeType"]:
57+
return cls._valid_value_ids().get(valid_value_id)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from enum import Enum
2+
from typing import Optional
3+
4+
5+
class CeasedConfirmationDetails(Enum):
6+
NULL = "null"
7+
NOT_NULL = "not null"
8+
9+
@classmethod
10+
def by_description(cls, description: str) -> Optional["CeasedConfirmationDetails"]:
11+
for item in cls:
12+
if item.value == description:
13+
return item
14+
return None
15+
16+
def get_description(self) -> str:
17+
return self.value
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from enum import Enum
2+
from typing import Optional, Dict
3+
4+
5+
class CeasedConfirmationUserId(Enum):
6+
AUTOMATED_PROCESS_ID = "automated process id"
7+
NULL = "null"
8+
NOT_NULL = "not null"
9+
USER_ID = "user's id"
10+
11+
@classmethod
12+
def by_description(cls, description: str) -> Optional["CeasedConfirmationUserId"]:
13+
for item in cls:
14+
if item.value == description:
15+
return item
16+
return None
17+
18+
def get_description(self) -> str:
19+
return self.value
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
from enum import Enum
2+
from typing import Optional, Dict
3+
4+
5+
class ClinicalCeaseReasonType(Enum):
6+
# BCSS values
7+
ALREADY_INVOLVED_IN_SURVEILLANCE_PROGRAMME_OUTSIDE_BCSP = (
8+
11369,
9+
"Already involved in Surveillance Programme outside BCSP",
10+
)
11+
CLINICAL_ASSESSMENT_INDICATES_CEASE_SURVEILLANCE_AND_SCREENING = (
12+
20066,
13+
"Clinical Assessment indicates Cease Surveillance and Screening",
14+
)
15+
CURRENTLY_UNDER_TREATMENT = (11371, "Currently under treatment")
16+
NO_FUNCTIONING_COLON = (11366, "No functioning colon")
17+
RECENT_COLONOSCOPY = (11372, "Recent colonoscopy")
18+
REFER_TO_SYMPTOMATIC_SERVICE = (205274, "Refer to Symptomatic Service")
19+
TERMINAL_ILLNESS = (11367, "Terminal Illness")
20+
UNDER_TREATMENT_FOR_ULCERATIVE_COLITIS_CROHNS_DISEASE_BOWEL_CANCER_OR_OTHER_RESULTING_IN_CEASE = (
21+
11368,
22+
"Under treatment for ulcerative colitis, Crohn's disease, bowel cancer or other, resulting in cease",
23+
)
24+
UNFIT_FOR_FURTHER_INVESTIGATION = (11373, "Unfit for further investigation")
25+
26+
# Extra subject selection criteria values
27+
NULL = (None, "Null")
28+
NOT_NULL = (None, "Not Null")
29+
30+
def __init__(self, valid_value_id: Optional[int], description: str):
31+
self._valid_value_id = valid_value_id
32+
self._description = description
33+
34+
@property
35+
def valid_value_id(self) -> Optional[int]:
36+
return self._valid_value_id
37+
38+
@property
39+
def description(self) -> str:
40+
return self._description
41+
42+
@classmethod
43+
def _build_lookup_maps(cls):
44+
cls._descriptions: Dict[str, "ClinicalCeaseReasonType"] = {}
45+
cls._lowercase_descriptions: Dict[str, "ClinicalCeaseReasonType"] = {}
46+
cls._valid_value_ids: Dict[int, "ClinicalCeaseReasonType"] = {}
47+
48+
for member in cls:
49+
if member.description:
50+
cls._descriptions[member.description] = member
51+
cls._lowercase_descriptions[member.description.lower()] = member
52+
if member.valid_value_id is not None:
53+
cls._valid_value_ids[member.valid_value_id] = member
54+
55+
@classmethod
56+
def by_description(cls, description: str) -> Optional["ClinicalCeaseReasonType"]:
57+
if not hasattr(cls, "_descriptions"):
58+
cls._build_lookup_maps()
59+
return cls._descriptions.get(description)
60+
61+
@classmethod
62+
def by_description_case_insensitive(
63+
cls, description: str
64+
) -> Optional["ClinicalCeaseReasonType"]:
65+
if not hasattr(cls, "_lowercase_descriptions"):
66+
cls._build_lookup_maps()
67+
return cls._lowercase_descriptions.get(description.lower())
68+
69+
@classmethod
70+
def by_valid_value_id(
71+
cls, valid_value_id: int
72+
) -> Optional["ClinicalCeaseReasonType"]:
73+
if not hasattr(cls, "_valid_value_ids"):
74+
cls._build_lookup_maps()
75+
return cls._valid_value_ids.get(valid_value_id)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from enum import Enum
2+
from typing import Optional, Dict
3+
4+
5+
class HasUnprocessedSSPIUpdates(Enum):
6+
NO = "no"
7+
YES = "yes"
8+
9+
@classmethod
10+
def by_description(cls, description: str) -> Optional["HasUnprocessedSSPIUpdates"]:
11+
for item in cls:
12+
if item.value == description:
13+
return item
14+
return None
15+
16+
def get_description(self) -> str:
17+
return self.value

classes/has_user_dob_update.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from enum import Enum
2+
from typing import Optional, Dict
3+
4+
5+
class HasUserDobUpdate(Enum):
6+
NO = "no"
7+
YES = "yes"
8+
9+
@classmethod
10+
def by_description(cls, description: str) -> Optional["HasUserDobUpdate"]:
11+
for item in cls:
12+
if item.value == description:
13+
return item
14+
return None
15+
16+
def get_description(self) -> str:
17+
return self.value

classes/manual_cease_requested.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from enum import Enum
2+
from typing import Optional
3+
4+
5+
class ManualCeaseRequested(Enum):
6+
NO = "no"
7+
DISCLAIMER_LETTER_REQUIRED = "yes - disclaimer letter required (c1)"
8+
DISCLAIMER_LETTER_SENT = "yes - disclaimer letter sent (c2)"
9+
YES = "yes"
10+
11+
def __init__(self, description: str) -> None:
12+
self._description: str = description
13+
14+
@property
15+
def description(self) -> str:
16+
return self._description
17+
18+
@classmethod
19+
def by_description(cls, description: str) -> Optional["ManualCeaseRequested"]:
20+
for item in cls:
21+
if item.description == description:
22+
return item
23+
return None
24+
25+
@classmethod
26+
def by_description_case_insensitive(
27+
cls, description: str
28+
) -> Optional["ManualCeaseRequested"]:
29+
if description is None:
30+
return None
31+
for item in cls:
32+
if item.description.lower() == description.lower():
33+
return item
34+
return None

utils/oracle/TEMP_subject_selection_query_builder.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,42 @@ Adds a date-based filter, supporting a wide range of date logic, including speci
144144

145145
Handles special date criteria such as "last birthday", "calculated due date", "unchanged", and various event-based offsets.
146146

147+
#### `_add_criteria_screening_due_date_reason(self, subject)`
148+
149+
Adds a filter for the screening due date reason, handling null, not null, unchanged, and specific value logic.
150+
151+
#### `_add_criteria_surveillance_due_date_reason(self, subject)`
152+
153+
Adds a filter for the surveillance due date reason, handling null, not null, unchanged, and specific value logic.
154+
155+
#### `_add_criteria_bowel_scope_due_date_reason(self, subject)`
156+
157+
Adds a filter for the bowel scope due date reason, handling null, not null, unchanged, and specific value logic.
158+
159+
#### `_add_criteria_ceased_confirmation_details(self)`
160+
161+
Adds a filter for ceased confirmation details, handling null, not null, and string matching.
162+
163+
#### `_add_criteria_ceased_confirmation_user_id(self, user)`
164+
165+
Adds a filter for ceased confirmation user ID, handling numeric IDs, enum values, and special cases.
166+
167+
#### `_add_criteria_clinical_reason_for_cease(self)`
168+
169+
Adds a filter for clinical reason for cease, supporting string and enum-based logic.
170+
171+
#### `_add_criteria_subject_has_event_status(self)`
172+
173+
Adds a filter for subjects with or without a specific event status.
174+
175+
#### `_add_criteria_has_unprocessed_sspi_updates(self)`
176+
177+
Adds a filter for subjects with unprocessed SSPI updates.
178+
179+
#### `_add_criteria_has_user_dob_update(self)`
180+
181+
Adds a filter for subjects with user date of birth updates.
182+
147183
---
148184

149185
### SQL Helper Methods
@@ -250,6 +286,62 @@ Returns a `SelectionBuilderException` for invalid use of "unchanged".
250286

251287
---
252288

289+
### Classes Used in This Module
290+
291+
#### `Subject`
292+
293+
Represents a screening subject, encapsulating all relevant subject data and providing methods to access screening status, due dates, and other subject-specific information.
294+
295+
#### `User`
296+
297+
Represents a user of the system, including their associated organisation and permissions.
298+
299+
#### `Organisation`
300+
301+
Represents an organisation (such as a hub or screening centre) with an organisation ID and related metadata.
302+
303+
#### `SubjectSelectionCriteriaKey`
304+
305+
An enum representing all possible criteria keys that can be used for subject selection. Each key includes metadata such as whether it allows the "NOT:" modifier or multiple values.
306+
307+
#### `ScreeningStatusType`
308+
309+
An enum representing possible screening statuses for a subject, with methods for lookup by description and value.
310+
311+
#### `SSReasonForChangeType`
312+
313+
An enum for reasons a subject's screening status was changed, with lookup methods.
314+
315+
#### `SDDReasonForChangeType`
316+
317+
An enum for reasons a subject's screening due date was changed, with lookup methods.
318+
319+
#### `SSDDReasonForChangeType`
320+
321+
An enum for reasons a subject's surveillance due date was changed, with lookup methods.
322+
323+
#### `BowelScopeDDReasonForChangeType`
324+
325+
An enum for reasons a subject's bowel scope due date was changed, with lookup methods.
326+
327+
#### `CeasedConfirmationDetails`
328+
329+
An enum for ceased confirmation details, supporting null/not-null and string matching.
330+
331+
#### `CeasedConfirmationUserId`
332+
333+
An enum for ceased confirmation user IDs, supporting special values and user lookups.
334+
335+
#### `ManualCeaseRequested`
336+
337+
An enum for manual cease request statuses, with case-insensitive lookup.
338+
339+
#### `HasGPPractice`
340+
341+
An enum for GP practice status (yes/no/active/inactive), with description-based lookup.
342+
343+
---
344+
253345
## ToDo
254346

255347
### Selenium Copy
@@ -266,3 +358,8 @@ Returns a `SelectionBuilderException` for invalid use of "unchanged".
266358
- [ ] Add logging for all major decision points in query construction.
267359
- [ ] Review and update doc strings for clarity and completeness.
268360
- [ ] Double check `_add_criteria_date_field` against `addCriteriaDateField` to see if functionality ported over correctly. This included looking at any methods referenced in this method.
361+
362+
### May Require Another Jira Ticket
363+
364+
- [ ] Create tests around this utility to prove it works as intended. See if there is a current selenium test that does this.
365+
- [ ] Create a new utility around populating the Subject and User class objects. This will be beneficial as these two objects are passed into this utility.

0 commit comments

Comments
 (0)