Skip to content

Commit 2d4800d

Browse files
committed
Merge branch 'feature/BCSS-21304-selenium0to-playwright-fobtregressiontests-scenario-1' into feature/BCSS-21304-selenium0to-playwright-fobtregressiontests-scenario-2
2 parents 52cdecf + 573c5fc commit 2d4800d

File tree

12 files changed

+942
-16
lines changed

12 files changed

+942
-16
lines changed

classes/analyser.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from dataclasses import dataclass
2+
from typing import Optional
3+
import pandas as pd
4+
5+
6+
@dataclass
7+
class Analyser:
8+
"""
9+
Data class representing an analyser.
10+
"""
11+
12+
analyser_id: Optional[int] = None
13+
analyser_code: Optional[str] = None
14+
hub_id: Optional[int] = None
15+
analyser_type_id: Optional[int] = None
16+
spoil_result_code: Optional[int] = None
17+
tech_fail_result_code: Optional[int] = None
18+
below_range_result_code: Optional[int] = None
19+
above_range_result_code: Optional[int] = None
20+
21+
def __str__(self) -> str:
22+
return (
23+
f"Analyser [analyser_id={self.analyser_id}, analyser_code={self.analyser_code}, "
24+
f"hub_id={self.hub_id}, spoil_result_code={self.spoil_result_code}, "
25+
f"tech_fail_result_code={self.tech_fail_result_code}, "
26+
f"below_range_result_code={self.below_range_result_code}, "
27+
f"above_range_result_code={self.above_range_result_code}]"
28+
)
29+
30+
@staticmethod
31+
def from_dataframe_row(row: pd.Series) -> "Analyser":
32+
"""
33+
Creates an Analyser object from a pandas DataFrame row containing analyser query results.
34+
35+
Args:
36+
row (pd.Series): A row from a pandas DataFrame with columns:
37+
- tk_analyser_id
38+
- analyser_code
39+
- hub_id
40+
- tk_analyser_type_id
41+
42+
Returns:
43+
Analyser: The constructed Analyser object.
44+
"""
45+
return Analyser(
46+
analyser_id=row.get("tk_analyser_id"),
47+
analyser_code=row.get("analyser_code"),
48+
hub_id=row.get("hub_id"),
49+
analyser_type_id=row.get("tk_analyser_type_id"),
50+
)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from enum import Enum
2+
from typing import Optional, Dict
3+
4+
5+
class AnalyserResultCodeType(Enum):
6+
"""
7+
Enum for analyser result code types, mapped to valid value IDs and descriptions.
8+
"""
9+
10+
ABOVE_DILUTION_RANGE = (309030, "Above dilution range")
11+
BELOW_MEASURING_RANGE = (309028, "Below measuring range")
12+
SPOILT = (309026, "Spoilt")
13+
TECHNICAL_FAIL = (309027, "Technical Fail")
14+
15+
def __init__(self, valid_value_id: int, description: str) -> None:
16+
self._valid_value_id = valid_value_id
17+
self._description = description
18+
19+
@property
20+
def valid_value_id(self) -> int:
21+
"""
22+
Returns the valid value ID for the analyser result code type.
23+
"""
24+
return self._valid_value_id
25+
26+
@property
27+
def description(self) -> str:
28+
"""
29+
Returns the description for the analyser result code type.
30+
"""
31+
return self._description
32+
33+
@classmethod
34+
def by_description(cls, description: str) -> Optional["AnalyserResultCodeType"]:
35+
"""
36+
Returns the enum member matching the given description (case-sensitive).
37+
"""
38+
for member in cls:
39+
if member.description == description:
40+
return member
41+
return None
42+
43+
@classmethod
44+
def by_description_case_insensitive(
45+
cls, description: str
46+
) -> Optional["AnalyserResultCodeType"]:
47+
"""
48+
Returns the enum member matching the given description (case-insensitive).
49+
"""
50+
desc_lower = description.lower()
51+
for member in cls:
52+
if member.description.lower() == desc_lower:
53+
return member
54+
return None
55+
56+
@classmethod
57+
def by_valid_value_id(
58+
cls, valid_value_id: int
59+
) -> Optional["AnalyserResultCodeType"]:
60+
"""
61+
Returns the enum member matching the given valid value ID.
62+
"""
63+
for member in cls:
64+
if member.valid_value_id == valid_value_id:
65+
return member
66+
return None
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
from dataclasses import dataclass
2+
from typing import Optional
3+
from decimal import Decimal
4+
from datetime import datetime
5+
from classes.kit_service_management_record import KitServiceManagementRecord
6+
7+
8+
@dataclass
9+
class KitServiceManagementEntity:
10+
"""
11+
Data class representing a kit service management entity (KIT_QUEUE table).
12+
"""
13+
14+
device_id: Optional[str] = None
15+
test_kit_type: Optional[str] = None
16+
test_kit_name: Optional[str] = None
17+
test_kit_status: Optional[str] = None
18+
logged_by_hub: Optional[str] = None
19+
date_time_logged: Optional[datetime] = None
20+
test_result: Optional[Decimal] = None
21+
calculated_result: Optional[str] = None
22+
error_code: Optional[int] = None
23+
analyser_code: Optional[str] = None
24+
date_time_authorised: Optional[datetime] = None
25+
authoriser_user_code: Optional[str] = None
26+
datestamp: Optional[datetime] = None
27+
bcss_error_id: Optional[int] = None
28+
post_response: Optional[int] = None
29+
post_attempts: Optional[int] = None
30+
put_response: Optional[int] = None
31+
put_attempts: Optional[int] = None
32+
date_time_error_archived: Optional[datetime] = None
33+
error_archived_user_code: Optional[str] = None
34+
issue_date: Optional[datetime] = None
35+
issued_by_hub: Optional[str] = None
36+
nhs_number: Optional[str] = None
37+
analyser_error_description: Optional[str] = None
38+
error_type: Optional[str] = None
39+
screening_test_result: Optional[str] = None
40+
41+
@staticmethod
42+
def from_record(
43+
record: "KitServiceManagementRecord",
44+
) -> "KitServiceManagementEntity":
45+
"""
46+
Converts a KitServiceManagementRecord object into a KitServiceManagementEntity object.
47+
48+
Args:
49+
record (KitServiceManagementRecord): The record to convert.
50+
51+
Returns:
52+
KitServiceManagementEntity: The converted entity.
53+
"""
54+
return KitServiceManagementEntity(
55+
device_id=record.device_id,
56+
test_kit_type=(
57+
str(record.test_kit_type) if record.test_kit_type is not None else None
58+
),
59+
test_kit_name=record.test_kit_name,
60+
test_kit_status=record.test_kit_status,
61+
logged_by_hub=record.logged_by_hub,
62+
date_time_logged=record.date_time_logged,
63+
test_result=record.test_result,
64+
calculated_result=record.calculated_result,
65+
error_code=record.error_code,
66+
analyser_code=record.analyser_code,
67+
date_time_authorised=record.date_time_authorised,
68+
authoriser_user_code=record.authoriser_user_code,
69+
datestamp=record.datestamp,
70+
bcss_error_id=record.bcss_error_id,
71+
post_response=record.post_response,
72+
post_attempts=record.post_attempts,
73+
put_response=record.put_response,
74+
put_attempts=record.put_attempts,
75+
date_time_error_archived=record.date_time_error_archived,
76+
error_archived_user_code=record.error_archived_user_code,
77+
issue_date=record.date_time_issued,
78+
issued_by_hub=record.issued_by_hub,
79+
nhs_number=record.nhs_number,
80+
analyser_error_description=record.analyser_error_description,
81+
error_type=record.error_type,
82+
screening_test_result=record.screening_test_result,
83+
)

