Summary
When an external EMR places an order via the FHIR Task/ServiceRequest import path (org.openelisglobal.remote.source.uri), a well-formed Specimen resource — correctly referenced from ServiceRequest.specimen — never makes it to the accessioning UI. The “Add Sample” screen’s sample-type dropdown is always empty, regardless of what the EMR sends, requiring a lab tech to manually re-select it every time.
Environment
- OpenELIS-Global-2 (
developbranch), docker-compose deployment - Remote FHIR source: public
hapi.fhir.orgtest server (reproducible against any HAPI FHIR server) - Confirmed via direct source inspection, not just observed behavior
Root cause (traced in source)
-
FhirApiWorkFlowServiceImpl’s Task-import path (saveRemoteTaskAsLocalTask/beginTaskImportOrderPath) does correctly resolveTask.basedOn→ServiceRequest→ServiceRequest.specimen→Specimen, and mirrors all of them into the co-resident FHIR store. This part works. -
However,
electronic_order.data(the table backing the Incoming Orders queue) only ever caches the rawTaskresource JSON — it never stores the associatedServiceRequestorSpecimen. Confirmed by inspecting the column directly:{"resourceType":"Task","id":"...","basedOn":[...],"for":{...},"owner":{...}}No
ServiceRequestorSpecimendata present, regardless of what was sent. -
The “Add Sample” screen (
frontend/src/components/addOrder/AddSample.jsx, line 21) initializessampleTypeId: ""with no pre-fill logic from any order source at all — manual entry, electronic order, or FHIR import all land on the same blank dropdown.
So the gap isn’t in FHIR resource resolution (that part is correct) — it’s that the specimen data gets dropped between “resolved during Task import” and “displayed at accessioning.”
We also checked and ruled out:
Task.input— not read anywhere inFhirApiWorkFlowServiceImpl,TaskInterpreterImpl, orTaskWorker. A checklist we found suggestingTask.inputexplicitly flags the specimen doesn’t match this codebase.sample_type_terminology_mapping— populating this (via the realAdmin → Sample Type Management → Terminologyfeature) makes no difference to this specific screen; it appears to serve a different purpose (unconfirmed which).
Minimal reproduction
Attached Postman collection (2 requests): upserts a Practitioner, then submits a transaction Bundle with Patient + Specimen + ServiceRequest (referencing the Specimen) + Task (referencing the ServiceRequest) to a public HAPI FHIR test server. Set remote_fhir_base to whatever your instance’s org.openelisglobal.remote.source.uri points at, and practitioner_id to match org.openelisglobal.requester.identifier.
{
"info": {
"name": "OpenELIS Specimen-Linking Repro",
"description": "Minimal reproduction: an external FHIR order (Task + ServiceRequest + Specimen + Patient) with a well-formed ServiceRequest.specimen reference still results in an empty 'Select sample type' dropdown when accessioning the order in OpenELIS. See the forum post this collection accompanies for full analysis.\n\nUsage:\n1. Set `remote_fhir_base` to whatever your OpenELIS instance's `org.openelisglobal.remote.source.uri` points at (this example uses the public
test server).\n2. Set `practitioner_id` to match your instance's `org.openelisglobal.requester.identifier` (strip any 'Practitioner/' prefix).\n3. Run '01 - Upsert requesting Practitioner', then '02 - Place order with Specimen'.\n4. Wait for OpenELIS's poll cycle (org.openelisglobal.remote.poll.frequency, default ~2 min), then check the Incoming Orders queue in OpenELIS and try to accession the resulting order.",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"variable": [
{ "key": "remote_fhir_base", "value": "
", "type": "string" },
{ "key": "practitioner_id", "value": "f9badd80-ab76-11e2-9e96-0800200c9a66", "type": "string" },
{ "key": "patient_id", "value": "", "type": "string" },
{ "key": "specimen_id", "value": "", "type": "string" },
{ "key": "service_request_id", "value": "", "type": "string" },
{ "key": "task_id", "value": "", "type": "string" }
],
"item": [
{
"name": "01 - Upsert requesting Practitioner",
"request": {
"auth": { "type": "noauth" },
"method": "PUT",
"header": [{ "key": "Content-Type", "value": "application/fhir+json" }],
"url": {
"raw": "{{remote_fhir_base}}/Practitioner/{{practitioner_id}}",
"host": ["{{remote_fhir_base}}"],
"path": ["Practitioner", "{{practitioner_id}}"]
},
"body": {
"mode": "raw",
"raw": "{\n \"resourceType\": \"Practitioner\",\n \"id\": \"{{practitioner_id}}\",\n \"name\": [{ \"family\": \"Smith\", \"given\": [\"John\"] }]\n}",
"options": { "raw": { "language": "json" } }
}
},
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Practitioner upserted', function () {",
" pm.expect([200, 201]).to.include(pm.response.code);",
"});"
]
}
}
]
},
{
"name": "02 - Place order with Specimen (repro)",
"request": {
"auth": { "type": "noauth" },
"method": "POST",
"header": [{ "key": "Content-Type", "value": "application/fhir+json" }],
"url": { "raw": "{{remote_fhir_base}}", "host": ["{{remote_fhir_base}}"] },
"body": {
"mode": "raw",
"raw": "{\n \"resourceType\": \"Bundle\",\n \"type\": \"transaction\",\n \"entry\": [\n {\n \"fullUrl\": \"urn:uuid:{{patient_id}}\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"id\": \"{{patient_id}}\",\n \"name\": [{ \"family\": \"Repro\", \"given\": [\"Specimen\"] }],\n \"gender\": \"unknown\"\n },\n \"request\": { \"method\": \"PUT\", \"url\": \"Patient/{{patient_id}}\" }\n },\n {\n \"fullUrl\": \"urn:uuid:{{specimen_id}}\",\n \"resource\": {\n \"resourceType\": \"Specimen\",\n \"id\": \"{{specimen_id}}\",\n \"status\": \"available\",\n \"subject\": { \"reference\": \"Patient/{{patient_id}}\" },\n \"type\": {\n \"coding\": [\n { \"system\": \"http://snomed.info/sct\", \"code\": \"258529004\", \"display\": \"Throat swab\" }\n ]\n },\n \"collection\": { \"collectedDateTime\": \"2026-08-24T09:00:00Z\" }\n },\n \"request\": { \"method\": \"PUT\", \"url\": \"Specimen/{{specimen_id}}\" }\n },\n {\n \"fullUrl\": \"urn:uuid:{{service_request_id}}\",\n \"resource\": {\n \"resourceType\": \"ServiceRequest\",\n \"id\": \"{{service_request_id}}\",\n \"status\": \"active\",\n \"intent\": \"order\",\n \"subject\": { \"reference\": \"Patient/{{patient_id}}\" },\n \"specimen\": [{ \"reference\": \"Specimen/{{specimen_id}}\" }],\n \"code\": {\n \"coding\": [\n { \"system\": \"http://loinc.org\", \"code\": \"94500-6\", \"display\": \"SARS-CoV-2 RNA panel\" }\n ]\n }\n },\n \"request\": { \"method\": \"PUT\", \"url\": \"ServiceRequest/{{service_request_id}}\" }\n },\n {\n \"fullUrl\": \"urn:uuid:{{task_id}}\",\n \"resource\": {\n \"resourceType\": \"Task\",\n \"id\": \"{{task_id}}\",\n \"status\": \"requested\",\n \"intent\": \"order\",\n \"basedOn\": [{ \"reference\": \"ServiceRequest/{{service_request_id}}\" }],\n \"for\": { \"reference\": \"Patient/{{patient_id}}\" },\n \"owner\": { \"reference\": \"Practitioner/{{practitioner_id}}\" },\n \"requester\": { \"reference\": \"Practitioner/{{practitioner_id}}\" }\n },\n \"request\": { \"method\": \"PUT\", \"url\": \"Task/{{task_id}}\" }\n }\n ]\n}",
"options": { "raw": { "language": "json" } }
}
},
"event": [
{
"listen": "prerequest",
"script": {
"type": "text/javascript",
"exec": [
"function newGuid() { return pm.variables.replaceIn('{{$guid}}'); }",
"pm.collectionVariables.set('patient_id', newGuid());",
"pm.collectionVariables.set('specimen_id', newGuid());",
"pm.collectionVariables.set('service_request_id', newGuid());",
"pm.collectionVariables.set('task_id', newGuid());"
]
}
},
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Transaction Bundle accepted', function () {",
" pm.expect([200, 201]).to.include(pm.response.code);",
"});",
"console.log('task_id=' + pm.collectionVariables.get('task_id'));",
"console.log('Expected: OpenELIS polls this Task, creates the order, but the resulting');",
"console.log('electronic_order carries no specimen data, and Add Sample shows no sample type.');"
]
}
}
]
}
]
}
Expected: the order appears in Incoming Orders, and generating a Lab Number pre-fills the sample type from the Specimen we sent.
Actual: order appears correctly, but “Add Sample” → “Select sample type” is blank, same as if no Specimen had been sent at all.
Question for the community: is this expected/by-design (i.e., sample type is always meant to be a manual lab-side confirmation regardless of source), or is this a genuine gap where ServiceRequest/Specimen data should be threaded through to the order cache and pre-filled?