meta-edc 1.2.6__py3-none-any.whl → 1.2.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of meta-edc might be problematic. Click here for more details.

Files changed (40) hide show
  1. meta_analytics/dataframes/constants.py +3 -1
  2. meta_analytics/dataframes/get_glucose_df.py +13 -3
  3. meta_analytics/dataframes/glucose_endpoints/endpoint_by_date.py +27 -5
  4. meta_analytics/dataframes/glucose_endpoints/glucose_endpoints_by_date.py +61 -8
  5. meta_analytics/dataframes/screening/get_screening_df.py +1 -5
  6. meta_consent/migrations/0035_alter_historicalsubjectconsent_consent_definition_name_and_more.py +43 -0
  7. meta_dashboard/navbars.py +2 -6
  8. meta_dashboard/urls.py +5 -5
  9. meta_dashboard/views/screening/listboard_view.py +2 -3
  10. meta_dashboard/views/subject/dashboard/dashboard_view.py +4 -5
  11. meta_dashboard/views/subject/listboard/listboard_view.py +2 -3
  12. meta_edc/settings/debug.py +2 -2
  13. {meta_edc-1.2.6.dist-info → meta_edc-1.2.8.dist-info}/METADATA +5 -5
  14. {meta_edc-1.2.6.dist-info → meta_edc-1.2.8.dist-info}/RECORD +40 -28
  15. {meta_edc-1.2.6.dist-info → meta_edc-1.2.8.dist-info}/WHEEL +1 -1
  16. meta_prn/forms/offschedule_form.py +25 -0
  17. meta_screening/admin/subject_screening_admin.py +4 -3
  18. meta_subject/admin/__init__.py +2 -0
  19. meta_subject/admin/glucose_fbg_admin.py +12 -1
  20. meta_subject/admin/hiv_exit_review_admin.py +55 -0
  21. meta_subject/form_validators/__init__.py +4 -0
  22. meta_subject/form_validators/glucose_fbg_form_validator.py +77 -0
  23. meta_subject/form_validators/glucose_form_validator.py +10 -82
  24. meta_subject/form_validators/hiv_exit_review_form_validator.py +18 -0
  25. meta_subject/form_validators/mixins.py +95 -0
  26. meta_subject/forms/__init__.py +2 -0
  27. meta_subject/forms/glucose_fbg_form.py +1 -46
  28. meta_subject/forms/hiv_exit_review_form.py +13 -0
  29. meta_subject/migrations/0235_glucosefbg_endpoint_today_and_more.py +606 -0
  30. meta_subject/migrations/0236_alter_historicalhivexitreview_other_current_arv_regimen_and_more.py +58 -0
  31. meta_subject/migrations/0237_historicalhivexitreview_singleton_field_and_more.py +68 -0
  32. meta_subject/migrations/0238_historicalhivexitreview_available_and_more.py +88 -0
  33. meta_subject/model_mixins/__init__.py +2 -0
  34. meta_subject/model_mixins/arv_history_model_mixin.py +3 -44
  35. meta_subject/model_mixins/arv_review_model_mixin.py +53 -0
  36. meta_subject/models/__init__.py +2 -0
  37. meta_subject/models/glucose_fbg.py +15 -1
  38. meta_subject/models/hiv_exit_review.py +44 -0
  39. meta_visit_schedule/visit_schedules/phase_three/crfs.py +14 -0
  40. {meta_edc-1.2.6.dist-info → meta_edc-1.2.8.dist-info}/licenses/LICENSE +0 -0
@@ -82,18 +82,18 @@ meta_analytics/README.rst,sha256=TRjju_9l-FoV6YU9qBwlktJDjiK3yfvrSvMo7Rd4mc8,422
82
82
  meta_analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
83
  meta_analytics/constants.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
84
  meta_analytics/dataframes/__init__.py,sha256=naGZtYGJ8BW03XslsFPZe9VZ2fWuU9ew84BB_iBLWxo,1266
85
- meta_analytics/dataframes/constants.py,sha256=D1rxTWPql3W8LalaerSvGgkHotL77e9JlH2O5kwZeTY,791
85
+ meta_analytics/dataframes/constants.py,sha256=AyEbvPGjZ4IVIukutRk5puzcGYLvzDtct7uvdOIqDYE,899
86
86
  meta_analytics/dataframes/get_eos_df.py,sha256=N_7A_Io3KCGj8mrMjUfYP7w6gi7_2Dx2RSG6orQTWp4,1226
87
- meta_analytics/dataframes/get_glucose_df.py,sha256=l-jl-ZecS00JsXpAla5CFuoT1A0HFCs7tBRK9d_wsxw,5131
87
+ meta_analytics/dataframes/get_glucose_df.py,sha256=vr0NqJ9N93d24W1UagL6PRBcMWpsXuL_GORJnmLdKfM,5477
88
88
  meta_analytics/dataframes/get_glucose_fbg_df.py,sha256=derkjnGL25ZdsX6mS6ebQEBlfe_gWOgGnMQVHojuHdg,902
89
89
  meta_analytics/dataframes/get_glucose_fbg_ogtt_df.py,sha256=BfMU1sNj1a4dVOy7yKGESARpb3SNTFxLA-BVB5oZ14Q,657
90
90
  meta_analytics/dataframes/get_last_imp_visits_df.py,sha256=N5tL6gANDr_g5AuNVv_cEN4U-QktLxJUAJaUIW2MiWs,3818
91
91
  meta_analytics/dataframes/glucose_endpoints/__init__.py,sha256=C78zm7_ebYdAQBaldn7LpKlRHvK2ufdT7nFBGZdAMFw,163
92
- meta_analytics/dataframes/glucose_endpoints/endpoint_by_date.py,sha256=BgX6nfBcEFYTMLLfSoMBp7UZJjCr_-ziQBY3CycgNZY,6435
93
- meta_analytics/dataframes/glucose_endpoints/glucose_endpoints_by_date.py,sha256=aflKAcq1zx8osSSrvRvrqJWq-cJTjaeRqaCYV96Z-bs,14112
92
+ meta_analytics/dataframes/glucose_endpoints/endpoint_by_date.py,sha256=bH5BHAsKHWfok9EFmh0kGb5iK1eM7KaZJn3JMTTajGc,7365
93
+ meta_analytics/dataframes/glucose_endpoints/glucose_endpoints_by_date.py,sha256=P2M5B5dwxSW786RVDEtIYZaaQV-PJ_yjgr4e1sHtx1Q,16373
94
94
  meta_analytics/dataframes/screening/__init__.py,sha256=1SegmpN-ceginLsJUADqJzfhLVpAgBmMb53gnKRQsPw,176
95
95
  meta_analytics/dataframes/screening/get_glucose_tested_only_df.py,sha256=jW8eCT2Nu2nBLwcxVg6ftnBk1SbCejSpiURORmi3Aso,648
96
- meta_analytics/dataframes/screening/get_screening_df.py,sha256=QTzFHN7kVk_YXF5l0oqHgcbLi9iEV7ZVA1ksGVlD7fg,6233
96
+ meta_analytics/dataframes/screening/get_screening_df.py,sha256=OU-cLE3FH7cvHoXJxR6RiMS4VcWfOGzP7whlRZ7N3Qg,6153
97
97
  meta_analytics/dataframes/utils.py,sha256=KdM7F0CIZ6RNlaEZonNvkXP-B_cTnl_P2iR2Tjf1XTU,2331
