Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Order Select Service

Dennis Patterson edited this page Apr 9, 2020 · 2 revisions

Goal: To display a card containing a suggestion to switch the selected medication order to Aspirin 81 MG Oral Tablets through text and the suggestions field. If the medication selected is our recommended prescription, then affirm the clincian's choice via text.

See documentation on the EHR calling a CDS Service: https://cds-hooks.org/specification/current/#calling-a-cds-service

See documentation on the CDS Service response: https://cds-hooks.org/specification/current/#cds-service-response

As we defined in our discovery endpoint, we have a CDS Service set up to listen for the order-select hook to be invoked. Once this hook is invoked, the EHR may decide to call upon our order-select-example CDS Service to provide support. Similar to the patient-view-example service, this service should also be invoked via a POST HTTP request with a request body containing context for the service call. And as you may have noticed in the discovery endpoint, the order-select-example service does not request a prefetch from the EHR. Instead, this service will rely just on the context property in the request body that may contain a FHIR resource for the order selected.

An example request body might look similar to this format:

{
  "hookInstance" : "abc234",
  "hook" : "order-select",
  "fhirServer" : "https://sb-fhir-dstu2.smarthealthit.org/api/smartdstu2/open",
  "context": {
    "patientId": "SMART-1288992",
    "user" : "Practitioner/example",
    "selections": [
      "MedicationOrder/order-123"
    ],
    "draftOrders": {
      "resourceType": "Bundle",
      "entry": [
        {
          "resource": {
            "resourceType": "MedicationOrder",
            "dateWritten": "2018-05-11",
            "status": "draft",
            "patient": {
              "reference": "Patient/SMART-1288992"
            },
            "medicationCodeableConcept": {
              "text": "Acetaminophen 80 MG Chewable Tablet [Tylenol]",
              "coding": [
                {
                  "display": "Acetaminophen 80 MG Chewable Tablet [Tylenol]",
                  "system": "http://www.nlm.nih.gov/research/umls/rxnorm",
                  "code": "731370"
                }
              ]
            },
            { ... snipped for brevity ... }
          }
        }
      ]
    }
  }
}

In the example request body above, notice that the context of the medication selected by the clinician is in two places within the context property. First, the selections property contains the reference for the selected order and second, the draftOrders property takes the form of a FHIR bundle with an entry array of the single medication selected, but in a real-world scenario could potentially contain other orders previously selected.
Once we have this FHIR resource, we can parse it to check if the clinician is prescribing our suggested medication. But first, let's define our route to this CDS Service.

app.post('/cds-services/order-select-example', (request, response) => {
  ...
});

Again, we define in our application a POST route to the order-select-example CDS Service endpoint. And we will use the request object to parse the body of incoming POST requests. Now let's look at the logic to return our cards inside that function block.

const draftOrder = request.body.context.draftOrders.entry[0].resource;
const selections = request.body.context.selections;

if (['MedicationRequest', 'MedicationOrder'].includes(draftOrder.resourceType) && selections.includes(`${draftOrder.resourceType}/${draftOrder.id}`)
  && draftOrder.medicationCodeableConcept) {
  const responseCard = createMedicationResponseCard(draftOrder);
  response.send(JSON.stringify(responseCard, null, 2));
}
response.status(200);

Above, we should immediately check for the context property in the request body, similar to how we checked the prefetch property on our patient-view-example service. Once we store that information in some variables, we should check to see if a medication is even being selected in the first place.

Note that the EHR could invoke the CDS Service at any given time, and we want to make sure our response for returning a card is appropriate only when a medication is selected. If a medication is not selected, our service should simply return a HTTP 200 status code without any response body.

If a medication is selected, by checking for the presence of a medicationCodeableConcept property in the MedicationOrder resource, then we can start to create a card response in JSON format like we have been doing. Let's dig in and see how we create that card in the createMedicationResponseCard function.

function createMedicationResponseCard(context) {
  const providerOrderedMedication = context.medicationCodeableConcept.coding[0].code;

  if (providerOrderedMedication === '243670') {
    return {
      cards: [
        {
          summary: 'Currently prescribing a low-dose Aspirin',
          indicator: 'info'
        }
      ]
    };
  } else {
    let newMedicationOrder = context;
    newMedicationOrder.medicationCodeableConcept = {
      text: 'Aspirin 81 MG Oral Tablet',
      coding: [
        {
          display: 'Aspirin 81 MG Oral Tablet',
          system: 'http://www.nlm.nih.gov/research/umls/rxnorm',
          code: '243670'
        }
      ]
    };
    return {
      cards: [
        {
          summary: 'Reduce cardiovascular risks, prescribe daily 81 MG Aspirin',
          indicator: 'warning',
          suggestions: [
            {
              label: 'Switch to low-dose Aspirin',
              actions: [
                {
                  type: 'create',
                  resource: newMedicationOrder
                }
              ]
            }
          ],
          source: {
            label: 'Learn more about Suggestions',
            url: 'https://cds-hooks.org/specification/current/#cds-service-response'
          }
        }
      ]
    };
  }
}

In this function, we handle two cases.

  1. If the code for this medication matches the code for our recommended Aspirin medication (code: 243670), return a card affirming their choice via plain text
  2. If the code for this medication does not match the code for our recommended Aspirin, return a card containing text of the benefits of Aspirin and a suggestion to switch to the recommended Aspirin. Additionally, we will include a source property link to the spec to learn more about suggestions

Let's look more closely at case 2 since it is more involved. This logic occurs in the else block of the conditional logic. First, we create a copy of the first object in the context property of the request body (which was passed in as a parameter) named newMedicationOrder. With this copy, we can mutate the medicationCodeableConcept property to contain our recommended Aspirin medication. We have now created a copy of a MedicationOrder resource that we ideally want the clinician to prescribe for the patient.

We can take this resource copy and put it in the suggestions field accordingly to match the CDS Hooks spec (see documentation above for CDS Service Response). And similar to how we included a link in the links field of the card response, we can put the URL to the CDS Hooks spec in the source field of the card. Finally, we should indicate this suggestion is of higher priority than our previous cards since we are suggesting a medication change, so the indicator field should be set to warning, and now we can return this card.

Once this function returns the appropriate card back to the main POST body for this service, we can return the response in JSON format to the EHR.

Next step: Testing Your Services