Clinic create form breaks when note field is skipped

I have a clinic create form with an init group and a repeat group. Both groups have embedded barcode scanner logic. The specific issue is on line 79 within the init group. If the note field is skipped, the person doc is not created in couch. But if it’s not skipped, then it works fine.

So to reproduce the error:

Register one person (i.e the init group person)
Choose “no” response on line 64
Choose “yes” response on line 66

This will ensure line 77 is skipped. Upon hitting submit, the client profile gets created, but with blank fields. Additionally, if you search for the contact ID in Couch, it won’t appear. I would like to understand why this behavior occurs when line 77 is skipped, and explore possible resolutions.

Okay, wow this turned out to be a deep rabbit hole! :sweat:

TLDR, I believe this is a bug caused by cht-conf functionality. So far I have not been able to figure out a viable workaround (besides manually editing your form xml file…). Hopefully, though, it should not be too hard to fix this in cht-conf. :crossed_fingers:

First, the easy bit: what is NOT causing this. This behavior does not appear to be related to the barcode/android-app-launcher functionality or the repeat group for adding additional contacts.

It DOES appear to be specific to a contact form that has a contact group and an init group that contains a nested group that is non-relevant. When that happens, cht-conf does some manual manipulation of the form xml file that messes with the body section in a way that ends up breaking the evaluation cascade for fields in the contact group. See the cht-conf issue for more details:

2 Likes

@jkuester , thanks for the inputs.

As we want to deploy this next week. Is there a quick workaround I can use? You mentioned manual edit of xml file. Can you share the edited file?

Okay, so here is the form xml that I have edited up like I think should be done to fix #640. You can diff if with your existing xml and see that it is a pretty simple movent in the hierarchy.

I smoke-tested this locally and it seemed to work, but I cannot emphasis enough that this is provided with no promises for guarantees! We have not had time to fully design or test a solution to #640. Under normal circumstances I would not recommend taking manually edited config like this to production. That being said, the scope of this config is limited (to creation of household contacts) and I expect you can get a higher confidence in its functionality through further testing on your end.

This should replace the contents of your forms/contact/clinic-create.xml file. You can still use the cht upload-contact-forms action to upload this config to your server, but you should avoid calling the cht convert-contact-forms action on the clinic-create form as it will overwrite the edited content.

@jkuester , I also have a person-edit form which also behaves weird. Here’s the flow that prevents the form from submission:

Does the client have health card? Yes

You then proceed with scanning a 12 digit QR code. Once the QR code is captured, you then submit the form. If you click submit, you will see that this question appears:

Does the client have the health card ID ?

If you look at the relevancy condition of this question, it is supposed to only appear if the ID is NOT captured. However, it appears for some reason causing the form to not be submitted. Can you please assist me on this?

@iesmail looking at the form config, I think the issue might be caused by a circular dependency in your relevant logic. the barcode group is relevant when ${kym_id}='' and ${kadi_ya_matibabu_id}='' and selected(${has_health_card_id},"yes"). However, the value of kym_id is calculated from the value of SCAN_RESULT which is contained in the barcode group.

The problem is that technically a non-relevant question has no value (it =''). So, one thing that could be happening is that clicking the Submit button triggers a re-evaluation of the of the various form calculations. Due to the circular dependency, maybe some of these evaluations where not done before, or they happened in a different order. Whatever the case, after completing the barcode scan SCAN_RESULT will have a value, which means that kym_id will have a value. BUT, this means that barcode would now be non-relevant (since ${kym_id}='' is false). Since the group contents inherent the non-relevance of the parent group, SCAN_RESULT would be non-relevant and so would actually not be valued…

The only real way to fix this behavior is to try and unravel some of these circular dependencies so that a value for SCAN_RESULT will not cause something to become non-relevant. Digging into your form config, this is going to be a bit tricky since we are dealing with an edit form where we want to be able to set some id values if they are not already populated.

After doing some tinkering, I think perhaps the best place to start would be to add a new field that is something like this:

type name calculation
calculate has_initial_id once(boolean(coalesce(${kym_id}, ${kadi_ya_matibabu_id})))

