clinicedc 2.0.5__py3-none-any.whl → 2.0.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of clinicedc might be problematic. Click here for more details.
- {clinicedc-2.0.5.dist-info → clinicedc-2.0.7.dist-info}/METADATA +2 -2
- {clinicedc-2.0.5.dist-info → clinicedc-2.0.7.dist-info}/RECORD +387 -336
- edc_action_item/action.py +1 -1
- edc_action_item/action_item_notification.py +2 -2
- edc_action_item/create_action_item.py +1 -1
- edc_action_item/decorators.py +1 -1
- edc_action_item/migrations/0001_initial.py +21 -22
- edc_action_item/migrations/0006_auto_20180707_1659.py +4 -4
- edc_action_item/migrations/0008_auto_20180809_0303.py +4 -4
- edc_action_item/migrations/0015_auto_20190114_0250.py +4 -4
- edc_action_item/migrations/0017_auto_20190305_0123.py +11 -30
- edc_action_item/migrations/0030_edcpermissions.py +3 -2
- edc_action_item/migrations/0039_alter_actionitem_auto_created_comment_and_more.py +398 -0
- edc_action_item/migrations/0040_alter_actionitem_report_datetime_and_more.py +34 -0
- edc_action_item/models/action_item.py +9 -4
- edc_action_item/models/action_model_mixin.py +4 -4
- edc_action_item/models/reference.py +2 -2
- edc_action_item/post_migrate_signals.py +1 -1
- edc_action_item/send_email.py +0 -85
- edc_adherence/migrations/0005_alter_nonadherencereasons_extra_value_and_more.py +36 -0
- edc_adherence/model_mixins.py +1 -1
- edc_adverse_event/migrations/0001_initial.py +5 -4
- edc_adverse_event/migrations/0002_auto_20190802_0059.py +3 -2
- edc_adverse_event/migrations/0008_auto_20220825_0451.py +3 -2
- edc_adverse_event/migrations/0009_auto_20220907_0157.py +3 -2
- edc_adverse_event/migrations/0016_alter_aeactionclassification_device_created_and_more.py +285 -0
- edc_adverse_event/model_mixins/ae_followup/ae_followup_fields_model_mixin.py +2 -2
- edc_adverse_event/model_mixins/ae_initial/ae_initial_fields_model_mixin.py +6 -5
- edc_adverse_event/model_mixins/ae_special_interest/aesi_fields_model_mixin.py +2 -2
- edc_adverse_event/model_mixins/ae_susar/ae_susar_fields_model_mixin.py +2 -2
- edc_adverse_event/model_mixins/ae_tmg/ae_tmg_fields_model_mixin.py +15 -11
- edc_adverse_event/model_mixins/death_report/death_report_model_mixin.py +5 -4
- edc_adverse_event/model_mixins/death_report/death_report_tmg_model_mixin.py +6 -3
- edc_adverse_event/model_mixins/death_report/simple_death_report_model_mixin.py +2 -2
- edc_adverse_event/model_mixins/hospitaization/hospitalization_model_mixin.py +4 -3
- edc_adverse_event/modeladmin_mixins/death_report_admin_mixin.py +3 -3
- edc_adverse_event/models/signals.py +7 -7
- edc_adverse_event/templatetags/edc_adverse_event_extras.py +5 -4
- edc_adverse_event/view_mixins/ae/ae_listboard_view_mixin.py +3 -5
- edc_adverse_event/view_mixins/ae/death_report_listboard_view_mixin.py +6 -8
- edc_adverse_event/view_mixins/tmg/tmg_ae_listboard_view_mixin.py +2 -2
- edc_adverse_event/views/tmg/summary_listboard_view.py +3 -2
- edc_appointment/admin/appointment_admin.py +2 -2
- edc_appointment/admin/list_filters.py +2 -2
- edc_appointment/form_validators/appointment_form_validator.py +108 -82
- edc_appointment/migrations/0003_auto_20161127_2226.py +5 -6
- edc_appointment/migrations/0006_auto_20170106_2118.py +5 -5
- edc_appointment/migrations/0018_auto_20190305_0123.py +5 -12
- edc_appointment/migrations/0050_alter_appointment_appt_type_and_more.py +220 -0
- edc_appointment/model_mixins/appointment_fields_model_mixin.py +1 -2
- edc_appointment/model_mixins/window_period_model_mixin.py +6 -7
- edc_appointment/models/signals.py +44 -35
- edc_appointment/view_utils/appointment_button.py +2 -2
- edc_auth/admin/user_admin.py +1 -1
- edc_auth/migrations/0001_squashed_0033_alter_userprofile_is_multisite_viewer.py +5 -5
- edc_auth/migrations/0012_auto_20191026_0034.py +3 -2
- edc_auth/migrations/0013_auto_20191026_0055.py +3 -2
- edc_auth/migrations/0025_permissions.py +3 -2
- edc_auth/migrations/0035_alter_edcpermissions_device_created_and_more.py +85 -0
- edc_auth/post_migrate_signals.py +1 -1
- edc_consent/actions.py +4 -5
- edc_consent/migrations/0001_initial.py +3 -2
- edc_consent/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_consent/model_mixins/consent_extension_model_mixin.py +4 -5
- edc_consent/model_mixins/requires_consent_fields_model_mixin.py +2 -2
- edc_consent/utils.py +1 -1
- edc_crf/migrations/0001_initial.py +3 -2
- edc_crf/migrations/0009_alter_crfstatus_device_created_and_more.py +54 -0
- edc_dashboard/migrations/0001_initial.py +3 -2
- edc_dashboard/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_dashboard/templatetags/edc_dashboard_extras.py +3 -2
- edc_data_manager/action_items.py +4 -6
- edc_data_manager/admin/actions.py +5 -5
- edc_data_manager/handlers/handlers.py +6 -7
- edc_data_manager/migrations/0001_initial.py +19 -19
- edc_data_manager/migrations/0025_edcpermissions.py +3 -2
- edc_data_manager/migrations/0040_alter_datadictionary_device_created_and_more.py +327 -0
- edc_data_manager/migrations/0041_alter_dataquery_dm_user_and_more.py +164 -0
- edc_data_manager/models/data_query.py +5 -5
- edc_data_manager/models/model_mixins.py +8 -8
- edc_data_manager/rule/rule_runner.py +4 -3
- edc_document_status/model_mixins.py +1 -1
- edc_egfr/egfr.py +11 -7
- edc_egfr/model_mixins/egfr_model_mixin.py +3 -7
- edc_export/admin/data_request_admin.py +2 -2
- edc_export/archive_exporter.py +4 -3
- edc_export/files_archiver.py +3 -2
- edc_export/migrations/0001_initial.py +26 -26
- edc_export/migrations/0004_auto_20190305_0123.py +25 -72
- edc_export/migrations/0013_edcpermissions.py +3 -2
- edc_export/migrations/0022_alter_datarequest_description_and_more.py +611 -0
- edc_export/migrations/0023_alter_datarequesthistory_archive_filename_and_more.py +29 -0
- edc_export/model_exporter/file_history_updater.py +10 -10
- edc_export/model_exporter/model_exporter.py +13 -14
- edc_export/model_exporter/object_history_helpers.py +2 -2
- edc_export/models/data_request_history.py +4 -4
- edc_export/utils.py +10 -15
- edc_facility/facility.py +10 -15
- edc_facility/import_holidays.py +13 -13
- edc_facility/migrations/0005_healthfacility_healthfacilitytypes_and_more.py +8 -7
- edc_facility/migrations/0016_alter_healthfacility_device_created_and_more.py +139 -0
- edc_facility/migrations/0017_alter_healthfacility_gps_and_more.py +54 -0
- edc_facility/model_mixins.py +5 -5
- edc_form_runners/form_runner.py +3 -5
- edc_form_runners/migrations/0001_initial.py +3 -2
- edc_form_runners/migrations/0005_alter_issue_device_created_and_more.py +49 -0
- edc_identifier/migrations/0001_squashed_0018_auto_20180128_1054.py +3 -3
- edc_identifier/migrations/0002_auto_20190305_0123.py +3 -6
- edc_identifier/migrations/0006_auto_20161127_2226.py +15 -15
- edc_identifier/migrations/0007_auto_20161204_2227.py +3 -3
- edc_identifier/migrations/0009_auto_20161221_2323.py +3 -5
- edc_identifier/migrations/0010_auto_20170112_0602.py +17 -17
- edc_identifier/migrations/0011_alter_identifiermodel_device_created_and_more.py +79 -0
- edc_identifier/model_mixins.py +1 -1
- edc_identifier/models.py +9 -9
- edc_identifier/simple_identifier.py +1 -3
- edc_identifier/subject_identifier.py +3 -2
- edc_lab/migrations/0001_initial.py +29 -29
- edc_lab/migrations/0008_auto_20170921_0719.py +3 -3
- edc_lab/migrations/0010_auto_20171127_1541.py +15 -15
- edc_lab/migrations/0012_auto_20180114_1438.py +3 -3
- edc_lab/migrations/0019_auto_20190305_0123.py +43 -127
- edc_lab/migrations/0036_alter_aliquot_comment_alter_aliquot_device_created_and_more.py +1139 -0
- edc_lab/migrations/0037_alter_historicalorder_order_datetime_and_more.py +31 -0
- edc_lab/model_mixins/aliquot/aliquot_identifier_model_mixin.py +2 -2
- edc_lab/model_mixins/aliquot/aliquot_model_mixin.py +2 -2
- edc_lab/model_mixins/panel_model_mixin.py +18 -7
- edc_lab/model_mixins/requisition/crf_with_requisition_model_mixin.py +2 -4
- edc_lab/model_mixins/requisition/requisition_model_mixin.py +7 -8
- edc_lab/model_mixins/requisition/requisition_verify_model_mixin.py +1 -1
- edc_lab/model_mixins/result/result_item_model_mixin.py +4 -4
- edc_lab/model_mixins/shipping/manifest_model_mixin.py +4 -5
- edc_lab/model_mixins/shipping/verify_model_mixin.py +4 -6
- edc_lab/models/box.py +1 -1
- edc_lab/models/box_item.py +6 -7
- edc_lab/models/manifest/manifest.py +1 -1
- edc_lab/models/manifest/manifest_item.py +6 -6
- edc_lab/models/manifest/shipper.py +3 -4
- edc_lab/models/order.py +6 -4
- edc_lab/models/panel.py +4 -4
- edc_lab/models/result.py +2 -2
- edc_lab/models/result_item.py +2 -2
- edc_lab_dashboard/migrations/0001_initial.py +3 -2
- edc_lab_dashboard/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_lab_dashboard/views/action_views/receive_view.py +2 -2
- edc_lab_dashboard/views/action_views/verify_box_item_view.py +2 -2
- edc_lab_results/model_mixins/blood_result_model_mixin.py +7 -7
- edc_lab_results/model_mixins/fbg_model_mixin.py +3 -3
- edc_lab_results/model_mixins/glucose_model_mixin.py +3 -3
- edc_lab_results/model_mixins/hba1c_model_mixin.py +3 -3
- edc_label/migrations/0001_initial.py +3 -2
- edc_label/migrations/0007_alter_zpllabeltemplates_device_created_and_more.py +49 -0
- edc_list_data/list_model_maker.py +2 -2
- edc_list_data/load_list_data.py +11 -14
- edc_list_data/model_mixins.py +12 -4
- edc_list_data/preload_data.py +3 -3
- edc_listboard/migrations/0001_initial.py +3 -2
- edc_listboard/migrations/0007_alter_listboard_device_created_and_more.py +49 -0
- edc_locator/migrations/0001_initial.py +7 -7
- edc_locator/migrations/0018_auto_20190305_0123.py +5 -12
- edc_locator/migrations/0040_alter_historicalsubjectlocator_action_identifier_and_more.py +187 -0
- edc_locator/migrations/0041_alter_historicalsubjectlocator_report_datetime_and_more.py +27 -0
- edc_locator/model_mixins/locator_model_mixin.py +2 -2
- edc_locator/model_mixins/subject_contact_fields_mixin.py +1 -1
- edc_locator/modeladmin_mixins.py +5 -4
- edc_ltfu/model_mixins.py +7 -5
- edc_metadata/metadata_rules/decorators.py +1 -1
- edc_metadata/migrations/0002_auto_20161127_2226.py +5 -5
- edc_metadata/migrations/0005_auto_20170112_0602.py +5 -5
- edc_metadata/migrations/0011_auto_20190305_0123.py +5 -12
- edc_metadata/migrations/0031_alter_crfmetadata_device_created_and_more.py +120 -0
- edc_metadata/model_mixins/updates/updates_crf_metadata_model_mixin.py +1 -1
- edc_metadata/model_mixins/updates/updates_requisition_metadata_model_mixin.py +1 -1
- edc_metadata/models/crf_metadata.py +5 -5
- edc_metadata/models/crf_metadata_model_mixin.py +4 -5
- edc_metadata/models/requisition_metadata.py +6 -6
- edc_metadata/views/refresh_metadata_actions_view.py +3 -3
- edc_model/models/address_mixin.py +6 -6
- edc_model/models/fields/initials_field.py +2 -1
- edc_model/models/historical_records.py +2 -9
- edc_model/models/url_model_mixin.py +2 -2
- edc_model/validators/date.py +7 -8
- edc_model_admin/list_filters/future_date_list_filter.py +3 -3
- edc_model_admin/list_filters/past_date_list_filter.py +3 -3
- edc_model_admin/mixins/model_admin_protect_pii_mixin.py +4 -5
- edc_model_fields/fields/other_charfield.py +2 -2
- edc_navbar/migrations/0004_auto_20220825_0451.py +3 -2
- edc_navbar/migrations/0009_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_notification/migrations/0001_initial.py +3 -3
- edc_notification/migrations/0004_auto_20190305_0123.py +3 -6
- edc_notification/migrations/0011_alter_notification_device_created_and_more.py +59 -0
- edc_notification/models/notification.py +1 -1
- edc_notification/notification/notification.py +12 -12
- edc_offstudy/migrations/0001_initial.py +4 -4
- edc_offstudy/migrations/0002_auto_20180921_0434.py +4 -4
- edc_offstudy/migrations/0005_auto_20190305_0123.py +5 -12
- edc_offstudy/migrations/0023_alter_historicalsubjectoffstudy_action_identifier_and_more.py +188 -0
- edc_offstudy/migrations/0024_alter_historicalsubjectoffstudy_offstudy_datetime_and_more.py +43 -0
- edc_offstudy/model_mixins/offstudy_model_mixin.py +3 -2
- edc_pdutils/df_exporters/csv_exporter.py +33 -37
- edc_pdutils/df_exporters/csv_model_exporter.py +2 -1
- edc_pdutils/migrations/0001_initial.py +8 -8
- edc_pharmacy/admin/prescription/rx_refill_admin.py +4 -3
- edc_pharmacy/admin/reports/stock_availability_admin.py +5 -6
- edc_pharmacy/migrations/0001_initial.py +64 -63
- edc_pharmacy/migrations/0015_auto_20220913_2139.py +26 -26
- edc_pharmacy/migrations/0024_allocation_assignment_containerunits_dispense_and_more.py +81 -86
- edc_pharmacy/migrations/0037_remove_historicalstock_confirmed_at_site_by_and_more.py +5 -5
- edc_pharmacy/migrations/0039_remove_dispense_registered_subject_and_more.py +7 -8
- edc_pharmacy/migrations/0049_remove_stocktransferconfirmation_stock_and_more.py +12 -12
- edc_pharmacy/migrations/0050_remove_stocktransferconfirmation2_location_and_more.py +5 -5
- edc_pharmacy/migrations/0051_alter_historicalstocktransferconfirmationitem_options_and_more.py +3 -4
- edc_pharmacy/migrations/0053_alter_location_managers_alter_historicalstock_lot_and_more.py +3 -3
- edc_pharmacy/migrations/0057_scanduplicates.py +3 -3
- edc_pharmacy/migrations/0060_alter_container_max_per_subject_and_more.py +13 -15
- edc_pharmacy/migrations/0068_stockout.py +2 -3
- edc_pharmacy/migrations/0076_historicalstockadjustment_stockadjustment.py +5 -5
- edc_pharmacy/migrations/0077_historicalstockadjustment_adjustment_datetime_and_more.py +3 -4
- edc_pharmacy/migrations/0081_historicalconfirmation_confirmation.py +8 -8
- edc_pharmacy/migrations/0084_confirmationatsiteitem_and_more.py +0 -2
- edc_pharmacy/migrations/0089_alter_allocation_allocated_by_and_more.py +3284 -0
- edc_pharmacy/migrations/0090_alter_allocation_allocation_datetime_and_more.py +227 -0
- edc_pharmacy/model_mixins/study_medication_refill_model_mixin.py +2 -2
- edc_pharmacy/models/medication/medication.py +3 -3
- edc_pharmacy/models/model_mixins.py +10 -11
- edc_pharmacy/models/prescription/rx.py +13 -12
- edc_pharmacy/models/prescription/rx_refill.py +0 -1
- edc_pharmacy/models/stock/allocation.py +3 -3
- edc_pharmacy/models/stock/confirmation.py +3 -3
- edc_pharmacy/models/stock/confirmation_at_site.py +3 -2
- edc_pharmacy/models/stock/confirmation_at_site_item.py +3 -4
- edc_pharmacy/models/stock/dispense.py +5 -6
- edc_pharmacy/models/stock/dispense_item.py +2 -2
- edc_pharmacy/models/stock/location.py +3 -4
- edc_pharmacy/models/stock/lot.py +6 -7
- edc_pharmacy/models/stock/order.py +1 -1
- edc_pharmacy/models/stock/receive.py +3 -3
- edc_pharmacy/models/stock/receive_item.py +4 -4
- edc_pharmacy/models/stock/repack_request.py +2 -2
- edc_pharmacy/models/stock/stock.py +12 -18
- edc_pharmacy/models/stock/stock_adjustment.py +4 -4
- edc_pharmacy/models/stock/stock_request.py +2 -2
- edc_pharmacy/models/stock/stock_request_item.py +2 -2
- edc_pharmacy/models/stock/stock_transfer.py +3 -3
- edc_pharmacy/models/stock/stock_transfer_item.py +2 -2
- edc_pharmacy/models/stock/storage_bin.py +3 -4
- edc_pharmacy/models/stock/storage_bin_item.py +2 -2
- edc_pharmacy/models/stock/supplier.py +3 -4
- edc_pharmacy/models/storage/box.py +2 -2
- edc_pharmacy/models/storage/items/container_model_mixin.py +3 -4
- edc_pharmacy/models/storage/items/pill_bottle_model_mixin.py +2 -2
- edc_pharmacy/models/storage/items/subject_pill_bottle.py +1 -1
- edc_pharmacy/models/storage/room.py +2 -2
- edc_pharmacy/models/storage/shelf.py +2 -2
- edc_pharmacy/models/storage/utils.py +1 -1
- edc_pharmacy/utils/allocate_stock.py +2 -3
- edc_pharmacy/utils/confirm_stock.py +2 -3
- edc_pharmacy/utils/confirm_stock_at_site.py +3 -4
- edc_pharmacy/utils/dispense.py +3 -4
- edc_pharmacy/utils/process_repack_request.py +4 -5
- edc_pharmacy/utils/stock_request/bulk_create_stock_request_items.py +2 -3
- edc_pharmacy/utils/transfer_stock.py +2 -3
- edc_pharmacy/views/add_to_storage_bin_view.py +2 -2
- edc_pharmacy/views/allocate_to_subject_view.py +2 -2
- edc_pharmacy/views/dispense_view.py +2 -2
- edc_pharmacy/views/move_to_storage_bin_view.py +2 -3
- edc_pharmacy/views/print_labels_view.py +2 -2
- edc_protocol/research_protocol_config.py +2 -3
- edc_protocol_incident/migrations/0001_initial.py +7 -7
- edc_protocol_incident/migrations/0001_squashed_0015_auto_20220927_0401.py +13 -13
- edc_protocol_incident/migrations/0005_protocolincident_historicalprotocolincident_and_more.py +7 -7
- edc_protocol_incident/migrations/0024_alter_actionsrequired_extra_value_and_more.py +625 -0
- edc_protocol_incident/migrations/0025_alter_historicalprotocoldeviationviolation_report_datetime_and_more.py +42 -0
- edc_protocol_incident/model_mixins/protocol_deviation_violation_model_mixin.py +18 -11
- edc_protocol_incident/model_mixins/protocol_incident_model_mixin.py +26 -11
- edc_pylabels/actions.py +3 -5
- edc_pylabels/migrations/0002_alter_label_options_label_created_and_more.py +3 -7
- edc_pylabels/migrations/0005_labelconfiguration_delete_label_and_more.py +3 -3
- edc_pylabels/migrations/0013_alter_labelconfiguration_device_created_and_more.py +49 -0
- edc_qareports/migrations/0001_initial.py +4 -5
- edc_qareports/migrations/0005_edcpermissions.py +3 -3
- edc_qareports/migrations/0006_qareportlog.py +2 -3
- edc_qareports/migrations/0019_alter_edcpermissions_device_created_and_more.py +102 -0
- edc_qareports/migrations/0020_alter_note_report_datetime_and_more.py +24 -0
- edc_qareports/model_mixins/note_model_mixin.py +7 -4
- edc_qareports/model_mixins/on_study_missing_values_model_mixin.py +4 -4
- edc_qareports/model_mixins/qa_report_model_mixin.py +2 -3
- edc_qareports/models/note.py +4 -4
- edc_qareports/models/qa_reports_log.py +2 -3
- edc_randomization/decorators.py +1 -1
- edc_randomization/migrations/0001_initial.py +3 -2
- edc_randomization/migrations/0002_historicalrandomizationlist.py +3 -2
- edc_randomization/migrations/0009_edcpermissions.py +3 -2
- edc_randomization/migrations/0014_alter_edcpermissions_device_created_and_more.py +141 -0
- edc_randomization/model_mixins.py +9 -9
- edc_randomization/utils.py +2 -2
- edc_refusal/migrations/0001_initial.py +4 -4
- edc_refusal/migrations/0002_historicalsubjectrefusal.py +4 -4
- edc_refusal/migrations/0012_alter_historicalsubjectrefusal_comment_and_more.py +122 -0
- edc_refusal/migrations/0013_alter_historicalsubjectrefusal_report_datetime_and_more.py +28 -0
- edc_refusal/model_mixins.py +3 -3
- edc_registration/migrations/0002_auto_20161127_2226.py +3 -4
- edc_registration/migrations/0005_auto_20170111_1809.py +4 -2
- edc_registration/migrations/0016_historicalregisteredsubject.py +3 -2
- edc_registration/migrations/0017_auto_20190305_0123.py +5 -12
- edc_registration/migrations/0033_alter_historicalregisteredsubject_additional_key_and_more.py +302 -0
- edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py +2 -3
- edc_registration/models/registered_subject.py +27 -26
- edc_reportable/age_evaluator.py +4 -2
- edc_reportable/formula.py +5 -5
- edc_reportable/migrations/0001_initial.py +7 -7
- edc_reportable/migrations/0003_referencerangecollection_grade1_and_more.py +3 -3
- edc_reportable/migrations/0004_alter_referencerangecollection_grade3_and_more.py +5 -5
- edc_reportable/migrations/0006_alter_gradingdata_revision_and_more.py +5 -6
- edc_reportable/migrations/0007_alter_gradingdata_age_phrase_and_more.py +509 -0
- edc_reportable/models/normal_data.py +4 -5
- edc_reportable/models/reference_model_mixins.py +10 -11
- edc_reportable/models/reference_range_collection.py +12 -13
- edc_reportable/post_migrate_signals.py +1 -1
- edc_reportable/utils/convert_units.py +11 -45
- edc_reportable/utils/get_normal_data_or_raise.py +2 -2
- edc_reportable/utils/load_data.py +4 -4
- edc_reportable/utils/update_grading_data.py +5 -5
- edc_review_dashboard/migrations/0001_initial.py +3 -2
- edc_review_dashboard/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_screening/age_evaluator.py +3 -3
- edc_screening/migrations/0001_initial.py +3 -2
- edc_screening/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_screening/model_mixins/eligibility_model_mixin.py +3 -4
- edc_screening/model_mixins/screening_fields_model_mixin.py +6 -8
- edc_search/model_mixins.py +2 -3
- edc_search/search_slug.py +9 -8
- edc_search/updater.py +2 -2
- edc_sites/migrations/0007_edcpermissions.py +3 -2
- edc_sites/migrations/0010_alter_edcpermissions_device_created_and_more.py +69 -0
- edc_sites/model_mixins/site_model_mixin.py +2 -2
- edc_sites/site.py +5 -5
- edc_sites/system_checks.py +1 -1
- edc_subject_dashboard/migrations/0001_initial.py +3 -2
- edc_subject_dashboard/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_subject_dashboard/requisition_report.py +6 -4
- edc_subject_dashboard/requisition_verifier.py +6 -6
- edc_subject_dashboard/templatetags/edc_subject_dashboard_extras.py +2 -2
- edc_subject_dashboard/view_mixins/subject_visit_view_mixin.py +7 -8
- edc_subject_dashboard/view_utils/subject_consent_listboard_button.py +3 -2
- edc_subject_dashboard/view_utils/timepoint_status_button.py +2 -2
- edc_timepoint/model_mixins.py +22 -20
- edc_transfer/model_mixins.py +4 -4
- edc_transfer/modeladmin_mixins.py +1 -1
- edc_unblinding/migrations/0001_initial.py +13 -13
- edc_unblinding/migrations/0014_alter_historicalunblindingrequest_action_identifier_and_more.py +291 -0
- edc_unblinding/migrations/0015_alter_historicalunblindingrequest_report_datetime_and_more.py +45 -0
- edc_unblinding/models/unblinding_request.py +2 -2
- edc_unblinding/models/unblinding_review.py +3 -3
- edc_utils/age.py +10 -16
- edc_visit_schedule/migrations/0001_initial.py +3 -3
- edc_visit_schedule/migrations/0002_auto_20190305_0123.py +3 -6
- edc_visit_schedule/migrations/0003_historicalvisitschedule_visitschedule.py +5 -4
- edc_visit_schedule/migrations/0015_historicalonschedule_offschedule_onschedule.py +10 -10
- edc_visit_schedule/migrations/0019_alter_historicalonschedule_device_created_and_more.py +229 -0
- edc_visit_schedule/migrations/0020_alter_historicalonschedule_onschedule_datetime_and_more.py +65 -0
- edc_visit_schedule/model_mixins/off_schedule_model_mixin.py +5 -4
- edc_visit_schedule/model_mixins/on_schedule_model_mixin.py +5 -4
- edc_visit_schedule/model_mixins/visit_schedule/visit_code_fields_model_mixin.py +1 -1
- edc_visit_schedule/models/subject_schedule_history.py +6 -6
- edc_visit_schedule/schedule/visit_collection.py +1 -1
- edc_visit_schedule/subject_schedule.py +5 -4
- edc_visit_schedule/view_mixins.py +2 -3
- edc_visit_schedule/visit/visit.py +3 -2
- edc_visit_tracking/migrations/0004_subjectvisit_subjectvisitmissedreasons_extra_value_and_more.py +13 -13
- edc_visit_tracking/migrations/0009_alter_historicalsubjectvisit_comments_and_more.py +450 -0
- edc_visit_tracking/migrations/0010_alter_historicalsubjectvisit_report_datetime_and_more.py +68 -0
- edc_visit_tracking/model_mixins/base/visit_methods_model_mixin.py +3 -3
- edc_visit_tracking/model_mixins/crfs/visit_tracking_crf_model_mixin.py +2 -2
- edc_visit_tracking/model_mixins/requisitions/visit_tracking_requisition_model_mixin.py +2 -2
- edc_visit_tracking/model_mixins/subject_visit_missed_model_mixin.py +2 -2
- edc_visit_tracking/model_mixins/visit_model_mixin/caretaker_fields_mixin.py +2 -3
- edc_visit_tracking/model_mixins/visit_model_mixin/previous_visit_model_mixin.py +1 -1
- edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_fields_mixin.py +8 -11
- edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_mixin.py +1 -1
- edc_visit_tracking/models/signals.py +1 -1
- edc_visit_tracking/models/subject_visit.py +1 -1
- edc_vitals/calculators/bmi.py +7 -5
- edc_vitals/form_validators/blood_pressure_form_validator_mixin.py +3 -1
- edc_vitals/utils.py +1 -1
- {clinicedc-2.0.5.dist-info → clinicedc-2.0.7.dist-info}/WHEEL +0 -0
- {clinicedc-2.0.5.dist-info → clinicedc-2.0.7.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
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_sites", "0009_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
|
+
migrations.AlterField(
|
|
50
|
+
model_name="siteprofile",
|
|
51
|
+
name="country",
|
|
52
|
+
field=models.CharField(default="", max_length=250),
|
|
53
|
+
),
|
|
54
|
+
migrations.AlterField(
|
|
55
|
+
model_name="siteprofile",
|
|
56
|
+
name="country_code",
|
|
57
|
+
field=models.CharField(default="", max_length=15),
|
|
58
|
+
),
|
|
59
|
+
migrations.AlterField(
|
|
60
|
+
model_name="siteprofile",
|
|
61
|
+
name="languages",
|
|
62
|
+
field=models.TextField(default=""),
|
|
63
|
+
),
|
|
64
|
+
migrations.AlterField(
|
|
65
|
+
model_name="siteprofile",
|
|
66
|
+
name="title",
|
|
67
|
+
field=models.CharField(default="", max_length=250),
|
|
68
|
+
),
|
|
69
|
+
]
|
|
@@ -28,7 +28,7 @@ class SiteModelMixin(models.Model):
|
|
|
28
28
|
self.update_site_on_save(*args, **kwargs)
|
|
29
29
|
super().save(*args, **kwargs)
|
|
30
30
|
|
|
31
|
-
def update_site_on_save(self, *args, **kwargs) -> None:
|
|
31
|
+
def update_site_on_save(self, *args, **kwargs) -> None: # noqa: ARG002
|
|
32
32
|
if not self.id:
|
|
33
33
|
if not self.site_id and not self.site:
|
|
34
34
|
self.site = self.get_site_on_create()
|
|
@@ -59,7 +59,7 @@ class SiteModelMixin(models.Model):
|
|
|
59
59
|
"Exception raised when trying manager method `get_current()`. "
|
|
60
60
|
f"Sites registered with `sites` global are {site_ids}. "
|
|
61
61
|
f"settings.SITE_ID={settings.SITE_ID}. Got {e}."
|
|
62
|
-
)
|
|
62
|
+
) from e
|
|
63
63
|
return site_obj
|
|
64
64
|
|
|
65
65
|
def validate_site_against_current(self) -> None:
|
edc_sites/site.py
CHANGED
|
@@ -160,13 +160,13 @@ class Sites:
|
|
|
160
160
|
single_site = dataclasses.replace(single_site, domain=domain)
|
|
161
161
|
|
|
162
162
|
if single_site.site_id in self._registry:
|
|
163
|
-
raise AlreadyRegistered(f"Site already registered. Got `{single_site}`.")
|
|
163
|
+
raise AlreadyRegistered(f"Site already registered. Got `{single_site}`.")
|
|
164
164
|
if single_site.name in [s.name for s in self._registry.values()]:
|
|
165
|
-
raise AlreadyRegisteredName(
|
|
165
|
+
raise AlreadyRegisteredName(
|
|
166
166
|
f"Site with this name is already registered. Got `{single_site}`."
|
|
167
167
|
)
|
|
168
168
|
if single_site.domain in [s.domain for s in self._registry.values()]:
|
|
169
|
-
raise AlreadyRegisteredDomain(
|
|
169
|
+
raise AlreadyRegisteredDomain(
|
|
170
170
|
f"Site with this domain is already registered. Got `{single_site}`."
|
|
171
171
|
)
|
|
172
172
|
self._registry.update({single_site.site_id: single_site})
|
|
@@ -187,7 +187,7 @@ class Sites:
|
|
|
187
187
|
msg = "In fact, no sites have been registered!"
|
|
188
188
|
else:
|
|
189
189
|
msg = f"Expected one of {[s.site_id for s in self.all(aslist=True)]}."
|
|
190
|
-
raise SiteNotRegistered(
|
|
190
|
+
raise SiteNotRegistered(
|
|
191
191
|
f"Site not registered. {msg} See {self!r}. Got `{site_id}`."
|
|
192
192
|
)
|
|
193
193
|
return self._registry.get(site_id)
|
|
@@ -196,7 +196,7 @@ class Sites:
|
|
|
196
196
|
for single_site in self._registry.values():
|
|
197
197
|
if getattr(single_site, attrname) == value:
|
|
198
198
|
return single_site
|
|
199
|
-
raise SiteDoesNotExist(f"No site exists with `{attrname}`==`{value}`.")
|
|
199
|
+
raise SiteDoesNotExist(f"No site exists with `{attrname}`==`{value}`.")
|
|
200
200
|
|
|
201
201
|
def all(self, aslist: bool | None = None) -> dict[int, SingleSite] | list[SingleSite]:
|
|
202
202
|
if aslist:
|
edc_sites/system_checks.py
CHANGED
|
@@ -10,7 +10,7 @@ from edc_sites.site import sites as site_sites
|
|
|
10
10
|
from edc_sites.utils import get_site_model_cls
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def sites_check(app_configs, **kwargs):
|
|
13
|
+
def sites_check(app_configs, **kwargs):
|
|
14
14
|
errors = []
|
|
15
15
|
if "migrate" not in sys.argv and "makemigrations" not in sys.argv:
|
|
16
16
|
try:
|
|
@@ -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=
|
|
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=
|
|
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_subject_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,6 +1,7 @@
|
|
|
1
1
|
from tempfile import mkdtemp
|
|
2
2
|
|
|
3
3
|
from django.contrib import messages
|
|
4
|
+
from django.utils import timezone
|
|
4
5
|
from reportlab.graphics.barcode import code39
|
|
5
6
|
from reportlab.lib import colors
|
|
6
7
|
from reportlab.lib.units import cm, mm
|
|
@@ -11,7 +12,6 @@ from edc_identifier.utils import convert_to_human_readable
|
|
|
11
12
|
from edc_lab.model_mixins import RequisitionModelMixin
|
|
12
13
|
from edc_lab.models.manifest.shipper import Shipper
|
|
13
14
|
from edc_pdf_reports import Report
|
|
14
|
-
from edc_utils import get_utcnow
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class RequisitionReport(Report):
|
|
@@ -33,7 +33,7 @@ class RequisitionReport(Report):
|
|
|
33
33
|
self.consignee = consignee
|
|
34
34
|
self.contact_name = f"{self.user.first_name} {self.user.last_name}"
|
|
35
35
|
self.image_folder = mkdtemp()
|
|
36
|
-
self.timestamp =
|
|
36
|
+
self.timestamp = timezone.now().strftime("%Y%m%d%H%M%S")
|
|
37
37
|
self.report_filename = f"requisition_{self.timestamp}.pdf"
|
|
38
38
|
|
|
39
39
|
@property
|
|
@@ -60,7 +60,9 @@ class RequisitionReport(Report):
|
|
|
60
60
|
Paragraph("REFERENCE", self.styles["line_label"]),
|
|
61
61
|
],
|
|
62
62
|
[
|
|
63
|
-
Paragraph(
|
|
63
|
+
Paragraph(
|
|
64
|
+
timezone.now().strftime("%Y-%m-%d"), self.styles["line_data_largest"]
|
|
65
|
+
),
|
|
64
66
|
Paragraph(
|
|
65
67
|
convert_to_human_readable(self.timestamp),
|
|
66
68
|
self.styles["line_data_largest"],
|
|
@@ -173,7 +175,7 @@ class RequisitionReport(Report):
|
|
|
173
175
|
Paragraph(self.contact_name, self.styles["line_data_large"]),
|
|
174
176
|
"",
|
|
175
177
|
Paragraph(
|
|
176
|
-
|
|
178
|
+
timezone.now().strftime("%Y-%m-%d %H:%M"),
|
|
177
179
|
self.styles["line_data_large"],
|
|
178
180
|
),
|
|
179
181
|
],
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
|
|
1
3
|
from django.core.exceptions import ObjectDoesNotExist
|
|
4
|
+
from django.utils import timezone
|
|
2
5
|
|
|
3
6
|
from edc_appointment.models import Appointment
|
|
4
7
|
from edc_constants.constants import NO, YES
|
|
5
8
|
from edc_lab.constants import TUBE
|
|
6
9
|
from edc_lab.model_mixins import RequisitionModelMixin
|
|
7
|
-
from edc_utils import get_utcnow
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class RequisitionVerifier:
|
|
@@ -22,12 +24,12 @@ class RequisitionVerifier:
|
|
|
22
24
|
if self.requisition and self.requisition.is_drawn != NO:
|
|
23
25
|
# verification fields
|
|
24
26
|
self.requisition.clinic_verified = YES
|
|
25
|
-
self.requisition.clinic_verified_datetime =
|
|
27
|
+
self.requisition.clinic_verified_datetime = timezone.now()
|
|
26
28
|
# other fields for label printing
|
|
27
29
|
self.requisition.is_drawn = self.requisition.is_drawn or YES
|
|
28
30
|
self.requisition.item_count = self.requisition.item_count or 1
|
|
29
31
|
self.requisition.item_type = self.requisition.item_type or TUBE
|
|
30
|
-
self.requisition.drawn_datetime = self.requisition.drawn_datetime or
|
|
32
|
+
self.requisition.drawn_datetime = self.requisition.drawn_datetime or timezone.now()
|
|
31
33
|
self.requisition.save()
|
|
32
34
|
self.verified = self.requisition.clinic_verified
|
|
33
35
|
|
|
@@ -43,12 +45,10 @@ class RequisitionVerifier:
|
|
|
43
45
|
def requisition(self):
|
|
44
46
|
"""Returns a requisition model instance."""
|
|
45
47
|
if not self._requisition:
|
|
46
|
-
|
|
48
|
+
with contextlib.suppress(ObjectDoesNotExist):
|
|
47
49
|
self._requisition = self.requisition_model_cls.objects.get(
|
|
48
50
|
requisition_identifier=self.requisition_identifier.strip()
|
|
49
51
|
)
|
|
50
|
-
except ObjectDoesNotExist:
|
|
51
|
-
pass
|
|
52
52
|
return self._requisition
|
|
53
53
|
|
|
54
54
|
@property
|
|
@@ -8,6 +8,7 @@ from django import template
|
|
|
8
8
|
from django.apps import apps as django_apps
|
|
9
9
|
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
|
|
10
10
|
from django.urls import reverse
|
|
11
|
+
from django.utils import timezone
|
|
11
12
|
|
|
12
13
|
from edc_appointment.constants import (
|
|
13
14
|
CANCELLED_APPT,
|
|
@@ -26,7 +27,6 @@ from edc_appointment.view_utils import AppointmentButton
|
|
|
26
27
|
from edc_auth.constants import AUDITOR_ROLE
|
|
27
28
|
from edc_metadata import KEYED, REQUIRED
|
|
28
29
|
from edc_metadata.metadata_helper import MetadataHelper
|
|
29
|
-
from edc_utils import get_utcnow
|
|
30
30
|
from edc_view_utils import PrnButton, render_history_and_query_buttons
|
|
31
31
|
from edc_visit_tracking.view_utils import RelatedVisitButton
|
|
32
32
|
|
|
@@ -171,7 +171,7 @@ def render_crf_totals(appointment: Appointment = None) -> dict[str, bool | int]:
|
|
|
171
171
|
skipped = True
|
|
172
172
|
elif (
|
|
173
173
|
appointment.appt_status == NEW_APPT
|
|
174
|
-
and appointment.appt_datetime.date() <
|
|
174
|
+
and appointment.appt_datetime.date() < timezone.now().date()
|
|
175
175
|
):
|
|
176
176
|
overdue = True
|
|
177
177
|
else:
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import contextlib
|
|
3
4
|
from typing import TYPE_CHECKING, Any
|
|
4
5
|
|
|
5
6
|
from django.core.exceptions import ObjectDoesNotExist
|
|
7
|
+
from django.utils import timezone
|
|
6
8
|
|
|
7
|
-
from edc_utils import get_utcnow
|
|
8
9
|
from edc_visit_schedule.models import VisitSchedule
|
|
9
10
|
|
|
10
11
|
if TYPE_CHECKING:
|
|
@@ -46,8 +47,8 @@ class SubjectVisitViewMixin:
|
|
|
46
47
|
self._related_visit = self.appointment.related_visit
|
|
47
48
|
except AttributeError as e:
|
|
48
49
|
raise SubjectVisitViewMixinError(
|
|
49
|
-
"Visit model must have a OneToOne relation to appointment.
|
|
50
|
-
)
|
|
50
|
+
f"Visit model must have a OneToOne relation to appointment. Got {e}"
|
|
51
|
+
) from e
|
|
51
52
|
return self._related_visit
|
|
52
53
|
|
|
53
54
|
def get_visit_schedule(self) -> VisitSchedule | None:
|
|
@@ -60,10 +61,8 @@ class SubjectVisitViewMixin:
|
|
|
60
61
|
schedule_name=self.appointment.schedule_name,
|
|
61
62
|
visit_code=self.appointment.visit_code,
|
|
62
63
|
)
|
|
63
|
-
|
|
64
|
+
with contextlib.suppress(ObjectDoesNotExist):
|
|
64
65
|
visit_schedule = VisitSchedule.objects.get(**opts)
|
|
65
|
-
except ObjectDoesNotExist:
|
|
66
|
-
pass
|
|
67
66
|
return visit_schedule
|
|
68
67
|
|
|
69
68
|
@property
|
|
@@ -76,7 +75,7 @@ class SubjectVisitViewMixin:
|
|
|
76
75
|
try:
|
|
77
76
|
self._report_datetime = self.appointment.appt_datetime
|
|
78
77
|
except AttributeError:
|
|
79
|
-
self._report_datetime =
|
|
78
|
+
self._report_datetime = timezone.now()
|
|
80
79
|
return self._report_datetime
|
|
81
80
|
|
|
82
81
|
def has_appointment_attr_or_raise(self) -> None:
|
|
@@ -89,5 +88,5 @@ class SubjectVisitViewMixin:
|
|
|
89
88
|
if "appointment" in str(e):
|
|
90
89
|
raise SubjectVisitViewMixinError(
|
|
91
90
|
f"Mixin must be declared together with AppointmentViewMixin. Got {e}"
|
|
92
|
-
)
|
|
91
|
+
) from e
|
|
93
92
|
raise
|
|
@@ -5,10 +5,11 @@ from dataclasses import dataclass, field
|
|
|
5
5
|
from typing import TYPE_CHECKING, TypeVar
|
|
6
6
|
from uuid import UUID
|
|
7
7
|
|
|
8
|
+
from django.utils import timezone
|
|
9
|
+
|
|
8
10
|
from edc_consent import site_consents
|
|
9
11
|
from edc_pdutils.site import Site
|
|
10
12
|
from edc_protocol.research_protocol_config import ResearchProtocolConfig
|
|
11
|
-
from edc_utils import get_utcnow
|
|
12
13
|
from edc_view_utils import ModelButton
|
|
13
14
|
|
|
14
15
|
if TYPE_CHECKING:
|
|
@@ -42,7 +43,7 @@ class SubjectConsentListboardButton(ModelButton):
|
|
|
42
43
|
|
|
43
44
|
def __post_init__(self):
|
|
44
45
|
cdef = site_consents.get_consent_definition(
|
|
45
|
-
report_datetime=
|
|
46
|
+
report_datetime=timezone.now(),
|
|
46
47
|
screening_model=self.screening_obj._meta.label_lower,
|
|
47
48
|
)
|
|
48
49
|
self.model_cls = cdef.model_cls
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
4
|
from typing import TYPE_CHECKING, TypeVar
|
|
5
5
|
|
|
6
|
+
from django.utils import timezone
|
|
6
7
|
from django.utils.translation import gettext as _
|
|
7
8
|
|
|
8
9
|
from edc_appointment.constants import (
|
|
@@ -13,7 +14,6 @@ from edc_appointment.constants import (
|
|
|
13
14
|
SKIPPED_APPT,
|
|
14
15
|
)
|
|
15
16
|
from edc_appointment.view_utils import AppointmentButton
|
|
16
|
-
from edc_utils import get_utcnow
|
|
17
17
|
|
|
18
18
|
if TYPE_CHECKING:
|
|
19
19
|
from edc_visit_tracking.model_mixins import VisitModelMixin
|
|
@@ -79,7 +79,7 @@ class TimepointStatusButton(AppointmentButton):
|
|
|
79
79
|
elif self.model_obj.appt_status == INCOMPLETE_APPT:
|
|
80
80
|
color = self.colors[INCOMPLETE] # default / grey
|
|
81
81
|
elif self.model_obj.appt_status == NEW_APPT:
|
|
82
|
-
if self.model_obj.appt_datetime <=
|
|
82
|
+
if self.model_obj.appt_datetime <= timezone.now():
|
|
83
83
|
color = self.colors[NEW_LATE] # warning / orange
|
|
84
84
|
else:
|
|
85
85
|
color = self.colors[NEW]
|
edc_timepoint/model_mixins.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from django.apps import apps as django_apps
|
|
2
2
|
from django.core.exceptions import ImproperlyConfigured
|
|
3
3
|
from django.db import models
|
|
4
|
-
|
|
5
|
-
from edc_utils import get_utcnow
|
|
4
|
+
from django.utils import timezone
|
|
6
5
|
|
|
7
6
|
from .choices import TIMEPOINT_STATUS
|
|
8
7
|
from .constants import CLOSED_TIMEPOINT, FEEDBACK, OPEN_TIMEPOINT
|
|
@@ -12,10 +11,17 @@ from .timepoint_lookup import TimepointLookup
|
|
|
12
11
|
from .utils import get_enable_timepoint_checks
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
class UnableToCloseTimepoint(Exception):
|
|
14
|
+
class UnableToCloseTimepoint(Exception): # noqa: N818
|
|
16
15
|
pass
|
|
17
16
|
|
|
18
17
|
|
|
18
|
+
MODEL_NOT_REGISTERED = (
|
|
19
|
+
"Model not registered. Model '{label_lower}' is not registered "
|
|
20
|
+
"in AppConfig as a timepoint. "
|
|
21
|
+
"See AppConfig for 'edc_timepoint'."
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
19
25
|
class TimepointLookupModelMixin(models.Model):
|
|
20
26
|
"""Makes a model lookup the timepoint model instance on `save`
|
|
21
27
|
and check if it is a closed before allowing a create or update.
|
|
@@ -59,15 +65,14 @@ class TimepointModelMixin(models.Model):
|
|
|
59
65
|
timepoint_closed_datetime = models.DateTimeField(null=True, editable=False)
|
|
60
66
|
|
|
61
67
|
def save(self, *args, **kwargs):
|
|
62
|
-
if self.enabled_as_timepoint
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
)
|
|
70
|
-
self.timepoint_open_or_raise()
|
|
68
|
+
if self.enabled_as_timepoint and (
|
|
69
|
+
kwargs.get("update_fields") != ["timepoint_status"]
|
|
70
|
+
and kwargs.get("update_fields")
|
|
71
|
+
!= ["timepoint_opened_datetime", "timepoint_status"]
|
|
72
|
+
and kwargs.get("update_fields")
|
|
73
|
+
!= ["timepoint_closed_datetime", "timepoint_status"]
|
|
74
|
+
):
|
|
75
|
+
self.timepoint_open_or_raise()
|
|
71
76
|
super().save(*args, **kwargs)
|
|
72
77
|
|
|
73
78
|
def update_timepoint(self):
|
|
@@ -95,12 +100,10 @@ class TimepointModelMixin(models.Model):
|
|
|
95
100
|
app_config = django_apps.get_app_config("edc_timepoint")
|
|
96
101
|
try:
|
|
97
102
|
timepoint = app_config.timepoints.get(self._meta.label_lower)
|
|
98
|
-
except KeyError:
|
|
103
|
+
except KeyError as e:
|
|
99
104
|
raise TimepointConfigError(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
f"See AppConfig for 'edc_timepoint'."
|
|
103
|
-
)
|
|
105
|
+
MODEL_NOT_REGISTERED.format(label_lower=self._meta.label_lower)
|
|
106
|
+
) from e
|
|
104
107
|
if getattr(self, timepoint.status_field) != timepoint.closed_status:
|
|
105
108
|
self.timepoint_status = OPEN_TIMEPOINT
|
|
106
109
|
self.timepoint_closed_datetime = None
|
|
@@ -122,7 +125,7 @@ class TimepointModelMixin(models.Model):
|
|
|
122
125
|
status = getattr(self, timepoint.status_field)
|
|
123
126
|
if status == timepoint.closed_status:
|
|
124
127
|
self.timepoint_status = CLOSED_TIMEPOINT
|
|
125
|
-
self.timepoint_closed_datetime =
|
|
128
|
+
self.timepoint_closed_datetime = timezone.now()
|
|
126
129
|
self.save(update_fields=["timepoint_status"])
|
|
127
130
|
else:
|
|
128
131
|
raise UnableToCloseTimepoint(
|
|
@@ -146,8 +149,7 @@ class TimepointModelMixin(models.Model):
|
|
|
146
149
|
return '<span style="color:red;">Closed</span>'
|
|
147
150
|
if self.timepoint_status == FEEDBACK:
|
|
148
151
|
return '<span style="color:orange;">Feedback</span>'
|
|
149
|
-
|
|
150
|
-
# timepoint.allow_tags = True
|
|
152
|
+
return None
|
|
151
153
|
|
|
152
154
|
class Meta:
|
|
153
155
|
abstract = True
|
edc_transfer/model_mixins.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from django.conf import settings
|
|
2
2
|
from django.db import models
|
|
3
|
+
from django.utils import timezone
|
|
3
4
|
from django_crypto_fields.fields import EncryptedTextField
|
|
4
5
|
|
|
5
6
|
from edc_action_item.models import ActionModelMixin
|
|
@@ -8,7 +9,6 @@ from edc_identifier.model_mixins import UniqueSubjectIdentifierFieldMixin
|
|
|
8
9
|
from edc_model import models as edc_models
|
|
9
10
|
from edc_sites.model_mixins import SiteModelMixin
|
|
10
11
|
from edc_utils import convert_php_dateformat
|
|
11
|
-
from edc_utils.date import get_utcnow
|
|
12
12
|
|
|
13
13
|
from .choices import TRANSFER_INITIATORS
|
|
14
14
|
from .constants import SUBJECT_TRANSFER_ACTION
|
|
@@ -23,10 +23,10 @@ class SubjectTransferModelMixin(
|
|
|
23
23
|
action_name = SUBJECT_TRANSFER_ACTION
|
|
24
24
|
|
|
25
25
|
report_datetime = models.DateTimeField(
|
|
26
|
-
verbose_name="Report Date and Time", default=
|
|
26
|
+
verbose_name="Report Date and Time", default=timezone.now
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
-
transfer_date = models.DateField(verbose_name="Transfer date", default=
|
|
29
|
+
transfer_date = models.DateField(verbose_name="Transfer date", default=timezone.now)
|
|
30
30
|
|
|
31
31
|
initiated_by = models.CharField(
|
|
32
32
|
verbose_name="Who initiated the transfer request",
|
|
@@ -53,7 +53,7 @@ class SubjectTransferModelMixin(
|
|
|
53
53
|
)
|
|
54
54
|
|
|
55
55
|
may_contact = models.CharField(
|
|
56
|
-
verbose_name=
|
|
56
|
+
verbose_name="Is the participant willing to be contacted at the end of the study?",
|
|
57
57
|
max_length=15,
|
|
58
58
|
choices=YES_NO,
|
|
59
59
|
)
|
|
@@ -17,7 +17,7 @@ from django.db import migrations, models
|
|
|
17
17
|
|
|
18
18
|
import edc_identifier.managers
|
|
19
19
|
import edc_sites.models
|
|
20
|
-
import
|
|
20
|
+
import django.utils.timezone
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class Migration(migrations.Migration):
|
|
@@ -81,14 +81,14 @@ class Migration(migrations.Migration):
|
|
|
81
81
|
"created",
|
|
82
82
|
models.DateTimeField(
|
|
83
83
|
blank=True,
|
|
84
|
-
default=
|
|
84
|
+
default=django.utils.timezone.now,
|
|
85
85
|
),
|
|
86
86
|
),
|
|
87
87
|
(
|
|
88
88
|
"modified",
|
|
89
89
|
models.DateTimeField(
|
|
90
90
|
blank=True,
|
|
91
|
-
default=
|
|
91
|
+
default=django.utils.timezone.now,
|
|
92
92
|
),
|
|
93
93
|
),
|
|
94
94
|
(
|
|
@@ -163,7 +163,7 @@ class Migration(migrations.Migration):
|
|
|
163
163
|
(
|
|
164
164
|
"report_datetime",
|
|
165
165
|
models.DateTimeField(
|
|
166
|
-
default=
|
|
166
|
+
default=django.utils.timezone.now,
|
|
167
167
|
verbose_name="Report Date and Time",
|
|
168
168
|
),
|
|
169
169
|
),
|
|
@@ -257,14 +257,14 @@ class Migration(migrations.Migration):
|
|
|
257
257
|
"created",
|
|
258
258
|
models.DateTimeField(
|
|
259
259
|
blank=True,
|
|
260
|
-
default=
|
|
260
|
+
default=django.utils.timezone.now,
|
|
261
261
|
),
|
|
262
262
|
),
|
|
263
263
|
(
|
|
264
264
|
"modified",
|
|
265
265
|
models.DateTimeField(
|
|
266
266
|
blank=True,
|
|
267
|
-
default=
|
|
267
|
+
default=django.utils.timezone.now,
|
|
268
268
|
),
|
|
269
269
|
),
|
|
270
270
|
(
|
|
@@ -339,7 +339,7 @@ class Migration(migrations.Migration):
|
|
|
339
339
|
(
|
|
340
340
|
"report_datetime",
|
|
341
341
|
models.DateTimeField(
|
|
342
|
-
default=
|
|
342
|
+
default=django.utils.timezone.now,
|
|
343
343
|
verbose_name="Report Date and Time",
|
|
344
344
|
),
|
|
345
345
|
),
|
|
@@ -452,14 +452,14 @@ class Migration(migrations.Migration):
|
|
|
452
452
|
"created",
|
|
453
453
|
models.DateTimeField(
|
|
454
454
|
blank=True,
|
|
455
|
-
default=
|
|
455
|
+
default=django.utils.timezone.now,
|
|
456
456
|
),
|
|
457
457
|
),
|
|
458
458
|
(
|
|
459
459
|
"modified",
|
|
460
460
|
models.DateTimeField(
|
|
461
461
|
blank=True,
|
|
462
|
-
default=
|
|
462
|
+
default=django.utils.timezone.now,
|
|
463
463
|
),
|
|
464
464
|
),
|
|
465
465
|
(
|
|
@@ -542,7 +542,7 @@ class Migration(migrations.Migration):
|
|
|
542
542
|
(
|
|
543
543
|
"report_datetime",
|
|
544
544
|
models.DateTimeField(
|
|
545
|
-
default=
|
|
545
|
+
default=django.utils.timezone.now,
|
|
546
546
|
verbose_name="Report Date and Time",
|
|
547
547
|
),
|
|
548
548
|
),
|
|
@@ -661,14 +661,14 @@ class Migration(migrations.Migration):
|
|
|
661
661
|
"created",
|
|
662
662
|
models.DateTimeField(
|
|
663
663
|
blank=True,
|
|
664
|
-
default=
|
|
664
|
+
default=django.utils.timezone.now,
|
|
665
665
|
),
|
|
666
666
|
),
|
|
667
667
|
(
|
|
668
668
|
"modified",
|
|
669
669
|
models.DateTimeField(
|
|
670
670
|
blank=True,
|
|
671
|
-
default=
|
|
671
|
+
default=django.utils.timezone.now,
|
|
672
672
|
),
|
|
673
673
|
),
|
|
674
674
|
(
|
|
@@ -751,7 +751,7 @@ class Migration(migrations.Migration):
|
|
|
751
751
|
(
|
|
752
752
|
"report_datetime",
|
|
753
753
|
models.DateTimeField(
|
|
754
|
-
default=
|
|
754
|
+
default=django.utils.timezone.now,
|
|
755
755
|
verbose_name="Report Date and Time",
|
|
756
756
|
),
|
|
757
757
|
),
|