clinicedc 2.0.3__py3-none-any.whl → 2.0.5__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.3.dist-info → clinicedc-2.0.5.dist-info}/METADATA +41 -45
- {clinicedc-2.0.3.dist-info → clinicedc-2.0.5.dist-info}/RECORD +478 -478
- edc_action_item/action.py +76 -54
- edc_action_item/action_item_notification.py +1 -3
- edc_action_item/action_with_notification.py +4 -4
- edc_action_item/create_action_item.py +2 -2
- edc_action_item/create_or_update_action_type.py +1 -1
- edc_action_item/data_fixers.py +4 -5
- edc_action_item/delete_action_item.py +0 -1
- edc_action_item/modeladmin_mixins.py +2 -4
- edc_action_item/modelform_mixins/modelform_mixins.py +1 -1
- edc_action_item/models/action_item.py +53 -38
- edc_action_item/models/action_model_mixin.py +17 -17
- edc_action_item/models/action_type.py +33 -13
- edc_action_item/models/reference.py +3 -2
- edc_action_item/site_action_items.py +13 -14
- edc_action_item/stubs.py +9 -9
- edc_action_item/templatetags/action_item_extras.py +2 -2
- edc_action_item/view_utils/action_item_button.py +3 -3
- edc_action_item/view_utils/action_item_popover_list_item.py +4 -4
- edc_adherence/form_validator_mixin.py +1 -1
- edc_adverse_event/action_items/ae_followup_action.py +1 -1
- edc_adverse_event/action_items/ae_initial_action.py +1 -1
- edc_adverse_event/action_items/ae_susar_action.py +1 -1
- edc_adverse_event/action_items/ae_tmg_action.py +1 -1
- edc_adverse_event/action_items/death_report_action.py +1 -2
- edc_adverse_event/action_items/death_report_tmg_action.py +1 -1
- edc_adverse_event/action_items/death_report_tmg_second_action.py +1 -1
- edc_adverse_event/action_items/hospitalization_action.py +1 -1
- edc_adverse_event/form_validator_mixins/death_report_form_validator.py +3 -3
- edc_adverse_event/form_validator_mixins/requires_death_report_form_validator_mixin.py +3 -4
- edc_adverse_event/form_validators/death_report_tmg.py +1 -1
- edc_adverse_event/model_mixins/ae_followup/ae_followup_methods_model_mixin.py +3 -3
- edc_adverse_event/model_mixins/ae_followup/ae_followup_model_mixin.py +3 -3
- edc_adverse_event/model_mixins/ae_initial/ae_initial_fields_model_mixin.py +0 -1
- edc_adverse_event/model_mixins/ae_initial/ae_initial_methods_model_mixin.py +3 -3
- edc_adverse_event/model_mixins/ae_initial/ae_initial_model_mixin.py +3 -3
- edc_adverse_event/model_mixins/ae_special_interest/aesi_methods_model_mixin.py +4 -4
- edc_adverse_event/model_mixins/ae_special_interest/aesi_model_mixin.py +3 -3
- edc_adverse_event/model_mixins/ae_susar/ae_susar_methods_model_mixin.py +4 -4
- edc_adverse_event/model_mixins/ae_susar/ae_susar_model_mixin.py +3 -3
- edc_adverse_event/model_mixins/ae_tmg/ae_tmg_fields_model_mixin.py +4 -5
- edc_adverse_event/model_mixins/ae_tmg/ae_tmg_methods_model_mixin.py +4 -4
- edc_adverse_event/model_mixins/ae_tmg/ae_tmg_model_mixin.py +3 -3
- edc_adverse_event/model_mixins/death_report/death_report_extra_fields_model_mixin.py +2 -3
- edc_adverse_event/model_mixins/death_report/death_report_model_mixin.py +11 -11
- edc_adverse_event/model_mixins/death_report/death_report_tmg_model_mixin.py +9 -11
- edc_adverse_event/model_mixins/death_report/simple_death_report_model_mixin.py +7 -6
- edc_adverse_event/model_mixins/hospitaization/hospitalization_model_mixin.py +0 -1
- edc_adverse_event/modeladmin_mixins/ae_followup_admin_mixin.py +9 -11
- edc_adverse_event/modeladmin_mixins/ae_initial_admin_mixin.py +4 -6
- edc_adverse_event/modeladmin_mixins/modeladmin_mixins.py +1 -1
- edc_adverse_event/modeladmin_mixins/utils.py +4 -4
- edc_adverse_event/models/signals.py +7 -19
- edc_adverse_event/pdf_reports/death_pdf_report.py +8 -9
- edc_adverse_event/templatetags/edc_adverse_event_extras.py +10 -20
- edc_adverse_event/urls.py +7 -3
- edc_adverse_event/utils.py +2 -2
- edc_adverse_event/view_utils/tmg_button.py +4 -4
- edc_appconfig/system_checks.py +1 -1
- edc_appointment/appointment_status_updater.py +14 -15
- edc_appointment/creators/appointment_creator.py +7 -11
- edc_appointment/creators/appointments_creator.py +1 -1
- edc_appointment/creators/unscheduled_appointment_creator.py +12 -13
- edc_appointment/form_validator_mixins/next_appointment_crf_form_validator_mixin.py +1 -3
- edc_appointment/form_validator_mixins/window_period_form_validator_mixin.py +7 -6
- edc_appointment/form_validators/appointment_form_validator.py +2 -4
- edc_appointment/form_validators/utils.py +4 -4
- edc_appointment/managers.py +4 -4
- edc_appointment/model_mixins/appointment_methods_model_mixin.py +2 -2
- edc_appointment/model_mixins/appointment_model_mixin.py +5 -5
- edc_appointment/model_mixins/window_period_model_mixin.py +1 -1
- edc_appointment/models/appointment.py +1 -1
- edc_appointment/skip_appointments.py +5 -6
- edc_appointment/stubs.py +12 -12
- edc_appointment/utils.py +41 -47
- edc_appointment/view_utils/appointment_button.py +3 -5
- edc_auth/admin/role_admin.py +5 -7
- edc_auth/auth_objects/default_roles.py +1 -3
- edc_auth/auth_updater/auth_updater.py +5 -7
- edc_auth/auth_updater/group_updater.py +8 -8
- edc_auth/auth_updater/role_updater.py +1 -2
- edc_auth/get_app_codenames.py +1 -3
- edc_auth/import_users.py +19 -19
- edc_auth/models/role.py +4 -3
- edc_auth/password_setter.py +6 -7
- edc_auth/send_new_credentials_to_user.py +2 -3
- edc_auth/site_auths.py +3 -3
- edc_consent/actions.py +4 -5
- edc_consent/consent_definition.py +8 -11
- edc_consent/consent_definition_extension.py +3 -3
- edc_consent/form_validators/__init__.py +1 -1
- edc_consent/model_mixins/__init__.py +2 -2
- edc_consent/model_mixins/consent_version_model_mixin.py +1 -1
- edc_consent/modeladmin_mixins/consent_model_admin_mixin.py +1 -2
- edc_consent/modelform_mixins/consent_modelform_mixin/consent_modelform_validation_mixin.py +3 -5
- edc_consent/site_consents.py +10 -15
- edc_consent/stubs.py +2 -2
- edc_consent/utils.py +1 -1
- edc_constants/utils.py +2 -4
- edc_crf/crf_form_validator_mixins.py +2 -2
- edc_crf/model_mixins/crf_no_manager_model_mixin.py +2 -2
- edc_crf/model_mixins/crf_status_model_mixin.py +1 -1
- edc_crf/models/crf_status.py +10 -12
- edc_crf/update_crf_status_command.py +1 -3
- edc_dashboard/management/commands/update_search_slugs.py +8 -11
- edc_dashboard/templatetags/edc_dashboard_extras.py +1 -1
- edc_dashboard/url_config.py +3 -3
- edc_dashboard/utils.py +3 -4
- edc_dashboard/views/dashboard_view.py +1 -1
- edc_data_manager/models/data_dictionary.py +1 -2
- edc_data_manager/models/data_query.py +3 -3
- edc_data_manager/models/query_rule.py +2 -2
- edc_data_manager/tasks.py +0 -2
- edc_device/device.py +1 -1
- edc_device/view_mixins.py +1 -1
- edc_document_status/fieldsets.py +1 -3
- edc_document_status/model_mixins.py +2 -2
- edc_document_status/modeladmin_mixins.py +1 -4
- edc_egfr/admin/egfr_drop_notification_admin_mixin.py +5 -7
- edc_egfr/egfr.py +6 -7
- edc_egfr/get_drop_notification_model.py +1 -1
- edc_egfr/model_mixins/egfr_drop_notification_model_mixin.py +1 -1
- edc_export/archive_exporter.py +26 -27
- edc_export/exportables.py +2 -3
- edc_export/management/commands/import_receipts.py +6 -6
- edc_export/model_exporter/file_history_updater.py +1 -1
- edc_export/model_exporter/model_exporter.py +1 -1
- edc_export/model_exporter/value_getter.py +6 -6
- edc_export/model_mixins/notification_model_mixin.py +4 -4
- edc_export/models/data_request.py +3 -3
- edc_export/models/data_request_history.py +2 -2
- edc_export/models/export_receipt.py +1 -1
- edc_export/models/file_history.py +5 -5
- edc_export/models/plan.py +4 -4
- edc_export/models/upload_export_receipt_file.py +2 -2
- edc_export/utils.py +1 -1
- edc_facility/facility.py +6 -6
- edc_facility/holidays.py +2 -5
- edc_facility/import_holidays.py +6 -6
- edc_facility/model_mixins.py +1 -1
- edc_facility/models/holiday.py +1 -1
- edc_facility/utils.py +3 -3
- edc_fieldsets/fieldsets.py +1 -1
- edc_form_describer/forms_reference.py +5 -8
- edc_form_describer/make_forms_reference.py +1 -1
- edc_form_describer/management/commands/make_forms_reference.py +1 -1
- edc_form_label/custom_label_condition.py +1 -1
- edc_form_label/form_label.py +2 -2
- edc_form_runners/exceptions.py +1 -1
- edc_form_runners/models/issue.py +3 -2
- edc_form_runners/site.py +2 -2
- edc_form_runners/templatetags/form_runners_extras.py +1 -1
- edc_form_runners/utils.py +5 -5
- edc_form_validators/applicable_field_validator.py +32 -32
- edc_form_validators/base_form_validator.py +1 -1
- edc_form_validators/extra_mixins/study_day_form_validator.py +1 -1
- edc_form_validators/many_to_many_field_validator.py +38 -43
- edc_form_validators/other_specify_field_validator.py +9 -17
- edc_form_validators/required_field_validator.py +34 -39
- edc_form_validators/test_case_mixin.py +5 -5
- edc_identifier/admin.py +1 -3
- edc_identifier/identifier.py +2 -3
- edc_identifier/model_mixins.py +5 -8
- edc_identifier/research_identifier.py +10 -12
- edc_identifier/short_identifier.py +1 -1
- edc_identifier/simple_identifier.py +22 -22
- edc_identifier/utils.py +1 -1
- edc_lab/admin/fieldsets.py +7 -9
- edc_lab/admin/modeladmin_mixins.py +5 -6
- edc_lab/form_validators/requisition_form_validator_mixin.py +2 -3
- edc_lab/forms/box_form.py +5 -11
- edc_lab/identifiers/aliquot_identifier.py +5 -8
- edc_lab/identifiers/prefix.py +2 -5
- edc_lab/lab/aliquot_creator.py +1 -2
- edc_lab/lab/aliquot_type.py +2 -4
- edc_lab/lab/manifest.py +5 -7
- edc_lab/lab/requisition_panel.py +2 -4
- edc_lab/lab/requisition_panel_group.py +5 -7
- edc_lab/model_mixins/requisition/requisition_model_mixin.py +5 -4
- edc_lab/model_mixins/shipping/manifest_model_mixin.py +6 -6
- edc_lab/model_mixins/shipping/verify_model_mixin.py +4 -3
- edc_lab/models/aliquot.py +1 -1
- edc_lab/models/box.py +2 -2
- edc_lab/models/box_item.py +1 -1
- edc_lab/models/box_type.py +1 -1
- edc_lab/models/manifest/manifest_item.py +1 -1
- edc_lab/pdf_reports/manifest_pdf_report.py +3 -7
- edc_lab/site_labs.py +3 -3
- edc_lab_dashboard/dashboard_templates.py +1 -1
- edc_lab_dashboard/view_mixins/box_view_mixin.py +4 -9
- edc_lab_dashboard/views/action_views/action_view.py +1 -2
- edc_lab_dashboard/views/action_views/manage_manifest_view.py +1 -1
- edc_lab_dashboard/views/action_views/manifest_view.py +9 -11
- edc_lab_dashboard/views/action_views/pack_view.py +11 -14
- edc_lab_results/calculate_missing.py +2 -2
- edc_lab_results/fieldsets.py +6 -6
- edc_lab_results/model_mixin_factories/__init__.py +2 -2
- edc_lab_results/model_mixin_factories/reportable_result_model_mixin_factory.py +7 -9
- edc_lab_results/model_mixin_factories/result_model_mixin_factory.py +7 -9
- edc_lab_results/model_mixins/fbg_model_mixin.py +1 -1
- edc_lab_results/model_mixins/glucose_model_mixin.py +1 -1
- edc_label/admin.py +1 -3
- edc_label/label.py +2 -4
- edc_label/label_template.py +1 -1
- edc_label/subject_label.py +1 -3
- edc_list_data/admin.py +3 -5
- edc_list_data/load_list_data.py +1 -1
- edc_list_data/load_model_data.py +1 -3
- edc_list_data/model_mixins.py +3 -5
- edc_list_data/preload_data.py +2 -4
- edc_list_data/site_list_data.py +6 -7
- edc_listboard/filters/listboard_filter.py +2 -2
- edc_listboard/views/listboard_view.py +1 -3
- edc_locator/models.py +2 -2
- edc_locator/view_mixins/subject_locator_view_mixins.py +2 -2
- edc_ltfu/action_items.py +1 -1
- edc_ltfu/model_mixins.py +0 -2
- edc_ltfu/models.py +4 -4
- edc_metadata/admin/modeladmin_mixins.py +1 -1
- edc_metadata/admin/requisition_metadata.py +2 -4
- edc_metadata/metadata/crf_metadata_getter.py +1 -3
- edc_metadata/metadata/requisition_metadata_getter.py +1 -3
- edc_metadata/metadata_handler.py +2 -2
- edc_metadata/metadata_helper/metadata_helper_mixin.py +2 -3
- edc_metadata/metadata_mixins/source_model_metadata_mixin.py +2 -2
- edc_metadata/metadata_refresher.py +1 -1
- edc_metadata/metadata_rules/crf/crf_rule_group.py +3 -5
- edc_metadata/metadata_rules/logic.py +1 -1
- edc_metadata/metadata_rules/requisition/requisition_rule.py +4 -4
- edc_metadata/metadata_rules/requisition/requisition_rule_group.py +2 -2
- edc_metadata/metadata_rules/rule_evaluator.py +5 -6
- edc_metadata/metadata_rules/rule_group_metaclass.py +2 -3
- edc_metadata/metadata_rules/site.py +6 -7
- edc_metadata/metadata_updater.py +2 -2
- edc_metadata/metadata_wrappers/metadata_wrapper.py +4 -4
- edc_metadata/model_mixins/creates/creates_metadata_model_mixin.py +6 -7
- edc_metadata/model_mixins/updates/updates_crf_metadata_model_mixin.py +2 -2
- edc_metadata/model_mixins/updates/updates_metadata_model_mixin.py +2 -2
- edc_metadata/model_mixins/updates/updates_requisition_metadata_model_mixin.py +2 -2
- edc_metadata/models/crf_metadata.py +27 -29
- edc_metadata/models/crf_metadata_model_mixin.py +1 -1
- edc_metadata/models/requisition_metadata.py +29 -31
- edc_metadata/stubs.py +17 -17
- edc_metadata/utils.py +4 -4
- edc_model/__init__.py +2 -2
- edc_model/models/historical_records.py +2 -2
- edc_model/models/signals.py +1 -1
- edc_model/models/url_model_mixin.py +1 -1
- edc_model/utils.py +0 -2
- edc_model_admin/dashboard/model_admin_dashboard_mixin.py +1 -3
- edc_model_admin/history/model_admin_simple_history.py +7 -9
- edc_model_admin/mixins/base_model_admin_redirect_mixin.py +4 -6
- edc_model_admin/mixins/model_admin_limit_to_selected_foreignkey.py +2 -2
- edc_model_admin/mixins/model_admin_model_redirect_mixin.py +2 -10
- edc_model_admin/mixins/model_admin_next_url_redirect_mixin.py +8 -9
- edc_model_admin/utils.py +6 -9
- edc_model_form/mixins/__init__.py +1 -1
- edc_model_form/mixins/base_model_form_mixin.py +1 -1
- edc_model_to_dataframe/model_to_dataframe.py +2 -4
- edc_navbar/site_navbars.py +2 -2
- edc_navbar/system_checks.py +1 -1
- edc_notification/mailing_list_manager.py +5 -8
- edc_notification/management/commands/list_recipients_by_notification.py +1 -1
- edc_notification/models/__init__.py +4 -2
- edc_notification/notification/graded_event_notification.py +2 -4
- edc_notification/notification/model_notification.py +1 -3
- edc_notification/notification/notification.py +14 -17
- edc_notification/site_notifications.py +7 -7
- edc_notification/stubs.py +6 -6
- edc_notification/update_mailing_lists_in_m2m.py +2 -2
- edc_offstudy/action_items.py +2 -2
- edc_offstudy/model_mixins/offstudy_model_mixin.py +1 -1
- edc_offstudy/models.py +1 -1
- edc_pdf_reports/crf_pdf_report.py +2 -2
- edc_pdf_reports/model_mixins.py +2 -2
- edc_pdf_reports/report.py +4 -5
- edc_pdf_reports/utils.py +1 -1
- edc_pdutils/dataframes/get_subject_consent.py +1 -3
- edc_pdutils/df_exporters/csv_exporter.py +5 -7
- edc_pdutils/df_exporters/tables_exporter.py +2 -2
- edc_pdutils/df_handlers/crf_df_handler.py +1 -2
- edc_pdutils/dialects/crf_dialect.py +3 -3
- edc_pdutils/management/commands/export_models.py +6 -7
- edc_pdutils/site_values_mappings.py +2 -2
- edc_pdutils/utils/datetime_to_date.py +1 -2
- edc_pdutils/utils/refresh_model_from_dataframe.py +1 -3
- edc_pdutils/utils/table_names.py +2 -4
- edc_pdutils/utils/undash.py +1 -1
- edc_pharmacy/admin/medication/assignment_admin.py +2 -4
- edc_pharmacy/admin/medication/dosage_guideline_admin.py +2 -4
- edc_pharmacy/admin/medication/formulation_admin.py +3 -5
- edc_pharmacy/admin/medication/medication_admin.py +3 -5
- edc_pharmacy/admin/prescription/rx_refill_admin.py +7 -9
- edc_pharmacy/admin/stock/lot_admin.py +5 -7
- edc_pharmacy/admin/stock/order_admin.py +2 -2
- edc_pharmacy/admin/stock/order_item_admin.py +6 -6
- edc_pharmacy/admin/stock/receive_admin.py +1 -1
- edc_pharmacy/admin/stock/receive_item_admin.py +2 -2
- edc_pharmacy/admin/stock/stock_request_admin.py +4 -6
- edc_pharmacy/dosage_calculator.py +4 -4
- edc_pharmacy/form_validators/crf/study_medication_form_validator.py +8 -8
- edc_pharmacy/forms/stock/stock_request_form.py +2 -4
- edc_pharmacy/model_mixins/study_medication_crf_model_mixin.py +2 -2
- edc_pharmacy/models/medication/formulation.py +3 -4
- edc_pharmacy/models/medication/medication.py +1 -2
- edc_pharmacy/models/prescription/rx.py +2 -2
- edc_pharmacy/models/prescription/rx_refill.py +7 -9
- edc_pharmacy/models/reports/stock_availability.py +3 -4
- edc_pharmacy/models/stock/confirmation_at_site.py +1 -3
- edc_pharmacy/models/stock/order.py +1 -2
- edc_pharmacy/models/stock/receive.py +3 -4
- edc_pharmacy/models/stock/receive_item.py +2 -3
- edc_pharmacy/models/stock/stock.py +1 -2
- edc_pharmacy/models/stock/stock_adjustment.py +1 -2
- edc_pharmacy/models/stock/stock_request.py +4 -5
- edc_pharmacy/models/storage/box.py +1 -1
- edc_pharmacy/models/storage/items/container_model_mixin.py +1 -1
- edc_pharmacy/models/storage/room.py +1 -1
- edc_pharmacy/models/storage/shelf.py +1 -1
- edc_pharmacy/models/storage/utils.py +15 -16
- edc_pharmacy/prescribe/create_prescription.py +5 -5
- edc_pharmacy/refill/refill_creator.py +1 -1
- edc_pharmacy/sample_usb_printing/usb_printing.py +1 -1
- edc_pharmacy/utils/__init__.py +1 -1
- edc_pharmacy/utils/confirm_stock.py +3 -3
- edc_pharmacy/utils/confirm_stock_at_site.py +9 -8
- edc_pharmacy/utils/dispense.py +5 -8
- edc_pharmacy/utils/format_qty.py +3 -3
- edc_pharmacy/utils/get_codenames.py +1 -1
- edc_pharmacy/utils/miscellaneous.py +1 -1
- edc_pharmacy/utils/process_repack_request.py +18 -19
- edc_pharmacy/utils/process_repack_request_queryset.py +0 -2
- edc_pharmacy/utils/stock_request/bulk_create_stock_request_items.py +2 -3
- edc_pharmacy/views/add_to_storage_bin_view.py +1 -1
- edc_pharmacy/views/allocate_to_subject_view.py +2 -6
- edc_pharmacy/views/confirm_stock_from_instance_view.py +4 -4
- edc_pharmacy/views/confirm_stock_from_queryset_view.py +1 -5
- edc_pharmacy/views/confirmation_at_site_view.py +2 -3
- edc_pharmacy/views/dispense_view.py +1 -1
- edc_pharmacy/views/move_to_storage_bin_view.py +2 -3
- edc_pharmacy/views/print_labels_view.py +30 -31
- edc_pharmacy/views/transfer_stock_view.py +1 -1
- edc_prn/prn.py +1 -1
- edc_prn/site_prn_forms.py +1 -2
- edc_protocol_incident/action_items.py +2 -2
- edc_protocol_incident/model_mixins/protocol_deviation_violation_model_mixin.py +3 -3
- edc_protocol_incident/model_mixins/protocol_incident_model_mixin.py +3 -5
- edc_protocol_incident/modeladmin_mixins.py +3 -5
- edc_protocol_incident/models/protocol_deviation_violation.py +5 -5
- edc_protocol_incident/models/protocol_incident.py +5 -5
- edc_pylabels/site_label_configs.py +5 -5
- edc_qareports/model_mixins/qa_report_model_mixin.py +4 -2
- edc_qareports/models/qa_reports_log.py +1 -2
- edc_qareports/utils.py +1 -2
- edc_randomization/admin.py +3 -5
- edc_randomization/auth_objects.py +2 -3
- edc_randomization/blinding.py +1 -1
- edc_randomization/constants.py +2 -4
- edc_randomization/model_mixins.py +3 -3
- edc_randomization/randomization_list_importer.py +13 -14
- edc_randomization/randomization_list_verifier.py +11 -13
- edc_randomization/randomizer.py +2 -2
- edc_randomization/system_checks.py +1 -2
- edc_randomization/utils.py +5 -5
- edc_refusal/admin.py +1 -1
- edc_refusal/model_mixins.py +1 -1
- edc_refusal/utils.py +1 -1
- edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py +2 -2
- edc_registration/modeladmin_mixins.py +4 -7
- edc_registration/models/registered_subject.py +7 -9
- edc_registration/utils.py +3 -4
- edc_reportable/data/grading_data/daids_july_2017.py +3 -3
- edc_reportable/evaluator.py +5 -5
- edc_reportable/formula.py +1 -1
- edc_reportable/reference_range_evaluator.py +3 -3
- edc_reportable/utils/convert_units.py +10 -12
- edc_reportable/utils/grading_data_model_cls.py +2 -2
- edc_reportable/utils/grading_exception_model_cls.py +2 -2
- edc_reportable/utils/molecular_weight_model_cls.py +2 -2
- edc_reportable/utils/normal_data_model_cls.py +2 -2
- edc_reportable/utils/reference_range_colllection_model_cls.py +2 -2
- edc_screening/age_evaluator.py +2 -4
- edc_screening/eligibility.py +1 -1
- edc_screening/form_validator_mixins.py +2 -2
- edc_screening/model_mixins/screening_methods_model_mixin.py +1 -1
- edc_screening/screening_eligibility.py +1 -1
- edc_screening/utils.py +4 -6
- edc_search/model_mixins.py +1 -1
- edc_search/search_slug.py +1 -3
- edc_search/updater.py +1 -1
- edc_sites/admin/site_model_admin_mixin.py +2 -2
- edc_sites/model_mixins/site_model_mixin.py +1 -2
- edc_sites/modelform_mixins.py +2 -2
- edc_sites/models/__init__.py +1 -1
- edc_sites/models/site_profile.py +4 -4
- edc_sites/site.py +24 -32
- edc_sites/system_checks.py +1 -1
- edc_sites/utils/get_message_text.py +1 -1
- edc_sites/utils/valid_site_for_subject_or_raise.py +5 -6
- edc_subject_dashboard/requisition_report.py +4 -5
- edc_subject_dashboard/requisition_verifier.py +4 -2
- edc_subject_dashboard/templatetags/edc_subject_dashboard_extras.py +16 -17
- edc_subject_dashboard/view_utils/__init__.py +1 -1
- edc_subject_dashboard/view_utils/crf_button.py +1 -3
- edc_subject_dashboard/view_utils/subject_consent_dashboard_button.py +2 -2
- edc_subject_dashboard/view_utils/subject_consent_listboard_button.py +2 -2
- edc_subject_dashboard/view_utils/timepoint_status_button.py +1 -4
- edc_subject_dashboard/views/requisition_print_actions_view.py +2 -2
- edc_subject_dashboard/views/subject_dashboard_view.py +1 -1
- edc_timepoint/model_mixins.py +2 -2
- edc_transfer/action_items.py +1 -1
- edc_transfer/model_mixins.py +4 -3
- edc_transfer/modeladmin_mixins.py +3 -6
- edc_unblinding/action_items.py +2 -2
- edc_unblinding/models/unblinding_request.py +3 -3
- edc_unblinding/models/unblinding_review.py +3 -3
- edc_utils/__init__.py +6 -5
- edc_utils/age.py +1 -1
- edc_utils/celery.py +3 -8
- edc_utils/get_static_file.py +1 -1
- edc_utils/text.py +5 -6
- edc_view_utils/__init__.py +3 -3
- edc_view_utils/dashboard_model_button.py +4 -4
- edc_view_utils/model_button.py +7 -8
- edc_view_utils/perms.py +3 -3
- edc_visit_schedule/action_items.py +2 -2
- edc_visit_schedule/admin/list_filters.py +11 -9
- edc_visit_schedule/admin/subject_schedule_history_admin.py +13 -15
- edc_visit_schedule/admin/visit_schedule_admin.py +7 -7
- edc_visit_schedule/fieldsets.py +4 -6
- edc_visit_schedule/management/commands/find_invalid_onschedules.py +1 -1
- edc_visit_schedule/model_mixins/off_schedule_model_mixin.py +3 -1
- edc_visit_schedule/model_mixins/on_schedule_model_mixin.py +1 -1
- edc_visit_schedule/modelform_mixins/__init__.py +1 -1
- edc_visit_schedule/modelform_mixins/off_schedule_modelform_mixin.py +1 -2
- edc_visit_schedule/models/subject_schedule_history.py +2 -1
- edc_visit_schedule/models/visit_schedule.py +2 -2
- edc_visit_schedule/schedule/schedule.py +11 -12
- edc_visit_schedule/schedule/visit_collection.py +4 -3
- edc_visit_schedule/schedule/window.py +19 -12
- edc_visit_schedule/site_visit_schedules.py +9 -9
- edc_visit_schedule/subject_schedule.py +6 -7
- edc_visit_schedule/system_checks.py +8 -4
- edc_visit_schedule/view_mixins.py +1 -1
- edc_visit_schedule/visit/crf.py +3 -7
- edc_visit_schedule/visit/requisition.py +2 -2
- edc_visit_schedule/visit/visit.py +6 -7
- edc_visit_schedule/visit/window_period.py +8 -8
- edc_visit_schedule/visit_schedule/schedules_collection.py +2 -5
- edc_visit_tracking/action_items.py +11 -13
- edc_visit_tracking/form_validators/visit_form_validator.py +5 -5
- edc_visit_tracking/model_mixins/base/visit_methods_model_mixin.py +3 -4
- edc_visit_tracking/model_mixins/crfs/visit_tracking_crf_model_mixin.py +2 -2
- edc_visit_tracking/model_mixins/subject_visit_missed_model_mixin.py +2 -3
- edc_visit_tracking/model_mixins/utils.py +1 -1
- edc_visit_tracking/model_mixins/visit_model_mixin/previous_visit_model_mixin.py +2 -2
- edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_mixin.py +3 -3
- edc_visit_tracking/modeladmin_mixins/crf_model_admin_mixin.py +6 -4
- edc_visit_tracking/modeladmin_mixins/visit_model_admin_mixin.py +6 -7
- edc_visit_tracking/modelform_mixins/crf/visit_tracking_crf_modelform_mixin.py +4 -5
- edc_visit_tracking/modelform_mixins/visit_tracking_modelform_mixin.py +3 -4
- edc_visit_tracking/models/subject_visit.py +1 -1
- edc_visit_tracking/models/subject_visit_missed.py +1 -1
- edc_visit_tracking/stubs.py +7 -7
- edc_visit_tracking/typing_stubs.py +11 -11
- edc_visit_tracking/utils.py +5 -5
- edc_visit_tracking/view_utils/related_visit_button.py +5 -5
- edc_vitals/calculators/bmi.py +1 -1
- edc_vitals/form_validators/blood_pressure_form_validator_mixin.py +8 -12
- edc_vitals/form_validators/bmi_form_validator_mixin.py +1 -1
- edc_vitals/form_validators/weight_height_with_bmi_form_validator_mixin.py +5 -2
- edc_vitals/model_mixins/blood_pressure_model_mixin.py +3 -4
- edc_vitals/model_mixins/weight_height_bmi_model_mixin.py +4 -4
- edc_vitals/utils.py +1 -1
- edc_vitals/validators.py +1 -1
- {clinicedc-2.0.3.dist-info → clinicedc-2.0.5.dist-info}/WHEEL +0 -0
- {clinicedc-2.0.3.dist-info → clinicedc-2.0.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -74,9 +74,7 @@ class BoxViewMixin(ContextMixin):
|
|
|
74
74
|
box=self.box, identifier=self.box_item_identifier
|
|
75
75
|
)
|
|
76
76
|
except ObjectDoesNotExist:
|
|
77
|
-
message = "Invalid box item. Got {}"
|
|
78
|
-
self.original_box_item_identifier
|
|
79
|
-
)
|
|
77
|
+
message = f"Invalid box item. Got {self.original_box_item_identifier}"
|
|
80
78
|
messages.error(self.request, message)
|
|
81
79
|
return self._box_item
|
|
82
80
|
|
|
@@ -85,7 +83,7 @@ class BoxViewMixin(ContextMixin):
|
|
|
85
83
|
try:
|
|
86
84
|
box_item = BoxItem.objects.get(box=self.box, position=position)
|
|
87
85
|
except ObjectDoesNotExist:
|
|
88
|
-
message = "Invalid position for box. Got {}"
|
|
86
|
+
message = f"Invalid position for box. Got {position}"
|
|
89
87
|
messages.error(self.request, message)
|
|
90
88
|
return None
|
|
91
89
|
return box_item
|
|
@@ -103,15 +101,12 @@ class BoxViewMixin(ContextMixin):
|
|
|
103
101
|
# raise BoxViewError(message)
|
|
104
102
|
else:
|
|
105
103
|
if obj.is_primary and not self.box.accept_primary:
|
|
106
|
-
message = 'Box does not accept "primary" specimens. Got {} is primary.'
|
|
107
|
-
self.original_box_item_identifier
|
|
108
|
-
)
|
|
104
|
+
message = f'Box does not accept "primary" specimens. Got {self.original_box_item_identifier} is primary.'
|
|
109
105
|
messages.error(self.request, message)
|
|
110
106
|
# raise BoxViewError(message)
|
|
111
107
|
elif obj.numeric_code not in self.box.specimen_types.split(","):
|
|
112
108
|
message = (
|
|
113
|
-
"Invalid specimen type. Box accepts types {}. "
|
|
114
|
-
"Got {} is type {}.".format(
|
|
109
|
+
"Invalid specimen type. Box accepts types {}. Got {} is type {}.".format(
|
|
115
110
|
", ".join(self.box.specimen_types.split(",")),
|
|
116
111
|
self.original_box_item_identifier,
|
|
117
112
|
obj.numeric_code,
|
|
@@ -60,8 +60,7 @@ class ActionView(TemplateView):
|
|
|
60
60
|
action = slugify(self.request.POST.get("action", "").lower())
|
|
61
61
|
if action not in self.valid_form_actions:
|
|
62
62
|
raise InvalidPostError(f"Invalid form action in POST. Got {action}")
|
|
63
|
-
|
|
64
|
-
self.action = action
|
|
63
|
+
self.action = action
|
|
65
64
|
self.process_form_action(request=request)
|
|
66
65
|
url_name = url_names.get(self.post_action_url)
|
|
67
66
|
url = reverse(url_name, kwargs=self.url_kwargs)
|
|
@@ -47,7 +47,7 @@ class ManageManifestView(EdcViewMixin, ManifestViewMixin, ActionView):
|
|
|
47
47
|
deleted = ManifestItem.objects.filter(
|
|
48
48
|
pk__in=self.selected_items, manifest__shipped=False
|
|
49
49
|
).delete()
|
|
50
|
-
message = "{} items have been removed."
|
|
50
|
+
message = f"{deleted[0]} items have been removed."
|
|
51
51
|
messages.success(self.request, message)
|
|
52
52
|
except ProtectedError:
|
|
53
53
|
message = "Unable to remove. Manifest is not empty."
|
|
@@ -24,15 +24,14 @@ class ManifestView(EdcViewMixin, ManifestViewMixin, LabPrintersMixin, ActionView
|
|
|
24
24
|
if not self.selected_items:
|
|
25
25
|
message = "Nothing to do. No items have been selected."
|
|
26
26
|
messages.warning(request, message)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
self.ship_selected_items()
|
|
27
|
+
elif self.action == "remove_selected_items":
|
|
28
|
+
self.remove_selected_items()
|
|
29
|
+
elif self.action == "print_labels":
|
|
30
|
+
job_result = self.print_labels(pks=self.selected_items, request=request)
|
|
31
|
+
if job_result:
|
|
32
|
+
add_job_results_to_messages(request, [job_result])
|
|
33
|
+
elif self.action == "ship_selected_items":
|
|
34
|
+
self.ship_selected_items()
|
|
36
35
|
|
|
37
36
|
def remove_selected_items(self):
|
|
38
37
|
"""Deletes the selected items, if allowed."""
|
|
@@ -51,8 +50,7 @@ class ManifestView(EdcViewMixin, ManifestViewMixin, LabPrintersMixin, ActionView
|
|
|
51
50
|
for manifest in Manifest.objects.filter(pk__in=self.selected_items):
|
|
52
51
|
if manifest.shipped:
|
|
53
52
|
message = (
|
|
54
|
-
f"Manifest has already been shipped. "
|
|
55
|
-
f"Got {manifest.manifest_identifier}."
|
|
53
|
+
f"Manifest has already been shipped. Got {manifest.manifest_identifier}."
|
|
56
54
|
)
|
|
57
55
|
messages.error(self.request, message)
|
|
58
56
|
else:
|
|
@@ -29,16 +29,15 @@ class PackView(EdcViewMixin, LabPrintersMixin, ActionView):
|
|
|
29
29
|
if not self.selected_items:
|
|
30
30
|
message = "Nothing to do. No items have been selected."
|
|
31
31
|
messages.warning(request, message)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
add_job_results_to_messages(request, [job_result])
|
|
32
|
+
elif self.action == "remove_selected_items":
|
|
33
|
+
self.remove_selected_items()
|
|
34
|
+
elif self.action == "add_selected_to_manifest":
|
|
35
|
+
if self.selected_manifest:
|
|
36
|
+
self.add_selected_to_manifest()
|
|
37
|
+
elif self.action == "print_labels":
|
|
38
|
+
job_result = self.print_labels(pks=self.selected_items, request=request)
|
|
39
|
+
if job_result:
|
|
40
|
+
add_job_results_to_messages(request, [job_result])
|
|
42
41
|
|
|
43
42
|
@property
|
|
44
43
|
def selected_manifest(self):
|
|
@@ -77,9 +76,7 @@ class PackView(EdcViewMixin, LabPrintersMixin, ActionView):
|
|
|
77
76
|
else:
|
|
78
77
|
break
|
|
79
78
|
if added > 0:
|
|
80
|
-
message = "{} items have been added to manifest {}."
|
|
81
|
-
added, self.selected_manifest.human_readable_identifier
|
|
82
|
-
)
|
|
79
|
+
message = f"{added} items have been added to manifest {self.selected_manifest.human_readable_identifier}."
|
|
83
80
|
messages.success(self.request, message)
|
|
84
81
|
except ProtectedError:
|
|
85
82
|
message = "Unable to remove. Box is not empty."
|
|
@@ -93,7 +90,7 @@ class PackView(EdcViewMixin, LabPrintersMixin, ActionView):
|
|
|
93
90
|
else:
|
|
94
91
|
try:
|
|
95
92
|
deleted = Box.objects.filter(pk__in=self.selected_items).delete()
|
|
96
|
-
message = "{} items have been removed."
|
|
93
|
+
message = f"{deleted[0]} items have been removed."
|
|
97
94
|
messages.success(self.request, message)
|
|
98
95
|
except ProtectedError:
|
|
99
96
|
message = "Unable to remove. Box is not empty."
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from typing import Any
|
|
1
|
+
from typing import Any
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def calculate_missing(obj: Any, panel: Any) ->
|
|
4
|
+
def calculate_missing(obj: Any, panel: Any) -> tuple[int, str | None]:
|
|
5
5
|
"""Returns a tuple of (missing_count, missing)
|
|
6
6
|
|
|
7
7
|
Counts the number of blank results within the model
|
edc_lab_results/fieldsets.py
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING, Any
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
4
|
|
|
5
5
|
from django_audit_fields import audit_fieldset_tuple
|
|
6
6
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
8
|
from edc_lab import RequisitionPanel
|
|
9
9
|
|
|
10
|
-
panel_conclusion_fieldset:
|
|
10
|
+
panel_conclusion_fieldset: tuple[str, dict] = (
|
|
11
11
|
"Conclusion",
|
|
12
12
|
{"fields": ("results_abnormal", "results_reportable")},
|
|
13
13
|
)
|
|
14
|
-
panel_summary_fieldset:
|
|
14
|
+
panel_summary_fieldset: tuple[str, dict] = (
|
|
15
15
|
"Summary",
|
|
16
16
|
{"fields": ("reportable_summary", "abnormal_summary", "errors")},
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
calculate_egfr_fieldset:
|
|
20
|
+
calculate_egfr_fieldset: tuple[str, dict] = (
|
|
21
21
|
"Calculated eGFR",
|
|
22
22
|
{
|
|
23
23
|
# "classes": ("collapse",),
|
|
@@ -26,7 +26,7 @@ calculate_egfr_fieldset: Tuple[str, dict] = (
|
|
|
26
26
|
},
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
-
calculate_egfr_drop_fieldset:
|
|
29
|
+
calculate_egfr_drop_fieldset: tuple[str, dict] = (
|
|
30
30
|
"Calculated eGFR Drop",
|
|
31
31
|
{
|
|
32
32
|
# "classes": ("collapse",),
|
|
@@ -50,7 +50,7 @@ class BloodResultFieldset:
|
|
|
50
50
|
panel: RequisitionPanel,
|
|
51
51
|
title: str = None,
|
|
52
52
|
model_cls: Any = None,
|
|
53
|
-
extra_fieldsets: list[
|
|
53
|
+
extra_fieldsets: list[tuple[int, tuple[str, dict]]] | None = None,
|
|
54
54
|
excluded_utest_ids: list[str] = None,
|
|
55
55
|
exclude_units: bool = None,
|
|
56
56
|
exclude_reportable: bool = None,
|
|
@@ -3,8 +3,8 @@ from .reportable_result_model_mixin_factory import reportable_result_model_mixin
|
|
|
3
3
|
from .result_model_mixin_factory import result_model_mixin_factory
|
|
4
4
|
|
|
5
5
|
__all__ = [
|
|
6
|
+
"get_field_attrs_for_reportable",
|
|
7
|
+
"get_field_attrs_for_utestid",
|
|
6
8
|
"reportable_result_model_mixin_factory",
|
|
7
9
|
"result_model_mixin_factory",
|
|
8
|
-
"get_field_attrs_for_utestid",
|
|
9
|
-
"get_field_attrs_for_reportable",
|
|
10
10
|
]
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Optional, Type
|
|
2
|
-
|
|
3
1
|
from django.db import models
|
|
4
2
|
|
|
5
3
|
from .field_attrs import get_field_attrs_for_reportable, get_field_attrs_for_utestid
|
|
@@ -10,13 +8,13 @@ __all__ = ["reportable_result_model_mixin_factory"]
|
|
|
10
8
|
def reportable_result_model_mixin_factory(
|
|
11
9
|
utest_id: str,
|
|
12
10
|
units_choices: tuple,
|
|
13
|
-
default_units:
|
|
14
|
-
verbose_name:
|
|
15
|
-
decimal_places:
|
|
16
|
-
max_digits:
|
|
17
|
-
validators:
|
|
18
|
-
exclude_attrs_for_reportable:
|
|
19
|
-
) ->
|
|
11
|
+
default_units: str | None = None,
|
|
12
|
+
verbose_name: str | None = None,
|
|
13
|
+
decimal_places: int | None = None,
|
|
14
|
+
max_digits: int | None = None,
|
|
15
|
+
validators: list | None = None,
|
|
16
|
+
exclude_attrs_for_reportable: bool | None = None,
|
|
17
|
+
) -> type[models.Model]:
|
|
20
18
|
"""Returns an abstract model class with a single field class"""
|
|
21
19
|
|
|
22
20
|
class AbstractModel(models.Model):
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Optional, Type
|
|
2
|
-
|
|
3
1
|
from django.db import models
|
|
4
2
|
|
|
5
3
|
from .field_attrs import get_field_attrs_for_utestid
|
|
@@ -10,13 +8,13 @@ __all__ = ["result_model_mixin_factory"]
|
|
|
10
8
|
def result_model_mixin_factory(
|
|
11
9
|
utest_id: str,
|
|
12
10
|
units_choices: tuple,
|
|
13
|
-
default_units:
|
|
14
|
-
verbose_name:
|
|
15
|
-
decimal_places:
|
|
16
|
-
max_digits:
|
|
17
|
-
validators:
|
|
18
|
-
help_text:
|
|
19
|
-
) ->
|
|
11
|
+
default_units: str | None = None,
|
|
12
|
+
verbose_name: str | None = None,
|
|
13
|
+
decimal_places: int | None = None,
|
|
14
|
+
max_digits: int | None = None,
|
|
15
|
+
validators: list | None = None,
|
|
16
|
+
help_text: str | None = None,
|
|
17
|
+
) -> type[models.Model]:
|
|
20
18
|
"""Returns an abstract model class with a single field class"""
|
|
21
19
|
|
|
22
20
|
class AbstractModel(models.Model):
|
|
@@ -54,7 +54,7 @@ class FbgModelMixin(
|
|
|
54
54
|
)
|
|
55
55
|
|
|
56
56
|
def get_summary_options(self) -> dict:
|
|
57
|
-
opts = super().get_summary_options()
|
|
57
|
+
opts = super().get_summary_options()
|
|
58
58
|
fasting = True if self.fasting == FASTING else False
|
|
59
59
|
opts.update(fasting=fasting)
|
|
60
60
|
return opts
|
|
@@ -51,7 +51,7 @@ class GlucoseModelMixin(
|
|
|
51
51
|
)
|
|
52
52
|
|
|
53
53
|
def get_summary_options(self: Any) -> dict:
|
|
54
|
-
opts = super().get_summary_options()
|
|
54
|
+
opts = super().get_summary_options()
|
|
55
55
|
fasting = True if self.fasting == FASTING else False
|
|
56
56
|
opts.update(fasting=fasting)
|
|
57
57
|
return opts
|
edc_label/admin.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Tuple
|
|
2
|
-
|
|
3
1
|
from django.contrib import admin
|
|
4
2
|
from django.contrib.admin import ModelAdmin
|
|
5
3
|
from django_audit_fields import audit_fieldset_tuple
|
|
@@ -15,4 +13,4 @@ class ZplLabelTemplatesAdmin(ModelAdmin):
|
|
|
15
13
|
audit_fieldset_tuple,
|
|
16
14
|
)
|
|
17
15
|
|
|
18
|
-
search_fields:
|
|
16
|
+
search_fields: tuple[str, ...] = ("name",)
|
edc_label/label.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
1
|
from django.utils import timezone
|
|
4
2
|
|
|
5
3
|
from .label_template import LabelTemplate
|
|
@@ -14,8 +12,8 @@ class Label:
|
|
|
14
12
|
|
|
15
13
|
def __init__(
|
|
16
14
|
self,
|
|
17
|
-
label_template_name:
|
|
18
|
-
static_files_path:
|
|
15
|
+
label_template_name: str | None = None,
|
|
16
|
+
static_files_path: str | None = None,
|
|
19
17
|
):
|
|
20
18
|
if label_template_name:
|
|
21
19
|
self.label_template_name = label_template_name
|
edc_label/label_template.py
CHANGED
|
@@ -39,7 +39,7 @@ class LabelTemplate:
|
|
|
39
39
|
f"Looking for template '{template_name}'. "
|
|
40
40
|
f"Got {path}. See edc_label.app_config."
|
|
41
41
|
)
|
|
42
|
-
with open(path
|
|
42
|
+
with open(path) as f:
|
|
43
43
|
self.template = f.read()
|
|
44
44
|
else:
|
|
45
45
|
self.template = zpl_label_template.zpl_data.strip()
|
edc_label/subject_label.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
1
|
from django.apps import apps as django_apps
|
|
4
2
|
|
|
5
3
|
from edc_protocol.research_protocol_config import ResearchProtocolConfig
|
|
@@ -11,7 +9,7 @@ class SubjectLabel(Label):
|
|
|
11
9
|
template_name = None
|
|
12
10
|
registered_subject_model = "edc_registration.registeredsubject"
|
|
13
11
|
|
|
14
|
-
def __init__(self, subject_identifier:
|
|
12
|
+
def __init__(self, subject_identifier: str | None = None, site=None, **kwargs):
|
|
15
13
|
super().__init__(**kwargs)
|
|
16
14
|
self._registered_subject = None
|
|
17
15
|
self.subject_identifier = subject_identifier
|
edc_list_data/admin.py
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
from typing import Tuple
|
|
2
|
-
|
|
3
1
|
from django.contrib import admin
|
|
4
2
|
|
|
5
3
|
from edc_model_admin.mixins import TemplatesModelAdminMixin
|
|
6
4
|
|
|
7
5
|
|
|
8
6
|
class ListModelAdminMixin(TemplatesModelAdminMixin, admin.ModelAdmin):
|
|
9
|
-
ordering:
|
|
7
|
+
ordering: tuple[str, ...] = ("display_index", "display_name")
|
|
10
8
|
|
|
11
|
-
list_display:
|
|
9
|
+
list_display: tuple[str, ...] = ("display_name", "name", "display_index")
|
|
12
10
|
|
|
13
|
-
search_fields:
|
|
11
|
+
search_fields: tuple[str, ...] = ("display_name", "name")
|
edc_list_data/load_list_data.py
CHANGED
edc_list_data/load_model_data.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
1
|
from django.apps import AppConfig
|
|
4
2
|
from django.apps import apps as django_apps
|
|
5
3
|
from django.core.exceptions import ObjectDoesNotExist
|
|
@@ -10,7 +8,7 @@ class LoadModelDataError(Exception):
|
|
|
10
8
|
pass
|
|
11
9
|
|
|
12
10
|
|
|
13
|
-
def load_model_data(model_data: dict, apps:
|
|
11
|
+
def load_model_data(model_data: dict, apps: AppConfig | None = None) -> int:
|
|
14
12
|
"""Loads data into a model, creates or updates existing.
|
|
15
13
|
|
|
16
14
|
Must have a unique field
|
edc_list_data/model_mixins.py
CHANGED
|
@@ -54,13 +54,11 @@ class BaseListModelMixin(models.Model):
|
|
|
54
54
|
super().save(*args, **kwargs)
|
|
55
55
|
|
|
56
56
|
def natural_key(self) -> tuple:
|
|
57
|
-
return (self.name,)
|
|
57
|
+
return (self.name,)
|
|
58
58
|
|
|
59
59
|
class Meta:
|
|
60
60
|
abstract = True
|
|
61
|
-
indexes = [
|
|
62
|
-
models.Index(fields=["display_index", "display_name"]),
|
|
63
|
-
]
|
|
61
|
+
indexes = (models.Index(fields=["display_index", "display_name"]),)
|
|
64
62
|
default_permissions = ("add", "change", "delete", "view", "export", "import")
|
|
65
63
|
|
|
66
64
|
|
|
@@ -104,4 +102,4 @@ class ListUuidModelMixin(BaseListModelMixin, BaseUuidModel):
|
|
|
104
102
|
|
|
105
103
|
class Meta(BaseListModelMixin.Meta, BaseUuidModel.Meta):
|
|
106
104
|
abstract = True
|
|
107
|
-
indexes = BaseListModelMixin.Meta.indexes
|
|
105
|
+
indexes = (*BaseListModelMixin.Meta.indexes, *BaseUuidModel.Meta.indexes)
|
edc_list_data/preload_data.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
1
|
from django.apps import AppConfig
|
|
4
2
|
from django.core.management.color import color_style
|
|
5
3
|
|
|
@@ -26,8 +24,8 @@ class PreloadData:
|
|
|
26
24
|
if self.model_data:
|
|
27
25
|
self.item_count += self.load_model_data()
|
|
28
26
|
|
|
29
|
-
def load_list_data(self, model_name: str = None, apps:
|
|
27
|
+
def load_list_data(self, model_name: str = None, apps: AppConfig | None = None) -> int:
|
|
30
28
|
return load_list_data(self.list_data, model_name=model_name, apps=apps)
|
|
31
29
|
|
|
32
|
-
def load_model_data(self, apps:
|
|
30
|
+
def load_model_data(self, apps: AppConfig | None = None) -> int:
|
|
33
31
|
return load_model_data(self.model_data, apps=apps)
|
edc_list_data/site_list_data.py
CHANGED
|
@@ -50,13 +50,12 @@ class SiteListData:
|
|
|
50
50
|
"""Registers but does NOT `load` list_data."""
|
|
51
51
|
if app_name and app_name in self.app_names:
|
|
52
52
|
raise AlreadyLoaded(f"App already loaded. Got {app_name}.")
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
self.registry[module.__name__] = opts
|
|
53
|
+
self.app_names.append(app_name)
|
|
54
|
+
opts = copy.deepcopy(self._get_options(module))
|
|
55
|
+
sys.stdout.write(f" - registered {self.module_name} from '{module.__name__}'\n")
|
|
56
|
+
if opts.get(self.module_name):
|
|
57
|
+
self._replace_list_data_or_raise_on_duplicate(module, opts)
|
|
58
|
+
self.registry[module.__name__] = opts
|
|
60
59
|
|
|
61
60
|
def load_data(self) -> None:
|
|
62
61
|
"""Calls `load` class with each list_data dictionary module to
|
|
@@ -24,8 +24,8 @@ class ListboardFilter:
|
|
|
24
24
|
|
|
25
25
|
def __repr__(self):
|
|
26
26
|
return (
|
|
27
|
-
"{
|
|
28
|
-
"exclude_filter={
|
|
27
|
+
f"{self.__class__.__name__}({self.name}, {self.label}, "
|
|
28
|
+
f"exclude_filter={self.exclude_filter}, {self.default})"
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
@property
|
|
@@ -114,9 +114,7 @@ class BaseListboardView(SiteViewMixin, TemplateRequestContextMixin, ListView):
|
|
|
114
114
|
Accepts `listboard_model` as a model class or label_lower.
|
|
115
115
|
"""
|
|
116
116
|
if not self.get_listboard_model():
|
|
117
|
-
raise ListboardViewError(
|
|
118
|
-
f"Listboard model not declared. Got None. See {repr(self)}"
|
|
119
|
-
)
|
|
117
|
+
raise ListboardViewError(f"Listboard model not declared. Got None. See {self!r}")
|
|
120
118
|
try:
|
|
121
119
|
return django_apps.get_model(self.get_listboard_model())
|
|
122
120
|
except (ValueError, AttributeError):
|
edc_locator/models.py
CHANGED
|
@@ -28,9 +28,9 @@ class SubjectLocator(
|
|
|
28
28
|
def natural_key(self):
|
|
29
29
|
return (self.subject_identifier,)
|
|
30
30
|
|
|
31
|
-
natural_key.dependencies =
|
|
31
|
+
natural_key.dependencies = ("sites.Site",)
|
|
32
32
|
|
|
33
33
|
class Meta(ActionModelMixin.Meta, BaseUuidModel.Meta):
|
|
34
34
|
verbose_name = "Subject Locator"
|
|
35
35
|
verbose_name_plural = "Subject Locators"
|
|
36
|
-
indexes = ActionModelMixin.Meta.indexes
|
|
36
|
+
indexes = (*ActionModelMixin.Meta.indexes, *BaseUuidModel.Meta.indexes)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING, Any
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
4
|
|
|
5
5
|
from django.apps import apps as django_apps
|
|
6
6
|
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
|
|
@@ -67,7 +67,7 @@ class SubjectLocatorViewMixin:
|
|
|
67
67
|
action_cls(subject_identifier=subject_identifier)
|
|
68
68
|
|
|
69
69
|
@property
|
|
70
|
-
def subject_locator_model_cls(self) ->
|
|
70
|
+
def subject_locator_model_cls(self) -> type[SubjectLocator]:
|
|
71
71
|
return django_apps.get_model(self.subject_locator_model)
|
|
72
72
|
|
|
73
73
|
@property
|
edc_ltfu/action_items.py
CHANGED
|
@@ -14,7 +14,7 @@ class LtfuAction(ActionWithNotification):
|
|
|
14
14
|
name = LTFU_ACTION
|
|
15
15
|
display_name = "Submit Loss to Follow Up Report"
|
|
16
16
|
notification_display_name = "Loss to Follow Up Report"
|
|
17
|
-
parent_action_names =
|
|
17
|
+
parent_action_names = (VISIT_MISSED_ACTION,)
|
|
18
18
|
show_link_to_changelist = True
|
|
19
19
|
priority = HIGH_PRIORITY
|
|
20
20
|
|
edc_ltfu/model_mixins.py
CHANGED
|
@@ -59,7 +59,6 @@ class LtfuModelMixin(models.Model):
|
|
|
59
59
|
|
|
60
60
|
home_visit_detail = models.TextField(
|
|
61
61
|
verbose_name="If YES, provide any further details of the home visit",
|
|
62
|
-
null=True,
|
|
63
62
|
blank=True,
|
|
64
63
|
)
|
|
65
64
|
|
|
@@ -76,7 +75,6 @@ class LtfuModelMixin(models.Model):
|
|
|
76
75
|
"If any, please give additional details of the "
|
|
77
76
|
"circumstances that led to this decision."
|
|
78
77
|
),
|
|
79
|
-
null=True,
|
|
80
78
|
blank=True,
|
|
81
79
|
)
|
|
82
80
|
|
edc_ltfu/models.py
CHANGED
|
@@ -22,8 +22,8 @@ class Ltfu(
|
|
|
22
22
|
verbose_name = "Loss to Follow Up"
|
|
23
23
|
verbose_name_plural = "Loss to Follow Ups"
|
|
24
24
|
indexes = (
|
|
25
|
-
NonUniqueSubjectIdentifierFieldMixin.Meta.indexes
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
*NonUniqueSubjectIdentifierFieldMixin.Meta.indexes,
|
|
26
|
+
*ActionModelMixin.Meta.indexes,
|
|
27
|
+
*BaseUuidModel.Meta.indexes,
|
|
28
|
+
models.Index(fields=["subject_identifier", "action_identifier", "site"]),
|
|
29
29
|
)
|
|
@@ -198,6 +198,6 @@ class MetadataModelAdminMixin(
|
|
|
198
198
|
def get_view_on_site_url(self, obj=None):
|
|
199
199
|
if obj is None or not self.view_on_site:
|
|
200
200
|
return None
|
|
201
|
-
|
|
201
|
+
if hasattr(obj, "get_absolute_url"):
|
|
202
202
|
url = reverse(self.changelist_url)
|
|
203
203
|
return f"{url}?q={obj.subject_identifier}"
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Tuple
|
|
2
|
-
|
|
3
1
|
from django.contrib import admin
|
|
4
2
|
|
|
5
3
|
from ..admin_site import edc_metadata_admin
|
|
@@ -21,12 +19,12 @@ class RequisitionMetadataAdmin(MetadataModelAdminMixin):
|
|
|
21
19
|
search_fields.append("panel_name")
|
|
22
20
|
return tuple(search_fields)
|
|
23
21
|
|
|
24
|
-
def get_list_display(self, request) ->
|
|
22
|
+
def get_list_display(self, request) -> tuple[str, ...]:
|
|
25
23
|
list_display = list(super().get_list_display(request))
|
|
26
24
|
list_display.insert(3, "panel_name")
|
|
27
25
|
return tuple(list_display)
|
|
28
26
|
|
|
29
|
-
def get_list_filter(self, request) ->
|
|
27
|
+
def get_list_filter(self, request) -> tuple[str, ...]:
|
|
30
28
|
list_filter = list(super().get_list_filter(request))
|
|
31
29
|
list_filter.insert(1, "panel_name")
|
|
32
30
|
return tuple(list_filter)
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Type
|
|
4
|
-
|
|
5
3
|
from .metadata_getter import MetadataGetter, MetadataValidator
|
|
6
4
|
|
|
7
5
|
|
|
@@ -12,4 +10,4 @@ class CrfMetadataValidator(MetadataValidator):
|
|
|
12
10
|
class CrfMetadataGetter(MetadataGetter):
|
|
13
11
|
metadata_model: str = "edc_metadata.crfmetadata"
|
|
14
12
|
|
|
15
|
-
metadata_validator_cls:
|
|
13
|
+
metadata_validator_cls: type[CrfMetadataValidator] = CrfMetadataValidator
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Type
|
|
4
|
-
|
|
5
3
|
from .metadata_getter import MetadataGetter, MetadataValidator
|
|
6
4
|
|
|
7
5
|
|
|
@@ -14,4 +12,4 @@ class RequisitionMetadataValidator(MetadataValidator):
|
|
|
14
12
|
class RequisitionMetadataGetter(MetadataGetter):
|
|
15
13
|
metadata_model: str = "edc_metadata.requisitionmetadata"
|
|
16
14
|
|
|
17
|
-
metadata_validator_cls:
|
|
15
|
+
metadata_validator_cls: type[RequisitionMetadataValidator] = RequisitionMetadataValidator
|
edc_metadata/metadata_handler.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from django.apps import apps as django_apps
|
|
6
6
|
from django.core.exceptions import ObjectDoesNotExist
|
|
@@ -48,7 +48,7 @@ class MetadataHandler:
|
|
|
48
48
|
self.creator = self.creator_cls(related_visit=self.related_visit, update_keyed=True)
|
|
49
49
|
|
|
50
50
|
@property
|
|
51
|
-
def metadata_model_cls(self) ->
|
|
51
|
+
def metadata_model_cls(self) -> type[CrfMetadata] | type[RequisitionMetadata]:
|
|
52
52
|
return django_apps.get_model(self.metadata_model)
|
|
53
53
|
|
|
54
54
|
@property
|
|
@@ -13,7 +13,7 @@ if TYPE_CHECKING:
|
|
|
13
13
|
from ..models import CrfMetadata, RequisitionMetadata
|
|
14
14
|
else:
|
|
15
15
|
|
|
16
|
-
class VisitScheduleFieldsProtocol: ...
|
|
16
|
+
class VisitScheduleFieldsProtocol: ...
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class MetadataHelperMixin(VisitScheduleFieldsProtocol):
|
|
@@ -30,8 +30,7 @@ class MetadataHelperMixin(VisitScheduleFieldsProtocol):
|
|
|
30
30
|
def metadata_helper_instance(self):
|
|
31
31
|
if self.metadata_helper_instance_attr:
|
|
32
32
|
return getattr(self, self.metadata_helper_instance_attr)
|
|
33
|
-
|
|
34
|
-
return self
|
|
33
|
+
return self
|
|
35
34
|
|
|
36
35
|
@property
|
|
37
36
|
def crf_metadata_exists(self) -> bool:
|