11from oracle .oracle import OracleDB
22import logging
33import pandas as pd
4+ from datetime import datetime
5+
46
57def get_kit_id_from_db () -> pd .DataFrame :
68 """
@@ -11,7 +13,8 @@ def get_kit_id_from_db() -> pd.DataFrame:
1113 - se.latest_event_status_id is 11198 or 11213 (Only kits at the status we want S10/S19 are retrieved)
1214 """
1315 logging .info ("Retrieving useable test kit ids" )
14- kit_id_df = OracleDB ().execute_query ("""select tk.kitid, tk.screening_subject_id, sst.subject_nhs_number
16+ kit_id_df = OracleDB ().execute_query (
17+ """select tk.kitid, tk.screening_subject_id, sst.subject_nhs_number
1518 from tk_items_t tk
1619 inner join ep_subject_episode_t se on se.screening_subject_id = tk.screening_subject_id
1720 inner join screening_subject_t sst on (sst.screening_subject_id = tk.screening_subject_id)
@@ -23,15 +26,18 @@ def get_kit_id_from_db() -> pd.DataFrame:
2326 and tk.invalidated_date is null
2427 and se.latest_event_status_id in (11198, 11213)
2528 order by tk.kitid DESC
26- fetch first 10 rows only""" )
29+ fetch first 10 rows only"""
30+ )
2731 return kit_id_df
2832
33+
2934def get_nhs_no_from_batch_id (batch_id ) -> pd .DataFrame :
3035 """
3136 This query returns a dataframe of NHS Numbers of the subjects in a certain batch
3237 We provide the batch ID e.g. 8812 and then we have a list of NHS Numbers we can verify the statuses
3338 """
34- nhs_number_df = OracleDB ().execute_query (f"""
39+ nhs_number_df = OracleDB ().execute_query (
40+ f"""
3541 SELECT SUBJECT_NHS_NUMBER
3642 FROM SCREENING_SUBJECT_T ss
3743 INNER JOIN sd_contact_t c ON ss.subject_nhs_number = c.nhs_number
@@ -40,5 +46,163 @@ def get_nhs_no_from_batch_id(batch_id) -> pd.DataFrame:
4046 WHERE lbr.BATCH_ID IN { batch_id }
4147 AND ss.screening_status_id != 4008
4248 ORDER BY ss.subject_nhs_number
43- """ )
49+ """
50+ )
4451 return nhs_number_df
52+
53+
54+ def get_kit_id_logged_from_db () -> pd .DataFrame :
55+ """
56+ This query is used to obtain test data used in compartment 3
57+ It searches for kits that have not been logged and meet the following criteria:
58+ - tk.tk_type_id = 2 (Only FIT Kits)
59+ - tk.logged_in_at = 23159 (Hub ID that the compartments are running in)
60+ """
61+ kit_id_df = OracleDB ().execute_query (
62+ """SELECT tk.kitid,tk.device_id,tk.screening_subject_id
63+ FROM tk_items_t tk
64+ INNER JOIN kit_queue kq ON kq.device_id = tk.device_id
65+ INNER JOIN ep_subject_episode_t se ON se.screening_subject_id = tk.screening_subject_id
66+ WHERE tk.logged_in_flag = 'Y'
67+ AND kq.test_kit_status IN ('LOGGED', 'POSTED')
68+ AND se.episode_status_id = 11352
69+ AND tk.tk_type_id = 2
70+ AND se.latest_event_status_id = 11223
71+ AND tk.logged_in_at = 23159
72+ AND tk.reading_flag = 'N'
73+ AND tk.test_results IS NULL
74+ fetch first 9 rows only
75+ """
76+ )
77+
78+ return kit_id_df
79+
80+
81+ def get_service_management_by_device_id (deviceid ) -> pd .DataFrame :
82+ """
83+ This SQL is similar to the one used in pkg_test_kit_queue.p_get_fit_monitor_details, but adapted to allow us to pick out sub-sets of records
84+ """
85+ get_service_management_df = OracleDB ().execute_query (
86+ f"""SELECT kq.device_id, kq.test_kit_name, kq.test_kit_type, kq.test_kit_status,
87+ CASE WHEN tki.logged_in_flag = 'Y' THEN kq.logged_by_hub END AS logged_by_hub,
88+ CASE WHEN tki.logged_in_flag = 'Y' THEN kq.date_time_logged END AS date_time_logged,
89+ tki.logged_in_on AS tk_logged_date_time, kq.test_result, kq.calculated_result,
90+ kq.error_code,
91+ (SELECT vvt.description
92+ FROM tk_analyser_t tka
93+ INNER JOIN tk_analyser_type_error tkate ON tkate.tk_analyser_type_id = tka.tk_analyser_type_id
94+ INNER JOIN valid_values vvt ON tkate.tk_analyser_error_type_id = vvt.valid_value_id
95+ WHERE tka.analyser_code = kq.analyser_code AND tkate.error_code = kq.error_code)
96+ AS analyser_error_description, kq.analyser_code, kq.date_time_authorised,
97+ kq.authoriser_user_code, kq.datestamp, kq.bcss_error_id,
98+ REPLACE(mt.description, 'ERROR - ', '') AS error_type,
99+ NVL(mta.allowed_value, 'N') AS error_ok_to_archive,
100+ kq.post_response, kq.post_attempts, kq.put_response,
101+ kq.put_attempts, kq.date_time_error_archived,
102+ kq.error_archived_user_code, sst.screening_subject_id,
103+ sst.subject_nhs_number, tki.test_results, tki.issue_date,
104+ o.org_code AS issued_by_hub
105+ FROM kit_queue kq
106+ LEFT OUTER JOIN tk_items_t tki ON tki.device_id = kq.device_id
107+ OR (tki.device_id IS NULL AND tki.kitid = pkg_test_kit.f_get_kit_id_from_device_id(kq.device_id))
108+ LEFT OUTER JOIN screening_subject_t sst ON sst.screening_subject_id = tki.screening_subject_id
109+ LEFT OUTER JOIN ep_subject_episode_t ep ON ep.subject_epis_id = tki.subject_epis_id
110+ LEFT OUTER JOIN message_types mt ON kq.bcss_error_id = mt.message_type_id
111+ LEFT OUTER JOIN valid_values mta ON mta.valid_value_id = mt.message_attribute_id AND mta.valid_value_id = 305482
112+ LEFT OUTER JOIN ORG o ON ep.start_hub_id = o.org_id
113+ LEFT OUTER JOIN ORG lo ON lo.org_code = kq.logged_by_hub
114+ WHERE kq.test_kit_type = 'FIT' AND kq.device_id = '{ deviceid } '
115+ """
116+ )
117+ return get_service_management_df
118+
119+
120+ def update_kit_service_management_entity (device_id , normal ) -> str :
121+ """
122+ This method is used to update the KIT_QUEUE table on the DB
123+ This is done so that we can then run two stored procedures to update the subjects and kits status to either normal or abnormal
124+ """
125+ get_service_management_df = get_service_management_by_device_id (device_id )
126+
127+ # Extract the NHS number from the DataFrame
128+ subject_nhs_number = get_service_management_df ["subject_nhs_number" ].iloc [0 ]
129+ test_kit_name = get_service_management_df ["test_kit_name" ].iloc [0 ]
130+ test_kit_type = get_service_management_df ["test_kit_type" ].iloc [0 ]
131+ logged_by_hub = get_service_management_df ["logged_by_hub" ].iloc [0 ]
132+ date_time_logged = get_service_management_df ["date_time_logged" ].iloc [0 ]
133+ calculated_result = get_service_management_df ["calculated_result" ].iloc [0 ]
134+ post_response = get_service_management_df ["post_response" ].iloc [0 ]
135+ post_attempts = get_service_management_df ["post_attempts" ].iloc [0 ]
136+ put_response = get_service_management_df ["put_response" ].iloc [0 ]
137+ put_attempts = get_service_management_df ["put_attempts" ].iloc [0 ]
138+ # format date
139+ date_time_authorised = (
140+ datetime .now ().strftime ("%d-%b-%y %H.%M.%S." )
141+ + f"{ datetime .now ().microsecond :06d} 000"
142+ )
143+ if normal :
144+ test_result = 75
145+ else :
146+ test_result = 150
147+ # Parameterized query
148+ update_query = """
149+ UPDATE kit_queue kq
150+ SET kq.test_kit_name = :test_kit_name,
151+ kq.test_kit_type = :test_kit_type,
152+ kq.test_kit_status =:test_kit_status,
153+ kq.logged_by_hub = :logged_by_hub,
154+ kq.date_time_logged = :date_time_logged,
155+ kq.test_result = :test_result,
156+ kq.calculated_result = :calculated_result,
157+ kq.error_code = NULL,
158+ kq.analyser_code = 'UU2_tdH3',
159+ kq.date_time_authorised = TO_TIMESTAMP(:date_time_authorised, 'DD-Mon-YY HH24.MI.SS.FF9'),
160+ kq.authoriser_user_code = 'AUTO1',
161+ kq.post_response = :post_response,
162+ kq.post_attempts = :post_attempts,
163+ kq.put_response = :put_response,
164+ kq.put_attempts = :put_attempts
165+ WHERE kq.device_id = :device_id
166+ """
167+
168+ # Parameters dictionary
169+ params = {
170+ "test_kit_name" : test_kit_name ,
171+ "test_kit_type" : test_kit_type ,
172+ "test_kit_status" : "BCSS_READY" ,
173+ "logged_by_hub" : logged_by_hub ,
174+ "date_time_logged" : date_time_logged ,
175+ "test_result" : int (test_result ),
176+ "calculated_result" : calculated_result ,
177+ "date_time_authorised" : str (date_time_authorised ),
178+ "post_response" : int (post_response ) if post_response is not None else 0 ,
179+ "post_attempts" : int (post_attempts ) if post_attempts is not None else 0 ,
180+ "put_response" : put_response ,
181+ "put_attempts" : put_attempts ,
182+ "device_id" : device_id ,
183+ }
184+
185+ # Execute query
186+ logging .info ("Parameters before execution:" , params )
187+ rows_affected = OracleDB ().update_or_insert_data_to_table (update_query , params )
188+ logging .info (f"Rows affected: { rows_affected } " )
189+ # Return the subject NHS number
190+ return subject_nhs_number
191+
192+
193+ def execute_stored_procedures () -> None :
194+ """
195+ This method executes two stored procedures:
196+ - PKG_TEST_KIT_QUEUE.p_validate_kit_queue
197+ - PKG_TEST_KIT_QUEUE.p_calculate_result
198+ This is needed for compartment 3 after we update the KIT_QUE table on the DB
199+ """
200+ db_instance = OracleDB () # Create an instance of the OracleDB class
201+ logging .info ("start: oracle.OracleDB.execute_stored_procedure" )
202+ db_instance .execute_stored_procedure (
203+ "PKG_TEST_KIT_QUEUE.p_validate_kit_queue"
204+ ) # Run stored procedure - validate kit queue
205+ db_instance .execute_stored_procedure (
206+ "PKG_TEST_KIT_QUEUE.p_calculate_result"
207+ ) # Run stored procedure - calculate result
208+ logging .info ("exit: oracle.OracleDB.execute_stored_procedure" )
0 commit comments