meta-edc 0.3.39__py3-none-any.whl → 1.4.0__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.
Files changed (637) hide show
  1. meta_ae/action_items.py +38 -27
  2. meta_ae/admin/__init__.py +11 -0
  3. meta_ae/admin/ae_initial_admin.py +5 -2
  4. meta_ae/admin/ae_susar_admin.py +1 -1
  5. meta_ae/admin/death_report_admin.py +1 -1
  6. meta_ae/admin/modeladmin_mixins.py +14 -15
  7. meta_ae/baker_recipes.py +4 -6
  8. meta_ae/choices.py +1 -1
  9. meta_ae/forms/__init__.py +13 -0
  10. meta_ae/forms/death_report_form.py +1 -1
  11. meta_ae/forms/modelform_mixins.py +2 -2
  12. meta_ae/list_data.py +1 -1
  13. meta_ae/migrations/0001_initial.py +27 -27
  14. meta_ae/migrations/0006_aelocalreview_aesponsorreview.py +5 -5
  15. meta_ae/migrations/0017_auto_20221130_2257.py +1 -1
  16. meta_ae/migrations/0022_historicalhospitalization_hospitalization.py +5 -13
  17. meta_ae/migrations/0023_alter_aefollowup_action_identifier_and_more.py +2017 -0
  18. meta_ae/model_mixins/__init__.py +2 -0
  19. meta_ae/model_mixins/ae_review_model_mixin.py +6 -6
  20. meta_ae/model_mixins/death_report_model_mixin.py +3 -3
  21. meta_ae/models/__init__.py +13 -0
  22. meta_ae/models/hospitalization.py +3 -3
  23. meta_ae/pdf_reports/__init__.py +2 -0
  24. meta_ae/templatetags/meta_ae_extras.py +4 -6
  25. meta_analytics/.DS_Store +0 -0
  26. meta_analytics/README.rst +1 -2
  27. meta_analytics/dataframes/__init__.py +27 -0
  28. meta_analytics/dataframes/constants.py +5 -2
  29. meta_analytics/dataframes/get_eos_df.py +16 -4
  30. meta_analytics/dataframes/get_glucose_df.py +166 -0
  31. meta_analytics/dataframes/get_glucose_fbg_df.py +26 -0
  32. meta_analytics/dataframes/get_glucose_fbg_ogtt_df.py +21 -0
  33. meta_analytics/dataframes/get_last_imp_visits_df.py +12 -10
  34. meta_analytics/dataframes/glucose_endpoints/__init__.py +2 -0
  35. meta_analytics/dataframes/glucose_endpoints/endpoint_by_date.py +125 -124
  36. meta_analytics/dataframes/glucose_endpoints/glucose_endpoints_by_date.py +111 -235
  37. meta_analytics/dataframes/screening/__init__.py +2 -0
  38. meta_analytics/dataframes/screening/get_glucose_tested_only_df.py +1 -2
  39. meta_analytics/dataframes/screening/get_screening_df.py +9 -15
  40. meta_analytics/dataframes/utils.py +21 -12
  41. meta_analytics/get_tables.py +1 -2
  42. meta_analytics/tables/__init__.py +2 -0
  43. meta_analytics/tables/enrolled/glucose.py +2 -1
  44. meta_analytics/utils.py +81 -0
  45. meta_auth/auths.py +1 -1
  46. meta_consent/action_items.py +22 -3
  47. meta_consent/admin/__init__.py +7 -0
  48. meta_consent/admin/actions/__init__.py +2 -0
  49. meta_consent/admin/actions/create_missing_prescriptions.py +2 -2
  50. meta_consent/admin/list_filters.py +22 -0
  51. meta_consent/admin/modeladmin_mixins.py +4 -5
  52. meta_consent/admin/subject_consent_v1_ext_admin.py +93 -0
  53. meta_consent/baker_recipes.py +7 -7
  54. meta_consent/consents.py +15 -2
  55. meta_consent/constants.py +1 -0
  56. meta_consent/form_validators/__init__.py +2 -0
  57. meta_consent/forms/__init__.py +8 -0
  58. meta_consent/forms/subject_consent_v1_ext_form.py +47 -0
  59. meta_consent/forms/subject_reconsent_form.py +4 -4
  60. meta_consent/management/commands/create_missing_prescriptions.py +5 -3
  61. meta_consent/migrations/0001_initial.py +9 -9
  62. meta_consent/migrations/0024_historicalsubjectconsentv1.py +3 -8
  63. meta_consent/migrations/0026_historicalsubjectconsentv1ext_subjectconsentv1ext.py +535 -0
  64. meta_consent/migrations/0027_auto_20250111_0344.py +30 -0
  65. meta_consent/migrations/0028_historicalsubjectconsentv1ext_assessment_score_and_more.py +162 -0
  66. meta_consent/migrations/0029_alter_historicalsubjectconsentv1ext_agrees_to_extension_and_more.py +33 -0
  67. meta_consent/migrations/0030_auto_20250120_2114.py +40 -0
  68. meta_consent/migrations/0031_alter_historicalsubjectconsent_guardian_name_and_more.py +124 -0
  69. meta_consent/migrations/0032_alter_historicalsubjectconsent_device_created_and_more.py +678 -0
  70. meta_consent/migrations/0033_historicalsubjectconsentspfq_subjectconsentspfq.py +615 -0
  71. meta_consent/migrations/0034_remove_subjectconsentspfq_site_and_more.py +23 -0
  72. meta_consent/migrations/0035_alter_historicalsubjectconsent_consent_definition_name_and_more.py +43 -0
  73. meta_consent/models/__init__.py +10 -0
  74. meta_consent/models/model_mixins.py +1 -2
  75. meta_consent/models/signals.py +25 -11
  76. meta_consent/models/subject_consent.py +2 -2
  77. meta_consent/models/subject_consent_v1.py +0 -1
  78. meta_consent/models/subject_consent_v1_ext.py +34 -0
  79. meta_consent/models/subject_reconsent.py +4 -4
  80. meta_dashboard/navbars.py +2 -6
  81. meta_dashboard/patterns.py +1 -1
  82. meta_dashboard/templates/meta_dashboard/{bootstrap3/buttons → buttons}/eligibility_button.html +1 -1
  83. meta_dashboard/templates/meta_dashboard/{bootstrap3/buttons → buttons}/screening_button.html +1 -1
  84. meta_dashboard/templates/meta_dashboard/subject/dashboard/sidebar.html +24 -0
  85. meta_dashboard/templates/meta_dashboard/{bootstrap3/subject → subject}/dashboard/top_bar.html +1 -1
  86. meta_dashboard/templates/meta_dashboard/subject/dashboard.html +14 -0
  87. meta_dashboard/templatetags/meta_dashboard_extras.py +9 -14
  88. meta_dashboard/urls.py +5 -5
  89. meta_dashboard/view_utils/__init__.py +13 -0
  90. meta_dashboard/view_utils/subject_screening_button.py +13 -20
  91. meta_dashboard/views/__init__.py +8 -0
  92. meta_dashboard/views/ae/__init__.py +2 -0
  93. meta_dashboard/views/ae/ae_listboard_view.py +1 -1
  94. meta_dashboard/views/ae/death_report_listboard_view.py +1 -1
  95. meta_dashboard/views/screening/__init__.py +2 -0
  96. meta_dashboard/views/screening/listboard_view.py +2 -3
  97. meta_dashboard/views/subject/__init__.py +2 -0
  98. meta_dashboard/views/subject/dashboard/__init__.py +2 -0
  99. meta_dashboard/views/subject/dashboard/dashboard_view.py +19 -8
  100. meta_dashboard/views/subject/listboard/__init__.py +2 -0
  101. meta_dashboard/views/subject/listboard/listboard_view.py +2 -3
  102. meta_edc/__init__.py +5 -9
  103. meta_edc/admin.py +3 -4
  104. meta_edc/celery.py +2 -2
  105. meta_edc/celery_live.py +19 -0
  106. meta_edc/celery_uat.py +25 -0
  107. meta_edc/management/commands/update_forms_reference.py +16 -14
  108. meta_edc/meta_version.py +2 -2
  109. meta_edc/navbars.py +7 -5
  110. meta_edc/settings/debug.py +13 -4
  111. meta_edc/settings/defaults.py +55 -18
  112. meta_edc/settings/live.py +4 -1
  113. meta_edc/settings/logging.py +9 -4
  114. meta_edc/settings/minimal.py +4 -5
  115. meta_edc/settings/uat.py +3 -1
  116. meta_edc/templates/meta_edc/{bootstrap3/base.html → base.html} +1 -1
  117. meta_edc/templates/meta_edc/{bootstrap3/home.html → home.html} +2 -2
  118. meta_edc/urls.py +3 -1
  119. meta_edc/utils.py +3 -1
  120. meta_edc/views/__init__.py +2 -0
  121. meta_edc/views/home_view.py +1 -2
  122. meta_edc-1.4.0.dist-info/METADATA +174 -0
  123. {meta_edc-0.3.39.dist-info → meta_edc-1.4.0.dist-info}/RECORD +578 -586
  124. meta_edc-1.4.0.dist-info/WHEEL +4 -0
  125. meta_labs/list_data.py +2 -2
  126. meta_labs/reportables.py +80 -11
  127. meta_lists/list_data.py +13 -4
  128. meta_lists/migrations/0008_auto_20200528_1517.py +2 -2
  129. meta_lists/migrations/0019_auto_20250128_0143.py +48 -0
  130. meta_lists/migrations/0020_alter_abnormalfootappearanceobservations_extra_value_and_more.py +404 -0
  131. meta_pharmacy/admin/__init__.py +5 -0
  132. meta_pharmacy/admin/rx_admin.py +1 -0
  133. meta_pharmacy/admin/substitutions_admin.py +3 -3
  134. meta_pharmacy/constants.py +1 -1
  135. meta_pharmacy/forms/__init__.py +2 -0
  136. meta_pharmacy/forms/rx_form.py +0 -1
  137. meta_pharmacy/forms/substitutions_form.py +6 -4
  138. meta_pharmacy/labels/__init__.py +5 -2
  139. meta_pharmacy/labels/draw_label_for_subject_with_barcode.py +4 -1
  140. meta_pharmacy/labels/draw_label_with_test_data.py +2 -2
  141. meta_pharmacy/labels/label_data.py +1 -2
  142. meta_pharmacy/labels/print_sheets.py +4 -6
  143. meta_pharmacy/management/commands/update_initial_pharmacy_data.py +4 -3
  144. meta_pharmacy/migrations/0002_initial.py +7 -20
  145. meta_pharmacy/migrations/0003_auto_20240909_2335.py +3 -2
  146. meta_pharmacy/migrations/0006_lotnumber_label.py +5 -14
  147. meta_pharmacy/migrations/0008_remove_lotnumber_medication_and_more.py +5 -6
  148. meta_pharmacy/migrations/0010_alter_historicallabeldata_device_created_and_more.py +382 -0
  149. meta_pharmacy/models/__init__.py +7 -0
  150. meta_pharmacy/models/label_data.py +4 -5
  151. meta_pharmacy/models/rx_label.py +0 -1
  152. meta_pharmacy/models/substitutions.py +4 -4
  153. meta_pharmacy/prepare_meta_pharmacy.py +1 -1
  154. meta_pharmacy/utils/__init__.py +2 -0
  155. meta_pharmacy/utils/update_initial_pharmacy_data.py +1 -1
  156. meta_prn/action_items.py +44 -45
  157. meta_prn/admin/__init__.py +16 -0
  158. meta_prn/admin/dm_referral_admin.py +2 -1
  159. meta_prn/admin/end_of_study_admin.py +26 -15
  160. meta_prn/admin/loss_to_followup_admin.py +3 -2
  161. meta_prn/admin/off_study_medication_admin.py +5 -6
  162. meta_prn/admin/offschedule_admin.py +12 -11
  163. meta_prn/admin/offschedule_dm_referral_admin.py +11 -10
  164. meta_prn/admin/offschedule_postnatal_admin.py +15 -7
  165. meta_prn/admin/offschedule_pregnancy_admin.py +18 -9
  166. meta_prn/admin/onschedule_admin.py +7 -8
  167. meta_prn/admin/onschedule_dm_referral_admin.py +11 -12
  168. meta_prn/admin/pregnancy_notification_admin.py +5 -6
  169. meta_prn/admin/protocol_incident_admin.py +1 -1
  170. meta_prn/admin/subject_transfer_admin.py +1 -1
  171. meta_prn/baker_recipes.py +10 -10
  172. meta_prn/choices.py +11 -7
  173. meta_prn/constants.py +1 -0
  174. meta_prn/form_validators/__init__.py +5 -0
  175. meta_prn/form_validators/end_of_study.py +65 -20
  176. meta_prn/form_validators/protocol_incident.py +1 -1
  177. meta_prn/forms/__init__.py +13 -0
  178. meta_prn/forms/dm_referral_form.py +2 -8
  179. meta_prn/forms/end_of_study_form.py +1 -1
  180. meta_prn/forms/loss_to_followup_form.py +1 -1
  181. meta_prn/forms/off_study_medication_form.py +2 -2
  182. meta_prn/forms/offschedule_form.py +25 -0
  183. meta_prn/forms/pregnancy_notification_form.py +15 -17
  184. meta_prn/list_data.py +3 -3
  185. meta_prn/migrations/0001_initial.py +25 -25
  186. meta_prn/migrations/0017_auto_20220307_1929.py +5 -5
  187. meta_prn/migrations/0018_auto_20220309_2106.py +9 -9
  188. meta_prn/migrations/0021_auto_20220316_2147.py +13 -13
  189. meta_prn/migrations/0022_auto_20220318_0133.py +9 -9
  190. meta_prn/migrations/0032_historicalegfrnotification_egfrnotification.py +5 -13
  191. meta_prn/migrations/0034_auto_20220630_1110.py +1 -1
  192. meta_prn/migrations/0035_auto_20220630_1140.py +1 -1
  193. meta_prn/migrations/0038_alter_endofstudy_delivery_date_and_more.py +5 -13
  194. meta_prn/migrations/0041_endofstudy_transfer_date_and_more.py +5 -13
  195. meta_prn/migrations/0057_historicalonscheduledmreferral_and_more.py +13 -38
  196. meta_prn/migrations/0060_alter_onschedule_managers_and_more.py +55 -0
  197. meta_prn/migrations/0061_auto_20250115_2025.py +56 -0
  198. meta_prn/migrations/0062_alter_endofstudy_offstudy_reason_and_more.py +72 -0
  199. meta_prn/migrations/0063_historicaloffstudymedication_singleton_field_and_more.py +37 -0
  200. meta_prn/migrations/0064_auto_20250602_2143.py +18 -0
  201. meta_prn/migrations/0065_alter_historicaloffstudymedication_subject_identifier_and_more.py +23 -0
  202. meta_prn/migrations/0066_alter_historicallosstofollowup_subject_identifier_and_more.py +23 -0
  203. meta_prn/migrations/0067_alter_offschedule_managers_and_more.py +2557 -0
  204. meta_prn/migrations/0068_alter_dmreferral_referral_note_and_more.py +235 -0
  205. meta_prn/migrations/0069_alter_historicaloffstudymedication_singleton_field_and_more.py +37 -0
  206. meta_prn/models/__init__.py +20 -0
  207. meta_prn/models/dm_referral.py +2 -2
  208. meta_prn/models/end_of_study.py +28 -23
  209. meta_prn/models/loss_to_followup.py +8 -10
  210. meta_prn/models/off_study_medication.py +7 -4
  211. meta_prn/models/offschedule.py +4 -4
  212. meta_prn/models/pregnancy_notification.py +3 -5
  213. meta_prn/models/protocol_incident.py +5 -2
  214. meta_prn/models/signals.py +16 -14
  215. meta_prn/models/subject_transfer.py +7 -0
  216. meta_prn/templates/meta_prn/eos/additional_instructions.html +3 -0
  217. meta_prn/templates/meta_prn/offschedule/additional_instructions.html +2 -0
  218. meta_rando/migrations/0001_initial.py +5 -5
  219. meta_rando/migrations/0006_alter_historicalrandomizationlist_allocated_user_and_more.py +130 -0
  220. meta_rando/migrations/0007_spfqlist.py +197 -0
  221. meta_rando/migrations/0008_delete_spfqlist.py +16 -0
  222. meta_rando/models/__init__.py +1 -0
  223. meta_rando/{models.py → models/randomization_list.py} +3 -3
  224. meta_rando/randomizers.py +2 -2
  225. meta_reports/__init__.py +2 -0
  226. meta_reports/admin/__init__.py +16 -0
  227. meta_reports/admin/dbviews/__init__.py +13 -0
  228. meta_reports/admin/dbviews/glucose_summary_admin.py +7 -7
  229. meta_reports/admin/dbviews/imp_substitutions_admin.py +14 -13
  230. meta_reports/admin/dbviews/missing_screening_ogtt_admin/__init__.py +5 -0
  231. meta_reports/admin/dbviews/missing_screening_ogtt_admin/note_model_admin.py +27 -3
  232. meta_reports/admin/dbviews/missing_screening_ogtt_admin/unmanaged_model_admin.py +7 -7
  233. meta_reports/admin/dbviews/on_study_missing_lab_values_admin/__init__.py +2 -0
  234. meta_reports/admin/dbviews/on_study_missing_lab_values_admin/unmanaged_model_admin.py +0 -3
  235. meta_reports/admin/dbviews/on_study_missing_values_admin/__init__.py +2 -0
  236. meta_reports/admin/dbviews/on_study_missing_values_admin/unmanaged_model_admin.py +0 -1
  237. meta_reports/admin/dbviews/patient_history_missing_baseline_cd4_admin.py +9 -9
  238. meta_reports/admin/dbviews/unattended_three_in_row2_admin.py +6 -6
  239. meta_reports/admin/dbviews/unattended_three_in_row_admin.py +5 -5
  240. meta_reports/admin/dbviews/unattended_two_in_row_admin.py +5 -5
  241. meta_reports/admin/endpoints_admin.py +1 -1
  242. meta_reports/admin/endpoints_all_admin.py +0 -1
  243. meta_reports/admin/last_imp_refill_admin.py +33 -36
  244. meta_reports/admin/list_filters.py +3 -3
  245. meta_reports/admin/modeladmin_mixins.py +10 -17
  246. meta_reports/death_report.py +2 -2
  247. meta_reports/forms/__init__.py +2 -0
  248. meta_reports/forms/missing_ogtt_note_form.py +3 -4
  249. meta_reports/management/commands/generate_endpoints.py +5 -4
  250. meta_reports/migrations/0035_historicalmissingogttnote_missingogttnote.py +5 -14
  251. meta_reports/migrations/0054_auto_20250422_2003.py +81 -0
  252. meta_reports/migrations/0055_alter_glucosesummary_table.py +17 -0
  253. meta_reports/migrations/0056_auto_20250422_2214.py +54 -0
  254. meta_reports/migrations/0057_auto_20250422_2224.py +54 -0
  255. meta_reports/migrations/0058_auto_20250422_2232.py +54 -0
  256. meta_reports/migrations/0059_alter_endpoints_created_and_more.py +161 -0
  257. meta_reports/migrations/0060_auto_20250926_0242.py +366 -0
  258. meta_reports/migrations/0061_auto_20251004_0043.py +21 -0
  259. meta_reports/migrations/0062_auto_20251004_0106.py +21 -0
  260. meta_reports/models/__init__.py +17 -0
  261. meta_reports/models/dbviews/__init__.py +14 -0
  262. meta_reports/models/dbviews/glucose_summary/__init__.py +2 -0
  263. meta_reports/models/dbviews/glucose_summary/unmanaged_model.py +15 -3
  264. meta_reports/models/dbviews/glucose_summary/view_definition.py +8 -5
  265. meta_reports/models/dbviews/imp_substitutions/__init__.py +2 -0
  266. meta_reports/models/dbviews/imp_substitutions/unmanaged_model.py +1 -2
  267. meta_reports/models/dbviews/imp_substitutions/view_definition.py +1 -1
  268. meta_reports/models/dbviews/missing_screening_ogtt/__init__.py +2 -0
  269. meta_reports/models/dbviews/missing_screening_ogtt/note_model.py +2 -2
  270. meta_reports/models/dbviews/missing_screening_ogtt/unmanaged_model.py +4 -3
  271. meta_reports/models/dbviews/on_study_missing_lab_values/__init__.py +2 -0
  272. meta_reports/models/dbviews/on_study_missing_lab_values/qa_cases.py +13 -11
  273. meta_reports/models/dbviews/on_study_missing_lab_values/unmanged_model.py +0 -1
  274. meta_reports/models/dbviews/on_study_missing_values/__init__.py +2 -0
  275. meta_reports/models/dbviews/on_study_missing_values/qa_cases.py +19 -1
  276. meta_reports/models/dbviews/on_study_missing_values/unmanged_model.py +0 -1
  277. meta_reports/models/dbviews/patient_history_missing_baseline_cd4/__init__.py +2 -0
  278. meta_reports/models/dbviews/patient_history_missing_baseline_cd4/unmanaged_model.py +0 -1
  279. meta_reports/models/dbviews/unattended_three_in_row/__init__.py +2 -0
  280. meta_reports/models/dbviews/unattended_three_in_row/unmanaged_model.py +0 -1
  281. meta_reports/models/dbviews/unattended_three_in_row2/__init__.py +2 -0
  282. meta_reports/models/dbviews/unattended_three_in_row2/unmanaged_model.py +0 -1
  283. meta_reports/models/dbviews/unattended_two_in_row/__init__.py +2 -0
  284. meta_reports/models/dbviews/unattended_two_in_row/unmanaged_model.py +0 -1
  285. meta_reports/models/endpoints.py +8 -4
  286. meta_reports/models/last_imp_refill.py +2 -3
  287. meta_reports/pdf_report.py +2 -2
  288. meta_reports/tasks.py +4 -3
  289. meta_reports/templates/meta_reports/columns/subject_identifier_column.html +1 -1
  290. meta_reports/templates/meta_reports/endpoints_all_change_list_note.html +1 -1
  291. meta_reports/templates/meta_reports/endpoints_change_list_note.html +1 -1
  292. meta_reports/templates/meta_reports/last_imp_refill/changelist_note.html +13 -0
  293. meta_screening/admin/__init__.py +8 -0
  294. meta_screening/admin/fieldsets.py +13 -15
  295. meta_screening/admin/list_filters.py +7 -5
  296. meta_screening/admin/screening_part_one_admin.py +1 -3
  297. meta_screening/admin/screening_part_three_admin.py +2 -3
  298. meta_screening/admin/screening_part_two_admin.py +7 -10
  299. meta_screening/admin/subject_refusal_admin.py +5 -3
  300. meta_screening/admin/subject_screening_admin.py +21 -10
  301. meta_screening/baker_recipes.py +18 -10
  302. meta_screening/calculators.py +1 -1
  303. meta_screening/choices.py +1 -1
  304. meta_screening/constants.py +1 -1
  305. meta_screening/eligibility/__init__.py +9 -0
  306. meta_screening/eligibility/eligibility.py +21 -14
  307. meta_screening/eligibility/eligibility_part_one.py +1 -1
  308. meta_screening/eligibility/eligibility_part_three/__init__.py +2 -0
  309. meta_screening/eligibility/eligibility_part_three/base_eligibility_part_three.py +68 -49
  310. meta_screening/eligibility/eligibility_part_three/eligibility_part_three_phase_three.py +14 -15
  311. meta_screening/eligibility/eligibility_part_two.py +1 -1
  312. meta_screening/form_validators/__init__.py +8 -0
  313. meta_screening/form_validators/screening_part_one.py +1 -1
  314. meta_screening/form_validators/screening_part_three.py +6 -2
  315. meta_screening/form_validators/screening_part_two.py +1 -1
  316. meta_screening/form_validators/subject_refusal.py +1 -1
  317. meta_screening/forms/__init__.py +20 -0
  318. meta_screening/forms/field_lists.py +16 -18
  319. meta_screening/forms/screening_part_one_form.py +2 -2
  320. meta_screening/forms/screening_part_three_form.py +5 -3
  321. meta_screening/forms/screening_part_two_form.py +1 -5
  322. meta_screening/forms/subject_refusal_form.py +0 -4
  323. meta_screening/forms/subject_screening_form.py +0 -4
  324. meta_screening/migrations/0001_initial.py +15 -15
  325. meta_screening/migrations/0010_auto_20191106_0828.py +5 -5
  326. meta_screening/migrations/0012_auto_20191107_0427.py +1 -1
  327. meta_screening/migrations/0068_alter_historicalscreeningpartone_acute_condition_and_more.py +1579 -0
  328. meta_screening/model_mixins/__init__.py +8 -0
  329. meta_screening/model_mixins/calculated_model_mixin.py +2 -2
  330. meta_screening/model_mixins/creatinine_fields_model_mixin.py +1 -1
  331. meta_screening/model_mixins/eligibility_model_mixin.py +6 -4
  332. meta_screening/model_mixins/part_one_fields_model_mixin.py +16 -19
  333. meta_screening/model_mixins/part_three_fields_model_mixin.py +6 -7
  334. meta_screening/model_mixins/part_two_fields_model_mixin.py +19 -17
  335. meta_screening/models/__init__.py +9 -0
  336. meta_screening/models/icp_referral.py +5 -5
  337. meta_screening/models/proxy_models.py +1 -1
  338. meta_screening/models/signals.py +10 -11
  339. meta_screening/models/subject_refusal.py +1 -1
  340. meta_screening/models/subject_screening.py +2 -4
  341. meta_subject/action_items.py +18 -14
  342. meta_subject/admin/__init__.py +42 -0
  343. meta_subject/admin/birth_outcome_admin.py +7 -9
  344. meta_subject/admin/blood_results/__init__.py +9 -0
  345. meta_subject/admin/blood_results/blood_results_fbc_admin.py +1 -1
  346. meta_subject/admin/blood_results/blood_results_hba1c_admin.py +1 -1
  347. meta_subject/admin/blood_results/blood_results_ins_admin.py +1 -1
  348. meta_subject/admin/blood_results/blood_results_lft_admin.py +1 -1
  349. meta_subject/admin/blood_results/blood_results_lipids_admin.py +1 -1
  350. meta_subject/admin/blood_results/blood_results_rft_admin.py +3 -5
  351. meta_subject/admin/complications_glycemia_admin.py +1 -1
  352. meta_subject/admin/delivery_admin.py +8 -11
  353. meta_subject/admin/diabetes/__init__.py +2 -0
  354. meta_subject/admin/diabetes/dm_endpoint_admin.py +2 -2
  355. meta_subject/admin/diabetes/dm_followup_admin.py +3 -2
  356. meta_subject/admin/egfr_drop_notification_admin.py +1 -1
  357. meta_subject/admin/fields.py +5 -5
  358. meta_subject/admin/fieldsets.py +5 -5
  359. meta_subject/admin/followup_examination_admin.py +11 -9
  360. meta_subject/admin/followup_vitals_admin.py +31 -6
  361. meta_subject/admin/glucose_admin.py +4 -8
  362. meta_subject/admin/glucose_fbg_admin.py +18 -11
  363. meta_subject/admin/health_economics/__init__.py +2 -0
  364. meta_subject/admin/health_economics/health_economics_simple_admin.py +1 -1
  365. meta_subject/admin/health_economics/health_economics_update_admin.py +1 -1
  366. meta_subject/admin/hepatitis_test_admin.py +1 -1
  367. meta_subject/admin/hiv_exit_review_admin.py +55 -0
  368. meta_subject/admin/list_filters.py +5 -5
  369. meta_subject/admin/mnsi_admin.py +7 -5
  370. meta_subject/admin/next_appointment_admin.py +19 -0
  371. meta_subject/admin/other_arv_regimens_admin.py +3 -3
  372. meta_subject/admin/patient_history_admin.py +4 -4
  373. meta_subject/admin/physical_exam_admin.py +1 -1
  374. meta_subject/admin/pregnancy_update_admin.py +1 -1
  375. meta_subject/admin/study_medication_admin.py +8 -15
  376. meta_subject/admin/subject_requisition_admin.py +2 -2
  377. meta_subject/admin/subject_visit_admin.py +1 -1
  378. meta_subject/admin/subject_visit_missed_admin.py +1 -1
  379. meta_subject/admin/urine_dipstick_test_admin.py +1 -1
  380. meta_subject/admin/urine_pregnancy_admin.py +1 -1
  381. meta_subject/baker_recipes.py +15 -15
  382. meta_subject/choices.py +4 -3
  383. meta_subject/form_validators/__init__.py +15 -0
  384. meta_subject/form_validators/delivery_form_validator.py +3 -3
  385. meta_subject/form_validators/dm_endpoint_form_validator.py +3 -1
  386. meta_subject/form_validators/dm_followup_form_validator.py +8 -7
  387. meta_subject/form_validators/egfr_drop_notification_form_validator.py +1 -1
  388. meta_subject/form_validators/followup_examination_form_validator.py +1 -1
  389. meta_subject/form_validators/glucose_fbg_form_validator.py +76 -0
  390. meta_subject/form_validators/glucose_form_validator.py +10 -67
  391. meta_subject/form_validators/hiv_exit_review_form_validator.py +18 -0
  392. meta_subject/form_validators/mixins.py +95 -0
  393. meta_subject/forms/__init__.py +44 -0
  394. meta_subject/forms/blood_results/__init__.py +9 -0
  395. meta_subject/forms/blood_results/blood_results_hba1c_form.py +1 -1
  396. meta_subject/forms/blood_results/blood_results_rft_form.py +60 -4
  397. meta_subject/forms/delivery_form.py +2 -0
  398. meta_subject/forms/diabetes/__init__.py +2 -0
  399. meta_subject/forms/diabetes/dm_followup_form.py +2 -2
  400. meta_subject/forms/followup_vitals_form.py +27 -1
  401. meta_subject/forms/glucose_fbg_form.py +1 -46
  402. meta_subject/forms/health_economics/__init__.py +2 -0
  403. meta_subject/forms/hepatitis_test_form.py +1 -1
  404. meta_subject/forms/hiv_exit_review_form.py +13 -0
  405. meta_subject/forms/mixins.py +1 -1
  406. meta_subject/forms/next_appointment_form.py +36 -0
  407. meta_subject/forms/other_arv_regimens_form.py +1 -1
  408. meta_subject/forms/patient_history_form.py +1 -1
  409. meta_subject/forms/physical_exam_form.py +1 -1
  410. meta_subject/forms/pregnancy_update_form.py +1 -1
  411. meta_subject/forms/slider_widget.py +1 -1
  412. meta_subject/forms/study_medication_form.py +18 -12
  413. meta_subject/forms/subject_requisition_form.py +1 -1
  414. meta_subject/forms/subject_visit_missed_form.py +1 -1
  415. meta_subject/forms/urine_dipstick_test_form.py +1 -1
  416. meta_subject/forms/urine_pregnancy_form.py +1 -1
  417. meta_subject/management/commands/create_missing_refills.py +3 -3
  418. meta_subject/management/commands/create_missing_rx.py +2 -2
  419. meta_subject/management/commands/missed.py +20 -23
  420. meta_subject/metadata_rules/__init__.py +2 -0
  421. meta_subject/metadata_rules/metadata_rules.py +14 -0
  422. meta_subject/metadata_rules/predicates.py +44 -25
  423. meta_subject/migrations/0001_initial.py +61 -61
  424. meta_subject/migrations/0002_auto_20191021_0353.py +5 -5
  425. meta_subject/migrations/0012_auto_20200118_2334.py +5 -5
  426. meta_subject/migrations/0014_auto_20200120_1622.py +5 -5
  427. meta_subject/migrations/0018_coronakap_historicalcoronakap.py +5 -5
  428. meta_subject/migrations/0033_auto_20200516_2356.py +5 -5
  429. meta_subject/migrations/0038_auto_20200520_0020.py +5 -5
  430. meta_subject/migrations/0040_auto_20200527_2155.py +1 -1
  431. meta_subject/migrations/0045_auto_20200530_1801.py +1 -1
  432. meta_subject/migrations/0051_auto_20200617_2117.py +5 -5
  433. meta_subject/migrations/0063_auto_20210715_0337.py +5 -5
  434. meta_subject/migrations/0066_auto_20210721_0335.py +9 -9
  435. meta_subject/migrations/0067_auto_20210726_0340.py +5 -5
  436. meta_subject/migrations/0068_auto_20210728_1809.py +5 -5
  437. meta_subject/migrations/0072_auto_20210805_1545.py +7 -7
  438. meta_subject/migrations/0073_auto_20210809_0055.py +5 -5
  439. meta_subject/migrations/0077_auto_20210809_2323.py +3 -3
  440. meta_subject/migrations/0082_auto_20210823_1612.py +3 -3
  441. meta_subject/migrations/0083_auto_20210823_1620.py +3 -3
  442. meta_subject/migrations/0088_auto_20210924_0027.py +5 -5
  443. meta_subject/migrations/0090_auto_20210924_0424.py +5 -5
  444. meta_subject/migrations/0093_auto_20211117_0352.py +5 -5
  445. meta_subject/migrations/0095_auto_20220128_1719.py +5 -5
  446. meta_subject/migrations/0098_auto_20220309_2106.py +5 -5
  447. meta_subject/migrations/0101_auto_20220316_2147.py +13 -13
  448. meta_subject/migrations/0107_auto_20220415_0043.py +1 -1
  449. meta_subject/migrations/0115_historicalegfrnotification_egfrnotification.py +5 -13
  450. meta_subject/migrations/0128_auto_20220720_0055.py +1 -1
  451. meta_subject/migrations/0131_auto_20220722_0411.py +1 -1
  452. meta_subject/migrations/0135_auto_20220722_2212.py +2 -1
  453. meta_subject/migrations/0164_dmreferralfollowup_historicaldmreferralfollowup.py +5 -5
  454. meta_subject/migrations/0172_remove_historicalbloodresultsglu_action_item_and_more.py +1 -2
  455. meta_subject/migrations/0177_alter_bloodresultslft_alp_value_and_more.py +1 -2
  456. meta_subject/migrations/0178_historicalhealtheconomicsupdate_and_more.py +5 -14
  457. meta_subject/migrations/0186_healtheconomicsupdate_singleton_field_and_more.py +1 -2
  458. meta_subject/migrations/0187_dmdiagnosis_historicaldmdiagnosis_dmdxresult_and_more.py +5 -14
  459. meta_subject/migrations/0188_historicaldmdxresult_dmdxresult.py +5 -14
  460. meta_subject/migrations/0199_auto_20240516_0247.py +1 -1
  461. meta_subject/migrations/0209_remove_historicaldmdxresult_dm_diagnosis_and_more.py +1 -2
  462. meta_subject/migrations/0212_auto_20240827_2222.py +1 -1
  463. meta_subject/migrations/0216_historicalnextappointment_nextappointment.py +553 -0
  464. meta_subject/migrations/0217_alter_historicalnextappointment_appt_datetime_and_more.py +42 -0
  465. meta_subject/migrations/0218_alter_historicalnextappointment_appt_date_and_more.py +53 -0
  466. meta_subject/migrations/0219_remove_historicalnextappointment_allow_create_interim_and_more.py +92 -0
  467. meta_subject/migrations/0220_historicalbloodresultsgludummy_bloodresultsgludummy.py +825 -0
  468. meta_subject/migrations/0221_auto_20250402_1913.py +42 -0
  469. meta_subject/migrations/0222_alter_historicalstudymedication_stock_codes_and_more.py +46 -0
  470. meta_subject/migrations/0223_bloodresultsfbc_errors_bloodresultsgludummy_errors_and_more.py +83 -0
  471. meta_subject/migrations/0224_bloodresultsfbc_abnormal_summary_and_more.py +153 -0
  472. meta_subject/migrations/0225_followupvitals_waist_circumference_and_more.py +46 -0
  473. meta_subject/migrations/0226_followupvitals_waist_circumference_comment_and_more.py +97 -0
  474. meta_subject/migrations/0227_alter_followupvitals_waist_circumference_comment_and_more.py +97 -0
  475. meta_subject/migrations/0228_bloodresultshba1c_hba1c_datetime_and_more.py +2518 -0
  476. meta_subject/migrations/0229_alter_glucosefbg_consent_model_and_more.py +1918 -0
  477. meta_subject/migrations/0230_alter_historicaldelivery_action_identifier_and_more.py +1733 -0
  478. meta_subject/migrations/0231_alter_historicalmedicationadherence_consent_model_and_more.py +2054 -0
  479. meta_subject/migrations/0232_alter_patienthistory_concomitant_conditions_and_more.py +1170 -0
  480. meta_subject/migrations/0233_historicalspfq_spfq.py +1066 -0
  481. meta_subject/migrations/0234_remove_spfq_site_remove_spfq_subject_visit_and_more.py +27 -0
  482. meta_subject/migrations/0235_glucosefbg_endpoint_today_and_more.py +606 -0
  483. meta_subject/migrations/0236_alter_historicalhivexitreview_other_current_arv_regimen_and_more.py +58 -0
  484. meta_subject/migrations/0237_historicalhivexitreview_singleton_field_and_more.py +68 -0
  485. meta_subject/migrations/0238_historicalhivexitreview_available_and_more.py +88 -0
  486. meta_subject/model_mixins/__init__.py +10 -0
  487. meta_subject/model_mixins/arv_history_model_mixin.py +3 -44
  488. meta_subject/model_mixins/arv_review_model_mixin.py +53 -0
  489. meta_subject/model_mixins/search_slug_model_mixin.py +1 -2
  490. meta_subject/model_mixins/vitals_fields_model_mixin.py +33 -0
  491. meta_subject/models/__init__.py +52 -0
  492. meta_subject/models/birth_outcomes.py +3 -3
  493. meta_subject/models/blood_results/__init__.py +11 -0
  494. meta_subject/models/blood_results/blood_results_glu.py +29 -0
  495. meta_subject/models/blood_results/blood_results_hba1c.py +0 -1
  496. meta_subject/models/blood_results/blood_results_ins.py +0 -1
  497. meta_subject/models/blood_results/blood_results_lft.py +0 -1
  498. meta_subject/models/delivery.py +4 -6
  499. meta_subject/models/diabetes/__init__.py +2 -0
  500. meta_subject/models/diabetes/dm_endpoint.py +5 -5
  501. meta_subject/models/diabetes/dm_followup.py +7 -8
  502. meta_subject/models/diet_and_lifestyle.py +2 -2
  503. meta_subject/models/followup_examination.py +12 -14
  504. meta_subject/models/glucose.py +5 -5
  505. meta_subject/models/glucose_fbg.py +17 -4
  506. meta_subject/models/health_economics/__init__.py +2 -0
  507. meta_subject/models/health_economics/health_economics.py +8 -8
  508. meta_subject/models/health_economics/health_economics_simple.py +2 -2
  509. meta_subject/models/health_economics/health_economics_update.py +3 -2
  510. meta_subject/models/hepatitis_test.py +2 -2
  511. meta_subject/models/hiv_exit_review.py +44 -0
  512. meta_subject/models/next_appointment.py +15 -0
  513. meta_subject/models/other_arv_regimens_detail.py +1 -1
  514. meta_subject/models/patient_history.py +6 -7
  515. meta_subject/models/physical_exam.py +2 -2
  516. meta_subject/models/pregnancy_update.py +1 -1
  517. meta_subject/models/signals.py +15 -13
  518. meta_subject/models/subject_visit.py +2 -2
  519. meta_subject/models/todo.txt +1 -1
  520. meta_subject/models/urine_dipstick_test.py +2 -2
  521. meta_subject/models/urine_pregnancy.py +1 -1
  522. meta_subject/static/meta_subject/slider.css +1 -1
  523. meta_subject/templates/meta_subject/endpoint_review_instructions.html +1 -1
  524. meta_subject/templates/meta_subject/widgets/slider.html +0 -1
  525. meta_visit_schedule/visit_schedules/__init__.py +2 -0
  526. meta_visit_schedule/visit_schedules/phase_three/__init__.py +2 -0
  527. meta_visit_schedule/visit_schedules/phase_three/crfs.py +34 -1
  528. meta_visit_schedule/visit_schedules/phase_three/schedule.py +4 -4
  529. meta_visit_schedule/visit_schedules/phase_three/schedule_dm_referral.py +1 -2
  530. meta_visit_schedule/visit_schedules/phase_three/schedule_pregnancy.py +2 -3
  531. meta_ae/tests/holidays.csv +0 -15
  532. meta_ae/tests/tests/test_actions.py +0 -127
  533. meta_ae/tests/urls.py +0 -10
  534. meta_analytics/dataframes/enrolled/__init__.py +0 -1
  535. meta_analytics/dataframes/enrolled/get_glucose_df.py +0 -122
  536. meta_analytics/tests/__init__.py +0 -0
  537. meta_analytics/tests/test_endpoints_by_date.py +0 -94
  538. meta_consent/tests/__init__.py +0 -0
  539. meta_consent/tests/holidays.csv +0 -15
  540. meta_consent/tests/tests/__init__.py +0 -0
  541. meta_consent/tests/tests/test_form_validators.py +0 -110
  542. meta_consent/tests/tests/test_subject_consent.py +0 -10
  543. meta_consent/tests/urls.py +0 -17
  544. meta_dashboard/templates/meta_dashboard/bootstrap3/subject/dashboard.html +0 -11
  545. meta_dashboard/tests/__init__.py +0 -0
  546. meta_dashboard/tests/admin.py +0 -22
  547. meta_dashboard/tests/holidays.csv +0 -15
  548. meta_dashboard/tests/tests/__init__.py +0 -0
  549. meta_dashboard/tests/urls.py +0 -55
  550. meta_edc/tests/__init__.py +0 -0
  551. meta_edc/tests/tests/__init__.py +0 -0
  552. meta_edc/tests/tests/test_endpoints.py +0 -554
  553. meta_edc-0.3.39.dist-info/AUTHORS +0 -0
  554. meta_edc-0.3.39.dist-info/METADATA +0 -766
  555. meta_edc-0.3.39.dist-info/WHEEL +0 -5
  556. meta_edc-0.3.39.dist-info/top_level.txt +0 -20
  557. meta_labs/tests/__init__.py +0 -0
  558. meta_labs/tests/test_labs.py +0 -27
  559. meta_labs/tests/test_reportables.py +0 -16
  560. meta_labs/tests/urls.py +0 -4
  561. meta_lists/tests/__init__.py +0 -0
  562. meta_lists/tests/test_lists.py +0 -8
  563. meta_pharmacy/admin/actions.py +0 -38
  564. meta_prn/tests/__init__.py +0 -0
  565. meta_prn/tests/tests/__init__.py +0 -0
  566. meta_prn/tests/tests/test_actions.py +0 -97
  567. meta_prn/tests/tests/test_dm_referral.py +0 -206
  568. meta_prn/tests/tests/test_manager_order.py +0 -14
  569. meta_prn/tests/tests/test_pregnancy_notification.py +0 -93
  570. meta_prn/tests/urls.py +0 -10
  571. meta_rando/tests/__init__.py +0 -0
  572. meta_rando/tests/tests/__init__.py +0 -0
  573. meta_rando/tests/tests/test_randomizers.py +0 -57
  574. meta_reports/tests/__init__.py +0 -0
  575. meta_reports/tests/test_reports.py +0 -35
  576. meta_reports/tests/test_sql_gen.py +0 -5
  577. meta_reports/tests/urls.py +0 -4
  578. meta_screening/offline_models.py +0 -3
  579. meta_screening/tests/__init__.py +0 -0
  580. meta_screening/tests/holidays.csv +0 -15
  581. meta_screening/tests/meta_test_case_mixin.py +0 -216
  582. meta_screening/tests/options.py +0 -127
  583. meta_screening/tests/tests/__init__.py +0 -0
  584. meta_screening/tests/tests/test_forms.py +0 -397
  585. meta_screening/tests/tests/test_screening_part_one.py +0 -108
  586. meta_screening/tests/tests/test_screening_part_three.py +0 -436
  587. meta_screening/tests/tests/test_screening_part_two.py +0 -84
  588. meta_sites/tests/__init__.py +0 -0
  589. meta_sites/tests/test_sites.py +0 -12
  590. meta_sites/tests/urls.py +0 -4
  591. meta_stats/__init__.py +0 -0
  592. meta_stats/incidence.py +0 -16
  593. meta_stats/models.py +0 -0
  594. meta_stats/tests/__init__.py +0 -0
  595. meta_stats/tests/tests/__init__.py +0 -0
  596. meta_stats/tests/tests/test_incidence.py +0 -10
  597. meta_subject/tests/__init__.py +0 -0
  598. meta_subject/tests/holidays.csv +0 -15
  599. meta_subject/tests/tests/__init__.py +0 -0
  600. meta_subject/tests/tests/test_egfr.py +0 -234
  601. meta_subject/tests/tests/test_fixes.py +0 -64
  602. meta_subject/tests/tests/test_followup.py +0 -52
  603. meta_subject/tests/tests/test_manager_order.py +0 -11
  604. meta_subject/tests/tests/test_medication_adherence.py +0 -75
  605. meta_subject/tests/tests/test_metadata_rules.py +0 -135
  606. meta_subject/tests/tests/test_mnsi.py +0 -317
  607. meta_subject/tests/tests/test_patient_history_form.py +0 -74
  608. meta_subject/tests/tests/test_physical_exam.py +0 -84
  609. meta_subject/tests/tests/test_sf12.py +0 -173
  610. meta_subject/tests/tests/test_study_medication.py +0 -230
  611. meta_subject/tests/urls.py +0 -24
  612. meta_visit_schedule/tests/__init__.py +0 -0
  613. meta_visit_schedule/tests/tests/__init__.py +0 -0
  614. meta_visit_schedule/tests/tests/test_schedule.py +0 -181
  615. meta_visit_schedule/tests/urls.py +0 -4
  616. tests/__init__.py +0 -0
  617. tests/etc/randomization_list.csv +0 -241
  618. tests/etc/randomization_list_phase_three.csv +0 -241
  619. tests/etc/user-aes-local.key +0 -0
  620. tests/etc/user-aes-restricted.key +0 -1
  621. tests/etc/user-rsa-local-private.pem +0 -27
  622. tests/etc/user-rsa-local-public.pem +0 -9
  623. tests/etc/user-rsa-restricted-private.pem +0 -27
  624. tests/etc/user-rsa-restricted-public.pem +0 -9
  625. tests/etc/user-salt-local.key +0 -0
  626. tests/etc/user-salt-restricted.key +0 -0
  627. tests/holidays.csv +0 -15
  628. tests/test_settings.py +0 -186
  629. /meta_ae/templates/meta_ae/{bootstrap3/ae_initial_description.html → aeinitial_description.html} +0 -0
  630. /meta_dashboard/templates/meta_dashboard/{bootstrap3/buttons → buttons}/add_consent_button.html +0 -0
  631. /meta_dashboard/templates/meta_dashboard/{bootstrap3/buttons → buttons}/dashboard_button.html +0 -0
  632. /meta_dashboard/templates/meta_dashboard/{bootstrap3/buttons → buttons}/refusal_button.html +0 -0
  633. /meta_dashboard/templates/meta_dashboard/{bootstrap3/screening → screening}/listboard.html +0 -0
  634. /meta_dashboard/templates/meta_dashboard/{bootstrap3/subject → subject}/listboard.html +0 -0
  635. {meta_edc-0.3.39.dist-info → meta_edc-1.4.0.dist-info/licenses}/LICENSE +0 -0
  636. /meta_ae/tests/__init__.py → /meta_subject/management/__init__py.py +0 -0
  637. /meta_ae/tests/tests/__init__.py → /meta_subject/management/commands/__init__py.py +0 -0
