clinicedc 2.0.4__py3-none-any.whl → 2.0.6__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.6.dist-info}/METADATA +41 -45
- {clinicedc-2.0.4.dist-info → clinicedc-2.0.6.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 -10
- 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.6.dist-info}/WHEEL +0 -0
- {clinicedc-2.0.4.dist-info → clinicedc-2.0.6.dist-info}/licenses/LICENSE +0 -0
|
@@ -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
|
|
@@ -88,7 +88,7 @@ class StudyMedicationCrfModelMixin(PreviousNextModelMixin, StudyMedicationRefill
|
|
|
88
88
|
|
|
89
89
|
super().save(*args, **kwargs)
|
|
90
90
|
|
|
91
|
-
def creates_refills_from_crf(self) ->
|
|
91
|
+
def creates_refills_from_crf(self) -> tuple[RxRefill, RxRefill | None]:
|
|
92
92
|
"""Attribute called in signal"""
|
|
93
93
|
return create_refills_from_crf(self, self.related_visit_model_attr())
|
|
94
94
|
|
|
@@ -25,7 +25,6 @@ class Manager(models.Manager):
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class Formulation(BaseUuidModel):
|
|
28
|
-
|
|
29
28
|
medication = models.ForeignKey(Medication, on_delete=PROTECT, null=True, blank=False)
|
|
30
29
|
|
|
31
30
|
strength = models.DecimalField(max_digits=6, decimal_places=1)
|
|
@@ -36,13 +35,13 @@ class Formulation(BaseUuidModel):
|
|
|
36
35
|
|
|
37
36
|
route = models.ForeignKey(Route, on_delete=PROTECT)
|
|
38
37
|
|
|
39
|
-
notes = models.TextField(max_length=250,
|
|
38
|
+
notes = models.TextField(max_length=250, default="", blank=True)
|
|
40
39
|
|
|
41
|
-
description = models.CharField(max_length=250,
|
|
40
|
+
description = models.CharField(max_length=250, default="", blank=True)
|
|
42
41
|
|
|
43
42
|
imp = models.BooleanField(default=False)
|
|
44
43
|
|
|
45
|
-
imp_description = models.CharField(max_length=250,
|
|
44
|
+
imp_description = models.CharField(max_length=250, default="", blank=True)
|
|
46
45
|
|
|
47
46
|
objects = Manager()
|
|
48
47
|
|
|
@@ -12,12 +12,11 @@ class Manager(models.Manager):
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class Medication(BaseUuidModel):
|
|
15
|
-
|
|
16
15
|
name = models.CharField(max_length=35, unique=True)
|
|
17
16
|
|
|
18
17
|
display_name = models.CharField(max_length=50, unique=True)
|
|
19
18
|
|
|
20
|
-
notes = models.TextField(max_length=250,
|
|
19
|
+
notes = models.TextField(max_length=250, default="", blank=True)
|
|
21
20
|
|
|
22
21
|
objects = Manager()
|
|
23
22
|
|
|
@@ -98,7 +98,7 @@ class Rx(
|
|
|
98
98
|
return f"{self.subject_identifier}"
|
|
99
99
|
|
|
100
100
|
def natural_key(self):
|
|
101
|
-
return (self.rx_identifier,)
|
|
101
|
+
return (self.rx_identifier,)
|
|
102
102
|
|
|
103
103
|
def save(self, *args, **kwargs):
|
|
104
104
|
self.registered_subject = RegisteredSubject.objects.get(
|
|
@@ -144,4 +144,4 @@ class Rx(
|
|
|
144
144
|
class Meta(BaseUuidModel.Meta):
|
|
145
145
|
verbose_name = "Prescription"
|
|
146
146
|
verbose_name_plural = "Prescriptions"
|
|
147
|
-
indexes =
|
|
147
|
+
indexes = (Index(fields=["rando_sid"]),)
|
|
@@ -102,7 +102,7 @@ class RxRefill(
|
|
|
102
102
|
|
|
103
103
|
notes = models.TextField(
|
|
104
104
|
max_length=250,
|
|
105
|
-
|
|
105
|
+
default="",
|
|
106
106
|
blank=True,
|
|
107
107
|
help_text="Additional information for patient",
|
|
108
108
|
)
|
|
@@ -137,7 +137,7 @@ class RxRefill(
|
|
|
137
137
|
)
|
|
138
138
|
|
|
139
139
|
def natural_key(self):
|
|
140
|
-
return (self.refill_identifier,)
|
|
140
|
+
return (self.refill_identifier,)
|
|
141
141
|
|
|
142
142
|
def save(self, *args, **kwargs):
|
|
143
143
|
self.adjust_end_datetimes()
|
|
@@ -167,7 +167,7 @@ class RxRefill(
|
|
|
167
167
|
).dosage
|
|
168
168
|
if self.roundup_dose:
|
|
169
169
|
return math.ceil(dosage)
|
|
170
|
-
|
|
170
|
+
if self.round_dose:
|
|
171
171
|
return round_half_away_from_zero(dosage, self.round_dose)
|
|
172
172
|
return dosage
|
|
173
173
|
|
|
@@ -179,13 +179,11 @@ class RxRefill(
|
|
|
179
179
|
return (
|
|
180
180
|
math.ceil(
|
|
181
181
|
(
|
|
182
|
-
(
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
* float(self.number_of_days)
|
|
186
|
-
)
|
|
187
|
-
/ self.roundup_divisible_by
|
|
182
|
+
float(self.get_dose())
|
|
183
|
+
* float(self.frequency)
|
|
184
|
+
* float(self.number_of_days)
|
|
188
185
|
)
|
|
186
|
+
/ self.roundup_divisible_by
|
|
189
187
|
)
|
|
190
188
|
* self.roundup_divisible_by
|
|
191
189
|
)
|
|
@@ -4,8 +4,7 @@ from edc_qareports.model_mixins import QaReportModelMixin, qa_reports_permission
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class StockAvailability(QaReportModelMixin, models.Model):
|
|
7
|
-
|
|
8
|
-
subject_identifier = models.CharField(max_length=50, null=True)
|
|
7
|
+
subject_identifier = models.CharField(max_length=50, default="")
|
|
9
8
|
|
|
10
9
|
visit_code = models.DecimalField(max_digits=8, decimal_places=1, null=True)
|
|
11
10
|
|
|
@@ -15,9 +14,9 @@ class StockAvailability(QaReportModelMixin, models.Model):
|
|
|
15
14
|
|
|
16
15
|
relative_days = models.IntegerField(null=True)
|
|
17
16
|
|
|
18
|
-
codes = models.TextField(
|
|
17
|
+
codes = models.TextField(default="")
|
|
19
18
|
|
|
20
|
-
bins = models.TextField(
|
|
19
|
+
bins = models.TextField(default="")
|
|
21
20
|
|
|
22
21
|
class Meta(QaReportModelMixin.Meta):
|
|
23
22
|
verbose_name = "Stock availability"
|
|
@@ -15,11 +15,9 @@ class Manager(models.Manager):
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class ConfirmationAtSite(SiteModelMixin, BaseUuidModel):
|
|
18
|
-
|
|
19
18
|
transfer_confirmation_identifier = models.CharField(
|
|
20
19
|
max_length=36,
|
|
21
20
|
unique=True,
|
|
22
|
-
null=True,
|
|
23
21
|
blank=True,
|
|
24
22
|
help_text="A sequential unique identifier set by the EDC",
|
|
25
23
|
)
|
|
@@ -32,7 +30,7 @@ class ConfirmationAtSite(SiteModelMixin, BaseUuidModel):
|
|
|
32
30
|
Location, on_delete=models.PROTECT, limit_choices_to={"site__isnull": False}
|
|
33
31
|
)
|
|
34
32
|
|
|
35
|
-
comments = models.TextField(
|
|
33
|
+
comments = models.TextField(default="", blank=True)
|
|
36
34
|
|
|
37
35
|
objects = Manager()
|
|
38
36
|
|
|
@@ -13,7 +13,6 @@ class Manager(models.Manager):
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class Order(BaseUuidModel):
|
|
16
|
-
|
|
17
16
|
order_identifier = models.CharField(
|
|
18
17
|
max_length=36,
|
|
19
18
|
unique=True,
|
|
@@ -40,7 +39,7 @@ class Order(BaseUuidModel):
|
|
|
40
39
|
null=True,
|
|
41
40
|
blank=False,
|
|
42
41
|
)
|
|
43
|
-
comment = models.TextField(
|
|
42
|
+
comment = models.TextField(default="", blank=True)
|
|
44
43
|
|
|
45
44
|
sent = models.BooleanField(default=False)
|
|
46
45
|
|
|
@@ -15,11 +15,10 @@ class Manager(models.Manager):
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class Receive(BaseUuidModel):
|
|
18
|
-
|
|
19
18
|
receive_identifier = models.CharField(
|
|
20
19
|
max_length=36,
|
|
21
20
|
unique=True,
|
|
22
|
-
|
|
21
|
+
default="",
|
|
23
22
|
blank=True,
|
|
24
23
|
help_text="A sequential unique identifier set by the EDC",
|
|
25
24
|
)
|
|
@@ -46,11 +45,11 @@ class Receive(BaseUuidModel):
|
|
|
46
45
|
blank=False,
|
|
47
46
|
)
|
|
48
47
|
|
|
49
|
-
invoice_number = models.CharField(max_length=50,
|
|
48
|
+
invoice_number = models.CharField(max_length=50, default="", blank=True)
|
|
50
49
|
|
|
51
50
|
invoice_date = models.DateField(null=True, blank=True)
|
|
52
51
|
|
|
53
|
-
comment = models.TextField(
|
|
52
|
+
comment = models.TextField(default="", blank=True)
|
|
54
53
|
|
|
55
54
|
objects = Manager()
|
|
56
55
|
|
|
@@ -18,7 +18,6 @@ class Manager(models.Manager):
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class ReceiveItem(BaseUuidModel):
|
|
21
|
-
|
|
22
21
|
receive_item_identifier = models.CharField(
|
|
23
22
|
max_length=36,
|
|
24
23
|
unique=True,
|
|
@@ -66,9 +65,9 @@ class ReceiveItem(BaseUuidModel):
|
|
|
66
65
|
help_text="Quantity x Container.Quantity, e.g. 10 x Bottle of 128 = 1280",
|
|
67
66
|
)
|
|
68
67
|
|
|
69
|
-
reference = models.CharField(max_length=150,
|
|
68
|
+
reference = models.CharField(max_length=150, default="", blank=True)
|
|
70
69
|
|
|
71
|
-
comment = models.TextField(
|
|
70
|
+
comment = models.TextField(default="", blank=True)
|
|
72
71
|
|
|
73
72
|
task_id = models.UUIDField(null=True)
|
|
74
73
|
|
|
@@ -29,7 +29,6 @@ from .repack_request import RepackRequest
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
class Stock(BaseUuidModel):
|
|
32
|
-
|
|
33
32
|
stock_identifier = models.CharField(
|
|
34
33
|
verbose_name="Internal stock identifier",
|
|
35
34
|
max_length=36,
|
|
@@ -208,7 +207,7 @@ class Stock(BaseUuidModel):
|
|
|
208
207
|
obj: Stock = self
|
|
209
208
|
receive_item = self.receive_item
|
|
210
209
|
while not receive_item:
|
|
211
|
-
obj = obj.from_stock
|
|
210
|
+
obj = obj.from_stock
|
|
212
211
|
receive_item = obj.receive_item
|
|
213
212
|
return receive_item
|
|
214
213
|
|
|
@@ -15,7 +15,6 @@ class StockAdjustmentManager(models.Manager):
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class StockAdjustment(BaseUuidModel):
|
|
18
|
-
|
|
19
18
|
stock = models.ForeignKey(
|
|
20
19
|
Stock,
|
|
21
20
|
# related_name="source_stock",
|
|
@@ -39,7 +38,7 @@ class StockAdjustment(BaseUuidModel):
|
|
|
39
38
|
validators=[MinValueValidator(0)],
|
|
40
39
|
)
|
|
41
40
|
|
|
42
|
-
reason = models.TextField(
|
|
41
|
+
reason = models.TextField(default="")
|
|
43
42
|
|
|
44
43
|
objects = StockAdjustmentManager()
|
|
45
44
|
|
|
@@ -87,7 +87,7 @@ class StockRequest(BaseUuidModel):
|
|
|
87
87
|
|
|
88
88
|
subject_identifiers = models.TextField(
|
|
89
89
|
verbose_name="Include ONLY these subjects in this request. (Usually left blank)",
|
|
90
|
-
|
|
90
|
+
default="",
|
|
91
91
|
blank=True,
|
|
92
92
|
help_text=(
|
|
93
93
|
"By adding subject identifiers in this box, only these subjects "
|
|
@@ -97,13 +97,13 @@ class StockRequest(BaseUuidModel):
|
|
|
97
97
|
|
|
98
98
|
excluded_subject_identifiers = models.TextField(
|
|
99
99
|
verbose_name="Exclude these subjects from this request. (Usually left blank)",
|
|
100
|
-
|
|
100
|
+
default="",
|
|
101
101
|
blank=True,
|
|
102
102
|
)
|
|
103
103
|
|
|
104
104
|
labels = models.TextField(
|
|
105
105
|
verbose_name="Labels",
|
|
106
|
-
|
|
106
|
+
default="",
|
|
107
107
|
blank=True,
|
|
108
108
|
help_text=(
|
|
109
109
|
"A cell to capture and confirm printed/scanned labels related to this "
|
|
@@ -114,8 +114,7 @@ class StockRequest(BaseUuidModel):
|
|
|
114
114
|
cancel = models.CharField(
|
|
115
115
|
verbose_name="To cancel this request, type the word 'CANCEL' here and save the form:",
|
|
116
116
|
max_length=6,
|
|
117
|
-
default=
|
|
118
|
-
null=True,
|
|
117
|
+
default="",
|
|
119
118
|
blank=True,
|
|
120
119
|
)
|
|
121
120
|
status = models.CharField(
|
|
@@ -19,7 +19,7 @@ class ContainerModelMixin(models.Model):
|
|
|
19
19
|
|
|
20
20
|
box = models.ForeignKey(Box, on_delete=models.PROTECT, null=True)
|
|
21
21
|
|
|
22
|
-
description = models.TextField(
|
|
22
|
+
description = models.TextField(default="")
|
|
23
23
|
|
|
24
24
|
contains_uniquely_identifiable_items = models.BooleanField(default=True)
|
|
25
25
|
|
|
@@ -30,21 +30,20 @@ def repackage(
|
|
|
30
30
|
):
|
|
31
31
|
if source_container.unit_qty - (source_container.unit_qty_out + unit_qty) < 0:
|
|
32
32
|
raise InsufficientQuantityError()
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
source_container.refresh_from_db()
|
|
33
|
+
new_container = new_container_model_cls(
|
|
34
|
+
container_type=source_container.container_type,
|
|
35
|
+
medication_lot=source_container.medication_lot,
|
|
36
|
+
unit_qty=unit_qty,
|
|
37
|
+
unit_qty_out=0,
|
|
38
|
+
source_container=source_container,
|
|
39
|
+
box=box,
|
|
40
|
+
**kwargs,
|
|
41
|
+
)
|
|
42
|
+
new_container.unit_qty = unit_qty
|
|
43
|
+
new_container.save()
|
|
44
|
+
source_container.unit_qty_out += new_container.unit_qty
|
|
45
|
+
source_container.save()
|
|
46
|
+
source_container.refresh_from_db()
|
|
48
47
|
return new_container, source_container
|
|
49
48
|
|
|
50
49
|
|
|
@@ -70,7 +69,7 @@ def repackage_for_subject(
|
|
|
70
69
|
raise PackagingSubjectIdentifierMismatchError(
|
|
71
70
|
f"Expected subject identifier. Subject is randomized. Got sid `{rando_sid}`."
|
|
72
71
|
)
|
|
73
|
-
|
|
72
|
+
if not randomization_list.allocated and subject_identifier:
|
|
74
73
|
raise PackagingSubjectIdentifierMismatchError(
|
|
75
74
|
"Did not expect subject identifier. SID has not been allocated. "
|
|
76
75
|
f"Got sid `{rando_sid}`."
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from datetime import datetime
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
|
6
6
|
from django.apps import apps as django_apps
|
|
7
7
|
from django.core.exceptions import ObjectDoesNotExist
|
|
@@ -17,10 +17,10 @@ def create_prescription(
|
|
|
17
17
|
subject_identifier: str,
|
|
18
18
|
report_datetime: datetime,
|
|
19
19
|
medication_names: list[str],
|
|
20
|
-
randomizer_name:
|
|
21
|
-
site:
|
|
22
|
-
site_id:
|
|
23
|
-
apps:
|
|
20
|
+
randomizer_name: str | None = None,
|
|
21
|
+
site: Any | None = None,
|
|
22
|
+
site_id: Any | None = None,
|
|
23
|
+
apps: Any | None = None,
|
|
24
24
|
) -> Rx:
|
|
25
25
|
"""Creates a PrescriptionAction and Rx model instance"""
|
|
26
26
|
site_id = site_id or site.id
|
edc_pharmacy/utils/__init__.py
CHANGED
|
@@ -32,6 +32,7 @@ __all__ = [
|
|
|
32
32
|
"get_imp_schedule_names",
|
|
33
33
|
"get_instock_and_nostock_data",
|
|
34
34
|
"get_random_code",
|
|
35
|
+
"get_related_or_none",
|
|
35
36
|
"get_rx_model_cls",
|
|
36
37
|
"get_rxrefill_model_cls",
|
|
37
38
|
"get_stock_for_location_df",
|
|
@@ -41,5 +42,4 @@ __all__ = [
|
|
|
41
42
|
"transfer_stock",
|
|
42
43
|
"update_previous_refill_end_datetime",
|
|
43
44
|
"update_stock_instance",
|
|
44
|
-
"get_related_or_none",
|
|
45
45
|
]
|
|
@@ -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
|
|
@@ -25,8 +25,8 @@ def confirm_stock(
|
|
|
25
25
|
|
|
26
26
|
See also: confirm_stock_action
|
|
27
27
|
"""
|
|
28
|
-
stock_model_cls:
|
|
29
|
-
confirmation_model_cls:
|
|
28
|
+
stock_model_cls: type[Stock] = django_apps.get_model("edc_pharmacy.stock")
|
|
29
|
+
confirmation_model_cls: type[Confirmation] = django_apps.get_model(
|
|
30
30
|
"edc_pharmacy.confirmation"
|
|
31
31
|
)
|
|
32
32
|
stock_codes = [s.strip() for s in stock_codes]
|
|
@@ -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.contrib import messages
|
|
@@ -37,14 +37,14 @@ def confirm_stock_at_site(
|
|
|
37
37
|
See also: confirm_stock_action
|
|
38
38
|
"""
|
|
39
39
|
confirmed_by = request.user.username
|
|
40
|
-
stock_model_cls:
|
|
41
|
-
confirmation_at_site_model_cls:
|
|
40
|
+
stock_model_cls: type[Stock] = django_apps.get_model("edc_pharmacy.stock")
|
|
41
|
+
confirmation_at_site_model_cls: type[ConfirmationAtSite] = django_apps.get_model(
|
|
42
42
|
"edc_pharmacy.confirmationatsite"
|
|
43
43
|
)
|
|
44
|
-
confirmation_at_site_item_model_cls:
|
|
44
|
+
confirmation_at_site_item_model_cls: type[ConfirmationAtSiteItem] = django_apps.get_model(
|
|
45
45
|
"edc_pharmacy.confirmationatsiteitem"
|
|
46
46
|
)
|
|
47
|
-
location_model_cls:
|
|
47
|
+
location_model_cls: type[Location] = django_apps.get_model("edc_pharmacy.location")
|
|
48
48
|
|
|
49
49
|
location = location_model_cls.objects.get(pk=location)
|
|
50
50
|
|
|
@@ -56,9 +56,10 @@ def confirm_stock_at_site(
|
|
|
56
56
|
confirmed, already_confirmed, invalid = [], [], []
|
|
57
57
|
stock_codes = [s.strip() for s in stock_codes]
|
|
58
58
|
for stock_code in stock_codes:
|
|
59
|
-
if
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
if (
|
|
60
|
+
not stock_model_cls.objects.filter(code=stock_code).exists()
|
|
61
|
+
or not stock_transfer.stocktransferitem_set.filter(stock__code=stock_code).exists()
|
|
62
|
+
):
|
|
62
63
|
invalid.append(stock_code)
|
|
63
64
|
else:
|
|
64
65
|
try:
|
edc_pharmacy/utils/dispense.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.contrib import messages
|
|
@@ -21,9 +21,9 @@ def dispense(
|
|
|
21
21
|
dispensed_by: str,
|
|
22
22
|
request: WSGIRequest,
|
|
23
23
|
) -> QuerySet[DispenseItem] | None:
|
|
24
|
-
stock_model_cls:
|
|
25
|
-
dispense_model_cls:
|
|
26
|
-
dispense_item_model_cls:
|
|
24
|
+
stock_model_cls: type[Stock] = django_apps.get_model("edc_pharmacy.stock")
|
|
25
|
+
dispense_model_cls: type[Dispense] = django_apps.get_model("edc_pharmacy.dispense")
|
|
26
|
+
dispense_item_model_cls: type[DispenseItem] = django_apps.get_model(
|
|
27
27
|
"edc_pharmacy.dispenseitem"
|
|
28
28
|
)
|
|
29
29
|
|
|
@@ -33,10 +33,7 @@ def dispense(
|
|
|
33
33
|
messages.add_message(
|
|
34
34
|
request,
|
|
35
35
|
messages.ERROR,
|
|
36
|
-
(
|
|
37
|
-
"Stock not allocated to subject. "
|
|
38
|
-
f"Got {stock.code}. Dispensing cancelled."
|
|
39
|
-
),
|
|
36
|
+
(f"Stock not allocated to subject. Got {stock.code}. Dispensing cancelled."),
|
|
40
37
|
)
|
|
41
38
|
assignment_mismatch = True
|
|
42
39
|
break
|
edc_pharmacy/utils/format_qty.py
CHANGED
|
@@ -11,9 +11,9 @@ def format_qty(qty: Decimal, container: Container):
|
|
|
11
11
|
qty = 0 if qty is None else qty
|
|
12
12
|
if container.qty_decimal_places == 0:
|
|
13
13
|
return str(int(qty))
|
|
14
|
-
|
|
15
|
-
return "{:0.1f}"
|
|
16
|
-
return "{:0.2f}"
|
|
14
|
+
if container.qty_decimal_places == 1:
|
|
15
|
+
return f"{qty:0.1f}"
|
|
16
|
+
return f"{qty:0.2f}"
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
__all__ = ["format_qty"]
|
|
@@ -19,7 +19,7 @@ def get_codenames(
|
|
|
19
19
|
app_name, model_name = label_lower.split(".")
|
|
20
20
|
if label_lower in exclude_models:
|
|
21
21
|
continue
|
|
22
|
-
|
|
22
|
+
if label_lower in view_only_models:
|
|
23
23
|
codenames.append(f"{app_name}.view_{model_name}")
|
|
24
24
|
else:
|
|
25
25
|
for prefix in ["view_", "add_", "change_", "delete_"]:
|
|
@@ -28,25 +28,24 @@ def process_repack_request(repack_request_id: UUID | None = None, username: str
|
|
|
28
28
|
number_to_process = repack_request.requested_qty - repack_request.processed_qty
|
|
29
29
|
if not getattr(repack_request.from_stock, "confirmation", None):
|
|
30
30
|
raise RepackError("Source stock item not confirmed")
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
break
|
|
31
|
+
stock_model_cls = repack_request.from_stock.__class__
|
|
32
|
+
for index in range(0, int(number_to_process)):
|
|
33
|
+
try:
|
|
34
|
+
stock_model_cls.objects.create(
|
|
35
|
+
receive_item=None,
|
|
36
|
+
qty_in=1,
|
|
37
|
+
qty_out=0,
|
|
38
|
+
qty=1,
|
|
39
|
+
from_stock=repack_request.from_stock,
|
|
40
|
+
container=repack_request.container,
|
|
41
|
+
location=repack_request.from_stock.location,
|
|
42
|
+
repack_request=repack_request,
|
|
43
|
+
lot=repack_request.from_stock.lot,
|
|
44
|
+
user_created=username,
|
|
45
|
+
created=get_utcnow(),
|
|
46
|
+
)
|
|
47
|
+
except InsufficientStockError:
|
|
48
|
+
break
|
|
50
49
|
repack_request.processed_qty = stock_model_cls.objects.filter(
|
|
51
50
|
repack_request=repack_request
|
|
52
51
|
).count()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from datetime import
|
|
3
|
+
from datetime import UTC
|
|
4
4
|
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
import pandas as pd
|
|
@@ -38,7 +38,7 @@ def bulk_create_stock_request_items(
|
|
|
38
38
|
rx = rx_model_cls.objects.get(registered_subject=registered_subject)
|
|
39
39
|
visit_code = str(int(row["next_visit_code"]))
|
|
40
40
|
visit_code_sequence = int(10 * row["next_visit_code"] % 1)
|
|
41
|
-
appt_datetime = row["next_appt_datetime"].replace(tzinfo=
|
|
41
|
+
appt_datetime = row["next_appt_datetime"].replace(tzinfo=UTC)
|
|
42
42
|
assignment = rx.get_assignment()
|
|
43
43
|
next_id = get_next_value(stock_request_item_model_cls._meta.label_lower)
|
|
44
44
|
request_item_identifier = f"{next_id:06d}"
|
|
@@ -63,7 +63,6 @@ def bulk_create_stock_request_items(
|
|
|
63
63
|
obj.save()
|
|
64
64
|
stock_request.item_count = len(data)
|
|
65
65
|
stock_request.save(update_fields=["item_count"])
|
|
66
|
-
return None
|
|
67
66
|
|
|
68
67
|
|
|
69
68
|
__all__ = ["bulk_create_stock_request_items"]
|