98
98
  meta_analytics/get_tables.py,sha256=cAZ6pCj1z7rnqHvi9QC3OlqdqUVM3j-7Q-7CsgOd-ms,2189
99
99
  meta_analytics/tables/__init__.py,sha256=HIiIBAeVCLSnhBQsVHlg33kNrHJkZdLweqoD7yax6nU,116
@@ -168,6 +168,7 @@ meta_consent/migrations/0031_alter_historicalsubjectconsent_guardian_name_and_mo
168
168
  meta_consent/migrations/0032_alter_historicalsubjectconsent_device_created_and_more.py,sha256=Ty4I6TSHw_rHRKyrYQUMDuZmCSe9_rC4PMD8PM6EdB0,24682
169
169
  meta_consent/migrations/0033_historicalsubjectconsentspfq_subjectconsentspfq.py,sha256=6GKEKT1BbPqqq2U2rHMQWl1VITtB3Inzl3aJGiy26ro,25192
170
170
  meta_consent/migrations/0034_remove_subjectconsentspfq_site_and_more.py,sha256=RbTC6Oo2pOLYaOMkhPtdM612nyZwnOXdWVZ769WGF4o,546
171
+ meta_consent/migrations/0035_alter_historicalsubjectconsent_consent_definition_name_and_more.py,sha256=JnsHyyNGGCv8Ui6B0zIb0V_Fqa9TJJWFoXRe9a21oyI,1241
171
172
  meta_consent/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
172
173
  meta_consent/models/__init__.py,sha256=qDfnpsbAP3hr5oKa80hkr5u9P2PN6KV8P5EMujfgt_8,465
173
174
  meta_consent/models/model_mixins.py,sha256=mEN2gDycLKoZiExM2_H3Dxz8AMAwRSrCq4vu3afr5hA,275
@@ -182,7 +183,7 @@ meta_dashboard/apps.py,sha256=xTdgYwloNayjOFxtsxEjSSrn50CqD_xWMe5B6SWEaO4,313
182
183
  meta_dashboard/locale/lg/LC_MESSAGES/django.po,sha256=k_8rNvTYu-a1KsGfcGsJ-cx65vxa67yhkTJUVu5mP64,836
183
184
  meta_dashboard/locale/sw/LC_MESSAGES/django.po,sha256=lL2_fidRWe_Zv2Q8t_lCfx6GtBNtlSwybL0xm7CLbGA,883
184
185
  meta_dashboard/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
185
- meta_dashboard/navbars.py,sha256=WJvZI5i3IsOA9PLqn_usUHrwMRzr-hILLeCfmDCneP4,1260
186
+ meta_dashboard/navbars.py,sha256=AnyIlPqRQr7UWioLZslioh7CcHknl8CgK9gSQxJ3xXo,1098
186
187
  meta_dashboard/patterns.py,sha256=a9ZY5HSGn_B4Y64hEDpCluxkoTYAo5yHlkwPSzyAvao,39
187
188
  meta_dashboard/templates/meta_dashboard/buttons/add_consent_button.html,sha256=6keqMZ7NrAvcCcl4Dx0dDn0MASj_cAd2IpaXK1ZglK4,447
188
189
  meta_dashboard/templates/meta_dashboard/buttons/dashboard_button.html,sha256=xGuwTLyegM1kVrFkRlDpXkzD7mcRVfSeO6ZVlQ6A_k8,280
@@ -196,7 +197,7 @@ meta_dashboard/templates/meta_dashboard/subject/dashboard.html,sha256=MoH3WSMV2f
196
197
  meta_dashboard/templates/meta_dashboard/subject/listboard.html,sha256=AyVcossXTf7grSrbWaz7Wek12YRixEdddxEQWatSXgs,1398
197
198
  meta_dashboard/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
198
199
  meta_dashboard/templatetags/meta_dashboard_extras.py,sha256=e_6NxocyfQ-ZNuhoRy5X_jKailKkOMNtDL-FVYMANck,3652
199
- meta_dashboard/urls.py,sha256=Nr9bQyY82rzsYecbD2hClGsiAfcT5UQIiwbKSalbHyg,1193
200
+ meta_dashboard/urls.py,sha256=Rfmm6MdCHQTALlySDN4HqX6Uof1lCfZ0EG9aZ02JT8w,1253
200
201
  meta_dashboard/view_utils/__init__.py,sha256=2O0Jvf-bdCU9SZRNhozeHMPax3qHUr-ts24d5khOKQk,335
201
202
  meta_dashboard/view_utils/subject_screening_button.py,sha256=zxeQsELFkC263DlaEEvw6CfKc2SwrEem4r_IuyGe3U0,3220
202
203
  meta_dashboard/views/__init__.py,sha256=7AT2QxwhggrtA_EYvIad6XhoBB8Q8aPi949JBG1lagc,378
@@ -204,12 +205,12 @@ meta_dashboard/views/ae/__init__.py,sha256=UVrz4wSiJInvGsWKwSfpLISXJY98sJpvGSq44
204
205
  meta_dashboard/views/ae/ae_listboard_view.py,sha256=CnHBeQkLJaWYMxP0LBo110OverSiKgncRoqSw0xZaLw,468
205
206
  meta_dashboard/views/ae/death_report_listboard_view.py,sha256=ctYh6AdBdpnW6FIseO5_vqmT0TGgAwR78eVIIledja8,510
206
207
  meta_dashboard/views/screening/__init__.py,sha256=bANJUlyPK9WnDNwocEgy0YPMdDt4EIT9klf5oyYSHoI,71
207
- meta_dashboard/views/screening/listboard_view.py,sha256=DF42XR3ftCHO4vd3cuxtq5ir2NqOmQHGQV6cGObr7is,578
208
+ meta_dashboard/views/screening/listboard_view.py,sha256=Hvd984VClIIU4KBhJ5DgauVNNY546lXruE0HFK7VBW4,563
208
209
  meta_dashboard/views/subject/__init__.py,sha256=gsxTSO68-wnigFiCIJDpi44t26xT0x1ga6yo4bfcT5s,134
209
210
  meta_dashboard/views/subject/dashboard/__init__.py,sha256=Mgx98zq9WcsmOSIc1EleDTDD49XGDf7H6YBwQYhGoo8,71
210
- meta_dashboard/views/subject/dashboard/dashboard_view.py,sha256=yjSnK7M9NukL8T3TK6XBeABM4Xxda6RN912vCmN8MkU,1921
211
+ meta_dashboard/views/subject/dashboard/dashboard_view.py,sha256=nt6hKf6BZtCqRVKDLTwGRS_LTB_XgQvHXhFdxJD7hd8,1894
211
212
  meta_dashboard/views/subject/listboard/__init__.py,sha256=6kBTk_IObcdSWs-K_4zrCDRuLAG_T4V9Ongq57ffJ9U,85
212
- meta_dashboard/views/subject/listboard/listboard_view.py,sha256=bQ5fPqbbkVvPNrmNvIGNZ_GoRIkqUFHk6T7p1dkjr_Y,601
213
+ meta_dashboard/views/subject/listboard/listboard_view.py,sha256=qAyoxgi3alrvHB6o0bYtRqIJ4Om3rQvwpF3ogk2EPKU,586
213
214
  meta_data_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
214
215
  meta_data_manager/apps.py,sha256=xpcMy8CxRMgyWiKmD2JhbfKgPKTgs42wD4AdNwZJANI,233