@@ -0,0 +1,81 @@
1
+ import pandas as pd
2
+ from great_tables import GT, html, loc, style
3
+
4
+
5
+ def df_as_great_table(
6
+ df_table: pd.DataFrame,
7
+ title=None,
8
+ subtitle=None,
9
+ ):
10
+ """Used by monitoring report"""
11
+ return (
12
+ GT(df_table)
13
+ .tab_header(title=html(f'<div class="table-header">{title}</div>'), subtitle=subtitle)
14
+ .cols_align(align="left", columns=[0, 1])
15
+ .cols_align(align="right", columns=list(range(2, len(df_table.columns))))
16
+ .opt_stylize(style=3)
17
+ .opt_row_striping(row_striping=True)
18
+ .opt_vertical_padding(scale=1.2)
19
+ .opt_horizontal_padding(scale=1.0)
20
+ .tab_options(
21
+ table_width="100%",
22
+ stub_background_color="snow",
23
+ row_group_border_bottom_style="hidden",
24
+ row_group_padding=0.5,
25
+ row_group_background_color="snow",
26
+ table_background_color="snow",
27
+ table_font_size=10,
28
+ )
29
+ .tab_style(
30
+ style=[style.fill(color="snow"), style.text(color="black")],
31
+ locations=loc.body(
32
+ columns=list(range(0, len(df_table.columns))),
33
+ rows=list(range(0, len(df_table))),
34
+ ),
35
+ )
36
+ .tab_style(
37
+ style=[style.fill(color="lightgray"), style.text(color="black")],
38
+ locations=loc.body(
39
+ columns=[0],
40
+ rows=list(range(0, len(df_table))),
41
+ ),
42
+ )
43
+ )
44
+
45
+
46
+ def df_as_great_table2(
47
+ df_table: pd.DataFrame,
48
+ title=None,
49
+ subtitle=None,
50
+ rowname_col: str | None = None,
51
+ groupname_col: str | None = None,
52
+ ):
53
+ """Used by monitoring report"""
54
+ rowname_col = rowname_col or "label"
55
+ groupname_col = groupname_col or "visit_code"
56
+ return (
57
+ GT(df_table, rowname_col=rowname_col, groupname_col=groupname_col)
58
+ .tab_header(title=html(f'<div class="table-header">{title}</div>'), subtitle=subtitle)
59
+ .cols_align(align="left", columns=[0, 1])
60
+ .cols_align(align="right", columns=list(range(2, len(df_table.columns))))
61
+ .opt_stylize(style=3)
62
+ .opt_row_striping(row_striping=True)
63
+ .opt_vertical_padding(scale=1.2)
64
+ .opt_horizontal_padding(scale=1.0)
65
+ .tab_options(
66
+ table_width="100%",
67
+ stub_background_color="snow",
68
+ row_group_border_bottom_style="hidden",
69
+ row_group_padding=0.5,
70
+ row_group_background_color="snow",
71
+ table_background_color="snow",
72
+ table_font_size=10,
73
+ )
74
+ .tab_style(
75
+ style=[style.fill(color="snow"), style.text(color="black")],
76
+ locations=loc.body(
77
+ columns=list(range(0, len(df_table.columns))),
78
+ rows=list(range(0, len(df_table))),
79
+ ),
80
+ )
81
+ )
meta_auth/auths.py CHANGED
@@ -1,5 +1,4 @@
1
1
  from edc_action_item.auth_objects import ACTION_ITEM, ACTION_ITEM_EXPORT