This field should get set to "true" if either kym_id or kadi_ya_matibabu_id are valued when the form is first opened. But, because of the once, this expression will not be re-evaluated later if either of the id fields changes. Then, basically anywhere in the form where we are checking ${kym_id}='' and ${kadi_ya_matibabu_id}='' can be updated to instead check for ${has_initial_id} = “false”.

@jkuester , thanks for the response. I believe the circular dependency is not the cause here. For instance, if I change the relevancy condition of the barcode group to: ${project_c}="kadiyamatibabu" and (selected(${has_health_card_id},"yes") or (selected(${has_health_card_id},"no") and selected(${is_client_in_kym_app},"no")))

Then the barcode group will appear even after scanning the results. However, upon form submission, the value of calculate field kadi_ya_matibabu becomes empty. This field depends on the text field kadi_ya_matibabu_id_read_only.

If this textfield is also given the same relevancy condition as the barcode group, that means upon form submission, the barcode group and the textfield will both be visible and the textfield will contain the scanned value. If we display the calculate field at this point, it will also contain the textfield value. However, form submission causes the value to disappear.

So I wonder why that happens since both the barcode group (which contains the scan_result) and the textfield are relevant at the point of form submission.

For testing purposes, I also removed the hidden attribute on SCAN_RESULT field but that also did not help.

Another thing I observed is that if :

Do you have health card id? Yes

And then the form is submitted without scanning anything, the couch doc shows this structure:

    "action": "com.google.zxing.client.android.SCAN",
    "android-app-inputs": "",
    "android-app-outputs": {
      "SCAN_RESULT": ""
    }
  },
  "kadi_ya_matibabu_id_read_only": "",
  "kadi_ya_matibabu_id_text_field": "",

If the form is submitted with a scanned barcode id, the above group does not appear, which makes be think maybe it’s related to some CHT issue.

if I change the relevancy condition of the barcode group to: ${project_c}="kadiyamatibabu" and (selected(${has_health_card_id},"yes")

Did you also update the relevant expression for has_health_card_id? That question also depends on ${kym_id}='' and ${kadi_ya_matibabu_id}='' and if it becomes non-relevant, then the barcode group would do so too.

However, upon form submission, the value of calculate field kadi_ya_matibabu becomes empty.

If the form is submitted with a scanned barcode id, the above group does not appear

So, this is why I still think this could all be related to the relevancy of barcode. Take the action question as a point of reference. It should always have that default text value and it should always be recorded in the report as long as barcode is relevant. So, when has_health_card_id = "yes", but nothing has been scanned (so kym_id='' and kadi_ya_matibabu_id='') we see action being populated in the report as expected. However, that fact that it is not there in the report with a scanned barcode indicates that the barcode group became non-relevant.

Then the barcode group will appear even after scanning the results. However, upon form submission, the value of calculate field kadi_ya_matibabu becomes empty.

This is the part where I agree things get super sketchy. I think in general it is hard to predict the “expected” behavior from circular relevant logic, but at least you would want it to be consistent. Unfortunately, I still have not been able to re-create this behavior. Using basically the same person-edit form as what you linked above, I removed hidden from both action and SCAN_RESULT and then opened the form on an Android device. After setting “Do you have health card id?” to “yes”, I see both fields along with the button for triggering the scanner app. But, once I scan a barcode, both fields disappear from the form. It happens even before I press the “Submit” button.

What version of the CHT are you using? I am beginning to wonder if this might be a factor here. I did my tests with 4.11. Here are a couple other tests that it would be useful to do in order to collect some more info about the issue:

  • With the SCAN_RESULT still not hidden, can you add a new page at the end of the form and then see if using the “Next” button to switch to a new page after scanning the barcode causes the SCAN_RESULT to become non-relevant? (So if you go to the third page and then go back to the second one, can you still see SCAN_RESULT?)
  • What happens if you remove the android-app-launcher appearances and just type some input into the SCAN_RESULT field? Do you see similar behavior as with the barcode scanner?

I also face this same issue from many days.