Skip to content

Commit 8491ff4

Browse files
committed
eip
1 parent eae63b0 commit 8491ff4

File tree

4 files changed

+93
-138
lines changed

4 files changed

+93
-138
lines changed

lambdas/id_sync/src/pds_details.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,29 @@ def pds_get_patient_details(nhs_number: str) -> dict:
3131
logger.info("SAW...4")
3232
patient = pds_service.get_patient_details(nhs_number)
3333
logger.info("SAW...5")
34-
logger.info("SAW...5.1 check Patient details")
35-
if patient:
36-
logger.info(f"Patient details found for NHS number: {nhs_number}")
37-
logger.info(f"Patient details: {patient}")
38-
pds_nhs_number = patient["identifier"][0]["value"]
39-
return pds_nhs_number
40-
else:
41-
logger.info(f"No patient details found for ID: {nhs_number}")
42-
return None
34+
return patient
4335
except Exception as e:
4436
msg = f"Error getting PDS patient details for {nhs_number}"
4537
logger.exception(msg)
4638
raise IdSyncException(message=msg, exception=e)
39+
40+
41+
def pds_get_patient_id(nhs_number: str) -> str:
42+
"""
43+
Get PDS patient ID from NHS number.
44+
:param nhs_number: NHS number of the patient
45+
:return: PDS patient ID
46+
"""
47+
try:
48+
logger.info(f"get_pds_patient_id. nhs_number: {nhs_number}")
49+
patient_details = pds_get_patient_details(nhs_number)
50+
if not patient_details:
51+
return None
52+
53+
return patient_details["identifier"][0]["value"]
54+
55+
# ✅ Remove the IdSyncException catch since you're just re-raising
56+
except Exception as e:
57+
msg = f"Error getting PDS patient ID for {nhs_number}"
58+
logger.exception(msg)
59+
raise IdSyncException(message=msg, exception=e)

