clinicedc 2.0.6__py3-none-any.whl → 2.0.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of clinicedc might be problematic. Click here for more details.
- {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/METADATA +2 -2
- {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/RECORD +489 -441
- {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/WHEEL +1 -1
- edc_action_item/action.py +1 -1
- edc_action_item/action_item_notification.py +2 -2
- edc_action_item/auths.py +37 -32
- edc_action_item/create_action_item.py +1 -1
- edc_action_item/decorators.py +1 -1
- edc_action_item/migrations/0001_initial.py +21 -22
- edc_action_item/migrations/0006_auto_20180707_1659.py +4 -4
- edc_action_item/migrations/0008_auto_20180809_0303.py +4 -4
- edc_action_item/migrations/0015_auto_20190114_0250.py +4 -4
- edc_action_item/migrations/0017_auto_20190305_0123.py +11 -30
- edc_action_item/migrations/0030_edcpermissions.py +3 -2
- edc_action_item/migrations/0039_alter_actionitem_auto_created_comment_and_more.py +398 -0
- edc_action_item/migrations/0040_alter_actionitem_report_datetime_and_more.py +34 -0
- edc_action_item/models/action_item.py +9 -4
- edc_action_item/models/action_model_mixin.py +5 -6
- edc_action_item/models/reference.py +2 -2
- edc_action_item/models/signals.py +22 -23
- edc_action_item/post_migrate_signals.py +1 -1
- edc_action_item/send_email.py +0 -85
- edc_action_item/site_action_items.py +5 -9
- edc_action_item/utils.py +3 -3
- edc_adherence/migrations/0005_alter_nonadherencereasons_extra_value_and_more.py +36 -0
- edc_adherence/model_mixins.py +1 -1
- edc_adverse_event/auths.py +55 -51
- edc_adverse_event/migrations/0001_initial.py +5 -4
- edc_adverse_event/migrations/0002_auto_20190802_0059.py +3 -2
- edc_adverse_event/migrations/0008_auto_20220825_0451.py +3 -2
- edc_adverse_event/migrations/0009_auto_20220907_0157.py +3 -2
- edc_adverse_event/migrations/0016_alter_aeactionclassification_device_created_and_more.py +285 -0
- edc_adverse_event/model_mixins/ae_followup/ae_followup_fields_model_mixin.py +2 -2
- edc_adverse_event/model_mixins/ae_initial/ae_initial_fields_model_mixin.py +6 -5
- edc_adverse_event/model_mixins/ae_special_interest/aesi_fields_model_mixin.py +2 -2
- edc_adverse_event/model_mixins/ae_susar/ae_susar_fields_model_mixin.py +2 -2
- edc_adverse_event/model_mixins/ae_tmg/ae_tmg_fields_model_mixin.py +15 -11
- edc_adverse_event/model_mixins/ae_tmg/ae_tmg_methods_model_mixin.py +2 -4
- edc_adverse_event/model_mixins/death_report/death_report_model_mixin.py +5 -4
- edc_adverse_event/model_mixins/death_report/death_report_tmg_model_mixin.py +6 -3
- edc_adverse_event/model_mixins/death_report/simple_death_report_model_mixin.py +2 -2
- edc_adverse_event/model_mixins/hospitaization/hospitalization_model_mixin.py +4 -3
- edc_adverse_event/modeladmin_mixins/death_report_admin_mixin.py +3 -3
- edc_adverse_event/models/signals.py +7 -7
- edc_adverse_event/templatetags/edc_adverse_event_extras.py +5 -4
- edc_adverse_event/view_mixins/ae/ae_listboard_view_mixin.py +3 -5
- edc_adverse_event/view_mixins/ae/death_report_listboard_view_mixin.py +6 -8
- edc_adverse_event/view_mixins/tmg/tmg_ae_listboard_view_mixin.py +2 -2
- edc_adverse_event/views/tmg/summary_listboard_view.py +3 -2
- edc_appointment/admin/appointment_admin.py +2 -2
- edc_appointment/admin/list_filters.py +2 -2
- edc_appointment/auths.py +14 -10
- edc_appointment/creators/appointment_creator.py +1 -1
- edc_appointment/creators/appointments_creator.py +1 -1
- edc_appointment/form_validators/appointment_form_validator.py +108 -82
- edc_appointment/migrations/0003_auto_20161127_2226.py +5 -6
- edc_appointment/migrations/0006_auto_20170106_2118.py +5 -5
- edc_appointment/migrations/0018_auto_20190305_0123.py +5 -12
- edc_appointment/migrations/0050_alter_appointment_appt_type_and_more.py +220 -0
- edc_appointment/model_mixins/appointment_fields_model_mixin.py +1 -2
- edc_appointment/model_mixins/appointment_methods_model_mixin.py +2 -3
- edc_appointment/model_mixins/appointment_model_mixin.py +31 -28
- edc_appointment/model_mixins/window_period_model_mixin.py +6 -7
- edc_appointment/models/appointment.py +1 -1
- edc_appointment/models/signals.py +44 -35
- edc_appointment/utils.py +19 -24
- edc_appointment/view_utils/appointment_button.py +2 -2
- edc_auth/admin/user_admin.py +1 -1
- edc_auth/auth_objects/__init__.py +2 -20
- edc_auth/auth_objects/default_groups.py +13 -11
- edc_auth/auth_objects/default_roles.py +26 -24
- edc_auth/auth_updater/auth_updater.py +13 -2
- edc_auth/auth_updater/group_updater.py +12 -10
- edc_auth/auth_updater/role_updater.py +2 -2
- edc_auth/constants.py +10 -0
- edc_auth/import_users.py +3 -3
- edc_auth/migrations/0001_squashed_0033_alter_userprofile_is_multisite_viewer.py +5 -5
- edc_auth/migrations/0012_auto_20191026_0034.py +3 -2
- edc_auth/migrations/0013_auto_20191026_0055.py +3 -2
- edc_auth/migrations/0025_permissions.py +3 -2
- edc_auth/migrations/0035_alter_edcpermissions_device_created_and_more.py +85 -0
- edc_auth/models/user_profile.py +14 -11
- edc_auth/post_migrate_signals.py +1 -1
- edc_auth/site_auths.py +80 -67
- edc_consent/actions.py +4 -5
- edc_consent/auths.py +18 -12
- edc_consent/migrations/0001_initial.py +3 -2
- edc_consent/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_consent/model_mixins/consent_extension_model_mixin.py +4 -5
- edc_consent/model_mixins/requires_consent_fields_model_mixin.py +2 -2
- edc_consent/utils.py +1 -1
- edc_constants/constants.py +1 -0
- edc_crf/auths.py +5 -0
- edc_crf/migrations/0001_initial.py +3 -2
- edc_crf/migrations/0009_alter_crfstatus_device_created_and_more.py +54 -0
- edc_dashboard/auths.py +10 -6
- edc_dashboard/migrations/0001_initial.py +3 -2
- edc_dashboard/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_dashboard/templatetags/edc_dashboard_extras.py +3 -2
- edc_dashboard/url_config.py +92 -83
- edc_dashboard/url_names.py +4 -4
- edc_dashboard/view_mixins/url_request_context_mixin.py +6 -5
- edc_data_manager/action_items.py +4 -6
- edc_data_manager/admin/actions.py +5 -5
- edc_data_manager/admin/data_query_admin.py +12 -11
- edc_data_manager/auths.py +37 -34
- edc_data_manager/handlers/handlers.py +6 -7
- edc_data_manager/migrations/0001_initial.py +19 -19
- edc_data_manager/migrations/0025_edcpermissions.py +3 -2
- edc_data_manager/migrations/0040_alter_datadictionary_device_created_and_more.py +327 -0
- edc_data_manager/migrations/0041_alter_dataquery_dm_user_and_more.py +164 -0
- edc_data_manager/models/data_query.py +5 -5
- edc_data_manager/models/model_mixins.py +8 -8
- edc_data_manager/rule/query_rule_wrapper.py +7 -7
- edc_data_manager/rule/rule_runner.py +4 -3
- edc_document_status/model_mixins.py +1 -1
- edc_egfr/egfr.py +11 -7
- edc_egfr/model_mixins/egfr_model_mixin.py +3 -7
- edc_export/admin/data_request_admin.py +2 -2
- edc_export/archive_exporter.py +7 -5
- edc_export/auths.py +32 -28
- edc_export/files_archiver.py +3 -2
- edc_export/migrations/0001_initial.py +26 -26
- edc_export/migrations/0004_auto_20190305_0123.py +25 -72
- edc_export/migrations/0013_edcpermissions.py +3 -2
- edc_export/migrations/0022_alter_datarequest_description_and_more.py +611 -0
- edc_export/migrations/0023_alter_datarequesthistory_archive_filename_and_more.py +29 -0
- edc_export/model_exporter/file_history_updater.py +10 -10
- edc_export/model_exporter/model_exporter.py +17 -15
- edc_export/model_exporter/object_history_helpers.py +2 -2
- edc_export/models/data_request_history.py +4 -4
- edc_export/utils.py +10 -15
- edc_facility/auths.py +8 -3
- edc_facility/facility.py +16 -22
- edc_facility/import_holidays.py +13 -13
- edc_facility/migrations/0005_healthfacility_healthfacilitytypes_and_more.py +8 -7
- edc_facility/migrations/0016_alter_healthfacility_device_created_and_more.py +139 -0
- edc_facility/migrations/0017_alter_healthfacility_gps_and_more.py +54 -0
- edc_facility/model_mixins.py +5 -5
- edc_form_label/custom_label_condition.py +11 -8
- edc_form_label/form_label.py +1 -1
- edc_form_runners/auths.py +11 -6
- edc_form_runners/form_runner.py +3 -5
- edc_form_runners/migrations/0001_initial.py +3 -2
- edc_form_runners/migrations/0005_alter_issue_device_created_and_more.py +49 -0
- edc_form_validators/applicable_field_validator.py +7 -6
- edc_form_validators/base_form_validator.py +8 -9
- edc_form_validators/other_specify_field_validator.py +2 -8
- edc_form_validators/required_field_validator.py +19 -16
- edc_identifier/migrations/0001_squashed_0018_auto_20180128_1054.py +3 -3
- edc_identifier/migrations/0002_auto_20190305_0123.py +3 -6
- edc_identifier/migrations/0006_auto_20161127_2226.py +15 -15
- edc_identifier/migrations/0007_auto_20161204_2227.py +3 -3
- edc_identifier/migrations/0009_auto_20161221_2323.py +3 -5
- edc_identifier/migrations/0010_auto_20170112_0602.py +17 -17
- edc_identifier/migrations/0011_alter_identifiermodel_device_created_and_more.py +79 -0
- edc_identifier/model_mixins.py +1 -1
- edc_identifier/models.py +9 -9
- edc_identifier/research_identifier.py +11 -10
- edc_identifier/simple_identifier.py +9 -5
- edc_identifier/subject_identifier.py +3 -2
- edc_lab/auths.py +26 -23
- edc_lab/lab/aliquot_creator.py +5 -8
- edc_lab/lab/primary_aliquot.py +14 -5
- edc_lab/migrations/0001_initial.py +29 -29
- edc_lab/migrations/0008_auto_20170921_0719.py +3 -3
- edc_lab/migrations/0010_auto_20171127_1541.py +15 -15
- edc_lab/migrations/0012_auto_20180114_1438.py +3 -3
- edc_lab/migrations/0019_auto_20190305_0123.py +43 -127
- edc_lab/migrations/0036_alter_aliquot_comment_alter_aliquot_device_created_and_more.py +1139 -0
- edc_lab/migrations/0037_alter_historicalorder_order_datetime_and_more.py +31 -0
- edc_lab/model_mixins/aliquot/aliquot_identifier_model_mixin.py +2 -2
- edc_lab/model_mixins/aliquot/aliquot_model_mixin.py +2 -2
- edc_lab/model_mixins/panel_model_mixin.py +18 -7
- edc_lab/model_mixins/requisition/crf_with_requisition_model_mixin.py +2 -4
- edc_lab/model_mixins/requisition/requisition_model_mixin.py +13 -16
- edc_lab/model_mixins/requisition/requisition_verify_model_mixin.py +1 -1
- edc_lab/model_mixins/result/result_item_model_mixin.py +4 -4
- edc_lab/model_mixins/shipping/manifest_model_mixin.py +4 -5
- edc_lab/model_mixins/shipping/verify_model_mixin.py +4 -6
- edc_lab/models/aliquot.py +2 -2
- edc_lab/models/box.py +1 -1
- edc_lab/models/box_item.py +6 -7
- edc_lab/models/manifest/manifest.py +3 -3
- edc_lab/models/manifest/manifest_item.py +7 -7
- edc_lab/models/manifest/shipper.py +3 -4
- edc_lab/models/order.py +6 -4
- edc_lab/models/panel.py +4 -4
- edc_lab/models/result.py +2 -2
- edc_lab/models/result_item.py +2 -2
- edc_lab_dashboard/auths.py +16 -11
- edc_lab_dashboard/migrations/0001_initial.py +3 -2
- edc_lab_dashboard/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_lab_dashboard/views/action_views/receive_view.py +2 -2
- edc_lab_dashboard/views/action_views/verify_box_item_view.py +2 -2
- edc_lab_results/calculate_missing.py +8 -8
- edc_lab_results/form_validator_mixins/blood_results_form_validator_mixin.py +2 -2
- edc_lab_results/get_summary.py +26 -25
- edc_lab_results/model_mixins/blood_result_model_mixin.py +9 -7
- edc_lab_results/model_mixins/fbg_model_mixin.py +3 -3
- edc_lab_results/model_mixins/glucose_model_mixin.py +3 -3
- edc_lab_results/model_mixins/hba1c_model_mixin.py +3 -3
- edc_label/auths.py +6 -1
- edc_label/label_template.py +8 -8
- edc_label/migrations/0001_initial.py +3 -2
- edc_label/migrations/0007_alter_zpllabeltemplates_device_created_and_more.py +49 -0
- edc_list_data/list_model_maker.py +2 -2
- edc_list_data/load_list_data.py +11 -14
- edc_list_data/load_model_data.py +3 -3
- edc_list_data/model_mixins.py +12 -4
- edc_list_data/post_migrate_signals.py +1 -1
- edc_list_data/preload_data.py +4 -4
- edc_list_data/row.py +1 -1
- edc_list_data/site_list_data.py +6 -5
- edc_listboard/migrations/0001_initial.py +3 -2
- edc_listboard/migrations/0007_alter_listboard_device_created_and_more.py +49 -0
- edc_locator/auths.py +18 -13
- edc_locator/migrations/0001_initial.py +7 -7
- edc_locator/migrations/0018_auto_20190305_0123.py +5 -12
- edc_locator/migrations/0040_alter_historicalsubjectlocator_action_identifier_and_more.py +187 -0
- edc_locator/migrations/0041_alter_historicalsubjectlocator_report_datetime_and_more.py +27 -0
- edc_locator/model_mixins/locator_model_mixin.py +2 -2
- edc_locator/model_mixins/subject_contact_fields_mixin.py +1 -1
- edc_locator/modeladmin_mixins.py +5 -4
- edc_ltfu/model_mixins.py +7 -5
- edc_metadata/auths.py +11 -7
- edc_metadata/metadata/metadata.py +1 -1
- edc_metadata/metadata_rules/crf/crf_rule.py +1 -1
- edc_metadata/metadata_rules/decorators.py +1 -1
- edc_metadata/metadata_rules/metadata_rule_evaluator.py +5 -3
- edc_metadata/metadata_rules/rule.py +2 -3
- edc_metadata/metadata_rules/rule_evaluator.py +1 -1
- edc_metadata/migrations/0002_auto_20161127_2226.py +5 -5
- edc_metadata/migrations/0005_auto_20170112_0602.py +5 -5
- edc_metadata/migrations/0011_auto_20190305_0123.py +5 -12
- edc_metadata/migrations/0031_alter_crfmetadata_device_created_and_more.py +120 -0
- edc_metadata/model_mixins/updates/updates_crf_metadata_model_mixin.py +7 -4
- edc_metadata/model_mixins/updates/updates_requisition_metadata_model_mixin.py +5 -2
- edc_metadata/models/crf_metadata.py +5 -5
- edc_metadata/models/crf_metadata_model_mixin.py +4 -5
- edc_metadata/models/requisition_metadata.py +6 -6
- edc_metadata/models/signals.py +10 -11
- edc_metadata/views/refresh_metadata_actions_view.py +3 -3
- edc_model/models/address_mixin.py +6 -6
- edc_model/models/fields/initials_field.py +2 -1
- edc_model/models/historical_records.py +2 -9
- edc_model/models/url_model_mixin.py +2 -2
- edc_model/validators/date.py +7 -8
- edc_model_admin/list_filters/future_date_list_filter.py +3 -3
- edc_model_admin/list_filters/past_date_list_filter.py +3 -3
- edc_model_admin/mixins/model_admin_protect_pii_mixin.py +4 -5
- edc_model_fields/fields/other_charfield.py +2 -2
- edc_navbar/auths.py +18 -13
- edc_navbar/migrations/0004_auto_20220825_0451.py +3 -2
- edc_navbar/migrations/0009_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_notification/auths.py +9 -4
- edc_notification/migrations/0001_initial.py +3 -3
- edc_notification/migrations/0004_auto_20190305_0123.py +3 -6
- edc_notification/migrations/0011_alter_notification_device_created_and_more.py +59 -0
- edc_notification/models/notification.py +1 -1
- edc_notification/notification/graded_event_notification.py +2 -2
- edc_notification/notification/model_notification.py +3 -30
- edc_notification/notification/new_model_notification.py +1 -1
- edc_notification/notification/notification.py +12 -12
- edc_notification/notification/updated_model_notification.py +2 -2
- edc_offstudy/auths.py +12 -7
- edc_offstudy/migrations/0001_initial.py +4 -4
- edc_offstudy/migrations/0002_auto_20180921_0434.py +4 -4
- edc_offstudy/migrations/0005_auto_20190305_0123.py +5 -12
- edc_offstudy/migrations/0023_alter_historicalsubjectoffstudy_action_identifier_and_more.py +188 -0
- edc_offstudy/migrations/0024_alter_historicalsubjectoffstudy_offstudy_datetime_and_more.py +43 -0
- edc_offstudy/model_mixins/offstudy_model_mixin.py +3 -2
- edc_pdutils/df_exporters/csv_exporter.py +33 -37
- edc_pdutils/df_exporters/csv_model_exporter.py +7 -3
- edc_pdutils/migrations/0001_initial.py +8 -8
- edc_pharmacy/admin/prescription/rx_refill_admin.py +4 -3
- edc_pharmacy/admin/reports/stock_availability_admin.py +5 -6
- edc_pharmacy/auths.py +19 -15
- edc_pharmacy/migrations/0001_initial.py +64 -63
- edc_pharmacy/migrations/0015_auto_20220913_2139.py +26 -26
- edc_pharmacy/migrations/0024_allocation_assignment_containerunits_dispense_and_more.py +81 -86
- edc_pharmacy/migrations/0037_remove_historicalstock_confirmed_at_site_by_and_more.py +5 -5
- edc_pharmacy/migrations/0039_remove_dispense_registered_subject_and_more.py +7 -8
- edc_pharmacy/migrations/0049_remove_stocktransferconfirmation_stock_and_more.py +12 -12
- edc_pharmacy/migrations/0050_remove_stocktransferconfirmation2_location_and_more.py +5 -5
- edc_pharmacy/migrations/0051_alter_historicalstocktransferconfirmationitem_options_and_more.py +3 -4
- edc_pharmacy/migrations/0053_alter_location_managers_alter_historicalstock_lot_and_more.py +3 -3
- edc_pharmacy/migrations/0057_scanduplicates.py +3 -3
- edc_pharmacy/migrations/0060_alter_container_max_per_subject_and_more.py +13 -15
- edc_pharmacy/migrations/0068_stockout.py +2 -3
- edc_pharmacy/migrations/0076_historicalstockadjustment_stockadjustment.py +5 -5
- edc_pharmacy/migrations/0077_historicalstockadjustment_adjustment_datetime_and_more.py +3 -4
- edc_pharmacy/migrations/0081_historicalconfirmation_confirmation.py +8 -8
- edc_pharmacy/migrations/0084_confirmationatsiteitem_and_more.py +0 -2
- edc_pharmacy/migrations/0089_alter_allocation_allocated_by_and_more.py +3284 -0
- edc_pharmacy/migrations/0090_alter_allocation_allocation_datetime_and_more.py +227 -0
- edc_pharmacy/model_mixins/study_medication_refill_model_mixin.py +2 -2
- edc_pharmacy/models/medication/formulation.py +5 -7
- edc_pharmacy/models/medication/medication.py +3 -3
- edc_pharmacy/models/model_mixins.py +10 -11
- edc_pharmacy/models/prescription/rx.py +13 -12
- edc_pharmacy/models/prescription/rx_refill.py +0 -1
- edc_pharmacy/models/stock/allocation.py +3 -3
- edc_pharmacy/models/stock/confirmation.py +3 -3
- edc_pharmacy/models/stock/confirmation_at_site.py +3 -2
- edc_pharmacy/models/stock/confirmation_at_site_item.py +3 -4
- edc_pharmacy/models/stock/dispense.py +5 -6
- edc_pharmacy/models/stock/dispense_item.py +2 -2
- edc_pharmacy/models/stock/location.py +3 -4
- edc_pharmacy/models/stock/lot.py +6 -7
- edc_pharmacy/models/stock/order.py +1 -1
- edc_pharmacy/models/stock/receive.py +3 -3
- edc_pharmacy/models/stock/receive_item.py +4 -4
- edc_pharmacy/models/stock/repack_request.py +2 -2
- edc_pharmacy/models/stock/stock.py +12 -18
- edc_pharmacy/models/stock/stock_adjustment.py +4 -4
- edc_pharmacy/models/stock/stock_request.py +2 -2
- edc_pharmacy/models/stock/stock_request_item.py +2 -2
- edc_pharmacy/models/stock/stock_transfer.py +3 -3
- edc_pharmacy/models/stock/stock_transfer_item.py +2 -2
- edc_pharmacy/models/stock/storage_bin.py +3 -4
- edc_pharmacy/models/stock/storage_bin_item.py +2 -2
- edc_pharmacy/models/stock/supplier.py +3 -4
- edc_pharmacy/models/storage/box.py +2 -2
- edc_pharmacy/models/storage/items/container_model_mixin.py +3 -4
- edc_pharmacy/models/storage/items/pill_bottle_model_mixin.py +2 -2
- edc_pharmacy/models/storage/items/subject_pill_bottle.py +1 -1
- edc_pharmacy/models/storage/room.py +2 -2
- edc_pharmacy/models/storage/shelf.py +2 -2
- edc_pharmacy/models/storage/utils.py +1 -1
- edc_pharmacy/prescribe/create_prescription.py +3 -3
- edc_pharmacy/utils/allocate_stock.py +2 -3
- edc_pharmacy/utils/confirm_stock.py +3 -4
- edc_pharmacy/utils/confirm_stock_at_site.py +4 -5
- edc_pharmacy/utils/dispense.py +3 -4
- edc_pharmacy/utils/process_repack_request.py +4 -5
- edc_pharmacy/utils/stock_request/bulk_create_stock_request_items.py +2 -3
- edc_pharmacy/utils/transfer_stock.py +2 -3
- edc_pharmacy/views/add_to_storage_bin_view.py +2 -2
- edc_pharmacy/views/allocate_to_subject_view.py +2 -2
- edc_pharmacy/views/confirmation_at_site_view.py +6 -9
- edc_pharmacy/views/dispense_view.py +2 -2
- edc_pharmacy/views/move_to_storage_bin_view.py +2 -3
- edc_pharmacy/views/print_labels_view.py +2 -2
- edc_prn/admin_site.py +5 -0
- edc_prn/prn.py +10 -11
- edc_prn/urls.py +11 -0
- edc_protocol/research_protocol_config.py +2 -3
- edc_protocol_incident/action_items.py +4 -4
- edc_protocol_incident/auths.py +27 -20
- edc_protocol_incident/migrations/0001_initial.py +7 -7
- edc_protocol_incident/migrations/0001_squashed_0015_auto_20220927_0401.py +13 -13
- edc_protocol_incident/migrations/0005_protocolincident_historicalprotocolincident_and_more.py +7 -7
- edc_protocol_incident/migrations/0024_alter_actionsrequired_extra_value_and_more.py +625 -0
- edc_protocol_incident/migrations/0025_alter_historicalprotocoldeviationviolation_report_datetime_and_more.py +42 -0
- edc_protocol_incident/model_mixins/protocol_deviation_violation_model_mixin.py +18 -11
- edc_protocol_incident/model_mixins/protocol_incident_model_mixin.py +26 -11
- edc_pylabels/actions.py +3 -5
- edc_pylabels/auths.py +6 -1
- edc_pylabels/migrations/0002_alter_label_options_label_created_and_more.py +3 -7
- edc_pylabels/migrations/0005_labelconfiguration_delete_label_and_more.py +3 -3
- edc_pylabels/migrations/0013_alter_labelconfiguration_device_created_and_more.py +49 -0
- edc_qareports/auths.py +11 -7
- edc_qareports/migrations/0001_initial.py +4 -5
- edc_qareports/migrations/0005_edcpermissions.py +3 -3
- edc_qareports/migrations/0006_qareportlog.py +2 -3
- edc_qareports/migrations/0019_alter_edcpermissions_device_created_and_more.py +102 -0
- edc_qareports/migrations/0020_alter_note_report_datetime_and_more.py +24 -0
- edc_qareports/model_mixins/note_model_mixin.py +7 -4
- edc_qareports/model_mixins/on_study_missing_values_model_mixin.py +4 -4
- edc_qareports/model_mixins/qa_report_model_mixin.py +2 -3
- edc_qareports/models/note.py +4 -4
- edc_qareports/models/qa_reports_log.py +2 -3
- edc_randomization/admin.py +30 -24
- edc_randomization/auths.py +12 -7
- edc_randomization/decorators.py +1 -1
- edc_randomization/migrations/0001_initial.py +3 -2
- edc_randomization/migrations/0002_historicalrandomizationlist.py +3 -2
- edc_randomization/migrations/0009_edcpermissions.py +3 -2
- edc_randomization/migrations/0014_alter_edcpermissions_device_created_and_more.py +141 -0
- edc_randomization/model_mixins.py +9 -9
- edc_randomization/randomizer.py +22 -20
- edc_randomization/utils.py +19 -18
- edc_refusal/auths.py +7 -2
- edc_refusal/migrations/0001_initial.py +4 -4
- edc_refusal/migrations/0002_historicalsubjectrefusal.py +4 -4
- edc_refusal/migrations/0012_alter_historicalsubjectrefusal_comment_and_more.py +122 -0
- edc_refusal/migrations/0013_alter_historicalsubjectrefusal_report_datetime_and_more.py +28 -0
- edc_refusal/model_mixins.py +4 -4
- edc_registration/auths.py +28 -23
- edc_registration/migrations/0002_auto_20161127_2226.py +3 -4
- edc_registration/migrations/0005_auto_20170111_1809.py +4 -2
- edc_registration/migrations/0016_historicalregisteredsubject.py +3 -2
- edc_registration/migrations/0017_auto_20190305_0123.py +5 -12
- edc_registration/migrations/0033_alter_historicalregisteredsubject_additional_key_and_more.py +302 -0
- edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py +15 -7
- edc_registration/models/registered_subject.py +28 -27
- edc_reportable/age_evaluator.py +4 -2
- edc_reportable/formula.py +5 -5
- edc_reportable/migrations/0001_initial.py +7 -7
- edc_reportable/migrations/0003_referencerangecollection_grade1_and_more.py +3 -3
- edc_reportable/migrations/0004_alter_referencerangecollection_grade3_and_more.py +5 -5
- edc_reportable/migrations/0006_alter_gradingdata_revision_and_more.py +5 -6
- edc_reportable/migrations/0007_alter_gradingdata_age_phrase_and_more.py +509 -0
- edc_reportable/models/normal_data.py +4 -5
- edc_reportable/models/reference_model_mixins.py +10 -11
- edc_reportable/models/reference_range_collection.py +12 -13
- edc_reportable/post_migrate_signals.py +1 -1
- edc_reportable/utils/convert_units.py +11 -45
- edc_reportable/utils/get_normal_data_or_raise.py +2 -2
- edc_reportable/utils/get_reference_range_collection.py +2 -3
- edc_reportable/utils/load_data.py +4 -4
- edc_reportable/utils/update_grading_data.py +5 -5
- edc_review_dashboard/auths.py +23 -18
- edc_review_dashboard/migrations/0001_initial.py +3 -2
- edc_review_dashboard/migrations/0006_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_screening/age_evaluator.py +6 -6
- edc_screening/auths.py +35 -30
- edc_screening/eligibility.py +1 -1
- edc_screening/gender_evaluator.py +1 -1
- edc_screening/migrations/0001_initial.py +3 -2
- edc_screening/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_screening/model_mixins/eligibility_model_mixin.py +3 -6
- edc_screening/model_mixins/screening_fields_model_mixin.py +6 -8
- edc_screening/model_mixins/screening_methods_model_mixin.py +1 -1
- edc_screening/screening_eligibility.py +2 -4
- edc_screening/utils.py +9 -9
- edc_search/generate_slug.py +26 -0
- edc_search/model_mixins.py +10 -22
- edc_sites/auths.py +8 -3
- edc_sites/migrations/0007_edcpermissions.py +3 -2
- edc_sites/migrations/0010_alter_edcpermissions_device_created_and_more.py +69 -0
- edc_sites/model_mixins/site_model_mixin.py +2 -2
- edc_sites/site.py +5 -5
- edc_sites/system_checks.py +1 -1
- edc_subject_dashboard/auths.py +27 -22
- edc_subject_dashboard/migrations/0001_initial.py +3 -2
- edc_subject_dashboard/migrations/0005_alter_edcpermissions_device_created_and_more.py +49 -0
- edc_subject_dashboard/requisition_report.py +6 -4
- edc_subject_dashboard/requisition_verifier.py +6 -6
- edc_subject_dashboard/templatetags/edc_subject_dashboard_extras.py +2 -2
- edc_subject_dashboard/view_mixins/subject_visit_view_mixin.py +7 -8
- edc_subject_dashboard/view_utils/subject_consent_listboard_button.py +3 -2
- edc_subject_dashboard/view_utils/timepoint_status_button.py +2 -2
- edc_timepoint/apps.py +0 -21
- edc_timepoint/model_mixins.py +22 -20
- edc_transfer/model_mixins.py +4 -4
- edc_transfer/modeladmin_mixins.py +1 -1
- edc_unblinding/auths.py +9 -4
- edc_unblinding/migrations/0001_initial.py +13 -13
- edc_unblinding/migrations/0014_alter_historicalunblindingrequest_action_identifier_and_more.py +291 -0
- edc_unblinding/migrations/0015_alter_historicalunblindingrequest_report_datetime_and_more.py +45 -0
- edc_unblinding/models/unblinding_request.py +2 -2
- edc_unblinding/models/unblinding_review.py +3 -3
- edc_utils/__init__.py +3 -1
- edc_utils/age.py +10 -16
- edc_utils/show_urls.py +29 -2
- edc_visit_schedule/auths.py +6 -1
- edc_visit_schedule/migrations/0001_initial.py +3 -3
- edc_visit_schedule/migrations/0002_auto_20190305_0123.py +3 -6
- edc_visit_schedule/migrations/0003_historicalvisitschedule_visitschedule.py +5 -4
- edc_visit_schedule/migrations/0015_historicalonschedule_offschedule_onschedule.py +10 -10
- edc_visit_schedule/migrations/0019_alter_historicalonschedule_device_created_and_more.py +229 -0
- edc_visit_schedule/migrations/0020_alter_historicalonschedule_onschedule_datetime_and_more.py +65 -0
- edc_visit_schedule/model_mixins/off_schedule_model_mixin.py +5 -4
- edc_visit_schedule/model_mixins/on_schedule_model_mixin.py +5 -4
- edc_visit_schedule/model_mixins/visit_schedule/visit_code_fields_model_mixin.py +1 -1
- edc_visit_schedule/models/subject_schedule_history.py +6 -6
- edc_visit_schedule/schedule/visit_collection.py +1 -1
- edc_visit_schedule/site_visit_schedules.py +2 -2
- edc_visit_schedule/subject_schedule.py +5 -4
- edc_visit_schedule/view_mixins.py +2 -3
- edc_visit_schedule/visit/visit.py +3 -2
- edc_visit_tracking/migrations/0004_subjectvisit_subjectvisitmissedreasons_extra_value_and_more.py +13 -13
- edc_visit_tracking/migrations/0009_alter_historicalsubjectvisit_comments_and_more.py +450 -0
- edc_visit_tracking/migrations/0010_alter_historicalsubjectvisit_report_datetime_and_more.py +68 -0
- edc_visit_tracking/model_mixins/base/visit_methods_model_mixin.py +3 -3
- edc_visit_tracking/model_mixins/crfs/visit_tracking_crf_model_mixin.py +2 -2
- edc_visit_tracking/model_mixins/requisitions/visit_tracking_requisition_model_mixin.py +2 -2
- edc_visit_tracking/model_mixins/subject_visit_missed_model_mixin.py +2 -2
- edc_visit_tracking/model_mixins/visit_model_mixin/caretaker_fields_mixin.py +2 -3
- edc_visit_tracking/model_mixins/visit_model_mixin/previous_visit_model_mixin.py +1 -1
- edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_fields_mixin.py +8 -11
- edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_mixin.py +1 -1
- edc_visit_tracking/models/signals.py +3 -3
- edc_visit_tracking/models/subject_visit.py +1 -1
- edc_vitals/calculators/bmi.py +7 -5
- edc_vitals/utils.py +1 -1
- edc_form_label/models.py +0 -0
- edc_search/constants.py +0 -1
- edc_search/models.py +0 -0
- edc_search/search_slug.py +0 -50
- edc_search/updater.py +0 -30
- edc_search/wsgi.py +0 -7
- {clinicedc-2.0.6.dist-info → clinicedc-2.0.8.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Generated by Django 5.2.6 on 2025-09-18 00:24
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
import django.utils.timezone
|
|
5
|
+
import uuid
|
|
6
|
+
from django.db import migrations, models
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Migration(migrations.Migration):
|
|
10
|
+
|
|
11
|
+
dependencies = [
|
|
12
|
+
("edc_data_manager", "0040_alter_datadictionary_device_created_and_more"),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
operations = [
|
|
16
|
+
migrations.AlterField(
|
|
17
|
+
model_name="dataquery",
|
|
18
|
+
name="dm_user",
|
|
19
|
+
field=models.ForeignKey(
|
|
20
|
+
blank=True,
|
|
21
|
+
help_text="Please select a name from the list",
|
|
22
|
+
null=True,
|
|
23
|
+
on_delete=django.db.models.deletion.PROTECT,
|
|
24
|
+
related_name="+",
|
|
25
|
+
to="edc_data_manager.datamanageruser",
|
|
26
|
+
verbose_name="DM resolved by",
|
|
27
|
+
),
|
|
28
|
+
),
|
|
29
|
+
migrations.AlterField(
|
|
30
|
+
model_name="dataquery",
|
|
31
|
+
name="locked_reason",
|
|
32
|
+
field=models.TextField(
|
|
33
|
+
blank=True,
|
|
34
|
+
default="",
|
|
35
|
+
help_text="If required, the reason the query cannot be resolved.",
|
|
36
|
+
verbose_name="Reason query locked",
|
|
37
|
+
),
|
|
38
|
+
),
|
|
39
|
+
migrations.AlterField(
|
|
40
|
+
model_name="dataquery",
|
|
41
|
+
name="plan_of_action",
|
|
42
|
+
field=models.TextField(
|
|
43
|
+
blank=True,
|
|
44
|
+
default="",
|
|
45
|
+
help_text="If required, provide a plan of action",
|
|
46
|
+
),
|
|
47
|
+
),
|
|
48
|
+
migrations.AlterField(
|
|
49
|
+
model_name="dataquery",
|
|
50
|
+
name="report_datetime",
|
|
51
|
+
field=models.DateTimeField(
|
|
52
|
+
default=django.utils.timezone.now, verbose_name="Query date"
|
|
53
|
+
),
|
|
54
|
+
),
|
|
55
|
+
migrations.AlterField(
|
|
56
|
+
model_name="dataquery",
|
|
57
|
+
name="rule_reference",
|
|
58
|
+
field=models.CharField(
|
|
59
|
+
default=uuid.uuid4, max_length=150, verbose_name="Query rule reference"
|
|
60
|
+
),
|
|
61
|
+
),
|
|
62
|
+
migrations.AlterField(
|
|
63
|
+
model_name="dataquery",
|
|
64
|
+
name="sender",
|
|
65
|
+
field=models.ForeignKey(
|
|
66
|
+
help_text="Please select a name from the list",
|
|
67
|
+
on_delete=django.db.models.deletion.PROTECT,
|
|
68
|
+
related_name="+",
|
|
69
|
+
to="edc_data_manager.datamanageruser",
|
|
70
|
+
verbose_name="Query raised by",
|
|
71
|
+
),
|
|
72
|
+
),
|
|
73
|
+
migrations.AlterField(
|
|
74
|
+
model_name="dataquery",
|
|
75
|
+
name="site_response_text",
|
|
76
|
+
field=models.TextField(blank=True, default=""),
|
|
77
|
+
),
|
|
78
|
+
migrations.AlterField(
|
|
79
|
+
model_name="dataquery",
|
|
80
|
+
name="subject_identifier",
|
|
81
|
+
field=models.CharField(default="", editable=False, max_length=50),
|
|
82
|
+
),
|
|
83
|
+
migrations.AlterField(
|
|
84
|
+
model_name="dataquery",
|
|
85
|
+
name="title",
|
|
86
|
+
field=models.CharField(default="", max_length=150),
|
|
87
|
+
),
|
|
88
|
+
migrations.AlterField(
|
|
89
|
+
model_name="historicaldataquery",
|
|
90
|
+
name="dm_user",
|
|
91
|
+
field=models.ForeignKey(
|
|
92
|
+
blank=True,
|
|
93
|
+
db_constraint=False,
|
|
94
|
+
help_text="Please select a name from the list",
|
|
95
|
+
null=True,
|
|
96
|
+
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
97
|
+
related_name="+",
|
|
98
|
+
to="edc_data_manager.datamanageruser",
|
|
99
|
+
verbose_name="DM resolved by",
|
|
100
|
+
),
|
|
101
|
+
),
|
|
102
|
+
migrations.AlterField(
|
|
103
|
+
model_name="historicaldataquery",
|
|
104
|
+
name="locked_reason",
|
|
105
|
+
field=models.TextField(
|
|
106
|
+
blank=True,
|
|
107
|
+
default="",
|
|
108
|
+
help_text="If required, the reason the query cannot be resolved.",
|
|
109
|
+
verbose_name="Reason query locked",
|
|
110
|
+
),
|
|
111
|
+
),
|
|
112
|
+
migrations.AlterField(
|
|
113
|
+
model_name="historicaldataquery",
|
|
114
|
+
name="plan_of_action",
|
|
115
|
+
field=models.TextField(
|
|
116
|
+
blank=True,
|
|
117
|
+
default="",
|
|
118
|
+
help_text="If required, provide a plan of action",
|
|
119
|
+
),
|
|
120
|
+
),
|
|
121
|
+
migrations.AlterField(
|
|
122
|
+
model_name="historicaldataquery",
|
|
123
|
+
name="report_datetime",
|
|
124
|
+
field=models.DateTimeField(
|
|
125
|
+
default=django.utils.timezone.now, verbose_name="Query date"
|
|
126
|
+
),
|
|
127
|
+
),
|
|
128
|
+
migrations.AlterField(
|
|
129
|
+
model_name="historicaldataquery",
|
|
130
|
+
name="rule_reference",
|
|
131
|
+
field=models.CharField(
|
|
132
|
+
default=uuid.uuid4, max_length=150, verbose_name="Query rule reference"
|
|
133
|
+
),
|
|
134
|
+
),
|
|
135
|
+
migrations.AlterField(
|
|
136
|
+
model_name="historicaldataquery",
|
|
137
|
+
name="sender",
|
|
138
|
+
field=models.ForeignKey(
|
|
139
|
+
blank=True,
|
|
140
|
+
db_constraint=False,
|
|
141
|
+
help_text="Please select a name from the list",
|
|
142
|
+
null=True,
|
|
143
|
+
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
144
|
+
related_name="+",
|
|
145
|
+
to="edc_data_manager.datamanageruser",
|
|
146
|
+
verbose_name="Query raised by",
|
|
147
|
+
),
|
|
148
|
+
),
|
|
149
|
+
migrations.AlterField(
|
|
150
|
+
model_name="historicaldataquery",
|
|
151
|
+
name="site_response_text",
|
|
152
|
+
field=models.TextField(blank=True, default=""),
|
|
153
|
+
),
|
|
154
|
+
migrations.AlterField(
|
|
155
|
+
model_name="historicaldataquery",
|
|
156
|
+
name="subject_identifier",
|
|
157
|
+
field=models.CharField(default="", editable=False, max_length=50),
|
|
158
|
+
),
|
|
159
|
+
migrations.AlterField(
|
|
160
|
+
model_name="historicaldataquery",
|
|
161
|
+
name="title",
|
|
162
|
+
field=models.CharField(default="", max_length=150),
|
|
163
|
+
),
|
|
164
|
+
]
|
|
@@ -6,6 +6,7 @@ from django.db import models
|
|
|
6
6
|
from django.db.models.deletion import PROTECT
|
|
7
7
|
from django.template.loader import render_to_string
|
|
8
8
|
from django.urls.base import reverse
|
|
9
|
+
from django.utils import timezone
|
|
9
10
|
|
|
10
11
|
from edc_action_item.models.action_model_mixin import ActionModelMixin
|
|
11
12
|
from edc_constants.constants import CLOSED, RESOLVED
|
|
@@ -13,7 +14,6 @@ from edc_dashboard.url_names import InvalidDashboardUrlName, url_names
|
|
|
13
14
|
from edc_model.models import BaseUuidModel
|
|
14
15
|
from edc_sites.managers import CurrentSiteManager
|
|
15
16
|
from edc_sites.model_mixins import SiteModelMixin
|
|
16
|
-
from edc_utils.date import get_utcnow
|
|
17
17
|
from edc_visit_tracking.utils import get_related_visit_model_cls
|
|
18
18
|
|
|
19
19
|
from ..action_items import DATA_QUERY_ACTION
|
|
@@ -28,7 +28,7 @@ from .requisition_panel import RequisitionPanel
|
|
|
28
28
|
class DataQuery(DataQueryModelMixin, ActionModelMixin, SiteModelMixin, BaseUuidModel):
|
|
29
29
|
action_name = DATA_QUERY_ACTION
|
|
30
30
|
|
|
31
|
-
subject_identifier = models.CharField(max_length=50,
|
|
31
|
+
subject_identifier = models.CharField(max_length=50, default="", editable=False)
|
|
32
32
|
|
|
33
33
|
registered_subject = models.ForeignKey(
|
|
34
34
|
QuerySubject,
|
|
@@ -83,7 +83,7 @@ class DataQuery(DataQueryModelMixin, ActionModelMixin, SiteModelMixin, BaseUuidM
|
|
|
83
83
|
)
|
|
84
84
|
|
|
85
85
|
rule_reference = models.CharField(
|
|
86
|
-
verbose_name="Query rule reference", max_length=150,
|
|
86
|
+
verbose_name="Query rule reference", max_length=150, default=uuid4
|
|
87
87
|
)
|
|
88
88
|
|
|
89
89
|
objects = models.Manager()
|
|
@@ -107,7 +107,7 @@ class DataQuery(DataQueryModelMixin, ActionModelMixin, SiteModelMixin, BaseUuidM
|
|
|
107
107
|
and self.site_response_text.strip() == AUTO_RESOLVED
|
|
108
108
|
):
|
|
109
109
|
self.status = CLOSED
|
|
110
|
-
self.resolved_datetime =
|
|
110
|
+
self.resolved_datetime = timezone.now()
|
|
111
111
|
self.dm_user = self.sender
|
|
112
112
|
|
|
113
113
|
def form_and_numbers_to_string(self):
|
|
@@ -192,7 +192,7 @@ class DataQuery(DataQueryModelMixin, ActionModelMixin, SiteModelMixin, BaseUuidM
|
|
|
192
192
|
class Meta(BaseUuidModel.Meta):
|
|
193
193
|
verbose_name = "Data Query"
|
|
194
194
|
verbose_name_plural = "Data Queries"
|
|
195
|
-
unique_together =
|
|
195
|
+
unique_together = ("registered_subject", "rule_reference", "visit_schedule")
|
|
196
196
|
indexes = (
|
|
197
197
|
models.Index(
|
|
198
198
|
fields=[
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from django.db import models
|
|
2
2
|
from django.db.models import PROTECT
|
|
3
|
+
from django.utils import timezone
|
|
3
4
|
|
|
4
5
|
from edc_constants.constants import CLOSED, NEW, NORMAL, OPEN, RESOLVED
|
|
5
|
-
from edc_utils import get_utcnow
|
|
6
6
|
|
|
7
7
|
from ..choices import DM_STATUS, QUERY_PRIORITY, RESPONSE_STATUS
|
|
8
8
|
from ..constants import CLOSED_WITH_ACTION
|
|
@@ -10,16 +10,16 @@ from .user import DataManagerUser, QueryUser
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class DataQueryModelMixin(models.Model):
|
|
13
|
-
report_datetime = models.DateTimeField(verbose_name="Query date", default=
|
|
13
|
+
report_datetime = models.DateTimeField(verbose_name="Query date", default=timezone.now)
|
|
14
14
|
|
|
15
|
-
title = models.CharField(max_length=150,
|
|
15
|
+
title = models.CharField(max_length=150, default="", blank=False)
|
|
16
16
|
|
|
17
17
|
sender = models.ForeignKey(
|
|
18
18
|
DataManagerUser,
|
|
19
19
|
related_name="+",
|
|
20
20
|
on_delete=PROTECT,
|
|
21
21
|
verbose_name="Query raised by",
|
|
22
|
-
help_text="
|
|
22
|
+
help_text="Please select a name from the list",
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
recipients = models.ManyToManyField(
|
|
@@ -43,7 +43,7 @@ class DataQueryModelMixin(models.Model):
|
|
|
43
43
|
verbose_name="Site resolved on", null=True, blank=True
|
|
44
44
|
)
|
|
45
45
|
|
|
46
|
-
site_response_text = models.TextField(
|
|
46
|
+
site_response_text = models.TextField(default="", blank=True)
|
|
47
47
|
|
|
48
48
|
site_response_status = models.CharField(
|
|
49
49
|
verbose_name="Site status", max_length=25, choices=RESPONSE_STATUS, default=NEW
|
|
@@ -60,7 +60,7 @@ class DataQueryModelMixin(models.Model):
|
|
|
60
60
|
on_delete=PROTECT,
|
|
61
61
|
null=True,
|
|
62
62
|
blank=True,
|
|
63
|
-
help_text="select a name from the list",
|
|
63
|
+
help_text="Please select a name from the list",
|
|
64
64
|
)
|
|
65
65
|
|
|
66
66
|
resolved_datetime = models.DateTimeField(
|
|
@@ -70,7 +70,7 @@ class DataQueryModelMixin(models.Model):
|
|
|
70
70
|
auto_resolved = models.BooleanField(default=False)
|
|
71
71
|
|
|
72
72
|
plan_of_action = models.TextField(
|
|
73
|
-
|
|
73
|
+
default="", blank=True, help_text="If required, provide a plan of action"
|
|
74
74
|
)
|
|
75
75
|
|
|
76
76
|
locked = models.BooleanField(
|
|
@@ -80,7 +80,7 @@ class DataQueryModelMixin(models.Model):
|
|
|
80
80
|
|
|
81
81
|
locked_reason = models.TextField(
|
|
82
82
|
verbose_name="Reason query locked",
|
|
83
|
-
|
|
83
|
+
default="",
|
|
84
84
|
blank=True,
|
|
85
85
|
help_text="If required, the reason the query cannot be resolved.",
|
|
86
86
|
)
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
from decimal import Decimal
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
from tqdm import tqdm
|
|
8
8
|
|
|
@@ -17,12 +17,12 @@ if TYPE_CHECKING:
|
|
|
17
17
|
class QueryRuleWrapper:
|
|
18
18
|
def __init__(
|
|
19
19
|
self,
|
|
20
|
-
query_rule_obj: QueryRule = None,
|
|
21
|
-
subject_identifiers: list[
|
|
22
|
-
visit_schedule_obj: QueryVisitSchedule = None,
|
|
23
|
-
timepoint: Decimal = None,
|
|
24
|
-
entry_status: str = None,
|
|
25
|
-
now: datetime = None,
|
|
20
|
+
query_rule_obj: QueryRule | None = None,
|
|
21
|
+
subject_identifiers: list[str] | None = None,
|
|
22
|
+
visit_schedule_obj: QueryVisitSchedule | None = None,
|
|
23
|
+
timepoint: Decimal | None = None,
|
|
24
|
+
entry_status: str | None = None,
|
|
25
|
+
now: datetime | None = None,
|
|
26
26
|
verbose: bool | None = None,
|
|
27
27
|
):
|
|
28
28
|
self.now = now
|
|
@@ -5,9 +5,10 @@ from datetime import datetime
|
|
|
5
5
|
from decimal import Decimal
|
|
6
6
|
from typing import TYPE_CHECKING
|
|
7
7
|
|
|
8
|
+
from django.utils import timezone
|
|
9
|
+
|
|
8
10
|
from edc_metadata import KEYED, REQUIRED
|
|
9
11
|
from edc_metadata.metadata_inspector import MetaDataInspector
|
|
10
|
-
from edc_utils import get_utcnow
|
|
11
12
|
|
|
12
13
|
from ..models import QueryVisitSchedule
|
|
13
14
|
from .query_rule_wrapper import QueryRuleWrapper
|
|
@@ -24,7 +25,7 @@ class RuleRunner:
|
|
|
24
25
|
verbose: bool | None = None,
|
|
25
26
|
):
|
|
26
27
|
self.query_rule_obj = query_rule_obj # query rule model instance
|
|
27
|
-
self.now = now or
|
|
28
|
+
self.now = now or timezone.now()
|
|
28
29
|
self.verbose = verbose
|
|
29
30
|
|
|
30
31
|
@property
|
|
@@ -39,7 +40,7 @@ class RuleRunner:
|
|
|
39
40
|
created_counter = 0
|
|
40
41
|
resolved_counter = 0
|
|
41
42
|
query_rules_data = query_rules_data or self.query_rules_data
|
|
42
|
-
for
|
|
43
|
+
for _, wrapped_query_rules in query_rules_data.items():
|
|
43
44
|
for wrapped_query_rule in wrapped_query_rules:
|
|
44
45
|
if self.verbose:
|
|
45
46
|
sys.stdout.write(f" - running {wrapped_query_rule}\n")
|
|
@@ -17,7 +17,7 @@ class DocumentStatusModelMixin(models.Model):
|
|
|
17
17
|
|
|
18
18
|
document_status_comments = models.TextField(
|
|
19
19
|
verbose_name="Any comments related to status of this document",
|
|
20
|
-
|
|
20
|
+
default="",
|
|
21
21
|
blank=True,
|
|
22
22
|
help_text="for example, why some data is still pending",
|
|
23
23
|
)
|
edc_egfr/egfr.py
CHANGED
|
@@ -8,12 +8,13 @@ from zoneinfo import ZoneInfo
|
|
|
8
8
|
from dateutil.relativedelta import relativedelta
|
|
9
9
|
from django.core.exceptions import ObjectDoesNotExist
|
|
10
10
|
from django.db import transaction
|
|
11
|
+
from django.utils import timezone
|
|
11
12
|
|
|
12
13
|
from edc_constants.constants import NEW
|
|
13
14
|
from edc_reportable.models import ReferenceRangeCollection
|
|
14
15
|
from edc_reportable.units import EGFR_UNITS, PERCENT
|
|
15
16
|
from edc_reportable.utils import get_grade_for_value
|
|
16
|
-
from edc_utils import age
|
|
17
|
+
from edc_utils.age import age
|
|
17
18
|
|
|
18
19
|
from .calculators import EgfrCkdEpi, EgfrCockcroftGault, egfr_percent_change
|
|
19
20
|
from .get_drop_notification_model import get_egfr_drop_notification_model_cls
|
|
@@ -27,7 +28,7 @@ class EgfrError(Exception):
|
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
class Egfr:
|
|
30
|
-
calculators: dict = {"ckd-epi": EgfrCkdEpi, "cockcroft-gault": EgfrCockcroftGault}
|
|
31
|
+
calculators: dict = {"ckd-epi": EgfrCkdEpi, "cockcroft-gault": EgfrCockcroftGault} # noqa: RUF012
|
|
31
32
|
|
|
32
33
|
def __init__(
|
|
33
34
|
self,
|
|
@@ -78,7 +79,7 @@ class Egfr:
|
|
|
78
79
|
name=reference_range_collection_name
|
|
79
80
|
)
|
|
80
81
|
except ObjectDoesNotExist as e:
|
|
81
|
-
raise ObjectDoesNotExist(f"{e} Got {reference_range_collection_name}")
|
|
82
|
+
raise ObjectDoesNotExist(f"{e} Got {reference_range_collection_name}") from e
|
|
82
83
|
else:
|
|
83
84
|
self.reference_range_collection = reference_range_collection
|
|
84
85
|
self.report_datetime = report_datetime
|
|
@@ -134,9 +135,12 @@ class Egfr:
|
|
|
134
135
|
"""A hook to respond if egfr percent drop from baseline
|
|
135
136
|
is at or beyond the percent drop threshold.
|
|
136
137
|
"""
|
|
137
|
-
if
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
if (
|
|
139
|
+
self.egfr_drop_value
|
|
140
|
+
and self.percent_drop_threshold is not None
|
|
141
|
+
and self.egfr_drop_value >= self.percent_drop_threshold
|
|
142
|
+
):
|
|
143
|
+
self.create_or_update_egfr_drop_notification()
|
|
140
144
|
|
|
141
145
|
@property
|
|
142
146
|
def egfr_value(self) -> float:
|
|
@@ -226,7 +230,7 @@ class Egfr:
|
|
|
226
230
|
obj.weight = self.get_weight_in_kgs()
|
|
227
231
|
obj.egfr_percent_change = self.egfr_drop_value
|
|
228
232
|
obj.creatinine_date = self.assay_date
|
|
229
|
-
obj.modified =
|
|
233
|
+
obj.modified = timezone.now()
|
|
230
234
|
obj.save()
|
|
231
235
|
obj.refresh_from_db()
|
|
232
236
|
return obj
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import contextlib
|
|
3
4
|
from decimal import Decimal
|
|
4
5
|
|
|
5
6
|
from django.core.exceptions import ObjectDoesNotExist
|
|
@@ -104,13 +105,8 @@ class EgfrModelMixin(
|
|
|
104
105
|
appointment__timepoint=self.baseline_timepoint,
|
|
105
106
|
visit_code_sequence=0,
|
|
106
107
|
)
|
|
107
|
-
with transaction.atomic():
|
|
108
|
-
|
|
109
|
-
egfr_value = self.__class__.objects.get(
|
|
110
|
-
subject_visit=baseline_visit
|
|
111
|
-
).egfr_value
|
|
112
|
-
except ObjectDoesNotExist:
|
|
113
|
-
pass
|
|
108
|
+
with transaction.atomic(), contextlib.suppress(ObjectDoesNotExist):
|
|
109
|
+
egfr_value = self.__class__.objects.get(subject_visit=baseline_visit).egfr_value
|
|
114
110
|
return egfr_value
|
|
115
111
|
|
|
116
112
|
def get_weight_in_kgs_for_egfr(self) -> Decimal | None:
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from django.contrib import admin
|
|
2
|
+
from django.utils import timezone
|
|
2
3
|
from django_audit_fields import ModelAdminAuditFieldsMixin
|
|
3
4
|
from django_revision.modeladmin_mixin import ModelAdminRevisionMixin
|
|
4
5
|
|
|
@@ -11,7 +12,6 @@ from edc_model_admin.mixins import (
|
|
|
11
12
|
TemplatesModelAdminMixin,
|
|
12
13
|
)
|
|
13
14
|
from edc_sites.admin import SiteModelAdminMixin
|
|
14
|
-
from edc_utils import get_utcnow
|
|
15
15
|
|
|
16
16
|
from ..admin_site import edc_export_admin
|
|
17
17
|
from ..forms import DataRequestForm
|
|
@@ -66,7 +66,7 @@ class DataRequestAdmin(
|
|
|
66
66
|
def export_selected(self, request, queryset):
|
|
67
67
|
for obj in queryset:
|
|
68
68
|
DataRequestHistory.objects.create(data_request=obj)
|
|
69
|
-
rows_updated = queryset.update(exported_datetime=
|
|
69
|
+
rows_updated = queryset.update(exported_datetime=timezone.now())
|
|
70
70
|
if rows_updated == 1:
|
|
71
71
|
message_bit = "1 data request was"
|
|
72
72
|
else:
|
edc_export/archive_exporter.py
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
from tempfile import mkdtemp
|
|
4
5
|
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
7
|
+
from django.utils import timezone
|
|
8
|
+
|
|
6
9
|
from edc_pdutils.df_exporters import CsvModelExporter
|
|
7
10
|
from edc_sites.site import sites
|
|
8
|
-
from edc_utils import get_utcnow
|
|
9
11
|
|
|
10
12
|
from .files_archiver import FilesArchiver
|
|
11
13
|
from .files_emailer import FilesEmailer, FilesEmailerError
|
|
@@ -16,7 +18,7 @@ if TYPE_CHECKING:
|
|
|
16
18
|
from django.contrib.auth.models import User
|
|
17
19
|
|
|
18
20
|
|
|
19
|
-
class ArchiveExporterNothingExported(Exception):
|
|
21
|
+
class ArchiveExporterNothingExported(Exception): # noqa: N818
|
|
20
22
|
pass
|
|
21
23
|
|
|
22
24
|
|
|
@@ -55,7 +57,7 @@ class ArchiveExporter:
|
|
|
55
57
|
for model in models:
|
|
56
58
|
csv_exporter = self.csv_exporter_cls(
|
|
57
59
|
model=model,
|
|
58
|
-
export_folder=tmp_folder,
|
|
60
|
+
export_folder=Path(tmp_folder),
|
|
59
61
|
decrypt=decrypt,
|
|
60
62
|
site_ids=sites.get_site_ids_for_user(
|
|
61
63
|
user=user, site_id=sites.get_current_site().site_id
|
|
@@ -85,8 +87,8 @@ class ArchiveExporter:
|
|
|
85
87
|
summary="\n".join(summary),
|
|
86
88
|
)
|
|
87
89
|
except FilesEmailerError as e:
|
|
88
|
-
raise ArchiveExporterEmailError(e)
|
|
90
|
+
raise ArchiveExporterEmailError(e) from e
|
|
89
91
|
else:
|
|
90
92
|
self.emailed_to = user.email
|
|
91
|
-
self.emailed_datetime =
|
|
93
|
+
self.emailed_datetime = timezone.now()
|
|
92
94
|
self.exported_datetime = self.exported_datetime or self.emailed_datetime
|
edc_export/auths.py
CHANGED
|
@@ -4,34 +4,38 @@ from edc_auth.utils import remove_default_model_permissions_from_edc_permissions
|
|
|
4
4
|
from .auth_objects import export_codenames
|
|
5
5
|
from .constants import DATA_EXPORTER_ROLE, EXPORT, EXPORT_PII
|
|
6
6
|
|
|
7
|
-
site_auths.add_post_update_func(
|
|
8
|
-
"edc_export",
|
|
9
|
-
remove_default_model_permissions_from_edc_permissions,
|
|
10
|
-
)
|
|
11
7
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"Can export the visit schedule",
|
|
18
|
-
),
|
|
19
|
-
(
|
|
20
|
-
"edc_export.view_export_dashboard",
|
|
21
|
-
"Can view export dashboard",
|
|
22
|
-
),
|
|
23
|
-
(
|
|
24
|
-
"edc_export.export_subjectschedulehistory",
|
|
25
|
-
"Can export subject schedule history",
|
|
26
|
-
),
|
|
27
|
-
(
|
|
28
|
-
"edc_export.export_pii",
|
|
29
|
-
"Can export PII",
|
|
30
|
-
),
|
|
31
|
-
],
|
|
32
|
-
)
|
|
8
|
+
def update_site_auths():
|
|
9
|
+
site_auths.add_post_update_func(
|
|
10
|
+
"edc_export",
|
|
11
|
+
remove_default_model_permissions_from_edc_permissions,
|
|
12
|
+
)
|
|
33
13
|
|
|
14
|
+
site_auths.add_custom_permissions_tuples(
|
|
15
|
+
model="edc_export.edcpermissions",
|
|
16
|
+
codename_tuples=[
|
|
17
|
+
(
|
|
18
|
+
"edc_export.export_visitschedule",
|
|
19
|
+
"Can export the visit schedule",
|
|
20
|
+
),
|
|
21
|
+
(
|
|
22
|
+
"edc_export.view_export_dashboard",
|
|
23
|
+
"Can view export dashboard",
|
|
24
|
+
),
|
|
25
|
+
(
|
|
26
|
+
"edc_export.export_subjectschedulehistory",
|
|
27
|
+
"Can export subject schedule history",
|
|
28
|
+
),
|
|
29
|
+
(
|
|
30
|
+
"edc_export.export_pii",
|
|
31
|
+
"Can export PII",
|
|
32
|
+
),
|
|
33
|
+
],
|
|
34
|
+
)
|
|
34
35
|
|
|
35
|
-
site_auths.add_group(*export_codenames, name=EXPORT)
|
|
36
|
-
site_auths.add_role(EXPORT, name=DATA_EXPORTER_ROLE)
|
|
37
|
-
site_auths.add_group("edc_export.export_pii", name=EXPORT_PII)
|
|
36
|
+
site_auths.add_group(*export_codenames, name=EXPORT)
|
|
37
|
+
site_auths.add_role(EXPORT, name=DATA_EXPORTER_ROLE)
|
|
38
|
+
site_auths.add_group("edc_export.export_pii", name=EXPORT_PII)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
update_site_auths()
|
edc_export/files_archiver.py
CHANGED
|
@@ -5,8 +5,9 @@ import shutil
|
|
|
5
5
|
import sys
|
|
6
6
|
from typing import TYPE_CHECKING
|
|
7
7
|
|
|
8
|
+
from django.utils import timezone
|
|
9
|
+
|
|
8
10
|
from edc_export.utils import get_base_dir
|
|
9
|
-
from edc_utils import get_utcnow
|
|
10
11
|
|
|
11
12
|
if TYPE_CHECKING:
|
|
12
13
|
from datetime import datetime
|
|
@@ -25,7 +26,7 @@ class FilesArchiver:
|
|
|
25
26
|
date_format: str = None,
|
|
26
27
|
verbose: bool | None = None,
|
|
27
28
|
):
|
|
28
|
-
self.exported_datetime: datetime = exported_datetime or
|
|
29
|
+
self.exported_datetime: datetime = exported_datetime or timezone.now()
|
|
29
30
|
formatted_date: str = self.exported_datetime.strftime(date_format)
|
|
30
31
|
base_dir: str = get_base_dir()
|
|
31
32
|
archive_name: str = os.path.join(path, f"{user.username}_{formatted_date}")
|