Support variable target goals for different CHWs / Areas etc
Currently our target config looks like this:
{
"items": [
{
"type": "count",
"id": "pregnancy-registrations",
"icon": "pregnancy-4",
"goal": 7,
"name": [
{
"locale": "en",
"content": "Pregnancies Registered"
}
]
}]
}
etc.
There is an interest in supporting different targets (the 7 in the above example) for different regions in a configurable way.
One reasonably simple way of supporting this is modifying goal to be a list of goals attached to place _ids. When rendering the target page, work upward through the CHW's lineage and use the first one they find (ie the CHW's id, or the area id, or the branch id…), falling back on the system level default.
Three downsides:
- If the partner changes this a lot we would want to move this file outside of main config to make it more editable without wasting data / requiring app refresh
- If the partner changes this a lot and the file is large itself we would still have to sync this to every phone, which is annoying
- This wouldn't be obvious from a analytics / impact perspective (even less obvious than targets already are), because it wouldn't be exposed to them. This would be fixed by writing collated targets to disk (because we'd back it into the file we write)
This ticket has not been prioritised. It is a note for discussion about how we'd best achieve this when the time came to do so.
An example, where for one CHW we want a goal of 5, for everyone under a branch we want a goal of 10, and otherwise we want a goal of 7.
{
"items": [
{
"type": "count",
"id": "pregnancy-registrations",
"icon": "pregnancy-4",
"goal": [{
"for": "system",
"goal": 7
}, {
"for": "a-chws-_id",
"goal": 5
}, {
"for": "a-branches-_id",
"goal": 10
}],
"name": [
{
"locale": "en",
"content": "Pregnancies Registered"
}
]
}]
}
Actually it's slightly easier to implement if it looks like this:
{
"goal": {
"system": 7,
"a-chws-_id": 5,
"a-branches-_id": 10
}
}
Basic change–ignoring moving config to a better location, fixing the edit UI that currently exists in admin (or dropping it), tests etc:
diff --git a/webapp/src/js/services/target-generator.js b/webapp/src/js/services/target-generator.js
index 8957d569c..f99a1ed20 100644
--- a/webapp/src/js/services/target-generator.js
+++ b/webapp/src/js/services/target-generator.js
@@ -73,12 +73,43 @@ var moment = require('moment'),
target.value = calculateValue(target);
};
+ // Correctly determine item goals based on the logged in user
+ var determineItemGoals = function(items, userContact) {
+ items.forEach(function(item) {
+ // Support both
+ // "goal": 10
+ // or
+ // "goal": {...}
+ if (typeof items.goal !== 'number') {
+ var contact = userContact;
+ var goal;
+
+ // Find the most specific goal for the contact
+ while (goal === undefined && contact !== undefined) {
+ goal = item.goal[contact._id];
+ contact = contact.parent;
+ }
+
+ // Or use the global system goal if there isn't one
+ if (goal === undefined) {
+ goal = goal['system'];
+ }
+
+ item.goal = goal;
+ }
+ });
+ };
+
var init = $q.all([ Settings(), UserContact() ])
.then(function(results) {
var items = results[0].tasks &&
results[0].tasks.targets &&
results[0].tasks.targets.items;
+
var userContact = results[1];
+
+ determineItemGoals(items, userContact);
+
if (!items) {
targets = [];
return;
@SCdF As we are re-examining tasks and targets in v3.8, would you be able to share details related to the user stories that brought about this feature request? Who expressed interest in it? Or concrete examples of the targets they were trying to create?
@kennsippell this was over a year ago, so I don't recall much more than what I've already written: target goals should be able to be different depending on the place a CHW is under. The one example I remember is that the average amount of families that CHWs take on isn't constant, and the structure of communities they care for isn't constant, so stuff like "N pregnancies registered a month" isn't a target that works globally.
I one thing I'm unsure of / have forgotten, is how static the differences would want to be. For example, is it "we have 10 regions and they all have slight variations based on regional blah", or is it "we want to be able to tweak targets per CHW at arbitrary moments" (which is obviously a very different thing).
I think Amanda Yembrick brought it up (github ain't doing autocomplete for me here), maybe chat to her?
Good memory @SCdF ! Yep, this was me. We are (still) exploring a data science initiative with PIH in Malawi that this requirement came from. The idea is to use a number of datasources, some external to our tool, and data from the application to come up with individualized targets for a number of activities CHWs undertake, for example TB screenings. In the future, this might be all calculated in the app, but this feature request was to enable a pilot in which all calculations would be done elsewhere, and then the resulting targets entered/uploaded into the application (1-2 times in the pilot period). We do now have dedicated funding for this initiative, so its possible we want to consider an expanded scope and do this differently. The exploratory work is likely to start in January for this, and @ecsalomon is leading it.
Per discussion among me, @kennsippell, @MaxDiz, and @garethbowen yesterday: The need for this is still undefined. We may choose a different approach ultimately for the intended implementation (e.g., a predictive model that targets both who to screen as well as how many to reach a specific recall target).
However, the proposed implementation here makes sense, and I believe it would be good to eventually implement it (or at least ensure that tasks and targets are compatible with it) because we know that burdens of specific conditions vary at the very least among districts. But it is not a priority for the immediate the future.
If we do go this route, I expect to know in January, and we would be looking to implement in April. Is that sufficient lead time?
@ecsalomon That's just enough time if everything goes well. If you can get us a decision any earlier that'd be greatly appreciated!
@garethbowen Ok. Timeline isn't fully set right now, but I will keep that in mind and try to get scoping discussion to happen with more lead time before implementation. Will stay in touch about possible pathways and timelines.
I've seen a few more requirements in this vein from DTree and @MaxDiz. We can discuss implementation in-depth if/when this gets scheduled, but could we consider supporting a more generic mechanic like having the "goal" attribute be a function which is passed the current user (among other inputs)? This would be a more generic, more powerful, and more consistent interface to how we handle this in other areas of the config. It might also be less costly to build.
{
"type": "count",
"id": "pregnancy-registrations",
"icon": "pregnancy-4",
"goal": function(user) {
return {
system: 7,
chw: 8,
supervisor: 10,
}[user.contact.type];
},
"name": [
{
"locale": "en",
"content": "Pregnancies Registered"
}
]
}
@kennsippell feedback from the team is supportive of moving this issue up in priority. How does it fit with the next round of task and target improvements that you're working on?
but could we consider supporting a more generic mechanic like having the "goal" attribute be a function which is passed the current user
Sorry I missed this when you wrote it!
So, if the different goals are either very statically allocated (eg parent X means 80%, parent Y means 90%) or statically defined (eg chws with the X flag on their user record are 80%, those without are 90%, or even the % is a value on their user record) making the goal a function that takes the user context is a great idea IMO. The thing to avoid would be situations where the function itself is forced to change a lot (as it would be pushed to everyone), so idk if that covers all cases
I wonder if this is another thing that should be emitted from nools...
Bumped to 3.11 due to later project kick off.
@katanu @PhilipNgari @nnbhandari1 requesting your input here regarding the priority of this feature. Do we have any projects that would implement this feature if it was available now or within the next 6 months? Any specific information would be very helpful + general thoughts on user need.
I heard this request where the supervisors want to change targets for CHWs based on one or several fixed or changing metrics such as the total number of population-could be HHs served by the CHW and their catchment area- to support the pay for performance approach with DTree. They wanted these targets to either be set by the supervisor (or someone with admin rights) through the user interface (ideal) or have a way to provide for that flexibility through configuration. It is still part of the current DTree work. @ranjuts . I am not sure, about this, but I also think LG had a similar request at one time.
I see this as a request to come when you look at it from the rising need of supervisor and target setting. The targets may vary from one person to another. Not sure how immediate this Ask would be but worth exploring.
Given the tool we are using in MoH Nepal, I am not sure if there has been a request for this in the past. However, having a reliable estimate in-terms of user goal would be very helpful.
One way to get the targets could be the HMIS data where we can get HF level projection but how that will trickle down to the FCHV level is something that is challenging.
@kennsippell as per our discussion, here are more details on the "why" For big deployments like LG and D Tree, their CHVs work in diverse areas so you may have some in peri urban areas with relatively dense populations and others where the areas are more spread out. Ideally these areas would have different demographics. Having uniform targets in these areas isn't fair/ doesn't work very well for incentives etc.. so ideally each CHV area should have customizable targets. This would also help when the population changes or the deployment scales up. I would classify them into urban, peri urban and rural for a start with a set range of population size for example. For the goals it would depend on how many targets the deployment has but without going into the field( disclaimer) I would say you can have it set as 4 pregnancies per population size x or based on x number of HHs registered per CHV.
Just to ensure we don'e make an implementation that precludes other use cases: One of the initial motivations for this issue was to support, e.g., epidemiological or machine learning models to set custom screening targets per catchment area. Inputs to such models might include:
- what month is it?
- is malaria endemic to this location?
- how many cases were identified in this catchment area last month?
- how many cases were identified in neighboring catchment areas last month?
- how many U5 assessments did this CHW do last month?
@ranjuts As part of D-Tree's supervisor feature requests we received the following user story:- "As a supervisor, I would like to see key health indicators for my supervisory area benchmarked against my district, in order to assess the topics that my CHVs should give special focus to Display visualizations of a few key, high-level health indicators in comparison to district-level or national-level benchmarks" They are requesting for the ability of a supervisor to compare targets in his/her area with that of a peer group.
Cc @PhilipNgari @korirm @kitsao @katanu @maremegaye
Thanks team! Do we have an estimate of when this feature will be out? cc @MaxDiz
Hi @PhilipNgari this issue has not been scheduled yet. It requires further scoping before it can be scheduled for development.
Hey @MaxDiz . This thread suggests to me we have numerous and somehow different Asks. I.e the PIH,Dtree and LG. Which one do we need further scoping on it so that I can rally teams for support? Most grateful. cc @ranjuts
how are we doing on this @MaxDiz on this Dtree request.
@MaxDiz It looks like this request could benefit from a PrO looking at requirements from across the deployments to ensure that we're covering each. I see a variety of user stories being brought forward for each kind of partner alongside the research and learning requirements. Has that already been planned by any chance? We could also have a service designer support if needed.
In terms of contractual requirements, this is not a blocker and D-Tree is aware and okay with what is coming with the first set of supervisor features but with the understanding that this is coming soon after (and despite it being a part of SOW due March 2020). This is high in the list of features that they are looking forward to as a Technical Partner and something we should deliver on in good faith.
This issue has been added to 3.10 to fulfill contractual obligations. It needs additional scoping to clarify requirements from project deployment and R&L team perspectives. If ready in time, eng can pick up, but it should not be a blocker for the release.
assigning myself to continue scoping
From discussion with @ecsalomon and @sacul-git , R&L minimum requirement is to create a feature MVP that does not need to be completely re-engineered to be able to incorporate:
- Individualized targets for activities CHWs undertake (ie targets irrespective of hierarchy)
- Calculate targets dynamically from a function, using internal + external data sources (gps, epidemiological models, etc). May overlap with https://github.com/medic/cht-core/issues/5706
- Ability to update targets monthly- targets would need to be recorded to hold them stable. May overlap with https://github.com/medic/cht-core/issues/5708
- Ability to update targets without syncing to server
Timeline for deployment is 6(ish) months - planned work with PIH has been delayed due to Covid redirect
From discussion with @ranjuts , project implementation minimum requirement is to create a feature that incorporates the ability to:
- set targets at a branch level in the deployment hierarchy
- manually change targets at the supervisor field level (ie not in config only)
- update targets without syncing to server (current timing expectation is quarterly)
- store historical target data for offline access for 3-months, and for a tbd amt of time for online access (clarifying with partners) - v3.9 release includes online access to targets
Timing for deployment is Q3/4 2020 - feature is a contractual obligation
@MaxDiz and I have a conversation about this from a technical perspective. I confess I don't completely understand the requirements as talked about in Max's past two comments, so @ecsalomon / @sacul-git / @ranjuts please read this comment carefully and let me know if what I'm saying is accurate. I apologise in advance for how wrong I'm about to get everything (and how long this has ended up being):
@ranjuts 's minimum requirements:
- set targets at a branch level in the deployment hierarchy
- So this is fine, though if I understand the next bullet point we'll need to modify replication so that offline users get read access to places documents that are higher than their attached place
- manually change targets at the supervisor field level (ie not in config only)
- I am understanding this to mean that supervisors get to personally change goals on the fly, presumably for the place that they are a supervisor of.
- update targets without syncing to server (current timing expectation is quarterly)
- If this means that the progress of a targets updated without a server (like it does now) then that's fine. If you mean something else I need more clarification.
- store historical target data for offline access for 3-months, and for server-side analytics access for a tbd amt of time (clarifying with partners)
- I believe this is either already done or shouldn't be a problem, but regardless it sounds like a different ticket entirely (ie it's not about configurable goals, it's about target storage)
@ecsalomon and @sacul-git 's future requirements:
- Individualized targets for activities CHWs undertake (ie targets irrespective of hierarchy)
- Does activities in this context mean reports that CHWs have created via tasks or other actions? Or does this mean reports about CHWs?
- Calculate targets dynamically from a function, using internal + external data sources (gps, epidemiological models, etc). May overlap with https://github.com/medic/cht-core/issues/5706
- As targets have to work offline it's not possible if external means "over the internet", but if the data you care about can be written into some specific places (more on this in examples below) and doesn't have to dynamically updated this is more coverable. Talking about the GPS example, in general I'd be very cautious about allowing targets to be configured with goals that have to be calculated asynchronously, as async code is hard to write correctly at the best of times.
- Ability to update targets monthly- targets would need to be recorded to hold them stable. May overlap with https://github.com/medic/cht-core/issues/5708
- Not sure I get this one sorry. Can you expand on it?
- Ability to update targets without syncing to server
- If this means as "update targets without syncing to server (current timing expectation is quarterly)" then the same comment applies.
Right, so presuming I understand what's going on, a MVP piece of work could be:
- change replication so that offline users have their entire parent hierarchy downloaded to be viewed offline (but not edited, obviously). This means that you can write target goals on branch place documents, for example.
- allow a targets
goalto be defined as a function that takes the userId/context (so we know who they are), as well as their contact object with the parents hydrated.
Later on we are able to extend the goal function to also allow for passing in all contacts and reports that chw has access to (if that's what "Individualized targets for activities CHWs undertake"` means) if we need to. Since this is potentially expensive we can also detect if your function asks for those values and only pull them in if we need to.
Having this will let you have goals that are:
- static like now:
"goal": 40 - defined by a tag or flag against the
org.couchdb.user:<blah>document:"goal": "function(userContext) { return userContext.thisGoalTarget;}" - pulled from hierarchy place documents:
function(userContext, contact) {
let parent = contact;
while (parent) {
if (parent.thisGoalTarget) {
return parent.thisGoalTarget;
}
parent = parent.parent;
}
// not defined anywhere in hierarchy
return 40;
}
Does this make sense? Am I on the right track?