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
@@ -0,0 +1,31 @@
1
+ # Generated by Django 5.2.6 on 2025-09-18 00:24
2
+
3
+ import django.utils.timezone
4
+ import edc_model.validators.date
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ("edc_lab", "0036_alter_aliquot_comment_alter_aliquot_device_created_and_more"),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.AlterField(
16
+ model_name="historicalorder",
17
+ name="order_datetime",
18
+ field=models.DateTimeField(
19
+ default=django.utils.timezone.now,
20
+ validators=[edc_model.validators.date.datetime_not_future],
21
+ ),
22
+ ),
23
+ migrations.AlterField(
24
+ model_name="order",
25
+ name="order_datetime",
26
+ field=models.DateTimeField(
27
+ default=django.utils.timezone.now,
28
+ validators=[edc_model.validators.date.datetime_not_future],
29
+ ),
30
+ ),
31
+ ]
@@ -11,9 +11,9 @@ class AliquotIdentifierModelMixin(models.Model):
11
11
 
12
12
  identifier_prefix = models.CharField(max_length=50, editable=False)
13
13
 
14
- subject_identifier = models.CharField(max_length=50, null=True, editable=False)
14
+ subject_identifier = models.CharField(max_length=50, default="", editable=False)
15
15
 
16
- requisition_identifier = models.CharField(max_length=50, null=True, editable=False)
16
+ requisition_identifier = models.CharField(max_length=50, default="", editable=False)
17
17
 
18
18
  class Meta:
19
19
  abstract = True
@@ -46,7 +46,7 @@ class AliquotModelMixin(SiteModelMixin, models.Model):
46
46
 
47
47
  condition = models.CharField(max_length=25, choices=ALIQUOT_CONDITIONS, default="10")
48
48
 
49
- comment = models.CharField(max_length=50, null=True, blank=True)
49
+ comment = models.CharField(max_length=50, blank=True, default="")
50
50
 
51
51
  def __str__(self: Any):
52
52
  return self.aliquot_identifier
@@ -54,7 +54,7 @@ class AliquotModelMixin(SiteModelMixin, models.Model):
54
54
  def natural_key(self: Any):
55
55
  return (self.aliquot_identifier,)
56
56
 
57
- natural_key.dependencies = ["sites.Site"]
57
+ natural_key.dependencies = ("sites.Site",)
58
58
 
59
59
  class Meta:
60
60
  abstract = True
@@ -3,6 +3,17 @@ from django.db.models.deletion import PROTECT
3
3
 
4
4
  from ..site_labs import site_labs
5
5
 
6
+ UNDEFINED_PANEL_OR_GROUP_NAME = (
7
+ "Undefined `panel` name or `panel group` name. "
8
+ "Got {panel_name}. See LabProfile and model Panel. Got {err}"
9
+ )
10
+ UNDEFINED_LAP_PROFILE_NAME = (
11
+ "Undefined lab profile name detected from panel {panel}. "
12
+ "Expected one of {lab_profiles}. "
13
+ "Got '{lab_profile_name}'. "
14
+ "See stored values in panel model."
15
+ )
16
+
6
17
 
7
18
  class PanelModelError(Exception):
8
19
  pass
@@ -32,9 +43,8 @@ class PanelModelMixin(models.Model):
32
43
  panel_object = self.lab_profile_object.panels[panel_name]
33
44
  except KeyError as e:
34
45
  raise PanelModelError(
35
- "Undefined `panel` name or `panel group` name. "
36
- f"Got {panel_name}. See LabProfile and model Panel. Got {e}"
37
- )
46
+ UNDEFINED_PANEL_OR_GROUP_NAME.format(panel_name=panel_name, err=str(e))
47
+ ) from e
38
48
  return panel_object
39
49
 
40
50
  @property
@@ -42,10 +52,11 @@ class PanelModelMixin(models.Model):
42
52
  lab_profile_object = site_labs.get(self.panel.lab_profile_name)
43
53
  if not lab_profile_object:
44
54
  raise LabProfileError(
45
- f"Undefined lab profile name detected from panel {self.panel}. "
46
- f"Expected one of {site_labs.lab_profiles}. "
47
- f"Got '{self.panel.lab_profile_name}'. "
48
- "See stored values in panel model."
55
+ UNDEFINED_LAP_PROFILE_NAME.format(
56
+ panel_name=self.panel,
57
+ lab_profiles=site_labs.lab_profiles,
58
+ lab_profile_name=self.panel.lab_profile_name,
59
+ )
49
60
  )