215
216
  meta_data_manager/data_manager.py,sha256=T9SWFI0iTSDjff-WX-exBNa3I2d985o-JjyCkrHL1FM,167
@@ -230,7 +231,7 @@ meta_edc/model_callers.py,sha256=PjQEW7Kp5HHcUMdmz7dvxg53HvGJHXUKr6QTd-4hsyE,133
230
231
  meta_edc/models.py,sha256=DLA-hDdFszAVNCe1sZqVoLmIXifFW0HeZsipP9D1Ic4,46
231
232
  meta_edc/navbars.py,sha256=Rl2a62elRVTbkGVV9toYwwT388TE1BI7-1j1w2v1m-I,1208
232
233
  meta_edc/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
233
- meta_edc/settings/debug.py,sha256=9QOu1wIjY-HpvyoNAnDByLFt5ao2ZKrb1Nc99A2gF18,1415
234
+ meta_edc/settings/debug.py,sha256=2XRA-0XUf_-Sv3CtAtNZQTg7m4MXQQa3g7dj82HitP4,1415
234
235
  meta_edc/settings/defaults.py,sha256=LlN2sKPiPQuuH-yiY4i6dWATUwMRCpaXK9ZiU0GKMDs,20486
235
236
  meta_edc/settings/live.py,sha256=vhlewV0mOBhnJkU7NWPDRst-By9LM1kVxPFPyGqAHTI,314
236
237
  meta_edc/settings/logging.py,sha256=7RQ2guyuMhK3MtoojmnD0CVqiFZZ6ZT6zc7Rwn0nYGk,2115
@@ -356,7 +357,7 @@ meta_prn/forms/end_of_study_form.py,sha256=Q5ZDQqHB3ejPWCwZCDPBEYsooFB--RzsnGeU9
356
357
  meta_prn/forms/loss_to_followup_form.py,sha256=Y9KZzoUy9tjRI37h0wgZoy0sSSWbqLn1JWAYTs8u4xU,1333
357
358
  meta_prn/forms/off_study_medication_form.py,sha256=VP8SF8V33L0DcPaiTExybXo88j_mCEPUz6cXQMIW2e8,2327
358
359
  meta_prn/forms/offschedule_dm_referral_form.py,sha256=DH7EsSmxcu8GVamu4DFVScCXJ0gQDHjU5ajsvidP_1E,1106
359
- meta_prn/forms/offschedule_form.py,sha256=xdJKEZv_5vMe9yUeofAUZBcjEnGCKjxXy0C_jNixWTU,1112
360
+ meta_prn/forms/offschedule_form.py,sha256=J_u76ZHI3S_yryofDa2tjfs5RRDs4M0aolT4ZiiWJUs,2086
360
361
  meta_prn/forms/offschedule_pregnancy_form.py,sha256=5yC8Sc-VSBdkm4rOnkDVsS2tbqe3OzE-m6k12156nUI,1101
361
362
  meta_prn/forms/pregnancy_notification_form.py,sha256=6lHUKD5spdBAaWXjilIq_DrF8DJ3rJ7uOGhvrhjWHPQ,4813
362
363
  meta_prn/forms/protocol_incident_form.py,sha256=HjyUChzYSH5QDKq9vUUBLNdy52I3ZKsnlKCgW0KUOs4,231
@@ -606,7 +607,7 @@ meta_screening/admin/screening_part_one_admin.py,sha256=fpIYr9iz33_UpAmWIGMe4uF9
606
607
  meta_screening/admin/screening_part_three_admin.py,sha256=dkt325ZJkwu9i4HUckMjjh41HVL47pwmrzEUlktMC8M,2567
607
608
  meta_screening/admin/screening_part_two_admin.py,sha256=rggsgB8UTPK9scms1D71j_EXJ4aYXSz8nWHZ1xAY_Ck,1251
608
609
  meta_screening/admin/subject_refusal_admin.py,sha256=Z2Wjh_mrZ5Ub3JFsLHYK1GKSephM55hmQRRmpsDOHYc,2302
609
- meta_screening/admin/subject_screening_admin.py,sha256=qfHQhILHY6Q93UtK9iWCRxkuOYKYiG67T6FJqjEo0t0,7218
610
+ meta_screening/admin/subject_screening_admin.py,sha256=DBuNjdhVTaKFwdkr5SYV6UxCNdwOS1jIboN2BIBkRhE,7302
610
611
  meta_screening/admin_site.py,sha256=tncjQR99ll80ncle8mMl6k1LdctI50RkwT0u7VQFjC8,173
611
612
  meta_screening/apps.py,sha256=p3QN1JpvGimrEBTPAaf6vr9IPl_877AJcSvCqnLJDfw,543
612
613
  meta_screening/baker_recipes.py,sha256=5PvEj8_kEznuIKHb_AgawCd8eBLiTp1Bbq-I0NhPF38,1738
@@ -723,7 +724,7 @@ meta_sites/models.py,sha256=DLA-hDdFszAVNCe1sZqVoLmIXifFW0HeZsipP9D1Ic4,46
723
724
  meta_sites/sites.py,sha256=H26Erar3_fLVl5wf2ILDM5C6wGEoi0dQbiSPmzb9OGw,1625
724
725
  meta_subject/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
725
726
  meta_subject/action_items.py,sha256=l7Bw4m0Hu72bemH70UToI__VCERz8YKEKcsWCL6BJxk,6804
726
- meta_subject/admin/__init__.py,sha256=04MeBKUNsTc1DKJDE7r9w-KfZWxBEB-QLBIiazhzzFs,2779
727
+ meta_subject/admin/__init__.py,sha256=RqjzQhqAVl1zmkmrkIoETxfwN4ZuKbH83r_dNtYxk-4,2859
727
728
  meta_subject/admin/autocomplete_admin.py,sha256=bVxma7KTHhKHWqLPxbP2GwiGcHeBUyMutTDXZ2RomEY,1158
728
729
  meta_subject/admin/birth_outcome_admin.py,sha256=76hwS4wIbuFpxAvIoQwjVqyr4znVGhWOnuKBuk1FIZ8,3242
729
730
  meta_subject/admin/blood_results/__init__.py,sha256=24WaqyGYCj3F-8amy7HFEwet1Z1ZHgsVvdSrWmmGvVs,546
@@ -747,11 +748,12 @@ meta_subject/admin/fieldsets.py,sha256=NjFKDAMvzePa9TijR_-zTLsDbawfBQDuws2BzWDze
747
748
  meta_subject/admin/followup_examination_admin.py,sha256=9euSMg0TjlmA3kSWN6HS2Cg0f4FCnf_5PXaZcCPbK6g,5282
748
749
  meta_subject/admin/followup_vitals_admin.py,sha256=a2bwBwFsQ1sMmnBgmeCOEv6wNCXuKeIqIwEZB-Lqt_E,2297
749
750
  meta_subject/admin/glucose_admin.py,sha256=5K9rMFE8jCZRTJBsORJi0aKJF1xizh0303iwdJCrTLM,2902
750
- meta_subject/admin/glucose_fbg_admin.py,sha256=qEvAlw_F6Ee2_iGUzRTTyRJYTPduHgqivngphR6sil8,2413
751
+ meta_subject/admin/glucose_fbg_admin.py,sha256=DbfO2opLwBJfQskYhGwN_i50qbzB6brZFtHCU2gh-dU,2810
751
752
  meta_subject/admin/health_economics/__init__.py,sha256=t0vFauE3auk7FESIvk5tFjc3-Jtshl9eiAJswQBG1gw,212