2
- from edc_adverse_event.constants import TMG_ROLE
3
2
  from edc_appointment.auth_objects import APPOINTMENT_EXPORT
4
3
  from edc_auth.constants import (
5
4
  AUDITOR,
@@ -10,6 +9,7 @@ from edc_auth.constants import (
10
9
  CLINICIAN_SUPER_ROLE,
11
10
  NURSE_ROLE,
12
11
  PII,
12
+ TMG_ROLE,
13
13
  )
14
14
  from edc_auth.site_auths import site_auths
15
15
  from edc_data_manager.auth_objects import DATA_MANAGER_EXPORT, DATA_MANAGER_ROLE
@@ -1,7 +1,8 @@
1
- from edc_action_item import Action, site_action_items
2
- from edc_constants.constants import HIGH_PRIORITY
1
+ from clinicedc_constants import HIGH_PRIORITY
2
+ from edc_action_item.action import Action
3
+ from edc_action_item.site_action_items import site_action_items
3
4
 
4
- from .constants import RECONSENT_ACTION
5
+ from .constants import CONSENT_V1_EXTENSION_ACTION, RECONSENT_ACTION
5
6
 
6
7
 
7
8
  class ReconsentAction(Action):
@@ -23,4 +24,22 @@ class ReconsentAction(Action):
23
24
  return False
24
25
 
25
26
 
27
+ class ConsentV1ExtensionAction(Action):
28
+ name = CONSENT_V1_EXTENSION_ACTION
29
+ display_name = "Ask to extend followup (required)"
30
+ reference_model = "meta_consent.subjectconsentv1ext"
31
+ priority = HIGH_PRIORITY
32
+ show_on_dashboard = True
33
+ show_link_to_changelist = True
34
+ admin_site_name = "meta_consent_admin"
35
+ show_link_to_add = True
36
+ create_by_user = True
37
+ singleton = True
38
+ instructions = "Participant must complete as soon as able. "
39
+
40
+ def reopen_action_item_on_change(self):
41
+ return False
42
+
43
+
26
44
  site_action_items.register(ReconsentAction)
45
+ site_action_items.register(ConsentV1ExtensionAction)
@@ -1,2 +1,9 @@
1
1
  from .subject_consent_admin import SubjectConsentAdmin
2
2
  from .subject_consent_v1_admin import SubjectConsentV1Admin
3
+ from .subject_consent_v1_ext_admin import SubjectConsentV1ExtAdmin
4
+
5
+ __all__ = [
6
+ "SubjectConsentAdmin",
7
+ "SubjectConsentV1Admin",
8
+ "SubjectConsentV1ExtAdmin",
9
+ ]
@@ -1 +1,3 @@
1
1
  from .create_missing_prescriptions import create_missing_metformin_rx
2
+
3
+ __all__ = ["create_missing_metformin_rx"]
@@ -9,7 +9,7 @@ from meta_pharmacy.constants import METFORMIN
9
9
 
10
10
 
11
11
  @admin.action(permissions=["view"], description="Create missing METFORMIN prescription")
12
- def create_missing_metformin_rx(modeladmin, request, queryset):
12
+ def create_missing_metformin_rx(modeladmin, request, queryset): # noqa: ARG001
13
13
  medication = Medication.objects.get(name=METFORMIN)
14
14
  total = queryset.count()
15
15
  subject_identifiers = queryset.values_list("subject_identifier", flat=True)
@@ -24,7 +24,7 @@ def create_missing_metformin_rx(modeladmin, request, queryset):
24
24
  subject_identifier=instance.subject_identifier,
25
25
  report_datetime=instance.consent_datetime,
26
26
  randomizer_name=get_meta_version(),
27
- medications=[medication],
27
+ medication_names=[medication.name],
28
28
  site_id=instance.site.id,
29
29
  )
