clinicedc 2.0.5__py3-none-any.whl → 2.0.7__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 (387) hide show
  1. {clinicedc-2.0.5.dist-info → clinicedc-2.0.7.dist-info}/METADATA +2 -2
  2. {clinicedc-2.0.5.dist-info → clinicedc-2.0.7.dist-info}/RECORD +387 -336
  3. edc_action_item/action.py +1 -1
  4. edc_action_item/action_item_notification.py +2 -2
  5. edc_action_item/create_action_item.py +1 -1
  6. edc_action_item/decorators.py +1 -1
  7. edc_action_item/migrations/0001_initial.py +21 -22
  8. edc_action_item/migrations/0006_auto_20180707_1659.py +4 -4
  9. edc_action_item/migrations/0008_auto_20180809_0303.py +4 -4
  10. edc_action_item/migrations/0015_auto_20190114_0250.py +4 -4
  11. edc_action_item/migrations/0017_auto_20190305_0123.py +11 -30
  12. edc_action_item/migrations/0030_edcpermissions.py +3 -2
  13. edc_action_item/migrations/0039_alter_actionitem_auto_created_comment_and_more.py +398 -0
  14. edc_action_item/migrations/0040_alter_actionitem_report_datetime_and_more.py +34 -0
  15. edc_action_item/models/action_item.py +9 -4
  16. edc_action_item/models/action_model_mixin.py +4 -4
  17. edc_action_item/models/reference.py +2 -2
  18. edc_action_item/post_migrate_signals.py +1 -1
  19. edc_action_item/send_email.py +0 -85
  20. edc_adherence/migrations/0005_alter_nonadherencereasons_extra_value_and_more.py +36 -0
  21. edc_adherence/model_mixins.py +1 -1
  22. edc_adverse_event/migrations/0001_initial.py +5 -4
  23. edc_adverse_event/migrations/0002_auto_20190802_0059.py +3 -2
  24. edc_adverse_event/migrations/0008_auto_20220825_0451.py +3 -2
  25. edc_adverse_event/migrations/0009_auto_20220907_0157.py +3 -2
  26. edc_adverse_event/migrations/0016_alter_aeactionclassification_device_created_and_more.py +285 -0
  27. edc_adverse_event/model_mixins/ae_followup/ae_followup_fields_model_mixin.py +2 -2
  28. edc_adverse_event/model_mixins/ae_initial/ae_initial_fields_model_mixin.py +6 -5
  29. edc_adverse_event/model_mixins/ae_special_interest/aesi_fields_model_mixin.py +2 -2
  30. edc_adverse_event/model_mixins/ae_susar/ae_susar_fields_model_mixin.py +2 -2
  31. edc_adverse_event/model_mixins/ae_tmg/ae_tmg_fields_model_mixin.py +15 -11
  32. edc_adverse_event/model_mixins/death_report/death_report_model_mixin.py +5 -4
  33. edc_adverse_event/model_mixins/death_report/death_report_tmg_model_mixin.py +6 -3
  34. edc_adverse_event/model_mixins/death_report/simple_death_report_model_mixin.py +2 -2
  35. edc_adverse_event/model_mixins/hospitaization/hospitalization_model_mixin.py +4 -3
  36. edc_adverse_event/modeladmin_mixins/death_report_admin_mixin.py +3 -3
  37. edc_adverse_event/models/signals.py +7 -7
  38. edc_adverse_event/templatetags/edc_adverse_event_extras.py +5 -4
  39. edc_adverse_event/view_mixins/ae/ae_listboard_view_mixin.py +3 -5
  40. edc_adverse_event/view_mixins/ae/death_report_listboard_view_mixin.py +6 -8
  41. edc_adverse_event/view_mixins/tmg/tmg_ae_listboard_view_mixin.py +2 -2
  42. edc_adverse_event/views/tmg/summary_listboard_view.py +3 -2
  43. edc_appointment/admin/appointment_admin.py +2 -2
  44. edc_appointment/admin/list_filters.py +2 -2
  45. edc_appointment/form_validators/appointment_form_validator.py +108 -82
  46. edc_appointment/migrations/0003_auto_20161127_2226.py +5 -6
  47. edc_appointment/migrations/0006_auto_20170106_2118.py +5 -5
  48. edc_appointment/migrations/0018_auto_20190305_0123.py +5 -12
  49. edc_appointment/migrations/0050_alter_appointment_appt_type_and_more.py +220 -0
  50. edc_appointment/model_mixins/appointment_fields_model_mixin.py +1 -2
  51. edc_appointment/model_mixins/window_period_model_mixin.py +6 -7
  52. edc_appointment/models/signals.py +44 -35
  53. edc_appointment/view_utils/appointment_button.py +2 -2
  54. edc_auth/admin/user_admin.py +1 -1
  55. edc_auth/migrations/0001_squashed_0033_alter_userprofile_is_multisite_viewer.py +5 -5
  56. edc_auth/migrations/0012_auto_20191026_0034.py +3 -2
  57. edc_auth/migrations/0013_auto_20191026_0055.py +3 -2
  58. edc_auth/migrations/0025_permissions.py +3 -2
  59. edc_auth/migrations/0035_alter_edcpermissions_device_created_and_more.py +85 -0
  60. edc_auth/post_migrate_signals.py +1 -1
  61. edc_consent/actions.py +4 -5
  62. edc_consent/migrations/0001_initial.py +3 -2
  63. edc_consent/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
  64. edc_consent/model_mixins/consent_extension_model_mixin.py +4 -5
  65. edc_consent/model_mixins/requires_consent_fields_model_mixin.py +2 -2
  66. edc_consent/utils.py +1 -1
  67. edc_crf/migrations/0001_initial.py +3 -2
  68. edc_crf/migrations/0009_alter_crfstatus_device_created_and_more.py +54 -0
  69. edc_dashboard/migrations/0001_initial.py +3 -2
  70. edc_dashboard/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
  71. edc_dashboard/templatetags/edc_dashboard_extras.py +3 -2
  72. edc_data_manager/action_items.py +4 -6
  73. edc_data_manager/admin/actions.py +5 -5
  74. edc_data_manager/handlers/handlers.py +6 -7
  75. edc_data_manager/migrations/0001_initial.py +19 -19
  76. edc_data_manager/migrations/0025_edcpermissions.py +3 -2
  77. edc_data_manager/migrations/0040_alter_datadictionary_device_created_and_more.py +327 -0
  78. edc_data_manager/migrations/0041_alter_dataquery_dm_user_and_more.py +164 -0
  79. edc_data_manager/models/data_query.py +5 -5
  80. edc_data_manager/models/model_mixins.py +8 -8
  81. edc_data_manager/rule/rule_runner.py +4 -3
  82. edc_document_status/model_mixins.py +1 -1
  83. edc_egfr/egfr.py +11 -7
  84. edc_egfr/model_mixins/egfr_model_mixin.py +3 -7
  85. edc_export/admin/data_request_admin.py +2 -2
  86. edc_export/archive_exporter.py +4 -3
  87. edc_export/files_archiver.py +3 -2
  88. edc_export/migrations/0001_initial.py +26 -26
  89. edc_export/migrations/0004_auto_20190305_0123.py +25 -72
  90. edc_export/migrations/0013_edcpermissions.py +3 -2
  91. edc_export/migrations/0022_alter_datarequest_description_and_more.py +611 -0
  92. edc_export/migrations/0023_alter_datarequesthistory_archive_filename_and_more.py +29 -0
  93. edc_export/model_exporter/file_history_updater.py +10 -10
  94. edc_export/model_exporter/model_exporter.py +13 -14
  95. edc_export/model_exporter/object_history_helpers.py +2 -2
  96. edc_export/models/data_request_history.py +4 -4
  97. edc_export/utils.py +10 -15
  98. edc_facility/facility.py +10 -15
  99. edc_facility/import_holidays.py +13 -13
  100. edc_facility/migrations/0005_healthfacility_healthfacilitytypes_and_more.py +8 -7
  101. edc_facility/migrations/0016_alter_healthfacility_device_created_and_more.py +139 -0
  102. edc_facility/migrations/0017_alter_healthfacility_gps_and_more.py +54 -0
  103. edc_facility/model_mixins.py +5 -5
  104. edc_form_runners/form_runner.py +3 -5
  105. edc_form_runners/migrations/0001_initial.py +3 -2
  106. edc_form_runners/migrations/0005_alter_issue_device_created_and_more.py +49 -0
  107. edc_identifier/migrations/0001_squashed_0018_auto_20180128_1054.py +3 -3
  108. edc_identifier/migrations/0002_auto_20190305_0123.py +3 -6
  109. edc_identifier/migrations/0006_auto_20161127_2226.py +15 -15
  110. edc_identifier/migrations/0007_auto_20161204_2227.py +3 -3
  111. edc_identifier/migrations/0009_auto_20161221_2323.py +3 -5
  112. edc_identifier/migrations/0010_auto_20170112_0602.py +17 -17
  113. edc_identifier/migrations/0011_alter_identifiermodel_device_created_and_more.py +79 -0
  114. edc_identifier/model_mixins.py +1 -1
  115. edc_identifier/models.py +9 -9
  116. edc_identifier/simple_identifier.py +1 -3
  117. edc_identifier/subject_identifier.py +3 -2
  118. edc_lab/migrations/0001_initial.py +29 -29
  119. edc_lab/migrations/0008_auto_20170921_0719.py +3 -3
  120. edc_lab/migrations/0010_auto_20171127_1541.py +15 -15
  121. edc_lab/migrations/0012_auto_20180114_1438.py +3 -3
  122. edc_lab/migrations/0019_auto_20190305_0123.py +43 -127
  123. edc_lab/migrations/0036_alter_aliquot_comment_alter_aliquot_device_created_and_more.py +1139 -0
  124. edc_lab/migrations/0037_alter_historicalorder_order_datetime_and_more.py +31 -0
  125. edc_lab/model_mixins/aliquot/aliquot_identifier_model_mixin.py +2 -2
  126. edc_lab/model_mixins/aliquot/aliquot_model_mixin.py +2 -2
  127. edc_lab/model_mixins/panel_model_mixin.py +18 -7
  128. edc_lab/model_mixins/requisition/crf_with_requisition_model_mixin.py +2 -4
  129. edc_lab/model_mixins/requisition/requisition_model_mixin.py +7 -8
  130. edc_lab/model_mixins/requisition/requisition_verify_model_mixin.py +1 -1
  131. edc_lab/model_mixins/result/result_item_model_mixin.py +4 -4
  132. edc_lab/model_mixins/shipping/manifest_model_mixin.py +4 -5
  133. edc_lab/model_mixins/shipping/verify_model_mixin.py +4 -6
  134. edc_lab/models/box.py +1 -1
  135. edc_lab/models/box_item.py +6 -7
  136. edc_lab/models/manifest/manifest.py +1 -1
  137. edc_lab/models/manifest/manifest_item.py +6 -6
  138. edc_lab/models/manifest/shipper.py +3 -4
  139. edc_lab/models/order.py +6 -4
  140. edc_lab/models/panel.py +4 -4
  141. edc_lab/models/result.py +2 -2
  142. edc_lab/models/result_item.py +2 -2
  143. edc_lab_dashboard/migrations/0001_initial.py +3 -2
  144. edc_lab_dashboard/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
  145. edc_lab_dashboard/views/action_views/receive_view.py +2 -2
  146. edc_lab_dashboard/views/action_views/verify_box_item_view.py +2 -2
  147. edc_lab_results/model_mixins/blood_result_model_mixin.py +7 -7
  148. edc_lab_results/model_mixins/fbg_model_mixin.py +3 -3
  149. edc_lab_results/model_mixins/glucose_model_mixin.py +3 -3
  150. edc_lab_results/model_mixins/hba1c_model_mixin.py +3 -3
  151. edc_label/migrations/0001_initial.py +3 -2
  152. edc_label/migrations/0007_alter_zpllabeltemplates_device_created_and_more.py +49 -0
  153. edc_list_data/list_model_maker.py +2 -2
  154. edc_list_data/load_list_data.py +11 -14
  155. edc_list_data/model_mixins.py +12 -4
  156. edc_list_data/preload_data.py +3 -3
  157. edc_listboard/migrations/0001_initial.py +3 -2
  158. edc_listboard/migrations/0007_alter_listboard_device_created_and_more.py +49 -0
  159. edc_locator/migrations/0001_initial.py +7 -7
  160. edc_locator/migrations/0018_auto_20190305_0123.py +5 -12
  161. edc_locator/migrations/0040_alter_historicalsubjectlocator_action_identifier_and_more.py +187 -0
  162. edc_locator/migrations/0041_alter_historicalsubjectlocator_report_datetime_and_more.py +27 -0
  163. edc_locator/model_mixins/locator_model_mixin.py +2 -2
  164. edc_locator/model_mixins/subject_contact_fields_mixin.py +1 -1
  165. edc_locator/modeladmin_mixins.py +5 -4
  166. edc_ltfu/model_mixins.py +7 -5
  167. edc_metadata/metadata_rules/decorators.py +1 -1
  168. edc_metadata/migrations/0002_auto_20161127_2226.py +5 -5
  169. edc_metadata/migrations/0005_auto_20170112_0602.py +5 -5
  170. edc_metadata/migrations/0011_auto_20190305_0123.py +5 -12
  171. edc_metadata/migrations/0031_alter_crfmetadata_device_created_and_more.py +120 -0
  172. edc_metadata/model_mixins/updates/updates_crf_metadata_model_mixin.py +1 -1
  173. edc_metadata/model_mixins/updates/updates_requisition_metadata_model_mixin.py +1 -1
  174. edc_metadata/models/crf_metadata.py +5 -5
  175. edc_metadata/models/crf_metadata_model_mixin.py +4 -5
  176. edc_metadata/models/requisition_metadata.py +6 -6
  177. edc_metadata/views/refresh_metadata_actions_view.py +3 -3
  178. edc_model/models/address_mixin.py +6 -6
  179. edc_model/models/fields/initials_field.py +2 -1
  180. edc_model/models/historical_records.py +2 -9
  181. edc_model/models/url_model_mixin.py +2 -2
  182. edc_model/validators/date.py +7 -8
  183. edc_model_admin/list_filters/future_date_list_filter.py +3 -3
  184. edc_model_admin/list_filters/past_date_list_filter.py +3 -3
  185. edc_model_admin/mixins/model_admin_protect_pii_mixin.py +4 -5
  186. edc_model_fields/fields/other_charfield.py +2 -2
  187. edc_navbar/migrations/0004_auto_20220825_0451.py +3 -2
  188. edc_navbar/migrations/0009_alter_edcpermissions_device_created_and_more.py +49 -0
  189. edc_notification/migrations/0001_initial.py +3 -3
  190. edc_notification/migrations/0004_auto_20190305_0123.py +3 -6
  191. edc_notification/migrations/0011_alter_notification_device_created_and_more.py +59 -0
  192. edc_notification/models/notification.py +1 -1
  193. edc_notification/notification/notification.py +12 -12
  194. edc_offstudy/migrations/0001_initial.py +4 -4
  195. edc_offstudy/migrations/0002_auto_20180921_0434.py +4 -4
  196. edc_offstudy/migrations/0005_auto_20190305_0123.py +5 -12
  197. edc_offstudy/migrations/0023_alter_historicalsubjectoffstudy_action_identifier_and_more.py +188 -0
  198. edc_offstudy/migrations/0024_alter_historicalsubjectoffstudy_offstudy_datetime_and_more.py +43 -0
  199. edc_offstudy/model_mixins/offstudy_model_mixin.py +3 -2
  200. edc_pdutils/df_exporters/csv_exporter.py +33 -37
  201. edc_pdutils/df_exporters/csv_model_exporter.py +2 -1
  202. edc_pdutils/migrations/0001_initial.py +8 -8
  203. edc_pharmacy/admin/prescription/rx_refill_admin.py +4 -3
  204. edc_pharmacy/admin/reports/stock_availability_admin.py +5 -6
  205. edc_pharmacy/migrations/0001_initial.py +64 -63
  206. edc_pharmacy/migrations/0015_auto_20220913_2139.py +26 -26
  207. edc_pharmacy/migrations/0024_allocation_assignment_containerunits_dispense_and_more.py +81 -86
  208. edc_pharmacy/migrations/0037_remove_historicalstock_confirmed_at_site_by_and_more.py +5 -5
  209. edc_pharmacy/migrations/0039_remove_dispense_registered_subject_and_more.py +7 -8
  210. edc_pharmacy/migrations/0049_remove_stocktransferconfirmation_stock_and_more.py +12 -12
  211. edc_pharmacy/migrations/0050_remove_stocktransferconfirmation2_location_and_more.py +5 -5
  212. edc_pharmacy/migrations/0051_alter_historicalstocktransferconfirmationitem_options_and_more.py +3 -4
  213. edc_pharmacy/migrations/0053_alter_location_managers_alter_historicalstock_lot_and_more.py +3 -3
  214. edc_pharmacy/migrations/0057_scanduplicates.py +3 -3
  215. edc_pharmacy/migrations/0060_alter_container_max_per_subject_and_more.py +13 -15
  216. edc_pharmacy/migrations/0068_stockout.py +2 -3
  217. edc_pharmacy/migrations/0076_historicalstockadjustment_stockadjustment.py +5 -5
  218. edc_pharmacy/migrations/0077_historicalstockadjustment_adjustment_datetime_and_more.py +3 -4
  219. edc_pharmacy/migrations/0081_historicalconfirmation_confirmation.py +8 -8
  220. edc_pharmacy/migrations/0084_confirmationatsiteitem_and_more.py +0 -2
  221. edc_pharmacy/migrations/0089_alter_allocation_allocated_by_and_more.py +3284 -0
  222. edc_pharmacy/migrations/0090_alter_allocation_allocation_datetime_and_more.py +227 -0
  223. edc_pharmacy/model_mixins/study_medication_refill_model_mixin.py +2 -2
  224. edc_pharmacy/models/medication/medication.py +3 -3
  225. edc_pharmacy/models/model_mixins.py +10 -11
  226. edc_pharmacy/models/prescription/rx.py +13 -12
  227. edc_pharmacy/models/prescription/rx_refill.py +0 -1
  228. edc_pharmacy/models/stock/allocation.py +3 -3
  229. edc_pharmacy/models/stock/confirmation.py +3 -3
  230. edc_pharmacy/models/stock/confirmation_at_site.py +3 -2
  231. edc_pharmacy/models/stock/confirmation_at_site_item.py +3 -4
  232. edc_pharmacy/models/stock/dispense.py +5 -6
  233. edc_pharmacy/models/stock/dispense_item.py +2 -2
  234. edc_pharmacy/models/stock/location.py +3 -4
  235. edc_pharmacy/models/stock/lot.py +6 -7
  236. edc_pharmacy/models/stock/order.py +1 -1
  237. edc_pharmacy/models/stock/receive.py +3 -3
  238. edc_pharmacy/models/stock/receive_item.py +4 -4
  239. edc_pharmacy/models/stock/repack_request.py +2 -2
  240. edc_pharmacy/models/stock/stock.py +12 -18
  241. edc_pharmacy/models/stock/stock_adjustment.py +4 -4
  242. edc_pharmacy/models/stock/stock_request.py +2 -2
  243. edc_pharmacy/models/stock/stock_request_item.py +2 -2
  244. edc_pharmacy/models/stock/stock_transfer.py +3 -3
  245. edc_pharmacy/models/stock/stock_transfer_item.py +2 -2
  246. edc_pharmacy/models/stock/storage_bin.py +3 -4
  247. edc_pharmacy/models/stock/storage_bin_item.py +2 -2
  248. edc_pharmacy/models/stock/supplier.py +3 -4
  249. edc_pharmacy/models/storage/box.py +2 -2
  250. edc_pharmacy/models/storage/items/container_model_mixin.py +3 -4
  251. edc_pharmacy/models/storage/items/pill_bottle_model_mixin.py +2 -2
  252. edc_pharmacy/models/storage/items/subject_pill_bottle.py +1 -1
  253. edc_pharmacy/models/storage/room.py +2 -2
  254. edc_pharmacy/models/storage/shelf.py +2 -2
  255. edc_pharmacy/models/storage/utils.py +1 -1
  256. edc_pharmacy/utils/allocate_stock.py +2 -3
  257. edc_pharmacy/utils/confirm_stock.py +2 -3
  258. edc_pharmacy/utils/confirm_stock_at_site.py +3 -4
  259. edc_pharmacy/utils/dispense.py +3 -4
  260. edc_pharmacy/utils/process_repack_request.py +4 -5
  261. edc_pharmacy/utils/stock_request/bulk_create_stock_request_items.py +2 -3
  262. edc_pharmacy/utils/transfer_stock.py +2 -3
  263. edc_pharmacy/views/add_to_storage_bin_view.py +2 -2
  264. edc_pharmacy/views/allocate_to_subject_view.py +2 -2
  265. edc_pharmacy/views/dispense_view.py +2 -2
  266. edc_pharmacy/views/move_to_storage_bin_view.py +2 -3
  267. edc_pharmacy/views/print_labels_view.py +2 -2
  268. edc_protocol/research_protocol_config.py +2 -3
  269. edc_protocol_incident/migrations/0001_initial.py +7 -7
  270. edc_protocol_incident/migrations/0001_squashed_0015_auto_20220927_0401.py +13 -13
  271. edc_protocol_incident/migrations/0005_protocolincident_historicalprotocolincident_and_more.py +7 -7
  272. edc_protocol_incident/migrations/0024_alter_actionsrequired_extra_value_and_more.py +625 -0
  273. edc_protocol_incident/migrations/0025_alter_historicalprotocoldeviationviolation_report_datetime_and_more.py +42 -0
  274. edc_protocol_incident/model_mixins/protocol_deviation_violation_model_mixin.py +18 -11
  275. edc_protocol_incident/model_mixins/protocol_incident_model_mixin.py +26 -11
  276. edc_pylabels/actions.py +3 -5
  277. edc_pylabels/migrations/0002_alter_label_options_label_created_and_more.py +3 -7
  278. edc_pylabels/migrations/0005_labelconfiguration_delete_label_and_more.py +3 -3
  279. edc_pylabels/migrations/0013_alter_labelconfiguration_device_created_and_more.py +49 -0
  280. edc_qareports/migrations/0001_initial.py +4 -5
  281. edc_qareports/migrations/0005_edcpermissions.py +3 -3
  282. edc_qareports/migrations/0006_qareportlog.py +2 -3
  283. edc_qareports/migrations/0019_alter_edcpermissions_device_created_and_more.py +102 -0
  284. edc_qareports/migrations/0020_alter_note_report_datetime_and_more.py +24 -0
  285. edc_qareports/model_mixins/note_model_mixin.py +7 -4
  286. edc_qareports/model_mixins/on_study_missing_values_model_mixin.py +4 -4
  287. edc_qareports/model_mixins/qa_report_model_mixin.py +2 -3
  288. edc_qareports/models/note.py +4 -4
  289. edc_qareports/models/qa_reports_log.py +2 -3
  290. edc_randomization/decorators.py +1 -1
  291. edc_randomization/migrations/0001_initial.py +3 -2
  292. edc_randomization/migrations/0002_historicalrandomizationlist.py +3 -2
  293. edc_randomization/migrations/0009_edcpermissions.py +3 -2
  294. edc_randomization/migrations/0014_alter_edcpermissions_device_created_and_more.py +141 -0
  295. edc_randomization/model_mixins.py +9 -9
  296. edc_randomization/utils.py +2 -2
  297. edc_refusal/migrations/0001_initial.py +4 -4
  298. edc_refusal/migrations/0002_historicalsubjectrefusal.py +4 -4
  299. edc_refusal/migrations/0012_alter_historicalsubjectrefusal_comment_and_more.py +122 -0
  300. edc_refusal/migrations/0013_alter_historicalsubjectrefusal_report_datetime_and_more.py +28 -0
  301. edc_refusal/model_mixins.py +3 -3
  302. edc_registration/migrations/0002_auto_20161127_2226.py +3 -4
  303. edc_registration/migrations/0005_auto_20170111_1809.py +4 -2
  304. edc_registration/migrations/0016_historicalregisteredsubject.py +3 -2
  305. edc_registration/migrations/0017_auto_20190305_0123.py +5 -12
  306. edc_registration/migrations/0033_alter_historicalregisteredsubject_additional_key_and_more.py +302 -0
  307. edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py +2 -3
  308. edc_registration/models/registered_subject.py +27 -26
  309. edc_reportable/age_evaluator.py +4 -2
  310. edc_reportable/formula.py +5 -5
  311. edc_reportable/migrations/0001_initial.py +7 -7
  312. edc_reportable/migrations/0003_referencerangecollection_grade1_and_more.py +3 -3
  313. edc_reportable/migrations/0004_alter_referencerangecollection_grade3_and_more.py +5 -5
  314. edc_reportable/migrations/0006_alter_gradingdata_revision_and_more.py +5 -6
  315. edc_reportable/migrations/0007_alter_gradingdata_age_phrase_and_more.py +509 -0
  316. edc_reportable/models/normal_data.py +4 -5
  317. edc_reportable/models/reference_model_mixins.py +10 -11
  318. edc_reportable/models/reference_range_collection.py +12 -13
  319. edc_reportable/post_migrate_signals.py +1 -1
  320. edc_reportable/utils/convert_units.py +11 -45
  321. edc_reportable/utils/get_normal_data_or_raise.py +2 -2
  322. edc_reportable/utils/load_data.py +4 -4
  323. edc_reportable/utils/update_grading_data.py +5 -5
  324. edc_review_dashboard/migrations/0001_initial.py +3 -2
  325. edc_review_dashboard/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
  326. edc_screening/age_evaluator.py +3 -3
  327. edc_screening/migrations/0001_initial.py +3 -2
  328. edc_screening/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
  329. edc_screening/model_mixins/eligibility_model_mixin.py +3 -4
  330. edc_screening/model_mixins/screening_fields_model_mixin.py +6 -8
  331. edc_search/model_mixins.py +2 -3
  332. edc_search/search_slug.py +9 -8
  333. edc_search/updater.py +2 -2
  334. edc_sites/migrations/0007_edcpermissions.py +3 -2
  335. edc_sites/migrations/0010_alter_edcpermissions_device_created_and_more.py +69 -0
  336. edc_sites/model_mixins/site_model_mixin.py +2 -2
  337. edc_sites/site.py +5 -5
  338. edc_sites/system_checks.py +1 -1
  339. edc_subject_dashboard/migrations/0001_initial.py +3 -2
  340. edc_subject_dashboard/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
  341. edc_subject_dashboard/requisition_report.py +6 -4
  342. edc_subject_dashboard/requisition_verifier.py +6 -6
  343. edc_subject_dashboard/templatetags/edc_subject_dashboard_extras.py +2 -2
  344. edc_subject_dashboard/view_mixins/subject_visit_view_mixin.py +7 -8
  345. edc_subject_dashboard/view_utils/subject_consent_listboard_button.py +3 -2
  346. edc_subject_dashboard/view_utils/timepoint_status_button.py +2 -2
  347. edc_timepoint/model_mixins.py +22 -20
  348. edc_transfer/model_mixins.py +4 -4
  349. edc_transfer/modeladmin_mixins.py +1 -1
  350. edc_unblinding/migrations/0001_initial.py +13 -13
  351. edc_unblinding/migrations/0014_alter_historicalunblindingrequest_action_identifier_and_more.py +291 -0
  352. edc_unblinding/migrations/0015_alter_historicalunblindingrequest_report_datetime_and_more.py +45 -0
  353. edc_unblinding/models/unblinding_request.py +2 -2
  354. edc_unblinding/models/unblinding_review.py +3 -3
  355. edc_utils/age.py +10 -16
  356. edc_visit_schedule/migrations/0001_initial.py +3 -3
  357. edc_visit_schedule/migrations/0002_auto_20190305_0123.py +3 -6
  358. edc_visit_schedule/migrations/0003_historicalvisitschedule_visitschedule.py +5 -4
  359. edc_visit_schedule/migrations/0015_historicalonschedule_offschedule_onschedule.py +10 -10
  360. edc_visit_schedule/migrations/0019_alter_historicalonschedule_device_created_and_more.py +229 -0
  361. edc_visit_schedule/migrations/0020_alter_historicalonschedule_onschedule_datetime_and_more.py +65 -0
  362. edc_visit_schedule/model_mixins/off_schedule_model_mixin.py +5 -4
  363. edc_visit_schedule/model_mixins/on_schedule_model_mixin.py +5 -4
  364. edc_visit_schedule/model_mixins/visit_schedule/visit_code_fields_model_mixin.py +1 -1
  365. edc_visit_schedule/models/subject_schedule_history.py +6 -6
  366. edc_visit_schedule/schedule/visit_collection.py +1 -1
  367. edc_visit_schedule/subject_schedule.py +5 -4
  368. edc_visit_schedule/view_mixins.py +2 -3
  369. edc_visit_schedule/visit/visit.py +3 -2
  370. edc_visit_tracking/migrations/0004_subjectvisit_subjectvisitmissedreasons_extra_value_and_more.py +13 -13
  371. edc_visit_tracking/migrations/0009_alter_historicalsubjectvisit_comments_and_more.py +450 -0
  372. edc_visit_tracking/migrations/0010_alter_historicalsubjectvisit_report_datetime_and_more.py +68 -0
  373. edc_visit_tracking/model_mixins/base/visit_methods_model_mixin.py +3 -3
  374. edc_visit_tracking/model_mixins/crfs/visit_tracking_crf_model_mixin.py +2 -2
  375. edc_visit_tracking/model_mixins/requisitions/visit_tracking_requisition_model_mixin.py +2 -2
  376. edc_visit_tracking/model_mixins/subject_visit_missed_model_mixin.py +2 -2
  377. edc_visit_tracking/model_mixins/visit_model_mixin/caretaker_fields_mixin.py +2 -3
  378. edc_visit_tracking/model_mixins/visit_model_mixin/previous_visit_model_mixin.py +1 -1
  379. edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_fields_mixin.py +8 -11
  380. edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_mixin.py +1 -1
  381. edc_visit_tracking/models/signals.py +1 -1
  382. edc_visit_tracking/models/subject_visit.py +1 -1
  383. edc_vitals/calculators/bmi.py +7 -5
  384. edc_vitals/form_validators/blood_pressure_form_validator_mixin.py +3 -1
  385. edc_vitals/utils.py +1 -1
  386. {clinicedc-2.0.5.dist-info → clinicedc-2.0.7.dist-info}/WHEEL +0 -0
  387. {clinicedc-2.0.5.dist-info → clinicedc-2.0.7.dist-info}/licenses/LICENSE +0 -0