classes/hub_type.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from enum import Enum
2+
3+
4+
class HubType(Enum):
5+
"""
6+
Enum representing hub types.
7+
"""
8+
9+
BCS01 = "BCS01"
10+
BCS02 = "BCS02"
11+
BCS03 = "BCS03"
12+
BCS04 = "BCS04"
13+
BCS05 = "BCS05"
14+
BCS099 = "BCS099"
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
from dataclasses import dataclass
2+
from typing import Optional
3+
from decimal import Decimal
4+
from datetime import datetime
5+
from utils.date_time_utils import DateTimeUtils
6+
7+
8+
@dataclass
9+
class KitServiceManagementRecord:
10+
"""
11+
Data class representing a kit service management record.
12+
"""
13+
14+
# Kit queue data items
15+
device_id: Optional[str] = None
16+
test_kit_type: Optional[int] = None
17+
test_kit_name: Optional[str] = None
18+
test_kit_status: Optional[str] = None
19+
logged_by_hub: Optional[str] = None
20+
date_time_logged: Optional[datetime] = None
21+
test_result: Optional[Decimal] = None
22+
calculated_result: Optional[str] = None
23+
error_code: Optional[int] = None
24+
analyser_code: Optional[str] = None
25+
date_time_authorised: Optional[datetime] = None
26+
authoriser_user_code: Optional[str] = None
27+
datestamp: Optional[datetime] = None
28+
bcss_error_id: Optional[int] = None
29+
post_response: Optional[int] = None
30+
post_attempts: Optional[int] = None
31+
put_response: Optional[int] = None
32+
put_attempts: Optional[int] = None
33+
date_time_error_archived: Optional[datetime] = None
34+
error_archived_user_code: Optional[str] = None
35+
36+
# Kit data items
37+
date_time_issued: Optional[datetime] = None
38+
issued_by_hub: Optional[str] = None
39+
nhs_number: Optional[str] = None
40+
analyser_error_description: Optional[str] = None
41+
error_type: Optional[str] = None
42+
screening_test_result: Optional[str] = None
43+
44+
def __str__(self) -> str:
45+
return (
46+
f"KitServiceManagementRecord [device_id={self.device_id}, test_kit_type={self.test_kit_type}, "
47+
f"test_kit_name={self.test_kit_name}, test_kit_status={self.test_kit_status}, "
48+
f"logged_by_hub={self.logged_by_hub}, date_time_logged={self.date_time_logged}, "
49+
f"test_result={self.test_result}, calculated_result={self.calculated_result}, "
50+
f"error_code={self.error_code}, analyser_code={self.analyser_code}, "
51+
f"date_time_authorised={self.date_time_authorised}, authoriser_user_code={self.authoriser_user_code}, "
52+
f"datestamp={self.datestamp}, bcss_error_id={self.bcss_error_id}, post_response={self.post_response}, "
53+
f"post_attempts={self.post_attempts}, put_response={self.put_response}, put_attempts={self.put_attempts}, "
54+
f"date_time_error_archived={self.date_time_error_archived}, error_archived_user_code={self.error_archived_user_code}, "
55+
f"date_time_issued={self.date_time_issued}, issued_by_hub={self.issued_by_hub}, nhs_number={self.nhs_number}, "
56+
f"analyser_error_description={self.analyser_error_description}, error_type={self.error_type}, "
57+
f"screening_test_result={self.screening_test_result}]"
58+
)
59+
60+
@staticmethod
61+
def from_dataframe_row(row) -> "KitServiceManagementRecord":
62+
"""
63+
Creates a KitServiceManagementRecord object from a pandas DataFrame row containing kit service management query results.
64+
65+
Args:
66+
row (pd.Series): A row from a pandas DataFrame with columns matching the query.
67+
68+
Returns:
69+
KitServiceManagementRecord: The constructed object.
70+
"""
71+
72+
def parse_enum(enum_cls, value):
73+
if value is None:
74+
return None
75+
try:
76+
return enum_cls(value)
77+
except ValueError:
78+
return None
79+
80+
def parse_decimal(value):
81+
if value is None or value == "":
82+
return None
83+
try:
84+
return Decimal(str(value))
85+
except Exception:
86+
return None
87+
88+
return KitServiceManagementRecord(
89+
device_id=row.get("device_id"),
90+
test_kit_type=row.get("test_kit_type"),
91+
test_kit_name=row.get("test_kit_name"),
92+
test_kit_status=row.get("test_kit_status"),
93+
logged_by_hub=row.get("logged_by_hub"),
94+
date_time_logged=DateTimeUtils.parse_datetime(row.get("date_time_logged")),
95+
test_result=parse_decimal(row.get("test_result")),
96+
calculated_result=row.get("calculated_result"),
97+
error_code=row.get("error_code"),
98+
analyser_code=row.get("analyser_code"),
99+
date_time_authorised=DateTimeUtils.parse_datetime(
100+
row.get("date_time_authorised")
101+
),
102+
authoriser_user_code=row.get("authoriser_user_code"),
103+
datestamp=DateTimeUtils.parse_datetime(row.get("datestamp")),
104+
bcss_error_id=row.get("bcss_error_id"),
105+
post_response=row.get("post_response"),
106+
post_attempts=row.get("post_attempts"),
107+
put_response=row.get("put_response"),
108+
put_attempts=row.get("put_attempts"),
109+
date_time_error_archived=DateTimeUtils.parse_datetime(
110+
row.get("date_time_error_archived")
111+
),
112+
error_archived_user_code=row.get("error_archived_user_code"),
113+
date_time_issued=DateTimeUtils.parse_datetime(row.get("issue_date")),
114+
issued_by_hub=row.get("issued_by_hub"),
115+
nhs_number=row.get("subject_nhs_number"),
116+
analyser_error_description=row.get("analyser_error_description"),
117+
error_type=row.get("error_type"),
118+
screening_test_result=row.get("test_results"),
119+
)

classes/kit_status.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+
3+
4+
class KitStatus(Enum):
5+
"""
6+
Enum representing kit statuses.
7+
"""
8+
9+
NEW = "NEW"
10+
LOGGED = "LOGGED"
11+
POSTED = "POSTED"
12+
AUTHORISED = "AUTHORISED"
13+
BCSS_READY = "BCSS_READY"
14+
BCSS_PROCESSING = "BCSS_PROCESSING"
15+
BCSS_PROCESSED = "BCSS_PROCESSED"
16+
COMPLETE = "COMPLETE"
17+
ERROR = "ERROR"

classes/kit_type.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from enum import Enum
2+
3+
4+
class KitType(Enum):
5+
"""
6+
Enum representing kit types.
7+
"""
8+
9+
ANY = 0
10+
GFOBT = 1
11+
FIT = 2
12+
QC = 999
13+
14+
@property
15+
def id(self) -> int:
16+
"""
17+
Returns the kit type ID.
18+
"""
19+
return self.value

0 commit comments

Comments
 (0)