Assigned actions for feeding user-centric dashboards and widgets

Hi all, @akanter / @burke / @ibacher / @jdick / @jteich / @mseaton,

We have been working for a while on a user-centric dashboard that summarises targeted “things to do” for the current user. Those “todos” can be anything really, from appointments notifications to acknowledge, to encounter data to double check, to orders to make… etc etc. Based on who you are this new dashboard brings up actions assigned to you that you should pay attention to.

We (credits to @premnisha and her team) introduced new data model that I share here, I have highlighted the core of it:

In short an assigned action:

  • Is mostly defined by its attributes. It is the type of action that drives which attributes to look at and to consume.
  • Points to an assignee. While the assignee could in theory be anything, it’s in fact meant to be a User, a Privilege or a Role.
  • Is (eventually) completed by a User.

Now, looking at the FHIR spec, I see the Task resource that looks like being a match. @ibacher question for you, should we adapt our current data model to be a closer subset of the FHIR specification for ‘Task’? … or it doesn’t matter, it’s anyway all about the FHIR/FHIR2 modules to eventually map assigned actions to FHIR tasks anyway? I guess the former :wink: but obviously this will bring further overhead.

Anyway, I’d be grateful to get some feedback on this fundamental building block that we have used for populating data to new user-centric dashboards (that we will be happy to share in due time.)

Where can we move this when we have received sufficient feedback? EMR API, our “incubator”? Directly into Core?

Cc: @premnisha, @rrameshbtech, @sukreet, @wyclif

FHIR-wise, one difficulty here is that in FHIR2, we’ve implemented the Task resource via it’s own table, which could make mapping this a little complicated, but that’s not insurmountable. The bigger complication is that parts of this might be better represented as ServiceRequests (e.g., for pending orders) and Appointments, resources designed specifically to represent particular kinds of requests. Or, I suppose, they could, in FHIR, be represented by Tasks with the Task.basedOn pointing to the appropriate kind of resource, in which case, it would be helpful to have, e.g., an Order or Appointment object that could be referenced.

A couple of comments more generally on the design:

  • In my view, it would be better if we could track more states of an assigned action. For example, it would seem to be helpful to track whether an action had been seen and put off for later or was new. If those states could be aligned with the FHIR task statuses, as has happened with Order, that would be helpful.

  • It’s probably also helpful to be able to track the action priority. Again, this would be great if it could be aligned with FHIR’s request priority.

  • For value_reference, I think it might be better to approximate something closer to what we do with Obs (as messy as that is). But, I’m also not entirely clear on what’s being stored here. Ideally, this would also eliminate the need for datatype and datatype_config. But again, it’s not 100% clear what’s stored there.

Is this task list/dashboard meant to be for providers seeing patient-specific requests, or is this more administrative tasks? I would like to better understand the specific problem this is solving and use case(s). The “inbox” associated with current EMRs are a disaster, and I think we should first understand what we are trying to accomplish and then map it on to FHIR. In my mind, separating a UI view of something is different from organizing all the things which are being viewed (orders, reminders, tasks, etc.). Has there been some discussions about this in a design call I can listen to?

So I think that’s what we are doing through assigned action attributes.

Imagine that an assigned action is of type “appointment validation”, then it would have an appointment attribute. Imagine that an assigned action is of type “order fulfilling”, then it would have an order attribute. Etc etc.


Agreed too.

Not sure I followed your point about value_reference, what are you pointing to?

Well what’s actually being stored in value_reference? I assumed doing something like value_concept, value_numeric, value_text, etc. would give us some more context about what the value actually is, but maybe I’ve misunderstood the point of this field.

@akanter the business request was indeed to do some sort of “inbox”, or rather a notification center. That’s what the user-centric dashboard does in the end, it summarises in various widgets things that the providers should pay attention to, and yes those are patient-specific requests.

However it’s to be noted that the dashboard in question was developed in the context of using the EMR in physical rehabilitation centres, so it’s not the typical clinical use case at all.

BUT… the data model for those “todos” (so those assigned actions) is meant to be generic, and hopefully mappable to FHIR’s Task. This thread is rather about the data model than what’s eventually done with it.

@ibacher ah ok, well that’s a different discussion, that’s baked in with attributes, see here.

Bumping this one up.

I intend to get this into EMR API, however using a package name that will make an easy transition to Core when/if this happens.

@ibacher, I’m actually concerned with the fact that Task is precisely one of the two tables that FHIR2 is adding (along with fhir_concept_source). How do we deal with such cases? What did you have in mind when you wrote this:


So, fhir_concept_source is, I think, a little cleaner to use. That table is essentially storing the information we need to connect the FHIR representation of a concept source to the OpenMRS concept source. So, e.g., “” should map to the OpenMRS concept source “LOINC”. In other words, this is metadata needed for FHIR, but probably not for anything else.

The task table is a little bit more complicated. We created this because we needed a representation of task and couldn’t find any structures within the OpenMRS data model that seemed to capture this information. This proposal would add a table that would also be mapped to tasks. There are a couple of ways we could handle this:

  1. We could continue to write these requests into our Task table and then have a rule that, e.g., if Task.owner is a Provider, we load some additional data from the Assigned Action tables.

  2. We could split things at our converter level instead (called Translators), e.g., for tasks where the Task.owner is a Provider instead read and write from the Assigned Actions tables and ignore the Task table altogether. Then in the data access layer, we’d need to load the relevant data from both the Task table and the Assigned Action tables.

Basically, the first case treats all tasks the same, but requires some work to keep the task table in sync with the assigned actions tables. The second approach avoids the data synchronization issues by adding a bit of complexity to the code involved.

Does that make sense?

How about using the existing concept_reference_source.hl7_code for this?

We could easily change to using that field. It’d actually make some of our queries much easier. However, I’m worried about the portability of doing this. E.g., in the baseline RefApp data model, two code systems have this value filled out SNOMED CT with the code SCT and HL7 2.x Route of Administration. HL7 2.x Route of Administration we can probably ignore, but I do need to be able to map “” to the SNOMED CT source. I also don’t want to interfere with any implementations that may currently be using that field for other concept sources.

Thanks for your suggestions @ibacher, what is the best technical option for you, 1 or 2?

The assignees of our actions can so far be typed Role, Privilege or User. All three are different routes to users basically. Just to say that the split doesn’t happen if Task.owner is a provider, but rather if Task.owner is a provider linked to a person linked to a user (I think).

But then the question is: what if an action is assigned to a user who is not a provider? Perhaps that question doesn’t make sense within FHIR’s boundaries? In other words that’s a REST endpoint that doesn’t concern FHIR2

2 is most similar to what we’re doing currently. I like to keep the gory details at one level of abstraction.

Yeah, sorry I was somewhat less precise than I should’ve been. FHIR Practitioner resources are actually intended to represent just about anyone who would have a login to the system. So essentially any user could be modeled as a Practitioner, though we don’t do that currently.

Thinking about mapping Role and Privilege, we might be able to stretch a point and map it to CareTeam, since I assume the intention is kind of the same, e.g., make this action available to any physician or any system administrator, etc.

@ibacher, there’s already a org.openmrs.scheduler.Task in Core. I wanted to introduce a org.openmrs.Task in EMR API, are we all good with that?

Those two should rarely be involved in the same snippets and -well- if they do we’ll namespace one of them.

I’m ok with that.