Skip to content

Commit 1b48d22

Browse files
authored
Merge pull request #50 from NHSDigital/feat/support-accession-number-c-find-queries
Feat/support accession number c find queries
2 parents 42e712e + deb97da commit 1b48d22

5 files changed

Lines changed: 65 additions & 40 deletions

File tree

src/services/mwl/c_find.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,15 @@ def call(self, event: evt.Event) -> Iterator[Tuple[int, Dataset | None]]:
3939
logger.info(f"C-FIND request from {requestor_aet}")
4040

4141
query_patient_id = identifier.get("PatientID")
42-
anonymised_patient_id = f"*******{query_patient_id[7:]}" if query_patient_id else "None"
4342

4443
procedure_sequence = identifier.get("ScheduledProcedureStepSequence", [{}])
4544
query_modality = procedure_sequence[0].get("Modality")
4645
query_date = procedure_sequence[0].get("ScheduledProcedureStepStartDate")
47-
48-
logger.debug(
49-
"Query parameters: modality=%s, date=%s, patient_id=%s", query_modality, query_date, anonymised_patient_id
50-
)
46+
query_accession_number = identifier.get("AccessionNumber")
5147

5248
try:
5349
items = self.storage.find_worklist_items(
50+
accession_number=query_accession_number if query_accession_number else None,
5451
modality=query_modality if query_modality else None,
5552
scheduled_date=query_date if query_date else None,
5653
patient_id=query_patient_id if query_patient_id else None,

src/services/storage.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ def store_worklist_item(
364364

365365
def find_worklist_items(
366366
self,
367+
accession_number: Optional[str] = None,
367368
modality: Optional[str] = None,
368369
scheduled_date: Optional[str] = None,
369370
patient_id: Optional[str] = None,
@@ -372,6 +373,7 @@ def find_worklist_items(
372373
Query worklist items with optional filters.
373374
374375
Args:
376+
accession_number: Filter by accession number
375377
modality: Filter by modality (e.g., "MG")
376378
scheduled_date: Filter by scheduled date (YYYYMMDD)
377379
patient_id: Filter by patient ID
@@ -388,6 +390,10 @@ def find_worklist_items(
388390
where_clauses = []
389391
params = []
390392

393+
if accession_number:
394+
where_clauses.append("accession_number = ?")
395+
params.append(accession_number)
396+
391397
if modality:
392398
where_clauses.append("modality = ?")
393399
params.append(modality)

tests/integration/test_c_find_returns_worklist_items.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,23 @@ def test_cfind_filters_by_scheduled_date(self, event, storage):
116116
assert status == SUCCESS
117117
assert ds is None
118118

119+
def test_cfind_filters_by_accession_number(self, event, storage):
120+
event.identifier.AccessionNumber = "ACC234567"
121+
122+
results = list(CFind(storage).call(event))
123+
124+
assert len(results) == 2
125+
126+
status, ds = results[0]
127+
assert status == PENDING
128+
assert ds.PatientID == "999234567"
129+
assert ds.PatientName == "JONES^MARY"
130+
assert ds.AccessionNumber == "ACC234567"
131+
132+
status, ds = results[1]
133+
assert status == SUCCESS
134+
assert ds is None
135+
119136
def test_cfind_filters_by_modality(self, event, storage):
120137
storage.store_worklist_item(
121138
WorklistItem(

tests/services/mwl/test_c_find.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,16 @@ def test_call_with_multiple_results(self, handler, mock_storage, mock_event):
107107
status, ds = results[3]
108108
assert status == SUCCESS
109109

110+
def test_call_with_accession_number_filter(self, handler, mock_storage, mock_event):
111+
mock_event.identifier.AccessionNumber = "ACC12345"
112+
mock_storage.find_worklist_items.return_value = []
113+
114+
list(handler.call(mock_event))
115+
116+
mock_storage.find_worklist_items.assert_called_once_with(
117+
accession_number="ACC12345", modality=None, scheduled_date=None, patient_id=None
118+
)
119+
110120
def test_call_with_modality_filter(self, handler, mock_storage, mock_event):
111121
# Add modality to query
112122
sps_item = Dataset()
@@ -116,7 +126,9 @@ def test_call_with_modality_filter(self, handler, mock_storage, mock_event):
116126

117127
list(handler.call(mock_event))
118128

119-
mock_storage.find_worklist_items.assert_called_once_with(modality="MG", scheduled_date=None, patient_id=None)
129+
mock_storage.find_worklist_items.assert_called_once_with(
130+
accession_number=None, modality="MG", scheduled_date=None, patient_id=None
131+
)
120132

121133
def test_call_with_date_filter(self, handler, mock_storage, mock_event):
122134
sps_item = Dataset()
@@ -127,7 +139,7 @@ def test_call_with_date_filter(self, handler, mock_storage, mock_event):
127139
list(handler.call(mock_event))
128140

129141
mock_storage.find_worklist_items.assert_called_once_with(
130-
modality=None, scheduled_date="20260107", patient_id=None
142+
accession_number=None, modality=None, scheduled_date="20260107", patient_id=None
131143
)
132144

133145
def test_call_with_patient_id_filter(self, handler, mock_storage, mock_event):
@@ -137,7 +149,7 @@ def test_call_with_patient_id_filter(self, handler, mock_storage, mock_event):
137149
list(handler.call(mock_event))
138150

139151
mock_storage.find_worklist_items.assert_called_once_with(
140-
modality=None, scheduled_date=None, patient_id="9876543210"
152+
accession_number=None, modality=None, scheduled_date=None, patient_id="9876543210"
141153
)
142154

143155
def test_call_handles_storage_exception(self, handler, mock_storage, mock_event):

tests/services/test_storage.py

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,16 @@ def test_find_worklist_items(self, mock_db, tmp_dir, result):
219219
assert len(results) == 1
220220
assert results[0] == WorklistItem(**result)
221221

222-
def test_find_worklist_items_with_filters(self, mock_db, tmp_dir):
222+
@pytest.mark.parametrize(
223+
"query_param_name, query_param_value",
224+
[
225+
("accession_number", "ACC123456"),
226+
("patient_id", "999123456"),
227+
("modality", "CT"),
228+
("scheduled_date", "20240101"),
229+
],
230+
)
231+
def test_find_worklist_items_with_filters(self, mock_db, tmp_dir, query_param_name, query_param_value):
223232
mock_cursor = MagicMock()
224233
mock_cursor.fetchall.return_value = []
225234
mock_connection = MagicMock()
@@ -229,58 +238,42 @@ def test_find_worklist_items_with_filters(self, mock_db, tmp_dir):
229238
subject = MWLStorage(tmp_dir)
230239
mock_connection.reset_mock()
231240

232-
subject.find_worklist_items(patient_id="999123456")
241+
find_args = {query_param_name: query_param_value}
242+
subject.find_worklist_items(**find_args)
233243

234244
mock_connection.execute.assert_called_once_with(
235245
(
236246
"SELECT accession_number, modality, patient_birth_date, patient_id, "
237247
"patient_name, patient_sex, procedure_code, scheduled_date, scheduled_time, "
238248
"source_message_id, study_description, study_instance_uid, status, mpps_instance_uid "
239-
"FROM worklist_items WHERE patient_id = ? ORDER BY scheduled_date, scheduled_time"
249+
f"FROM worklist_items WHERE {query_param_name} = ? ORDER BY scheduled_date, scheduled_time"
240250
),
241-
["999123456"],
251+
[query_param_value],
242252
)
243253

244-
mock_connection.reset_mock()
245-
subject.find_worklist_items(modality="CT")
246-
247-
mock_connection.execute.assert_called_once_with(
248-
(
249-
"SELECT accession_number, modality, patient_birth_date, patient_id, "
250-
"patient_name, patient_sex, procedure_code, scheduled_date, scheduled_time, "
251-
"source_message_id, study_description, study_instance_uid, status, mpps_instance_uid "
252-
"FROM worklist_items WHERE modality = ? ORDER BY scheduled_date, scheduled_time"
253-
),
254-
["CT"],
255-
)
254+
def test_find_worklist_items_with_multiple_filters(self, mock_db, tmp_dir):
255+
mock_cursor = MagicMock()
256+
mock_cursor.fetchall.return_value = []
257+
mock_connection = MagicMock()
258+
mock_connection.execute.return_value = mock_cursor
259+
mock_db.connect.return_value = mock_connection
256260

261+
subject = MWLStorage(tmp_dir)
257262
mock_connection.reset_mock()
258-
subject.find_worklist_items(scheduled_date="20240101")
259-
260-
mock_connection.execute.assert_called_once_with(
261-
(
262-
"SELECT accession_number, modality, patient_birth_date, patient_id, "
263-
"patient_name, patient_sex, procedure_code, scheduled_date, scheduled_time, "
264-
"source_message_id, study_description, study_instance_uid, status, mpps_instance_uid "
265-
"FROM worklist_items WHERE scheduled_date = ? "
266-
"ORDER BY scheduled_date, scheduled_time"
267-
),
268-
["20240101"],
263+
subject.find_worklist_items(
264+
accession_number="ACC123456", modality="MG", scheduled_date="20240101", patient_id="999123456"
269265
)
270266

271-
mock_connection.reset_mock()
272-
subject.find_worklist_items(modality="MG", scheduled_date="20240101", patient_id="999123456")
273-
274267
mock_connection.execute.assert_called_once_with(
275268
(
276269
"SELECT accession_number, modality, patient_birth_date, patient_id, "
277270
"patient_name, patient_sex, procedure_code, scheduled_date, scheduled_time, "
278271
"source_message_id, study_description, study_instance_uid, status, mpps_instance_uid "
279272
"FROM worklist_items "
280-
"WHERE modality = ? AND scheduled_date = ? AND patient_id = ? "
273+
"WHERE accession_number = ? AND modality = ? AND scheduled_date = ? AND patient_id = ? "
281274
"ORDER BY scheduled_date, scheduled_time"
282275
),
283-
["MG", "20240101", "999123456"],
276+
["ACC123456", "MG", "20240101", "999123456"],
284277
)
285278

286279
def test_get_worklist_item(self, mock_db, tmp_dir, result):

0 commit comments

Comments
 (0)