752
753
  meta_subject/admin/health_economics/health_economics_simple_admin.py,sha256=nL0CvjWQsFsR19ine14iItt9e8Px53Ln_tSppMN8UQ4,1053
753
754
  meta_subject/admin/health_economics/health_economics_update_admin.py,sha256=mtsd1fJ8yvTK1eol5f03fZ8jk1afeYKSxEydPGmma7w,3905
754
755
  meta_subject/admin/hepatitis_test_admin.py,sha256=v81v96eoH2rCJabf1YB-JXXUxqZftMaoq24ZoTZszr4,1420
756
+ meta_subject/admin/hiv_exit_review_admin.py,sha256=6PUGJkUOGgD5NEx4sLc488ISbtDA3MGCUBoIFIMHryQ,1507
755
757
  meta_subject/admin/list_filters.py,sha256=j_HkCiXqWHJ_HrZjK7doxJAEJYFy2Kbjy2Md9r707tg,2328
756
758
  meta_subject/admin/malaria_test_admin.py,sha256=qLa5StnwN_2ytNYykXcLKwSJn6tc7e0-myH2cNHbZ_c,492
757
759
  meta_subject/admin/medication_adherence_admin.py,sha256=mhKGcDHUParW6BATj9S2wa5Th3u_ndQRKVNnjYcxKyM,543
@@ -774,16 +776,19 @@ meta_subject/apps.py,sha256=iAQ8lizUpKa4gJnCGkTsuRQPtGWmSjnshZn8rZUguO8,289
774
776
  meta_subject/baker_recipes.py,sha256=KEJQTjNH47KcGCR_2OxDwmSKhAWhmjiD3YsnqeqkzFU,2816
775
777
  meta_subject/choices.py,sha256=lFseBsxliIRshCmqsIwdPnYXs1p_WT5D_Dfn2PcWONs,6754
776
778
  meta_subject/constants.py,sha256=6rpHsHj3CPV7ntdWxYScRhPVoj4YIxX2lUZdZ9lrFN0,704
777
- meta_subject/form_validators/__init__.py,sha256=2g1unLOkE4Wj1ZrWkXSdnZzYnV0kggn_SCpMrhnc_Rg,840
779
+ meta_subject/form_validators/__init__.py,sha256=OZXAIRmojQVrY_oANAnTBhi3wNzOPf7hnWXfqpGRrks,1040
778
780
  meta_subject/form_validators/birth_outcomes_form_validator.py,sha256=vujgXKIW4z8bJ536_9uBhETlbChhUvA3Rj5H8zR3UfI,349
779
781
  meta_subject/form_validators/delivery_form_validator.py,sha256=mmi6mnr-DLa93uGMoqud_J1LuM1nPyu-VcNyIwEOXk8,3205
780
782
  meta_subject/form_validators/dm_endpoint_form_validator.py,sha256=KKt2G1UVzeCgpKtyHsJWJ-h-9Ags2Ld8Rfb-Pnwi_F0,1507
781
783
  meta_subject/form_validators/dm_followup_form_validator.py,sha256=ACUbvOrKj7_DqGxbKX4kMenI05kG4EUGQu0e6Cfbxt8,7981
782
784
  meta_subject/form_validators/egfr_drop_notification_form_validator.py,sha256=y5MUdRriMo8C2Qj_yzebDWsDkjQsFhcqTGrP8tBuhfA,530
783
785
  meta_subject/form_validators/followup_examination_form_validator.py,sha256=NS3Sa-bwC_HEe-CmezkFrbbjPanLe9p1v5ZOFspqgxg,4241
784
- meta_subject/form_validators/glucose_form_validator.py,sha256=azIttaercmdE2-KM8hrlAzBmH3LHknrIxQ-o_s1kYcE,3979
786
+ meta_subject/form_validators/glucose_fbg_form_validator.py,sha256=aCi-g0jWJwszTykl2Goo7i7U9uxVFuCGxVBhMau_L2g,3138
787
+ meta_subject/form_validators/glucose_form_validator.py,sha256=PhBYjvuukCnzeEwrkoj_1tVzBUZRSUbOt2VCKi-o804,1012
785
788
  meta_subject/form_validators/health_economics_form_validator.py,sha256=kp-LQU4ydBXlnYFt-0xKuVSb8Y4irlhz9d_X8ppvWgE,250
786
- meta_subject/forms/__init__.py,sha256=LaxPRgHKMfmEWYnxHFbPkVFGSSNVrelG8dL2x49M5oU,2776
789
+ meta_subject/form_validators/hiv_exit_review_form_validator.py,sha256=NTdcStOVExItrYRCfrensAF17RNyBRtXPYPfIK4ZA5Y,634
790
+ meta_subject/form_validators/mixins.py,sha256=bNwCau8TSinslk8NTDq0sJ2HmBlSyvwBJFuvdd6SZAY,3610
791
+ meta_subject/forms/__init__.py,sha256=KOuMcL66-FN192az3dDSmzBb7X4r1RE2HM2zpv4PNbQ,2853
787
792
  meta_subject/forms/birth_outcomes_form.py,sha256=qqhZNQKiYk8C8CFebZTQB0hOm4ONrgkTG7hfuK7kW-o,374
788
793
  meta_subject/forms/blood_results/__init__.py,sha256=DYs2J30cgTPxvY9qDuKfr_kF_muoZ1iVmpu_I3wLpdM,528
789
794
  meta_subject/forms/blood_results/blood_results_fbc_form.py,sha256=g6m0HE9I3DIxDPgk6TZUPVU-vliOb3Fiqe3kDyN7h38,714
@@ -802,12 +807,13 @@ meta_subject/forms/egfr_drop_notification_form.py,sha256=qQ5Q1aeGqzohD5FjBto1ThM
802
807
  meta_subject/forms/eq53d3l_form.py,sha256=EE67-CAIRNKZCKpmQolC8wgL5MMIjXlkn5SXe3XdhN0,508
803
808
  meta_subject/forms/followup_examination_form.py,sha256=PATGiGn1AXmK1koXy1QjMvgn43KuZn7yyZIrA_8sPXk,502
804
809
  meta_subject/forms/followup_vitals_form.py,sha256=TaAOa6M_SzIctmOn1A4qECOgqC97Q3yDO1gIAVZUk9k,1321
805
- meta_subject/forms/glucose_fbg_form.py,sha256=H1cEIkGUBe49nnhDd7x62Tr-3nrZg5Hn62GAMvIJZkU,2372
810
+ meta_subject/forms/glucose_fbg_form.py,sha256=XvT8Tbp9DZcYNy5IQQfu2r8QtHoMzB015wH40Y_MiC0,347
806
811
  meta_subject/forms/glucose_form.py,sha256=3PjxVaUEjswCq-m-LGz4Gj6dX1EDVdFs6UQH99ekMBs,442
807
812
  meta_subject/forms/health_economics/__init__.py,sha256=9R06pGhU2QsorMIMpJZb2UYfq8j-Dogb8UsXkmW6EGI,206
808
813
  meta_subject/forms/health_economics/health_economics_simple_form.py,sha256=MlPppvF8lrka9hAzmAV7aiyerjtVihxmOWpbTF-k5P8,392
