clinicedc 2.0.4__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.4.dist-info → clinicedc-2.0.5.dist-info}/METADATA +41 -45
- {clinicedc-2.0.4.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 +1 -1
- 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.4.dist-info → clinicedc-2.0.5.dist-info}/WHEEL +0 -0
- {clinicedc-2.0.4.dist-info → clinicedc-2.0.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -11,6 +11,13 @@ from edc_model.models import BaseUuidModel
|
|
|
11
11
|
from ..choices import PRIORITY
|
|
12
12
|
from ..exceptions import ActionTypeError
|
|
13
13
|
|
|
14
|
+
MISSING_ACTION_CLASS = "Model missing an action class. See {reference_model_cls!r}"
|
|
15
|
+
NOT_CONFIGURED_FOR_ACTIONS = (
|
|
16
|
+
"Model not configured for Actions. Are you using the model mixin? "
|
|
17
|
+
"See {reference_model_cls!r}. Got {err}"
|
|
18
|
+
)
|
|
19
|
+
REFERENCE_MODEL_LOOKUP_ERROR = "{err}. Got reference_model=`{reference_model}`"
|
|
20
|
+
|
|
14
21
|
|
|
15
22
|
class ActionTypeManager(models.Manager):
|
|
16
23
|
use_in_migrations = True
|
|
@@ -25,11 +32,17 @@ class ActionType(BaseUuidModel):
|
|
|
25
32
|
display_name = models.CharField(max_length=100)
|
|
26
33
|
|
|
27
34
|
reference_model = models.CharField(
|
|
28
|
-
max_length=100,
|
|
35
|
+
max_length=100,
|
|
36
|
+
blank=True,
|
|
37
|
+
default="",
|
|
38
|
+
help_text="reference model",
|
|
29
39
|
)
|
|
30
40
|
|
|
31
41
|
related_reference_model = models.CharField(
|
|
32
|
-
max_length=100,
|
|
42
|
+
max_length=100,
|
|
43
|
+
blank=True,
|
|
44
|
+
default="",
|
|
45
|
+
help_text="origin reference model",
|
|
33
46
|
)
|
|
34
47
|
|
|
35
48
|
priority = models.CharField(max_length=25, choices=PRIORITY, default=HIGH_PRIORITY)
|
|
@@ -46,7 +59,7 @@ class ActionType(BaseUuidModel):
|
|
|
46
59
|
default=True, help_text="This action may be created by the user"
|
|
47
60
|
)
|
|
48
61
|
|
|
49
|
-
instructions = models.TextField(max_length=250,
|
|
62
|
+
instructions = models.TextField(max_length=250, blank=True, default="")
|
|
50
63
|
|
|
51
64
|
objects = ActionTypeManager()
|
|
52
65
|
|
|
@@ -54,7 +67,7 @@ class ActionType(BaseUuidModel):
|
|
|
54
67
|
return self.display_name
|
|
55
68
|
|
|
56
69
|
def natural_key(self) -> tuple:
|
|
57
|
-
return (self.name,)
|
|
70
|
+
return (self.name,)
|
|
58
71
|
|
|
59
72
|
@property
|
|
60
73
|
def reference_model_cls(self) -> Any:
|
|
@@ -63,7 +76,11 @@ class ActionType(BaseUuidModel):
|
|
|
63
76
|
try:
|
|
64
77
|
model_cls = django_apps.get_model(self.reference_model)
|
|
65
78
|
except (LookupError, ValueError) as e:
|
|
66
|
-
raise ActionTypeError(
|
|
79
|
+
raise ActionTypeError(
|
|
80
|
+
REFERENCE_MODEL_LOOKUP_ERROR.format(
|
|
81
|
+
err=str(e), reference_model=self.reference_model
|
|
82
|
+
)
|
|
83
|
+
) from e
|
|
67
84
|
return model_cls
|
|
68
85
|
|
|
69
86
|
def save(self, *args, **kwargs):
|
|
@@ -72,20 +89,23 @@ class ActionType(BaseUuidModel):
|
|
|
72
89
|
try:
|
|
73
90
|
if not self.reference_model_cls.action_name:
|
|
74
91
|
raise ActionTypeError(
|
|
75
|
-
|
|
92
|
+
MISSING_ACTION_CLASS.format(
|
|
93
|
+
reference_model_cls=self.reference_model_cls
|
|
94
|
+
)
|
|
76
95
|
)
|
|
77
96
|
except AttributeError as e:
|
|
78
97
|
if "action_name" in str(e):
|
|
79
98
|
raise ActionTypeError(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
99
|
+
NOT_CONFIGURED_FOR_ACTIONS.format(
|
|
100
|
+
reference_model_cls=self.reference_model_cls, err=str(e)
|
|
101
|
+
)
|
|
102
|
+
) from e
|
|
103
|
+
raise
|
|
85
104
|
super().save(*args, **kwargs)
|
|
86
105
|
|
|
87
106
|
class Meta(BaseUuidModel.Meta):
|
|
88
|
-
indexes =
|
|
107
|
+
indexes = (
|
|
108
|
+
*BaseUuidModel.Meta.indexes,
|
|
89
109
|
models.Index(fields=["id", "name"]),
|
|
90
|
-
|
|
110
|
+
)
|
|
91
111
|
default_permissions = ("add", "change", "delete", "view", "export", "import")
|
|
@@ -33,9 +33,10 @@ class Reference(NonUniqueSubjectIdentifierFieldMixin, ActionModelMixin, BaseUuid
|
|
|
33
33
|
objects = ReferenceManager()
|
|
34
34
|
|
|
35
35
|
def natural_key(self):
|
|
36
|
-
return (self.action_identifier,)
|
|
36
|
+
return (self.action_identifier,)
|
|
37
37
|
|
|
38
38
|
class Meta(BaseUuidModel.Meta, NonUniqueSubjectIdentifierFieldMixin.Meta):
|
|
39
39
|
indexes = (
|
|
40
|
-
BaseUuidModel.Meta.indexes
|
|
40
|
+
*BaseUuidModel.Meta.indexes,
|
|
41
|
+
*NonUniqueSubjectIdentifierFieldMixin.Meta.indexes,
|
|
41
42
|
)
|
|
@@ -4,7 +4,7 @@ import copy
|
|
|
4
4
|
import sys
|
|
5
5
|
from dataclasses import InitVar, dataclass, field
|
|
6
6
|
from importlib import import_module
|
|
7
|
-
from typing import TYPE_CHECKING
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
8
|
|
|
9
9
|
from django.apps import apps as django_apps
|
|
10
10
|
from django.core.management.color import color_style
|
|
@@ -36,12 +36,12 @@ class SiteActionError(Exception):
|
|
|
36
36
|
|
|
37
37
|
@dataclass
|
|
38
38
|
class ActionButton:
|
|
39
|
-
action_cls: InitVar[
|
|
39
|
+
action_cls: InitVar[type[Action] | type[ActionWithNotification]] = None
|
|
40
40
|
name: str = field(init=False)
|
|
41
41
|
display_name: str = field(init=False)
|
|
42
42
|
action_type_id: str = field(init=False)
|
|
43
43
|
|
|
44
|
-
def __post_init__(self, action_cls:
|
|
44
|
+
def __post_init__(self, action_cls: type[Action] | type[ActionWithNotification]):
|
|
45
45
|
self.name = action_cls.name
|
|
46
46
|
self.display_name = action_cls.display_name
|
|
47
47
|
self.action_type_id = str(get_action_type(action_cls).pk)
|
|
@@ -49,7 +49,7 @@ class ActionButton:
|
|
|
49
49
|
|
|
50
50
|
class SiteActionItemCollection:
|
|
51
51
|
def __init__(self):
|
|
52
|
-
self.registry: dict[str,
|
|
52
|
+
self.registry: dict[str, type[Action] | type[ActionWithNotification]] = {}
|
|
53
53
|
self.updated_action_types: bool | None = None
|
|
54
54
|
prn = Prn(model="edc_action_item.actionitem", url_namespace="edc_action_item_admin")
|
|
55
55
|
site_prn_forms.register(prn)
|
|
@@ -63,7 +63,7 @@ class SiteActionItemCollection:
|
|
|
63
63
|
def __iter__(self):
|
|
64
64
|
return iter(self.registry.values())
|
|
65
65
|
|
|
66
|
-
def unregister(self, action_cls:
|
|
66
|
+
def unregister(self, action_cls: type[Action] | type[ActionWithNotification]) -> None:
|
|
67
67
|
if action_cls.name in self.registry:
|
|
68
68
|
del self.registry[action_cls.name]
|
|
69
69
|
prn = Prn(
|
|
@@ -72,14 +72,13 @@ class SiteActionItemCollection:
|
|
|
72
72
|
)
|
|
73
73
|
site_prn_forms.unregister(prn)
|
|
74
74
|
|
|
75
|
-
def register(self, action_cls:
|
|
75
|
+
def register(self, action_cls: type[Action] | type[ActionWithNotification] = None) -> None:
|
|
76
76
|
if action_cls.name in self.registry:
|
|
77
77
|
raise AlreadyRegistered(
|
|
78
78
|
f"Action class is already registered. Got name='{action_cls.name}' "
|
|
79
79
|
f"for {action_cls.__name__}"
|
|
80
80
|
)
|
|
81
|
-
|
|
82
|
-
self.registry.update({action_cls.name: action_cls})
|
|
81
|
+
self.registry.update({action_cls.name: action_cls})
|
|
83
82
|
if action_cls.show_link_to_changelist:
|
|
84
83
|
prn = Prn(
|
|
85
84
|
model=action_cls.get_reference_model(),
|
|
@@ -97,7 +96,7 @@ class SiteActionItemCollection:
|
|
|
97
96
|
self.register_notifications(action_cls)
|
|
98
97
|
|
|
99
98
|
@staticmethod
|
|
100
|
-
def register_notifications(action_cls:
|
|
99
|
+
def register_notifications(action_cls: type[Action] | type[ActionWithNotification]):
|
|
101
100
|
"""Registers a new model notification and an updated model
|
|
102
101
|
notification for this action cls.
|
|
103
102
|
|
|
@@ -110,10 +109,10 @@ class SiteActionItemCollection:
|
|
|
110
109
|
pass
|
|
111
110
|
|
|
112
111
|
@property
|
|
113
|
-
def all(self) -> dict[str,
|
|
112
|
+
def all(self) -> dict[str, type[Action] | type[ActionWithNotification]]:
|
|
114
113
|
return self.registry
|
|
115
114
|
|
|
116
|
-
def get(self, name) ->
|
|
115
|
+
def get(self, name) -> type[Action] | type[ActionWithNotification]:
|
|
117
116
|
"""Returns an action class."""
|
|
118
117
|
if name not in self.registry:
|
|
119
118
|
raise SiteActionError(
|
|
@@ -122,14 +121,14 @@ class SiteActionItemCollection:
|
|
|
122
121
|
)
|
|
123
122
|
return self.registry.get(name)
|
|
124
123
|
|
|
125
|
-
def get_by_model(self, model=None) ->
|
|
124
|
+
def get_by_model(self, model=None) -> type[Action] | type[ActionWithNotification] | None:
|
|
126
125
|
"""Returns the action_cls linked to this reference model."""
|
|
127
126
|
for action_cls in self.registry.values():
|
|
128
127
|
if action_cls.get_reference_model() == model:
|
|
129
128
|
return self.get(action_cls.name)
|
|
130
129
|
return None
|
|
131
130
|
|
|
132
|
-
def get_add_actions_to_show(self) -> dict[str,
|
|
131
|
+
def get_add_actions_to_show(self) -> dict[str, type[Action]]:
|
|
133
132
|
actions = {
|
|
134
133
|
action_cls.name: action_cls
|
|
135
134
|
for action_cls in self.registry.values()
|
|
@@ -164,7 +163,7 @@ class SiteActionItemCollection:
|
|
|
164
163
|
except ImportError as e:
|
|
165
164
|
site_action_items.registry = before_import_registry
|
|
166
165
|
if module_has_submodule(mod, module_name):
|
|
167
|
-
raise SiteActionError(str(e))
|
|
166
|
+
raise SiteActionError(str(e)) from e
|
|
168
167
|
except ImportError:
|
|
169
168
|
pass
|
|
170
169
|
# except Exception as e:
|
edc_action_item/stubs.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Optional, Protocol
|
|
1
|
+
from typing import Optional, Protocol
|
|
2
2
|
from uuid import UUID
|
|
3
3
|
|
|
4
4
|
from django.db import models
|
|
@@ -8,20 +8,20 @@ class ActionStub(Protocol):
|
|
|
8
8
|
def __init__(
|
|
9
9
|
self,
|
|
10
10
|
action_item: Optional["ActionItemStub"] = None,
|
|
11
|
-
reference_obj:
|
|
11
|
+
reference_obj: models.Model | None = None,
|
|
12
12
|
subject_identifier: str = None,
|
|
13
13
|
action_identifier: str = None,
|
|
14
14
|
parent_action_item: Optional["ActionItemStub"] = None,
|
|
15
15
|
related_action_item: Optional["ActionItemStub"] = None,
|
|
16
|
-
using:
|
|
17
|
-
readonly:
|
|
16
|
+
using: str | None = None,
|
|
17
|
+
readonly: bool | None = None,
|
|
18
18
|
) -> None: ...
|
|
19
19
|
|
|
20
20
|
name: str
|
|
21
21
|
action_item: "ActionItemStub"
|
|
22
22
|
action_identifier: str
|
|
23
|
-
related_reference_model:
|
|
24
|
-
related_reference_fk_attr:
|
|
23
|
+
related_reference_model: str | None
|
|
24
|
+
related_reference_fk_attr: str | None
|
|
25
25
|
subject_identifier: str
|
|
26
26
|
related_action_item: Optional["ActionItemStub"]
|
|
27
27
|
...
|
|
@@ -30,8 +30,8 @@ class ActionStub(Protocol):
|
|
|
30
30
|
class ActionTypeStub(Protocol):
|
|
31
31
|
name: str
|
|
32
32
|
display_name: str
|
|
33
|
-
reference_model:
|
|
34
|
-
related_reference_model:
|
|
33
|
+
reference_model: str | None
|
|
34
|
+
related_reference_model: str | None
|
|
35
35
|
...
|
|
36
36
|
|
|
37
37
|
|
|
@@ -53,7 +53,7 @@ class ActionItemStub(Protocol):
|
|
|
53
53
|
|
|
54
54
|
def get_status_display(self) -> str: ...
|
|
55
55
|
|
|
56
|
-
def get_action_cls(self) ->
|
|
56
|
+
def get_action_cls(self) -> type[ActionStub]: ...
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
class ActionItemWithNotificationStub(ActionItemStub, Protocol):
|
|
@@ -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 import template
|
|
6
6
|
|
|
@@ -74,7 +74,7 @@ def add_action_item_popover(
|
|
|
74
74
|
`Add action linked PRN forms`
|
|
75
75
|
"""
|
|
76
76
|
action_item_add_url: str = "edc_action_item_admin:edc_action_item_actionitem_add"
|
|
77
|
-
add_actions: dict[str,
|
|
77
|
+
add_actions: dict[str, type[Action]] = site_action_items.get_add_actions_to_show()
|
|
78
78
|
if add_actions:
|
|
79
79
|
d = {k: v.display_name for k, v in add_actions.items()}
|
|
80
80
|
add_actions = {}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
5
|
from uuid import UUID
|
|
6
6
|
|
|
7
7
|
from django.contrib.sites.models import Site
|
|
@@ -18,9 +18,9 @@ if TYPE_CHECKING:
|
|
|
18
18
|
|
|
19
19
|
@dataclass(kw_only=True)
|
|
20
20
|
class ActionItemButton(ModelButton):
|
|
21
|
-
action_cls:
|
|
21
|
+
action_cls: type[Action] = None
|
|
22
22
|
model_obj: ActionItem | None = None
|
|
23
|
-
model_cls:
|
|
23
|
+
model_cls: type[ActionItem] = field(default=None)
|
|
24
24
|
appointment: Appointment = None
|
|
25
25
|
next_url_name: str = field(default="subject_dashboard_url")
|
|
26
26
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
5
|
from uuid import UUID
|
|
6
6
|
|
|
7
7
|
from django.core.exceptions import ObjectDoesNotExist
|
|
@@ -17,9 +17,9 @@ if TYPE_CHECKING:
|
|
|
17
17
|
|
|
18
18
|
class PrnModel(BaseUuidModel):
|
|
19
19
|
subject_identifier: str
|
|
20
|
-
...
|
|
20
|
+
...
|
|
21
21
|
|
|
22
|
-
class CrfModel(CrfModelMixin): ...
|
|
22
|
+
class CrfModel(CrfModelMixin): ...
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
@dataclass
|
|
@@ -28,7 +28,7 @@ class ActionItemPopoverListItem(PrnButton):
|
|
|
28
28
|
category: str = None
|
|
29
29
|
appointment: Appointment | None = None
|
|
30
30
|
model_obj: PrnModel | CrfModel | None = field(default=None, init=False)
|
|
31
|
-
model_cls:
|
|
31
|
+
model_cls: type[PrnModel | CrfModel | None] = field(default=None, init=False)
|
|
32
32
|
|
|
33
33
|
def __post_init__(self):
|
|
34
34
|
if self.category == "reference":
|
|
@@ -35,7 +35,7 @@ class AeFollowupAction(ActionWithNotification):
|
|
|
35
35
|
name = AE_FOLLOWUP_ACTION
|
|
36
36
|
display_name = "Submit AE Followup Report"
|
|
37
37
|
notification_display_name = "AE Followup Report"
|
|
38
|
-
parent_action_names =
|
|
38
|
+
parent_action_names = (AE_INITIAL_ACTION, AE_FOLLOWUP_ACTION)
|
|
39
39
|
related_reference_fk_attr = "ae_initial"
|
|
40
40
|
create_by_user = False
|
|
41
41
|
show_link_to_changelist = True
|
|
@@ -15,7 +15,7 @@ class AeInitialAction(ActionWithNotification):
|
|
|
15
15
|
name = AE_INITIAL_ACTION
|
|
16
16
|
display_name = "Submit AE Initial Report"
|
|
17
17
|
notification_display_name = "AE Initial Report"
|
|
18
|
-
parent_action_names =
|
|
18
|
+
parent_action_names = ()
|
|
19
19
|
reference_model = f"{ADVERSE_EVENT_APP_LABEL}.aeinitial"
|
|
20
20
|
show_link_to_changelist = True
|
|
21
21
|
show_link_to_add = True
|
|
@@ -13,7 +13,7 @@ class AeSusarAction(ActionWithNotification):
|
|
|
13
13
|
name = AE_SUSAR_ACTION
|
|
14
14
|
display_name = "Submit AE SUSAR Report"
|
|
15
15
|
notification_display_name = "AE SUSAR Report"
|
|
16
|
-
parent_action_names =
|
|
16
|
+
parent_action_names = (AE_INITIAL_ACTION,)
|
|
17
17
|
reference_model = f"{ADVERSE_EVENT_APP_LABEL}.aesusar"
|
|
18
18
|
related_reference_model = f"{ADVERSE_EVENT_APP_LABEL}.aeinitial"
|
|
19
19
|
related_reference_fk_attr = "ae_initial"
|
|
@@ -13,7 +13,7 @@ class AeTmgAction(ActionWithNotification):
|
|
|
13
13
|
name = AE_TMG_ACTION
|
|
14
14
|
display_name = "TMG AE Report pending"
|
|
15
15
|
notification_display_name = "TMG AE Report"
|
|
16
|
-
parent_action_names =
|
|
16
|
+
parent_action_names = (AE_INITIAL_ACTION, AE_FOLLOWUP_ACTION, AE_TMG_ACTION)
|
|
17
17
|
reference_model = f"{ADVERSE_EVENT_APP_LABEL}.aetmg"
|
|
18
18
|
related_reference_model = f"{ADVERSE_EVENT_APP_LABEL}.aeinitial"
|
|
19
19
|
related_reference_fk_attr = "ae_initial"
|
|
@@ -17,12 +17,11 @@ class DeathReportAction(ActionWithNotification):
|
|
|
17
17
|
name = DEATH_REPORT_ACTION
|
|
18
18
|
display_name = "Submit Death Report"
|
|
19
19
|
notification_display_name = "Death Report"
|
|
20
|
-
parent_action_names =
|
|
20
|
+
parent_action_names = (AE_INITIAL_ACTION, AE_FOLLOWUP_ACTION)
|
|
21
21
|
show_link_to_changelist = True
|
|
22
22
|
show_link_to_add = True
|
|
23
23
|
priority = HIGH_PRIORITY
|
|
24
24
|
singleton = True
|
|
25
|
-
dirty_fields = ["cause_of_death"]
|
|
26
25
|
enable_tmg_workflow = True
|
|
27
26
|
|
|
28
27
|
reference_model = f"{ADVERSE_EVENT_APP_LABEL}.deathreport"
|
|
@@ -14,7 +14,7 @@ class DeathReportTmgAction(ActionWithNotification):
|
|
|
14
14
|
name = DEATH_REPORT_TMG_ACTION
|
|
15
15
|
display_name = "TMG Death Report (1st) pending"
|
|
16
16
|
notification_display_name = "TMG Death Report (1st)"
|
|
17
|
-
parent_action_names =
|
|
17
|
+
parent_action_names = (DEATH_REPORT_ACTION,)
|
|
18
18
|
related_reference_fk_attr = "death_report"
|
|
19
19
|
priority = HIGH_PRIORITY
|
|
20
20
|
create_by_user = False
|
|
@@ -13,7 +13,7 @@ class DeathReportTmgSecondAction(ActionWithNotification):
|
|
|
13
13
|
name = DEATH_REPORT_TMG_SECOND_ACTION
|
|
14
14
|
display_name = "TMG Death Report (2nd) pending"
|
|
15
15
|
notification_display_name = "TMG Death Report (2nd)"
|
|
16
|
-
parent_action_names =
|
|
16
|
+
parent_action_names = (DEATH_REPORT_TMG_ACTION,)
|
|
17
17
|
related_reference_fk_attr = "death_report"
|
|
18
18
|
priority = HIGH_PRIORITY
|
|
19
19
|
create_by_user = False
|
|
@@ -11,7 +11,7 @@ class HospitalizationAction(ActionWithNotification):
|
|
|
11
11
|
name = HOSPITALIZATION_ACTION
|
|
12
12
|
display_name = "Submit Hospitalization Report"
|
|
13
13
|
notification_display_name = "Hospitalization"
|
|
14
|
-
parent_action_names =
|
|
14
|
+
parent_action_names = ()
|
|
15
15
|
show_link_to_changelist = True
|
|
16
16
|
show_link_to_add = True
|
|
17
17
|
priority = HIGH_PRIORITY
|
|
@@ -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
|
from zoneinfo import ZoneInfo
|
|
5
5
|
|
|
6
6
|
from django import forms
|
|
@@ -56,7 +56,7 @@ class DeathReportFormValidatorMixin:
|
|
|
56
56
|
|
|
57
57
|
def validate_study_day_with_death_report_date(
|
|
58
58
|
self: Any,
|
|
59
|
-
subject_identifier:
|
|
59
|
+
subject_identifier: str | None = None,
|
|
60
60
|
) -> None:
|
|
61
61
|
"""Raises an exception if study day does not match
|
|
62
62
|
calculation against ZoneInfo.
|
|
@@ -73,7 +73,7 @@ class DeathReportFormValidatorMixin:
|
|
|
73
73
|
or self.instance.subject_identifier
|
|
74
74
|
)
|
|
75
75
|
if not subject_identifier:
|
|
76
|
-
raise ValueError(f"Subject identifier cannot be None. See {
|
|
76
|
+
raise ValueError(f"Subject identifier cannot be None. See {self!r}")
|
|
77
77
|
registered_subject_model_cls = django_apps.get_model(
|
|
78
78
|
"edc_registration.registeredsubject"
|
|
79
79
|
)
|
|
@@ -56,7 +56,7 @@ class BaseRequiresDeathReportFormValidatorMixin:
|
|
|
56
56
|
instance.
|
|
57
57
|
"""
|
|
58
58
|
death_report = self.death_report_or_raises
|
|
59
|
-
value = getattr(death_report,
|
|
59
|
+
value = getattr(death_report, death_report.death_date_field)
|
|
60
60
|
|
|
61
61
|
try:
|
|
62
62
|
death_report_date = value.astimezone(ZoneInfo("UTC")).date()
|
|
@@ -105,7 +105,7 @@ class RequiresDeathReportFormValidatorMixin(BaseRequiresDeathReportFormValidator
|
|
|
105
105
|
"death report form first."
|
|
106
106
|
}
|
|
107
107
|
)
|
|
108
|
-
|
|
108
|
+
if (
|
|
109
109
|
self.cleaned_data.get(self.offschedule_reason_field).name != DEAD
|
|
110
110
|
and self.death_report
|
|
111
111
|
):
|
|
@@ -125,7 +125,7 @@ class RequiresDeathReportFormValidatorMixin(BaseRequiresDeathReportFormValidator
|
|
|
125
125
|
)
|
|
126
126
|
}
|
|
127
127
|
)
|
|
128
|
-
|
|
128
|
+
if self.cleaned_data.get(self.death_date_field) and self.death_report:
|
|
129
129
|
self.match_date_of_death_or_raise()
|
|
130
130
|
|
|
131
131
|
def match_date_of_death_or_raise(self) -> None:
|
|
@@ -153,4 +153,3 @@ class RequiresDeathReportFormValidatorMixin(BaseRequiresDeathReportFormValidator
|
|
|
153
153
|
)
|
|
154
154
|
}
|
|
155
155
|
)
|
|
156
|
-
return None
|
|
@@ -27,7 +27,7 @@ class DeathReportTmgFormValidator(
|
|
|
27
27
|
)
|
|
28
28
|
except ObjectDoesNotExist:
|
|
29
29
|
self.raise_validation_error("Death report not found.", INVALID_ERROR)
|
|
30
|
-
death_date = getattr(obj,
|
|
30
|
+
death_date = getattr(obj, obj.death_date_field)
|
|
31
31
|
try:
|
|
32
32
|
death_date = death_date.date()
|
|
33
33
|
except AttributeError:
|
|
@@ -7,6 +7,9 @@ class AeFollowupMethodsModelMixin(models.Model):
|
|
|
7
7
|
def __str__(self):
|
|
8
8
|
return f"{self.action_identifier[-9:]}"
|
|
9
9
|
|
|
10
|
+
class Meta:
|
|
11
|
+
abstract = True
|
|
12
|
+
|
|
10
13
|
def save(self, *args, **kwargs):
|
|
11
14
|
self.subject_identifier = self.ae_initial.subject_identifier
|
|
12
15
|
super().save(*args, **kwargs)
|
|
@@ -27,6 +30,3 @@ class AeFollowupMethodsModelMixin(models.Model):
|
|
|
27
30
|
|
|
28
31
|
def get_action_item_reason(self):
|
|
29
32
|
return self.ae_initial.ae_description
|
|
30
|
-
|
|
31
|
-
class Meta:
|
|
32
|
-
abstract = True
|
|
@@ -35,7 +35,7 @@ class AeFollowupModelMixin(
|
|
|
35
35
|
abstract = True
|
|
36
36
|
verbose_name = "AE Follow-up Report"
|
|
37
37
|
indexes = (
|
|
38
|
-
NonUniqueSubjectIdentifierFieldMixin.Meta.indexes
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
*NonUniqueSubjectIdentifierFieldMixin.Meta.indexes,
|
|
39
|
+
*ActionModelMixin.Meta.indexes,
|
|
40
|
+
models.Index(fields=["subject_identifier", "action_identifier", "site", "id"]),
|
|
41
41
|
)
|
|
@@ -3,6 +3,9 @@ from django.db import models
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class AeInitialMethodsModelMixin(models.Model):
|
|
6
|
+
class Meta:
|
|
7
|
+
abstract = True
|
|
8
|
+
|
|
6
9
|
def __str__(self):
|
|
7
10
|
return f"{self.action_identifier[-9:]} Grade {self.ae_grade}"
|
|
8
11
|
|
|
@@ -26,6 +29,3 @@ class AeInitialMethodsModelMixin(models.Model):
|
|
|
26
29
|
def description(self):
|
|
27
30
|
"""Returns a description."""
|
|
28
31
|
return f"{self.action_identifier[-9:]} Grade-{self.ae_grade}. {self.ae_description}"
|
|
29
|
-
|
|
30
|
-
class Meta:
|
|
31
|
-
abstract = True
|
|
@@ -44,7 +44,7 @@ class AeInitialModelMixin(
|
|
|
44
44
|
abstract = True
|
|
45
45
|
verbose_name = "AE Initial Report"
|
|
46
46
|
indexes = (
|
|
47
|
-
NonUniqueSubjectIdentifierFieldMixin.Meta.indexes
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
*NonUniqueSubjectIdentifierFieldMixin.Meta.indexes,
|
|
48
|
+
*ActionModelMixin.Meta.indexes,
|
|
49
|
+
models.Index(fields=["subject_identifier", "action_identifier", "site"]),
|
|
50
50
|
)
|
|
@@ -2,6 +2,9 @@ from django.db import models
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class AesiMethodsModelMixin(models.Model):
|
|
5
|
+
class Meta:
|
|
6
|
+
abstract = True
|
|
7
|
+
|
|
5
8
|
def __str__(self):
|
|
6
9
|
return f"{self.action_identifier[-9:]}"
|
|
7
10
|
|
|
@@ -10,7 +13,4 @@ class AesiMethodsModelMixin(models.Model):
|
|
|
10
13
|
super().save(*args, **kwargs)
|
|
11
14
|
|
|
12
15
|
def natural_key(self):
|
|
13
|
-
return (self.action_identifier,)
|
|
14
|
-
|
|
15
|
-
class Meta:
|
|
16
|
-
abstract = True
|
|
16
|
+
return (self.action_identifier,)
|
|
@@ -33,7 +33,7 @@ class AesiModelMixin(
|
|
|
33
33
|
abstract = True
|
|
34
34
|
verbose_name = "AE of Special Interest Report"
|
|
35
35
|
indexes = (
|
|
36
|
-
NonUniqueSubjectIdentifierFieldMixin.Meta.indexes
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
*NonUniqueSubjectIdentifierFieldMixin.Meta.indexes,
|
|
37
|
+
*ActionModelMixin.Meta.indexes,
|
|
38
|
+
models.Index(fields=["subject_identifier", "action_identifier", "site", "id"]),
|
|
39
39
|
)
|
|
@@ -4,6 +4,9 @@ from edc_constants.constants import CLOSED, OPEN
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class AeSusarMethodsModelMixin(models.Model):
|
|
7
|
+
class Meta:
|
|
8
|
+
abstract = True
|
|
9
|
+
|
|
7
10
|
def __str__(self):
|
|
8
11
|
return f"{self.action_identifier[-9:]}"
|
|
9
12
|
|
|
@@ -18,7 +21,4 @@ class AeSusarMethodsModelMixin(models.Model):
|
|
|
18
21
|
super().save(*args, **kwargs)
|
|
19
22
|
|
|
20
23
|
def natural_key(self):
|
|
21
|
-
return (self.action_identifier,)
|
|
22
|
-
|
|
23
|
-
class Meta:
|
|
24
|
-
abstract = True
|
|
24
|
+
return (self.action_identifier,)
|
|
@@ -34,7 +34,7 @@ class AeSusarModelMixin(
|
|
|
34
34
|
verbose_name = "AE SUSAR Report"
|
|
35
35
|
verbose_name_plural = "AE SUSAR Reports"
|
|
36
36
|
indexes = (
|
|
37
|
-
NonUniqueSubjectIdentifierFieldMixin.Meta.indexes
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
*NonUniqueSubjectIdentifierFieldMixin.Meta.indexes,
|
|
38
|
+
*ActionModelMixin.Meta.indexes,
|
|
39
|
+
models.Index(fields=["subject_identifier", "action_identifier", "site", "id"]),
|
|
40
40
|
)
|