Supporting SNapp: Lists of medications

In this post we’re going to look at representing the Medication List using a List resource as part of supporting the SNapp event at the SNOMED conference in New Zealand next month. As we discussed in the last post – this is a preferable, albeit more complex way than just using queries against MedicationStatement resources.

To understand how this works, take a look at this image:

4

It’s a screen dump from clinFHIR that shows how the List resource in the middle of the graph refers to the individual MedicationStatement resources that are part of the List (as well as the patient). Yes, I know, I really need to work on those colours! Oh, and BTW take a look at this post to see how you can create your own sample patients on a FHIR server

What you can see is that you still need the individual MedicationStatement resources that represent each medication, but you now have an additional resource that adds the extra information about the list – e.g.

  • When the list was created, and by whom.
  • Type of list eg a comprehensive review of all mediations, or just updating it in the context of a specific event (an antibiotic for a fixed period)
  • Medications that have been stopped in this review (you can indicate why they were stopped using an extension)
  • Notes about the list

And we can be explicit about stating that the patient is not taking any medications (as far as we know), plus versioning of the list as it changes.

So lets see how we can do that.

To retrieve an existing list, you have a few options. (We assume that you have the patient Id – 149632 in this case).

You could get all the lists for a patient, then find the medications list (it is the one where the List.code value is ‘medications’ (remembering it’s a CodeableConcept):

http://fhirtest.uhn.ca/baseDstu3/List?subject=149632

You could get a bit smarter, and include the type of list in the query:

http://fhirtest.uhn.ca/baseDstu3/List?subject=149632&code=http://hl7.org/fhir/list-example-use-codes|medications

(Note that we’re being a good FHIR citizen and including the system in the query. You don’t have to, but it’s recommended. And note also that even though there’s only a single list you always get back a bundle – no surprises!) – Actually, if there multiple matching lists, they’d all be included…

Of course, these queries only return the List resource – it’s up to you to retrieve the actual contents of the list – boring! _include to the rescue:

http://fhirtest.uhn.ca/baseDstu3/List?subject=149632&code=http://hl7.org/fhir/list-example-use-codes|medications&_include=List:item

So now – in a single call – we get the List and all the resources it refers to. Note that the syntax for _include is based on the search parameters – not necessarily the path in the resource, and it works because this is a query – we’re not GETting a single resource.

There are even more options:

But as these aren’t imlemented by HAPI, we won’t discuss them further.

What if the patient doesn’t have a medication List? Well, to create a new List manually, there are 3 steps.

  1. Locate the patient Id as we did in the last post.
  2. Create the individual MedicationStatement resources – 1 for each medication, including the reference to the patient and save each one on the server (POST to the /MedicationStatement root). The server will return the id of the newly created resource in either the Location or Content-Location response header. (the spec is a bit ambiguous at the moment I’m afraid).
  3. Create a List resource that references those resources in its entry element, set the value of the ‘code’ property to ‘medications’ (It’s a CodeableConcept actually), the patient property to the patient and any other properties you need to then POST to the server.

(In step 3, you set the ‘type’ of the list (List.code) to indicate that it’s a medication list – more details in the spec.)

As you can see, this is all a bit tedious. It does work, but involves a fair amount of client side work – something we try to avoid with FHIR. However there is an alternative – and that is to use the transaction. The flow is similar, except that rather than sending each resource to the server, you instead place them in a bundle and send the bundle to the root of the server. The server will then save each resource, updating the references appropriately and return the completed bundle to you.

So here’s the new set of steps.

  1. Locate the patient Id as we did in the last post.
  2. Create a bundle, setting the type to transaction
  3. Create a List resource and add it to the bundle
  4. Create the individual MedicationStatement resources – 1 for each medication, including the reference to the patient and make up an id. It doesn’t matter what the id is, so long as it is unique in the context of the bundle as the server will replace it.
  5. Add the resource to the bundle
  6. Update the List resource (still in the bundle) by adding an entry.item.reference to the List that has a reference to the id you just created.
  7. POST the bundle to the server root.

The server will then perform the processing and return another bundle containing the newly created resources. Much easier! This is exactly the process that clinFHIR uses when creating the sample data – if you put a ‘sniffer’ across the HTTP connection you will see the bundles going back and forth. You can also check out the code if you want – search for the function buildMedicationList() in the github source code.

As you can imagine, this can get quite complicated, and not all servers will support it (those that do – including HAPI – will declare so in their conformance resource).

One thing to be a bit careful of in the scenario above, is that a new List (and MedicationStatement resources) will always be created. What do you do if there is already a List (of the correct type) – if you just do the above, then the patient will have 2 lists – hardly what we are after. (Actually, this is a question of data integrity – and really important. We don’t have time to discuss right now, but will return to it at some point)

There are a couple of solutions

  • You could check first (using the examples above) if there is a already a list, and if so update it (more on that in a moment)
  • You could use the conditional update mechanism on the List – specifying the patient and list type as the identification criteria.

Most of the time you’re going to want to retrieve the list first (so you know what changes to make) so let’s think about updating the list.

 

Updating is not really all that hard (conceptually at least).

You retrieve the current List resource and all the MedicationStatement resources (_include is your friend). We’ll start by doing this manually

  1. Make whatever changes to MedicationStatements you need – updating the status to completed (or whatever) or creating a new one. Update the server as you go.
  2. Update the List resource to reflect the changes. You may add a new entry to reflect an additional medication, or remove one that is no longer current. In the latter case, you could leave it in the List, but set the deleted property to true so you can be explicit about the fact that you’ve removed it. You can also set the ‘flag’ property to give more details, or use an extension.
  3. Update the List resource on the server

As with creating a new list, you can also use a transaction. You’d follow the steps above, but place the updated resources in the bundle and then send the bundle once at the end. You wouldn’t bother with resources that are unchanged (although you could if you wanted to). For changed resources, remember to use the conditional update facility of the bundle (request.ifMatch) so the original resource is updated rather than creating a new one. We discussed this in the previous post, and the principles are the same.

 

Retrieving the history of changes to the list is also straightforward.

First, you’ll need the id of the List – perhaps by:

http://fhirtest.uhn.ca/baseDstu3/List?subject=149632&code=http://hl7.org/fhir/list-example-use-codes|medications&_include=List:item

Next, you can get the history of changes to the List:

http://fhirtest.uhn.ca/baseDstu3/List/149655/_history

This will give you a bundle containing all the previous versions of the List with that id.

Then you can GET the version you want:

http://fhirtest.uhn.ca/baseDstu3/List/149655/_history/2

Unfortunately, _include won’t work when you’re retrieving a specific version of a resource (it’s not a query) so you’ll need to retrieve each MedicationStatement separately. Oh well, you can’t have everything…

 

The last thing we’ll discuss is how to absolutely assert that the patient is not on any medications. This is done by simply creating a List resource and setting the emptyReason property.

 

So that should be enough to get going. The purpose of these 2 posts is to support SNapp – so for those participating (or anyone else for that matter) feel free to reach out with any questions. I’m not planning any further posts, unless reasons arise why I should do so…

 

But – as mentioned in the previous post – we have been completely ignoring the security and privacy considerations in these discussions, as well as integrity issues – e.g. multiple medication lists. They are worth discussing – and we’ll do so in the not too distant future.

Oh – and just to be clear – the url’s in this post are correct at the time of writing (ie the patient and list exist on the HAPI server. This will not always be the case, and sooner or later the resources will be removed and the URL’s will break. But hopefully you can figure out how to correct them (Hint: find the patient id, luke…). Sorry.

 

 

About David Hay
I'm an independent contractor working with a number of Organizations in the health IT space. I'm an HL7 Fellow, Chair Emeritus of HL7 New Zealand and a co-chair of the FHIR Management Group. I have a keen interest in health IT, especially health interoperability with HL7 and the FHIR standard. I'm the author of a FHIR training and design tool - clinFHIR - which is sponsored by InterSystems Ltd.

6 Responses to Supporting SNapp: Lists of medications

  1. Peter Jordan says:

    Great work, David! If anything you’re almost making it too easy for the participants – think that I might take up the other challenge instead. 🙂

    • David Hay says:

      Oh don’t do that peter – we need your terminology server!

      • Peter Jordan says:

        Don’t worry David, Terminz will be available for both challenges. However, if time and the rules permit me to actually enter one of them, the mapping exercise would be my choice.

  2. Nice explanation and very doable as Peter says.
    Do we have patient Ngaio’s medication list at an endpoint anywhere – or do I need to do something to make that happen?

Leave a Reply

Discover more from Hay on FHIR

Subscribe now to keep reading and get access to the full archive.

Continue reading