clinicedc 2.0.6__py3-none-any.whl → 2.0.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of clinicedc might be problematic. Click here for more details.
- {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/METADATA +2 -2
- {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/RECORD +489 -441
- {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/WHEEL +1 -1
- edc_action_item/action.py +1 -1
- edc_action_item/action_item_notification.py +2 -2
- edc_action_item/auths.py +37 -32
- 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 +5 -6
- edc_action_item/models/reference.py +2 -2
- edc_action_item/models/signals.py +22 -23
- edc_action_item/post_migrate_signals.py +1 -1
- edc_action_item/send_email.py +0 -85
- edc_action_item/site_action_items.py +5 -9
- edc_action_item/utils.py +3 -3
- edc_adherence/migrations/0005_alter_nonadherencereasons_extra_value_and_more.py +36 -0
- edc_adherence/model_mixins.py +1 -1
- edc_adverse_event/auths.py +55 -51
- 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/ae_tmg/ae_tmg_methods_model_mixin.py +2 -4
- 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/auths.py +14 -10
- edc_appointment/creators/appointment_creator.py +1 -1
- edc_appointment/creators/appointments_creator.py +1 -1
- 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/appointment_methods_model_mixin.py +2 -3
- edc_appointment/model_mixins/appointment_model_mixin.py +31 -28
- edc_appointment/model_mixins/window_period_model_mixin.py +6 -7
- edc_appointment/models/appointment.py +1 -1
- edc_appointment/models/signals.py +44 -35
- edc_appointment/utils.py +19 -24
- edc_appointment/view_utils/appointment_button.py +2 -2
- edc_auth/admin/user_admin.py +1 -1
- edc_auth/auth_objects/__init__.py +2 -20
- edc_auth/auth_objects/default_groups.py +13 -11
- edc_auth/auth_objects/default_roles.py +26 -24
- edc_auth/auth_updater/auth_updater.py +13 -2
- edc_auth/auth_updater/group_updater.py +12 -10
- edc_auth/auth_updater/role_updater.py +2 -2
- edc_auth/constants.py +10 -0
- edc_auth/import_users.py +3 -3
- 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/models/user_profile.py +14 -11
- edc_auth/post_migrate_signals.py +1 -1
- edc_auth/site_auths.py +80 -67
- edc_consent/actions.py +4 -5
- edc_consent/auths.py +18 -12
- 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_constants/constants.py +1 -0
- edc_crf/auths.py +5 -0
- edc_crf/migrations/0001_initial.py +3 -2
- edc_crf/migrations/0009_alter_crfstatus_device_created_and_more.py +54 -0
- edc_dashboard/auths.py +10 -6
- 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_dashboard/url_config.py +92 -83
- edc_dashboard/url_names.py +4 -4
- edc_dashboard/view_mixins/url_request_context_mixin.py +6 -5
- edc_data_manager/action_items.py +4 -6
- edc_data_manager/admin/actions.py +5 -5
- edc_data_manager/admin/data_query_admin.py +12 -11
- edc_data_manager/auths.py +37 -34
- 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/query_rule_wrapper.py +7 -7
- 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 +7 -5
- edc_export/auths.py +32 -28
- 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 +17 -15
- 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/auths.py +8 -3
- edc_facility/facility.py +16 -22
- 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_label/custom_label_condition.py +11 -8
- edc_form_label/form_label.py +1 -1
- edc_form_runners/auths.py +11 -6
- 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_form_validators/applicable_field_validator.py +7 -6
- edc_form_validators/base_form_validator.py +8 -9
- edc_form_validators/other_specify_field_validator.py +2 -8
- edc_form_validators/required_field_validator.py +19 -16
- 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/research_identifier.py +11 -10
- edc_identifier/simple_identifier.py +9 -5
- edc_identifier/subject_identifier.py +3 -2
- edc_lab/auths.py +26 -23
- edc_lab/lab/aliquot_creator.py +5 -8
- edc_lab/lab/primary_aliquot.py +14 -5
- 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 +13 -16
- 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/aliquot.py +2 -2
- edc_lab/models/box.py +1 -1
- edc_lab/models/box_item.py +6 -7
- edc_lab/models/manifest/manifest.py +3 -3
- edc_lab/models/manifest/manifest_item.py +7 -7
- 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/auths.py +16 -11
- 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/calculate_missing.py +8 -8
- edc_lab_results/form_validator_mixins/blood_results_form_validator_mixin.py +2 -2
- edc_lab_results/get_summary.py +26 -25
- edc_lab_results/model_mixins/blood_result_model_mixin.py +9 -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/auths.py +6 -1
- edc_label/label_template.py +8 -8
- 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/load_model_data.py +3 -3
- edc_list_data/model_mixins.py +12 -4
- edc_list_data/post_migrate_signals.py +1 -1
- edc_list_data/preload_data.py +4 -4
- edc_list_data/row.py +1 -1
- edc_list_data/site_list_data.py +6 -5
- edc_listboard/migrations/0001_initial.py +3 -2
- edc_listboard/migrations/0007_alter_listboard_device_created_and_more.py +49 -0
- edc_locator/auths.py +18 -13
- 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/auths.py +11 -7
- edc_metadata/metadata/metadata.py +1 -1
- edc_metadata/metadata_rules/crf/crf_rule.py +1 -1
- edc_metadata/metadata_rules/decorators.py +1 -1
- edc_metadata/metadata_rules/metadata_rule_evaluator.py +5 -3
- edc_metadata/metadata_rules/rule.py +2 -3
- edc_metadata/metadata_rules/rule_evaluator.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 +7 -4
- edc_metadata/model_mixins/updates/updates_requisition_metadata_model_mixin.py +5 -2
- 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/models/signals.py +10 -11
- 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/auths.py +18 -13
- 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/auths.py +9 -4
- 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/graded_event_notification.py +2 -2
- edc_notification/notification/model_notification.py +3 -30
- edc_notification/notification/new_model_notification.py +1 -1
- edc_notification/notification/notification.py +12 -12
- edc_notification/notification/updated_model_notification.py +2 -2
- edc_offstudy/auths.py +12 -7
- 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 +7 -3
- 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/auths.py +19 -15
- 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/formulation.py +5 -7
- 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/prescribe/create_prescription.py +3 -3
- edc_pharmacy/utils/allocate_stock.py +2 -3
- edc_pharmacy/utils/confirm_stock.py +3 -4
- edc_pharmacy/utils/confirm_stock_at_site.py +4 -5
- 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/confirmation_at_site_view.py +6 -9
- 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_prn/admin_site.py +5 -0
- edc_prn/prn.py +10 -11
- edc_prn/urls.py +11 -0
- edc_protocol/research_protocol_config.py +2 -3
- edc_protocol_incident/action_items.py +4 -4
- edc_protocol_incident/auths.py +27 -20
- 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/auths.py +6 -1
- 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/auths.py +11 -7
- 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/admin.py +30 -24
- edc_randomization/auths.py +12 -7
- 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/randomizer.py +22 -20
- edc_randomization/utils.py +19 -18
- edc_refusal/auths.py +7 -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 +4 -4
- edc_registration/auths.py +28 -23
- 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 +15 -7
- edc_registration/models/registered_subject.py +28 -27
- 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/get_reference_range_collection.py +2 -3
- edc_reportable/utils/load_data.py +4 -4
- edc_reportable/utils/update_grading_data.py +5 -5
- edc_review_dashboard/auths.py +23 -18
- 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 +6 -6
- edc_screening/auths.py +35 -30
- edc_screening/eligibility.py +1 -1
- edc_screening/gender_evaluator.py +1 -1
- 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 -6
- edc_screening/model_mixins/screening_fields_model_mixin.py +6 -8
- edc_screening/model_mixins/screening_methods_model_mixin.py +1 -1
- edc_screening/screening_eligibility.py +2 -4
- edc_screening/utils.py +9 -9
- edc_search/generate_slug.py +26 -0
- edc_search/model_mixins.py +10 -22
- edc_sites/auths.py +8 -3
- 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/auths.py +27 -22
- 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/apps.py +0 -21
- edc_timepoint/model_mixins.py +22 -20
- edc_transfer/model_mixins.py +4 -4
- edc_transfer/modeladmin_mixins.py +1 -1
- edc_unblinding/auths.py +9 -4
- 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/__init__.py +3 -1
- edc_utils/age.py +10 -16
- edc_utils/show_urls.py +29 -2
- edc_visit_schedule/auths.py +6 -1
- 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/site_visit_schedules.py +2 -2
- 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 +3 -3
- edc_visit_tracking/models/subject_visit.py +1 -1
- edc_vitals/calculators/bmi.py +7 -5
- edc_vitals/utils.py +1 -1
- edc_form_label/models.py +0 -0
- edc_search/constants.py +0 -1
- edc_search/models.py +0 -0
- edc_search/search_slug.py +0 -50
- edc_search/updater.py +0 -30
- edc_search/wsgi.py +0 -7
- {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/licenses/LICENSE +0 -0
edc_facility/model_mixins.py
CHANGED
|
@@ -2,10 +2,10 @@ import calendar
|
|
|
2
2
|
|
|
3
3
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
|
4
4
|
from django.db import models
|
|
5
|
+
from django.utils import timezone
|
|
5
6
|
|
|
6
7
|
from edc_model.models import BaseUuidModel
|
|
7
8
|
from edc_model_fields.fields import OtherCharField
|
|
8
|
-
from edc_utils import get_utcnow
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class HealthFacilityCalendarError(Exception):
|
|
@@ -28,11 +28,11 @@ class HealthFacilityModelMixin(models.Model):
|
|
|
28
28
|
See also edc_appointment.
|
|
29
29
|
"""
|
|
30
30
|
|
|
31
|
-
report_datetime = models.DateTimeField(default=
|
|
31
|
+
report_datetime = models.DateTimeField(default=timezone.now)
|
|
32
32
|
|
|
33
33
|
name = models.CharField(max_length=25, unique=True)
|
|
34
34
|
|
|
35
|
-
title = models.CharField(max_length=150,
|
|
35
|
+
title = models.CharField(max_length=150, default="", blank=True)
|
|
36
36
|
|
|
37
37
|
health_facility_type = models.ForeignKey(
|
|
38
38
|
"edc_facility.HealthFacilityTypes",
|
|
@@ -45,7 +45,7 @@ class HealthFacilityModelMixin(models.Model):
|
|
|
45
45
|
|
|
46
46
|
gps = models.CharField(
|
|
47
47
|
max_length=50,
|
|
48
|
-
|
|
48
|
+
default="",
|
|
49
49
|
blank=True,
|
|
50
50
|
help_text="copy and paste directly from google maps",
|
|
51
51
|
)
|
|
@@ -115,7 +115,7 @@ class HealthFacilityModelMixin(models.Model):
|
|
|
115
115
|
days = []
|
|
116
116
|
mapping = {k: v for k, v in enumerate(calendar.weekheader(3).split(" "))}
|
|
117
117
|
for day_int in self.clinic_days:
|
|
118
|
-
days.append(mapping.get(day_int))
|
|
118
|
+
days.append(mapping.get(day_int)) # noqa: PERF401
|
|
119
119
|
return ",".join(days)
|
|
120
120
|
|
|
121
121
|
class Meta(BaseUuidModel.Meta):
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import contextlib
|
|
3
4
|
from typing import TYPE_CHECKING
|
|
4
5
|
|
|
5
6
|
from django.apps import apps as django_apps
|
|
@@ -28,20 +29,24 @@ class CustomLabelCondition:
|
|
|
28
29
|
"""
|
|
29
30
|
return
|
|
30
31
|
|
|
31
|
-
def get_additional_options(self, request=None, obj=None, model=None):
|
|
32
|
+
def get_additional_options(self, request=None, obj=None, model=None): # noqa: ARG002
|
|
32
33
|
return {}
|
|
33
34
|
|
|
34
35
|
@property
|
|
35
36
|
def appointment(self) -> Appointment | None:
|
|
36
37
|
"""Returns the appointment instance for this request or None."""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
with contextlib.suppress(ObjectDoesNotExist):
|
|
39
|
+
return django_apps.get_model(self.appointment_model).objects.get(
|
|
40
|
+
pk=self.request.GET.get("appointment")
|
|
41
|
+
)
|
|
42
|
+
return None
|
|
40
43
|
|
|
41
44
|
@property
|
|
42
45
|
def previous_appointment(self) -> Appointment | None:
|
|
43
46
|
"""Returns the previous appointment for this request or None."""
|
|
44
|
-
|
|
47
|
+
with contextlib.suppress(ObjectDoesNotExist):
|
|
48
|
+
return self.appointment.previous_by_timepoint
|
|
49
|
+
return None
|
|
45
50
|
|
|
46
51
|
@property
|
|
47
52
|
def previous_visit(self):
|
|
@@ -73,10 +78,8 @@ class CustomLabelCondition:
|
|
|
73
78
|
"""
|
|
74
79
|
previous_obj = None
|
|
75
80
|
if self.previous_visit:
|
|
76
|
-
|
|
81
|
+
with contextlib.suppress(ObjectDoesNotExist):
|
|
77
82
|
previous_obj = self.model.objects.get(
|
|
78
83
|
**{f"{self.model.related_visit_model_attr()}": self.previous_visit}
|
|
79
84
|
)
|
|
80
|
-
except ObjectDoesNotExist:
|
|
81
|
-
pass
|
|
82
85
|
return previous_obj
|
edc_form_label/form_label.py
CHANGED
edc_form_runners/auths.py
CHANGED
|
@@ -9,10 +9,15 @@ from .auth_objects import (
|
|
|
9
9
|
codenames,
|
|
10
10
|
)
|
|
11
11
|
|
|
12
|
-
site_auths.add_group(*codenames, name=EDC_FORM_RUNNERS_VIEW, view_only=True)
|
|
13
|
-
site_auths.add_group(*codenames, name=EDC_FORM_RUNNERS, no_delete=True)
|
|
14
|
-
site_auths.add_group(*codenames, name=EDC_FORM_RUNNERS_SUPER)
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
site_auths.
|
|
18
|
-
site_auths.
|
|
13
|
+
def update_site_auths():
|
|
14
|
+
site_auths.add_group(*codenames, name=EDC_FORM_RUNNERS_VIEW, view_only=True)
|
|
15
|
+
site_auths.add_group(*codenames, name=EDC_FORM_RUNNERS, no_delete=True)
|
|
16
|
+
site_auths.add_group(*codenames, name=EDC_FORM_RUNNERS_SUPER)
|
|
17
|
+
|
|
18
|
+
site_auths.update_role(EDC_FORM_RUNNERS_VIEW, name=AUDITOR_ROLE)
|
|
19
|
+
site_auths.update_role(EDC_FORM_RUNNERS, name=CLINICIAN_ROLE)
|
|
20
|
+
site_auths.update_role(EDC_FORM_RUNNERS_SUPER, name=DATA_MANAGER_ROLE)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
update_site_auths()
|
edc_form_runners/form_runner.py
CHANGED
|
@@ -8,10 +8,9 @@ from bs4 import BeautifulSoup
|
|
|
8
8
|
from django.apps import apps as django_apps
|
|
9
9
|
from django.db.models import ForeignKey, ManyToManyField, Model, OneToOneField, QuerySet
|
|
10
10
|
from django.forms import ModelForm
|
|
11
|
+
from django.utils import timezone
|
|
11
12
|
from tqdm import tqdm
|
|
12
13
|
|
|
13
|
-
from edc_utils import get_utcnow
|
|
14
|
-
|
|
15
14
|
from .exceptions import FormRunnerModelAdminNotFound, FormRunnerModelFormNotFound
|
|
16
15
|
from .utils import get_modeladmin_cls
|
|
17
16
|
|
|
@@ -37,7 +36,7 @@ class FormRunner:
|
|
|
37
36
|
) -> None:
|
|
38
37
|
self.messages = {}
|
|
39
38
|
self.session_id = uuid.uuid4()
|
|
40
|
-
self.session_datetime =
|
|
39
|
+
self.session_datetime = timezone.now()
|
|
41
40
|
self.verbose = verbose
|
|
42
41
|
self.model_name = self.model_name or model_name
|
|
43
42
|
self.modeladmin_cls = get_modeladmin_cls(self.model_name)
|
|
@@ -48,8 +47,7 @@ class FormRunner:
|
|
|
48
47
|
)
|
|
49
48
|
if self.modeladmin_cls.form == ModelForm:
|
|
50
49
|
raise FormRunnerModelFormNotFound(
|
|
51
|
-
"ModelAdmin does not have a custom form. Nothing to do. "
|
|
52
|
-
f"Got `{model_name}`."
|
|
50
|
+
f"ModelAdmin does not have a custom form. Nothing to do. Got `{model_name}`."
|
|
53
51
|
)
|
|
54
52
|
self.src_model_cls = self.modeladmin_cls.model
|
|
55
53
|
|
|
@@ -8,6 +8,7 @@ import django_audit_fields.fields.uuid_auto_field
|
|
|
8
8
|
import django_audit_fields.models.audit_model_mixin
|
|
9
9
|
import django_revision.revision_field
|
|
10
10
|
from django.db import migrations, models
|
|
11
|
+
import django.utils.timezone
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
class Migration(migrations.Migration):
|
|
@@ -36,14 +37,14 @@ class Migration(migrations.Migration):
|
|
|
36
37
|
"created",
|
|
37
38
|
models.DateTimeField(
|
|
38
39
|
blank=True,
|
|
39
|
-
default=
|
|
40
|
+
default=django.utils.timezone.now,
|
|
40
41
|
),
|
|
41
42
|
),
|
|
42
43
|
(
|
|
43
44
|
"modified",
|
|
44
45
|
models.DateTimeField(
|
|
45
46
|
blank=True,
|
|
46
|
-
default=
|
|
47
|
+
default=django.utils.timezone.now,
|
|
47
48
|
),
|
|
48
49
|
),
|
|
49
50
|
(
|
|
@@ -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_form_runners", "0004_alter_issue_revision"),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name="issue",
|
|
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="issue",
|
|
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="issue",
|
|
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="issue",
|
|
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,6 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
|
-
from edc_constants.constants import NOT_APPLICABLE
|
|
3
|
+
from edc_constants.constants import NOT_APPLICABLE, NULL_STRING
|
|
4
4
|
|
|
5
5
|
from .base_form_validator import (
|
|
6
6
|
APPLICABLE_ERROR,
|
|
@@ -33,8 +33,8 @@ class ApplicableFieldValidator(BaseFormValidator):
|
|
|
33
33
|
def applicable_if(
|
|
34
34
|
self,
|
|
35
35
|
*responses: Any,
|
|
36
|
-
field: str
|
|
37
|
-
field_applicable: str
|
|
36
|
+
field: str,
|
|
37
|
+
field_applicable: str,
|
|
38
38
|
inverse: bool | None = None,
|
|
39
39
|
is_instance_field: bool | None = None,
|
|
40
40
|
msg: str | None = None,
|
|
@@ -95,8 +95,8 @@ class ApplicableFieldValidator(BaseFormValidator):
|
|
|
95
95
|
def applicable(
|
|
96
96
|
self,
|
|
97
97
|
*responses: Any,
|
|
98
|
-
field: str
|
|
99
|
-
field_applicable: str
|
|
98
|
+
field: str,
|
|
99
|
+
field_applicable: str,
|
|
100
100
|
inverse: bool | None = None,
|
|
101
101
|
is_instance_field: bool | None = None,
|
|
102
102
|
msg: str | None = None,
|
|
@@ -117,7 +117,8 @@ class ApplicableFieldValidator(BaseFormValidator):
|
|
|
117
117
|
field_applicable_value = self.get(field_applicable)
|
|
118
118
|
|
|
119
119
|
if field_value in responses and (
|
|
120
|
-
field_applicable_value
|
|
120
|
+
field_applicable_value in (NULL_STRING, not_applicable)
|
|
121
|
+
or field_applicable_value is None
|
|
121
122
|
):
|
|
122
123
|
self.raise_applicable(field_applicable, msg=msg, applicable_msg=applicable_msg)
|
|
123
124
|
elif (
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import contextlib
|
|
3
4
|
from copy import copy
|
|
4
5
|
from typing import Any
|
|
5
6
|
|
|
6
7
|
from django.core.exceptions import NON_FIELD_ERRORS
|
|
7
|
-
from django.forms import ValidationError
|
|
8
|
+
from django.forms import ValidationError
|
|
8
9
|
|
|
9
10
|
APPLICABLE_ERROR = "applicable"
|
|
10
11
|
INVALID_ERROR = "invalid"
|
|
@@ -14,7 +15,7 @@ REQUIRED_ERROR = "required"
|
|
|
14
15
|
OUT_OF_RANGE_ERROR = "out_of_range"
|
|
15
16
|
|
|
16
17
|
|
|
17
|
-
class InvalidModelFormFieldValidator(Exception):
|
|
18
|
+
class InvalidModelFormFieldValidator(Exception): # noqa: N818
|
|
18
19
|
def __init__(self, message, code=None):
|
|
19
20
|
message = f"Invalid field validator. Got '{message}'"
|
|
20
21
|
super().__init__(message)
|
|
@@ -119,13 +120,13 @@ class BaseFormValidator:
|
|
|
119
120
|
"""
|
|
120
121
|
try:
|
|
121
122
|
self._clean()
|
|
122
|
-
except
|
|
123
|
+
except ValidationError as e:
|
|
123
124
|
self.capture_error_message(e)
|
|
124
125
|
self.capture_error_code(e)
|
|
125
|
-
raise
|
|
126
|
+
raise ValidationError(e) from e
|
|
126
127
|
return self.cleaned_data
|
|
127
128
|
|
|
128
|
-
def capture_error_message(self, e:
|
|
129
|
+
def capture_error_message(self, e: ValidationError) -> None:
|
|
129
130
|
try:
|
|
130
131
|
self._errors.update(**e.error_dict)
|
|
131
132
|
except AttributeError:
|
|
@@ -134,11 +135,9 @@ class BaseFormValidator:
|
|
|
134
135
|
except AttributeError:
|
|
135
136
|
self._errors.update({NON_FIELD_ERRORS: str(e)})
|
|
136
137
|
|
|
137
|
-
def capture_error_code(self, e:
|
|
138
|
-
|
|
138
|
+
def capture_error_code(self, e: ValidationError) -> None:
|
|
139
|
+
with contextlib.suppress(AttributeError):
|
|
139
140
|
self._error_codes.append(e.code)
|
|
140
|
-
except AttributeError:
|
|
141
|
-
pass
|
|
142
141
|
|
|
143
142
|
def get_inline_field_value(self, field=None, inline_set=None):
|
|
144
143
|
"""Returns the value of the first inline field that has a value."""
|
|
@@ -41,20 +41,14 @@ class OtherSpecifyFieldValidator(BaseFormValidator):
|
|
|
41
41
|
cleaned_data.get(field), fk_stored_field_name, cleaned_data.get(field)
|
|
42
42
|
)
|
|
43
43
|
|
|
44
|
-
if (
|
|
45
|
-
field_value is not None
|
|
46
|
-
and field_value == other
|
|
47
|
-
and not cleaned_data.get(other_specify_field)
|
|
48
|
-
):
|
|
44
|
+
if field_value and field_value == other and not cleaned_data.get(other_specify_field):
|
|
49
45
|
ref = "" if not ref else f" ref: {ref}"
|
|
50
46
|
message = {other_specify_field: required_msg or f"This field is required.{ref}"}
|
|
51
47
|
self._errors.update(message)
|
|
52
48
|
self._error_codes.append(REQUIRED_ERROR)
|
|
53
49
|
raise ValidationError(message, code=REQUIRED_ERROR)
|
|
54
50
|
if (
|
|
55
|
-
field_value
|
|
56
|
-
and field_value != other
|
|
57
|
-
and cleaned_data.get(other_specify_field)
|
|
51
|
+
field_value and field_value != other and cleaned_data.get(other_specify_field)
|
|
58
52
|
) or (field_value is None and cleaned_data.get(other_specify_field)):
|
|
59
53
|
ref = "" if not ref else f" ref: {ref}"
|
|
60
54
|
message = {
|
|
@@ -43,8 +43,8 @@ class RequiredFieldValidator(BaseFormValidator):
|
|
|
43
43
|
def required_if(
|
|
44
44
|
self,
|
|
45
45
|
*responses: str | int | bool,
|
|
46
|
-
field: str
|
|
47
|
-
field_required: str
|
|
46
|
+
field: str,
|
|
47
|
+
field_required: str,
|
|
48
48
|
required_msg: str | None = None,
|
|
49
49
|
not_required_msg: str | None = None,
|
|
50
50
|
optional_if_dwta: bool | None = None,
|
|
@@ -82,7 +82,7 @@ class RequiredFieldValidator(BaseFormValidator):
|
|
|
82
82
|
self.get(field_required, inline_set=inline_set) is not None
|
|
83
83
|
)
|
|
84
84
|
else:
|
|
85
|
-
field_required_has_value = self.get(field_required, inline_set=inline_set)
|
|
85
|
+
field_required_has_value = bool(self.get(field_required, inline_set=inline_set))
|
|
86
86
|
|
|
87
87
|
if field in self.cleaned_data:
|
|
88
88
|
if (DWTA in responses and optional_if_dwta and field_value == DWTA) or (
|
|
@@ -117,7 +117,7 @@ class RequiredFieldValidator(BaseFormValidator):
|
|
|
117
117
|
def required_if_true(
|
|
118
118
|
self,
|
|
119
119
|
condition: bool,
|
|
120
|
-
field_required: str
|
|
120
|
+
field_required: str,
|
|
121
121
|
required_msg: str | None = None,
|
|
122
122
|
not_required_msg: str | None = None,
|
|
123
123
|
inverse: bool | None = None,
|
|
@@ -145,7 +145,7 @@ class RequiredFieldValidator(BaseFormValidator):
|
|
|
145
145
|
def not_required_if_true(
|
|
146
146
|
self,
|
|
147
147
|
condition: bool,
|
|
148
|
-
field: str
|
|
148
|
+
field: str,
|
|
149
149
|
msg: str | None = None,
|
|
150
150
|
is_instance_field: bool | None = None,
|
|
151
151
|
) -> bool:
|
|
@@ -170,8 +170,8 @@ class RequiredFieldValidator(BaseFormValidator):
|
|
|
170
170
|
|
|
171
171
|
def required_if_not_none(
|
|
172
172
|
self,
|
|
173
|
-
field: str
|
|
174
|
-
field_required: str
|
|
173
|
+
field: str,
|
|
174
|
+
field_required: str,
|
|
175
175
|
required_msg: str | None = None,
|
|
176
176
|
not_required_msg: str | None = None,
|
|
177
177
|
optional_if_dwta: bool | None = None,
|
|
@@ -182,6 +182,9 @@ class RequiredFieldValidator(BaseFormValidator):
|
|
|
182
182
|
"""Raises an exception or returns False.
|
|
183
183
|
|
|
184
184
|
If field is not none, field_required is "required".
|
|
185
|
+
|
|
186
|
+
Note: CharFields usually default to an empty string and not NULL.
|
|
187
|
+
For IntegerFields, zero is a value.
|
|
185
188
|
"""
|
|
186
189
|
inverse = True if inverse is None else inverse
|
|
187
190
|
if is_instance_field:
|
|
@@ -197,7 +200,7 @@ class RequiredFieldValidator(BaseFormValidator):
|
|
|
197
200
|
if field_required_evaluate_as_int:
|
|
198
201
|
field_required_has_value = self.cleaned_data.get(field_required) is not None
|
|
199
202
|
else:
|
|
200
|
-
field_required_has_value = self.cleaned_data.get(field_required)
|
|
203
|
+
field_required_has_value = bool(self.cleaned_data.get(field_required))
|
|
201
204
|
|
|
202
205
|
if field_value is not None and not field_required_has_value:
|
|
203
206
|
self.raise_required(field=field_required, msg=required_msg)
|
|
@@ -221,8 +224,8 @@ class RequiredFieldValidator(BaseFormValidator):
|
|
|
221
224
|
def not_required_if(
|
|
222
225
|
self,
|
|
223
226
|
*responses: str | int | bool,
|
|
224
|
-
field: str
|
|
225
|
-
field_required: str = None,
|
|
227
|
+
field: str,
|
|
228
|
+
field_required: str | None = None,
|
|
226
229
|
field_not_required: str | None = None,
|
|
227
230
|
required_msg: str | None = None,
|
|
228
231
|
not_required_msg: str | None = None,
|
|
@@ -259,8 +262,8 @@ class RequiredFieldValidator(BaseFormValidator):
|
|
|
259
262
|
|
|
260
263
|
def require_together(
|
|
261
264
|
self,
|
|
262
|
-
field: str
|
|
263
|
-
field_required: str
|
|
265
|
+
field: str,
|
|
266
|
+
field_required: str,
|
|
264
267
|
required_msg: str | None = None,
|
|
265
268
|
is_instance_field: bool | None = None,
|
|
266
269
|
) -> bool:
|
|
@@ -280,15 +283,15 @@ class RequiredFieldValidator(BaseFormValidator):
|
|
|
280
283
|
return False
|
|
281
284
|
|
|
282
285
|
@staticmethod
|
|
283
|
-
def _inspect_params(
|
|
284
|
-
*responses: str | int | bool, field: str = None, field_required: str = None
|
|
285
|
-
) -> bool:
|
|
286
|
+
def _inspect_params(*responses: str | int | bool, field: str, field_required: str) -> bool:
|
|
286
287
|
"""Inspects params and raises if any are None"""
|
|
287
288
|
if not field:
|
|
288
289
|
errmsg = _("`field` cannot be `None`")
|
|
289
290
|
raise InvalidModelFormFieldValidator(f"{errmsg}.")
|
|
290
291
|
if not responses:
|
|
291
|
-
errmsg = _(
|
|
292
|
+
errmsg = _(
|
|
293
|
+
"At least one valid response for field '{field}' must be provided."
|
|
294
|
+
).format(field=field)
|
|
292
295
|
raise InvalidModelFormFieldValidator(errmsg)
|
|
293
296
|
if not field_required:
|
|
294
297
|
raise InvalidModelFormFieldValidator('"field_required" cannot be None.')
|
|
@@ -11,7 +11,7 @@ from django.db import migrations, models
|
|
|
11
11
|
|
|
12
12
|
import edc_model_fields.fields.hostname_modification_field
|
|
13
13
|
import edc_model_fields.fields.userfield
|
|
14
|
-
import
|
|
14
|
+
import django.utils.timezone
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class Migration(migrations.Migration):
|
|
@@ -52,11 +52,11 @@ class Migration(migrations.Migration):
|
|
|
52
52
|
fields=[
|
|
53
53
|
(
|
|
54
54
|
"created",
|
|
55
|
-
models.DateTimeField(blank=True, default=
|
|
55
|
+
models.DateTimeField(blank=True, default=django.utils.timezone.now),
|
|
56
56
|
),
|
|
57
57
|
(
|
|
58
58
|
"modified",
|
|
59
|
-
models.DateTimeField(blank=True, default=
|
|
59
|
+
models.DateTimeField(blank=True, default=django.utils.timezone.now),
|
|
60
60
|
),
|
|
61
61
|
(
|
|
62
62
|
"user_created",
|
|
@@ -4,6 +4,7 @@ import django_audit_fields.fields.hostname_modification_field
|
|
|
4
4
|
import django_audit_fields.fields.userfield
|
|
5
5
|
import django_audit_fields.models.audit_model_mixin
|
|
6
6
|
from django.db import migrations, models
|
|
7
|
+
import django.utils.timezone
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class Migration(migrations.Migration):
|
|
@@ -13,9 +14,7 @@ class Migration(migrations.Migration):
|
|
|
13
14
|
migrations.AlterField(
|
|
14
15
|
model_name="identifiermodel",
|
|
15
16
|
name="created",
|
|
16
|
-
field=models.DateTimeField(
|
|
17
|
-
blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
|
|
18
|
-
),
|
|
17
|
+
field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
|
|
19
18
|
),
|
|
20
19
|
migrations.AlterField(
|
|
21
20
|
model_name="identifiermodel",
|
|
@@ -29,9 +28,7 @@ class Migration(migrations.Migration):
|
|
|
29
28
|
migrations.AlterField(
|
|
30
29
|
model_name="identifiermodel",
|
|
31
30
|
name="modified",
|
|
32
|
-
field=models.DateTimeField(
|
|
33
|
-
blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
|
|
34
|
-
),
|
|
31
|
+
field=models.DateTimeField(blank=True, default=django.utils.timezone.now),
|
|
35
32
|
),
|
|
36
33
|
migrations.AlterField(
|
|
37
34
|
model_name="identifiermodel",
|
|
@@ -8,7 +8,7 @@ from django.db import migrations, models
|
|
|
8
8
|
|
|
9
9
|
import edc_model_fields.fields.hostname_modification_field
|
|
10
10
|
import edc_model_fields.fields.userfield
|
|
11
|
-
import
|
|
11
|
+
import django.utils.timezone
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class Migration(migrations.Migration):
|
|
@@ -23,7 +23,7 @@ class Migration(migrations.Migration):
|
|
|
23
23
|
migrations.AddField(
|
|
24
24
|
model_name="historicalidentifierhistory",
|
|
25
25
|
name="created",
|
|
26
|
-
field=models.DateTimeField(default=
|
|
26
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
27
27
|
),
|
|
28
28
|
migrations.AddField(
|
|
29
29
|
model_name="historicalidentifierhistory",
|
|
@@ -48,7 +48,7 @@ class Migration(migrations.Migration):
|
|
|
48
48
|
migrations.AddField(
|
|
49
49
|
model_name="historicalidentifierhistory",
|
|
50
50
|
name="modified",
|
|
51
|
-
field=models.DateTimeField(default=
|
|
51
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
52
52
|
),
|
|
53
53
|
migrations.AddField(
|
|
54
54
|
model_name="historicalidentifierhistory",
|
|
@@ -79,7 +79,7 @@ class Migration(migrations.Migration):
|
|
|
79
79
|
migrations.AddField(
|
|
80
80
|
model_name="identifierhistory",
|
|
81
81
|
name="created",
|
|
82
|
-
field=models.DateTimeField(default=
|
|
82
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
83
83
|
),
|
|
84
84
|
migrations.AddField(
|
|
85
85
|
model_name="identifierhistory",
|
|
@@ -104,7 +104,7 @@ class Migration(migrations.Migration):
|
|
|
104
104
|
migrations.AddField(
|
|
105
105
|
model_name="identifierhistory",
|
|
106
106
|
name="modified",
|
|
107
|
-
field=models.DateTimeField(default=
|
|
107
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
108
108
|
),
|
|
109
109
|
migrations.AddField(
|
|
110
110
|
model_name="identifierhistory",
|
|
@@ -152,22 +152,22 @@ class Migration(migrations.Migration):
|
|
|
152
152
|
migrations.AlterField(
|
|
153
153
|
model_name="historicalidentifiertracker",
|
|
154
154
|
name="created",
|
|
155
|
-
field=models.DateTimeField(default=
|
|
155
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
156
156
|
),
|
|
157
157
|
migrations.AlterField(
|
|
158
158
|
model_name="historicalidentifiertracker",
|
|
159
159
|
name="modified",
|
|
160
|
-
field=models.DateTimeField(default=
|
|
160
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
161
161
|
),
|
|
162
162
|
migrations.AlterField(
|
|
163
163
|
model_name="historicalsubjectidentifier",
|
|
164
164
|
name="created",
|
|
165
|
-
field=models.DateTimeField(default=
|
|
165
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
166
166
|
),
|
|
167
167
|
migrations.AlterField(
|
|
168
168
|
model_name="historicalsubjectidentifier",
|
|
169
169
|
name="modified",
|
|
170
|
-
field=models.DateTimeField(default=
|
|
170
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
171
171
|
),
|
|
172
172
|
migrations.AlterField(
|
|
173
173
|
model_name="identifierhistory",
|
|
@@ -183,31 +183,31 @@ class Migration(migrations.Migration):
|
|
|
183
183
|
migrations.AlterField(
|
|
184
184
|
model_name="identifiertracker",
|
|
185
185
|
name="created",
|
|
186
|
-
field=models.DateTimeField(default=
|
|
186
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
187
187
|
),
|
|
188
188
|
migrations.AlterField(
|
|
189
189
|
model_name="identifiertracker",
|
|
190
190
|
name="modified",
|
|
191
|
-
field=models.DateTimeField(default=
|
|
191
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
192
192
|
),
|
|
193
193
|
migrations.AlterField(
|
|
194
194
|
model_name="sequence",
|
|
195
195
|
name="created",
|
|
196
|
-
field=models.DateTimeField(default=
|
|
196
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
197
197
|
),
|
|
198
198
|
migrations.AlterField(
|
|
199
199
|
model_name="sequence",
|
|
200
200
|
name="modified",
|
|
201
|
-
field=models.DateTimeField(default=
|
|
201
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
202
202
|
),
|
|
203
203
|
migrations.AlterField(
|
|
204
204
|
model_name="subjectidentifier",
|
|
205
205
|
name="created",
|
|
206
|
-
field=models.DateTimeField(default=
|
|
206
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
207
207
|
),
|
|
208
208
|
migrations.AlterField(
|
|
209
209
|
model_name="subjectidentifier",
|
|
210
210
|
name="modified",
|
|
211
|
-
field=models.DateTimeField(default=
|
|
211
|
+
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
212
212
|
),
|
|
213
213
|
]
|
|
@@ -8,7 +8,7 @@ from django.db import migrations, models
|
|
|
8
8
|
|
|
9
9
|
import edc_model_fields.fields.hostname_modification_field
|
|
10
10
|
import edc_model_fields.fields.userfield
|
|
11
|
-
import
|
|
11
|
+
import django.utils.timezone
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class Migration(migrations.Migration):
|
|
@@ -20,11 +20,11 @@ class Migration(migrations.Migration):
|
|
|
20
20
|
fields=[
|
|
21
21
|
(
|
|
22
22
|
"created",
|
|
23
|
-
models.DateTimeField(default=
|
|
23
|
+
models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
24
24
|
),
|
|
25
25
|
(
|
|
26
26
|
"modified",
|
|
27
|
-
models.DateTimeField(default=
|
|
27
|
+
models.DateTimeField(default=django.utils.timezone.now, editable=False),
|
|
28
28
|
),
|
|
29
29
|
(
|
|
30
30
|
"user_created",
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# Generated by Django 1.10.4 on 2016-12-21 23:23
|
|
3
3
|
from __future__ import unicode_literals
|
|
4
|
-
|
|
4
|
+
import django.utils.timezone
|
|
5
5
|
from django.db import migrations, models
|
|
6
6
|
|
|
7
|
-
from edc_utils import get_utcnow
|
|
8
|
-
|
|
9
7
|
|
|
10
8
|
class Migration(migrations.Migration):
|
|
11
9
|
dependencies = [("edc_identifier", "0008_identifiermodel_linked_identifier")]
|
|
@@ -14,11 +12,11 @@ class Migration(migrations.Migration):
|
|
|
14
12
|
migrations.AlterField(
|
|
15
13
|
model_name="historicalidentifierhistory",
|
|
16
14
|
name="created_datetime",
|
|
17
|
-
field=models.DateTimeField(default=
|
|
15
|
+
field=models.DateTimeField(default=django.utils.timezone.now),
|
|
18
16
|
),
|
|
19
17
|
migrations.AlterField(
|
|
20
18
|
model_name="identifierhistory",
|
|
21
19
|
name="created_datetime",
|
|
22
|
-
field=models.DateTimeField(default=
|
|
20
|
+
field=models.DateTimeField(default=django.utils.timezone.now),
|
|
23
21
|
),
|
|
24
22
|
]
|