50
61
  return lab_profile_object
51
62
 
@@ -23,16 +23,14 @@ class CrfWithRequisitionModelMixin(models.Model):
23
23
  For example:
24
24
  from edc_lab.model_mixins import (
25
25
  CrfWithRequisitionModelMixin,
26
- requisition_fk_options,
27
- )
26
+ requisition_fk_options)
28
27
 
29
28
  class MyRequisition(CrfWithRequisitionModelMixin, etc):
30
29
  ...
31
30
  lab_panel = fbc_panel
32
31
  requisition = models.ForeignKey(
33
32
  limit_choices_to={"panel__name": fbc_panel.name},
34
- **requisition_fk_options,
35
- )
33
+ **requisition_fk_options)
36
34
  ...
37
35
  """
38
36
 
@@ -72,12 +72,12 @@ class RequisitionModelMixin(
72
72
 
73
73
  reason_not_drawn_other = OtherCharField()
74
74
 
75
- protocol_number = models.CharField(max_length=10, null=True, editable=False)
75
+ protocol_number = models.CharField(max_length=10, default="", editable=False)
76
76
 
77
- clinician_initials = InitialsField(null=True, blank=True)
77
+ clinician_initials = InitialsField(default="", blank=True)
78
78
 
79
79
  specimen_type = models.CharField(
80
- verbose_name="Specimen type", max_length=25, null=True, blank=True
80
+ verbose_name="Specimen type", max_length=25, default="", blank=True
81
81
  )
82
82
 
83
83
  item_type = models.CharField(
@@ -132,7 +132,7 @@ class RequisitionModelMixin(
132
132
  def natural_key(self):
133
133
  return (self.requisition_identifier,)
134
134
 
135
- natural_key.dependencies = [settings.SUBJECT_VISIT_MODEL, "sites.Site"]
135
+ natural_key.dependencies = (settings.SUBJECT_VISIT_MODEL, "sites.Site")
136
136
 
137
137
  def get_search_slug_fields(self):
138
138
  fields = super().get_search_slug_fields()
@@ -148,13 +148,12 @@ class RequisitionModelMixin(
148
148
 
149
149
  class Meta(NonUniqueSubjectIdentifierFieldMixin.Meta):
150
150
  abstract = True
151
- constraints = [
151
+ constraints = (
152
152
  UniqueConstraint(
153
153
  fields=["panel", "subject_visit"],
154
154
  name="%(app_label)s_%(class)s_panel_uniq",
155
- )
156
- ]
157
-
155
+ ),
156
+ )
158
157
  indexes = (
159
158
  *NonUniqueSubjectIdentifierFieldMixin.Meta.indexes,
160
159
  models.Index(fields=["subject_visit", "site", "panel"]),
@@ -4,7 +4,7 @@ from edc_constants.choices import YES_NO
4
4
 
5
5
 
6
6
  class RequisitionVerifyModelMixin(models.Model):
7
- clinic_verified = models.CharField(max_length=15, choices=YES_NO, null=True)
7
+ clinic_verified = models.CharField(max_length=15, choices=YES_NO, default="")
8
8
 
9
9
  clinic_verified_datetime = models.DateTimeField(null=True)
10
10
 
@@ -7,15 +7,15 @@ from edc_sites.model_mixins import SiteModelMixin
7
7
  class ResultItemModelMixin(SiteModelMixin, models.Model):
8
8
  report_datetime = models.DateTimeField(null=True)
9
9
 
10
- utestid = models.CharField(max_length=25, null=True)
10
+ utestid = models.CharField(max_length=25, default="")
11
11
 
12
- value = models.CharField(max_length=25, null=True)
12
+ value = models.CharField(max_length=25, default="")
13
13
 
14
- quantifier = models.CharField(max_length=25, null=True)
14
+ quantifier = models.CharField(max_length=25, default="")
15
15
 
16
16
  value_datetime = models.DateTimeField(null=True)
17
17
 
18
- reference = models.CharField(max_length=25, null=True)
18
+ reference = models.CharField(max_length=25, default="")
19
19
 
20
20
  pending_datetime = models.DateTimeField(default=timezone.now)
21
21
 
@@ -3,7 +3,6 @@ from django.utils import timezone
3
3
 
4
4
  from edc_constants.constants import CLOSED, OPEN, OTHER
5
5
  from edc_sites.model_mixins import SiteModelMixin
6
- from edc_utils import get_utcnow
7
6
 
8
7
  from ...constants import STORAGE, TESTING
9
8
  from ...identifiers import ManifestIdentifier
@@ -20,7 +19,7 @@ class ManifestModelMixin(SiteModelMixin, models.Model):
20
19
 
21
20
  manifest_datetime = models.DateTimeField(default=timezone.now)
22
21
 
23
- export_datetime = models.DateTimeField(blank=True)
22
+ export_datetime = models.DateTimeField(blank=True, null=True)
24
23
 
25
24
  export_references = models.TextField(blank=True, default="")
26
25
 
@@ -34,7 +33,7 @@ class ManifestModelMixin(SiteModelMixin, models.Model):
34
33
 
35
34
  category = models.CharField(max_length=25, default=TESTING, choices=MANIFEST_CATEGORY)
36
35
 
37
- category_other = models.CharField(max_length=25, null=True, blank=True)
36
+ category_other = models.CharField(max_length=25, default="", blank=True)
38
37
 
39
38
  comment = models.TextField(verbose_name="Comment", blank=True, default="")
40
39
 
@@ -49,7 +48,7 @@ class ManifestModelMixin(SiteModelMixin, models.Model):
49
48
  identifier = ManifestIdentifier()
50
49
  self.manifest_identifier = identifier.identifier
51
50
  if self.shipped and not self.export_datetime:
52
- self.export_datetime = get_utcnow()
51
+ self.export_datetime = timezone.now()
53
52
  elif not self.shipped:
54
53
  self.export_datetime = None
55
54
  self.printed = False
@@ -58,7 +57,7 @@ class ManifestModelMixin(SiteModelMixin, models.Model):
58
57
  def natural_key(self):
59
58
  return (self.manifest_identifier,)
60
59
 
61
- natural_key.dependencies = ["sites.Site"]
60
+ natural_key.dependencies = ("sites.Site",)
62
61
 
63
62
  @property
64
63
  def human_readable_identifier(self):
@@ -1,7 +1,7 @@
1
1
  from django.db import models
2
+ from django.utils import timezone
2
3
 
3
4
  from edc_constants.constants import OPEN
4
- from edc_utils import get_utcnow
5
5
 
6
6
  from ...constants import VERIFIED
7
7
 
@@ -27,7 +27,7 @@ class VerifyBoxModelMixin(VerifyModelMixin, models.Model):
27
27
  if self.is_verified:
28
28
  self.verified = 1
29
29
  self.status = VERIFIED
30
- self.verified_datetime = get_utcnow()
30
+ self.verified_datetime = timezone.now()
31
31
  else:
32
32
  self.verified = 0
33
33
  self.verified_datetime = None
@@ -41,12 +41,10 @@ class VerifyBoxModelMixin(VerifyModelMixin, models.Model):
41
41
 
42
42
  @property
43
43
  def is_verified(self):
44
- if (
44
+ return not (
45
45
  self.boxitem_set.all().count() == 0
46
46
  or self.boxitem_set.filter(verified=False).exists()
47
- ):
48
- return False
49
- return True
47
+ )
50
48
 
51
49
  class Meta:
52
50
  abstract = True
edc_lab/models/box.py CHANGED
@@ -39,7 +39,7 @@ class BoxManager(SearchSlugManager, models.Manager):
39
39
 
40
40
 
41
41
  class Box(SearchSlugModelMixin, VerifyBoxModelMixin, SiteModelMixin, BaseUuidModel):
42
- search_slug_fields = ["box_identifier", "human_readable_identifier", "name"]
42
+ search_slug_fields = ("box_identifier", "human_readable_identifier", "name")
43
43
 
44
44
  box_identifier = models.CharField(max_length=25, editable=False, unique=True)
45
45
 
@@ -28,16 +28,16 @@ class BoxItem(SearchSlugModelMixin, VerifyModelMixin, BaseUuidModel):
28
28
 
29
29
  identifier = models.CharField(max_length=25)
30
30
 
31
- comment = models.CharField(max_length=25, null=True, blank=True)
31
+ comment = models.CharField(max_length=25, default="", blank=True)
32
32
 
33
33
  objects = BoxItemManager()
34
34
 
35
35
  history = HistoricalRecords()
36
36
 
37
37
  def natural_key(self):
38
- return (self.position, self.identifier) + self.box.natural_key()
38
+ return self.position, self.identifier, *self.box.natural_key()
39
39
 
40
- natural_key.dependencies = ["edc_lab.box", "edc_lab.boxtype", "sites.Site"]
40
+ natural_key.dependencies = ("edc_lab.box", "edc_lab.boxtype", "sites.Site")
41
41
 
42
42
  @property
43
43
  def human_readable_identifier(self):
@@ -49,12 +49,11 @@ class BoxItem(SearchSlugModelMixin, VerifyModelMixin, BaseUuidModel):
49
49
  return self.identifier
50
50
 
51
51
  def get_slugs(self):
52
- slugs = [self.identifier, self.human_readable_identifier]
53
- return slugs
52
+ return self.identifier, self.human_readable_identifier
54
53
 
55
54
  class Meta(BaseUuidModel.Meta):
56
55
  verbose_name = "Box Item"
57
- constraints = [
56
+ constraints = (
58
57
  UniqueConstraint(
59
58
  fields=["box", "position"], name="%(app_label)s_%(class)s_box_pos_uniq"
60
59
  ),
@@ -62,4 +61,4 @@ class BoxItem(SearchSlugModelMixin, VerifyModelMixin, BaseUuidModel):
62
61
  fields=["box", "identifier"],
63
62
  name="%(app_label)s_%(class)s_box_ide_uniq",
64
63
  ),
65
- ]
64
+ )
@@ -41,7 +41,7 @@ class Manifest(ManifestModelMixin, PdfReportModelMixin, SearchSlugModelMixin, Ba
41
41
  def natural_key(self):
42
42
  return (self.manifest_identifier,)
43
43
 
44
- natural_key.dependencies = ["edc_lab.shipper", "edc_lab.consignee"]
44
+ natural_key.dependencies = ("edc_lab.shipper", "edc_lab.consignee")
45
45
 
46
46
  def __str__(self):
47
47
  return "{} created on {} by {}".format(
@@ -23,14 +23,14 @@ class ManifestItem(SiteModelMixin, SearchSlugModelMixin, VerifyModelMixin, BaseU
23
23
 
24
24
  identifier = models.CharField(max_length=25)
25
25
 
26
- comment = models.CharField(max_length=25, null=True, blank=True)
26
+ comment = models.CharField(max_length=25, default="", blank=True)
27
27
 
28
28
  objects = ManifestItemManager()
29
29
 
30
30
  def natural_key(self):
31
- return (self.identifier,) + self.manifest.natural_key()
31
+ return self.identifier, *self.manifest.natural_key()
32
32
 
33
- natural_key.dependencies = ["edc_lab.manifest", "sites.Site"]
33
+ natural_key.dependencies = ("edc_lab.manifest", "sites.Site")
34
34
 
35
35
  @property
36
36
  def human_readable_identifier(self):
@@ -39,9 +39,9 @@ class ManifestItem(SiteModelMixin, SearchSlugModelMixin, VerifyModelMixin, BaseU
39
39
 
40
40
  class Meta(BaseUuidModel.Meta):
41
41
  verbose_name = "Manifest Item"
42
- constraints = [
42
+ constraints = (
43
43
  UniqueConstraint(
44
44
  fields=["manifest", "identifier"],
45
45
  name="%(app_label)s_%(class)s_manifest_uniq",
46
- )
47
- ]
46
+ ),
47
+ )
@@ -1,7 +1,6 @@
1
1
  from django.db import models
2
2
 
3
- from edc_model import models as edc_models
4
- from edc_model.models import BaseUuidModel
3
+ from edc_model.models import AddressMixin, BaseUuidModel, HistoricalRecords
5
4
 
6
5
 
7
6
  class ShipperManager(models.Manager):
@@ -9,12 +8,12 @@ class ShipperManager(models.Manager):
9
8
  return self.get(name=name)
10
9
 
11
10
 
12
- class Shipper(edc_models.AddressMixin, BaseUuidModel):
11
+ class Shipper(AddressMixin, BaseUuidModel):
13
12
  name = models.CharField(unique=True, max_length=50)
14
13
 
15
14
  objects = ShipperManager()
16
15
 
17
- history = edc_models.HistoricalRecords()
16
+ history = HistoricalRecords()
18
17
 
19
18
  def natural_key(self):
20
19
  return (self.name,)
edc_lab/models/order.py CHANGED
@@ -1,11 +1,11 @@
1
1
  from django.db import models
2
2
  from django.db.models.deletion import PROTECT
3
+ from django.utils import timezone
3
4
 
4
5
  from edc_model.models import BaseUuidModel, HistoricalRecords
5
6
  from edc_model.validators import datetime_not_future
6
7
  from edc_sites.managers import CurrentSiteManager
7
8
  from edc_sites.model_mixins import SiteModelMixin
8
- from edc_utils import get_utcnow
9
9
 
10
10
  from .aliquot import Aliquot
11
11
 
@@ -25,7 +25,9 @@ class Order(SiteModelMixin, BaseUuidModel):
25
25
 
26
26
  order_identifier = models.CharField(max_length=25, editable=False, unique=True)
27
27
 
28
- order_datetime = models.DateTimeField(default=get_utcnow, validators=[datetime_not_future])
28
+ order_datetime = models.DateTimeField(
29
+ default=timezone.now, validators=[datetime_not_future]
30
+ )
29
31
 
30
32
  panel_name = models.CharField(max_length=25)
31
33
 
@@ -36,9 +38,9 @@ class Order(SiteModelMixin, BaseUuidModel):
36
38
  history = HistoricalRecords()
37
39
 
38
40
  def natural_key(self):
39
- return (self.report_datetime,) + self.aliquot.natural_key()
41
+ return self.report_datetime, *self.aliquot.natural_key()
40
42
 
41
- natural_key.dependencies = ["edc_lab.aliquot", "sites.Site"]
43
+ natural_key.dependencies = ("edc_lab.aliquot", "sites.Site")
42
44
 
43
45
  class Meta(BaseUuidModel.Meta):
44
46
  verbose_name = "Order"
edc_lab/models/panel.py CHANGED
@@ -24,14 +24,14 @@ class Panel(BaseUuidModel):
24
24
  return self.display_name or self.name
25
25
 
26
26
  def natural_key(self):
27
- return (self.name, self.lab_profile_name)
27
+ return self.name, self.lab_profile_name
28
28
 
29
29
  class Meta(BaseUuidModel.Meta):
30
30
  verbose_name = "Panel"
31
31
  verbose_name_plural = "Panels"
32
- constraints = [
32
+ constraints = (
33
33
  UniqueConstraint(
34
34
  fields=["name", "lab_profile_name"],
35
35
  name="%(app_label)s_%(class)s_name_uniq",
36
- )
37
- ]
36
+ ),
37
+ )
edc_lab/models/result.py CHANGED
@@ -27,9 +27,9 @@ class Result(ResultModelMixin, BaseUuidModel):
27
27
  history = HistoricalRecords()
28
28
 
29
29
  def natural_key(self):
30
- return (self.report_datetime, self.order.order_identifier)
30
+ return self.report_datetime, self.order.order_identifier
31
31
 
32
- natural_key.dependencies = ["edc_lab.order", "edc_lab.panel", "sites.Site"]
32
+ natural_key.dependencies = ("edc_lab.order", "edc_lab.panel", "sites.Site")
33
33
 
34
34
  class Meta(BaseUuidModel.Meta):
35
35
  verbose_name = "Result"
@@ -28,9 +28,9 @@ class ResultItem(ResultItemModelMixin, BaseUuidModel):
28
28
  history = HistoricalRecords()
29
29
 
30
30
  def natural_key(self):
31
- return (self.report_datetime,) + self.result.natural_key()
31
+ return self.report_datetime, *self.result.natural_key()
32
32
 
33
- natural_key.dependencies = ["edc_lab.result", "sites.Site"]
33
+ natural_key.dependencies = ("edc_lab.result", "sites.Site")
34
34
 
35
35
  class Meta(BaseUuidModel.Meta):
36
36
  verbose_name = "Result Item"
@@ -7,6 +7,7 @@ import django_audit_fields.fields.uuid_auto_field
7
7
  import django_audit_fields.models.audit_model_mixin
8
8
  import django_revision.revision_field
9
9
  from django.db import migrations, models
10
+ import django.utils.timezone
10
11
 
11
12
 
12
13
  class Migration(migrations.Migration):
@@ -33,14 +34,14 @@ class Migration(migrations.Migration):
33
34
  "created",
34
35
  models.DateTimeField(
35
36
  blank=True,
36
- default=django_audit_fields.models.audit_model_mixin.utcnow,
37
+ default=django.utils.timezone.now,
37
38
  ),
38
39
  ),
39
40
  (
40
41
  "modified",
41
42
  models.DateTimeField(
42
43
  blank=True,
43
- default=django_audit_fields.models.audit_model_mixin.utcnow,
44
+ default=django.utils.timezone.now,
44
45
  ),
45
46
  ),
46
47
  (
@@ -0,0 +1,49 @@
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_lab_dashboard", "0004_alter_edcpermissions_revision"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name="edcpermissions",
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="edcpermissions",
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="edcpermissions",
29
+ name="locale_created",
30
+ field=models.CharField(
31
+ blank=True,
32
+ default="",
33
+ help_text="Auto-updated by Modeladmin",
34
+ max_length=10,
35
+ verbose_name="Locale created",
36
+ ),
37
+ ),
38
+ migrations.AlterField(
39
+ model_name="edcpermissions",
40
+ name="locale_modified",
41
+ field=models.CharField(
42
+ blank=True,
43
+ default="",
44
+ help_text="Auto-updated by Modeladmin",
45
+ max_length=10,
46
+ verbose_name="Locale modified",
47
+ ),
48
+ ),
49
+ ]
@@ -1,12 +1,12 @@
1
1
  from django.apps import apps as django_apps
2
2
  from django.contrib import messages
3
+ from django.utils import timezone
3
4
 
4
5
  from edc_constants.constants import YES
5
6
  from edc_dashboard.view_mixins import EdcViewMixin
6
7
  from edc_lab import Specimen
7
8
  from edc_lab.labels import AliquotLabel
8
9
  from edc_lab.site_labs import site_labs
9
- from edc_utils import get_utcnow
10
10
 
11
11
  from ...view_mixins import ProcessRequisitionViewMixin
12
12
  from .action_view import ActionView
@@ -38,7 +38,7 @@ class ReceiveView(EdcViewMixin, ProcessRequisitionViewMixin, ActionView):
38
38
  updated += (
39
39
  model_cls.objects.filter(pk__in=self.selected_items, is_drawn=YES)
40
40
  .exclude(received=True)
41
- .update(received=True, received_datetime=get_utcnow())
41
+ .update(received=True, received_datetime=timezone.now())
42
42
  )
43
43
  if updated:
44
44
  message = f"{updated} requisitions received."
@@ -1,8 +1,8 @@
1
1
  from django.contrib import messages
2
+ from django.utils import timezone
2
3
 
3
4
  from edc_dashboard.view_mixins import EdcViewMixin
4
5
  from edc_lab import SHIPPED
5
- from edc_utils import get_utcnow
6
6
 
7
7
  from ...view_mixins import BoxViewMixin
8
8
  from .action_view import ActionView
@@ -48,7 +48,7 @@ class VerifyBoxItemView(EdcViewMixin, BoxViewMixin, ActionView):
48
48
  if self.box_item:
49
49
  if self.box_item == box_item_in_position:
50
50
  box_item_in_position.verified = 1
51
- box_item_in_position.verified_datetime = get_utcnow()
51
+ box_item_in_position.verified_datetime = timezone.now()
52
52
  self.next_position()
53
53
  self.redirect_querystring.pop("alert")
54
54
  else:
@@ -16,12 +16,12 @@ class BloodResultsFieldsModelMixin(models.Model):
16
16
  choices=YES_NO,
17
17
  max_length=25,
18
18
  help_text=(
19
- "Abnormal results present at baseline or continuing from " "baseline not included."
19
+ "Abnormal results present at baseline or continuing from baseline not included."
20
20
  ),
21
21
  )
22
22
 
23
23
  results_reportable = models.CharField(
24
- verbose_name=("If any results are abnormal, are results within grade 3 or above?"),
24
+ verbose_name="If any results are abnormal, are results within grade 3 or above?",
25
25
  max_length=25,
26
26
  choices=YES_NO_NA,
27
27
  help_text=(
@@ -30,13 +30,13 @@ class BloodResultsFieldsModelMixin(models.Model):
30
30
  ),
31
31
  )
32
32
 
33
- summary = models.TextField(null=True, blank=True)
33
+ summary = models.TextField(default="", blank=True)
34
34
 
35
- reportable_summary = models.TextField(null=True, blank=True)
35
+ reportable_summary = models.TextField(default="", blank=True)
36
36
 
37
- abnormal_summary = models.TextField(null=True, blank=True)
37
+ abnormal_summary = models.TextField(default="", blank=True)
38
38
 
39
- errors = models.TextField(null=True, blank=True)
39
+ errors = models.TextField(default="", blank=True)
40
40
 
41
41
  missing_count = models.IntegerField(
42
42
  default=0,
@@ -45,7 +45,7 @@ class BloodResultsFieldsModelMixin(models.Model):
45
45
  )
46
46
 
47
47
  missing = models.TextField(
48
- null=True,
48
+ default="",
49
49
  editable=False,
50
50
  help_text="calculated string of field names that have been left blank",
51
51
  )