Specimen data from external FHIR orders is never available at accessioning (Add Sample sample-type always blank)

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 (develop branch), docker-compose deployment
  • Remote FHIR source: public hapi.fhir.org test server (reproducible against any HAPI FHIR server)
  • Confirmed via direct source inspection, not just observed behavior

Root cause (traced in source)

  1. FhirApiWorkFlowServiceImpl’s Task-import path (saveRemoteTaskAsLocalTask / beginTaskImportOrderPath) does correctly resolve Task.basedOnServiceRequestServiceRequest.specimenSpecimen, and mirrors all of them into the co-resident FHIR store. This part works.

  2. However, electronic_order.data (the table backing the Incoming Orders queue) only ever caches the raw Task resource JSON — it never stores the associated ServiceRequest or Specimen. Confirmed by inspecting the column directly:

    {"resourceType":"Task","id":"...","basedOn":[...],"for":{...},"owner":{...}} 
    
    

    No ServiceRequest or Specimen data present, regardless of what was sent.

  3. The “Add Sample” screen (frontend/src/components/addOrder/AddSample.jsx, line 21) initializes sampleTypeId: "" 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 in FhirApiWorkFlowServiceImpl, TaskInterpreterImpl, or TaskWorker. A checklist we found suggesting Task.input explicitly flags the specimen doesn’t match this codebase.
  • sample_type_terminology_mapping — populating this (via the real Admin → Sample Type Management → Terminology feature) 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?

1 Like

thanks @Bhupesh_Gupta for the question, just to confirm what version of OE are you running ?

1 Like

I am using OpenELIS version 3.2.1.11, currently I am evaluating it for integrating it with our own EMR.

1 Like

Could u find this resource use full.

Yes this is useful and this is working as expected however the demo is using OpenELIS version 2.8 whereas mine is version 3.2.1.11. Seems like it is either broken in 3.2.1.11 or may be my FHIR bundle is not properly configured. Can you please advise on how I can fix it?