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
|
@@ -20,7 +20,6 @@ if TYPE_CHECKING:
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class ReferenceRangeCollection(BaseUuidModel):
|
|
23
|
-
|
|
24
23
|
name = models.CharField(max_length=50, unique=True)
|
|
25
24
|
|
|
26
25
|
grade1 = models.BooleanField(default=False)
|
|
@@ -60,13 +59,13 @@ class ReferenceRangeCollection(BaseUuidModel):
|
|
|
60
59
|
|
|
61
60
|
def get_grade(
|
|
62
61
|
self,
|
|
63
|
-
value: float | int = None,
|
|
64
|
-
label: str = None,
|
|
65
|
-
units: str = None,
|
|
62
|
+
value: float | int | None = None,
|
|
63
|
+
label: str | None = None,
|
|
64
|
+
units: str | None = None,
|
|
66
65
|
subject_identifier: str | None = None,
|
|
67
|
-
report_datetime: datetime = None,
|
|
68
|
-
gender: str = None,
|
|
69
|
-
dob: date = None,
|
|
66
|
+
report_datetime: datetime | None = None,
|
|
67
|
+
gender: str | None = None,
|
|
68
|
+
dob: date | None = None,
|
|
70
69
|
age_units: str | None = None,
|
|
71
70
|
site: Site | None = None,
|
|
72
71
|
) -> tuple[GradingData | None, str | None]:
|
|
@@ -89,13 +88,13 @@ class ReferenceRangeCollection(BaseUuidModel):
|
|
|
89
88
|
|
|
90
89
|
def is_normal(
|
|
91
90
|
self,
|
|
92
|
-
value: float | int = None,
|
|
93
|
-
label: str = None,
|
|
94
|
-
units: str = None,
|
|
91
|
+
value: float | int | None = None,
|
|
92
|
+
label: str | None = None,
|
|
93
|
+
units: str | None = None,
|
|
95
94
|
subject_identifier: str | None = None,
|
|
96
|
-
report_datetime: datetime = None,
|
|
97
|
-
gender: str = None,
|
|
98
|
-
dob: date = None,
|
|
95
|
+
report_datetime: datetime | None = None,
|
|
96
|
+
gender: str | None = None,
|
|
97
|
+
dob: date | None = None,
|
|
99
98
|
age_units: str | None = None,
|
|
100
99
|
site: Site | None = None,
|
|
101
100
|
) -> tuple[bool, NormalData]:
|
|
@@ -19,7 +19,7 @@ def load_mw():
|
|
|
19
19
|
model_cls.objects.get_or_create(label=label, mw=mw)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
def post_migrate_load_reference_ranges(sender=None, **kwargs):
|
|
22
|
+
def post_migrate_load_reference_ranges(sender=None, **kwargs):
|
|
23
23
|
sys.stdout.write(style.MIGRATE_HEADING("Loading reference ranges (reportables):\n"))
|
|
24
24
|
load_mw()
|
|
25
25
|
load_all_reference_ranges()
|
|
@@ -20,18 +20,16 @@ __all__ = ["convert_units"]
|
|
|
20
20
|
def get_mw(label):
|
|
21
21
|
try:
|
|
22
22
|
molecular_weight = molecular_weight_model_cls().objects.get(label=label)
|
|
23
|
-
except ObjectDoesNotExist:
|
|
23
|
+
except ObjectDoesNotExist as e:
|
|
24
24
|
raise ConversionNotHandled(
|
|
25
25
|
f"Conversion not handled. Molecular weight not found for {label}."
|
|
26
|
-
)
|
|
26
|
+
) from e
|
|
27
27
|
else:
|
|
28
28
|
mw = molecular_weight.mw
|
|
29
29
|
return mw
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def micromoles_per_liter_to(
|
|
33
|
-
*, label: str = None, value: float | int = None, units_to: str = None
|
|
34
|
-
) -> dict:
|
|
32
|
+
def micromoles_per_liter_to(*, label: str, value: float | int, units_to: str) -> dict:
|
|
35
33
|
if units_to == MICROMOLES_PER_LITER:
|
|
36
34
|
return {MICROMOLES_PER_LITER: float(value)}
|
|
37
35
|
if units_to == MILLIMOLES_PER_LITER:
|
|
@@ -44,8 +42,8 @@ def micromoles_per_liter_to(
|
|
|
44
42
|
|
|
45
43
|
|
|
46
44
|
def milligrams_per_deciliter_to(
|
|
47
|
-
*, label: str
|
|
48
|
-
) -> dict[str
|
|
45
|
+
*, label: str, value: float | int, units_to: str
|
|
46
|
+
) -> dict[str, float]:
|
|
49
47
|
if units_to == MILLIGRAMS_PER_DECILITER:
|
|
50
48
|
return {MILLIGRAMS_PER_DECILITER: float(value)}
|
|
51
49
|
if units_to == MILLIMOLES_PER_LITER:
|
|
@@ -63,10 +61,10 @@ class UnitsConverter:
|
|
|
63
61
|
def __init__(
|
|
64
62
|
self,
|
|
65
63
|
*,
|
|
66
|
-
label: str
|
|
67
|
-
value: int | float
|
|
68
|
-
units_from: str
|
|
69
|
-
units_to: str
|
|
64
|
+
label: str,
|
|
65
|
+
value: int | float,
|
|
66
|
+
units_from: str,
|
|
67
|
+
units_to: str,
|
|
70
68
|
places: int | None = None,
|
|
71
69
|
):
|
|
72
70
|
self.label = label
|
|
@@ -97,7 +95,7 @@ class UnitsConverter:
|
|
|
97
95
|
f"Conversion not handled. Tried {self.label} from {self.units_from} "
|
|
98
96
|
f"to {self.units_to}. "
|
|
99
97
|
f"Got {e} when rounding {converted_value} to {self.places} places."
|
|
100
|
-
)
|
|
98
|
+
) from e
|
|
101
99
|
return converted_value
|
|
102
100
|
|
|
103
101
|
def from_milligrams_per_deciliter(self) -> float | int:
|
|
@@ -106,14 +104,6 @@ class UnitsConverter:
|
|
|
106
104
|
label=self.label, value=float(self.value), units_to=self.units_to
|
|
107
105
|
)[self.units_to]
|
|
108
106
|
return self.value
|
|
109
|
-
# converted_value = None
|
|
110
|
-
# if self.units_to == MILLIMOLES_PER_LITER:
|
|
111
|
-
# converted_value = (float(self.value) * 10.00) / self.get_mw()
|
|
112
|
-
# elif self.units_to == MICROMOLES_PER_LITER:
|
|
113
|
-
# converted_value = (float(self.value) * 10.00**3) / self.get_mw()
|
|
114
|
-
# elif self.units_to == GRAMS_PER_LITER:
|
|
115
|
-
# converted_value = float(self.value) / 100.00
|
|
116
|
-
# return converted_value
|
|
117
107
|
|
|
118
108
|
def from_grams_per_liter(self) -> float | int:
|
|
119
109
|
if self.units_to != GRAMS_PER_LITER:
|
|
@@ -123,14 +113,6 @@ class UnitsConverter:
|
|
|
123
113
|
units_to=self.units_to,
|
|
124
114
|
)[self.units_to]
|
|
125
115
|
return self.value
|
|
126
|
-
# converted_value = None
|
|
127
|
-
# if self.units_to == MILLIMOLES_PER_LITER:
|
|
128
|
-
# converted_value = (self.value * 1000.00) / self.get_mw()
|
|
129
|
-
# elif self.units_to == MICROMOLES_PER_LITER:
|
|
130
|
-
# converted_value = (self.value * 10.00**6) / self.get_mw()
|
|
131
|
-
# elif self.units_to == MILLIGRAMS_PER_DECILITER:
|
|
132
|
-
# converted_value = float(self.value) * 100.00
|
|
133
|
-
# return converted_value
|
|
134
116
|
|
|
135
117
|
def from_millimoles_per_liter(self) -> float | int:
|
|
136
118
|
if self.units_to != MILLIMOLES_PER_LITER:
|
|
@@ -138,14 +120,6 @@ class UnitsConverter:
|
|
|
138
120
|
label=self.label, value=self.value / 1000, units_to=self.units_to
|
|
139
121
|
)[self.units_to]
|
|
140
122
|
return self.value
|
|
141
|
-
# converted_value = None
|
|
142
|
-
# if self.units_to == MICROMOLES_PER_LITER:
|
|
143
|
-
# converted_value = self.value * 1000.00
|
|
144
|
-
# elif self.units_to == GRAMS_PER_LITER:
|
|
145
|
-
# converted_value = (self.value * self.get_mw()) / 1000.00
|
|
146
|
-
# elif self.units_to == MILLIGRAMS_PER_DECILITER:
|
|
147
|
-
# converted_value = (self.value * self.get_mw()) / 10.00
|
|
148
|
-
# return converted_value
|
|
149
123
|
|
|
150
124
|
def from_micromoles_per_liter(self):
|
|
151
125
|
if self.units_to != MICROMOLES_PER_LITER:
|
|
@@ -153,14 +127,6 @@ class UnitsConverter:
|
|
|
153
127
|
label=self.label, value=self.value, units_to=self.units_to
|
|
154
128
|
)[self.units_to]
|
|
155
129
|
return self.value
|
|
156
|
-
# converted_value = None
|
|
157
|
-
# if self.units_to == MILLIMOLES_PER_LITER:
|
|
158
|
-
# converted_value = self.value / 1000.00
|
|
159
|
-
# elif self.units_to == GRAMS_PER_LITER:
|
|
160
|
-
# converted_value = (self.value * self.get_mw()) / 10**6
|
|
161
|
-
# elif self.units_to == MILLIGRAMS_PER_DECILITER:
|
|
162
|
-
# converted_value = (self.value * self.get_mw()) / 10**4
|
|
163
|
-
# return converted_value
|
|
164
130
|
|
|
165
131
|
def get_converted_value(self) -> int | float:
|
|
166
132
|
converted_value = None
|
|
@@ -182,7 +148,7 @@ class UnitsConverter:
|
|
|
182
148
|
|
|
183
149
|
def convert_units(
|
|
184
150
|
*,
|
|
185
|
-
label: str = None,
|
|
151
|
+
label: str | None = None,
|
|
186
152
|
value: int | float | None = None,
|
|
187
153
|
units_from: str | None = None,
|
|
188
154
|
units_to: str | None = None,
|
|
@@ -5,10 +5,10 @@ from typing import TYPE_CHECKING
|
|
|
5
5
|
|
|
6
6
|
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
|
|
7
7
|
from django.db.models import Q
|
|
8
|
+
from django.utils import timezone
|
|
8
9
|
|
|
9
10
|
from edc_model_to_dataframe.constants import SYSTEM_COLUMNS
|
|
10
11
|
from edc_utils import age as get_age
|
|
11
|
-
from edc_utils import get_utcnow
|
|
12
12
|
|
|
13
13
|
from ..exceptions import NotEvaluated
|
|
14
14
|
from .convert_units import convert_units
|
|
@@ -135,7 +135,7 @@ def create_obj_for_new_units_or_raise(
|
|
|
135
135
|
)
|
|
136
136
|
opts["units"] = units
|
|
137
137
|
opts["auto_created"] = True
|
|
138
|
-
opts["created"] =
|
|
138
|
+
opts["created"] = timezone.now()
|
|
139
139
|
opts["modified"] = opts["created"]
|
|
140
140
|
break
|
|
141
141
|
if opts:
|
|
@@ -58,10 +58,10 @@ def load_all_reference_ranges() -> None:
|
|
|
58
58
|
|
|
59
59
|
def load_reference_ranges(
|
|
60
60
|
collection_name: str,
|
|
61
|
-
normal_data: dict[str, list[Formula]]
|
|
62
|
-
grading_data: dict[str, list[Formula]]
|
|
63
|
-
reportable_grades: list[int]
|
|
64
|
-
reportable_grades_exceptions: dict[str, list[int]] = None,
|
|
61
|
+
normal_data: dict[str, list[Formula]],
|
|
62
|
+
grading_data: dict[str, list[Formula]],
|
|
63
|
+
reportable_grades: list[int],
|
|
64
|
+
reportable_grades_exceptions: dict[str, list[int]] | None = None,
|
|
65
65
|
keep_existing: bool | None = None,
|
|
66
66
|
create_missing_normal: bool | None = None,
|
|
67
67
|
) -> ReferenceRangeCollection:
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import sys
|
|
3
4
|
from typing import TYPE_CHECKING
|
|
4
5
|
|
|
5
6
|
from dateutil.relativedelta import relativedelta
|
|
6
7
|
from django.core.exceptions import ObjectDoesNotExist
|
|
7
|
-
|
|
8
|
-
from edc_utils import get_utcnow
|
|
8
|
+
from django.utils import timezone
|
|
9
9
|
|
|
10
10
|
from ..exceptions import NotEvaluated
|
|
11
11
|
from ..formula import Formula
|
|
@@ -55,7 +55,7 @@ def update_grading_data(
|
|
|
55
55
|
value=value,
|
|
56
56
|
units=formula_opts.get("units"),
|
|
57
57
|
gender=gender,
|
|
58
|
-
dob=
|
|
58
|
+
dob=timezone.now()
|
|
59
59
|
- relativedelta(
|
|
60
60
|
**{
|
|
61
61
|
age_opts.get("age_units"): age_opts.get(
|
|
@@ -63,12 +63,12 @@ def update_grading_data(
|
|
|
63
63
|
)
|
|
64
64
|
}
|
|
65
65
|
),
|
|
66
|
-
report_datetime=
|
|
66
|
+
report_datetime=timezone.now(),
|
|
67
67
|
age_units=age_opts.get("age_units"),
|
|
68
68
|
create_missing_normal=create_missing_normal,
|
|
69
69
|
)
|
|
70
70
|
except NotEvaluated as e:
|
|
71
|
-
|
|
71
|
+
sys.stdout.write(f"{e}\n")
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
def get_reportable_grades(
|
|
@@ -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_review_dashboard", "0005_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
|
+
]
|
edc_screening/age_evaluator.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from dateutil.relativedelta import relativedelta
|
|
2
|
+
from django.utils import timezone
|
|
2
3
|
from django.utils.timezone import localtime
|
|
3
4
|
|
|
4
5
|
from edc_reportable.age_evaluator import AgeEvaluator as ReportableAgeEvaluator
|
|
5
6
|
from edc_reportable.exceptions import ValueBoundryError
|
|
6
|
-
from edc_utils.date import get_utcnow
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class AgeEvaluator(ReportableAgeEvaluator):
|
|
@@ -27,9 +27,9 @@ class AgeEvaluator(ReportableAgeEvaluator):
|
|
|
27
27
|
|
|
28
28
|
def in_bounds_or_raise(self, age: int = None, **kwargs):
|
|
29
29
|
self.reasons_ineligible = None
|
|
30
|
-
dob = localtime(
|
|
30
|
+
dob = localtime(timezone.now() - relativedelta(years=age)).date()
|
|
31
31
|
age_units = "years"
|
|
32
|
-
report_datetime = localtime(
|
|
32
|
+
report_datetime = localtime(timezone.now())
|
|
33
33
|
return super().in_bounds_or_raise(
|
|
34
34
|
dob=dob, report_datetime=report_datetime, age_units=age_units
|
|
35
35
|
)
|
|
@@ -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_screening", "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,5 @@
|
|
|
1
1
|
from django.db import models
|
|
2
|
-
|
|
3
|
-
from edc_utils import get_utcnow
|
|
2
|
+
from django.utils import timezone
|
|
4
3
|
|
|
5
4
|
from ..screening_eligibility import ScreeningEligibility
|
|
6
5
|
|
|
@@ -9,7 +8,7 @@ class EligibilityFieldsModelMixin(models.Model):
|
|
|
9
8
|
eligible = models.BooleanField(default=False)
|
|
10
9
|
|
|
11
10
|
reasons_ineligible = models.TextField(
|
|
12
|
-
verbose_name="Reason not eligible", max_length=150,
|
|
11
|
+
verbose_name="Reason not eligible", max_length=150, default=""
|
|
13
12
|
)
|
|
14
13
|
|
|
15
14
|
eligibility_datetime = models.DateTimeField(
|
|
@@ -52,7 +51,7 @@ class EligibilityModelMixin(EligibilityFieldsModelMixin, models.Model):
|
|
|
52
51
|
self.screening_identifier = self.identifier_cls().identifier
|
|
53
52
|
if self.eligible:
|
|
54
53
|
self.eligibility_datetime = self.get_report_datetime_for_eligibility_datetime()
|
|
55
|
-
self.real_eligibility_datetime =
|
|
54
|
+
self.real_eligibility_datetime = timezone.now()
|
|
56
55
|
else:
|
|
57
56
|
self.eligibility_datetime = None
|
|
58
57
|
self.real_eligibility_datetime = None
|
|
@@ -8,6 +8,7 @@ from django.core.validators import (
|
|
|
8
8
|
RegexValidator,
|
|
9
9
|
)
|
|
10
10
|
from django.db import models
|
|
11
|
+
from django.utils import timezone
|
|
11
12
|
from django_crypto_fields.fields import EncryptedCharField
|
|
12
13
|
|
|
13
14
|
from edc_constants.choices import GENDER, YES_NO, YES_NO_NA
|
|
@@ -15,7 +16,6 @@ from edc_constants.constants import NO, NOT_APPLICABLE
|
|
|
15
16
|
from edc_model.validators import datetime_not_future
|
|
16
17
|
from edc_protocol.validators import datetime_not_before_study_start
|
|
17
18
|
from edc_sites.model_mixins import SiteModelMixin
|
|
18
|
-
from edc_utils.date import get_utcnow
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class ScreeningFieldsModeMixin(SiteModelMixin, models.Model):
|
|
@@ -34,7 +34,7 @@ class ScreeningFieldsModeMixin(SiteModelMixin, models.Model):
|
|
|
34
34
|
report_datetime = models.DateTimeField(
|
|
35
35
|
verbose_name="Report Date and Time",
|
|
36
36
|
validators=[datetime_not_before_study_start, datetime_not_future],
|
|
37
|
-
default=
|
|
37
|
+
default=timezone.now,
|
|
38
38
|
help_text="Date and time of report.",
|
|
39
39
|
)
|
|
40
40
|
|
|
@@ -54,7 +54,7 @@ class ScreeningFieldsModeMixin(SiteModelMixin, models.Model):
|
|
|
54
54
|
validators=[MinValueValidator(0), MaxValueValidator(110)]
|
|
55
55
|
)
|
|
56
56
|
|
|
57
|
-
ethnicity = models.CharField(max_length=25,
|
|
57
|
+
ethnicity = models.CharField(max_length=25, default="", blank=True)
|
|
58
58
|
|
|
59
59
|
consent_ability = models.CharField(
|
|
60
60
|
verbose_name="Participant or legal guardian/representative able and "
|
|
@@ -65,8 +65,7 @@ class ScreeningFieldsModeMixin(SiteModelMixin, models.Model):
|
|
|
65
65
|
|
|
66
66
|
unsuitable_for_study = models.CharField(
|
|
67
67
|
verbose_name=(
|
|
68
|
-
"Is there any other reason the patient is "
|
|
69
|
-
"deemed to not be suitable for the study?"
|
|
68
|
+
"Is there any other reason the patient is deemed to not be suitable for the study?"
|
|
70
69
|
),
|
|
71
70
|
max_length=5,
|
|
72
71
|
choices=YES_NO,
|
|
@@ -77,14 +76,13 @@ class ScreeningFieldsModeMixin(SiteModelMixin, models.Model):
|
|
|
77
76
|
reasons_unsuitable = models.TextField(
|
|
78
77
|
verbose_name="Reason not suitable for the study",
|
|
79
78
|
max_length=150,
|
|
80
|
-
|
|
79
|
+
default="",
|
|
81
80
|
blank=True,
|
|
82
81
|
)
|
|
83
82
|
|
|
84
83
|
unsuitable_agreed = models.CharField(
|
|
85
84
|
verbose_name=(
|
|
86
|
-
"Does the study coordinator agree that the patient "
|
|
87
|
-
"is not suitable for the study?"
|
|
85
|
+
"Does the study coordinator agree that the patient is not suitable for the study?"
|
|
88
86
|
),
|
|
89
87
|
max_length=5,
|
|
90
88
|
choices=YES_NO_NA,
|
edc_search/model_mixins.py
CHANGED
|
@@ -20,13 +20,12 @@ class SearchSlugModelMixin(models.Model):
|
|
|
20
20
|
search_slug_warning = None
|
|
21
21
|
search_slug_updater_cls = SearchSlugUpdater
|
|
22
22
|
|
|
23
|
-
def get_search_slug_fields(self) ->
|
|
24
|
-
return
|
|
23
|
+
def get_search_slug_fields(self) -> tuple[str] | None:
|
|
24
|
+
return None
|
|
25
25
|
|
|
26
26
|
slug = models.CharField(
|
|
27
27
|
max_length=250,
|
|
28
28
|
default="",
|
|
29
|
-
null=True,
|
|
30
29
|
editable=False,
|
|
31
30
|
db_index=True,
|
|
32
31
|
help_text="a field used for quick search",
|
edc_search/search_slug.py
CHANGED
|
@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
|
|
|
6
6
|
from django.apps import apps as django_apps
|
|
7
7
|
from django.core.management.color import color_style
|
|
8
8
|
from django.utils.text import slugify
|
|
9
|
+
from django_crypto_fields.fields import BaseField
|
|
9
10
|
|
|
10
11
|
from .constants import SEARCH_SLUG_SEP
|
|
11
12
|
|
|
@@ -20,7 +21,9 @@ if TYPE_CHECKING:
|
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class SearchSlug:
|
|
23
|
-
def __init__(
|
|
24
|
+
def __init__(
|
|
25
|
+
self, obj: Model | SearchSlugModelMixin = None, fields: tuple[str] | None = None
|
|
26
|
+
):
|
|
24
27
|
self.warning = None
|
|
25
28
|
self.slug = ""
|
|
26
29
|
self.model_cls = None
|
|
@@ -41,10 +44,8 @@ class SearchSlug:
|
|
|
41
44
|
sys.stdout.write(style.WARNING(self.warning))
|
|
42
45
|
self.slug = slug[:250]
|
|
43
46
|
|
|
44
|
-
def get_safe_fields(self, fields):
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
]
|
|
50
|
-
return [f for f in fields if f not in encrypted_fields]
|
|
47
|
+
def get_safe_fields(self, fields) -> tuple[str]:
|
|
48
|
+
encrypted_fields = tuple(
|
|
49
|
+
[fld.name for fld in self.model_cls._meta.fields if isinstance(fld, BaseField)]
|
|
50
|
+
)
|
|
51
|
+
return tuple([f for f in fields if f not in encrypted_fields])
|
edc_search/updater.py
CHANGED
|
@@ -13,14 +13,14 @@ if TYPE_CHECKING:
|
|
|
13
13
|
pass
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
class SearchSlugDuplicateFields(Exception):
|
|
16
|
+
class SearchSlugDuplicateFields(Exception): # noqa: N818
|
|
17
17
|
pass
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class SearchSlugUpdater:
|
|
21
21
|
search_slug_cls = SearchSlug
|
|
22
22
|
|
|
23
|
-
def __init__(self, fields:
|
|
23
|
+
def __init__(self, fields: tuple[str], model_obj: Model | SearchSlugModelMixin = None):
|
|
24
24
|
if len(fields) > len(list(set(fields))):
|
|
25
25
|
raise SearchSlugDuplicateFields(
|
|
26
26
|
f"Duplicate search slug fields detected. Got {fields}. See {self!r}"
|
|
@@ -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
|
(
|