clinicedc 2.0.6__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 (386) hide show
  1. {clinicedc-2.0.6.dist-info → clinicedc-2.0.7.dist-info}/METADATA +2 -2
  2. {clinicedc-2.0.6.dist-info → clinicedc-2.0.7.dist-info}/RECORD +386 -335
  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/utils.py +1 -1
  385. {clinicedc-2.0.6.dist-info → clinicedc-2.0.7.dist-info}/WHEEL +0 -0
  386. {clinicedc-2.0.6.dist-info → clinicedc-2.0.7.dist-info}/licenses/LICENSE +0 -0
@@ -1,11 +1,10 @@
1
1
  import csv
2
- import os
3
2
  import uuid
3
+ from pathlib import Path
4
4
 
5
5
  from django.apps import apps as django_apps
6
6
  from django.core.exceptions import ValidationError
7
-
8
- from edc_utils import get_utcnow
7
+ from django.utils import timezone
9
8
 
10
9
  from ..utils import get_export_folder
11
10
  from .file_history_updater import FileHistoryUpdater
@@ -17,11 +16,11 @@ class ModelExporterError(Exception):
17
16
  pass
18
17
 
19
18
 
20
- class ModelExporterInvalidLookup(Exception):
19
+ class ModelExporterInvalidLookup(Exception): # noqa: N818
21
20
  pass
22
21
 
23
22
 
24
- class ModelExporterUnknownField(ValidationError):
23
+ class ModelExporterUnknownField(ValidationError): # noqa: N818
25
24
  pass
26
25
 
27
26
 
@@ -40,14 +39,14 @@ class ModelExporter:
40
39
  value_getter_cls = ValueGetter
41
40
  additional_values_cls = AdditionalValues
42
41
 
43
- export_fields = [
42
+ export_fields = (
44
43
  "export_uuid",
45
44
  "timestamp",
46
45
  "export_datetime",
47
46
  "export_change_type",
48
- ]
49
- required_fields = ["subject_identifier", "report_datetime"]
50
- audit_fields = [
47
+ )
48
+ required_fields = ("subject_identifier", "report_datetime")
49
+ audit_fields = (
51
50
  "hostname_created",
52
51
  "hostname_modified",
53
52
  "created",
@@ -55,7 +54,7 @@ class ModelExporter:
55
54
  "user_created",
56
55
  "user_modified",
57
56
  "revision",
58
- ]
57
+ )
59
58
 
