Skip to content

Commit c60d0c8

Browse files
committed
snomed validation added
1 parent 1525013 commit c60d0c8

File tree

5 files changed

+69
-11
lines changed

5 files changed

+69
-11
lines changed

delta_backend/src/ConversionChecker.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,18 @@ def convertData(self, expressionType, expressionRule, fieldName, fieldValue):
7272
return self._convertToChangeTo(
7373
expressionRule, fieldName, fieldValue, self.summarise, self.report_unexpected_exception
7474
)
75+
case "BOOLEAN":
76+
return self._convertToBoolean(
77+
expressionRule, fieldName, fieldValue, self.summarise, self.report_unexpected_exception
78+
)
7579
case "LOOKUP":
7680
return self._convertToLookUp(
7781
expressionRule, fieldName, fieldValue, self.summarise, self.report_unexpected_exception
7882
)
83+
case "SNOMED":
84+
return self._convertToSnomed(
85+
expressionRule, fieldName, fieldValue, self.summarise, self.report_unexpected_exception
86+
)
7987
case "DEFAULT":
8088
return self._convertToDefaultTo(
8189
expressionRule, fieldName, fieldValue, self.summarise, self.report_unexpected_exception
@@ -148,14 +156,17 @@ def _convertToDateTime(self, expressionRule, fieldName, fieldValue, summarise, r
148156
# Not Empty Validate - Returns exactly what is in the extracted fields no parsing or logic needed
149157
def _convertToNotEmpty(self, expressionRule, fieldName, fieldValue, summarise, report_unexpected_exception):
150158
try:
151-
if len(str(fieldValue)) > 0:
159+
if isinstance(fieldValue, (int, float)):
160+
return "" # Reject plain numbers
161+
if isinstance(fieldValue, str) and fieldValue.strip():
152162
return fieldValue
153163
return ""
154164
except Exception as e:
155165
if report_unexpected_exception:
156166
message = ExceptionMessages.MESSAGES[ExceptionMessages.UNEXPECTED_EXCEPTION] % (e.__class__.__name__, e)
157167
return message
158168

169+
159170
# NHSNumber Validate
160171
def _convertToNHSNumber(self, expressionRule, fieldName, fieldValue, summarise, report_unexpected_exception):
161172
"""
@@ -266,3 +277,46 @@ def _convertToOnlyIfTo(self, expressionRule, fieldName, fieldValue, summarise, r
266277
if report_unexpected_exception:
267278
message = ExceptionMessages.MESSAGES[ExceptionMessages.UNEXPECTED_EXCEPTION] % (e.__class__.__name__, e)
268279
return message
280+
281+
# Check if Snomed code is numeric and reject other forms
282+
def _convertToSnomed(self, expressionRule, fieldName, fieldValue, summarise, report_unexpected_exception):
283+
"""
284+
Validates that a SNOMED code is a non-empty string containing only digits.
285+
"""
286+
try:
287+
if not fieldValue or not isinstance(fieldValue, str) or not fieldValue.isdigit():
288+
raise ValueError(f"Invalid SNOMED code: {fieldValue}")
289+
return fieldValue
290+
except Exception as e:
291+
if report_unexpected_exception:
292+
message = ExceptionMessages.MESSAGES[ExceptionMessages.UNEXPECTED_EXCEPTION] % (e.__class__.__name__, e)
293+
self.errorRecords.append({
294+
"field": fieldName,
295+
"value": fieldValue,
296+
"message": message
297+
})
298+
return ""
299+
300+
# Check if Input is boolean or if input is a string with true or false, convert to Boolean
301+
def _convertToBoolean(self, expressionRule, fieldName, fieldValue, summarise, report_unexpected_exception):
302+
try:
303+
if isinstance(fieldValue, bool):
304+
return fieldValue
305+
306+
if isinstance(fieldValue, str):
307+
lowered = fieldValue.strip().lower()
308+
if lowered == "true":
309+
return True
310+
elif lowered == "false":
311+
return False
312+
313+
return "" # Invalid input
314+
except Exception as e:
315+
if report_unexpected_exception:
316+
message = ExceptionMessages.MESSAGES[ExceptionMessages.UNEXPECTED_EXCEPTION] % (
317+
e.__class__.__name__, e
318+
)
319+
return message
320+
321+
322+

delta_backend/src/ConversionLayout.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@
148148
"fieldNameFlat": "PRIMARY_SOURCE",
149149
"expression": {
150150
"expressionName": "Not Empty",
151-
"expressionType": "NOTEMPTY",
151+
"expressionType": "BOOLEAN",
152152
"expressionRule": ""
153153
}
154154
},
@@ -157,7 +157,7 @@
157157
"fieldNameFlat": "VACCINATION_PROCEDURE_CODE",
158158
"expression": {
159159
"expressionName": "Not Empty",
160-
"expressionType": "NOTEMPTY",
160+
"expressionType": "SNOMED",
161161
"expressionRule": ""
162162
}
163163
},
@@ -184,7 +184,7 @@
184184
"fieldNameFlat": "VACCINE_PRODUCT_CODE",
185185
"expression": {
186186
"expressionName": "Not Empty",
187-
"expressionType": "NOTEMPTY",
187+
"expressionType": "SNOMED",
188188
"expressionRule": ""
189189
}
190190
},
@@ -229,7 +229,7 @@
229229
"fieldNameFlat": "SITE_OF_VACCINATION_CODE",
230230
"expression": {
231231
"expressionName": "Not Empty",
232-
"expressionType": "NOTEMPTY",
232+
"expressionType": "SNOMED",
233233
"expressionRule": ""
234234
}
235235
},
@@ -247,7 +247,7 @@
247247
"fieldNameFlat": "ROUTE_OF_VACCINATION_CODE",
248248
"expression": {
249249
"expressionName": "Not Empty",
250-
"expressionType": "NOTEMPTY",
250+
"expressionType": "SNOMED",
251251
"expressionRule": ""
252252
}
253253
},
@@ -292,7 +292,7 @@
292292
"fieldNameFlat": "INDICATION_CODE",
293293
"expression": {
294294
"expressionName": "Not Empty",
295-
"expressionType": "NOTEMPTY",
295+
"expressionType": "SNOMED",
296296
"expressionRule": ""
297297
}
298298
},

delta_backend/src/log_firehose.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ def __init__(
1919
self.delivery_stream_name = stream_name
2020

2121
def send_log(self, log_message):
22+
# if not self.delivery_stream_name:
23+
# logger.warning("No SPLUNK_FIREHOSE_NAME set — skipping Firehose log.")
24+
# return
25+
2226
log_to_splunk = log_message
2327
logger.info(f"Log sent to Firehose for save: {log_to_splunk}")
2428
encoded_log_data = json.dumps(log_to_splunk).encode("utf-8")

delta_backend/tests/sample_data/fhir_sample.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"coding": [
4747
{
4848
"system": "http://snomed.info/sct",
49-
"code": "1324681000000101",
49+
"code": "abletimes",
5050
"display": "Administration of first dose of severe acute respiratory syndrome coronavirus 2 vaccine (procedure)"
5151
}
5252
]
@@ -131,7 +131,7 @@
131131
{
132132
"coding": [
133133
{
134-
"code": "443684005",
134+
"code": "nauthgy",
135135
"system": "http://snomed.info/sct"
136136
}
137137
]

delta_backend/tests/test_delta.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ def test_handler_exception_intrusion_check_false(self, mock_boto_resource, mock_
203203
with self.assertRaises(Exception):
204204
handler(event, context)
205205

206-
@patch("delta.firehose_logger.send_log") # Mock Firehose logger
206+
@patch("delta.firehose_logger.send_log", return_value=None) # Mock Firehose logger
207207
@patch("delta.logger.info") # Mock logging
208208
def test_dps_record_skipped(self, mock_logger_info, mock_firehose_send_log):
209209
event = self.get_event(supplier="DPSFULL")
@@ -219,7 +219,7 @@ def test_dps_record_skipped(self, mock_logger_info, mock_firehose_send_log):
219219
mock_logger_info.assert_called_with("Record from DPS skipped for 12345")
220220

221221
# TODO - amend test once error handling implemented
222-
@patch("delta.firehose_logger.send_log")
222+
@patch("delta.firehose_logger.send_log", return_value=None)
223223
@patch("delta.logger.info")
224224
@patch("Converter.Converter")
225225
@patch("delta.boto3.resource")

0 commit comments

Comments
 (0)