Data design for Task List feature

We have designs for a Task Management feature. I will be implementing these over the next few months, with the direction of @michaelbontyes . Relevant previous discussions:

I would like to design the data side and backend implementation strategy here.

FHIR Representation

I think these are the entities that are needed:

  1. System Tasks: the elements of the Task Library, like task templates, optionally with trigger conditions.
  2. Tasks: the actual to-do items.
  3. Sub-tasks: this is not part of the design but is part of the project I am undertaking.

I am not sure how to represent these things with respect to PlanDefinitions, CarePlans, ActivityDefinitions, and maybe Tasks.

I think it would make sense for a System Task to be a PlanDefinition.activity. Maybe there would just be a 1:1 relationship there, so each System Task is a PlanDefinition, and most of its content lives in a single element of PlanDefinition.activity?

@ibacher has expressed, in the thread I linked at the top, that task list items should not be represented as FHIR Tasks, but rather as activities associated with a CarePlan. Note that the CarePlan has changed radically from v4 to v5. I have trouble imagining how we could use the v5 CarePlan for this purpose, without relying heavily on Tasks.

A CarePlan does not contain reference to an ActivityDefinition, so it doesn’t seem that an ActivityDefinition could be the thing that represents a task in the task list. An ActivityDefinition would rather be part of how a PlanDefinition defines its action to be taken when the plan’s action is instantiated into a CarePlan action.

My inclination is then to represent each task as a CarePlan with a single activity, which in some cases will have a corresponding PlanDefinition with a single action. All the relevant information would be in CarePlan.activity[0].detail.

Does this all make sense, seem right?

Once we get some consensus on this, then we can discuss the database representation and implementation strategy.

@ibacher @dkayiwa @mozzy @samuel34

3 Likes

For an MVP, I would like to exclusively use the two entities PlanDefinition and CarePlan. No ActivityDefinitions or MedicationRequests or whatever. There would be a URL that will take the user to the right part of the O3 app to fulfill the task.

1 Like

So the “*Definition” resources are meant to represent definitions, a sort of template or pattern that can become a concrete resource, like a CarePlan, etc.

So, going from your list:

  • System Tasks: these are almost certainly a combination of a “PlanDefintion” and one or more "ActivityDefinition"s where the “PlanDefinition” becomes a concrete “CarePlan” (an organized list of tasks) and the "ActivityDefinition"s define the concrete “steps” (“activities”) that are part of the CarePlan.
  • Tasks: These are probably activities within a specific “CarePlan”. A little more about that below.
  • Sub-tasks: I’d want to here more concretely about what you’re planning on using these for. They might be the point where we want to talk about the FHIR Task resource.

Essentially, a “CarePlan” is a way of organizing a set of tasks that share a concrete goal, e.g., “this is the plan we’re following to manage the patient’s HIV care”, etc. It’s a way of categorizing tasks. A “PlanDefinition” is a template for a “CarePlan” that can include logic for customizing the CarePlan to a patient context or can just serve as a library of available plans.

It’s the “activity” elements within the CarePlan that most closely resemble what I think of as a Task. A catalog of potential “activity” elements would be captured via the “ActivityDefinition”.

All that said, maybe for an MVP we could get away with something like ActivityDefinitions and CarePlans.

1 Like

Follow-up on the weirdness: So, for the most part, we’re locked into FHIR R4. This is for technical reasons that are too boring to recite here. Weirdly, as @bistenes points out, the CarePlan changes a lot between R4 and R5, but in the direction of becoming less detailed in R5. I.e., in R4, we have the activity[n].detail element that can include a lot of information about the activity, but in R5, this gets collapsed into the plannedActivityReference and performedActivity elements. The lack of a standardized conversion between these makes it hard to know exactly how we should use them.

However, for the simplest thing, where we just need a string description of the specific activity and we want to be as forward-compatible as possible, the best thing to do might be to use the standard extension for activity.title since this is basically identical between R4 and R5.

Not sure if that meets all the requirements here though.

Thanks for the analysis, @ibacher .

I am not sure what subtasks are for, actually. Maybe @michaelbontyes can provide some user stories. My inclination is just to represent them exactly like tasks, and use CarePlan.partOf to refer to the main task. It is possible that the requested use case is actually like the CarePlan-Activity relationship, but I hope that that’s not the case, because that will be more complexity than I bargained for.

Using ActivityDefinitions for the elements of the Task Library makes sense. I am not sure what role the PlanDefinition would serve. Right now, we do not have designs or specifications that suggest that tasks should be grouped together into plans (modulo the paragraph above about subtasks and tasks).

I am inclined to use activity.title, and also to use the detail fields to support things like due dates and user assignment. If we were to move to FHIR v5 someday, I would assume that those fields could be structured into the plannedActivityReference activity-resource (e.g. MedicationRequest) returned by the API. That kind of e.g. MedicationRequest would be semantically totally different from a MedicationRequest returned by the /MedicationRequest endpoint (the former representing a request for a medication request, the latter representing a request for medication), but I think that is FHIR’s intention.

Implementation

So then there’s the question of how the data is represented in the database. Right now I think it’s pretty straightforward either way—two tables, one for system tasks / ActivityDefinitions and one for tasks / CarePlans, with just the fields we need to build the two FHIR entities expected. Does that seem right? Since the FHIR objects have some structure to them, and may eventually have activity-specific subresources, I am inclined to name the tables according to application logic (systemtask and task) rather than according to their FHIR representation.

Hi @bistenes , so as promised, I met with @michaelbontyes today and we created this project page write-up on the wiki: :backhand_index_pointing_right: https://openmrs.atlassian.net/wiki/x/mIDpJ :backhand_index_pointing_left:

I tried to add many more examples for you. Please see the examples and in particular I think you’ll ‘enjoy’ the giant set of example sub-tasks if you expand the “More Sub-Task Examples”.

Also added some more context about the first phase of this Tasks project from back in 2023, and added all the design links and helpful links I could think of :slight_smile:

1 Like

Thank you @grace ! This is indeed clarifying.

The use cases for subtasks make it look like they would be best represented as activities within a single CarePlan.

So then tasks with no subtasks are a CarePlan with a single activity, and tasks with subtasks are a CarePlan with one activity per subtask.

In the database, I am not sure whether to make subtasks its own table, or just to put subtasks in the tasks table. I don’t presently see it as consequential, and I guess may as well do the latter.

This does make me think that PlanDefinition should be taken more seriously from the get-go. Maybe the move is to represent definitions as PlanDefinitions, which can be defined with subtasks. A task definition with no subtasks would be a PlanDefinition with a single action. We then would not really be using ActivityDefinition, which I think makes sense because we’re talking about not really using activities (/request resources) as tasks or subtasks.

2 Likes