@@ -1,7 +1,7 @@
1
+ import django.utils.timezone
1
2
  from django.db import models
2
3
 
3
4
  from edc_identifier.model_mixins import UniqueSubjectIdentifierFieldMixin
4
- from edc_utils import get_utcnow
5
5
 
6
6
  from .locator_methods_model_mixin import LocatorMethodsModelMixin
7
7
  from .subject_contact_fields_mixin import SubjectContactFieldsMixin
@@ -30,7 +30,7 @@ class LocatorModelMixin(
30
30
  This model is used in ListboardViews.
31
31
  """
32
32
 
33
- report_datetime = models.DateTimeField(default=get_utcnow)
33
+ report_datetime = models.DateTimeField(default=django.utils.timezone.now)
34
34
 
35
35
  objects = LocatorManager()
36
36
 
@@ -30,7 +30,7 @@ class SubjectContactFieldsMixin(models.Model):
30
30
  may_sms = models.CharField(
31
31
  max_length=25,
32
32
  choices=YES_NO,
33
- null=True,
33
+ default="",
34
34
  blank=False,
35
35
  verbose_name=format_html(
36
36
  "Has the participant given permission <b>{text}</b> "
@@ -1,12 +1,13 @@
1
1
  from django.contrib import admin
2
2
  from django.template.loader import render_to_string
3
+ from django.utils import timezone
3
4
  from django_audit_fields.admin import audit_fieldset_tuple
4
5
 
5
6
  from edc_consent import site_consents
6
7
  from edc_constants.constants import NO, YES
7
8
  from edc_model_admin.mixins import ModelAdminProtectPiiMixin
8
9
  from edc_sites import site_sites
9
- from edc_utils import age, get_utcnow
10
+ from edc_utils.age import age
10
11
 
11
12
  from .fieldsets import (
12
13
  indirect_contacts_fieldset,
@@ -19,7 +20,7 @@ from .forms import SubjectLocatorForm
19
20
  class SubjectLocatorModelAdminMixin(ModelAdminProtectPiiMixin):
20
21
  form = SubjectLocatorForm
21
22
 
22
- extra_pii_attrs: list[str] = ["contacts"]
23
+ extra_pii_attrs: list[str] = ("contacts",)
23
24
 
24
25
  fieldsets = (
25
26
  (None, {"fields": ("subject_identifier",)}),
@@ -29,7 +30,7 @@ class SubjectLocatorModelAdminMixin(ModelAdminProtectPiiMixin):
29
30
  audit_fieldset_tuple,
30
31
  )
31
32
 
32
- radio_fields = {
33
+ radio_fields = { # noqa: RUF012
33
34
  "may_visit_home": admin.VERTICAL,
34
35
  "may_call": admin.VERTICAL,
35
36
  "may_sms": admin.VERTICAL,
@@ -74,7 +75,7 @@ class SubjectLocatorModelAdminMixin(ModelAdminProtectPiiMixin):
74
75
  context = dict(
75
76
  subject_identifier=obj.subject_identifier,
76
77
  gender=consent.gender.upper(),
77
- age_in_years=age(born=consent.dob, reference_dt=get_utcnow()).years,
78
+ age_in_years=age(born=consent.dob, reference_dt=timezone.now()).years,
78
79
  initials=consent.initials,
79
80
  )
80
81
  return render_to_string("edc_locator/changelist_locator_subject.html", context=context)
edc_ltfu/model_mixins.py CHANGED
@@ -1,10 +1,10 @@
1
1
  from django.core.validators import MinValueValidator
2
2
  from django.db import models
3
+ from django.utils import timezone
3
4
 
4
5
  from edc_constants.choices import YES_NO
5
6
  from edc_model import models as edc_models
6
7
  from edc_protocol.validators import date_not_before_study_start
7
- from edc_utils.date import get_utcnow
8
8
 
9
9
  from .choices import LTFU_CHOICES
10
10
 
@@ -12,7 +12,7 @@ from .choices import LTFU_CHOICES
12
12
  class LtfuModelMixin(models.Model):
13
13
  report_datetime = models.DateTimeField(
14
14
  verbose_name="Report Date and Time",
15
- default=get_utcnow,
15
+ default=timezone.now,
16
16
  validators=[date_not_before_study_start],
17
17
  )
18
18
 
@@ -33,7 +33,7 @@ class LtfuModelMixin(models.Model):
33
33
 
34
34
  ltfu_date = models.DateField(
35
35
  verbose_name="Date participant considered lost to follow up",
36
- default=get_utcnow,
36
+ default=timezone.now,
37
37
  null=True,
38
38
  blank=False,
39
39
  )
@@ -42,12 +42,12 @@ class LtfuModelMixin(models.Model):
42
42
  verbose_name="Was contact by phone attempted",
43
43
  max_length=15,
44
44
  choices=YES_NO,
45
- null=True,
45
+ default="",
46
46
  blank=False,
47
47
  )
48
48
  phone_attempts = models.IntegerField(
49
49
  verbose_name=(
50
- "If YES, how many attempts were made to contact the participant by phone",
50
+ "If YES, how many attempts were made to contact the participant by phone"
51
51
  ),
52
52
  validators=[MinValueValidator(0)],
53
53
  default=0,
@@ -60,6 +60,7 @@ class LtfuModelMixin(models.Model):
60
60
  home_visit_detail = models.TextField(
61
61
  verbose_name="If YES, provide any further details of the home visit",
62
62
  blank=True,
63
+ default="",
63
64
  )
64
65
 
65
66
  ltfu_category = models.CharField(
@@ -76,6 +77,7 @@ class LtfuModelMixin(models.Model):
76
77
  "circumstances that led to this decision."
77
78
  ),
78
79
  blank=True,
80
+ default="",
79
81
  )
80
82
 
81
83
  class Meta:
@@ -9,7 +9,7 @@ class RegisterRuleGroupError(Exception):
9
9
  pass
10
10
 
11
11
 
12
- def register(site=None, **kwargs) -> Any: # noqa
12
+ def register(site=None, **kwargs) -> Any:
13
13
  """Registers a rule group."""
14
14
  site = site or site_metadata_rules
15
15
 
@@ -4,7 +4,7 @@ from __future__ import unicode_literals
4
4
 
5
5
  from django.db import migrations, models
6
6
 
7
- import edc_utils
7
+ import django.utils.timezone
8
8
 
9
9
 
10
10
  class Migration(migrations.Migration):
@@ -14,21 +14,21 @@ class Migration(migrations.Migration):
14
14
  migrations.AlterField(
15
15
  model_name="crfmetadata",
16
16
  name="created",
17
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
17
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
18
18
  ),
19
19
  migrations.AlterField(
20
20
  model_name="crfmetadata",
21
21
  name="modified",
22
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
22
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
23
23
  ),
24
24
  migrations.AlterField(
25
25
  model_name="requisitionmetadata",
26
26
  name="created",
27
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
27
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
28
28
  ),
29
29
  migrations.AlterField(
30
30
  model_name="requisitionmetadata",
31
31
  name="modified",
32
- field=models.DateTimeField(default=edc_utils.date.get_utcnow, editable=False),
32
+ field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
33
33
  ),
34
34
  ]
@@ -6,7 +6,7 @@ from django.db import migrations, models
6
6
 
7
7
  import edc_model_fields.fields.hostname_modification_field
8
8
  import edc_model_fields.fields.userfield
9
- import edc_utils
9
+ import django.utils.timezone
10
10
 
11
11
 
12
12
  class Migration(migrations.Migration):
@@ -16,7 +16,7 @@ class Migration(migrations.Migration):
16
16
  migrations.AlterField(
17
17
  model_name="crfmetadata",
18
18
  name="created",
19
- field=models.DateTimeField(blank=True, default=edc_utils.date.get_utcnow),
19
+ field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
20
20
  ),
21
21
  migrations.AlterField(
22
22
  model_name="crfmetadata",
@@ -40,7 +40,7 @@ class Migration(migrations.Migration):
40
40
  migrations.AlterField(
41
41
  model_name="crfmetadata",
42
42
  name="modified",
43
- field=models.DateTimeField(blank=True, default=edc_utils.date.get_utcnow),
43
+ field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
44
44
  ),
45
45
  migrations.AlterField(
46
46
  model_name="crfmetadata",
@@ -59,7 +59,7 @@ class Migration(migrations.Migration):
59
59
  migrations.AlterField(
60
60
  model_name="requisitionmetadata",
61
61
  name="created",
62
- field=models.DateTimeField(blank=True, default=edc_utils.date.get_utcnow),
62
+ field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
63
63
  ),
64
64
  migrations.AlterField(
65
65
  model_name="requisitionmetadata",
@@ -83,7 +83,7 @@ class Migration(migrations.Migration):
83
83
  migrations.AlterField(
84
84
  model_name="requisitionmetadata",
85
85
  name="modified",
86
- field=models.DateTimeField(blank=True, default=edc_utils.date.get_utcnow),
86
+ field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
87
87
  ),
88
88
  migrations.AlterField(
89
89
  model_name="requisitionmetadata",
@@ -4,6 +4,7 @@ import django_audit_fields.fields.hostname_modification_field
4
4
  import django_audit_fields.fields.userfield
5
5
  import django_audit_fields.models.audit_model_mixin
6
6
  from django.db import migrations, models
7
+ import django.utils.timezone
7
8
 
8
9
 
9
10
  class Migration(migrations.Migration):
@@ -13,9 +14,7 @@ class Migration(migrations.Migration):
13
14
  migrations.AlterField(
14
15
  model_name="crfmetadata",
15
16
  name="created",
16
- field=models.DateTimeField(
17
- blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
18
- ),
17
+ field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
19
18
  ),
20
19
  migrations.AlterField(
21
20
  model_name="crfmetadata",
@@ -29,9 +28,7 @@ class Migration(migrations.Migration):
29
28
  migrations.AlterField(
30
29
  model_name="crfmetadata",
31
30
  name="modified",
32
- field=models.DateTimeField(
33
- blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
34
- ),
31
+ field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
35
32
  ),
36
33
  migrations.AlterField(
37
34
  model_name="crfmetadata",
@@ -56,9 +53,7 @@ class Migration(migrations.Migration):
56
53
  migrations.AlterField(
57
54
  model_name="requisitionmetadata",
58
55
  name="created",
59
- field=models.DateTimeField(
60
- blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
61
- ),
56
+ field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
62
57
  ),
63
58
  migrations.AlterField(
64
59
  model_name="requisitionmetadata",
@@ -72,9 +67,7 @@ class Migration(migrations.Migration):
72
67
  migrations.AlterField(
73
68
  model_name="requisitionmetadata",
74
69
  name="modified",
75
- field=models.DateTimeField(
76
- blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
77
- ),
70
+ field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
78
71
  ),
79
72
  migrations.AlterField(
80
73
  model_name="requisitionmetadata",
@@ -0,0 +1,120 @@
1
+ # Generated by Django 5.2.6 on 2025-09-17 16:53
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("edc_metadata", "0030_alter_crfmetadata_revision_and_more"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name="crfmetadata",
15
+ name="device_created",
16
+ field=models.CharField(
17
+ blank=True, default="", max_length=10, verbose_name="Device created"
18
+ ),
19
+ ),
20
+ migrations.AlterField(
21
+ model_name="crfmetadata",
22
+ name="device_modified",
23
+ field=models.CharField(
24
+ blank=True, default="", max_length=10, verbose_name="Device modified"
25
+ ),
26
+ ),
27
+ migrations.AlterField(
28
+ model_name="crfmetadata",
29
+ name="document_name",
30
+ field=models.CharField(default="", max_length=250, verbose_name="Document"),
31
+ ),
32
+ migrations.AlterField(
33
+ model_name="crfmetadata",
34
+ name="document_user",
35
+ field=models.CharField(default="", max_length=50, verbose_name="User"),
36
+ ),
37
+ migrations.AlterField(
38
+ model_name="crfmetadata",
39
+ name="entry_comment",
40
+ field=models.TextField(blank=True, default="", max_length=250),
41
+ ),
42
+ migrations.AlterField(
43
+ model_name="crfmetadata",
44
+ name="locale_created",
45
+ field=models.CharField(
46
+ blank=True,
47
+ default="",
48
+ help_text="Auto-updated by Modeladmin",
49
+ max_length=10,
50
+ verbose_name="Locale created",
51
+ ),
52
+ ),
53
+ migrations.AlterField(
54
+ model_name="crfmetadata",
55
+ name="locale_modified",
56
+ field=models.CharField(
57
+ blank=True,
58
+ default="",
59
+ help_text="Auto-updated by Modeladmin",
60
+ max_length=10,
61
+ verbose_name="Locale modified",
62
+ ),
63
+ ),
64
+ migrations.AlterField(
65
+ model_name="requisitionmetadata",
66
+ name="device_created",
67
+ field=models.CharField(
68
+ blank=True, default="", max_length=10, verbose_name="Device created"
69
+ ),
70
+ ),
71
+ migrations.AlterField(
72
+ model_name="requisitionmetadata",
73
+ name="device_modified",
74
+ field=models.CharField(
75
+ blank=True, default="", max_length=10, verbose_name="Device modified"
76
+ ),
77
+ ),
78
+ migrations.AlterField(
79
+ model_name="requisitionmetadata",
80
+ name="document_name",
81
+ field=models.CharField(default="", max_length=250, verbose_name="Document"),
82
+ ),
83
+ migrations.AlterField(
84
+ model_name="requisitionmetadata",
85
+ name="document_user",
86
+ field=models.CharField(default="", max_length=50, verbose_name="User"),
87
+ ),
88
+ migrations.AlterField(
89
+ model_name="requisitionmetadata",
90
+ name="entry_comment",
91
+ field=models.TextField(blank=True, default="", max_length=250),
92
+ ),
93
+ migrations.AlterField(
94
+ model_name="requisitionmetadata",
95
+ name="locale_created",
96
+ field=models.CharField(
97
+ blank=True,
98
+ default="",
99
+ help_text="Auto-updated by Modeladmin",
100
+ max_length=10,
101
+ verbose_name="Locale created",
102
+ ),
103
+ ),
104
+ migrations.AlterField(
105
+ model_name="requisitionmetadata",
106
+ name="locale_modified",
107
+ field=models.CharField(
108
+ blank=True,
109
+ default="",
110
+ help_text="Auto-updated by Modeladmin",
111
+ max_length=10,
112
+ verbose_name="Locale modified",
113
+ ),
114
+ ),
115
+ migrations.AlterField(
116
+ model_name="requisitionmetadata",
117
+ name="panel_name",
118
+ field=models.CharField(default="", max_length=50),
119
+ ),
120
+ ]
@@ -59,7 +59,7 @@ class UpdatesCrfMetadataModelMixin(UpdatesMetadataModelMixin):
59
59
  crfs = self.metadata_visit_object.crfs_unscheduled.forms + crfs_prn.forms
60
60
  else:
61
61
  crfs = self.metadata_visit_object.crfs.forms + crfs_prn.forms
62
- crf = [c for c in crfs if c.model == self._meta.label_lower][0]
62
+ crf = next(c for c in crfs if c.model == self._meta.label_lower)
63
63
  return REQUIRED if crf.required else NOT_REQUIRED
64
64
 
65
65
  class Meta:
@@ -64,7 +64,7 @@ class UpdatesRequisitionMetadataModelMixin(UpdatesMetadataModelMixin):
64
64
  requisitions = (
65
65
  self.metadata_visit_object.requisitions.forms + requisitions_prn.forms
66
66
  )
67
- requisition = [r for r in requisitions if r.panel.name == self.panel.name][0]
67
+ requisition = next(r for r in requisitions if r.panel.name == self.panel.name)
68
68
  return REQUIRED if requisition.required else NOT_REQUIRED
69
69
 
70
70
  @property
@@ -29,7 +29,7 @@ class CrfMetadata(CrfMetadataModelMixin, BaseUuidModel):
29
29
  )
30
30
 
31
31
  # noinspection PyTypeHints
32
- natural_key.dependencies = ["sites.Site"] # type: ignore
32
+ natural_key.dependencies = ("sites.Site",)
33
33
 
34
34
  @property
35
35
  def verbose_name(self) -> str:
@@ -42,8 +42,8 @@ class CrfMetadata(CrfMetadataModelMixin, BaseUuidModel):
42
42
  class Meta(CrfMetadataModelMixin.Meta, BaseUuidModel.Meta):
43
43
  verbose_name = "Crf collection status"
44
44
  verbose_name_plural = "Crf collection status"
45
- unique_together = []
46
- constraints = [
45
+ unique_together = ()
46
+ constraints = (
47
47
  UniqueConstraint(
48
48
  fields=[
49
49
  "subject_identifier",
@@ -54,8 +54,8 @@ class CrfMetadata(CrfMetadataModelMixin, BaseUuidModel):
54
54
  "model",
55
55
  ],
56
56
  name="%(app_label)s_%(class)s_subject_iden_visit_uniq",
57
- )
58
- ]
57
+ ),
58
+ )
59
59
  indexes = (
60
60
  *CrfMetadataModelMixin.Meta.indexes,
61
61
  *BaseUuidModel.Meta.indexes,
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import contextlib
3
4
  from typing import TYPE_CHECKING, Any
4
5
 
5
6
  from django.apps import apps as django_apps
@@ -38,7 +39,7 @@ class CrfMetadataModelMixin(
38
39
 
39
40
  model = models.CharField(max_length=50)
40
41
 
41
- document_name = models.CharField(verbose_name=_("Document"), max_length=250, null=True)
42
+ document_name = models.CharField(verbose_name=_("Document"), max_length=250, default="")
42
43
 
43
44
  show_order = models.IntegerField() # must always be provided!
44
45
 
@@ -54,7 +55,7 @@ class CrfMetadataModelMixin(
54
55
 
55
56
  fill_datetime = models.DateTimeField(null=True, blank=True)
56
57
 
57
- document_user = models.CharField(verbose_name=_("User"), max_length=50, null=True)
58
+ document_user = models.CharField(verbose_name=_("User"), max_length=50, default="")
58
59
 
59
60
  def natural_key(self):
60
61
  return (
@@ -92,10 +93,8 @@ class CrfMetadataModelMixin(
92
93
  def model_instance(self: Any) -> Any:
93
94
  """Returns the CRF/Requisition model instance or None"""
94
95
  instance = None
95
- try:
96
+ with contextlib.suppress(ObjectDoesNotExist):
96
97
  instance = self.model_cls.objects.get(**self.model_instance_query_opts())
97
- except ObjectDoesNotExist:
98
- pass
99
98
  return instance
100
99
 
101
100
  def refresh_entry_status(self) -> str:
@@ -10,7 +10,7 @@ from .crf_metadata_model_mixin import CrfMetadataModelMixin
10
10
 
11
11
 
12
12
  class RequisitionMetadata(CrfMetadataModelMixin, BaseUuidModel):
13
- panel_name = models.CharField(max_length=50, null=True)
13
+ panel_name = models.CharField(max_length=50, default="")
14
14
 
15
15
  objects = RequisitionMetadataManager()
16
16
 
@@ -26,7 +26,7 @@ class RequisitionMetadata(CrfMetadataModelMixin, BaseUuidModel):
26
26
 
27
27
  @property
28
28
  def verbose_name(self) -> str:
29
- from edc_lab.site_labs import site_labs
29
+ from edc_lab.site_labs import site_labs # noqa: PLC0415
30
30
 
31
31
  return site_labs.panel_names.get(self.panel_name) or self.panel_name
32
32
 
@@ -42,7 +42,7 @@ class RequisitionMetadata(CrfMetadataModelMixin, BaseUuidModel):
42
42
  )
43
43
 
44
44
  # noinspection PyTypeHints
45
- natural_key.dependencies = ["sites.Site"] # type: ignore
45
+ natural_key.dependencies = ("sites.Site",) # type: ignore
46
46
 
47
47
  def model_instance_query_opts(self) -> dict:
48
48
  opts = super().model_instance_query_opts()
@@ -71,7 +71,7 @@ class RequisitionMetadata(CrfMetadataModelMixin, BaseUuidModel):
71
71
  app_label = "edc_metadata"
72
72
  verbose_name = "Requisition collection status"
73
73
  verbose_name_plural = "Requisition collection status"
74
- constraints = [
74
+ constraints = (
75
75
  UniqueConstraint(
76
76
  fields=[
77
77
  "subject_identifier",
@@ -83,8 +83,8 @@ class RequisitionMetadata(CrfMetadataModelMixin, BaseUuidModel):
83
83
  "panel_name",
84
84
  ],
85
85
  name="%(app_label)s_%(class)s_subject_iden_visit_uniq",
86
- )
87
- ]
86
+ ),
87
+ )
88
88
  indexes = (
89
89
  *CrfMetadataModelMixin.Meta.indexes,
90
90
  *BaseUuidModel.Meta.indexes,
@@ -3,11 +3,11 @@ from django.contrib.auth.mixins import LoginRequiredMixin
3
3
  from django.contrib.messages import SUCCESS
4
4
  from django.http.response import HttpResponseRedirect
5
5
  from django.urls import reverse
6
+ from django.utils import timezone
6
7
  from django.views import View
7
8
 
8
9
  from edc_appointment.utils import update_appt_status_for_timepoint
9
10
  from edc_dashboard.url_names import url_names
10
- from edc_utils import get_utcnow
11
11
  from edc_utils.round_up import round_half_away_from_zero
12
12
  from edc_visit_tracking.utils import get_related_visit_model_cls
13
13
 
@@ -34,7 +34,7 @@ class RefreshMetadataActionsView(LoginRequiredMixin, View):
34
34
  return related_visit
35
35
 
36
36
  def get(self, request, *args, **kwargs):
37
- dte1 = get_utcnow()
37
+ dte1 = timezone.now()
38
38
  related_visit = self.refresh_metadata_for_timepoint(**kwargs)
39
39
  url_name = url_names.get("subject_dashboard_url")
40
40
  args = (
@@ -47,7 +47,7 @@ class RefreshMetadataActionsView(LoginRequiredMixin, View):
47
47
  SUCCESS,
48
48
  f"The data collection schedule for {related_visit.visit_code}."
49
49
  f"{related_visit.visit_code_sequence} has been refreshed "
50
- f"({round_half_away_from_zero((get_utcnow()-dte1).microseconds/1000000, 2)} "
50
+ f"({round_half_away_from_zero((timezone.now() - dte1).microseconds / 1000000, 2)} "
51
51
  "seconds)",
52
52
  )
53
53
  return HttpResponseRedirect(url)
@@ -2,7 +2,7 @@ from django.db import models
2
2
 
3
3
 
4
4
  class AddressMixin(models.Model):
5
- contact_name = models.CharField(max_length=50, null=True, blank=True)
5
+ contact_name = models.CharField(max_length=50, default="", blank=True)
6
6
 
7
7
  address = models.CharField(verbose_name="Address", max_length=50)
8
8
 
@@ -11,18 +11,18 @@ class AddressMixin(models.Model):
11
11
  city = models.CharField(max_length=50)
12
12
 
13
13
  state = models.CharField(
14
- verbose_name="State or Province", null=True, blank=True, max_length=50
14
+ verbose_name="State or Province", default="", blank=True, max_length=50
15
15
  )
16
16
 
17
17
  country = models.CharField(max_length=50)
18
18
 
19
- telephone = models.CharField(null=True, blank=True, max_length=50)
19
+ telephone = models.CharField(default="", blank=True, max_length=50)
20
20
 
21
- mobile = models.CharField(null=True, blank=True, max_length=50)
21
+ mobile = models.CharField(default="", blank=True, max_length=50)
22
22
 
23
- fax = models.CharField(null=True, blank=True, max_length=50)
23
+ fax = models.CharField(default="", blank=True, max_length=50)
24
24
 
25
- email = models.EmailField(null=True, blank=True, max_length=50)
25
+ email = models.EmailField(default="", blank=True, max_length=50)
26
26
 
27
27
  class Meta:
28
28
  abstract = True
@@ -12,6 +12,7 @@ class InitialsField(CharField):
12
12
  kwargs.setdefault("editable", True)
13
13
  kwargs.setdefault("verbose_name", _("Initials"))
14
14
  kwargs.setdefault("max_length", 3)
15
+ kwargs.setdefault("default", "")
15
16
  kwargs.setdefault("help_text", _("Type 2-3 letters, all in uppercase and no spaces"))
16
17
  CharField.__init__(self, *args, **kwargs)
17
18
 
@@ -31,4 +32,4 @@ class InitialsField(CharField):
31
32
  },
32
33
  }
33
34
  defaults.update(kwargs)
34
- return super(InitialsField, self).formfield(**defaults)
35
+ return super().formfield(**defaults)
@@ -16,10 +16,7 @@ class SerializableModel(models.Model):
16
16
  return (self.history_id,)
17
17
 
18
18
  def related_visit_model_attr(self):
19
- try:
20
- return self.history_object.related_visit_model_attr()
21
- except AttributeError:
22
- raise
19
+ return self.history_object.related_visit_model_attr()
23
20
 
24
21
  @property
25
22
  def related_visit(self):
@@ -61,10 +58,6 @@ class HistoricalRecords(SimpleHistoricalRecords):
61
58
  super().__init__(**kwargs)
62
59
 
63
60
  def contribute_to_class(self, cls, name):
64
- try:
65
- cls.related_visit_model_attr
66
- except AttributeError:
67
- pass
68
- else:
61
+ if getattr(cls, "related_visit_model_attr", None):
69
62
  self.model_cls = SerializableCrfModel
70
63
  return super().contribute_to_class(cls, name)
@@ -5,7 +5,7 @@ from django.urls import reverse
5
5
  from django.urls.exceptions import NoReverseMatch
6
6
 
7
7
 
8
- class UrlModelMixinNoReverseMatch(Exception):
8
+ class UrlModelMixinNoReverseMatch(Exception): # noqa: N818
9
9
  pass
10
10
 
11
11
 
@@ -23,7 +23,7 @@ class UrlModelMixin(models.Model):
23
23
  f"Tried {self.admin_url_name}. Got {e}. "
24
24
  "Check urls and confirm app is in INSTALLED_APPS. If running tests, "
25
25
  "you may need to set `use_test_urls=True`."
26
- )
26
+ ) from e
27
27
  return absolute_url
28
28
 
29
29
  def get_changelist_url(self, search_term=None) -> str: