medic / cht-core

The CHT Core Framework makes it faster to build responsive, offline-first digital health apps that equip health workers to provide better care in their communities. It is a central resource of the Community Health Toolkit.
https://communityhealthtoolkit.org
GNU Affero General Public License v3.0
467 stars 217 forks source link

Support adding phone number when registering patients via SMS #8204

Closed PrjShrestha closed 1 year ago

PrjShrestha commented 1 year ago

Is your feature request related to a problem? Please describe. @binokaryg was trying to register a patient with phone number using SMS form that utilizes the add_patient trigger but it wasn't possible.

Describe the solution you'd like

Update: July 3, 2023

Describe alternatives you've considered Using RapidPro to process the messages you can use a flow to update the phone number of the contact.

Additional context Add any other context or screenshots about the feature request here.

Update: PR for this is https://github.com/medic/cht-core/pull/8369

PrjShrestha commented 1 year ago

Update: April 26th: Have been able to successfully set up the CHT development environment. May 6th: Able to run and debug unit tests. Small overview from Mokhtar Currently on hold due to Nepal MOH SMS and Nepal Echis task priorities.

PrjShrestha commented 1 year ago

I have also gone over the code flow and figured out these changes might be necessary. Discussed with @binokaryg and @m5r about this.

  1. Changes in registration.js: Seems registration.js handles the orchestration and is the entry point for SMS parsing so we need to

    • Add a new function "add_phone_number(options)" to registration that will be triggered during form creation:
    • Add it in the triggers constant of registration.js.
    • This function should append the country code by locale by getting it from app_settings as well.
  2. Changes in SMSparser.js Seems the correct parser is chosen at runtime based and it splits the given SMS and based on the index figures out which index represents what. So

    • I should add a new form config that accepts phone numbers

3.. Add a phone_number data type

  1. Parsing and Validation:

    • Check if the phone number already exists.
    • Figure out what do if no phone number is sent.
    • Figure out if we can make phone number optional.
  2. Unit tests and DevQA

m5r commented 1 year ago

@PrjShrestha Just chiming in to make sure we include @medic/quality-assurance as early as possible in the process and can provide feedback along the way

ngaruko commented 1 year ago

Thanks @m5r . @PrjShrestha Ideally, when we add a new feature or improvement, we'd like to add some automated tests to cover the added part. Sometimes it might be a simple as fixing an existing spec to reflect the new change. We have existing e2e tests that cover sms, including rapidpro . Maybe that could be your starting point. It could be confusing atm because we have tests written in protractor and others in webdriverIO, but that's going to change soon. Please feel let the QA know if you need any assistance on this.

PrjShrestha commented 1 year ago

@ngaruko Sure thanks I have added multiple unit tests

Thanks for the heads up. :)

ngaruko commented 1 year ago

@PrjShrestha We might need to add one or 2 specs to existing sms tests. If you could please link me to your PR/branch, I would have a look and suggest what test to add.

PrjShrestha commented 1 year ago

@ngaruko Please find the branch here.

PrjShrestha commented 1 year ago

Update:

This can be done simply by adding a phone_number field with uniquePhone validation:

"property": "phone_number",
                        "translation_key": "",
                        "rule": "uniquePhone('phone_number')",
                        "message": [
                            {
                                "content": "The registration format for {{patient_name}} is incorrect, please ensure that phone number is not already registered",
                                "locale": "en"
                            }
                        ]

This internally checks our "medic-client/_view/contacts_by_phone" view to find pre-registered contacts and errors or continues based upon that.

tatilepizs commented 1 year ago

Hi @PrjShrestha,

Thank you for these changes, and for all the information added in this ticket and in the PR, it is super helpful to understand clearly what the feature is about ✨


Manual test

I don't have a lot of experience with how these SMS config forms work, so I just have a couple of questions that I am sure you can help me with:

  1. I am not 100% sure about where the creation of the patient is configured if it is in the config file or in the core code. I used the config that you used for your tests, please let me know if there is something that I need to add there, but when I sent the SMS with an incorrect phone number or an incorrect age the report is showing the error but the patient was still created. I was expecting to see only the report with the error, not the patient actually created. Can you please clarify?
  2. The age is not saved in the patient information card with the config form that I am using. Can you please help me create one that will save both? the phone number and the age.