30
30
  except PrescriptionAlreadyExists:
@@ -0,0 +1,22 @@
1
+ from clinicedc_constants import NO, NOT_APPLICABLE, YES
2
+ from django.contrib.admin import SimpleListFilter
3
+ from edc_constants.choices import YES_NO_NA
4
+
5
+
6
+ class AgreesListFilter(SimpleListFilter):
7
+ title = "Agrees"
8
+ parameter_name = "agrees"
9
+
10
+ def lookups(self, request, model_admin): # noqa: ARG002
11
+ return YES_NO_NA
12
+
13
+ def queryset(self, request, queryset): # noqa: ARG002
14
+ qs = None
15
+ if self.value():
16
+ if self.value() == YES:
17
+ qs = queryset.filter(agrees_to_extension=YES)
18
+ elif self.value() == NO:
19
+ qs = queryset.filter(agrees_to_extension=NO)
20
+ elif self.value() == NOT_APPLICABLE:
21
+ qs = queryset.filter(agrees_to_extension=NOT_APPLICABLE)
22
+ return qs
@@ -21,14 +21,13 @@ from ..models import SubjectConsent
21
21
 
22
22
 
23
23
  class SubjectConsentModelAdminMixin:
24
-
25
24
  form = SubjectConsentForm
26
25
 