809
814
  meta_subject/forms/health_economics/health_economics_update_form.py,sha256=gpdBcJxSXG8hp34JWdTQHrKT2pXeuBGAF503zCXLyEs,308
810
815
  meta_subject/forms/hepatitis_test_form.py,sha256=d4ZZuB0cGiuTHrbhkLnkyMmnOKs76op-J4CFATDJML4,794
816
+ meta_subject/forms/hiv_exit_review_form.py,sha256=xRk900fPE_FTafeN5cAmzZcgds-XPPKD-F6ra-XiNko,362
811
817
  meta_subject/forms/malaria_test_form.py,sha256=xQeF-wBq06anAU9it0lLvQhIxJoWoFc_bCogzp1YwQU,365
812
818
  meta_subject/forms/medication_adherence_form.py,sha256=yjDmr3uIDwQXnph6mkCgluYEJgFCpXzUPoTVbivba0Y,865
813
819
  meta_subject/forms/mixins.py,sha256=MdiCuVB5pyD0ExZs48t0NiL_BiQD8pVwMoWbjHR3WBA,2084
@@ -1071,14 +1077,19 @@ meta_subject/migrations/0231_alter_historicalmedicationadherence_consent_model_a
1071
1077
  meta_subject/migrations/0232_alter_patienthistory_concomitant_conditions_and_more.py,sha256=vX0wJmbLQSg7JYnvzAt3zA20bfPz1AnxNpodKAxdYhM,43686
1072
1078
  meta_subject/migrations/0233_historicalspfq_spfq.py,sha256=U8imocD_gtCGTC0zUNt6UZlqZYBUtUNB7cEdFxBbnjA,46072
1073
1079
  meta_subject/migrations/0234_remove_spfq_site_remove_spfq_subject_visit_and_more.py,sha256=s_1aOSihYNqca-oVYWxiC19joGtOgvB4nz0qtEqmdwQ,584
1080
+ meta_subject/migrations/0235_glucosefbg_endpoint_today_and_more.py,sha256=ctq-NpqrIuLBeGd21sl3L_bTBS5j1uVOUCCy8Uuzohs,24072
1081
+ meta_subject/migrations/0236_alter_historicalhivexitreview_other_current_arv_regimen_and_more.py,sha256=YU8IC-nONmzwV6jJ3P-f5jpp9HUEMyKKhRpWgl8HjHo,1883
1082
+ meta_subject/migrations/0237_historicalhivexitreview_singleton_field_and_more.py,sha256=V_6u5YMGCRYgwrwqJpQam53fZcYWHHWDRWBhPtTkTuw,2115
1083
+ meta_subject/migrations/0238_historicalhivexitreview_available_and_more.py,sha256=r2kSbcMSbKzQswJSfMP1CqRAZSdDayHjjQzsv6p-D3I,2900
1074
1084
  meta_subject/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1075
- meta_subject/model_mixins/__init__.py,sha256=fWZpFJ_Ex-TOJFjgSGjcrquKSCenCh_K9Hiy8QUg36o,439
1076
- meta_subject/model_mixins/arv_history_model_mixin.py,sha256=6ILacF2koyYmwZIFHmmQO1uIT1eWzrahXxhAlxpQiX0,2898
1085
+ meta_subject/model_mixins/__init__.py,sha256=2Dae7t4r2f3YubLevk_HH_GVTDrZREOpCDDMYthLV5U,522
1086
+ meta_subject/model_mixins/arv_history_model_mixin.py,sha256=Ync4oLFng1OQW3pVxNxbEhKplWVNpUY5BiXy47lv6pk,1573
1087
+ meta_subject/model_mixins/arv_review_model_mixin.py,sha256=rzVQgOsUsapeRb_zsITS-qVXEOOPiyn1r8sUCQmcIqk,1660
1077
1088
  meta_subject/model_mixins/crf_model_mixin.py,sha256=UK1ycbYwaZ8LSNTJm74QJ5c-01HDXOApDy5k9LM4RKM,248
1078
1089
  meta_subject/model_mixins/crf_with_action_model_mixin.py,sha256=q1Q16YyPjQlpDtCPOXRkO5C7Vr7JO_QL8xWC48Uz33M,298
1079
1090
  meta_subject/model_mixins/search_slug_model_mixin.py,sha256=mEN2gDycLKoZiExM2_H3Dxz8AMAwRSrCq4vu3afr5hA,275
1080
1091
  meta_subject/model_mixins/vitals_fields_model_mixin.py,sha256=Uimo-sQS-l4I3KyHej8t0_49mT2UakMKCbO8giYUMQw,2205
1081
- meta_subject/models/__init__.py,sha256=NXw6Ba2QlYL7ZjZoWeoS1A5g6R3ONnOKtFEH8ltDTvg,2974
1092
+ meta_subject/models/__init__.py,sha256=TThRJzFZbrMHVkLV4bXOZBVEtVTd1sVz0MwGfkjqph8,3038
1082
1093
  meta_subject/models/birth_outcomes.py,sha256=DQp-8Cv5ZWBuaGdiYlL1V3uJaL6H2tf9gYPfYcMTCs8,3142
1083
1094
  meta_subject/models/blood_results/__init__.py,sha256=F2jncEUtvrb4G9v5V6p3gSi4dI721CFVCImdJ9qFHmQ,530
1084
1095
  meta_subject/models/blood_results/blood_results_fbc.py,sha256=kkOqCsqeIvCf2rw7vHGWMCEgo1_yiMDtTOi44aKtBro,1324
@@ -1101,13 +1112,14 @@ meta_subject/models/eq5d3l.py,sha256=itRrbfzL7Jsg9u7ml0SXwsw4nMoMcNyG0-YCD2VeXB0
1101
1112
  meta_subject/models/followup_examination.py,sha256=xcPcqMZPA3BQWH86WYiPyskbSW56swcUKq-uY-Gvsy8,8076
1102
1113
  meta_subject/models/followup_vitals.py,sha256=pBZt4xrw7eVUfHBRtotUh9orJdNjOGxSuNa6JeWQRqA,903
1103
1114
  meta_subject/models/glucose.py,sha256=23egMXtmZELPDLU7KYaa60hi7z9bCpyJeFjexwiiIEg,2252
1104
- meta_subject/models/glucose_fbg.py,sha256=MzTPX1sVlp_ypqLmhsurVUV-Ks8XTIMHJy5MBjAFYOM,1588
1115
+ meta_subject/models/glucose_fbg.py,sha256=I_xSRHTzRrH2M9fScA85AoKGHTDlKbN_3Nn-oJPVj_A,2107
1105
1116
  meta_subject/models/glucose_review.py,sha256=bCnSBe_C3LeBy1XrZpV9rv-hOk8onZ_Tl37t7dqm-sw,450
1106
1117
  meta_subject/models/health_economics/__init__.py,sha256=J557vTjzK1EvUAM4mx9zDVQ7Zr0W25stnWXz_zE2a-c,245
1107
1118
  meta_subject/models/health_economics/health_economics.py,sha256=pjEbz3d6s-Cy2DEPZnGcd8KjFc27pVed9D6vr3eYLVg,9709
1108
1119
  meta_subject/models/health_economics/health_economics_simple.py,sha256=w46TrjNvfk736IjtZ8lrN0H3is_ddGRUq8v6MgSqoBY,711
1109
1120
  meta_subject/models/health_economics/health_economics_update.py,sha256=gzbu2lpVr9txwYUVfYKADgE0Om1YkNfrVPcwLczbNYc,3334
1110
1121
  meta_subject/models/hepatitis_test.py,sha256=_jfDlR_spt7h4KGsMDxmobgAaToKiAZdLGIXCqfH60o,1852
1122
+ meta_subject/models/hiv_exit_review.py,sha256=FCqZ_3DYlGQKC2Nd9E6lPQ_Pq9JG-ez0VLDFizlyWzQ,1371
1111
1123
  meta_subject/models/malaria_test.py,sha256=4gQNBnvLDv70rjRcFBOpLPmYL8eeuqs0lRsJ7LrFqHM,343
1112
1124
  meta_subject/models/medication_adherence.py,sha256=7a9WQAvgin2WeSgznNDNdet69JTT7DO61hfMseF4cVY,399
1113
1125
  meta_subject/models/mnsi.py,sha256=tD6Sh4aQ1Oszt3SLzhgOLwxXr8zW8jvEEETEJP75Hdc,284
@@ -1139,14 +1151,14 @@ meta_visit_schedule/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
1139
1151
  meta_visit_schedule/models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1140
1152
  meta_visit_schedule/visit_schedules/__init__.py,sha256=3tZOHj7JFj31gRxrULgPl8AWSvBb36i7uhx46C8x0T0,381
1141
1153
  meta_visit_schedule/visit_schedules/phase_three/__init__.py,sha256=lnBC3j17W54TQv8_tKKWmyp_QtSTeaA3UKGN_yRcOAI,116
1142
- meta_visit_schedule/visit_schedules/phase_three/crfs.py,sha256=JcAHxtui3ZEnr7wjih34V8yuTUJ6ZVWTDFANabYYovo,17563
1154
+ meta_visit_schedule/visit_schedules/phase_three/crfs.py,sha256=ZOZN44IMuAq2cHJrTbSqcCoq5oLS98bQMLSgkSfma-4,18609
1143
1155
  meta_visit_schedule/visit_schedules/phase_three/crfs_pregnancy.py,sha256=_I6IVLMC3-KlpI86eii790mlx-p2vxWxvNRKD927rXo,169
1144
1156
  meta_visit_schedule/visit_schedules/phase_three/requisitions.py,sha256=Noeki8zX2MCwQVmCCWfuOyh_aN4YC-cyhUmrAZP8d5g,4579
1145
1157
  meta_visit_schedule/visit_schedules/phase_three/schedule.py,sha256=LU1HRaV6o1UeKB2NoHKkI5R9w7UhVSYw550g9jDZ6_c,8197
1146
1158
  meta_visit_schedule/visit_schedules/phase_three/schedule_dm_referral.py,sha256=q12p5wXc2D7lSiJVBnoSQw8Q3vL6uDx1t3PuDJO-Z-U,1735
1147
1159
  meta_visit_schedule/visit_schedules/phase_three/schedule_pregnancy.py,sha256=bEpbpCX3vfZmnsqudr0z8PU5kiaX4ws1sO5Im98Mo28,1106
1148
1160
  meta_visit_schedule/visit_schedules/phase_three/visit_schedule.py,sha256=ak4qazeKlpIlvpqrK9hDDO0fwWuWyvb4Ec-JU31IJxc,654
1149
- meta_edc-1.2.6.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
1150
- meta_edc-1.2.6.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
1151
- meta_edc-1.2.6.dist-info/METADATA,sha256=8TFazXkaKloEytDbSHG700VM-OWMZlxPKfvP48fG4sE,5163
1152
- meta_edc-1.2.6.dist-info/RECORD,,
1161
+ meta_edc-1.2.8.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
1162
+ meta_edc-1.2.8.dist-info/WHEEL,sha256=M6du7VZflc4UPsGphmOXHANdgk8zessdJG0DBUuoA-U,78
1163
+ meta_edc-1.2.8.dist-info/METADATA,sha256=hfh32Dy7w0cp-riFAigC_8mS_59qSD9Q3dV1iP6EX90,5163
1164
+ meta_edc-1.2.8.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: uv 0.8.24
2
+ Generator: uv 0.9.5
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,5 +1,8 @@
1
1
  from django import forms
2
+ from django.core.exceptions import ObjectDoesNotExist
2
3
  from edc_action_item.forms.action_item_form_mixin import ActionItemFormMixin
4
+ from edc_appointment.constants import MISSED_APPT
5
+ from edc_appointment.models import Appointment
3
6
  from edc_form_validators.form_validator import FormValidator
4
7
  from edc_form_validators.form_validator_mixins import FormValidatorMixin
5
8
  from edc_model_form.mixins import BaseModelFormMixin
@@ -7,6 +10,8 @@ from edc_prn.modelform_mixins import PrnFormValidatorMixin
7
10
  from edc_sites.forms import SiteModelFormMixin
8
11
  from edc_visit_schedule.modelform_mixins import OffScheduleModelFormMixin
9
12
 
13
+ from meta_subject.models import HivExitReview
14
+
10
15
  from ..models import OffSchedule
11
16
 
12
17
 
@@ -31,6 +36,26 @@ class OffScheduleForm(
31
36
  widget=forms.TextInput(attrs={"readonly": "readonly"}),
32
37
  )
33
38
 
39
+ def clean(self):
40
+ try:
41
+ HivExitReview.objects.get(
42
+ subject_visit__subject_identifier=self.get_subject_identifier()
43
+ )
44
+ except ObjectDoesNotExist as e:
45
+ # if last visit was missed do not require
46
+ last_appointment = (
47
+ Appointment.objects.filter(
48
+ subject_identifier=self.get_subject_identifier(),
49
+ subjectvisit__isnull=False,
50
+ )
51
+ .order_by("appt_datetime")
52
+ .last()
53
+ )
54
+ if last_appointment.appt_timing != MISSED_APPT:
55
+ raise forms.ValidationError(
56
+ "Hiv Exit Review CRF is required before taking subject off schedule."
57
+ ) from e
58
+
34
59
  class Meta:
35
60
  model = OffSchedule
36
61
  fields = "__all__"
@@ -31,7 +31,8 @@ class SubjectScreeningAdmin(ModelAdminSubjectDashboardMixin, SimpleHistoryAdmin)
31
31
  form = SubjectScreeningForm
32
32
  list_per_page = 15
33
33
  post_url_on_delete_name = "screening_listboard_url"
34
- subject_listboard_url_name = "screening_listboard_url"
34
+ subject_listboard_url_name = "screening_listboard_url" # :FIXME is this ok?
35
+ screening_listboard_url_name = "screening_listboard_url"
35
36
 
36
37
  additional_instructions = (
37
38
  "Patients must meet ALL of the inclusion criteria and NONE of the "
@@ -174,7 +175,7 @@ class SubjectScreeningAdmin(ModelAdminSubjectDashboardMixin, SimpleHistoryAdmin)
174
175
  def eligibility_status(self, obj=None):
175
176
  eligibility = MetaEligibility(obj, update_model=False)
176
177
  screening_listboard_url = reverse(
177
- url_names.get(self.subject_listboard_url_name), args=(obj.screening_identifier,)
178
+ url_names.get(self.screening_listboard_url_name), args=(obj.screening_identifier,)
178
179
  )
179
180
  context = dict(
180
181
  title="Go to screening listboard",
@@ -197,7 +198,7 @@ class SubjectScreeningAdmin(ModelAdminSubjectDashboardMixin, SimpleHistoryAdmin)
197
198
  kwargs=self.get_subject_dashboard_url_kwargs(obj),
198
199
  )
199
200
  except NoReverseMatch:
200
- url = reverse(url_names.get("screening_listboard_url"), kwargs={})
201
+ url = reverse(self.get_screening_listboard_url_name(), kwargs={})
201
202
  context = dict(
202
203
  title="Go to screening listboard",
203
204
  url=f"{url}?q={obj.screening_identifier}",
@@ -19,6 +19,7 @@ from .glucose_admin import GlucoseAdmin
19
19
  from .glucose_fbg_admin import GlucoseFbgAdmin
20
20
  from .health_economics import HealthEconomicsSimpleAdmin, HealthEconomicsUpdateAdmin
21
21
  from .hepatitis_test_admin import HepatitisTestAdmin
22
+ from .hiv_exit_review_admin import HivExitReviewAdmin
22
23
  from .malaria_test_admin import MalariaTestAdmin
23
24
  from .medication_adherence_admin import MedicationAdherenceAdmin
24
25
  from .mnsi_admin import MnsiAdmin
@@ -57,6 +58,7 @@ __all__ = [
57
58
  "HealthEconomicsSimpleAdmin",
58
59
  "HealthEconomicsUpdateAdmin",
59
60
  "HepatitisTestAdmin",
61
+ "HivExitReviewAdmin",
60
62
  "MalariaTestAdmin",
61
63
  "MedicationAdherenceAdmin",
62
64
  "MnsiAdmin",
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from django.contrib import admin
4
4
  from django.contrib.admin import SimpleListFilter
5
+ from django.template.loader import render_to_string
5
6
  from django_audit_fields import audit_fieldset_tuple
6
7
  from edc_crf.fieldset import crf_status_fieldset
7
8
  from edc_model_admin.history import SimpleHistoryAdmin
@@ -40,11 +41,21 @@ class GlucoseFbgAdmin(CrfModelAdminMixin, SimpleHistoryAdmin):
40
41
  )
41
42
  },
42
43
  ),