Config added - I used the Standard config ``` .json "registrations": [ { "form": "NP", "events": [ { "name": "on_create", "trigger": "add_phone_number", "params": "phone_number", "bool_expr": "doc.fields.phone_number" }, { "name": "on_create", "trigger": "add_patient", "params": "", "bool_expr": "" } ], "messages": [ { "recipient": "reporting_unit", "event_type": "report_accepted", "message": [ { "locale": "en", "content": "Patient {{patient_name}} ({{patient_id}}) added to {{clinic.name}}" } ] } ] }, ] "forms": { "NP": { "meta": { "code": "NP", "translation_key": "forms.np.title", "label": { "en": "New Person with phone_number Registration" } }, "fields": { "patient_age": { "labels": { "tiny": { "en": "Person Age" }, "short": { "en": "Person Age" } }, "position": 0, "type": "integer", "required": true }, "phone_number": { "labels": { "tiny": { "en": "phone number" }, "description": { "en": "phone number" }, "short": { "en": "phone number" } }, "position": 1, "type": "phone_number", "required": true }, "patient_name": { "labels": { "tiny": { "en": "patient_name" }, "description": { "en": "Patient name" }, "short": { "en": "Patient name" } }, "position": 2, "type": "string", "required": true } }, "public_form": false, "use_sentinel": true }, } ```
Patient created with a wrong phone number ![image](https://github.com/medic/cht-core/assets/94494491/bce43756-51e3-4ae1-9e6b-60323b380887) ![image](https://github.com/medic/cht-core/assets/94494491/aeb02a80-d4c4-452d-b23f-91658b58569a)
Patient created a wrong age value ![image](https://github.com/medic/cht-core/assets/94494491/b3eca2b9-e3df-44de-8d6a-ab31a73f6615) ![image](https://github.com/medic/cht-core/assets/94494491/cadbea9e-1f6e-42c3-9daa-d16c60fe389b)
Patient successfully created with no errors but not showing the age in the contact summary ![image](https://github.com/medic/cht-core/assets/94494491/76d14f6b-16fe-453b-a782-029287a64700) ![image](https://github.com/medic/cht-core/assets/94494491/30685649-2010-4d0c-a13a-ea7f384e8ca9)

Automated e2e test

I will suggest adding an individual test to verify the "happy path". It should:

This is an example that you can use, it will be pretty similar, you only will need to change the config, the form message and the asserts. Please let me know if you need any help and I will be happy to help you.

Good luck ✨

garethbowen commented 1 year ago

@tatilepizs Thanks for the testing!

Given this is a blocker for 4.3.0 release would you be comfortable with us adding the e2e test later? I accept that this isn't the best practice.

tatilepizs commented 1 year ago

Yes, that will be fine. It is not a very complicated test, and we can definitely open a separate PR to create it

garethbowen commented 1 year ago

Great! Issue raised here: #8431

tatilepizs commented 1 year ago

Thank you @garethbowen !

PrjShrestha commented 1 year ago

Hi @tatilepizs

  1. I am not 100% sure about where the creation of the patient is configured if it is in the config file or in the core code. I used the config that you used for your tests, please let me know if there is something that I need to add there, but when I sent the SMS with an incorrect phone number or an incorrect age the report is showing the error but the patient was still created. I was expecting to see only the report with the error, not the patient actually created. Can you please clarify?

[Uploading 8204 registration form and .form config…]()

  1. The age is not saved in the patient information card with the config form that I am using. Can you please help me create one that will save both? the phone number and the age.
    • I have removed the age being added to the patient doc because it wasn't a part of this story. I was doing that as a part of testing on my side and gradually forgot to remove it. My bad :)

This is an example that you can use, it will be pretty similar, you only will need to change the config, the form message and the asserts. Please let me know if you need any help and I will be happy to help you.

  • I will surely look into this on Monday but would be grateful if we can skipt it if I cannot complete it by Monday EOD. e2e tests on Windows are an absolute headache. While writing registration trigger tests, most of the times the logs didn't generate, transitions fail for no reason etc 😭 and I talked with various people and just couldn't verify why.

Good luck ✨ Thanks πŸ‘

Thank you for very descriptive feedback and unit test advice :D

tatilepizs commented 1 year ago

@PrjShrestha,

I have the "It works on my machine" syndrome :D

🀣 Probably is something that I am missing. This is the complete app_settings.json file that I am using, it is the one from the standard config with the "NP" form added. I don't have a branch, I just changed that file locally. So, using your branch and the attached file it's my complete local env πŸ™‚

I have removed the age being added to the patient doc because it wasn't a part of this story.

Thanks! πŸ‘

... would be grateful if we can skip it ...

Sure, Gareth created ticket #8431 to work in the e2e test part of the ticket.

PrjShrestha commented 1 year ago

@tatilepizs The env setup sounds right.

Added validations in registrations part of the app_settings for the NP form in the above app settings. Due to missing validations in registrations, patient might still be created. Internally A failure in validation (uniquePhone validation for phone_number field) stops the patient from being created. I had stopped committing app settings midway through working on my ticket as it is not good to do so hence maybe those weren't in the app settings you used as template.

Can you please try with these app settings below which has the added parts. I have modified the form "NP" and the registration entry for the form as well. app_settings.zip

Please kindly try with the latest commit and above app settings. Hopefully it works πŸ˜„

P.S. It seems the config I tried to upload didn't upload in the last comment as json file upload wasn't supported. My bad :)

Seems we have almost 12 hour time diff. If necessary we can catch up from 7:30am to 10:30am or 7:30 pm to 9:30pm your time (Hi from the other side of the world 🌐)

tatilepizs commented 1 year ago

@PrjShrestha,

Thank you for checking! I tried with the latest commit and using the app_settings file that you attached and the person is still created when the phone number is wrong πŸ˜΅β€πŸ’« I don't really understand what I am doing wrong.

I will be online during my night, let me know when you are available to talk.

Thank you!

tatilepizs commented 1 year ago

@PrjShrestha,

Attached is a video with all the processes that I am doing.

Here are the steps that you can see in the video:

video

Let me know if there is anything else I can do to help πŸ™‚

tatilepizs commented 1 year ago

It looks like with the new changes the feature is working fine πŸŽ‰

Using this app_settings.json file I sent three different messages to try to create three different person:

Images attached ![image](https://github.com/medic/cht-core/assets/94494491/456142f5-8c64-49a5-82b9-d2febb04ed1c) ![image](https://github.com/medic/cht-core/assets/94494491/9658c9b4-9ce0-43bf-bf4e-d47da71871a5) ![image](https://github.com/medic/cht-core/assets/94494491/153ca1e3-c16c-41b8-911f-8014309c1b6b) ![image](https://github.com/medic/cht-core/assets/94494491/2fae10f8-5348-4d23-ab23-76f6b46d5864) ![image](https://github.com/medic/cht-core/assets/94494491/56676a66-8d74-46d0-8e70-d12fe373ff1b)

I just have one last question @PrjShrestha, do you know why in the report that failed due to the incorrect phone number it is showing two times the status and the phone number for the Automated reply section? Only in that report, it is shown two times.

image

PrjShrestha commented 1 year ago

@tatilepizs Thank you for the testing snips and description. I am unsure why there are 2 pending messages as you highlighted. I could only see the message being logged once in code and only one message in the outgoing tab as well. image

Sadly, I couldn't figure out the root cause today. Will take a look again tomorrow.

PrjShrestha commented 1 year ago

@tatilepizs The issue of double messages turned out to be a behavior that was present before. So basically what happens is if while adding a patient (using add_patient trigger) we have an error (phone invalid in this case) and end the add_patient midway , the code still checks form config for messages and _appends any message that has "reportaccepted" or empty _"eventtype" messages. Hence we see 2 messages there. First one is the invalid phone message which is expected and second is the empty message which was there due to the config I sent having empty event_type in one of the messages for the form. (Similarly if we add a message which has report_accepted event type, it would show even if there was an invalid_phone error due to the above issue)

Below is my attempt to capture the code, UI and causes in 1 picture. image

Tried resolutions: _Throw error from registration addpatient trigger: I tried hard exiting by throwing an error but it turns out even if we throw an error it will come up as Error in Transition in the errors section of the report in UI which is not ideal as well.

_bool_expr check for errors =0 before adding empty or reportaccepted type messages One way to fix this error was to check errors = 0 in the "bool_expr" for the message of event type "report_accepted" so that only where there are no errors the report accepted message is fired.

image

_Delete patient_Id and check it in bool_expr before adding empty or reportaccepted type messages: Diana suggested to delete the patient Id for any patient that cannot be registered due to errors and checking for empty patient_id in the bool_expr. (i.e. doc.patient_id !== undefined ) check before sending the report_accepted message.

Hence as for all the possible fixes we need to change code and unit tests and that this is a prexisting issue we plan to fix this in another ticket.

cc: @dianabarsan @binokaryg @yrimal

PrjShrestha commented 1 year ago

@tatilepizs Hi Tatiana. Here is an updated config which you can use to retest if necessary. From the previous config

tatilepizs commented 1 year ago

@PrjShrestha,

First I really wanted to thank you for the level of detail about the progress that you added to the ticket, especially in this comment, it is great to see and understand what was happing in the feedback process, I really appreciate that, so thank you again! 🀩

I re-tested it and it worked perfectly, thank you for all the improvements. And since the PR was already approved I think that it is ready to go! 🚒 🚒

Settings file that I used to test: app_settings.json

Test video [video](https://github.com/medic/cht-core/assets/94494491/49b34efd-b117-4b5a-b26f-b4160d3fa01a)
garethbowen commented 1 year ago

Merged. Thank you @PrjShrestha ! This is a great feature.

PrjShrestha commented 1 year ago

@tatilepizs @garethbowen Thank you both for your reviews and feedbacks :)