Some use cases and workflows require additional information to be displayed in the contact profile. For example, seeing a woman's EDD on her contact profile or knowing if her pregnancy is high-risk by looking at her profile. Another example would be showing a child's height and weight for growth monitoring for malnutrition.
This should be configurable, so we can adjust what displays in the contact profile on a per-project basis or based on the type of contact profile we are viewing.
Information like the EDD could then be passed to the action context predicate to enable showing actions based on status.
Has anyone got a clear idea of how this should be configured, or any examples apart from EDD?
I have some ideas, happy to chat about it. Other examples would be patient height and weight for growth monitoring (malnutrition) or a list of immunizations received by a child. The main piece is just being able to pull in data from previous reports to display in the contact profile.
The way I've been thinking about it is to be able to configure certain fields from a report xform to store in the patient's contact doc, making them available for display, setting form context or for pulling into a later form.
@abbyad may have thoughts as well.
Here are some mockups, showing some different configurable subgroups:



Since we want these modifications to be done even completely offline, we'll need to rely on XForms and not transitions. As a result, we'd want to be able to specify which fields should go to the person or place's profile in the XForm, using a special trigger group (could be named action, but thought that would be confusing since we refer to "Actions" in the app).
For example, a form could have a person (or place) group inside an trigger group where all sub fields would update values for matching keys in the profile for the person (or place). The top level fields would correspond to top level fields, and those in further subgroups would be grouped accordingly in the contact's doc. These would then be represented as groups like Immunization or Pregnancy in the mockups above. From my understanding there could 0 to n groups on a single profile, limited by project design considerations.
For instance, a form would have:
trigger/person/_id used as a reference to the person to update. We'd obviously not allow updating the _id, but could we would use NEW for creating a person using the same configuration notation (#2912). trigger/person/date_of_birth create/update a value in top level fieldtrigger/person/pregnancy/edd update a specific value in a subgroupOn the profile we'd list all fields accordingly in the profile, and grouping those from subgroups. It is not an immediate requirement to show/hide specific fields on the profile, but that is likely to be requested at a later time. When we do this we'd want to do it similarly to the way we specify it for report fields on the Reports tab.
We can configure projects to have labels for the profile fields based on the paths of the fields, like we do for a report in the Reports tab. Eg
"trigger.person.pregnancy": "Pregancy"
"trigger.person.pregnancy.edd": "Expected Date of Delivery (EDD)"
Two more things it might be worthwhile to consider after chatting about this more with @sglangevin and @abbyad:
It seems like most fields for the different "configurable subgroups" are coming from patient forms, not contact forms. What special considerations would need to be made around this feature in order to enable displaying additional information from a contact form like 'Add Person' in a configurable way? And if a contact was later edited ('Edit Person'), would the updated value be reflected on the profile?
Some information from the 'Add Person' form (i.e. info about a child's chronic illness) may be better to include in the top section of the profile page, which contains static information about a person like Name, Age, and Gender. It's worth considering what types of info should be in the top profile card vs. the other card for growth monitoring/pregnancy info/etc. Could the top card have configurable fields for profile info?
Statically setting values on the report has a couple of downsides we might wish to consider:
That last point is really important IMO. We should come up with as many realistic and diverse examples as possible, to make sure that we can cover these with this system. There are things I can think of that might be challenging to do in this system safely, but I don't know if they are ever relevant in real world cases. Think any kind of "off by one" style of error, or anything where the answer dynamically changes over time without user input. Examples:
The more flexible approach would be to have form designers write code that pulls this related data in real-time when you view the person, instead of statically writing it to said record. The downside is that they are writing code, but then again we already expect people to be able to do that with Nools. It would suffer far less from potential "off by one" errors.
@SCdF I noticed that the examples you are citing are related to aggregate numbers of the work a CHW is doing. This issue was created to help keep track of current data, not data over time. So, for example, having a way to store a woman's EDD and display that on their profile or storing a child's heigh and weight and displaying that on their profile. The data we're talking about is individual patient information as opposed to aggregates and we're talking about specific points in time as opposed to tracking over time. So I wouldn't expect this feature to support either of the use cases you mentioned. Those would be handled with analytics.
One use case that might be relevant when thinking about "off by one" errors would be tracking the number of ANC visits a particular woman has had, but there is only one form that would add to that number and there are no subtractions. The number of ANC visits would just be cleared when the woman delivered.
I'm not sure what you meant by "have form designers write code that pulls this related data in real-time when you view the person". Are you saying that we would have to create a form that then reviews all of the forms about a person before displaying their profile?
I noticed that the examples you are citing are related to aggregate numbers of the work a CHW is doing. This issue was created to help keep track of current data, not data over time
As you say, ANC visits is an aggregate though right? As are how many immunisations they've had.
Looking at the examples above, I'd also be concerned about how you'd implement the chronic disabilities example. I.e. would that be a string that gets composed out of many different forms that get filled out over time (i.e. people don't always have the disability, they get added over time). Pregnancy risk could be similar.
I don't want to make this more complicated than it needs to be, which is why I'm interested in a list of use cases and how people think they would be implemented. It may be that we can just make some really simple rules that cover everything we want, i.e.
@SCdF , hereâs a list of use cases I can think of for malnutrition and how I think theyâll be implemented. Iâll re-paste the mockup from earlier to help illustrate the examples:

Examples: In the Growth Monitoring card above, âLast Visitâ, âWeightâ, and âHeightâ will all come from the most recent child assessment form. Each will basically just be a read-out of a single calculation, string, date, integer, etc.
Examples: In the Growth Monitoring card above, âSupplementationâ will come from the most recent âAssign Supplementâ form and âStatusâ will come from the most recent âAssign Statusâ form, both of which are actions that a Branch Manager would take. Each will basically just be a read-out of a single calculation, string, or select_one option.
Example: In the Growth Monitoring card above, âChronic Illness or Disabilityâ will come from the âAdd Personâ form. If a child has no chronic illness or disability when he is first registered, but the CHW later submits an âEdit Personâ form and changes the answer to âAsthma,â the profile should then be updated to show asthma. This will either be a string or a select_one option. To answer your earlier question Stefan, this wouldnât be a string that gets composed from many forms but rather a single string from the latest edit person form.
These are the examples I can think of that are relevant for projects we are already deploying or that are critical for projects we are deploying very soon. Iâll loop back if I can think of any other use cases we might run up against in future malnutrition scenarios.
Iâll let others add in other examples before we synthesize into rules that cover everything we want.
@SCdF I think your assessment is mostly correct:
- Can only be applied to patients (so only one person, their CHW, will ever write to that patient record)
A CHW or Nurse/Branch Manager could submit a form about a person - but in all cases they are submitting a report about a single person.
Can only be writing a fixed known value to the patient (eg their height or weight)
Or incrementing or decrementing a value by 1.
Correct, with our planned uses we'll be writing a string (eg new score, or value with units, or adding visit), or clear the value (eg a new pregnancy report clears the number of ANC visits back to 0). The math or string manipulation can happen in the form even if previous values are needed, because fields on the person's profile would be included as input for the form. This means that a simple increment is easy to do in the XForm - which is probably easier than having different trigger types.
That said, there are still some things for us to consider:
@abbyad I agree with your comments. In terms of adding this functionality for SMS reports, what happens once SMS reports are being sent via task rules?
In terms of adding this functionality for SMS reports, what happens once SMS reports are being sent via task rules?
Curious about @garethbowen's thoughts on this, but I think I recall him saying that the transitions in app_settings would live on.
@abbyad I've talked to @garethbowen about approaches. From a technical stand point we'd like to look at extending nools to be used for this. Effectively configurers would write rules that emit values against the thing (emit visit against a patient id for example), and we would provide a service that found those and exposed them to the form in an understood way. This would also be available to the context, solving #2913.
Upsides is that you don't get unsolvable off by one / ordering / static errors in the future, because if there is a bug in configuration you just get the fix and refresh. The (potential) downside is that only people with the data to generate this summary data will be able to generate and thus see it. For example, admins / branch managers wouldn't be able to see how many visits a patient has had[1]. This is solvable in the same way that we're considering things like targets to be solvable, either by running nools on the server and making it online-viewable, or by generating summary docs at lower levels and pushing them upwards.
Let us know when you've got time so we can chat about it on a call.
[1] if they can even see the patient: I'm not sure if we've decided how much information people other then CHWs can see offline yet?
@SCdF I'd be interested in chatting with you guys about this as well if you don't mind including me in the call.
Sounds like an interesting approach that will be more powerful in the long run. Let's chat with Sharon about this as soon as possible.
Talked with @garethbowen, @abbyad and @sglangevin. We've decided to not bother with Nools for this because we're not really getting anything from it.
Instead we'll do something similar: the code they write will accept a list of documents[1] (as opposed to the similar but different nools structure), and we will run that code ourselves "manually" when the contact page is loaded. This can be extended cleanly in the future when we need to support summary documents (eg branch managers etc) by having something that watches the changes feed and runs the code for the relative contact and saves the outputted block if it changes.
In more boring technical detail (IMO, @garethbowen fight me â¤ď¸ ):
context and display (or something, names tbd)context is for extra arbitrarily structured data you want to expose to the context code block to allow it to make decisions, but you don't want to display it on the pagedisplay should be a JSON object structured in the same way you'd like it to be displayed. It can support two layers, the section and then the value. The third layer can be used as key/value pairs to fill out complex translation keys. Example below.display portion, and generate the extra UI sections from it.Example, taken from the immunisations example above.
The code block would return something like this:
{
display: {
immunisations: {
dateRecorded: 1235245322, // eg ms since 1970
immuComplete: {
bcg: 1,
oralPolio: 4,
penta: 3,
pneumo: 3,
rota: 2,
measles: 1
},
immuPending: {
measles: 2,
vitA: 10
}
}
context: {
// maybe some stuff here
}
}
The configurer would also provide translations like this:
prefix.immunisations = "Immunisations"
prefix.immunisations.dateRecorded = "Date Recorded"
prefix.immunisations.dateRecoded.value = "{{0 | formatDate}}"[3]
prefix.immunisations.immuComplete = "Immunisations Complete"
prefix.immunisations.immuComplete.value = "BCG ({{bcg}} of 1), Oral Polio ({{oralPolio}} of 4), etc etc"
prefix.immunisations.immuPending = "Immunisations Pending"
prefix.immunisations.immuPending.value = "Measles ({{measles}} of 2), Vitamin A ({{vitA}} of 10)"
prefix tbd.value is the translation key for the third-layer property. Note that the third layer can be a json object as well. If that's the case the keys are used in the translation key[1] And the contact as well @garethbowen, for good measure / flexibility? We already have that loaded so it's free to pass.
[2] As scary as that is, I can't imagine how else nools is doing it.
[3] @garethbowen how smart can our translations get? Would we want to do this kind of thing in the code block, or leave it to the translations?
Looks pretty good. IMO display should be an array not an object to allow multiple sections with the same name...
1) Yes include the contact as well.
3) I don't think we can do date formatting in translations. We could either expose date formatting to the configurer to call and just give us a string, or try and do something clever to detect dates, numbers, etc.
But yeah, we pretty much agree :)
Looks good, with a minor area to clarify: the code the Tech Leads would write is for all person/place profiles... not _per form_.
Code review please @estellecomment : https://github.com/medic/medic-webapp/pull/3106 . It's rather large and also solves #3037 #2913 and #1930
Configuration documentation added here: https://github.com/medic/medic-docs/blob/master/md/config/contact-summary.md
For acceptance testing try out different configuration options and ensure that you can generate the whole range of data for display.
This is really cool!
Good job @sglangevin and @abbyad and @guptasanchay for the thorough and helpful input, @SCdF for nailing all the design to the end, and @garethbowen for implementing it.
Re: code review, my main complaint is the naming of fields in the object that the script returns, the rest is smaller things. https://github.com/medic/medic-webapp/pull/3106#pullrequestreview-20733429
I love your documentation! And I'll love it even more after you've added this million things I'm asking for : https://github.com/medic/medic-docs/commit/3c2a73ee58436acc6230728d79add04318b8f92a
Cool!
This is working well so far!
Profile fields and cards are configurable and display as expected in tests.
We should add examples in the documentation for the context section of the card configuration, as well as for the context passed to each form's expression.
Most helpful comment
This is really cool!
Good job @sglangevin and @abbyad and @guptasanchay for the thorough and helpful input, @SCdF for nailing all the design to the end, and @garethbowen for implementing it.