60
59
  def __init__(
61
60
  self,
@@ -117,13 +116,13 @@ class ModelExporter:
117
116
  self._model_cls = self.queryset.model
118
117
  return self._model_cls
119
118
 
120
- def export(self, queryset=None):
119
+ def export(self, queryset=None) -> Path:
121
120
  """Writes the export file and returns the file name."""
122
121
  self.queryset = queryset or self.queryset
123
- exported_datetime = get_utcnow()
122
+ exported_datetime = timezone.now()
124
123
  filename = self.get_filename(exported_datetime)
125
- path = os.path.join(get_export_folder(), filename)
126
- with open(path, "w") as f:
124
+ path = get_export_folder() / filename
125
+ with path.open("w") as f:
127
126
  csv_writer = csv.DictWriter(
128
127
  f, fieldnames=self.field_names, delimiter=self.delimiter
129
128
  )
@@ -1,9 +1,9 @@
1
1
  from django.apps import apps as django_apps
2
2
  from django.core import serializers
3
3
  from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
4
+ from django.utils import timezone
4
5
 
5
6
  from edc_constants.constants import NEW
6
- from edc_utils import get_utcnow
7
7
 
8
8
  from ..constants import EXPORTED, INSERT, UPDATE
9
9
 
@@ -24,7 +24,7 @@ class ObjectHistoryCreator(Base):
24
24
  def create(self, model_obj=None, change_type=None, using=None):
25
25
  if not change_type:
26
26
  change_type = self.get_change_type(model_obj=model_obj)
27
- export_datetime = get_utcnow()
27
+ export_datetime = timezone.now()
28
28
  if model_obj._meta.proxy_for_model: # if proxy model, get main model
29
29
  model_obj = model_obj._meta.proxy_for_model.objects.get(id=model_obj.id)
30
30
  obj = self.model_cls.objects.using(using).create(
@@ -1,10 +1,10 @@
1
1
  from django.db import models
2
2
  from django.db.models import Index
3
3
  from django.db.models.deletion import PROTECT
4
+ from django.utils import timezone
4
5
 
5
6
  from edc_model.models import BaseUuidModel
6
7
  from edc_sites.model_mixins import SiteModelMixin
7
- from edc_utils import get_utcnow
8
8
 
9
9
  from .data_request import DataRequest
10
10
 
@@ -12,15 +12,15 @@ from .data_request import DataRequest
12
12
  class DataRequestHistory(SiteModelMixin, BaseUuidModel):
13
13
  data_request = models.ForeignKey(DataRequest, on_delete=PROTECT)
14
14
 
15
- archive_filename = models.CharField(max_length=200, null=True)
15
+ archive_filename = models.CharField(max_length=200, default="")
16
16
 
17
- emailed_to = models.EmailField(null=True)
17
+ emailed_to = models.EmailField(default="")
18
18
 
19
19
  emailed_datetime = models.DateTimeField(null=True)
20
20
 
21
21
  summary = models.TextField(default="")
22
22
 
23
- exported_datetime = models.DateTimeField(default=get_utcnow)
23
+ exported_datetime = models.DateTimeField(default=timezone.now)
24
24
 
25
25
  class Meta:
26
26
  verbose_name = "Data Request History"
edc_export/utils.py CHANGED
@@ -1,10 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
- import os
4
3
  import re
5
4
  from collections.abc import Iterable
5
+ from pathlib import Path
6
6
 
7
7
  from django import forms
8
+ from django.conf import settings
8
9
  from django.utils.html import format_html
9
10
 
10
11
  from edc_protocol.research_protocol_config import ResearchProtocolConfig
@@ -13,15 +14,13 @@ from .constants import EXPORT_PII
13
14
  from .exceptions import ExporterExportFolder
14
15
 
15
16
 
16
- def get_export_folder() -> str:
17
- from django.conf import settings
18
-
17
+ def get_export_folder() -> Path:
19
18
  if path := getattr(settings, "EDC_EXPORT_EXPORT_FOLDER", None):
20
- return os.path.expanduser(path)
21
- return os.path.join(settings.MEDIA_ROOT, "data_folder", "export")
19
+ return Path(path).expanduser()
20
+ return Path(settings.MEDIA_ROOT) / "data_folder" / "export"
22
21
 
23
22
 
24
- def get_base_dir() -> str:
23
+ def get_base_dir() -> Path:
25
24
  """Returns the base_dir used by, for example,
26
25
  shutil.make_archive.
27
26
 
@@ -37,20 +36,16 @@ def get_base_dir() -> str:
37
36
  "Invalid base_dir, invalid characters. Using `protocol_lower_name`. "
38
37
  f"Got `{base_dir}`."
39
38
  )
40
- return base_dir
41
-
39
+ return Path(base_dir)
42
40
 
43
- def get_upload_folder() -> str:
44
- from django.conf import settings
45
41
 
42
+ def get_upload_folder() -> Path:
46
43
  if path := getattr(settings, "EDC_EXPORT_UPLOAD_FOLDER", None):
47
- return os.path.expanduser(path)
48
- return os.path.join(settings.MEDIA_ROOT, "data_folder", "upload")
44
+ return Path(path).expanduser()
45
+ return Path(settings.MEDIA_ROOT) / "data_folder" / "upload"
49
46
 
50
47
 
51
48
  def get_export_pii_users() -> list[str]:
52
- from django.conf import settings
53
-
54
49
  return getattr(settings, "EDC_EXPORT_EXPORT_PII_USERS", [])
55
50
 
56
51
 
edc_facility/facility.py CHANGED
@@ -10,14 +10,15 @@ from arrow import Arrow
10
10
  from dateutil._common import weekday
11
11
  from dateutil.relativedelta import relativedelta
12
12
  from django.conf import settings
13
+ from django.utils import timezone
13
14
 
14
- from edc_utils import convert_php_dateformat, get_utcnow, to_utc
15
+ from edc_utils import convert_php_dateformat, to_utc
15
16
 
16
17
  from .exceptions import FacilityError
17
18
  from .holidays import Holidays
18
19
 
19
20
  if TYPE_CHECKING:
20
- from django.contrib.sites.models import Site
21
+ pass
21
22
 
22
23
 
23
24
  class Facility:
@@ -34,9 +35,9 @@ class Facility:
34
35
 
35
36
  def __init__(
36
37
  self,
37
- name: str = None,
38
- days: list = None,
39
- slots: list[int] = None,
38
+ name: str | None = None,
39
+ days: list | None = None,
40
+ slots: list[int] | None = None,
40
41
  best_effort_available_datetime: datetime | None = None,
41
42
  ):
42
43
  self.days = []
@@ -47,11 +48,7 @@ class Facility:
47
48
  True if best_effort_available_datetime is None else best_effort_available_datetime
48
49
  )
49
50
  for day in days:
50
- try:
51
- day.weekday
52
- except AttributeError:
53
- day = weekday(day)
54
- self.days.append(day)
51
+ self.days.append(getattr(day, "weekday", weekday(day)))
55
52
  self.slots = slots or [99999 for _ in self.days]
56
53
  self.config = dict(zip([str(d) for d in self.days], self.slots, strict=False))
57
54
  self.holidays = self.holiday_cls()
@@ -112,7 +109,7 @@ class Facility:
112
109
  span_gt = [arw for arw in span if arw.date() > suggested_arr.date()]
113
110
  arr_span = []
114
111
  max_len = max(len(span_lt), len(span_gt))
115
- for i in range(0, max_len):
112
+ for _ in range(0, max_len):
116
113
  try:
117
114
  item = span_lt.pop()
118
115
  except IndexError:
@@ -135,7 +132,6 @@ class Facility:
135
132
  reverse_delta=None,
136
133
  taken_datetimes=None,
137
134
  schedule_on_holidays=None,
138
- site: Site = None,
139
135
  ):
140
136
  """Returns an arrow object for a datetime equal to or
141
137
  close to the suggested datetime.
@@ -153,7 +149,7 @@ class Facility:
153
149
  if suggested_datetime:
154
150
  suggested_arr = arrow.Arrow.fromdatetime(suggested_datetime)
155
151
  else:
156
- suggested_arr = arrow.Arrow.fromdatetime(get_utcnow())
152
+ suggested_arr = arrow.Arrow.fromdatetime(timezone.now())
157
153
  arr_span_range, min_arr, max_arr = self.get_arr_span(
158
154
  suggested_arr,
159
155
  forward_delta,
@@ -185,7 +181,6 @@ class Facility:
185
181
  f"{forward_delta.days} days of {formatted_date}. "
186
182
  f"Facility is {self!r}."
187
183
  )
188
- available_arr = arrow.Arrow.fromdatetime(
184
+ return arrow.Arrow.fromdatetime(
189
185
  datetime.combine(available_arr.date(), suggested_arr.time())
190
186
  )
191
- return available_arr
@@ -9,10 +9,10 @@ from typing import TYPE_CHECKING
9
9
  from django.conf import settings
10
10
  from django.core.exceptions import ObjectDoesNotExist
11
11
  from django.db import transaction
12
+ from django.utils import timezone
12
13
  from tqdm import tqdm
13
14
 
14
15
  from edc_sites.site import sites
15
- from edc_utils import get_utcnow
16
16
 
17
17
  from .exceptions import HolidayFileNotFoundError, HolidayImportError
18
18
  from .utils import get_holiday_model_cls
@@ -30,14 +30,14 @@ def import_holidays(verbose: bool | None = None, test: bool | None = None) -> No
30
30
  if test:
31
31
  import_for_tests(model_cls)
32
32
  else:
33
- path = settings.HOLIDAY_FILE
33
+ path = Path(settings.HOLIDAY_FILE)
34
34
  try:
35
35
  if not Path(path).exists():
36
36
  raise HolidayFileNotFoundError(path)
37
- except TypeError:
37
+ except TypeError as e:
38
38
  raise HolidayImportError(
39
39
  f"Invalid path importing holiday file. See settings.HOLIDAY_FILE. Got {path}."
40
- )
40
+ ) from e
41
41
  if verbose:
42
42
  sys.stdout.write(
43
43
  f"\nImporting holidays from '{path}' into {model_cls._meta.label_lower}\n"
@@ -52,9 +52,9 @@ def import_holidays(verbose: bool | None = None, test: bool | None = None) -> No
52
52
  sys.stdout.write("Done.\n")
53
53
 
54
54
 
55
- def check_for_duplicates_in_file(path) -> list:
55
+ def check_for_duplicates_in_file(path: Path) -> list:
56
56
  """Returns a list of records."""
57
- with open(path) as f:
57
+ with path.open("r") as f:
58
58
  reader = csv.DictReader(f, fieldnames=["local_date", "label", "country"])
59
59
  recs = [(row["local_date"], row["country"]) for row in reader]
60
60
  if len(recs) != len(list(set(recs))):
@@ -62,18 +62,18 @@ def check_for_duplicates_in_file(path) -> list:
62
62
  return recs
63
63
 
64
64
 
65
- def import_file(path: str, recs: list, model_cls: Holiday):
66
- with open(path) as f:
65
+ def import_file(path: Path, recs: list, model_cls: Holiday):
66
+ with path.open("r") as f:
67
67
  reader = csv.DictReader(f, fieldnames=["local_date", "label", "country"])
68
68
  for index, row in tqdm(enumerate(reader), total=len(recs)):
69
69
  if index == 0:
70
70
  continue
71
71
  try:
72
- local_date = datetime.strptime(row["local_date"], "%Y-%m-%d").date()
72
+ local_date = datetime.strptime(row["local_date"], "%Y-%m-%d").date() # noqa: DTZ007
73
73
  except ValueError as e:
74
74
  raise HolidayImportError(
75
75
  f"Invalid format when importing from {path}. Got '{e}'"
76
- )
76
+ ) from e
77
77
  else:
78
78
  try:
79
79
  obj = model_cls.objects.get(country=row["country"], local_date=local_date)
@@ -87,7 +87,7 @@ def import_file(path: str, recs: list, model_cls: Holiday):
87
87
 
88
88
 
89
89
  def import_for_tests(model_cls: type[Holiday]):
90
- year = get_utcnow().year
90
+ year = timezone.now().year
91
91
  country = sites.get_current_country()
92
92
  if not country:
93
93
  raise HolidayImportError(
@@ -112,11 +112,11 @@ def import_for_tests(model_cls: type[Holiday]):
112
112
  if index == 0:
113
113
  continue
114
114
  try:
115
- local_date = datetime.strptime(row[LOCAL_DATE], "%Y-%m-%d").date()
115
+ local_date = datetime.strptime(row[LOCAL_DATE], "%Y-%m-%d").date() # noqa: DTZ007
116
116
  except ValueError as e:
117
117
  raise HolidayImportError(
118
118
  f"Invalid format when importing holidays (test). Got '{e}'"
119
- )
119
+ ) from e
120
120
  else:
121
121
  objs.append(
122
122
  model_cls(country=row[COUNTRY], local_date=local_date, name=row[LABEL])
@@ -17,7 +17,8 @@ from django.db import migrations, models
17
17
  import edc_facility.model_mixins
18
18
  import edc_model_fields.fields.other_charfield
19
19
  import edc_sites.models
20
- import edc_utils.date
20
+ import django.utils.timezone
21
+ import django.utils.timezone
21
22
 
22
23
 
23
24
  class Migration(migrations.Migration):
@@ -46,14 +47,14 @@ class Migration(migrations.Migration):
46
47
  "created",
47
48
  models.DateTimeField(
48
49
  blank=True,
49
- default=django_audit_fields.models.audit_model_mixin.utcnow,
50
+ default=django.utils.timezone.now,
50
51
  ),
51
52
  ),
52
53
  (
53
54
  "modified",
54
55
  models.DateTimeField(
55
56
  blank=True,
56
- default=django_audit_fields.models.audit_model_mixin.utcnow,
57
+ default=django.utils.timezone.now,
57
58
  ),
58
59
  ),
59
60
  (
@@ -105,7 +106,7 @@ class Migration(migrations.Migration):
105
106
  ),
106
107
  (
107
108
  "report_datetime",
108
- models.DateTimeField(default=edc_utils.date.get_utcnow),
109
+ models.DateTimeField(default=django.utils.timezone.now),
109
110
  ),
110
111
  ("name", models.CharField(max_length=25, unique=True)),
111
112
  (
@@ -265,14 +266,14 @@ class Migration(migrations.Migration):
265
266
  "created",
266
267
  models.DateTimeField(
267
268
  blank=True,
268
- default=django_audit_fields.models.audit_model_mixin.utcnow,
269
+ default=django.utils.timezone.now,
269
270
  ),
270
271
  ),
271
272
  (
272
273
  "modified",
273
274
  models.DateTimeField(
274
275
  blank=True,
275
- default=django_audit_fields.models.audit_model_mixin.utcnow,
276
+ default=django.utils.timezone.now,
276
277
  ),
277
278
  ),
278
279
  (
@@ -323,7 +324,7 @@ class Migration(migrations.Migration):
323
324
  ),
324
325
  (
325
326
  "report_datetime",
326
- models.DateTimeField(default=edc_utils.date.get_utcnow),
327
+ models.DateTimeField(default=django.utils.timezone.now),
327
328
  ),
328
329
  ("name", models.CharField(db_index=True, max_length=25)),
329
330
  (
@@ -0,0 +1,139 @@
1
+ # Generated by Django 5.2.6 on 2025-09-17 16:53
2
+
3
+ import edc_model_fields.fields.other_charfield
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ("edc_facility", "0015_alter_healthfacility_revision_and_more"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AlterField(
15
+ model_name="healthfacility",
16
+ name="device_created",
17
+ field=models.CharField(
18
+ blank=True, default="", max_length=10, verbose_name="Device created"
19
+ ),
20
+ ),
21
+ migrations.AlterField(
22
+ model_name="healthfacility",
23
+ name="device_modified",
24
+ field=models.CharField(
25
+ blank=True, default="", max_length=10, verbose_name="Device modified"
26
+ ),
27
+ ),
28
+ migrations.AlterField(
29
+ model_name="healthfacility",
30
+ name="health_facility_type_other",
31
+ field=edc_model_fields.fields.other_charfield.OtherCharField(
32
+ blank=True,
33
+ default="",
34
+ max_length=35,
35
+ verbose_name="If other, please specify ...",
36
+ ),
37
+ ),
38
+ migrations.AlterField(
39
+ model_name="healthfacility",
40
+ name="locale_created",
41
+ field=models.CharField(
42
+ blank=True,
43
+ default="",
44
+ help_text="Auto-updated by Modeladmin",
45
+ max_length=10,
46
+ verbose_name="Locale created",
47
+ ),
48
+ ),
49
+ migrations.AlterField(
50
+ model_name="healthfacility",
51
+ name="locale_modified",
52
+ field=models.CharField(
53
+ blank=True,
54
+ default="",
55
+ help_text="Auto-updated by Modeladmin",
56
+ max_length=10,
57
+ verbose_name="Locale modified",
58
+ ),
59
+ ),
60
+ migrations.AlterField(
61
+ model_name="healthfacility",
62
+ name="notes",
63
+ field=models.TextField(blank=True, default=""),
64
+ ),
65
+ migrations.AlterField(
66
+ model_name="healthfacilitytypes",
67
+ name="extra_value",
68
+ field=models.CharField(default="", max_length=250),
69
+ ),
70
+ migrations.AlterField(
71
+ model_name="healthfacilitytypes",
72
+ name="field_name",
73
+ field=models.CharField(
74
+ blank=True,
75
+ default="",
76
+ editable=False,
77
+ help_text="Not required",
78
+ max_length=25,
79
+ ),
80
+ ),
81
+ migrations.AlterField(
82
+ model_name="healthfacilitytypes",
83
+ name="plural_name",
84
+ field=models.CharField(
85
+ default="", max_length=250, verbose_name="Plural name"
86
+ ),
87
+ ),
88
+ migrations.AlterField(
89
+ model_name="historicalhealthfacility",
90
+ name="device_created",
91
+ field=models.CharField(
92
+ blank=True, default="", max_length=10, verbose_name="Device created"
93
+ ),
94
+ ),
95
+ migrations.AlterField(
96
+ model_name="historicalhealthfacility",
97
+ name="device_modified",
98
+ field=models.CharField(
99
+ blank=True, default="", max_length=10, verbose_name="Device modified"
100
+ ),
101
+ ),
102
+ migrations.AlterField(
103
+ model_name="historicalhealthfacility",
104
+ name="health_facility_type_other",
105
+ field=edc_model_fields.fields.other_charfield.OtherCharField(
106
+ blank=True,
107
+ default="",
108
+ max_length=35,
109
+ verbose_name="If other, please specify ...",
110
+ ),
111
+ ),
112
+ migrations.AlterField(
113
+ model_name="historicalhealthfacility",
114
+ name="locale_created",
115
+ field=models.CharField(
116
+ blank=True,
117
+ default="",
118
+ help_text="Auto-updated by Modeladmin",
119
+ max_length=10,
120
+ verbose_name="Locale created",
121
+ ),
122
+ ),
123
+ migrations.AlterField(
124
+ model_name="historicalhealthfacility",
125
+ name="locale_modified",
126
+ field=models.CharField(
127
+ blank=True,
128
+ default="",
129
+ help_text="Auto-updated by Modeladmin",
130
+ max_length=10,
131
+ verbose_name="Locale modified",
132
+ ),
133
+ ),
134
+ migrations.AlterField(
135
+ model_name="historicalhealthfacility",
136
+ name="notes",
137
+ field=models.TextField(blank=True, default=""),
138
+ ),
139
+ ]
@@ -0,0 +1,54 @@
1
+ # Generated by Django 5.2.6 on 2025-09-18 00:24
2
+
3
+ import django.utils.timezone
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ("edc_facility", "0016_alter_healthfacility_device_created_and_more"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AlterField(
15
+ model_name="healthfacility",
16
+ name="gps",
17
+ field=models.CharField(
18
+ blank=True,
19
+ default="",
20
+ help_text="copy and paste directly from google maps",
21
+ max_length=50,
22
+ ),
23
+ ),
24
+ migrations.AlterField(
25
+ model_name="healthfacility",
26
+ name="report_datetime",
27
+ field=models.DateTimeField(default=django.utils.timezone.now),
28
+ ),
29
+ migrations.AlterField(
30
+ model_name="healthfacility",
31
+ name="title",
32
+ field=models.CharField(blank=True, default="", max_length=150),
33
+ ),
34
+ migrations.AlterField(
35
+ model_name="historicalhealthfacility",
36
+ name="gps",
37
+ field=models.CharField(
38
+ blank=True,
39
+ default="",
40
+ help_text="copy and paste directly from google maps",
41
+ max_length=50,
42
+ ),
43
+ ),
44
+ migrations.AlterField(
45
+ model_name="historicalhealthfacility",
46
+ name="report_datetime",
47
+ field=models.DateTimeField(default=django.utils.timezone.now),
48
+ ),
49
+ migrations.AlterField(
50
+ model_name="historicalhealthfacility",
51
+ name="title",
52
+ field=models.CharField(blank=True, default="", max_length=150),
53
+ ),
54
+ ]
@@ -2,10 +2,10 @@ import calendar
2
2
 
3
3
  from django.core.validators import MaxValueValidator, MinValueValidator
4
4
  from django.db import models
5
+ from django.utils import timezone
5
6
 
6
7
  from edc_model.models import BaseUuidModel
7
8
  from edc_model_fields.fields import OtherCharField
8
- from edc_utils import get_utcnow
9
9
 
10
10
 
11
11
  class HealthFacilityCalendarError(Exception):
@@ -28,11 +28,11 @@ class HealthFacilityModelMixin(models.Model):
28
28
  See also edc_appointment.
29
29
  """
30
30
 
31
- report_datetime = models.DateTimeField(default=get_utcnow)
31
+ report_datetime = models.DateTimeField(default=timezone.now)
32
32
 
33
33
  name = models.CharField(max_length=25, unique=True)
34
34
 
35
- title = models.CharField(max_length=150, null=True, blank=True)
35
+ title = models.CharField(max_length=150, default="", blank=True)
36
36
 
37
37
  health_facility_type = models.ForeignKey(
38
38
  "edc_facility.HealthFacilityTypes",
@@ -45,7 +45,7 @@ class HealthFacilityModelMixin(models.Model):
45
45
 
46
46
  gps = models.CharField(
47
47
  max_length=50,
48
- null=True,
48
+ default="",
49
49
  blank=True,
50
50
  help_text="copy and paste directly from google maps",
51
51
  )
@@ -115,7 +115,7 @@ class HealthFacilityModelMixin(models.Model):
115
115
  days = []
116
116
  mapping = {k: v for k, v in enumerate(calendar.weekheader(3).split(" "))}
117
117
  for day_int in self.clinic_days:
118
- days.append(mapping.get(day_int))
118
+ days.append(mapping.get(day_int)) # noqa: PERF401
119
119
  return ",".join(days)
120
120
 
121
121
  class Meta(BaseUuidModel.Meta):
@@ -8,10 +8,9 @@ from bs4 import BeautifulSoup
8
8
  from django.apps import apps as django_apps
9
9
  from django.db.models import ForeignKey, ManyToManyField, Model, OneToOneField, QuerySet
10
10
  from django.forms import ModelForm
11
+ from django.utils import timezone
11
12
  from tqdm import tqdm
12
13
 
13
- from edc_utils import get_utcnow
14
-
15
14
  from .exceptions import FormRunnerModelAdminNotFound, FormRunnerModelFormNotFound
16
15
  from .utils import get_modeladmin_cls
17
16
 
@@ -37,7 +36,7 @@ class FormRunner:
37
36
  ) -> None:
38
37
  self.messages = {}
39
38
  self.session_id = uuid.uuid4()
40
- self.session_datetime = get_utcnow()
39
+ self.session_datetime = timezone.now()
41
40
  self.verbose = verbose
42
41
  self.model_name = self.model_name or model_name
43
42
  self.modeladmin_cls = get_modeladmin_cls(self.model_name)
@@ -48,8 +47,7 @@ class FormRunner:
48
47
  )
49
48
  if self.modeladmin_cls.form == ModelForm:
50
49
  raise FormRunnerModelFormNotFound(
51
- "ModelAdmin does not have a custom form. Nothing to do. "
52
- f"Got `{model_name}`."
50
+ f"ModelAdmin does not have a custom form. Nothing to do. Got `{model_name}`."
53
51
  )
54
52
  self.src_model_cls = self.modeladmin_cls.model
55
53