27
- actions = [
26
+ actions = (
28
27
  flag_as_verified_against_paper,
29
28
  unflag_as_verified_against_paper,
30
29
  "create_missing_metformin_rx",
31
- ]
30
+ )
32
31
 
33
32
  fieldsets = (
34
33
  (
@@ -73,7 +72,7 @@ class SubjectConsentModelAdminMixin:
73
72
 
74
73
  search_fields = ("subject_identifier", "screening_identifier", "identity")
75
74
 
76
- radio_fields = {
75
+ radio_fields = { # noqa: RUF012
77
76
  "gender": admin.VERTICAL,
78
77
  "assessment_score": admin.VERTICAL,
79
78
  "consent_copy": admin.VERTICAL,
@@ -127,7 +126,7 @@ class SubjectConsentModelAdminMixin:
127
126
  subject_identifier=instance.subject_identifier,
128
127
  report_datetime=instance.consent_datetime,
129
128
  randomizer_name=get_meta_version(),
130
- medications=[medication],
129
+ medication_names=[medication.name],
131
130
  site_id=instance.site.id,
132
131
  )
133
132
  except PrescriptionAlreadyExists:
@@ -0,0 +1,93 @@
1
+ from django.contrib import admin
2
+ from django.utils.translation import gettext_lazy as _
3
+ from django_audit_fields import audit_fieldset_tuple
4
+ from edc_model_admin.dashboard import ModelAdminSubjectDashboardMixin
5
+ from edc_model_admin.history import SimpleHistoryAdmin
6
+
7
+ from ..admin_site import meta_consent_admin
8
+ from ..forms import SubjectConsentV1ExtForm
9
+ from ..models import SubjectConsentV1Ext
10
+ from .list_filters import AgreesListFilter
11
+
12
+
13
+ @admin.register(SubjectConsentV1Ext, site=meta_consent_admin)
14
+ class SubjectConsentV1ExtAdmin(
15
+ ModelAdminSubjectDashboardMixin,
16
+ SimpleHistoryAdmin,
17
+ ):
18
+ form = SubjectConsentV1ExtForm
19
+
20
+ additional_instructions = (
21
+ "This consent offers the participant the option to agree to "
22
+ "extend clinic followup from the original 36 months to 48 months. "
23
+ )
24
+
25
+ fieldsets = (
26
+ (
27
+ None,
28
+ {
29
+ "fields": (
30
+ "subject_consent",
31
+ "report_datetime",
32
+ "agrees_to_extension",
33
+ )
34
+ },
35
+ ),
36
+ (
37
+ "Review Questions",
38
+ {
39
+ "fields": (
40
+ "consent_reviewed",
41
+ "study_questions",
42
+ "assessment_score",
43
+ "consent_signature",
44
+ "consent_copy",
45
+ ),
46
+ "description": _("The following questions are directed to the interviewer."),
47
+ },
48
+ ),
49
+ audit_fieldset_tuple,
50
+ )
51
+
52
+ list_display = (
53
+ "subject_consent",
54
+ "report_date",
55
+ "agrees",
56
+ )
57
+
58
+ list_filter = (
59
+ "report_datetime",
60
+ AgreesListFilter,
61
+ )
62
+
63
+ radio_fields = { # noqa: RUF012
64
+ "agrees_to_extension": admin.VERTICAL,
65
+ "consent_reviewed": admin.VERTICAL,
66
+ "study_questions": admin.VERTICAL,
67
+ "assessment_score": admin.VERTICAL,
68
+ "consent_signature": admin.VERTICAL,
69
+ "consent_copy": admin.VERTICAL,
70
+ }
71
+
72
+ def get_readonly_fields(self, request, obj=None) -> tuple[str, ...]: # noqa: ARG002
73
+ if obj:
74
+ return ("subject_consent",)
75
+ return ()
76
+
77
+ def formfield_for_foreignkey(self, db_field, request, **kwargs):
78
+ if db_field.name == "subject_consent":
79
+ subject_identifier = request.GET.get("subject_identifier")
80
+ kwargs["queryset"] = db_field.related_model.objects.filter(
81
+ subject_identifier=subject_identifier
82
+ )
83
+ return super().formfield_for_foreignkey(db_field, request, **kwargs)
84
+
85
+ @admin.display(description="Agrees")
86
+ def agrees(self, obj):
87
+ return obj.agrees_to_extension
88
+
89
+ @admin.display(description="Report date")
90
+ def report_date(self, obj):
91
+ if obj:
92
+ return obj.report_datetime.date()
93
+ return None
@@ -1,7 +1,7 @@
1
+ from clinicedc_constants import NO, NULL_STRING, YES
1
2
  from dateutil.relativedelta import relativedelta
2
3
  from django.contrib.sites.models import Site
3
- from edc_constants.constants import NO, YES
4
- from edc_utils import get_utcnow
4
+ from django.utils import timezone
5
5
  from faker import Faker
6
6
  from model_bakery.recipe import Recipe, seq
7
7
 
@@ -13,10 +13,10 @@ opts = dict(
13
13
  assessment_score=YES,
14
14
  confirm_identity=seq("12315678"),
15
15
  consent_copy=YES,
16
- consent_datetime=get_utcnow(),
16
+ consent_datetime=timezone.now(),
17
17
  consent_reviewed=YES,
18
18
  consent_signature=YES,
19
- dob=get_utcnow() - relativedelta(years=25),
19
+ dob=timezone.now() - relativedelta(years=25),
20
20
  first_name=fake.first_name,
21
21
  gender="M",
22
22
  identity=seq("12315678"),
@@ -26,10 +26,10 @@ opts = dict(
26
26
  is_incarcerated=NO,
27
27
  is_literate=YES,
28
28
  last_name=fake.last_name,
29
- screening_identifier=None,
29
+ screening_identifier=NULL_STRING,
30
30
  study_questions=YES,
31
31
  site=Site.objects.get_current(),
32
- subject_identifier=None,
32
+ subject_identifier=NULL_STRING,
33
33
  user_created="erikvw",
34
34
  user_modified="erikvw",
35
35
  )
@@ -43,7 +43,7 @@ subjectreconsent = Recipe(
43
43
  assessment_score=YES,
44
44
  study_questions=YES,
45
45
  consent_copy=YES,
46
- action_identifier=None,
46
+ action_identifier=NULL_STRING,
47
47
  user_created="erikvw",
48
48
  user_modified="erikvw",
49
49
  )
meta_consent/consents.py CHANGED
@@ -1,6 +1,10 @@
1
+ from datetime import datetime
2
+ from zoneinfo import ZoneInfo
3
+
4
+ from clinicedc_constants import FEMALE, MALE
1
5
  from edc_consent.consent_definition import ConsentDefinition
6
+ from edc_consent.consent_definition_extension import ConsentDefinitionExtension
2
7
  from edc_consent.site_consents import site_consents
3
- from edc_constants.constants import FEMALE, MALE
4
8
  from edc_protocol.research_protocol_config import ResearchProtocolConfig
5
9
 
6
10
  consent_v1 = ConsentDefinition(
@@ -18,6 +22,15 @@ consent_v1 = ConsentDefinition(
18
22
  "meta_screening.screeningparttwo",
19
23
  "meta_screening.screeningpartthree",
20
24
  ],
25
+ timepoints=list(range(1, 14 + 1)),
26
+ )
27
+
28
+ consent_v1_ext = ConsentDefinitionExtension(
29
+ "meta_consent.subjectconsentv1ext",
30
+ version="1.1",
31
+ start=datetime(2024, 12, 16, tzinfo=ZoneInfo("UTC")),
32
+ extends=consent_v1,
33
+ timepoints=[15, 16, 17, 18],
21
34
  )
22
35
 
23
- site_consents.register(consent_v1)
36
+ site_consents.register(consent_v1, extended_by=consent_v1_ext)
meta_consent/constants.py CHANGED
@@ -1 +1,2 @@
1
1
  RECONSENT_ACTION = "reconsent"
2
+ CONSENT_V1_EXTENSION_ACTION = "consent_v1_ext"
@@ -1 +1,3 @@
1
1
  from .subject_consent_form_validator import SubjectConsentFormValidator
2
+
3
+ __all__ = ["SubjectConsentFormValidator"]
@@ -1,3 +1,11 @@
1
1
  from .subject_consent_form import SubjectConsentForm
2
+ from .subject_consent_v1_ext_form import SubjectConsentV1ExtForm
2
3
  from .subject_consent_v1_form import SubjectConsentV1Form
3
4
  from .subject_reconsent_form import SubjectReconsentForm
5
+
6
+ __all__ = [
7
+ "SubjectConsentForm",
8
+ "SubjectConsentV1ExtForm",
9
+ "SubjectConsentV1Form",
10
+ "SubjectReconsentForm",
11
+ ]
@@ -0,0 +1,47 @@
1
+ from clinicedc_constants import NOT_APPLICABLE
2
+ from django import forms
3
+ from edc_consent.modelform_mixins import ReviewFieldsModelFormMixin
4
+ from edc_form_validators import FormValidatorMixin
5
+ from edc_sites.forms import SiteModelFormMixin
6
+ from edc_utils.date import to_local
7
+
8
+ from ..consents import consent_v1_ext
9
+ from ..models import SubjectConsentV1Ext
10
+
11
+
12
+ class SubjectConsentV1ExtForm(
13
+ SiteModelFormMixin, ReviewFieldsModelFormMixin, FormValidatorMixin, forms.ModelForm
14
+ ):
15
+ def clean(self):
16
+ cleaned_data = super().clean()
17
+ start_datetime = to_local(consent_v1_ext.start)
18
+ if (
19
+ cleaned_data.get("report_datetime")
20
+ and cleaned_data.get("report_datetime") < start_datetime
21
+ ):
22
+ dt = start_datetime.date().strftime("%Y-%m-%d")
23
+ raise forms.ValidationError(
24
+ {"report_datetime": f"Cannot be before consent approval date {dt}."}
25
+ )
26
+
27
+ if cleaned_data.get("agrees_to_extension") == NOT_APPLICABLE:
28
+ raise forms.ValidationError({"agrees_to_extension": "Invalid option"})
29
+ return cleaned_data
30
+
31
+ widgets = { # noqa: RUF012
32
+ "subject_identifier": forms.TextInput(attrs={"readonly": "readonly"}),
33
+ }
34
+
35
+ class Meta:
36
+ model = SubjectConsentV1Ext
37
+ fields = "__all__"
38
+ labels = { # noqa: RUF012
39
+ "study_questions": (
40
+ "I have answered all questions the participant had about the "
41
+ "follow-up extension"
42
+ ),
43
+ "assessment_score": (
44
+ "I have asked the participant questions about the follow-up extension and "
45
+ "the participant has demonstrated understanding"
46
+ ),
47
+ }
@@ -23,15 +23,15 @@ class SubjectReconsentForm(
23
23
  subject_identifier=cleaned_data.get("subject_identifier"),
24
24
  identity=cleaned_data.get("identity"),
25
25
  )
26
- except ObjectDoesNotExist:
27
- raise forms.ValidationError({"identity": "Identity number does not match."})
26
+ except ObjectDoesNotExist as e:
27
+ raise forms.ValidationError({"identity": "Identity number does not match."}) from e
28
28
  return cleaned_data
29
29
 
30
30
  class Meta:
31
31
  model = SubjectReconsent
32
32
  fields = "__all__"
33
- help_text = {"action_identifier": "(read-only)", "subject_identifier": "(read-only)"}
34
- widgets = {
33
+ help_text = {"action_identifier": "(read-only)", "subject_identifier": "(read-only)"} # noqa: RUF012
34
+ widgets = { # noqa: RUF012
35
35
  "action_identifier": forms.TextInput(attrs={"readonly": "readonly"}),
36
36
  "subject_identifier": forms.TextInput(attrs={"readonly": "readonly"}),
37
37
  }
@@ -1,3 +1,5 @@
1
+ import sys
2
+
1
3
  from django.core.management.base import BaseCommand, CommandError
2
4
  from edc_pharmacy.exceptions import PrescriptionAlreadyExists
3
5
  from edc_pharmacy.models import Medication, Rx
@@ -12,7 +14,7 @@ from meta_pharmacy.constants import METFORMIN
12
14
  class Command(BaseCommand):
13
15
  help = "Create missing prescriptions"
14
16
 
15
- def handle(self, *args, **options):
17
+ def handle(self, *args, **options): # noqa: ARG002
16
18
  medication = Medication.objects.get(name=METFORMIN)
17
19
  subject_identifiers = Rx.objects.values_list("subject_identifier", flat=True).all()
18
20
  subject_consents_wo_rx = SubjectConsent.objects.exclude(
@@ -25,10 +27,10 @@ class Command(BaseCommand):
25
27
  subject_identifier=instance.subject_identifier,
26
28
  report_datetime=instance.consent_datetime,
27
29
  randomizer_name=get_meta_version(),
28
- medications=[medication],
30
+ medication_names=[medication.name],
29
31
  site_id=instance.site.id,
30
32
  )
31
33
  except PrescriptionAlreadyExists:
32
34
  pass
33
35
  except CommandError as e:
34
- print(f"Failed for {instance.subject_identifier}. Got {e}")
36
+ sys.stdout.write(f"Failed for {instance.subject_identifier}. Got {e}\n")
@@ -8,7 +8,7 @@ import django.db.models.deletion
8
8
  import django_audit_fields.fields.hostname_modification_field
9
9
  import django_audit_fields.fields.userfield
10
10
  import django_audit_fields.fields.uuid_auto_field
11
- import django_audit_fields.models.audit_model_mixin
11
+ import django.utils.timezone
12
12
  import django_crypto_fields.fields.encrypted_char_field
13
13
  import django_crypto_fields.fields.encrypted_text_field
14
14
  import django_crypto_fields.fields.firstname_field
@@ -55,14 +55,14 @@ class Migration(migrations.Migration):
55
55
  "created",
56
56
  models.DateTimeField(
57
57
  blank=True,
58
- default=django_audit_fields.models.audit_model_mixin.utcnow,
58
+ default=django.utils.timezone.now,
59
59
  ),
60
60
  ),
61
61
  (
62
62
  "modified",
63
63
  models.DateTimeField(
64
64
  blank=True,
65
- default=django_audit_fields.models.audit_model_mixin.utcnow,
65
+ default=django.utils.timezone.now,
66
66
  ),
67
67
  ),
68
68
  (
@@ -288,14 +288,14 @@ class Migration(migrations.Migration):
288
288
  "created",
289
289
  models.DateTimeField(
290
290
  blank=True,
291
- default=django_audit_fields.models.audit_model_mixin.utcnow,
291
+ default=django.utils.timezone.now,
292
292
  ),
293
293
  ),
294
294
  (
295
295
  "modified",
296
296
  models.DateTimeField(
297
297
  blank=True,
298
- default=django_audit_fields.models.audit_model_mixin.utcnow,
298
+ default=django.utils.timezone.now,
299
299
  ),
300
300
  ),
301
301
  (
@@ -773,14 +773,14 @@ class Migration(migrations.Migration):
773
773
  "created",
774
774
  models.DateTimeField(
775
775
  blank=True,
776
- default=django_audit_fields.models.audit_model_mixin.utcnow,
776
+ default=django.utils.timezone.now,
777
777
  ),
778
778
  ),
779
779
  (
780
780
  "modified",
781
781
  models.DateTimeField(
782
782
  blank=True,
783
- default=django_audit_fields.models.audit_model_mixin.utcnow,
783
+ default=django.utils.timezone.now,
784
784
  ),
785
785
  ),
786
786
  (
@@ -1043,14 +1043,14 @@ class Migration(migrations.Migration):
1043
1043
  "created",
1044
1044
  models.DateTimeField(
1045
1045
  blank=True,
1046
- default=django_audit_fields.models.audit_model_mixin.utcnow,
1046
+ default=django.utils.timezone.now,
1047
1047
  ),
1048
1048
  ),
1049
1049
  (
1050
1050
  "modified",
1051
1051
  models.DateTimeField(
1052
1052
  blank=True,
1053
- default=django_audit_fields.models.audit_model_mixin.utcnow,
1053
+ default=django.utils.timezone.now,
1054
1054
  ),
1055
1055
  ),
1056
1056
  (
@@ -8,7 +8,7 @@ import django.db.models.deletion
8
8
  import django_audit_fields.fields.hostname_modification_field
9
9
  import django_audit_fields.fields.userfield
10
10
  import django_audit_fields.fields.uuid_auto_field
11
- import django_audit_fields.models.audit_model_mixin
11
+ import django.utils.timezone
12
12
  import django_crypto_fields.fields.encrypted_char_field
13
13
  import django_crypto_fields.fields.encrypted_text_field
14
14
  import django_crypto_fields.fields.firstname_field
@@ -24,7 +24,6 @@ import uuid
24
24
 
25
25
 
26
26
  class Migration(migrations.Migration):
27
-
28
27
  dependencies = [
29
28
  ("sites", "0002_alter_domain_unique"),
30
29
  migrations.swappable_dependency(settings.AUTH_USER_MODEL),
@@ -48,15 +47,11 @@ class Migration(migrations.Migration):
48
47
  ),
49
48
  (
50
49
  "created",
51
- models.DateTimeField(
52
- blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
53
- ),
50
+ models.DateTimeField(blank=True, default=django.utils.timezone.now),
54
51
  ),
55
52
  (
56
53
  "modified",
57
- models.DateTimeField(
58
- blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
59
- ),
54
+ models.DateTimeField(blank=True, default=django.utils.timezone.now),
60
55
  ),
61
56
  (
62
57
  "user_created",