Skip to content

Commit 0625047

Browse files
committed
Add the return key attributes as specified in the conformance doc
The documentation says non-requested keys will be ignored, so we are safe to always return the full set for each item.
1 parent 678ed78 commit 0625047

3 files changed

Lines changed: 100 additions & 26 deletions

File tree

src/services/mwl/c_find.py

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,26 +88,47 @@ def _build_worklist_response(self, item: WorklistItem) -> Dataset:
8888
ds.PatientID = item.patient_id
8989
ds.PatientName = item.patient_name
9090
ds.PatientBirthDate = item.patient_birth_date
91-
if item.patient_sex:
92-
ds.PatientSex = item.patient_sex
91+
ds.PatientSex = item.patient_sex
92+
ds.PatientAge = item.patient_age
93+
ds.PatientWeight = item.patient_weight
94+
ds.PatientAddress = item.patient_address
95+
ds.PatientComments = item.patient_comments
9396

9497
# Study information
9598
ds.AccessionNumber = item.accession_number
96-
if item.study_instance_uid:
97-
ds.StudyInstanceUID = item.study_instance_uid
99+
ds.StudyInstanceUID = item.study_instance_uid
98100

99-
if item.study_description:
100-
ds.StudyDescription = item.study_description
101-
sps_item.ScheduledProcedureStepDescription = ds.StudyDescription
101+
ds.StudyDescription = item.study_description
102+
sps_item.ScheduledProcedureStepDescription = ds.StudyDescription
102103

103-
if item.procedure_code:
104-
ds.RequestedProcedureID = item.procedure_code
105-
sps_item.ScheduledProcedureStepID = ds.RequestedProcedureID
104+
ds.RequestedProcedureID = item.procedure_code
105+
106+
ds.RequestedProcedureCodeSequence = [Dataset()]
107+
ds.RequestedProcedureCodeSequence[0].CodeValue = item.procedure_code
108+
ds.RequestedProcedureCodeSequence[0].CodingSchemeDesignator = item.procedure_coding_scheme_designator
109+
ds.RequestedProcedureCodeSequence[0].CodeMeaning = item.procedure_code_meaning
110+
111+
ds.ReasonForRequestedProcedureCodeSequence = [Dataset()]
112+
ds.ReasonForRequestedProcedureCodeSequence[0].CodeValue = item.reason_code_value
113+
ds.ReasonForRequestedProcedureCodeSequence[0].CodingSchemeDesignator = item.reason_coding_scheme_designator
114+
ds.ReasonForRequestedProcedureCodeSequence[0].CodeMeaning = item.reason_code_meaning
115+
116+
sps_item.ScheduledProcedureStepID = ds.RequestedProcedureID
106117

107118
# Scheduled Procedure Step Sequence
108119
sps_item.ScheduledProcedureStepStartDate = item.scheduled_date
109120
sps_item.ScheduledProcedureStepStartTime = item.scheduled_time
110121
sps_item.Modality = item.modality
122+
sps_item.ScheduledStationAETitle = item.scheduled_station_aet
123+
sps_item.ScheduledPerformingPhysicianName = item.scheduled_performing_physician_name
124+
sps_item.ScheduledStationName = item.scheduled_station_name
125+
sps_item.ScheduledProcedureStepLocation = item.scheduled_procedure_step_location
126+
sps_item.ScheduledProtocolCodeSequence = [Dataset()]
127+
sps_item.ScheduledProtocolCodeSequence[0].CodeValue = item.scheduled_protocol_code_value
128+
sps_item.ScheduledProtocolCodeSequence[
129+
0
130+
].CodingSchemeDesignator = item.scheduled_protocol_coding_scheme_designator
131+
sps_item.ScheduledProtocolCodeSequence[0].CodeMeaning = item.scheduled_protocol_code_meaning
111132

112133
ds.ScheduledProcedureStepSequence = [sps_item]
113134

src/services/storage.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ class WorklistItem:
291291
scheduled_date: str = field(doc="Date the procedure is scheduled for.")
292292
scheduled_time: str = field(doc="Time the procedure is scheduled for.")
293293
status: str = field(doc="Status of the worklist item", default=MWLStatus.SCHEDULED.value)
294+
294295
source_message_id: Optional[str] = field(
295296
default=None, doc="Message ID from system which created this worklist item", hash=True
296297
)
@@ -302,6 +303,36 @@ class WorklistItem:
302303
default=None, doc="Modality Performed Procedure Step (MPPS) instance UID if available."
303304
)
304305