44
+ (
45
+ "Endpoint review",
46
+ {
47
+ "description": render_to_string(
48
+ "meta_subject/endpoint_review_instructions.html", context={}
49
+ ),
50
+ "fields": ("endpoint_today",),
51
+ },
52
+ ),
43
53
  (
44
54
  "Confirmation appointment",
45
55
  {
46
56
  "description": (
47
- "If blood glucose value is >= 7.0 mmol/L, schedule an "
57
+ "If patient has not reached the endpoint and the blood glucose "
58
+ "value is >= 7.0 mmol/L, schedule an "
48
59
  "appointment within 1 week to confirm"
49
60
  ),
50
61
  "fields": ("repeat_fbg_date",),
@@ -0,0 +1,55 @@
1
+ from __future__ import annotations
2
+
3
+ from django.contrib import admin
4
+ from django_audit_fields import audit_fieldset_tuple
5
+ from edc_crf.fieldset import crf_status_fieldset
6
+ from edc_model_admin.history import SimpleHistoryAdmin
7
+
8
+ from ..admin_site import meta_subject_admin
9
+ from ..forms import HivExitReviewForm
10
+ from ..models import HivExitReview
11
+ from .modeladmin import CrfModelAdminMixin
12
+
13
+
14
+ @admin.register(HivExitReview, site=meta_subject_admin)
15
+ class HivExitReviewAdmin(CrfModelAdminMixin, SimpleHistoryAdmin):
16
+ autocomplete_fields = ("current_arv_regimen",)
17
+
18
+ form = HivExitReviewForm
19
+
20
+ fieldsets = (
21
+ (
22
+ None,
23
+ {
24
+ "fields": (
25
+ "subject_visit",
26
+ "report_datetime",
27
+ "available",
28
+ "not_available_reason",
29
+ )
30
+ },
31
+ ),
32
+ (
33
+ "HIV and ARVs",
34
+ {
35
+ "fields": (
36
+ "viral_load",
37
+ "viral_load_date",
38
+ "cd4",
39
+ "cd4_date",
40
+ "current_arv_regimen",
41
+ "other_current_arv_regimen",
42
+ "current_arv_regimen_start_date",
43
+ )
44
+ },
45
+ ),
46
+ ("Comment", {"fields": ("comment",)}),
47
+ crf_status_fieldset,
48
+ audit_fieldset_tuple,
49
+ )
50
+
51
+ list_filter = ("available",)
52
+
53
+ radio_fields = { # noqa: RUF012
54
+ "available": admin.VERTICAL,
55
+ }
@@ -4,8 +4,10 @@ from .dm_endpoint_form_validator import DmEndpointFormValidator
4
4
  from .dm_followup_form_validator import DmFollowupFormValidator
5
5
  from .egfr_drop_notification_form_validator import EgfrDropNotificationFormValidator
6
6
  from .followup_examination_form_validator import FollowupExaminationFormValidator
7
+ from .glucose_fbg_form_validator import GlucoseFbgFormValidator
7
8
  from .glucose_form_validator import GlucoseFormValidator
8
9
  from .health_economics_form_validator import HealthEconomicsFormValidator
10
+ from .hiv_exit_review_form_validator import HivExitReviewFormValidator
9
11
 
10
12
  __all__ = [
11
13
  "BirthOutcomesFormValidator",
@@ -14,6 +16,8 @@ __all__ = [
14
16
  "DmFollowupFormValidator",
15
17
  "EgfrDropNotificationFormValidator",
16
18
  "FollowupExaminationFormValidator",
19
+ "GlucoseFbgFormValidator",
17
20
  "GlucoseFormValidator",
18
21
  "HealthEconomicsFormValidator",
22
+ "HivExitReviewFormValidator",
19
23
  ]
@@ -0,0 +1,77 @@
1
+ from decimal import Decimal
2
+
3
+ from edc_constants.constants import NO, PENDING, YES
4
+ from edc_crf.crf_form_validator import CrfFormValidator
5
+ from edc_form_validators import INVALID_ERROR
6
+ from edc_glucose.utils import validate_glucose_as_millimoles_per_liter
7
+ from edc_reportable import MILLIMOLES_PER_LITER
8
+ from edc_reportable.utils import convert_units
9
+
10
+ from meta_reports.models import GlucoseSummary
11
+
12
+ from .mixins import EndpointValidatorMixin, RepeatFbgDateValidatorMixin
13
+
14
+
15
+ class GlucoseFbgFormValidator(
16
+ EndpointValidatorMixin, RepeatFbgDateValidatorMixin, CrfFormValidator
17
+ ):
18
+ def clean(self):
19
+ self.required_if(YES, field="fasting", field_required="fasting_duration_str")
20
+ self.required_if(NO, field="fbg_performed", field_required="fbg_not_performed_reason")
21
+ self.required_if(YES, field="fbg_performed", field_required="fbg_datetime")
22
+ if self.cleaned_data.get("fbg_datetime") and self.cleaned_data.get(
23
+ "fbg_datetime"
24
+ ) < self.cleaned_data.get("report_datetime"):
25
+ self.raise_validation_error(
26
+ {"fbg_datetime": "Invalid. Must be on or after report date above"},
27
+ INVALID_ERROR,
28
+ )
29
+ self.required_if(YES, field="fbg_performed", field_required="fbg_value")
30
+
31
+ self.applicable_if(YES, field="fbg_performed", field_applicable="fbg_units")
32
+
33
+ # endpoint
34
+ self.applicable_if(YES, field="fbg_performed", field_applicable="endpoint_today")
35
+ self.validate_endpoint_fields()
36
+
37
+ # repeat_fbg_date
38
+ self.required_if(PENDING, field="endpoint_today", field_required="repeat_fbg_date")
39
+ self.validate_repeat_fbg_date()
40
+
41
+ @property
42
+ def converted_fbg_value(self):
43
+ if self.cleaned_data.get("fbg_value") is not None:
44
+ return validate_glucose_as_millimoles_per_liter("fbg", self.cleaned_data)
45
+ return None
46
+
47
+ def is_endpoint(self):
48
+ value = NO
49
+ if self.converted_fbg_value and self.converted_fbg_value >= Decimal("7.0"):
50
+ # is there a previous FBG>=7.0 in sequence or do you need to repeat?
51
+ previous_obj = (
52
+ GlucoseSummary.objects.filter(
53
+ subject_identifier=self.subject_identifier,
54
+ fbg_datetime__lt=self.cleaned_data.get("fbg_datetime"),
55
+ )
56
+ .order_by("fbg_datetime")
57
+ .last()
58
+ )
59
+ previous_fbg_value = convert_units(
60
+ label="fbg",
61
+ value=float(previous_obj.fbg_value),
62
+ units_from=previous_obj.fbg_units,
63
+ units_to=MILLIMOLES_PER_LITER,
64
+ )
65
+ previous_ogtt_value = convert_units(
66
+ label="ogtt",
67
+ value=float(previous_obj.ogtt_value),
68
+ units_from=previous_obj.ogtt_units,
69
+ units_to=MILLIMOLES_PER_LITER,
70
+ )
71
+
72
+ if previous_obj and previous_fbg_value >= 7.0 and previous_ogtt_value <= 11.1:
73
+ value = YES
74
+ else:
75
+ # you need to schedule a repeat
76
+ value = PENDING
77
+ return value
@@ -1,16 +1,17 @@
1
- from decimal import Decimal
2
-
3
- from edc_constants.constants import NO, PENDING, YES
1
+ from edc_constants.constants import PENDING
4
2
  from edc_crf.crf_form_validator import CrfFormValidator
5
- from edc_form_validators import INVALID_ERROR
6
3
  from edc_glucose.form_validators import FbgOgttFormValidatorMixin
7
4
 
8
- from meta_reports.models import GlucoseSummary
9
-
10
5
  from ..constants import AMENDMENT_DATE
6
+ from .mixins import EndpointValidatorMixin, RepeatFbgDateValidatorMixin
11
7
 
12
8
 
13
- class GlucoseFormValidator(FbgOgttFormValidatorMixin, CrfFormValidator):
9
+ class GlucoseFormValidator(
10
+ EndpointValidatorMixin,
11
+ RepeatFbgDateValidatorMixin,
12
+ FbgOgttFormValidatorMixin,
13
+ CrfFormValidator,
14
+ ):
14
15
  def clean(self):
15
16
  self.validate_glucose_testing_matrix()
16
17
  has_results = (
@@ -20,79 +21,6 @@ class GlucoseFormValidator(FbgOgttFormValidatorMixin, CrfFormValidator):
20
21
  )
21
22
  self.applicable_if_true(has_results, field_applicable="endpoint_today")
22
23
  if has_results:
23
- is_endpoint = self.is_endpoint()
24
- if is_endpoint == YES and self.cleaned_data.get("endpoint_today") != YES:
25
- self.raise_validation_error(
26
- {
27
- "endpoint_today": (
28
- "Participant has reached a study endpoint today. Expected YES"
29
- )
30
- },
31
- INVALID_ERROR,
32
- )
33
- elif is_endpoint == PENDING and self.cleaned_data.get("endpoint_today") != PENDING:
34
- self.raise_validation_error(
35
- {
36
- "endpoint_today": (
37
- "Participant has not reached a study endpoint today. "
38
- "Expected to repeat FBG"
39
- )
40
- },
41
- INVALID_ERROR,
42
- )
43
-
44
- elif is_endpoint == NO and self.cleaned_data.get("endpoint_today") != NO:
45
- self.raise_validation_error(
46
- {"endpoint_today": "Participant has not reached a study endpoint today"},
47
- INVALID_ERROR,
48
- )
49
-
24
+ self.validate_endpoint_fields()
50
25
  self.required_if(PENDING, field="endpoint_today", field_required="repeat_fbg_date")
51
- if self.cleaned_data.get("repeat_fbg_date"):
52
- delta = (
53
- self.cleaned_data.get("repeat_fbg_date")
54
- - self.cleaned_data.get("fbg_datetime").date()
55
- )
56
- if delta.days < 7:
57
- self.raise_validation_error(
58
- {"repeat_fbg_date": "Must be at least 7 days from the FBG date above"},
59
- INVALID_ERROR,
60
- )
61
- if delta.days > 10:
62
- self.raise_validation_error(
63
- {
64
- "repeat_fbg_date": (
65
- "Must be no more than 10 days from the FBG date above"
66
- )
67
- },
68
- INVALID_ERROR,
69
- )
70
-
71
- def is_endpoint(self):
72
- value = NO
73
- if (
74
- self.cleaned_data.get("fbg_value") >= Decimal("7.0")
75
- and self.cleaned_data.get("ogtt_value") >= Decimal("11.1")
76
- ) or (
77
- self.cleaned_data.get("fbg_value") < Decimal("7.0")
78
- and self.cleaned_data.get("ogtt_value") >= Decimal("11.1")
79
- ):
80
- value = YES
81
- elif self.cleaned_data.get("fbg_value") >= Decimal("7.0") and self.cleaned_data.get(
82
- "ogtt_value"
83
- ) < Decimal("11.1"):
84
- # is there a previous FBG>=7.0 in sequence or do you need to repeat?
85
- previous_obj = (
86
- GlucoseSummary.objects.filter(
87
- subject_identifier=self.subject_identifier,
88
- fbg_datetime__lt=self.cleaned_data.get("fbg_datetime"),
89
- )
90
- .order_by("fbg_datetime")
91
- .last()
92
- )
93
- if previous_obj and previous_obj.fbg_value >= Decimal("7.0"):
94
- value = YES
95
- else:
96
- # you need to schedule a repeat
97
- value = PENDING
98
- return value
26
+ self.validate_repeat_fbg_date()
@@ -0,0 +1,18 @@
1
+ from edc_constants.constants import NO, OTHER
2
+ from edc_crf.crf_form_validator import CrfFormValidator
3
+
4
+
5
+ class HivExitReviewFormValidator(CrfFormValidator):
6
+ def clean(self):
7
+ self.required_if(NO, field="available", field_required="not_available_reason")
8
+ self.required_if_not_none(
9
+ "viral_load", "viral_load_date", field_required_evaluate_as_int=True
10
+ )
11
+
12
+ self.required_if_not_none("cd4", "cd4_date", field_required_evaluate_as_int=True)
13
+
14
+ self.required_if(
15
+ OTHER,
16
+ field="current_arv_regimen",
17
+ field_required="other_current_arv_regimen",
18
+ )