clinicedc 2.0.6__py3-none-any.whl → 2.0.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of clinicedc might be problematic. Click here for more details.

Files changed (495) hide show
  1. {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/METADATA +2 -2
  2. {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/RECORD +489 -441
  3. {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/WHEEL +1 -1
  4. edc_action_item/action.py +1 -1
  5. edc_action_item/action_item_notification.py +2 -2
  6. edc_action_item/auths.py +37 -32
  7. edc_action_item/create_action_item.py +1 -1
  8. edc_action_item/decorators.py +1 -1
  9. edc_action_item/migrations/0001_initial.py +21 -22
  10. edc_action_item/migrations/0006_auto_20180707_1659.py +4 -4
  11. edc_action_item/migrations/0008_auto_20180809_0303.py +4 -4
  12. edc_action_item/migrations/0015_auto_20190114_0250.py +4 -4
  13. edc_action_item/migrations/0017_auto_20190305_0123.py +11 -30
  14. edc_action_item/migrations/0030_edcpermissions.py +3 -2
  15. edc_action_item/migrations/0039_alter_actionitem_auto_created_comment_and_more.py +398 -0
  16. edc_action_item/migrations/0040_alter_actionitem_report_datetime_and_more.py +34 -0
  17. edc_action_item/models/action_item.py +9 -4
  18. edc_action_item/models/action_model_mixin.py +5 -6
  19. edc_action_item/models/reference.py +2 -2
  20. edc_action_item/models/signals.py +22 -23
  21. edc_action_item/post_migrate_signals.py +1 -1
  22. edc_action_item/send_email.py +0 -85
  23. edc_action_item/site_action_items.py +5 -9
  24. edc_action_item/utils.py +3 -3
  25. edc_adherence/migrations/0005_alter_nonadherencereasons_extra_value_and_more.py +36 -0
  26. edc_adherence/model_mixins.py +1 -1
  27. edc_adverse_event/auths.py +55 -51
  28. edc_adverse_event/migrations/0001_initial.py +5 -4
  29. edc_adverse_event/migrations/0002_auto_20190802_0059.py +3 -2
  30. edc_adverse_event/migrations/0008_auto_20220825_0451.py +3 -2
  31. edc_adverse_event/migrations/0009_auto_20220907_0157.py +3 -2
  32. edc_adverse_event/migrations/0016_alter_aeactionclassification_device_created_and_more.py +285 -0
  33. edc_adverse_event/model_mixins/ae_followup/ae_followup_fields_model_mixin.py +2 -2
  34. edc_adverse_event/model_mixins/ae_initial/ae_initial_fields_model_mixin.py +6 -5
  35. edc_adverse_event/model_mixins/ae_special_interest/aesi_fields_model_mixin.py +2 -2
  36. edc_adverse_event/model_mixins/ae_susar/ae_susar_fields_model_mixin.py +2 -2
  37. edc_adverse_event/model_mixins/ae_tmg/ae_tmg_fields_model_mixin.py +15 -11
  38. edc_adverse_event/model_mixins/ae_tmg/ae_tmg_methods_model_mixin.py +2 -4
  39. edc_adverse_event/model_mixins/death_report/death_report_model_mixin.py +5 -4
  40. edc_adverse_event/model_mixins/death_report/death_report_tmg_model_mixin.py +6 -3
  41. edc_adverse_event/model_mixins/death_report/simple_death_report_model_mixin.py +2 -2
  42. edc_adverse_event/model_mixins/hospitaization/hospitalization_model_mixin.py +4 -3
  43. edc_adverse_event/modeladmin_mixins/death_report_admin_mixin.py +3 -3
  44. edc_adverse_event/models/signals.py +7 -7
  45. edc_adverse_event/templatetags/edc_adverse_event_extras.py +5 -4
  46. edc_adverse_event/view_mixins/ae/ae_listboard_view_mixin.py +3 -5
  47. edc_adverse_event/view_mixins/ae/death_report_listboard_view_mixin.py +6 -8
  48. edc_adverse_event/view_mixins/tmg/tmg_ae_listboard_view_mixin.py +2 -2
  49. edc_adverse_event/views/tmg/summary_listboard_view.py +3 -2
  50. edc_appointment/admin/appointment_admin.py +2 -2
  51. edc_appointment/admin/list_filters.py +2 -2
  52. edc_appointment/auths.py +14 -10
  53. edc_appointment/creators/appointment_creator.py +1 -1
  54. edc_appointment/creators/appointments_creator.py +1 -1
  55. edc_appointment/form_validators/appointment_form_validator.py +108 -82
  56. edc_appointment/migrations/0003_auto_20161127_2226.py +5 -6
  57. edc_appointment/migrations/0006_auto_20170106_2118.py +5 -5
  58. edc_appointment/migrations/0018_auto_20190305_0123.py +5 -12
  59. edc_appointment/migrations/0050_alter_appointment_appt_type_and_more.py +220 -0
  60. edc_appointment/model_mixins/appointment_fields_model_mixin.py +1 -2
  61. edc_appointment/model_mixins/appointment_methods_model_mixin.py +2 -3
  62. edc_appointment/model_mixins/appointment_model_mixin.py +31 -28
  63. edc_appointment/model_mixins/window_period_model_mixin.py +6 -7
  64. edc_appointment/models/appointment.py +1 -1
  65. edc_appointment/models/signals.py +44 -35
  66. edc_appointment/utils.py +19 -24
  67. edc_appointment/view_utils/appointment_button.py +2 -2
  68. edc_auth/admin/user_admin.py +1 -1
  69. edc_auth/auth_objects/__init__.py +2 -20
  70. edc_auth/auth_objects/default_groups.py +13 -11
  71. edc_auth/auth_objects/default_roles.py +26 -24
  72. edc_auth/auth_updater/auth_updater.py +13 -2
  73. edc_auth/auth_updater/group_updater.py +12 -10
  74. edc_auth/auth_updater/role_updater.py +2 -2
  75. edc_auth/constants.py +10 -0
  76. edc_auth/import_users.py +3 -3
  77. edc_auth/migrations/0001_squashed_0033_alter_userprofile_is_multisite_viewer.py +5 -5
  78. edc_auth/migrations/0012_auto_20191026_0034.py +3 -2
  79. edc_auth/migrations/0013_auto_20191026_0055.py +3 -2
  80. edc_auth/migrations/0025_permissions.py +3 -2
  81. edc_auth/migrations/0035_alter_edcpermissions_device_created_and_more.py +85 -0
  82. edc_auth/models/user_profile.py +14 -11
  83. edc_auth/post_migrate_signals.py +1 -1
  84. edc_auth/site_auths.py +80 -67
  85. edc_consent/actions.py +4 -5
  86. edc_consent/auths.py +18 -12
  87. edc_consent/migrations/0001_initial.py +3 -2
  88. edc_consent/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
  89. edc_consent/model_mixins/consent_extension_model_mixin.py +4 -5
  90. edc_consent/model_mixins/requires_consent_fields_model_mixin.py +2 -2
  91. edc_consent/utils.py +1 -1
  92. edc_constants/constants.py +1 -0
  93. edc_crf/auths.py +5 -0
  94. edc_crf/migrations/0001_initial.py +3 -2
  95. edc_crf/migrations/0009_alter_crfstatus_device_created_and_more.py +54 -0
  96. edc_dashboard/auths.py +10 -6
  97. edc_dashboard/migrations/0001_initial.py +3 -2
  98. edc_dashboard/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
  99. edc_dashboard/templatetags/edc_dashboard_extras.py +3 -2
  100. edc_dashboard/url_config.py +92 -83
  101. edc_dashboard/url_names.py +4 -4
  102. edc_dashboard/view_mixins/url_request_context_mixin.py +6 -5
  103. edc_data_manager/action_items.py +4 -6
  104. edc_data_manager/admin/actions.py +5 -5
  105. edc_data_manager/admin/data_query_admin.py +12 -11
  106. edc_data_manager/auths.py +37 -34
  107. edc_data_manager/handlers/handlers.py +6 -7
  108. edc_data_manager/migrations/0001_initial.py +19 -19
  109. edc_data_manager/migrations/0025_edcpermissions.py +3 -2
  110. edc_data_manager/migrations/0040_alter_datadictionary_device_created_and_more.py +327 -0
  111. edc_data_manager/migrations/0041_alter_dataquery_dm_user_and_more.py +164 -0
  112. edc_data_manager/models/data_query.py +5 -5
  113. edc_data_manager/models/model_mixins.py +8 -8
  114. edc_data_manager/rule/query_rule_wrapper.py +7 -7
  115. edc_data_manager/rule/rule_runner.py +4 -3
  116. edc_document_status/model_mixins.py +1 -1
  117. edc_egfr/egfr.py +11 -7
  118. edc_egfr/model_mixins/egfr_model_mixin.py +3 -7
  119. edc_export/admin/data_request_admin.py +2 -2
  120. edc_export/archive_exporter.py +7 -5
  121. edc_export/auths.py +32 -28
  122. edc_export/files_archiver.py +3 -2
  123. edc_export/migrations/0001_initial.py +26 -26
  124. edc_export/migrations/0004_auto_20190305_0123.py +25 -72
  125. edc_export/migrations/0013_edcpermissions.py +3 -2
  126. edc_export/migrations/0022_alter_datarequest_description_and_more.py +611 -0
  127. edc_export/migrations/0023_alter_datarequesthistory_archive_filename_and_more.py +29 -0
  128. edc_export/model_exporter/file_history_updater.py +10 -10
  129. edc_export/model_exporter/model_exporter.py +17 -15
  130. edc_export/model_exporter/object_history_helpers.py +2 -2
  131. edc_export/models/data_request_history.py +4 -4
  132. edc_export/utils.py +10 -15
  133. edc_facility/auths.py +8 -3
  134. edc_facility/facility.py +16 -22
  135. edc_facility/import_holidays.py +13 -13
  136. edc_facility/migrations/0005_healthfacility_healthfacilitytypes_and_more.py +8 -7
  137. edc_facility/migrations/0016_alter_healthfacility_device_created_and_more.py +139 -0
  138. edc_facility/migrations/0017_alter_healthfacility_gps_and_more.py +54 -0
  139. edc_facility/model_mixins.py +5 -5
  140. edc_form_label/custom_label_condition.py +11 -8
  141. edc_form_label/form_label.py +1 -1
  142. edc_form_runners/auths.py +11 -6
  143. edc_form_runners/form_runner.py +3 -5
  144. edc_form_runners/migrations/0001_initial.py +3 -2
  145. edc_form_runners/migrations/0005_alter_issue_device_created_and_more.py +49 -0
  146. edc_form_validators/applicable_field_validator.py +7 -6
  147. edc_form_validators/base_form_validator.py +8 -9
  148. edc_form_validators/other_specify_field_validator.py +2 -8
  149. edc_form_validators/required_field_validator.py +19 -16
  150. edc_identifier/migrations/0001_squashed_0018_auto_20180128_1054.py +3 -3
  151. edc_identifier/migrations/0002_auto_20190305_0123.py +3 -6
  152. edc_identifier/migrations/0006_auto_20161127_2226.py +15 -15
  153. edc_identifier/migrations/0007_auto_20161204_2227.py +3 -3
  154. edc_identifier/migrations/0009_auto_20161221_2323.py +3 -5
  155. edc_identifier/migrations/0010_auto_20170112_0602.py +17 -17
  156. edc_identifier/migrations/0011_alter_identifiermodel_device_created_and_more.py +79 -0
  157. edc_identifier/model_mixins.py +1 -1
  158. edc_identifier/models.py +9 -9
  159. edc_identifier/research_identifier.py +11 -10
  160. edc_identifier/simple_identifier.py +9 -5
  161. edc_identifier/subject_identifier.py +3 -2
  162. edc_lab/auths.py +26 -23
  163. edc_lab/lab/aliquot_creator.py +5 -8
  164. edc_lab/lab/primary_aliquot.py +14 -5
  165. edc_lab/migrations/0001_initial.py +29 -29
  166. edc_lab/migrations/0008_auto_20170921_0719.py +3 -3
  167. edc_lab/migrations/0010_auto_20171127_1541.py +15 -15
  168. edc_lab/migrations/0012_auto_20180114_1438.py +3 -3
  169. edc_lab/migrations/0019_auto_20190305_0123.py +43 -127
  170. edc_lab/migrations/0036_alter_aliquot_comment_alter_aliquot_device_created_and_more.py +1139 -0
  171. edc_lab/migrations/0037_alter_historicalorder_order_datetime_and_more.py +31 -0
  172. edc_lab/model_mixins/aliquot/aliquot_identifier_model_mixin.py +2 -2
  173. edc_lab/model_mixins/aliquot/aliquot_model_mixin.py +2 -2
  174. edc_lab/model_mixins/panel_model_mixin.py +18 -7
  175. edc_lab/model_mixins/requisition/crf_with_requisition_model_mixin.py +2 -4
  176. edc_lab/model_mixins/requisition/requisition_model_mixin.py +13 -16
  177. edc_lab/model_mixins/requisition/requisition_verify_model_mixin.py +1 -1
  178. edc_lab/model_mixins/result/result_item_model_mixin.py +4 -4
  179. edc_lab/model_mixins/shipping/manifest_model_mixin.py +4 -5
  180. edc_lab/model_mixins/shipping/verify_model_mixin.py +4 -6
  181. edc_lab/models/aliquot.py +2 -2
  182. edc_lab/models/box.py +1 -1
  183. edc_lab/models/box_item.py +6 -7
  184. edc_lab/models/manifest/manifest.py +3 -3
  185. edc_lab/models/manifest/manifest_item.py +7 -7
  186. edc_lab/models/manifest/shipper.py +3 -4
  187. edc_lab/models/order.py +6 -4
  188. edc_lab/models/panel.py +4 -4
  189. edc_lab/models/result.py +2 -2
  190. edc_lab/models/result_item.py +2 -2
  191. edc_lab_dashboard/auths.py +16 -11
  192. edc_lab_dashboard/migrations/0001_initial.py +3 -2
  193. edc_lab_dashboard/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
  194. edc_lab_dashboard/views/action_views/receive_view.py +2 -2
  195. edc_lab_dashboard/views/action_views/verify_box_item_view.py +2 -2
  196. edc_lab_results/calculate_missing.py +8 -8
  197. edc_lab_results/form_validator_mixins/blood_results_form_validator_mixin.py +2 -2
  198. edc_lab_results/get_summary.py +26 -25
  199. edc_lab_results/model_mixins/blood_result_model_mixin.py +9 -7
  200. edc_lab_results/model_mixins/fbg_model_mixin.py +3 -3
  201. edc_lab_results/model_mixins/glucose_model_mixin.py +3 -3
  202. edc_lab_results/model_mixins/hba1c_model_mixin.py +3 -3
  203. edc_label/auths.py +6 -1
  204. edc_label/label_template.py +8 -8
  205. edc_label/migrations/0001_initial.py +3 -2
  206. edc_label/migrations/0007_alter_zpllabeltemplates_device_created_and_more.py +49 -0
  207. edc_list_data/list_model_maker.py +2 -2
  208. edc_list_data/load_list_data.py +11 -14
  209. edc_list_data/load_model_data.py +3 -3
  210. edc_list_data/model_mixins.py +12 -4
  211. edc_list_data/post_migrate_signals.py +1 -1
  212. edc_list_data/preload_data.py +4 -4
  213. edc_list_data/row.py +1 -1
  214. edc_list_data/site_list_data.py +6 -5
  215. edc_listboard/migrations/0001_initial.py +3 -2
  216. edc_listboard/migrations/0007_alter_listboard_device_created_and_more.py +49 -0
  217. edc_locator/auths.py +18 -13
  218. edc_locator/migrations/0001_initial.py +7 -7
  219. edc_locator/migrations/0018_auto_20190305_0123.py +5 -12
  220. edc_locator/migrations/0040_alter_historicalsubjectlocator_action_identifier_and_more.py +187 -0
  221. edc_locator/migrations/0041_alter_historicalsubjectlocator_report_datetime_and_more.py +27 -0
  222. edc_locator/model_mixins/locator_model_mixin.py +2 -2
  223. edc_locator/model_mixins/subject_contact_fields_mixin.py +1 -1
  224. edc_locator/modeladmin_mixins.py +5 -4
  225. edc_ltfu/model_mixins.py +7 -5
  226. edc_metadata/auths.py +11 -7
  227. edc_metadata/metadata/metadata.py +1 -1
  228. edc_metadata/metadata_rules/crf/crf_rule.py +1 -1
  229. edc_metadata/metadata_rules/decorators.py +1 -1
  230. edc_metadata/metadata_rules/metadata_rule_evaluator.py +5 -3
  231. edc_metadata/metadata_rules/rule.py +2 -3
  232. edc_metadata/metadata_rules/rule_evaluator.py +1 -1
  233. edc_metadata/migrations/0002_auto_20161127_2226.py +5 -5
  234. edc_metadata/migrations/0005_auto_20170112_0602.py +5 -5
  235. edc_metadata/migrations/0011_auto_20190305_0123.py +5 -12
  236. edc_metadata/migrations/0031_alter_crfmetadata_device_created_and_more.py +120 -0
  237. edc_metadata/model_mixins/updates/updates_crf_metadata_model_mixin.py +7 -4
  238. edc_metadata/model_mixins/updates/updates_requisition_metadata_model_mixin.py +5 -2
  239. edc_metadata/models/crf_metadata.py +5 -5
  240. edc_metadata/models/crf_metadata_model_mixin.py +4 -5
  241. edc_metadata/models/requisition_metadata.py +6 -6
  242. edc_metadata/models/signals.py +10 -11
  243. edc_metadata/views/refresh_metadata_actions_view.py +3 -3
  244. edc_model/models/address_mixin.py +6 -6
  245. edc_model/models/fields/initials_field.py +2 -1
  246. edc_model/models/historical_records.py +2 -9
  247. edc_model/models/url_model_mixin.py +2 -2
  248. edc_model/validators/date.py +7 -8
  249. edc_model_admin/list_filters/future_date_list_filter.py +3 -3
  250. edc_model_admin/list_filters/past_date_list_filter.py +3 -3
  251. edc_model_admin/mixins/model_admin_protect_pii_mixin.py +4 -5
  252. edc_model_fields/fields/other_charfield.py +2 -2
  253. edc_navbar/auths.py +18 -13
  254. edc_navbar/migrations/0004_auto_20220825_0451.py +3 -2
  255. edc_navbar/migrations/0009_alter_edcpermissions_device_created_and_more.py +49 -0
  256. edc_notification/auths.py +9 -4
  257. edc_notification/migrations/0001_initial.py +3 -3
  258. edc_notification/migrations/0004_auto_20190305_0123.py +3 -6
  259. edc_notification/migrations/0011_alter_notification_device_created_and_more.py +59 -0
  260. edc_notification/models/notification.py +1 -1
  261. edc_notification/notification/graded_event_notification.py +2 -2
  262. edc_notification/notification/model_notification.py +3 -30
  263. edc_notification/notification/new_model_notification.py +1 -1
  264. edc_notification/notification/notification.py +12 -12
  265. edc_notification/notification/updated_model_notification.py +2 -2
  266. edc_offstudy/auths.py +12 -7
  267. edc_offstudy/migrations/0001_initial.py +4 -4
  268. edc_offstudy/migrations/0002_auto_20180921_0434.py +4 -4
  269. edc_offstudy/migrations/0005_auto_20190305_0123.py +5 -12
  270. edc_offstudy/migrations/0023_alter_historicalsubjectoffstudy_action_identifier_and_more.py +188 -0
  271. edc_offstudy/migrations/0024_alter_historicalsubjectoffstudy_offstudy_datetime_and_more.py +43 -0
  272. edc_offstudy/model_mixins/offstudy_model_mixin.py +3 -2
  273. edc_pdutils/df_exporters/csv_exporter.py +33 -37
  274. edc_pdutils/df_exporters/csv_model_exporter.py +7 -3
  275. edc_pdutils/migrations/0001_initial.py +8 -8
  276. edc_pharmacy/admin/prescription/rx_refill_admin.py +4 -3
  277. edc_pharmacy/admin/reports/stock_availability_admin.py +5 -6
  278. edc_pharmacy/auths.py +19 -15
  279. edc_pharmacy/migrations/0001_initial.py +64 -63
  280. edc_pharmacy/migrations/0015_auto_20220913_2139.py +26 -26
  281. edc_pharmacy/migrations/0024_allocation_assignment_containerunits_dispense_and_more.py +81 -86
  282. edc_pharmacy/migrations/0037_remove_historicalstock_confirmed_at_site_by_and_more.py +5 -5
  283. edc_pharmacy/migrations/0039_remove_dispense_registered_subject_and_more.py +7 -8
  284. edc_pharmacy/migrations/0049_remove_stocktransferconfirmation_stock_and_more.py +12 -12
  285. edc_pharmacy/migrations/0050_remove_stocktransferconfirmation2_location_and_more.py +5 -5
  286. edc_pharmacy/migrations/0051_alter_historicalstocktransferconfirmationitem_options_and_more.py +3 -4
  287. edc_pharmacy/migrations/0053_alter_location_managers_alter_historicalstock_lot_and_more.py +3 -3
  288. edc_pharmacy/migrations/0057_scanduplicates.py +3 -3
  289. edc_pharmacy/migrations/0060_alter_container_max_per_subject_and_more.py +13 -15
  290. edc_pharmacy/migrations/0068_stockout.py +2 -3
  291. edc_pharmacy/migrations/0076_historicalstockadjustment_stockadjustment.py +5 -5
  292. edc_pharmacy/migrations/0077_historicalstockadjustment_adjustment_datetime_and_more.py +3 -4
  293. edc_pharmacy/migrations/0081_historicalconfirmation_confirmation.py +8 -8
  294. edc_pharmacy/migrations/0084_confirmationatsiteitem_and_more.py +0 -2
  295. edc_pharmacy/migrations/0089_alter_allocation_allocated_by_and_more.py +3284 -0
  296. edc_pharmacy/migrations/0090_alter_allocation_allocation_datetime_and_more.py +227 -0
  297. edc_pharmacy/model_mixins/study_medication_refill_model_mixin.py +2 -2
  298. edc_pharmacy/models/medication/formulation.py +5 -7
  299. edc_pharmacy/models/medication/medication.py +3 -3
  300. edc_pharmacy/models/model_mixins.py +10 -11
  301. edc_pharmacy/models/prescription/rx.py +13 -12
  302. edc_pharmacy/models/prescription/rx_refill.py +0 -1
  303. edc_pharmacy/models/stock/allocation.py +3 -3
  304. edc_pharmacy/models/stock/confirmation.py +3 -3
  305. edc_pharmacy/models/stock/confirmation_at_site.py +3 -2
  306. edc_pharmacy/models/stock/confirmation_at_site_item.py +3 -4
  307. edc_pharmacy/models/stock/dispense.py +5 -6
  308. edc_pharmacy/models/stock/dispense_item.py +2 -2
  309. edc_pharmacy/models/stock/location.py +3 -4
  310. edc_pharmacy/models/stock/lot.py +6 -7
  311. edc_pharmacy/models/stock/order.py +1 -1
  312. edc_pharmacy/models/stock/receive.py +3 -3
  313. edc_pharmacy/models/stock/receive_item.py +4 -4
  314. edc_pharmacy/models/stock/repack_request.py +2 -2
  315. edc_pharmacy/models/stock/stock.py +12 -18
  316. edc_pharmacy/models/stock/stock_adjustment.py +4 -4
  317. edc_pharmacy/models/stock/stock_request.py +2 -2
  318. edc_pharmacy/models/stock/stock_request_item.py +2 -2
  319. edc_pharmacy/models/stock/stock_transfer.py +3 -3
  320. edc_pharmacy/models/stock/stock_transfer_item.py +2 -2
  321. edc_pharmacy/models/stock/storage_bin.py +3 -4
  322. edc_pharmacy/models/stock/storage_bin_item.py +2 -2
  323. edc_pharmacy/models/stock/supplier.py +3 -4
  324. edc_pharmacy/models/storage/box.py +2 -2
  325. edc_pharmacy/models/storage/items/container_model_mixin.py +3 -4
  326. edc_pharmacy/models/storage/items/pill_bottle_model_mixin.py +2 -2
  327. edc_pharmacy/models/storage/items/subject_pill_bottle.py +1 -1
  328. edc_pharmacy/models/storage/room.py +2 -2
  329. edc_pharmacy/models/storage/shelf.py +2 -2
  330. edc_pharmacy/models/storage/utils.py +1 -1
  331. edc_pharmacy/prescribe/create_prescription.py +3 -3
  332. edc_pharmacy/utils/allocate_stock.py +2 -3
  333. edc_pharmacy/utils/confirm_stock.py +3 -4
  334. edc_pharmacy/utils/confirm_stock_at_site.py +4 -5
  335. edc_pharmacy/utils/dispense.py +3 -4
  336. edc_pharmacy/utils/process_repack_request.py +4 -5
  337. edc_pharmacy/utils/stock_request/bulk_create_stock_request_items.py +2 -3
  338. edc_pharmacy/utils/transfer_stock.py +2 -3
  339. edc_pharmacy/views/add_to_storage_bin_view.py +2 -2
  340. edc_pharmacy/views/allocate_to_subject_view.py +2 -2
  341. edc_pharmacy/views/confirmation_at_site_view.py +6 -9
  342. edc_pharmacy/views/dispense_view.py +2 -2
  343. edc_pharmacy/views/move_to_storage_bin_view.py +2 -3
  344. edc_pharmacy/views/print_labels_view.py +2 -2
  345. edc_prn/admin_site.py +5 -0
  346. edc_prn/prn.py +10 -11
  347. edc_prn/urls.py +11 -0
  348. edc_protocol/research_protocol_config.py +2 -3
  349. edc_protocol_incident/action_items.py +4 -4
  350. edc_protocol_incident/auths.py +27 -20
  351. edc_protocol_incident/migrations/0001_initial.py +7 -7
  352. edc_protocol_incident/migrations/0001_squashed_0015_auto_20220927_0401.py +13 -13
  353. edc_protocol_incident/migrations/0005_protocolincident_historicalprotocolincident_and_more.py +7 -7
  354. edc_protocol_incident/migrations/0024_alter_actionsrequired_extra_value_and_more.py +625 -0
  355. edc_protocol_incident/migrations/0025_alter_historicalprotocoldeviationviolation_report_datetime_and_more.py +42 -0
  356. edc_protocol_incident/model_mixins/protocol_deviation_violation_model_mixin.py +18 -11
  357. edc_protocol_incident/model_mixins/protocol_incident_model_mixin.py +26 -11
  358. edc_pylabels/actions.py +3 -5
  359. edc_pylabels/auths.py +6 -1
  360. edc_pylabels/migrations/0002_alter_label_options_label_created_and_more.py +3 -7
  361. edc_pylabels/migrations/0005_labelconfiguration_delete_label_and_more.py +3 -3
  362. edc_pylabels/migrations/0013_alter_labelconfiguration_device_created_and_more.py +49 -0
  363. edc_qareports/auths.py +11 -7
  364. edc_qareports/migrations/0001_initial.py +4 -5
  365. edc_qareports/migrations/0005_edcpermissions.py +3 -3
  366. edc_qareports/migrations/0006_qareportlog.py +2 -3
  367. edc_qareports/migrations/0019_alter_edcpermissions_device_created_and_more.py +102 -0
  368. edc_qareports/migrations/0020_alter_note_report_datetime_and_more.py +24 -0
  369. edc_qareports/model_mixins/note_model_mixin.py +7 -4
  370. edc_qareports/model_mixins/on_study_missing_values_model_mixin.py +4 -4
  371. edc_qareports/model_mixins/qa_report_model_mixin.py +2 -3
  372. edc_qareports/models/note.py +4 -4
  373. edc_qareports/models/qa_reports_log.py +2 -3
  374. edc_randomization/admin.py +30 -24
  375. edc_randomization/auths.py +12 -7
  376. edc_randomization/decorators.py +1 -1
  377. edc_randomization/migrations/0001_initial.py +3 -2
  378. edc_randomization/migrations/0002_historicalrandomizationlist.py +3 -2
  379. edc_randomization/migrations/0009_edcpermissions.py +3 -2
  380. edc_randomization/migrations/0014_alter_edcpermissions_device_created_and_more.py +141 -0
  381. edc_randomization/model_mixins.py +9 -9
  382. edc_randomization/randomizer.py +22 -20
  383. edc_randomization/utils.py +19 -18
  384. edc_refusal/auths.py +7 -2
  385. edc_refusal/migrations/0001_initial.py +4 -4
  386. edc_refusal/migrations/0002_historicalsubjectrefusal.py +4 -4
  387. edc_refusal/migrations/0012_alter_historicalsubjectrefusal_comment_and_more.py +122 -0
  388. edc_refusal/migrations/0013_alter_historicalsubjectrefusal_report_datetime_and_more.py +28 -0
  389. edc_refusal/model_mixins.py +4 -4
  390. edc_registration/auths.py +28 -23
  391. edc_registration/migrations/0002_auto_20161127_2226.py +3 -4
  392. edc_registration/migrations/0005_auto_20170111_1809.py +4 -2
  393. edc_registration/migrations/0016_historicalregisteredsubject.py +3 -2
  394. edc_registration/migrations/0017_auto_20190305_0123.py +5 -12
  395. edc_registration/migrations/0033_alter_historicalregisteredsubject_additional_key_and_more.py +302 -0
  396. edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py +15 -7
  397. edc_registration/models/registered_subject.py +28 -27
  398. edc_reportable/age_evaluator.py +4 -2
  399. edc_reportable/formula.py +5 -5
  400. edc_reportable/migrations/0001_initial.py +7 -7
  401. edc_reportable/migrations/0003_referencerangecollection_grade1_and_more.py +3 -3
  402. edc_reportable/migrations/0004_alter_referencerangecollection_grade3_and_more.py +5 -5
  403. edc_reportable/migrations/0006_alter_gradingdata_revision_and_more.py +5 -6
  404. edc_reportable/migrations/0007_alter_gradingdata_age_phrase_and_more.py +509 -0
  405. edc_reportable/models/normal_data.py +4 -5
  406. edc_reportable/models/reference_model_mixins.py +10 -11
  407. edc_reportable/models/reference_range_collection.py +12 -13
  408. edc_reportable/post_migrate_signals.py +1 -1
  409. edc_reportable/utils/convert_units.py +11 -45
  410. edc_reportable/utils/get_normal_data_or_raise.py +2 -2
  411. edc_reportable/utils/get_reference_range_collection.py +2 -3
  412. edc_reportable/utils/load_data.py +4 -4
  413. edc_reportable/utils/update_grading_data.py +5 -5
  414. edc_review_dashboard/auths.py +23 -18
  415. edc_review_dashboard/migrations/0001_initial.py +3 -2
  416. edc_review_dashboard/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
  417. edc_screening/age_evaluator.py +6 -6
  418. edc_screening/auths.py +35 -30
  419. edc_screening/eligibility.py +1 -1
  420. edc_screening/gender_evaluator.py +1 -1
  421. edc_screening/migrations/0001_initial.py +3 -2
  422. edc_screening/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
  423. edc_screening/model_mixins/eligibility_model_mixin.py +3 -6
  424. edc_screening/model_mixins/screening_fields_model_mixin.py +6 -8
  425. edc_screening/model_mixins/screening_methods_model_mixin.py +1 -1
  426. edc_screening/screening_eligibility.py +2 -4
  427. edc_screening/utils.py +9 -9
  428. edc_search/generate_slug.py +26 -0
  429. edc_search/model_mixins.py +10 -22
  430. edc_sites/auths.py +8 -3
  431. edc_sites/migrations/0007_edcpermissions.py +3 -2
  432. edc_sites/migrations/0010_alter_edcpermissions_device_created_and_more.py +69 -0
  433. edc_sites/model_mixins/site_model_mixin.py +2 -2
  434. edc_sites/site.py +5 -5
  435. edc_sites/system_checks.py +1 -1
  436. edc_subject_dashboard/auths.py +27 -22
  437. edc_subject_dashboard/migrations/0001_initial.py +3 -2
  438. edc_subject_dashboard/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
  439. edc_subject_dashboard/requisition_report.py +6 -4
  440. edc_subject_dashboard/requisition_verifier.py +6 -6
  441. edc_subject_dashboard/templatetags/edc_subject_dashboard_extras.py +2 -2
  442. edc_subject_dashboard/view_mixins/subject_visit_view_mixin.py +7 -8
  443. edc_subject_dashboard/view_utils/subject_consent_listboard_button.py +3 -2
  444. edc_subject_dashboard/view_utils/timepoint_status_button.py +2 -2
  445. edc_timepoint/apps.py +0 -21
  446. edc_timepoint/model_mixins.py +22 -20
  447. edc_transfer/model_mixins.py +4 -4
  448. edc_transfer/modeladmin_mixins.py +1 -1
  449. edc_unblinding/auths.py +9 -4
  450. edc_unblinding/migrations/0001_initial.py +13 -13
  451. edc_unblinding/migrations/0014_alter_historicalunblindingrequest_action_identifier_and_more.py +291 -0
  452. edc_unblinding/migrations/0015_alter_historicalunblindingrequest_report_datetime_and_more.py +45 -0
  453. edc_unblinding/models/unblinding_request.py +2 -2
  454. edc_unblinding/models/unblinding_review.py +3 -3
  455. edc_utils/__init__.py +3 -1
  456. edc_utils/age.py +10 -16
  457. edc_utils/show_urls.py +29 -2
  458. edc_visit_schedule/auths.py +6 -1
  459. edc_visit_schedule/migrations/0001_initial.py +3 -3
  460. edc_visit_schedule/migrations/0002_auto_20190305_0123.py +3 -6
  461. edc_visit_schedule/migrations/0003_historicalvisitschedule_visitschedule.py +5 -4
  462. edc_visit_schedule/migrations/0015_historicalonschedule_offschedule_onschedule.py +10 -10
  463. edc_visit_schedule/migrations/0019_alter_historicalonschedule_device_created_and_more.py +229 -0
  464. edc_visit_schedule/migrations/0020_alter_historicalonschedule_onschedule_datetime_and_more.py +65 -0
  465. edc_visit_schedule/model_mixins/off_schedule_model_mixin.py +5 -4
  466. edc_visit_schedule/model_mixins/on_schedule_model_mixin.py +5 -4
  467. edc_visit_schedule/model_mixins/visit_schedule/visit_code_fields_model_mixin.py +1 -1
  468. edc_visit_schedule/models/subject_schedule_history.py +6 -6
  469. edc_visit_schedule/schedule/visit_collection.py +1 -1
  470. edc_visit_schedule/site_visit_schedules.py +2 -2
  471. edc_visit_schedule/subject_schedule.py +5 -4
  472. edc_visit_schedule/view_mixins.py +2 -3
  473. edc_visit_schedule/visit/visit.py +3 -2
  474. edc_visit_tracking/migrations/0004_subjectvisit_subjectvisitmissedreasons_extra_value_and_more.py +13 -13
  475. edc_visit_tracking/migrations/0009_alter_historicalsubjectvisit_comments_and_more.py +450 -0
  476. edc_visit_tracking/migrations/0010_alter_historicalsubjectvisit_report_datetime_and_more.py +68 -0
  477. edc_visit_tracking/model_mixins/base/visit_methods_model_mixin.py +3 -3
  478. edc_visit_tracking/model_mixins/crfs/visit_tracking_crf_model_mixin.py +2 -2
  479. edc_visit_tracking/model_mixins/requisitions/visit_tracking_requisition_model_mixin.py +2 -2
  480. edc_visit_tracking/model_mixins/subject_visit_missed_model_mixin.py +2 -2
  481. edc_visit_tracking/model_mixins/visit_model_mixin/caretaker_fields_mixin.py +2 -3
  482. edc_visit_tracking/model_mixins/visit_model_mixin/previous_visit_model_mixin.py +1 -1
  483. edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_fields_mixin.py +8 -11
  484. edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_mixin.py +1 -1
  485. edc_visit_tracking/models/signals.py +3 -3
  486. edc_visit_tracking/models/subject_visit.py +1 -1
  487. edc_vitals/calculators/bmi.py +7 -5
  488. edc_vitals/utils.py +1 -1
  489. edc_form_label/models.py +0 -0
  490. edc_search/constants.py +0 -1
  491. edc_search/models.py +0 -0
  492. edc_search/search_slug.py +0 -50
  493. edc_search/updater.py +0 -30
  494. edc_search/wsgi.py +0 -7
  495. {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,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,29 +132,26 @@ 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()
139
- fields.extend(
140
- [
141
- "subject_identifier",
142
- "requisition_identifier",
143
- "human_readable_identifier",
144
- "identifier_prefix",
145
- ]
139
+ return (
140
+ *fields,
141
+ "subject_identifier",
142
+ "requisition_identifier",
143
+ "human_readable_identifier",
144
+ "identifier_prefix",
146
145
  )
147
- return fields
148
146
 
149
147
  class Meta(NonUniqueSubjectIdentifierFieldMixin.Meta):
150
148
  abstract = True
151
- constraints = [
149
+ constraints = (
152
150
  UniqueConstraint(
153
151
  fields=["panel", "subject_visit"],
154
152
  name="%(app_label)s_%(class)s_panel_uniq",
155
- )
156
- ]
157
-
153
+ ),
154
+ )
158
155
  indexes = (
159
156
  *NonUniqueSubjectIdentifierFieldMixin.Meta.indexes,
160
157
  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/aliquot.py CHANGED
@@ -24,13 +24,13 @@ class Aliquot(
24
24
  BaseUuidModel,
25
25
  ):
26
26
  def get_search_slug_fields(self):
27
- return [
27
+ return (
28
28
  "aliquot_identifier",
29
29
  "human_readable_identifier",
30
30
  "subject_identifier",
31
31
  "parent_identifier",
32
32
  "requisition_identifier",
33
- ]
33
+ )
34
34
 
35
35
  objects = Manager()
36
36
 
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
+ )
@@ -21,12 +21,12 @@ class Manifest(ManifestModelMixin, PdfReportModelMixin, SearchSlugModelMixin, Ba
21
21
  pdf_report_cls = ManifestPdfReport
22
22
 
23
23
  def get_search_slug_fields(self):
24
- return [
24
+ return (
25
25
  "manifest_identifier",
26
26
  "human_readable_identifier",
27
27
  "shipper.name",
28
28
  "consignee.name",
29
- ]
29
+ )
30
30
 
31
31
  consignee = models.ForeignKey(Consignee, verbose_name="Consignee", on_delete=PROTECT)
32
32
 
@@ -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(
@@ -17,20 +17,20 @@ class ManifestItemManager(SearchSlugManager, models.Manager):
17
17
 
18
18
  class ManifestItem(SiteModelMixin, SearchSlugModelMixin, VerifyModelMixin, BaseUuidModel):
19
19
  def get_search_slug_fields(self):
20
- return ["identifier", "human_readable_identifier"]
20
+ return "identifier", "human_readable_identifier"
21
21
 
22
22
  manifest = models.ForeignKey(Manifest, on_delete=PROTECT)
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"
@@ -8,16 +8,21 @@ from edc_lab_dashboard.auth_objects import (
8
8
  lab_navbar_tuples,
9
9
  )
10
10
 
11
- site_auths.add_post_update_func(
12
- "edc_lab_dashboard", remove_default_model_permissions_from_edc_permissions
13
- )
14
11
 
15
- site_auths.add_custom_permissions_tuples(
16
- model="edc_lab_dashboard.edcpermissions", codename_tuples=lab_navbar_tuples
17
- )
18
- site_auths.add_custom_permissions_tuples(
19
- model="edc_lab_dashboard.edcpermissions", codename_tuples=lab_dashboard_tuples
20
- )
12
+ def update_site_auths():
13
+ site_auths.add_post_update_func(
14
+ "edc_lab_dashboard", remove_default_model_permissions_from_edc_permissions
15
+ )
16
+
17
+ site_auths.add_custom_permissions_tuples(
18
+ model="edc_lab_dashboard.edcpermissions", codename_tuples=lab_navbar_tuples
19
+ )
20
+ site_auths.add_custom_permissions_tuples(
21
+ model="edc_lab_dashboard.edcpermissions", codename_tuples=lab_dashboard_tuples
22
+ )
23
+
24
+ site_auths.update_group(*lab_dashboard_codenames, *lab_navbar_codenames, name=LAB)
25
+ site_auths.update_group(*lab_dashboard_codenames, *lab_navbar_codenames, name=LAB_VIEW)
26
+
21
27
 
22
- site_auths.update_group(*lab_dashboard_codenames, *lab_navbar_codenames, name=LAB)
23
- site_auths.update_group(*lab_dashboard_codenames, *lab_navbar_codenames, name=LAB_VIEW)
28
+ update_site_auths()
@@ -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
+ ]