This scoping document defines the narrative and technical requirements for dynamic task generation and entity persistence for the Reveal platform. The contents of this document relates to dynamic form configuration, but is not wholly dependent on that feature set. In essence dynamic task generation and entity persistence can take place independently of which form is opened when a task is assigned.
...
Plans will be updated to include action criteria that supports defining templated logic that should be evaluated when generating tasks in the server and client. This will be used at multiple steps across the system.
We will move bulk task generation from Nifi into the OpenSRP server, adding a business layer and queue that supports the evaluation of plans and generation of tasks. This process will walk the relationship tree for all affected entities that are affected in the jurisdiction, evaluating the logic defined in the plan action at each step.
(CRAIG CHECK THIS AGAIN AFTER YOU FINISH THIS DOC) We will not implement a state machine in the OpenSRP Server.
Configurable forms will be able to define the task’s business status as a hidden value in the bottom of the form labeled business_status.
This allows for configuration of the business logic, color coding, and task processing
We will implement a task state machine in the Android client that is able to execute logic on task state changes.
This allows us to respond to changes in task state independent of form submissions. A post save action on a form may or may not change the state of an assigned task. This allows us to chain actions in the event we need to execute multiple, independent, actions based on task state changes.
Plans will be evaluated in the Android client after a task state has changed to identify if follow-on actions should be taken. Each action will include evaluation criteria that determines the action.
The Android client will be able to display multiple tasks assigned to a structure in the map view. This will allow implementers to assign multiple action items and independent forms at the structure level.
(I’m not sure if we want to do this or solve it another way) We will provide access to view and edit locations, families and family members in the Android client even if a task is not assigned to that entity.
The location is the primary unit of navigation from the map view. A user can not access the information at a location if a task is not assigned. We will lift that constraint and allow users to view the underlying entity.
...
Forms (Upload Web UI)
System administrators will be able to add, edit, and update fields for forms that are available in the system. This includes changing the business status that impacts task generation
Plan Templates (No Web UI)
This is a new item that will allow system administrators to define plan templates for certain workflows. We currently hard code this into the OpenSRP Web UI for IRS and Focus Investigation. These templates allow a user to select from a drop down menu and control the actions that show up. Ultimately, the template creator has the capacity to create any action they wish.
Creating, updating, and archiving Plan Templates will not be accessible through the web UI.
Plans (Web UI)
Users are currently able to create plans in the Web UI. We will expand this to support adding criteria to action.
Task State Change Logic (No Web UI)
This will allow us to define logic that executes when the task state changes
(Placeholder: I’m not sure if we need to do this) Post form save logic (No Web UI)
We want to standardize the post form save logic so that it can be templated and eventually defined server side. This would allow us to define what happens after a form is saved.
(I’m not sure if we want to do this, or if MapBox provides this for us) Map View Styles (No Web UI)
System administrators will be able to define color coding for business status combinations available in the Android client and Web UI’s map views. This will allow system administrators to define color coding combinations on state
...
User creates a plan in the Web UI
They select from a drop down of plan templates, choosing (IRS Zambia 2020 plan template)
They complete the online form, confirm the default dates are correct and click Save
(optional) The user walks through the map based planning UI
The plan’s status is changed to “active” which triggers an action that generates all tasks for the plan in the OpenSRP Server
The user assigns a team to the plan if it wasn’t done in the map based planning UI
The spray operator logs into the Android client and the data syncs to their device
The user drops a point to add a location
The form is saved
The post form save action generates a task with status=”complete” and business_status defined by the form.
The task state change triggers an evaluation of the actions in the plan
The spray action evaluates to true because the location is marked as a residential structure.
The task state machine generates a “spray” task based on the spray task template that was configured with status “Ready”
The color coding is reflected as it was defined for this type of task in the Map View Styles configuration
The user taps the structure
If multiple tasks were assigned, they would be presented with a list of those tasks so they could choose which one to complete. The user should also be able to archive a task if it’s not relevant.
The form opens, they complete the form, and save it.
The post save action executes, updating the business status of the task
The task state change in status and business_status triggers an evaluation of the actions of the plan
All criteria evaluates to false for each action, so nothing is changed in the system
The user is returned to the map view. The color coding is reflected as it was defined for this type of task in the Map View Styles configuration.
...
User creates a plan in the Web UI
They select from a drop down of plan templates, choosing (Thailand Routine FI 2020 plan template)
They complete the online form, confirm the default dates are correct.
They make sure to check the plan as active
The plan’s status is changed to “active” which triggers an action that generates all tasks for the plan in the OpenSRP Server
The user assigns a team to the plan
The frontline worker logs into the Android client and the data syncs to their device
The user drops a point to add a location
The form is saved
The post form save action generates a task with status=”complete” and business_status defined by the form.
The task state change triggers an evaluation of the actions in the plan
The spray action evaluates to true because the location is marked as a residential structure.
The task state machine generates a “register family” task based on the register family task template that was configured with status “Ready”
The color coding is reflected as it was defined for this type of task in the Map View Styles configuration
The user taps the structure
If multiple tasks were assigned, they would be presented with a list of those tasks so they could choose which one to complete. The user should also be able to archive a task if it’s not relevant.
The form opens, they complete the form, and save it.
The post save action executes, updating the business status of the task.
The task state change in status and business_status triggers an evaluation of the actions of the plan
The criteria for the “Bednet Distribution” action evaluates to true so a bednet distribution task is created
The criteria for the “Blood Screening” action evaluates to true so a blood screening task is created for the head of household.
The criteria for all other actions evaluate to false.
The user is forwarded to the household view
The user registers the spouse of the head of household and saves the form.
The post save action executes, creating a task with status=”complete” and business_status based on the register family member form. (This allows us to count that work, even though it wasn’t initially assigned)
The task state change in status and business_status triggers an evaluation of the actions of the plan
The criteria for the “Blood Screening” action evaluates to true so a blood screening task is created for the recently added family member.
The criteria for all other actions evaluate to false.
The user returns to the household view.
The user completes the blood screening form for the head of household.
The post save action executes, updating the business status of the task.
The task state change in status and business_status triggers an evaluation of the actions of the plan
The criteria for all actions evaluate to false.
The user returns to the household view.
The user edits the blood screening form for the head of household.
The post save action executes, updating the business status of the task.
The task state change in business_status triggers an evaluation of the actions of the plan
The criteria for all actions evaluate to false.
The user returns to the household view.
The user navigates back to the map view and the color of that structure changes to the color defined in the configurable Map View Style
...
We need to remove the idea of an Intervention Type across the system. Instead of an intervention type, we need to depend on the task actions that are set. Ultimately, we want any action that is added to the plan to be supported in the Android client.
There’s a difference between the form that’s filled to create the plan and the plan itself. For example, there are specific use contexts related to FI plan types. This should remain optional to be filled in as a template for FI specific plans, but we do not need to depend on intervention type for internal business logic.
We need to add support for conditions on 0…* triggers within plan actions so they can be evaluated during generation.
specifically
condition.kind:”applicability”
condition.expression: (See specifically (following https://www.hl7.org/fhir/metadatatypes.
html#Expression)We need to add a definitionUri that points to the form to be filled out by form name. This will be evaluated when a task is opened to determine which form to open. (i.e. the IRS Spray Structures action will have a definitionUri that points to the spray_form.json)
that we can quickly evaluate whether we want to trigger the evaluation of this action based on a value in the system
New PlanDefinition
We need to create a new entity in OpenSRP server called PlanDefinition which acts as a template for plans so that we can make and reference plan templates from the web UI. So, the IRS plan would have a particular type of planDefinition template and the MDA would have another one. When a user creates a plan in the web UI, they would read from a dropdown of available plandefinitions and that would populate the form in the web UI. When they hit “save” it creates the plan as per usual.
...
plan.action.trigger should contain the following:
type: “named-event”
name:””
options:
“planActivation” - This event represents the one time a plan is activated
“locationAdded” - This event represents when a location is added
“familyRegistered” - This event represents when a family is registered
“familyMemberRegistered” - This event represents when a family member is registered
(Any encountertype that’s in the json form definition. So, you could fill out a “MDA Adherence” form that creates an “mdaAdherence” event)
We need to add support for conditions on actions so they can be evaluated during generation.
specifically (following http://hl7.org/fhirpath/)
condition.kind:”applicability”
condition.resourceType:””
This is an extension to FHIR to make the evaluation of the expression easier based on the resource type
Supported resourceTypes:
location - This references a location that is not a jurisdiction (is_jurisdiction=false)
jurisdiction - This references a location that is a jurisdiction (is_jurisdiction=true)
family - This references a family
familyMember - This references a family member
condition.expression: We will implement a light version of FHIRPath in the initial implementation to support boolean expressions that evaluate to true or false
$this.tree1.tree2.treeN We will support a dot notation that can go down different levels of a JSON object
Required expressions for this MVP
$this.properties.type = ““ and ($this.properties.status = “active” or $this.properties.status = “pending”) (resourceType = “location”)
We use this expression to validate the type of location and act when the location status is active or pending so we can trigger actions. The user can enter the type of location such as residential_structure.
$this.exists() (resourceType = “jurisdiction”)
This expression will evaluate to true if the jurisdiction exists. We will use this to trigger jurisdiction level tasks
$this.relationship(family,'status!=”active”') (resourceType = “location”)
This expression identifies if a location has an existing relationship with a family resourceType and that family’s status is active, not archived. We will use this to determine if we want to generate a register family task.
familyMember.age >= “5”
This expression identifies if the family member’s age is greater than or equal to 5
Supported operators
= (equals) This operator evaluates to true or false
!= (not equals) This operator determines if the values are not equivalent
> (greater than) This operator is used to evaluate if a value is greater than a number
< (less than) This operator is used to evaluate if a value is less than a number
>= (greater than or equal) This operator is used to evaluate if a value is greater than or equal to a number
<= (less than or equal) This operator is used to evaluate if a value is less than or equal to a number
and (and) This operator evaluate to true if all expressions evaluate to true
or (or) This operator evaluates to true if one or more expression evaluates to true
() (parenthesis) We use parenthesis to group logic
'' (single quotes) We use single quotes to segment expressions within a function
Supported functions to get additional information
exists() - This function identifies if the entity exists and evaluates to false if it does not
relationship(resourceType,'expression') - This function supports a nested expression so you can search expressions for existing relationships and evaluate the entity
We need the ability to have functions that determine if a relationship is available between entities
We do not support looping through different entities in these expressions. A user can create a plan action for each entity in the jurisdiction if they wish to
We need to add a definitionUri that points to the form to be filled out by form name. This will be evaluated when a task is opened to determine which form to open. (i.e. the IRS Spray Structures action will have a definitionUri that points to the spray_form.json)
New PlanDefinition
We need to create a new entity in OpenSRP server called PlanDefinition which acts as a template for plans so that we can make and reference plan templates from the web UI. So, the IRS plan would have a particular type of planDefinition template and the MDA would have another one. When a user creates a plan in the web UI, they would read from a dropdown of available plandefinitions and that would populate the form in the web UI. When they hit “save” it creates the plan as per usual.
We don’t need a UI for creating planDefinitions, but we need a REST API to POST, PUT and GET these templates.
Software to be Developed
This section outlines the software packages that need to be developed in order to deliver these features. The target is to break out these items into tangible chunks of work that can be scheduled and delivered within two weeks.
1. Develop Plan Evaluator Java Library
We need to develop a Java library that can be run both in the Android client and OpenSRP server. This library will be responsible for evaluating plans and generating tasks. The inputs vary depending on the location where the library is deployed. This library is responsible for consistently executing the logic that generates tasks.
Inputs:
planIdentifier - This is the identifier of the plan that needs to be executed
trigger -
(optional) Entity - This is an entity to be evaluated against the plan. This allows us to evaluate a specific
Triggers:
Server - This library gets triggered the single time that a plan transitions from status:draft to status:active
Android Client - This library gets triggered through an asynchronous call
Logic:
...
Don’t evaluate anything below this
...