306+
patient_age: Optional[str] = field(default=None, doc="Age of the patient at the time of scheduling.")
307+
patient_weight: Optional[str] = field(default=None, doc="Weight of the patient at the time of scheduling.")
308+
patient_address: Optional[str] = field(default=None, doc="Address of the patient.")
309+
patient_comments: Optional[str] = field(default=None, doc="Additional comments about the patient.")
310+
311+
procedure_coding_scheme_designator: Optional[str] = field(
312+
default=None, doc="Coding scheme designator for the procedure code."
313+
)
314+
procedure_code_meaning: Optional[str] = field(default=None, doc="Code meaning for the procedure code.")
315+
316+
reason_code_value: Optional[str] = field(default=None, doc="Code value for the reason for requested procedure.")
317+
reason_coding_scheme_designator: Optional[str] = field(
318+
default=None, doc="Coding scheme designator for the reason for requested procedure."
319+
)
320+
reason_code_meaning: Optional[str] = field(default=None, doc="Code meaning for the reason for requested procedure.")
321+
322+
scheduled_performing_physician_name: Optional[str] = field(
323+
default=None, doc="Name of the scheduled performing physician."
324+
)
325+
scheduled_procedure_step_location: Optional[str] = field(
326+
default=None, doc="Location of the scheduled procedure step."
327+
)
328+
scheduled_station_aet: Optional[str] = field(default=None, doc="AE Title of the scheduled station.")
329+
scheduled_station_name: Optional[str] = field(default=None, doc="Name of the scheduled station.")
330+
scheduled_protocol_code_value: Optional[str] = field(default=None, doc="Code value for the scheduled protocol.")
331+
scheduled_protocol_coding_scheme_designator: Optional[str] = field(
332+
default=None, doc="Coding scheme designator for the scheduled protocol."
333+
)
334+
scheduled_protocol_code_meaning: Optional[str] = field(default=None, doc="Code meaning for the scheduled protocol.")
335+
305336

306337
class WorklistItemNotFoundError(Exception):
307338
"""Raised when a worklist item is not found in storage."""

tests/services/mwl/test_c_find.py

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -215,23 +215,45 @@ def test_call_handles_storage_exception(self, handler, mock_storage, mock_event)
215215
assert status == FAILURE
216216
assert ds is None
217217

218-
def test_build_worklist_response_missing_optional_fields(self, handler):
219-
minimal_item = WorklistItem(
220-
accession_number="ACC001",
221-
patient_id="9876543210",
222-
patient_name="TEST^PATIENT",
223-
patient_birth_date="19800101",
224-
scheduled_date="20260107",
225-
scheduled_time="100000",
226-
modality="MG",
227-
)
218+
def test_call_return_key_attributes_present(self, handler, mock_storage, mock_event, sample_worklist_item):
219+
worklist_item = WorklistItem(**sample_worklist_item)
220+
mock_storage.find_worklist_items.return_value = [worklist_item]
228221

229-
ds = handler._build_worklist_response(minimal_item)
222+
results = list(handler.call(mock_event))
230223

231-
# Required fields present
224+
assert len(results) == 2
225+
status, ds = results[0]
226+
assert status == PENDING
232227
assert ds.PatientID == "9876543210"
233228
assert ds.AccessionNumber == "ACC001"
234-
# Optional fields absent
235-
assert not hasattr(ds, "PatientSex")
236-
assert not hasattr(ds, "StudyInstanceUID")
237-
assert not hasattr(ds, "StudyDescription")
229+
assert ds.PatientName == "TEST^PATIENT"
230+
assert ds.PatientBirthDate == "19800101"
231+
232+
assert ds.PatientAddress is None
233+
assert ds.PatientComments is None
234+
assert ds.PatientWeight is None
235+
assert ds.PatientAge is None
236+
assert ds.PatientSex == "F"
237+
238+
assert ds.StudyDescription == "Bilateral Screening Mammogram"
239+
assert ds.StudyInstanceUID == "1.2.3.4.5" # gitleaks:allow
240+
241+
scheduled_procedure_step = ds.ScheduledProcedureStepSequence[0]
242+
243+
assert scheduled_procedure_step.Modality == "MG"
244+
assert scheduled_procedure_step.ScheduledProcedureStepStartDate == "20260107"
245+
assert scheduled_procedure_step.ScheduledProcedureStepStartTime == "100000"
246+
assert scheduled_procedure_step.ScheduledProcedureStepID == "PROC001"
247+
assert scheduled_procedure_step.ScheduledStationAETitle is None
248+
assert scheduled_procedure_step.ScheduledStationName is None
249+
assert scheduled_procedure_step.ScheduledProtocolCodeSequence[0].CodeValue is None
250+
assert scheduled_procedure_step.ScheduledProtocolCodeSequence[0].CodingSchemeDesignator is None
251+
assert scheduled_procedure_step.ScheduledProtocolCodeSequence[0].CodeMeaning is None
252+
253+
assert ds.ReasonForRequestedProcedureCodeSequence[0].CodeValue is None
254+
assert ds.ReasonForRequestedProcedureCodeSequence[0].CodingSchemeDesignator is None
255+
assert ds.ReasonForRequestedProcedureCodeSequence[0].CodeMeaning is None
256+
257+
assert ds.RequestedProcedureCodeSequence[0].CodeValue == "PROC001"
258+
assert ds.RequestedProcedureCodeSequence[0].CodingSchemeDesignator is None
259+
assert ds.RequestedProcedureCodeSequence[0].CodeMeaning is None

0 commit comments

Comments
 (0)