lambdas/id_sync/src/record_processor.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
'''
44
from common.clients import logger
55
from typing import Optional
6-
from pds_details import pds_get_patient_details
6+
from pds_details import pds_get_patient_id
77
from ieds_db_operations import ieds_check_exist, ieds_update_patient_id
88
import json
99
import ast
@@ -38,19 +38,11 @@ def process_record(event_record):
3838
def process_nhs_number(nhs_number: str) -> Optional[str]:
3939
# get patient details from PDS
4040
logger.debug(f"process_nhs_number. Processing NHS number: {nhs_number}")
41-
patient_details = pds_get_patient_details(nhs_number)
42-
logger.info(f"process_nhs_number. Patient details: {patient_details}")
43-
if not patient_details:
44-
return {"status": "error", "message": f"No records returned for ID: {nhs_number}"}
45-
46-
logger.info(f"process_nhs_number.get ID: from {patient_details.get('id')}")
47-
if patient_details and "identifier" in patient_details and patient_details["identifier"]:
48-
patient_details_id = patient_details["identifier"][0]["value"]
49-
else:
50-
return {"status": "error", "message": f"No records returned for ID: {nhs_number}"}
41+
patient_details_id = pds_get_patient_id(nhs_number)
5142

5243
base_log_data = {"nhs_number": nhs_number}
5344
if patient_details_id:
45+
logger.info(f"process_nhs_number. Patient details ID: {patient_details_id}")
5446
# if patient NHS != id, update patient index of vax events to new number
5547
if patient_details_id != nhs_number and patient_details_id:
5648
if ieds_check_exist(patient_details_id):
@@ -60,6 +52,6 @@ def process_nhs_number(nhs_number: str) -> Optional[str]:
6052
else:
6153
return {"status": "success", "message": "No update required"}
6254
else:
63-
response = {"status": "error", "message": f"No patient ID found for NHS number: {nhs_number}"}
55+
response = {"status": "success", "message": f"No patient ID found for NHS number: {nhs_number}"}
6456
response.update(base_log_data)
6557
return response

lambdas/id_sync/tests/test_pds_details.py

Lines changed: 55 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import unittest
22
from unittest.mock import patch, MagicMock
3-
from pds_details import pds_get_patient_details
3+
from pds_details import pds_get_patient_details, pds_get_patient_id
44
from models.id_sync_exception import IdSyncException
55

66

@@ -57,7 +57,7 @@ def test_pds_get_patient_details_success(self):
5757
result = pds_get_patient_details(self.test_patient_id)
5858

5959
# Assert
60-
self.assertEqual(result, "9912003888")
60+
self.assertEqual(result["identifier"][0]["value"], "9912003888")
6161

6262
# Verify Cache was initialized correctly
6363
self.mock_cache_class.assert_called_once()
@@ -76,114 +76,19 @@ def test_pds_get_patient_details_no_patient_found(self):
7676
# Assert
7777
self.assertIsNone(result)
7878

79-
# Verify both logger calls
80-
self.mock_logger.info.assert_any_call(f"No patient details found for ID: {self.test_patient_id}")
81-
8279
self.mock_pds_service_instance.get_patient_details.assert_called_once_with(self.test_patient_id)
8380

8481
def test_pds_get_patient_details_empty_response(self):
8582
"""Test when PDS returns empty dict (falsy)"""
8683
# Arrange
87-
self.mock_pds_service_instance.get_patient_details.return_value = {}
84+
self.mock_pds_service_instance.get_patient_details.return_value = None
8885

8986
# Act
9087
result = pds_get_patient_details(self.test_patient_id)
9188

9289
# Assert
9390
self.assertIsNone(result)
9491

95-
# Verify both logger calls
96-
self.mock_logger.info.assert_any_call(f"No patient details found for ID: {self.test_patient_id}")
97-
98-
def test_pds_get_patient_details_missing_identifier_field(self):
99-
"""Test when PDS response doesn't contain 'identifier' field"""
100-
# Arrange
101-
test_nhs_number = "my-nhs-number"
102-
patient_data_without_identifier = {
103-
"name": "John Doe",
104-
"birthDate": "1990-01-01",
105-
"gender": "male"
106-
# Missing 'identifier' field
107-
}
108-
self.mock_pds_service_instance.get_patient_details.return_value = patient_data_without_identifier
109-
110-
# Act
111-
with self.assertRaises(IdSyncException) as context:
112-
pds_get_patient_details(test_nhs_number)
113-
114-
exception = context.exception
115-
116-
# Assert
117-
self.assertEqual(exception.message, f"Error getting PDS patient details for {test_nhs_number}")
118-
self.assertEqual(exception.nhs_numbers, None)
119-
120-
# Verify exception was logged
121-
self.mock_logger.exception.assert_called_once_with(
122-
f"Error getting PDS patient details for {test_nhs_number}")
123-
124-
def test_pds_get_patient_details_empty_identifier_array(self):
125-
"""Test when identifier array is empty"""
126-
# Arrange
127-
patient_data_empty_identifier = {
128-
"identifier": [], # Empty array
129-
"name": "John Doe"
130-
}
131-
self.mock_pds_service_instance.get_patient_details.return_value = patient_data_empty_identifier
132-
133-
# Act
134-
with self.assertRaises(IdSyncException) as context:
135-
pds_get_patient_details(self.test_patient_id)
136-
137-
# Assert
138-
exception = context.exception
139-
self.assertEqual(exception.message, f"Error getting PDS patient details for {self.test_patient_id}")
140-
self.assertEqual(exception.nhs_numbers, None)
141-
142-
# Verify exception was logged due to IndexError
143-
self.mock_logger.exception.assert_called_once_with(
144-
f"Error getting PDS patient details for {self.test_patient_id}")
145-
146-
def test_pds_get_patient_details_identifier_missing_value(self):
147-
"""Test when identifier object doesn't have 'value' field"""
148-
# Arrange
149-
patient_data_missing_value = {
150-
"identifier": [
151-
{"system": "https://fhir.nhs.uk/Id/nhs-number"} # Missing 'value'
152-
]
153-
}
154-
self.mock_pds_service_instance.get_patient_details.return_value = patient_data_missing_value
155-
156-
# Act
157-
with self.assertRaises(IdSyncException) as context:
158-
pds_get_patient_details(self.test_patient_id)
159-
160-
exception = context.exception
161-
162-
# Assert
163-
self.assertEqual(exception.message, f"Error getting PDS patient details for {self.test_patient_id}")
164-
self.assertEqual(exception.nhs_numbers, None)
165-
166-
# Verify exception was logged due to KeyError
167-
self.mock_logger.exception.assert_called_once_with(
168-
f"Error getting PDS patient details for {self.test_patient_id}")
169-
170-
def test_pds_get_patient_details_multiple_identifiers(self):
171-
"""Test when patient has multiple identifiers - should return first one"""
172-
# Arrange
173-
patient_data_multiple_identifiers = {
174-
"identifier": [
175-
{"value": "9912003888"}, # First identifier
176-
{"value": "9912003999"} # Second identifier
177-
]
178-
}
179-
self.mock_pds_service_instance.get_patient_details.return_value = patient_data_multiple_identifiers
180-
181-
# Act
182-
result = pds_get_patient_details(self.test_patient_id)
183-
184-
# Assert
185-
self.assertEqual(result, "9912003888") # Should return first identifier
186-
18792
def test_pds_get_patient_details_pds_service_exception(self):
18893
"""Test when PdsService.get_patient_details raises an exception"""
18994
# Arrange
@@ -286,7 +191,7 @@ def test_pds_get_patient_details_different_patient_ids(self):
286191
result = pds_get_patient_details(patient_id)
287192

288193
# Assert
289-
self.assertEqual(result, patient_id)
194+
self.assertEqual(result, test_cases[patient_id])
290195
self.mock_pds_service_instance.get_patient_details.assert_called_once_with(patient_id)
291196

292197
def test_pds_get_patient_details_service_dependencies(self):
@@ -299,7 +204,7 @@ def test_pds_get_patient_details_service_dependencies(self):
299204
result = pds_get_patient_details(self.test_patient_id)
300205

301206
# Assert service initialization order and parameters
302-
self.assertEqual(result, "9912003888")
207+
self.assertEqual(result["identifier"][0]["value"], "9912003888")
303208

304209
# Verify initialization order by checking call counts
305210
self.assertEqual(self.mock_cache_class.call_count, 1)
@@ -315,15 +220,60 @@ def test_pds_get_patient_details(self):
315220
# Arrange
316221
test_nhs_number = "9912003888"
317222
pds_id = "abcefghijkl"
318-
self.mock_pds_service_instance.get_patient_details.return_value = {"identifier": [{"value": pds_id}]}
319-
223+
mock_pds_response = {"identifier": [{"value": pds_id}]}
224+
self.mock_pds_service_instance.get_patient_details.return_value = mock_pds_response
320225
# Act
321226
result = pds_get_patient_details(test_nhs_number)
322227

323228
# Assert - function should extract the value from first identifier
324-
self.assertEqual(result, pds_id)
229+
self.assertEqual(result, mock_pds_response)
325230
self.mock_pds_service_instance.get_patient_details.assert_called_once_with(test_nhs_number)
326231

327232

328-
if __name__ == '__main__':
329-
unittest.main()
233+
# test pds_get_patient_id function
234+
class TestGetPdsPatientId(unittest.TestCase):
235+
def setUp(self):
236+
"""Set up test fixtures and mocks"""
237+
self.test_nhs_number = "9912003888"
238+
239+
# Patch all external dependencies
240+
self.logger_patcher = patch('pds_details.logger')
241+
self.mock_logger = self.logger_patcher.start()
242+
243+
self.pds_get_patient_details_patcher = patch('pds_details.pds_get_patient_details')
244+
self.mock_pds_get_patient_details = self.pds_get_patient_details_patcher.start()
245+
246+
def tearDown(self):
247+
"""Clean up patches"""
248+
patch.stopall()
249+
250+
def test_pds_get_patient_id_success(self):
251+
"""Test successful retrieval of PDS patient ID"""
252+
# Arrange
253+
expected_id = "1234567890"
254+
self.mock_pds_get_patient_details.return_value = {"identifier": [{"value": expected_id}]}
255+
256+
# Act
257+
result = pds_get_patient_id(self.test_nhs_number)
258+
259+
# Assert
260+
self.assertEqual(result, expected_id)
261+
262+
def test_pds_get_patient_id_empty_identifier_array(self):
263+
"""Test when identifier array is empty"""
264+
# Arrange
265+
patient_data_empty_identifier = {
266+
"identifier": [], # Empty array
267+
"name": "John Doe"
268+
}
269+
self.mock_pds_get_patient_details.return_value = patient_data_empty_identifier
270+
271+
# Act
272+
with self.assertRaises(IdSyncException) as context:
273+
pds_get_patient_id(self.test_nhs_number)
274+
275+
# Assert
276+
exception = context.exception
277+
self.assertEqual(exception.message, f"Error getting PDS patient ID for {self.test_nhs_number}")
278+
self.assertEqual(exception.nhs_numbers, None)
279+

lambdas/id_sync/tests/test_record_processor.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ def setUp(self):
1212
self.mock_logger = self.logger_patcher.start()
1313

1414
# Mock external dependencies
15-
self.pds_get_patient_details_patcher = patch('record_processor.pds_get_patient_details')
16-
self.mock_pds_get_patient_details = self.pds_get_patient_details_patcher.start()
15+
self.pds_get_patient_id_patcher = patch('record_processor.pds_get_patient_id')
16+
self.mock_pds_get_patient_id = self.pds_get_patient_id_patcher.start()
1717

1818
# mock record_processor.ieds_check_exist
1919
self.ieds_check_exist_patcher = patch('record_processor.ieds_check_exist')
@@ -33,7 +33,7 @@ def test_process_record_success_no_update_required(self):
3333
with patch('record_processor.ieds_check_exist', return_value=True):
3434

3535
test_record = {"body": {"subject": test_id}}
36-
self.mock_pds_get_patient_details.return_value = {"identifier": [{"value": test_id}]}
36+
self.mock_pds_get_patient_id.return_value = test_id
3737

3838
# Act
3939
result = process_record(test_record)
@@ -43,7 +43,7 @@ def test_process_record_success_no_update_required(self):
4343
self.assertEqual(result, expected_result)
4444

4545
# Verify calls
46-
self.mock_pds_get_patient_details.assert_called_once_with(test_id)
46+
self.mock_pds_get_patient_id.assert_called_once_with(test_id)
4747

4848
def test_process_record_success_update_required(self):
4949
"""Test successful processing when patient ID differs"""
@@ -52,7 +52,7 @@ def test_process_record_success_update_required(self):
5252
nhs_number = "nhs-number-1"
5353

5454
test_sqs_record = {"body": {"subject": nhs_number}}
55-
self.mock_pds_get_patient_details.return_value = {"identifier": [{"value": pds_id}]}
55+
self.mock_pds_get_patient_id.return_value = pds_id
5656
success_response = {"status": "success"}
5757
self.mock_ieds_update_patient_id.return_value = success_response
5858
# Act
@@ -63,7 +63,7 @@ def test_process_record_success_update_required(self):
6363
self.assertEqual(result, expected_result)
6464

6565
# Verify calls
66-
self.mock_pds_get_patient_details.assert_called_once_with(nhs_number)
66+
self.mock_pds_get_patient_id.assert_called_once_with(nhs_number)
6767

6868
def test_process_record_no_records_exist(self):
6969
"""Test when no records exist for the patient ID"""
@@ -81,18 +81,18 @@ def test_process_record_no_records_exist(self):
8181
self.assertEqual(result["message"], f"No records returned for ID: {test_id}")
8282

8383
# Verify PDS was not called
84-
self.mock_pds_get_patient_details.assert_called_once()
84+
self.mock_pds_get_patient_id.assert_called_once()
8585

8686
def test_process_record_pds_returns_none_id(self):
8787
"""Test when PDS returns none """
8888
# Arrange
8989
test_id = "12345a"
90-
self.mock_pds_get_patient_details.return_value = {}
90+
self.mock_pds_get_patient_id.return_value = None
9191
test_record = {"body": {"subject": test_id}}
9292
# Act & Assert
9393
result = process_record(test_record)
94-
expected_result = {"status": "error", "message": f"No records returned for ID: {test_id}"}
95-
self.assertEqual(result, expected_result)
94+
self.assertEqual(result["status"], "success")
95+
self.assertEqual(result["message"], f"No patient ID found for NHS number: {test_id}")
9696
self.mock_ieds_check_exist.assert_not_called()
9797
self.mock_ieds_update_patient_id.assert_not_called()
9898

@@ -101,7 +101,7 @@ def test_process_record_ieds_returns_false(self):
101101
# Arrange
102102
test_id = "12345a"
103103
pds_id = "pds-id-1"
104-
self.mock_pds_get_patient_details.return_value = {"id": pds_id}
104+
self.mock_pds_get_patient_id.return_value = pds_id
105105
self.mock_ieds_check_exist.return_value = False
106106
# Act & Assert
107107
result = process_record({"body": {"subject": test_id}})
@@ -114,7 +114,7 @@ def test_body_is_string(self):
114114
test_record = {"body": "{'subject': 'nhs-number-1'}"}
115115
new_test_id = "nhs-number-2"
116116

117-
self.mock_pds_get_patient_details.return_value = {"identifier": [{"value": new_test_id}]}
117+
self.mock_pds_get_patient_id.return_value = new_test_id
118118
self.mock_ieds_update_patient_id.return_value = {"status": "success"}
119119
# Act
120120
result = process_record(test_record)

0 commit comments

Comments
 (0)