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
438 stars 209 forks source link

Barcode input can not be re-input #9337

Closed mrjones-plip closed 1 month ago

mrjones-plip commented 1 month ago

Describe the bug

To Reproduce

  1. load a form with a barcode input via app launcher - here's an example form
  2. scan a barcode: image
  3. delete the input from the barcode: image
  4. rescan the barcode

Expected behavior The cleared field in step 3 above gets re-input in step 4. What happens is nothing.

NB - you can scan a 2nd barcode and then scan the 1st barcode as a work around, oddly.

Environment

Additional context Forum discussion on same

mrjones-plip commented 1 month ago

cc @latin-panda

jkuester commented 1 month ago

I was not able to reproduce this behavior in a simple form:

type name label::en hint appearance default calculation
begin_group qr_code Capturing data from a QR code   field-list    
begin_group qr_code_app NO_LABEL   android-app-launcher    
string action NO_LABEL   hidden com.google.zxing.client.android.SCAN  
begin_group qr_code_app_outputs NO_LABEL   android-app-outputs    
string SCAN_RESULT NO_LABEL hidden    
end_group qr_code_app_outputs          
end_group qr_code_app          
string health_card_id Health card ID Health card ID should be a 12 digit number number   ../qr_code_app/qr_code_app_outputs/SCAN_RESULT

Screencast from 2024-08-16 09-20-17.webm

Also, it seems like there is a disconnect between your linked example form and screenshots that you posted. In the linked form, the "Health card ID" field is a calculate which should not actually be displayed in the form.

mrjones-plip commented 1 month ago

Oh - interesting! Thanks for the testing and follow up @jkuester . I've updated the form to be current with screenshots - sorry!

As well - I'll try and grab ya for a chat and report back our findings here.

mrjones-plip commented 1 month ago

Ah - I see a difference in your testing:

your steps are:

  1. scan barcode 1234567890
  2. delete entry
  3. scan barcode 0987654321
  4. barcode is successfully entered

The bug we found is that in step 3 we re-scan the barcode in step 1. You're scanning a different barcode which we agree works (and is an odd work around)

jkuester commented 1 month ago

Okay, after digging into this more, @mrjones-plip and I were able to reproduce the behavior with the simple form I described above (by re-scanning the same barcode). We found the issue is that the health_card_id field gets the value from SCAN_RESULT, but this value update is only triggered if the value stored in SCAN_RESULT changes. So, if I open the form and scan the value 1234, this value gets set for SCAN_RESULT and the xform logic will update any expressions that depend on SCAN_RESULT to reflect this value. This means that health_card_id will get set to 1234. However if the user goes and manually edits health_card_id to be "" (or anything else), the value for health_card_id will change, but not the value for SCAN_RESULT. SCAN_RESULT will still be 1234. Then, when the user re-scans the barcode with the value 1234, the xform's logic knows that the value for SCAN_RESULT did not change, and so it does not trigger an update to any of the dependent expressions. This is why health_card_id does not get updated back to 1234.

The most simple and clean way to avoid this problem is to update the form so that the SCAN_RESULT field is the one shown to the user for editing. Then, the heath_card_id can be a calculate to save the value wherever it actually needs to be in the data hierarchy. This keeps the update flow of the data linear and avoids any kind of circular dependencies between the SCAN_RESULT and health_card_id fields.

type name label::en hint appearance readonly default calculation
begin_group qr_code Capturing data from a QR code   field-list      
begin_group qr_code_app NO_LABEL   android-app-launcher      
string action NO_LABEL   hidden   com.google.zxing.client.android.SCAN  
begin_group qr_code_app_outputs NO_LABEL   android-app-outputs      
string SCAN_RESULT Health card ID Health card ID should be a 12 digit number number      
end_group qr_code_app_outputs            
end_group qr_code_app            
calculate health_card_id           ../qr_code_app/qr_code_app_outputs/SCAN_RESULT
end_group qr_code            

With this new form structure, the user is able to update/clear the health card id value and then re-scan the same QR code as before.

Screencast from 2024-08-16 10-02-46.webm


It is a best practice to keep the data update flow as simple and linear as possible. That being said, this is not always possible for extra complex cases. The ODK spec does support the concept of a trigger column that I think could possibly be useful in cases similar to this. Unfortunately, we do not support trigger yet in the CHT.