clinicedc 2.0.6__py3-none-any.whl → 2.0.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 clinicedc might be problematic. Click here for more details.

Files changed (495) hide show
  1. {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/METADATA +2 -2
  2. {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/RECORD +489 -441
  3. {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/WHEEL +1 -1
  4. edc_action_item/action.py +1 -1
  5. edc_action_item/action_item_notification.py +2 -2
  6. edc_action_item/auths.py +37 -32
  7. edc_action_item/create_action_item.py +1 -1
  8. edc_action_item/decorators.py +1 -1
  9. edc_action_item/migrations/0001_initial.py +21 -22
  10. edc_action_item/migrations/0006_auto_20180707_1659.py +4 -4
  11. edc_action_item/migrations/0008_auto_20180809_0303.py +4 -4
  12. edc_action_item/migrations/0015_auto_20190114_0250.py +4 -4
  13. edc_action_item/migrations/0017_auto_20190305_0123.py +11 -30
  14. edc_action_item/migrations/0030_edcpermissions.py +3 -2
  15. edc_action_item/migrations/0039_alter_actionitem_auto_created_comment_and_more.py +398 -0
  16. edc_action_item/migrations/0040_alter_actionitem_report_datetime_and_more.py +34 -0
  17. edc_action_item/models/action_item.py +9 -4
  18. edc_action_item/models/action_model_mixin.py +5 -6
  19. edc_action_item/models/reference.py +2 -2
  20. edc_action_item/models/signals.py +22 -23
  21. edc_action_item/post_migrate_signals.py +1 -1
  22. edc_action_item/send_email.py +0 -85
  23. edc_action_item/site_action_items.py +5 -9
  24. edc_action_item/utils.py +3 -3
  25. edc_adherence/migrations/0005_alter_nonadherencereasons_extra_value_and_more.py +36 -0
  26. edc_adherence/model_mixins.py +1 -1
  27. edc_adverse_event/auths.py +55 -51
  28. edc_adverse_event/migrations/0001_initial.py +5 -4
  29. edc_adverse_event/migrations/0002_auto_20190802_0059.py +3 -2
  30. edc_adverse_event/migrations/0008_auto_20220825_0451.py +3 -2
  31. edc_adverse_event/migrations/0009_auto_20220907_0157.py +3 -2
  32. edc_adverse_event/migrations/0016_alter_aeactionclassification_device_created_and_more.py +285 -0
  33. edc_adverse_event/model_mixins/ae_followup/ae_followup_fields_model_mixin.py +2 -2
  34. edc_adverse_event/model_mixins/ae_initial/ae_initial_fields_model_mixin.py +6 -5
  35. edc_adverse_event/model_mixins/ae_special_interest/aesi_fields_model_mixin.py +2 -2
  36. edc_adverse_event/model_mixins/ae_susar/ae_susar_fields_model_mixin.py +2 -2
  37. edc_adverse_event/model_mixins/ae_tmg/ae_tmg_fields_model_mixin.py +15 -11
  38. edc_adverse_event/model_mixins/ae_tmg/ae_tmg_methods_model_mixin.py +2 -4
  39. edc_adverse_event/model_mixins/death_report/death_report_model_mixin.py +5 -4
  40. edc_adverse_event/model_mixins/death_report/death_report_tmg_model_mixin.py +6 -3
  41. edc_adverse_event/model_mixins/death_report/simple_death_report_model_mixin.py +2 -2
  42. edc_adverse_event/model_mixins/hospitaization/hospitalization_model_mixin.py +4 -3
  43. edc_adverse_event/modeladmin_mixins/death_report_admin_mixin.py +3 -3
  44. edc_adverse_event/models/signals.py +7 -7
  45. edc_adverse_event/templatetags/edc_adverse_event_extras.py +5 -4
  46. edc_adverse_event/view_mixins/ae/ae_listboard_view_mixin.py +3 -5
  47. edc_adverse_event/view_mixins/ae/death_report_listboard_view_mixin.py +6 -8
  48. edc_adverse_event/view_mixins/tmg/tmg_ae_listboard_view_mixin.py +2 -2
  49. edc_adverse_event/views/tmg/summary_listboard_view.py +3 -2
  50. edc_appointment/admin/appointment_admin.py +2 -2
  51. edc_appointment/admin/list_filters.py +2 -2
  52. edc_appointment/auths.py +14 -10
  53. edc_appointment/creators/appointment_creator.py +1 -1
  54. edc_appointment/creators/appointments_creator.py +1 -1
  55. edc_appointment/form_validators/appointment_form_validator.py +108 -82
  56. edc_appointment/migrations/0003_auto_20161127_2226.py +5 -6
  57. edc_appointment/migrations/0006_auto_20170106_2118.py +5 -5
  58. edc_appointment/migrations/0018_auto_20190305_0123.py +5 -12
  59. edc_appointment/migrations/0050_alter_appointment_appt_type_and_more.py +220 -0
  60. edc_appointment/model_mixins/appointment_fields_model_mixin.py +1 -2
  61. edc_appointment/model_mixins/appointment_methods_model_mixin.py +2 -3
  62. edc_appointment/model_mixins/appointment_model_mixin.py +31 -28
  63. edc_appointment/model_mixins/window_period_model_mixin.py +6 -7
  64. edc_appointment/models/appointment.py +1 -1
  65. edc_appointment/models/signals.py +44 -35
  66. edc_appointment/utils.py +19 -24
  67. edc_appointment/view_utils/appointment_button.py +2 -2
  68. edc_auth/admin/user_admin.py +1 -1
  69. edc_auth/auth_objects/__init__.py +2 -20
  70. edc_auth/auth_objects/default_groups.py +13 -11
  71. edc_auth/auth_objects/default_roles.py +26 -24
  72. edc_auth/auth_updater/auth_updater.py +13 -2
  73. edc_auth/auth_updater/group_updater.py +12 -10
  74. edc_auth/auth_updater/role_updater.py +2 -2
  75. edc_auth/constants.py +10 -0
  76. edc_auth/import_users.py +3 -3
  77. edc_auth/migrations/0001_squashed_0033_alter_userprofile_is_multisite_viewer.py +5 -5
  78. edc_auth/migrations/0012_auto_20191026_0034.py +3 -2
  79. edc_auth/migrations/0013_auto_20191026_0055.py +3 -2
  80. edc_auth/migrations/0025_permissions.py +3 -2
  81. edc_auth/migrations/0035_alter_edcpermissions_device_created_and_more.py +85 -0
  82. edc_auth/models/user_profile.py +14 -11
  83. edc_auth/post_migrate_signals.py +1 -1
  84. edc_auth/site_auths.py +80 -67
  85. edc_consent/actions.py +4 -5
  86. edc_consent/auths.py +18 -12
  87. edc_consent/migrations/0001_initial.py +3 -2
  88. edc_consent/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
  89. edc_consent/model_mixins/consent_extension_model_mixin.py +4 -5
  90. edc_consent/model_mixins/requires_consent_fields_model_mixin.py +2 -2
  91. edc_consent/utils.py +1 -1
  92. edc_constants/constants.py +1 -0
  93. edc_crf/auths.py +5 -0
  94. edc_crf/migrations/0001_initial.py +3 -2
  95. edc_crf/migrations/0009_alter_crfstatus_device_created_and_more.py +54 -0
  96. edc_dashboard/auths.py +10 -6
  97. edc_dashboard/migrations/0001_initial.py +3 -2
  98. edc_dashboard/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
  99. edc_dashboard/templatetags/edc_dashboard_extras.py +3 -2
  100. edc_dashboard/url_config.py +92 -83
  101. edc_dashboard/url_names.py +4 -4
  102. edc_dashboard/view_mixins/url_request_context_mixin.py +6 -5
  103. edc_data_manager/action_items.py +4 -6
  104. edc_data_manager/admin/actions.py +5 -5
  105. edc_data_manager/admin/data_query_admin.py +12 -11
  106. edc_data_manager/auths.py +37 -34
  107. edc_data_manager/handlers/handlers.py +6 -7
  108. edc_data_manager/migrations/0001_initial.py +19 -19
  109. edc_data_manager/migrations/0025_edcpermissions.py +3 -2
  110. edc_data_manager/migrations/0040_alter_datadictionary_device_created_and_more.py +327 -0
  111. edc_data_manager/migrations/0041_alter_dataquery_dm_user_and_more.py +164 -0
  112. edc_data_manager/models/data_query.py +5 -5
  113. edc_data_manager/models/model_mixins.py +8 -8
  114. edc_data_manager/rule/query_rule_wrapper.py +7 -7
  115. edc_data_manager/rule/rule_runner.py +4 -3
  116. edc_document_status/model_mixins.py +1 -1
  117. edc_egfr/egfr.py +11 -7
  118. edc_egfr/model_mixins/egfr_model_mixin.py +3 -7
  119. edc_export/admin/data_request_admin.py +2 -2
  120. edc_export/archive_exporter.py +7 -5
  121. edc_export/auths.py +32 -28
  122. edc_export/files_archiver.py +3 -2
  123. edc_export/migrations/0001_initial.py +26 -26
  124. edc_export/migrations/0004_auto_20190305_0123.py +25 -72
  125. edc_export/migrations/0013_edcpermissions.py +3 -2
  126. edc_export/migrations/0022_alter_datarequest_description_and_more.py +611 -0
  127. edc_export/migrations/0023_alter_datarequesthistory_archive_filename_and_more.py +29 -0
  128. edc_export/model_exporter/file_history_updater.py +10 -10
  129. edc_export/model_exporter/model_exporter.py +17 -15
  130. edc_export/model_exporter/object_history_helpers.py +2 -2
  131. edc_export/models/data_request_history.py +4 -4
  132. edc_export/utils.py +10 -15
  133. edc_facility/auths.py +8 -3
  134. edc_facility/facility.py +16 -22
  135. edc_facility/import_holidays.py +13 -13
  136. edc_facility/migrations/0005_healthfacility_healthfacilitytypes_and_more.py +8 -7
  137. edc_facility/migrations/0016_alter_healthfacility_device_created_and_more.py +139 -0
  138. edc_facility/migrations/0017_alter_healthfacility_gps_and_more.py +54 -0
  139. edc_facility/model_mixins.py +5 -5
  140. edc_form_label/custom_label_condition.py +11 -8
  141. edc_form_label/form_label.py +1 -1
  142. edc_form_runners/auths.py +11 -6
  143. edc_form_runners/form_runner.py +3 -5
  144. edc_form_runners/migrations/0001_initial.py +3 -2
  145. edc_form_runners/migrations/0005_alter_issue_device_created_and_more.py +49 -0
  146. edc_form_validators/applicable_field_validator.py +7 -6
  147. edc_form_validators/base_form_validator.py +8 -9
  148. edc_form_validators/other_specify_field_validator.py +2 -8
  149. edc_form_validators/required_field_validator.py +19 -16
  150. edc_identifier/migrations/0001_squashed_0018_auto_20180128_1054.py +3 -3
  151. edc_identifier/migrations/0002_auto_20190305_0123.py +3 -6
  152. edc_identifier/migrations/0006_auto_20161127_2226.py +15 -15
  153. edc_identifier/migrations/0007_auto_20161204_2227.py +3 -3
  154. edc_identifier/migrations/0009_auto_20161221_2323.py +3 -5
  155. edc_identifier/migrations/0010_auto_20170112_0602.py +17 -17
  156. edc_identifier/migrations/0011_alter_identifiermodel_device_created_and_more.py +79 -0
  157. edc_identifier/model_mixins.py +1 -1
  158. edc_identifier/models.py +9 -9
  159. edc_identifier/research_identifier.py +11 -10
  160. edc_identifier/simple_identifier.py +9 -5
  161. edc_identifier/subject_identifier.py +3 -2
  162. edc_lab/auths.py +26 -23
  163. edc_lab/lab/aliquot_creator.py +5 -8
  164. edc_lab/lab/primary_aliquot.py +14 -5
  165. edc_lab/migrations/0001_initial.py +29 -29
  166. edc_lab/migrations/0008_auto_20170921_0719.py +3 -3
  167. edc_lab/migrations/0010_auto_20171127_1541.py +15 -15
  168. edc_lab/migrations/0012_auto_20180114_1438.py +3 -3
  169. edc_lab/migrations/0019_auto_20190305_0123.py +43 -127
  170. edc_lab/migrations/0036_alter_aliquot_comment_alter_aliquot_device_created_and_more.py +1139 -0
  171. edc_lab/migrations/0037_alter_historicalorder_order_datetime_and_more.py +31 -0
  172. edc_lab/model_mixins/aliquot/aliquot_identifier_model_mixin.py +2 -2
  173. edc_lab/model_mixins/aliquot/aliquot_model_mixin.py +2 -2
  174. edc_lab/model_mixins/panel_model_mixin.py +18 -7
  175. edc_lab/model_mixins/requisition/crf_with_requisition_model_mixin.py +2 -4
  176. edc_lab/model_mixins/requisition/requisition_model_mixin.py +13 -16
  177. edc_lab/model_mixins/requisition/requisition_verify_model_mixin.py +1 -1
  178. edc_lab/model_mixins/result/result_item_model_mixin.py +4 -4
  179. edc_lab/model_mixins/shipping/manifest_model_mixin.py +4 -5
  180. edc_lab/model_mixins/shipping/verify_model_mixin.py +4 -6
  181. edc_lab/models/aliquot.py +2 -2
  182. edc_lab/models/box.py +1 -1
  183. edc_lab/models/box_item.py +6 -7
  184. edc_lab/models/manifest/manifest.py +3 -3
  185. edc_lab/models/manifest/manifest_item.py +7 -7
  186. edc_lab/models/manifest/shipper.py +3 -4
  187. edc_lab/models/order.py +6 -4
  188. edc_lab/models/panel.py +4 -4
  189. edc_lab/models/result.py +2 -2
  190. edc_lab/models/result_item.py +2 -2
  191. edc_lab_dashboard/auths.py +16 -11
  192. edc_lab_dashboard/migrations/0001_initial.py +3 -2
  193. edc_lab_dashboard/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
  194. edc_lab_dashboard/views/action_views/receive_view.py +2 -2
  195. edc_lab_dashboard/views/action_views/verify_box_item_view.py +2 -2
  196. edc_lab_results/calculate_missing.py +8 -8
  197. edc_lab_results/form_validator_mixins/blood_results_form_validator_mixin.py +2 -2
  198. edc_lab_results/get_summary.py +26 -25
  199. edc_lab_results/model_mixins/blood_result_model_mixin.py +9 -7
  200. edc_lab_results/model_mixins/fbg_model_mixin.py +3 -3
  201. edc_lab_results/model_mixins/glucose_model_mixin.py +3 -3
  202. edc_lab_results/model_mixins/hba1c_model_mixin.py +3 -3
  203. edc_label/auths.py +6 -1
  204. edc_label/label_template.py +8 -8
  205. edc_label/migrations/0001_initial.py +3 -2
  206. edc_label/migrations/0007_alter_zpllabeltemplates_device_created_and_more.py +49 -0
  207. edc_list_data/list_model_maker.py +2 -2
  208. edc_list_data/load_list_data.py +11 -14
  209. edc_list_data/load_model_data.py +3 -3
  210. edc_list_data/model_mixins.py +12 -4
  211. edc_list_data/post_migrate_signals.py +1 -1
  212. edc_list_data/preload_data.py +4 -4
  213. edc_list_data/row.py +1 -1
  214. edc_list_data/site_list_data.py +6 -5
  215. edc_listboard/migrations/0001_initial.py +3 -2
  216. edc_listboard/migrations/0007_alter_listboard_device_created_and_more.py +49 -0
  217. edc_locator/auths.py +18 -13
  218. edc_locator/migrations/0001_initial.py +7 -7
  219. edc_locator/migrations/0018_auto_20190305_0123.py +5 -12
  220. edc_locator/migrations/0040_alter_historicalsubjectlocator_action_identifier_and_more.py +187 -0
  221. edc_locator/migrations/0041_alter_historicalsubjectlocator_report_datetime_and_more.py +27 -0
  222. edc_locator/model_mixins/locator_model_mixin.py +2 -2
  223. edc_locator/model_mixins/subject_contact_fields_mixin.py +1 -1
  224. edc_locator/modeladmin_mixins.py +5 -4
  225. edc_ltfu/model_mixins.py +7 -5
  226. edc_metadata/auths.py +11 -7
  227. edc_metadata/metadata/metadata.py +1 -1
  228. edc_metadata/metadata_rules/crf/crf_rule.py +1 -1
  229. edc_metadata/metadata_rules/decorators.py +1 -1
  230. edc_metadata/metadata_rules/metadata_rule_evaluator.py +5 -3
  231. edc_metadata/metadata_rules/rule.py +2 -3
  232. edc_metadata/metadata_rules/rule_evaluator.py +1 -1
  233. edc_metadata/migrations/0002_auto_20161127_2226.py +5 -5
  234. edc_metadata/migrations/0005_auto_20170112_0602.py +5 -5
  235. edc_metadata/migrations/0011_auto_20190305_0123.py +5 -12
  236. edc_metadata/migrations/0031_alter_crfmetadata_device_created_and_more.py +120 -0
  237. edc_metadata/model_mixins/updates/updates_crf_metadata_model_mixin.py +7 -4
  238. edc_metadata/model_mixins/updates/updates_requisition_metadata_model_mixin.py +5 -2
  239. edc_metadata/models/crf_metadata.py +5 -5
  240. edc_metadata/models/crf_metadata_model_mixin.py +4 -5
  241. edc_metadata/models/requisition_metadata.py +6 -6
  242. edc_metadata/models/signals.py +10 -11
  243. edc_metadata/views/refresh_metadata_actions_view.py +3 -3
  244. edc_model/models/address_mixin.py +6 -6
  245. edc_model/models/fields/initials_field.py +2 -1
  246. edc_model/models/historical_records.py +2 -9
  247. edc_model/models/url_model_mixin.py +2 -2
  248. edc_model/validators/date.py +7 -8
  249. edc_model_admin/list_filters/future_date_list_filter.py +3 -3
  250. edc_model_admin/list_filters/past_date_list_filter.py +3 -3
  251. edc_model_admin/mixins/model_admin_protect_pii_mixin.py +4 -5
  252. edc_model_fields/fields/other_charfield.py +2 -2
  253. edc_navbar/auths.py +18 -13
  254. edc_navbar/migrations/0004_auto_20220825_0451.py +3 -2
  255. edc_navbar/migrations/0009_alter_edcpermissions_device_created_and_more.py +49 -0
  256. edc_notification/auths.py +9 -4
  257. edc_notification/migrations/0001_initial.py +3 -3
  258. edc_notification/migrations/0004_auto_20190305_0123.py +3 -6
  259. edc_notification/migrations/0011_alter_notification_device_created_and_more.py +59 -0
  260. edc_notification/models/notification.py +1 -1
  261. edc_notification/notification/graded_event_notification.py +2 -2
  262. edc_notification/notification/model_notification.py +3 -30
  263. edc_notification/notification/new_model_notification.py +1 -1
  264. edc_notification/notification/notification.py +12 -12
  265. edc_notification/notification/updated_model_notification.py +2 -2
  266. edc_offstudy/auths.py +12 -7
  267. edc_offstudy/migrations/0001_initial.py +4 -4
  268. edc_offstudy/migrations/0002_auto_20180921_0434.py +4 -4
  269. edc_offstudy/migrations/0005_auto_20190305_0123.py +5 -12
  270. edc_offstudy/migrations/0023_alter_historicalsubjectoffstudy_action_identifier_and_more.py +188 -0
  271. edc_offstudy/migrations/0024_alter_historicalsubjectoffstudy_offstudy_datetime_and_more.py +43 -0
  272. edc_offstudy/model_mixins/offstudy_model_mixin.py +3 -2
  273. edc_pdutils/df_exporters/csv_exporter.py +33 -37
  274. edc_pdutils/df_exporters/csv_model_exporter.py +7 -3
  275. edc_pdutils/migrations/0001_initial.py +8 -8
  276. edc_pharmacy/admin/prescription/rx_refill_admin.py +4 -3
  277. edc_pharmacy/admin/reports/stock_availability_admin.py +5 -6
  278. edc_pharmacy/auths.py +19 -15
  279. edc_pharmacy/migrations/0001_initial.py +64 -63
  280. edc_pharmacy/migrations/0015_auto_20220913_2139.py +26 -26
  281. edc_pharmacy/migrations/0024_allocation_assignment_containerunits_dispense_and_more.py +81 -86
  282. edc_pharmacy/migrations/0037_remove_historicalstock_confirmed_at_site_by_and_more.py +5 -5
  283. edc_pharmacy/migrations/0039_remove_dispense_registered_subject_and_more.py +7 -8
  284. edc_pharmacy/migrations/0049_remove_stocktransferconfirmation_stock_and_more.py +12 -12
  285. edc_pharmacy/migrations/0050_remove_stocktransferconfirmation2_location_and_more.py +5 -5
  286. edc_pharmacy/migrations/0051_alter_historicalstocktransferconfirmationitem_options_and_more.py +3 -4
  287. edc_pharmacy/migrations/0053_alter_location_managers_alter_historicalstock_lot_and_more.py +3 -3
  288. edc_pharmacy/migrations/0057_scanduplicates.py +3 -3
  289. edc_pharmacy/migrations/0060_alter_container_max_per_subject_and_more.py +13 -15
  290. edc_pharmacy/migrations/0068_stockout.py +2 -3
  291. edc_pharmacy/migrations/0076_historicalstockadjustment_stockadjustment.py +5 -5
  292. edc_pharmacy/migrations/0077_historicalstockadjustment_adjustment_datetime_and_more.py +3 -4
  293. edc_pharmacy/migrations/0081_historicalconfirmation_confirmation.py +8 -8
  294. edc_pharmacy/migrations/0084_confirmationatsiteitem_and_more.py +0 -2
  295. edc_pharmacy/migrations/0089_alter_allocation_allocated_by_and_more.py +3284 -0
  296. edc_pharmacy/migrations/0090_alter_allocation_allocation_datetime_and_more.py +227 -0
  297. edc_pharmacy/model_mixins/study_medication_refill_model_mixin.py +2 -2
  298. edc_pharmacy/models/medication/formulation.py +5 -7
  299. edc_pharmacy/models/medication/medication.py +3 -3
  300. edc_pharmacy/models/model_mixins.py +10 -11
  301. edc_pharmacy/models/prescription/rx.py +13 -12
  302. edc_pharmacy/models/prescription/rx_refill.py +0 -1
  303. edc_pharmacy/models/stock/allocation.py +3 -3
  304. edc_pharmacy/models/stock/confirmation.py +3 -3
  305. edc_pharmacy/models/stock/confirmation_at_site.py +3 -2
  306. edc_pharmacy/models/stock/confirmation_at_site_item.py +3 -4
  307. edc_pharmacy/models/stock/dispense.py +5 -6
  308. edc_pharmacy/models/stock/dispense_item.py +2 -2
  309. edc_pharmacy/models/stock/location.py +3 -4
  310. edc_pharmacy/models/stock/lot.py +6 -7
  311. edc_pharmacy/models/stock/order.py +1 -1
  312. edc_pharmacy/models/stock/receive.py +3 -3
  313. edc_pharmacy/models/stock/receive_item.py +4 -4
  314. edc_pharmacy/models/stock/repack_request.py +2 -2
  315. edc_pharmacy/models/stock/stock.py +12 -18
  316. edc_pharmacy/models/stock/stock_adjustment.py +4 -4
  317. edc_pharmacy/models/stock/stock_request.py +2 -2
  318. edc_pharmacy/models/stock/stock_request_item.py +2 -2
  319. edc_pharmacy/models/stock/stock_transfer.py +3 -3
  320. edc_pharmacy/models/stock/stock_transfer_item.py +2 -2
  321. edc_pharmacy/models/stock/storage_bin.py +3 -4
  322. edc_pharmacy/models/stock/storage_bin_item.py +2 -2
  323. edc_pharmacy/models/stock/supplier.py +3 -4
  324. edc_pharmacy/models/storage/box.py +2 -2
  325. edc_pharmacy/models/storage/items/container_model_mixin.py +3 -4
  326. edc_pharmacy/models/storage/items/pill_bottle_model_mixin.py +2 -2
  327. edc_pharmacy/models/storage/items/subject_pill_bottle.py +1 -1
  328. edc_pharmacy/models/storage/room.py +2 -2
  329. edc_pharmacy/models/storage/shelf.py +2 -2
  330. edc_pharmacy/models/storage/utils.py +1 -1
  331. edc_pharmacy/prescribe/create_prescription.py +3 -3
  332. edc_pharmacy/utils/allocate_stock.py +2 -3
  333. edc_pharmacy/utils/confirm_stock.py +3 -4
  334. edc_pharmacy/utils/confirm_stock_at_site.py +4 -5
  335. edc_pharmacy/utils/dispense.py +3 -4
  336. edc_pharmacy/utils/process_repack_request.py +4 -5
  337. edc_pharmacy/utils/stock_request/bulk_create_stock_request_items.py +2 -3
  338. edc_pharmacy/utils/transfer_stock.py +2 -3
  339. edc_pharmacy/views/add_to_storage_bin_view.py +2 -2
  340. edc_pharmacy/views/allocate_to_subject_view.py +2 -2
  341. edc_pharmacy/views/confirmation_at_site_view.py +6 -9
  342. edc_pharmacy/views/dispense_view.py +2 -2
  343. edc_pharmacy/views/move_to_storage_bin_view.py +2 -3
  344. edc_pharmacy/views/print_labels_view.py +2 -2
  345. edc_prn/admin_site.py +5 -0
  346. edc_prn/prn.py +10 -11
  347. edc_prn/urls.py +11 -0
  348. edc_protocol/research_protocol_config.py +2 -3
  349. edc_protocol_incident/action_items.py +4 -4
  350. edc_protocol_incident/auths.py +27 -20
  351. edc_protocol_incident/migrations/0001_initial.py +7 -7
  352. edc_protocol_incident/migrations/0001_squashed_0015_auto_20220927_0401.py +13 -13
  353. edc_protocol_incident/migrations/0005_protocolincident_historicalprotocolincident_and_more.py +7 -7
  354. edc_protocol_incident/migrations/0024_alter_actionsrequired_extra_value_and_more.py +625 -0
  355. edc_protocol_incident/migrations/0025_alter_historicalprotocoldeviationviolation_report_datetime_and_more.py +42 -0
  356. edc_protocol_incident/model_mixins/protocol_deviation_violation_model_mixin.py +18 -11
  357. edc_protocol_incident/model_mixins/protocol_incident_model_mixin.py +26 -11
  358. edc_pylabels/actions.py +3 -5
  359. edc_pylabels/auths.py +6 -1
  360. edc_pylabels/migrations/0002_alter_label_options_label_created_and_more.py +3 -7
  361. edc_pylabels/migrations/0005_labelconfiguration_delete_label_and_more.py +3 -3
  362. edc_pylabels/migrations/0013_alter_labelconfiguration_device_created_and_more.py +49 -0
  363. edc_qareports/auths.py +11 -7
  364. edc_qareports/migrations/0001_initial.py +4 -5
  365. edc_qareports/migrations/0005_edcpermissions.py +3 -3
  366. edc_qareports/migrations/0006_qareportlog.py +2 -3
  367. edc_qareports/migrations/0019_alter_edcpermissions_device_created_and_more.py +102 -0
  368. edc_qareports/migrations/0020_alter_note_report_datetime_and_more.py +24 -0
  369. edc_qareports/model_mixins/note_model_mixin.py +7 -4
  370. edc_qareports/model_mixins/on_study_missing_values_model_mixin.py +4 -4
  371. edc_qareports/model_mixins/qa_report_model_mixin.py +2 -3
  372. edc_qareports/models/note.py +4 -4
  373. edc_qareports/models/qa_reports_log.py +2 -3
  374. edc_randomization/admin.py +30 -24
  375. edc_randomization/auths.py +12 -7
  376. edc_randomization/decorators.py +1 -1
  377. edc_randomization/migrations/0001_initial.py +3 -2
  378. edc_randomization/migrations/0002_historicalrandomizationlist.py +3 -2
  379. edc_randomization/migrations/0009_edcpermissions.py +3 -2
  380. edc_randomization/migrations/0014_alter_edcpermissions_device_created_and_more.py +141 -0
  381. edc_randomization/model_mixins.py +9 -9
  382. edc_randomization/randomizer.py +22 -20
  383. edc_randomization/utils.py +19 -18
  384. edc_refusal/auths.py +7 -2
  385. edc_refusal/migrations/0001_initial.py +4 -4
  386. edc_refusal/migrations/0002_historicalsubjectrefusal.py +4 -4
  387. edc_refusal/migrations/0012_alter_historicalsubjectrefusal_comment_and_more.py +122 -0
  388. edc_refusal/migrations/0013_alter_historicalsubjectrefusal_report_datetime_and_more.py +28 -0
  389. edc_refusal/model_mixins.py +4 -4
  390. edc_registration/auths.py +28 -23
  391. edc_registration/migrations/0002_auto_20161127_2226.py +3 -4
  392. edc_registration/migrations/0005_auto_20170111_1809.py +4 -2
  393. edc_registration/migrations/0016_historicalregisteredsubject.py +3 -2
  394. edc_registration/migrations/0017_auto_20190305_0123.py +5 -12
  395. edc_registration/migrations/0033_alter_historicalregisteredsubject_additional_key_and_more.py +302 -0
  396. edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py +15 -7
  397. edc_registration/models/registered_subject.py +28 -27
  398. edc_reportable/age_evaluator.py +4 -2
  399. edc_reportable/formula.py +5 -5
  400. edc_reportable/migrations/0001_initial.py +7 -7
  401. edc_reportable/migrations/0003_referencerangecollection_grade1_and_more.py +3 -3
  402. edc_reportable/migrations/0004_alter_referencerangecollection_grade3_and_more.py +5 -5
  403. edc_reportable/migrations/0006_alter_gradingdata_revision_and_more.py +5 -6
  404. edc_reportable/migrations/0007_alter_gradingdata_age_phrase_and_more.py +509 -0
  405. edc_reportable/models/normal_data.py +4 -5
  406. edc_reportable/models/reference_model_mixins.py +10 -11
  407. edc_reportable/models/reference_range_collection.py +12 -13
  408. edc_reportable/post_migrate_signals.py +1 -1
  409. edc_reportable/utils/convert_units.py +11 -45
  410. edc_reportable/utils/get_normal_data_or_raise.py +2 -2
  411. edc_reportable/utils/get_reference_range_collection.py +2 -3
  412. edc_reportable/utils/load_data.py +4 -4
  413. edc_reportable/utils/update_grading_data.py +5 -5
  414. edc_review_dashboard/auths.py +23 -18
  415. edc_review_dashboard/migrations/0001_initial.py +3 -2
  416. edc_review_dashboard/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
  417. edc_screening/age_evaluator.py +6 -6
  418. edc_screening/auths.py +35 -30
  419. edc_screening/eligibility.py +1 -1
  420. edc_screening/gender_evaluator.py +1 -1
  421. edc_screening/migrations/0001_initial.py +3 -2
  422. edc_screening/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
  423. edc_screening/model_mixins/eligibility_model_mixin.py +3 -6
  424. edc_screening/model_mixins/screening_fields_model_mixin.py +6 -8
  425. edc_screening/model_mixins/screening_methods_model_mixin.py +1 -1
  426. edc_screening/screening_eligibility.py +2 -4
  427. edc_screening/utils.py +9 -9
  428. edc_search/generate_slug.py +26 -0
  429. edc_search/model_mixins.py +10 -22
  430. edc_sites/auths.py +8 -3
  431. edc_sites/migrations/0007_edcpermissions.py +3 -2
  432. edc_sites/migrations/0010_alter_edcpermissions_device_created_and_more.py +69 -0
  433. edc_sites/model_mixins/site_model_mixin.py +2 -2
  434. edc_sites/site.py +5 -5
  435. edc_sites/system_checks.py +1 -1
  436. edc_subject_dashboard/auths.py +27 -22
  437. edc_subject_dashboard/migrations/0001_initial.py +3 -2
  438. edc_subject_dashboard/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
  439. edc_subject_dashboard/requisition_report.py +6 -4
  440. edc_subject_dashboard/requisition_verifier.py +6 -6
  441. edc_subject_dashboard/templatetags/edc_subject_dashboard_extras.py +2 -2
  442. edc_subject_dashboard/view_mixins/subject_visit_view_mixin.py +7 -8
  443. edc_subject_dashboard/view_utils/subject_consent_listboard_button.py +3 -2
  444. edc_subject_dashboard/view_utils/timepoint_status_button.py +2 -2
  445. edc_timepoint/apps.py +0 -21
  446. edc_timepoint/model_mixins.py +22 -20
  447. edc_transfer/model_mixins.py +4 -4
  448. edc_transfer/modeladmin_mixins.py +1 -1
  449. edc_unblinding/auths.py +9 -4
  450. edc_unblinding/migrations/0001_initial.py +13 -13
  451. edc_unblinding/migrations/0014_alter_historicalunblindingrequest_action_identifier_and_more.py +291 -0
  452. edc_unblinding/migrations/0015_alter_historicalunblindingrequest_report_datetime_and_more.py +45 -0
  453. edc_unblinding/models/unblinding_request.py +2 -2
  454. edc_unblinding/models/unblinding_review.py +3 -3
  455. edc_utils/__init__.py +3 -1
  456. edc_utils/age.py +10 -16
  457. edc_utils/show_urls.py +29 -2
  458. edc_visit_schedule/auths.py +6 -1
  459. edc_visit_schedule/migrations/0001_initial.py +3 -3
  460. edc_visit_schedule/migrations/0002_auto_20190305_0123.py +3 -6
  461. edc_visit_schedule/migrations/0003_historicalvisitschedule_visitschedule.py +5 -4
  462. edc_visit_schedule/migrations/0015_historicalonschedule_offschedule_onschedule.py +10 -10
  463. edc_visit_schedule/migrations/0019_alter_historicalonschedule_device_created_and_more.py +229 -0
  464. edc_visit_schedule/migrations/0020_alter_historicalonschedule_onschedule_datetime_and_more.py +65 -0
  465. edc_visit_schedule/model_mixins/off_schedule_model_mixin.py +5 -4
  466. edc_visit_schedule/model_mixins/on_schedule_model_mixin.py +5 -4
  467. edc_visit_schedule/model_mixins/visit_schedule/visit_code_fields_model_mixin.py +1 -1
  468. edc_visit_schedule/models/subject_schedule_history.py +6 -6
  469. edc_visit_schedule/schedule/visit_collection.py +1 -1
  470. edc_visit_schedule/site_visit_schedules.py +2 -2
  471. edc_visit_schedule/subject_schedule.py +5 -4
  472. edc_visit_schedule/view_mixins.py +2 -3
  473. edc_visit_schedule/visit/visit.py +3 -2
  474. edc_visit_tracking/migrations/0004_subjectvisit_subjectvisitmissedreasons_extra_value_and_more.py +13 -13
  475. edc_visit_tracking/migrations/0009_alter_historicalsubjectvisit_comments_and_more.py +450 -0
  476. edc_visit_tracking/migrations/0010_alter_historicalsubjectvisit_report_datetime_and_more.py +68 -0
  477. edc_visit_tracking/model_mixins/base/visit_methods_model_mixin.py +3 -3
  478. edc_visit_tracking/model_mixins/crfs/visit_tracking_crf_model_mixin.py +2 -2
  479. edc_visit_tracking/model_mixins/requisitions/visit_tracking_requisition_model_mixin.py +2 -2
  480. edc_visit_tracking/model_mixins/subject_visit_missed_model_mixin.py +2 -2
  481. edc_visit_tracking/model_mixins/visit_model_mixin/caretaker_fields_mixin.py +2 -3
  482. edc_visit_tracking/model_mixins/visit_model_mixin/previous_visit_model_mixin.py +1 -1
  483. edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_fields_mixin.py +8 -11
  484. edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_mixin.py +1 -1
  485. edc_visit_tracking/models/signals.py +3 -3
  486. edc_visit_tracking/models/subject_visit.py +1 -1
  487. edc_vitals/calculators/bmi.py +7 -5
  488. edc_vitals/utils.py +1 -1
  489. edc_form_label/models.py +0 -0
  490. edc_search/constants.py +0 -1
  491. edc_search/models.py +0 -0
  492. edc_search/search_slug.py +0 -50
  493. edc_search/updater.py +0 -30
  494. edc_search/wsgi.py +0 -7
  495. {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,164 @@
1
+ # Generated by Django 5.2.6 on 2025-09-18 00:24
2
+
3
+ import django.db.models.deletion
4
+ import django.utils.timezone
5
+ import uuid
6
+ from django.db import migrations, models
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+
11
+ dependencies = [
12
+ ("edc_data_manager", "0040_alter_datadictionary_device_created_and_more"),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.AlterField(
17
+ model_name="dataquery",
18
+ name="dm_user",
19
+ field=models.ForeignKey(
20
+ blank=True,
21
+ help_text="Please select a name from the list",
22
+ null=True,
23
+ on_delete=django.db.models.deletion.PROTECT,
24
+ related_name="+",
25
+ to="edc_data_manager.datamanageruser",
26
+ verbose_name="DM resolved by",
27
+ ),
28
+ ),
29
+ migrations.AlterField(
30
+ model_name="dataquery",
31
+ name="locked_reason",
32
+ field=models.TextField(
33
+ blank=True,
34
+ default="",
35
+ help_text="If required, the reason the query cannot be resolved.",
36
+ verbose_name="Reason query locked",
37
+ ),
38
+ ),
39
+ migrations.AlterField(
40
+ model_name="dataquery",
41
+ name="plan_of_action",
42
+ field=models.TextField(
43
+ blank=True,
44
+ default="",
45
+ help_text="If required, provide a plan of action",
46
+ ),
47
+ ),
48
+ migrations.AlterField(
49
+ model_name="dataquery",
50
+ name="report_datetime",
51
+ field=models.DateTimeField(
52
+ default=django.utils.timezone.now, verbose_name="Query date"
53
+ ),
54
+ ),
55
+ migrations.AlterField(
56
+ model_name="dataquery",
57
+ name="rule_reference",
58
+ field=models.CharField(
59
+ default=uuid.uuid4, max_length=150, verbose_name="Query rule reference"
60
+ ),
61
+ ),
62
+ migrations.AlterField(
63
+ model_name="dataquery",
64
+ name="sender",
65
+ field=models.ForeignKey(
66
+ help_text="Please select a name from the list",
67
+ on_delete=django.db.models.deletion.PROTECT,
68
+ related_name="+",
69
+ to="edc_data_manager.datamanageruser",
70
+ verbose_name="Query raised by",
71
+ ),
72
+ ),
73
+ migrations.AlterField(
74
+ model_name="dataquery",
75
+ name="site_response_text",
76
+ field=models.TextField(blank=True, default=""),
77
+ ),
78
+ migrations.AlterField(
79
+ model_name="dataquery",
80
+ name="subject_identifier",
81
+ field=models.CharField(default="", editable=False, max_length=50),
82
+ ),
83
+ migrations.AlterField(
84
+ model_name="dataquery",
85
+ name="title",
86
+ field=models.CharField(default="", max_length=150),
87
+ ),
88
+ migrations.AlterField(
89
+ model_name="historicaldataquery",
90
+ name="dm_user",
91
+ field=models.ForeignKey(
92
+ blank=True,
93
+ db_constraint=False,
94
+ help_text="Please select a name from the list",
95
+ null=True,
96
+ on_delete=django.db.models.deletion.DO_NOTHING,
97
+ related_name="+",
98
+ to="edc_data_manager.datamanageruser",
99
+ verbose_name="DM resolved by",
100
+ ),
101
+ ),
102
+ migrations.AlterField(
103
+ model_name="historicaldataquery",
104
+ name="locked_reason",
105
+ field=models.TextField(
106
+ blank=True,
107
+ default="",
108
+ help_text="If required, the reason the query cannot be resolved.",
109
+ verbose_name="Reason query locked",
110
+ ),
111
+ ),
112
+ migrations.AlterField(
113
+ model_name="historicaldataquery",
114
+ name="plan_of_action",
115
+ field=models.TextField(
116
+ blank=True,
117
+ default="",
118
+ help_text="If required, provide a plan of action",
119
+ ),
120
+ ),
121
+ migrations.AlterField(
122
+ model_name="historicaldataquery",
123
+ name="report_datetime",
124
+ field=models.DateTimeField(
125
+ default=django.utils.timezone.now, verbose_name="Query date"
126
+ ),
127
+ ),
128
+ migrations.AlterField(
129
+ model_name="historicaldataquery",
130
+ name="rule_reference",
131
+ field=models.CharField(
132
+ default=uuid.uuid4, max_length=150, verbose_name="Query rule reference"
133
+ ),
134
+ ),
135
+ migrations.AlterField(
136
+ model_name="historicaldataquery",
137
+ name="sender",
138
+ field=models.ForeignKey(
139
+ blank=True,
140
+ db_constraint=False,
141
+ help_text="Please select a name from the list",
142
+ null=True,
143
+ on_delete=django.db.models.deletion.DO_NOTHING,
144
+ related_name="+",
145
+ to="edc_data_manager.datamanageruser",
146
+ verbose_name="Query raised by",
147
+ ),
148
+ ),
149
+ migrations.AlterField(
150
+ model_name="historicaldataquery",
151
+ name="site_response_text",
152
+ field=models.TextField(blank=True, default=""),
153
+ ),
154
+ migrations.AlterField(
155
+ model_name="historicaldataquery",
156
+ name="subject_identifier",
157
+ field=models.CharField(default="", editable=False, max_length=50),
158
+ ),
159
+ migrations.AlterField(
160
+ model_name="historicaldataquery",
161
+ name="title",
162
+ field=models.CharField(default="", max_length=150),
163
+ ),
164
+ ]
@@ -6,6 +6,7 @@ from django.db import models
6
6
  from django.db.models.deletion import PROTECT
7
7
  from django.template.loader import render_to_string
8
8
  from django.urls.base import reverse
9
+ from django.utils import timezone
9
10
 
10
11
  from edc_action_item.models.action_model_mixin import ActionModelMixin
11
12
  from edc_constants.constants import CLOSED, RESOLVED
@@ -13,7 +14,6 @@ from edc_dashboard.url_names import InvalidDashboardUrlName, url_names
13
14
  from edc_model.models import BaseUuidModel
14
15
  from edc_sites.managers import CurrentSiteManager
15
16
  from edc_sites.model_mixins import SiteModelMixin
16
- from edc_utils.date import get_utcnow
17
17
  from edc_visit_tracking.utils import get_related_visit_model_cls
18
18
 
19
19
  from ..action_items import DATA_QUERY_ACTION
@@ -28,7 +28,7 @@ from .requisition_panel import RequisitionPanel
28
28
  class DataQuery(DataQueryModelMixin, ActionModelMixin, SiteModelMixin, BaseUuidModel):
29
29
  action_name = DATA_QUERY_ACTION
30
30
 
31
- subject_identifier = models.CharField(max_length=50, null=True, editable=False)
31
+ subject_identifier = models.CharField(max_length=50, default="", editable=False)
32
32
 
33
33
  registered_subject = models.ForeignKey(
34
34
  QuerySubject,
@@ -83,7 +83,7 @@ class DataQuery(DataQueryModelMixin, ActionModelMixin, SiteModelMixin, BaseUuidM
83
83
  )
84
84
 
85
85
  rule_reference = models.CharField(
86
- verbose_name="Query rule reference", max_length=150, null=True, default=uuid4
86
+ verbose_name="Query rule reference", max_length=150, default=uuid4
87
87
  )
88
88
 
89
89
  objects = models.Manager()
@@ -107,7 +107,7 @@ class DataQuery(DataQueryModelMixin, ActionModelMixin, SiteModelMixin, BaseUuidM
107
107
  and self.site_response_text.strip() == AUTO_RESOLVED
108
108
  ):
109
109
  self.status = CLOSED
110
- self.resolved_datetime = get_utcnow()
110
+ self.resolved_datetime = timezone.now()
111
111
  self.dm_user = self.sender
112
112
 
113
113
  def form_and_numbers_to_string(self):
@@ -192,7 +192,7 @@ class DataQuery(DataQueryModelMixin, ActionModelMixin, SiteModelMixin, BaseUuidM
192
192
  class Meta(BaseUuidModel.Meta):
193
193
  verbose_name = "Data Query"
194
194
  verbose_name_plural = "Data Queries"
195
- unique_together = ["registered_subject", "rule_reference", "visit_schedule"]
195
+ unique_together = ("registered_subject", "rule_reference", "visit_schedule")
196
196
  indexes = (
197
197
  models.Index(
198
198
  fields=[
@@ -1,8 +1,8 @@
1
1
  from django.db import models
2
2
  from django.db.models import PROTECT
3
+ from django.utils import timezone
3
4
 
4
5
  from edc_constants.constants import CLOSED, NEW, NORMAL, OPEN, RESOLVED
5
- from edc_utils import get_utcnow
6
6
 
7
7
  from ..choices import DM_STATUS, QUERY_PRIORITY, RESPONSE_STATUS
8
8
  from ..constants import CLOSED_WITH_ACTION
@@ -10,16 +10,16 @@ from .user import DataManagerUser, QueryUser
10
10
 
11
11
 
12
12
  class DataQueryModelMixin(models.Model):
13
- report_datetime = models.DateTimeField(verbose_name="Query date", default=get_utcnow)
13
+ report_datetime = models.DateTimeField(verbose_name="Query date", default=timezone.now)
14
14
 
15
- title = models.CharField(max_length=150, null=True, blank=False)
15
+ title = models.CharField(max_length=150, default="", blank=False)
16
16
 
17
17
  sender = models.ForeignKey(
18
18
  DataManagerUser,
19
19
  related_name="+",
20
20
  on_delete=PROTECT,
21
21
  verbose_name="Query raised by",
22
- help_text="Select a name from the list",
22
+ help_text="Please select a name from the list",
23
23
  )
24
24
 
25
25
  recipients = models.ManyToManyField(
@@ -43,7 +43,7 @@ class DataQueryModelMixin(models.Model):
43
43
  verbose_name="Site resolved on", null=True, blank=True
44
44
  )
45
45
 
46
- site_response_text = models.TextField(null=True, blank=True)
46
+ site_response_text = models.TextField(default="", blank=True)
47
47
 
48
48
  site_response_status = models.CharField(
49
49
  verbose_name="Site status", max_length=25, choices=RESPONSE_STATUS, default=NEW
@@ -60,7 +60,7 @@ class DataQueryModelMixin(models.Model):
60
60
  on_delete=PROTECT,
61
61
  null=True,
62
62
  blank=True,
63
- help_text="select a name from the list",
63
+ help_text="Please select a name from the list",
64
64
  )
65
65
 
66
66
  resolved_datetime = models.DateTimeField(
@@ -70,7 +70,7 @@ class DataQueryModelMixin(models.Model):
70
70
  auto_resolved = models.BooleanField(default=False)
71
71
 
72
72
  plan_of_action = models.TextField(
73
- null=True, blank=True, help_text="If required, provide a plan of action"
73
+ default="", blank=True, help_text="If required, provide a plan of action"
74
74
  )
75
75
 
76
76
  locked = models.BooleanField(
@@ -80,7 +80,7 @@ class DataQueryModelMixin(models.Model):
80
80
 
81
81
  locked_reason = models.TextField(
82
82
  verbose_name="Reason query locked",
83
- null=True,
83
+ default="",
84
84
  blank=True,
85
85
  help_text="If required, the reason the query cannot be resolved.",
86
86
  )
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from datetime import datetime
4
4
  from decimal import Decimal
5
- from typing import TYPE_CHECKING, LiteralString
5
+ from typing import TYPE_CHECKING
6
6
 
7
7
  from tqdm import tqdm
8
8
 
@@ -17,12 +17,12 @@ if TYPE_CHECKING:
17
17
  class QueryRuleWrapper:
18
18
  def __init__(
19
19
  self,
20
- query_rule_obj: QueryRule = None,
21
- subject_identifiers: list[LiteralString] = None,
22
- visit_schedule_obj: QueryVisitSchedule = None,
23
- timepoint: Decimal = None,
24
- entry_status: str = None,
25
- now: datetime = None,
20
+ query_rule_obj: QueryRule | None = None,
21
+ subject_identifiers: list[str] | None = None,
22
+ visit_schedule_obj: QueryVisitSchedule | None = None,
23
+ timepoint: Decimal | None = None,
24
+ entry_status: str | None = None,
25
+ now: datetime | None = None,
26
26
  verbose: bool | None = None,
27
27
  ):
28
28
  self.now = now
@@ -5,9 +5,10 @@ from datetime import datetime
5
5
  from decimal import Decimal
6
6
  from typing import TYPE_CHECKING
7
7
 
8
+ from django.utils import timezone
9
+
8
10
  from edc_metadata import KEYED, REQUIRED
9
11
  from edc_metadata.metadata_inspector import MetaDataInspector
10
- from edc_utils import get_utcnow
11
12
 
12
13
  from ..models import QueryVisitSchedule
13
14
  from .query_rule_wrapper import QueryRuleWrapper
@@ -24,7 +25,7 @@ class RuleRunner:
24
25
  verbose: bool | None = None,
25
26
  ):
26
27
  self.query_rule_obj = query_rule_obj # query rule model instance
27
- self.now = now or get_utcnow()
28
+ self.now = now or timezone.now()
28
29
  self.verbose = verbose
29
30
 
30
31
  @property
@@ -39,7 +40,7 @@ class RuleRunner:
39
40
  created_counter = 0
40
41
  resolved_counter = 0
41
42
  query_rules_data = query_rules_data or self.query_rules_data
42
- for key, wrapped_query_rules in query_rules_data.items():
43
+ for _, wrapped_query_rules in query_rules_data.items():
43
44
  for wrapped_query_rule in wrapped_query_rules:
44
45
  if self.verbose:
45
46
  sys.stdout.write(f" - running {wrapped_query_rule}\n")
@@ -17,7 +17,7 @@ class DocumentStatusModelMixin(models.Model):
17
17
 
18
18
  document_status_comments = models.TextField(
19
19
  verbose_name="Any comments related to status of this document",
20
- null=True,
20
+ default="",
21
21
  blank=True,
22
22
  help_text="for example, why some data is still pending",
23
23
  )
edc_egfr/egfr.py CHANGED
@@ -8,12 +8,13 @@ from zoneinfo import ZoneInfo
8
8
  from dateutil.relativedelta import relativedelta
9
9
  from django.core.exceptions import ObjectDoesNotExist
10
10
  from django.db import transaction
11
+ from django.utils import timezone
11
12
 
12
13
  from edc_constants.constants import NEW
13
14
  from edc_reportable.models import ReferenceRangeCollection
14
15
  from edc_reportable.units import EGFR_UNITS, PERCENT
15
16
  from edc_reportable.utils import get_grade_for_value
16
- from edc_utils import age, get_utcnow
17
+ from edc_utils.age import age
17
18
 
18
19
  from .calculators import EgfrCkdEpi, EgfrCockcroftGault, egfr_percent_change
19
20
  from .get_drop_notification_model import get_egfr_drop_notification_model_cls
@@ -27,7 +28,7 @@ class EgfrError(Exception):
27
28
 
28
29
 
29
30
  class Egfr:
30
- calculators: dict = {"ckd-epi": EgfrCkdEpi, "cockcroft-gault": EgfrCockcroftGault}
31
+ calculators: dict = {"ckd-epi": EgfrCkdEpi, "cockcroft-gault": EgfrCockcroftGault} # noqa: RUF012
31
32
 
32
33
  def __init__(
33
34
  self,
@@ -78,7 +79,7 @@ class Egfr:
78
79
  name=reference_range_collection_name
79
80
  )
80
81
  except ObjectDoesNotExist as e:
81
- raise ObjectDoesNotExist(f"{e} Got {reference_range_collection_name}")
82
+ raise ObjectDoesNotExist(f"{e} Got {reference_range_collection_name}") from e
82
83
  else:
83
84
  self.reference_range_collection = reference_range_collection
84
85
  self.report_datetime = report_datetime
@@ -134,9 +135,12 @@ class Egfr:
134
135
  """A hook to respond if egfr percent drop from baseline
135
136
  is at or beyond the percent drop threshold.
136
137
  """
137
- if self.egfr_drop_value and self.percent_drop_threshold is not None:
138
- if self.egfr_drop_value >= self.percent_drop_threshold:
139
- self.create_or_update_egfr_drop_notification()
138
+ if (
139
+ self.egfr_drop_value
140
+ and self.percent_drop_threshold is not None
141
+ and self.egfr_drop_value >= self.percent_drop_threshold
142
+ ):
143
+ self.create_or_update_egfr_drop_notification()
140
144
 
141
145
  @property
142
146
  def egfr_value(self) -> float:
@@ -226,7 +230,7 @@ class Egfr:
226
230
  obj.weight = self.get_weight_in_kgs()
227
231
  obj.egfr_percent_change = self.egfr_drop_value
228
232
  obj.creatinine_date = self.assay_date
229
- obj.modified = get_utcnow()
233
+ obj.modified = timezone.now()
230
234
  obj.save()
231
235
  obj.refresh_from_db()
232
236
  return obj
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import contextlib
3
4
  from decimal import Decimal
4
5
 
5
6
  from django.core.exceptions import ObjectDoesNotExist
@@ -104,13 +105,8 @@ class EgfrModelMixin(
104
105
  appointment__timepoint=self.baseline_timepoint,
105
106
  visit_code_sequence=0,
106
107
  )
107
- with transaction.atomic():
108
- try:
109
- egfr_value = self.__class__.objects.get(
110
- subject_visit=baseline_visit
111
- ).egfr_value
112
- except ObjectDoesNotExist:
113
- pass
108
+ with transaction.atomic(), contextlib.suppress(ObjectDoesNotExist):
109
+ egfr_value = self.__class__.objects.get(subject_visit=baseline_visit).egfr_value
114
110
  return egfr_value
115
111
 
116
112
  def get_weight_in_kgs_for_egfr(self) -> Decimal | None:
@@ -1,4 +1,5 @@
1
1
  from django.contrib import admin
2
+ from django.utils import timezone
2
3
  from django_audit_fields import ModelAdminAuditFieldsMixin
3
4
  from django_revision.modeladmin_mixin import ModelAdminRevisionMixin
4
5
 
@@ -11,7 +12,6 @@ from edc_model_admin.mixins import (
11
12
  TemplatesModelAdminMixin,
12
13
  )
13
14
  from edc_sites.admin import SiteModelAdminMixin
14
- from edc_utils import get_utcnow
15
15
 
16
16
  from ..admin_site import edc_export_admin
17
17
  from ..forms import DataRequestForm
@@ -66,7 +66,7 @@ class DataRequestAdmin(
66
66
  def export_selected(self, request, queryset):
67
67
  for obj in queryset:
68
68
  DataRequestHistory.objects.create(data_request=obj)
69
- rows_updated = queryset.update(exported_datetime=get_utcnow())
69
+ rows_updated = queryset.update(exported_datetime=timezone.now())
70
70
  if rows_updated == 1:
71
71
  message_bit = "1 data request was"
72
72
  else:
@@ -1,11 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from pathlib import Path
3
4
  from tempfile import mkdtemp
4
5
  from typing import TYPE_CHECKING
5
6
 
7
+ from django.utils import timezone
8
+
6
9
  from edc_pdutils.df_exporters import CsvModelExporter
7
10
  from edc_sites.site import sites
8
- from edc_utils import get_utcnow
9
11
 
10
12
  from .files_archiver import FilesArchiver
11
13
  from .files_emailer import FilesEmailer, FilesEmailerError
@@ -16,7 +18,7 @@ if TYPE_CHECKING:
16
18
  from django.contrib.auth.models import User
17
19
 
18
20
 
19
- class ArchiveExporterNothingExported(Exception):
21
+ class ArchiveExporterNothingExported(Exception): # noqa: N818
20
22
  pass
21
23
 
22
24
 
@@ -55,7 +57,7 @@ class ArchiveExporter:
55
57
  for model in models:
56
58
  csv_exporter = self.csv_exporter_cls(
57
59
  model=model,
58
- export_folder=tmp_folder,
60
+ export_folder=Path(tmp_folder),
59
61
  decrypt=decrypt,
60
62
  site_ids=sites.get_site_ids_for_user(
61
63
  user=user, site_id=sites.get_current_site().site_id
@@ -85,8 +87,8 @@ class ArchiveExporter:
85
87
  summary="\n".join(summary),
86
88
  )
87
89
  except FilesEmailerError as e:
88
- raise ArchiveExporterEmailError(e)
90
+ raise ArchiveExporterEmailError(e) from e
89
91
  else:
90
92
  self.emailed_to = user.email
91
- self.emailed_datetime = get_utcnow()
93
+ self.emailed_datetime = timezone.now()
92
94
  self.exported_datetime = self.exported_datetime or self.emailed_datetime
edc_export/auths.py CHANGED
@@ -4,34 +4,38 @@ from edc_auth.utils import remove_default_model_permissions_from_edc_permissions
4
4
  from .auth_objects import export_codenames
5
5
  from .constants import DATA_EXPORTER_ROLE, EXPORT, EXPORT_PII
6
6
 
7
- site_auths.add_post_update_func(
8
- "edc_export",
9
- remove_default_model_permissions_from_edc_permissions,
10
- )
11
7
 
12
- site_auths.add_custom_permissions_tuples(
13
- model="edc_export.edcpermissions",
14
- codename_tuples=[
15
- (
16
- "edc_export.export_visitschedule",
17
- "Can export the visit schedule",
18
- ),
19
- (
20
- "edc_export.view_export_dashboard",
21
- "Can view export dashboard",
22
- ),
23
- (
24
- "edc_export.export_subjectschedulehistory",
25
- "Can export subject schedule history",
26
- ),
27
- (
28
- "edc_export.export_pii",
29
- "Can export PII",
30
- ),
31
- ],
32
- )
8
+ def update_site_auths():
9
+ site_auths.add_post_update_func(
10
+ "edc_export",
11
+ remove_default_model_permissions_from_edc_permissions,
12
+ )
33
13
 
14
+ site_auths.add_custom_permissions_tuples(
15
+ model="edc_export.edcpermissions",
16
+ codename_tuples=[
17
+ (
18
+ "edc_export.export_visitschedule",
19
+ "Can export the visit schedule",
20
+ ),
21
+ (
22
+ "edc_export.view_export_dashboard",
23
+ "Can view export dashboard",
24
+ ),
25
+ (
26
+ "edc_export.export_subjectschedulehistory",
27
+ "Can export subject schedule history",
28
+ ),
29
+ (
30
+ "edc_export.export_pii",
31
+ "Can export PII",
32
+ ),
33
+ ],
34
+ )
34
35
 
35
- site_auths.add_group(*export_codenames, name=EXPORT)
36
- site_auths.add_role(EXPORT, name=DATA_EXPORTER_ROLE)
37
- site_auths.add_group("edc_export.export_pii", name=EXPORT_PII)
36
+ site_auths.add_group(*export_codenames, name=EXPORT)
37
+ site_auths.add_role(EXPORT, name=DATA_EXPORTER_ROLE)
38
+ site_auths.add_group("edc_export.export_pii", name=EXPORT_PII)
39
+
40
+
41
+ update_site_auths()
@@ -5,8 +5,9 @@ import shutil
5
5
  import sys
6
6
  from typing import TYPE_CHECKING
7
7
 
8
+ from django.utils import timezone
9
+
8
10
  from edc_export.utils import get_base_dir
9
- from edc_utils import get_utcnow
10
11
 
11
12
  if TYPE_CHECKING:
12
13
  from datetime import datetime
@@ -25,7 +26,7 @@ class FilesArchiver:
25
26
  date_format: str = None,
26
27
  verbose: bool | None = None,
27
28
  ):
28
- self.exported_datetime: datetime = exported_datetime or get_utcnow()
29
+ self.exported_datetime: datetime = exported_datetime or timezone.now()
29
30
  formatted_date: str = self.exported_datetime.strftime(date_format)
30
31
  base_dir: str = get_base_dir()
31
32
  archive_name: str = os.path.join(path, f"{user.username}_{formatted_date}")