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
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from django.apps import apps as django_apps
|
|
2
2
|
from django.contrib import messages
|
|
3
|
+
from django.utils import timezone
|
|
3
4
|
|
|
4
5
|
from edc_constants.constants import YES
|
|
5
6
|
from edc_dashboard.view_mixins import EdcViewMixin
|
|
6
7
|
from edc_lab import Specimen
|
|
7
8
|
from edc_lab.labels import AliquotLabel
|
|
8
9
|
from edc_lab.site_labs import site_labs
|
|
9
|
-
from edc_utils import get_utcnow
|
|
10
10
|
|
|
11
11
|
from ...view_mixins import ProcessRequisitionViewMixin
|
|
12
12
|
from .action_view import ActionView
|
|
@@ -38,7 +38,7 @@ class ReceiveView(EdcViewMixin, ProcessRequisitionViewMixin, ActionView):
|
|
|
38
38
|
updated += (
|
|
39
39
|
model_cls.objects.filter(pk__in=self.selected_items, is_drawn=YES)
|
|
40
40
|
.exclude(received=True)
|
|
41
|
-
.update(received=True, received_datetime=
|
|
41
|
+
.update(received=True, received_datetime=timezone.now())
|
|
42
42
|
)
|
|
43
43
|
if updated:
|
|
44
44
|
message = f"{updated} requisitions received."
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from django.contrib import messages
|
|
2
|
+
from django.utils import timezone
|
|
2
3
|
|
|
3
4
|
from edc_dashboard.view_mixins import EdcViewMixin
|
|
4
5
|
from edc_lab import SHIPPED
|
|
5
|
-
from edc_utils import get_utcnow
|
|
6
6
|
|
|
7
7
|
from ...view_mixins import BoxViewMixin
|
|
8
8
|
from .action_view import ActionView
|
|
@@ -48,7 +48,7 @@ class VerifyBoxItemView(EdcViewMixin, BoxViewMixin, ActionView):
|
|
|
48
48
|
if self.box_item:
|
|
49
49
|
if self.box_item == box_item_in_position:
|
|
50
50
|
box_item_in_position.verified = 1
|
|
51
|
-
box_item_in_position.verified_datetime =
|
|
51
|
+
box_item_in_position.verified_datetime = timezone.now()
|
|
52
52
|
self.next_position()
|
|
53
53
|
self.redirect_querystring.pop("alert")
|
|
54
54
|
else:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import contextlib
|
|
1
2
|
from typing import Any
|
|
2
3
|
|
|
3
4
|
|
|
@@ -20,11 +21,10 @@ def calculate_missing(obj: Any, panel: Any) -> tuple[int, str | None]:
|
|
|
20
21
|
missing = []
|
|
21
22
|
for utest_id in panel.utest_ids:
|
|
22
23
|
for field in fields:
|
|
23
|
-
|
|
24
|
-
utest_id, _ = utest_id
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return len(missing), ",".join(missing) if missing else None
|
|
24
|
+
with contextlib.suppress(ValueError):
|
|
25
|
+
utest_id, _ = utest_id # noqa: PLW2901
|
|
26
|
+
if field == utest_id or (
|
|
27
|
+
field == f"{utest_id}_value" and getattr(obj, field) is None
|
|
28
|
+
):
|
|
29
|
+
missing.append(field)
|
|
30
|
+
return len(missing), ",".join(missing) if missing else ""
|
|
@@ -51,13 +51,13 @@ class BloodResultsFormValidatorMixin(
|
|
|
51
51
|
self.required_if_not_none(
|
|
52
52
|
field=f"{utest_id}{self.value_field_suffix or ''}",
|
|
53
53
|
field_required=f"{utest_id}_abnormal",
|
|
54
|
-
field_required_evaluate_as_int=
|
|
54
|
+
field_required_evaluate_as_int=False,
|
|
55
55
|
)
|
|
56
56
|
if f"{utest_id}_reportable" in self.cleaned_data:
|
|
57
57
|
self.required_if_not_none(
|
|
58
58
|
field=f"{utest_id}{self.value_field_suffix or ''}",
|
|
59
59
|
field_required=f"{utest_id}_reportable",
|
|
60
|
-
field_required_evaluate_as_int=
|
|
60
|
+
field_required_evaluate_as_int=False,
|
|
61
61
|
)
|
|
62
62
|
self.evaluate_value(prefix=utest_id)
|
|
63
63
|
self.validate_reportable_fields(
|
edc_lab_results/get_summary.py
CHANGED
|
@@ -18,36 +18,37 @@ def get_summary(obj) -> tuple[list[str], list[str], list[str]]:
|
|
|
18
18
|
except ValueError:
|
|
19
19
|
utest_id = field_name
|
|
20
20
|
reference_range_collection = get_reference_range_collection(obj)
|
|
21
|
-
if units := getattr(obj, f"{utest_id}_units", None)
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
if (units := getattr(obj, f"{utest_id}_units", None)) and (
|
|
22
|
+
value := getattr(obj, field_name)
|
|
23
|
+
):
|
|
24
|
+
opts.update(units=units, label=utest_id)
|
|
25
|
+
try:
|
|
26
|
+
grading_data, grading_eval_phrase = reference_range_collection.get_grade(
|
|
27
|
+
value, **opts
|
|
28
|
+
)
|
|
29
|
+
except NotEvaluated as e:
|
|
30
|
+
errors.append(f"{e}.")
|
|
31
|
+
grading_data = None
|
|
32
|
+
grading_eval_phrase = None
|
|
33
|
+
if (
|
|
34
|
+
grading_data
|
|
35
|
+
and grading_data.grade
|
|
36
|
+
in reference_range_collection.reportable_grades(utest_id)
|
|
37
|
+
):
|
|
38
|
+
setattr(obj, f"{utest_id}_grade", grading_data.grade)
|
|
39
|
+
setattr(obj, f"{utest_id}_grade_description", grading_data.description)
|
|
40
|
+
reportable.append(f"{grading_eval_phrase}")
|
|
41
|
+
else:
|
|
24
42
|
try:
|
|
25
|
-
|
|
43
|
+
is_normal, normal_data = reference_range_collection.is_normal(
|
|
26
44
|
value, **opts
|
|
27
45
|
)
|
|
28
46
|
except NotEvaluated as e:
|
|
29
47
|
errors.append(f"{e}.")
|
|
30
|
-
grading_data = None
|
|
31
|
-
grading_eval_phrase = None
|
|
32
|
-
if (
|
|
33
|
-
grading_data
|
|
34
|
-
and grading_data.grade
|
|
35
|
-
in reference_range_collection.reportable_grades(utest_id)
|
|
36
|
-
):
|
|
37
|
-
setattr(obj, f"{utest_id}_grade", grading_data.grade)
|
|
38
|
-
setattr(obj, f"{utest_id}_grade_description", grading_data.description)
|
|
39
|
-
reportable.append(f"{grading_eval_phrase}")
|
|
40
48
|
else:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
value
|
|
49
|
+
if is_normal is False:
|
|
50
|
+
abnormal.append(
|
|
51
|
+
f"{normal_data.label}: {value} {units} "
|
|
52
|
+
f"{normal_data.phrase} Abnormal"
|
|
44
53
|
)
|
|
45
|
-
except NotEvaluated as e:
|
|
46
|
-
errors.append(f"{e}.")
|
|
47
|
-
else:
|
|
48
|
-
if is_normal is False:
|
|
49
|
-
abnormal.append(
|
|
50
|
-
f"{normal_data.label}: {value} {units} "
|
|
51
|
-
f"{normal_data.phrase} Abnormal"
|
|
52
|
-
)
|
|
53
54
|
return reportable, abnormal, errors
|
|
@@ -16,12 +16,12 @@ class BloodResultsFieldsModelMixin(models.Model):
|
|
|
16
16
|
choices=YES_NO,
|
|
17
17
|
max_length=25,
|
|
18
18
|
help_text=(
|
|
19
|
-
"Abnormal results present at baseline or continuing from
|
|
19
|
+
"Abnormal results present at baseline or continuing from baseline not included."
|
|
20
20
|
),
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
results_reportable = models.CharField(
|
|
24
|
-
verbose_name=
|
|
24
|
+
verbose_name="If any results are abnormal, are results within grade 3 or above?",
|
|
25
25
|
max_length=25,
|
|
26
26
|
choices=YES_NO_NA,
|
|
27
27
|
help_text=(
|
|
@@ -30,13 +30,13 @@ class BloodResultsFieldsModelMixin(models.Model):
|
|
|
30
30
|
),
|
|
31
31
|
)
|
|
32
32
|
|
|
33
|
-
summary = models.TextField(
|
|
33
|
+
summary = models.TextField(default="", blank=True)
|
|
34
34
|
|
|
35
|
-
reportable_summary = models.TextField(
|
|
35
|
+
reportable_summary = models.TextField(default="", blank=True)
|
|
36
36
|
|
|
37
|
-
abnormal_summary = models.TextField(
|
|
37
|
+
abnormal_summary = models.TextField(default="", blank=True)
|
|
38
38
|
|
|
39
|
-
errors = models.TextField(
|
|
39
|
+
errors = models.TextField(default="", blank=True)
|
|
40
40
|
|
|
41
41
|
missing_count = models.IntegerField(
|
|
42
42
|
default=0,
|
|
@@ -45,7 +45,7 @@ class BloodResultsFieldsModelMixin(models.Model):
|
|
|
45
45
|
)
|
|
46
46
|
|
|
47
47
|
missing = models.TextField(
|
|
48
|
-
|
|
48
|
+
default="",
|
|
49
49
|
editable=False,
|
|
50
50
|
help_text="calculated string of field names that have been left blank",
|
|
51
51
|
)
|
|
@@ -70,6 +70,8 @@ class BloodResultsMethodsModelMixin(models.Model):
|
|
|
70
70
|
return get_summary(self)
|
|
71
71
|
|
|
72
72
|
def get_summary_options(self: Any) -> dict:
|
|
73
|
+
# note: gender and dob are queried from RegisteredSubject
|
|
74
|
+
# in reportables
|
|
73
75
|
return dict(
|
|
74
76
|
subject_identifier=self.subject_visit.subject_identifier,
|
|
75
77
|
report_datetime=self.report_datetime,
|
|
@@ -37,13 +37,13 @@ class FbgModelMixin(
|
|
|
37
37
|
verbose_name="Was a point-of-care test used?",
|
|
38
38
|
max_length=15,
|
|
39
39
|
choices=YES_NO,
|
|
40
|
-
|
|
40
|
+
default="",
|
|
41
41
|
)
|
|
42
42
|
fasting = models.CharField(
|
|
43
43
|
verbose_name="Was this fasting or non-fasting?",
|
|
44
44
|
max_length=25,
|
|
45
45
|
choices=FASTING_CHOICES,
|
|
46
|
-
|
|
46
|
+
default="",
|
|
47
47
|
blank=False,
|
|
48
48
|
)
|
|
49
49
|
|
|
@@ -55,7 +55,7 @@ class FbgModelMixin(
|
|
|
55
55
|
|
|
56
56
|
def get_summary_options(self) -> dict:
|
|
57
57
|
opts = super().get_summary_options()
|
|
58
|
-
fasting =
|
|
58
|
+
fasting = self.fasting == FASTING
|
|
59
59
|
opts.update(fasting=fasting)
|
|
60
60
|
return opts
|
|
61
61
|
|
|
@@ -34,13 +34,13 @@ class GlucoseModelMixin(
|
|
|
34
34
|
verbose_name="Was a point-of-care test used?",
|
|
35
35
|
max_length=15,
|
|
36
36
|
choices=YES_NO,
|
|
37
|
-
|
|
37
|
+
default="",
|
|
38
38
|
)
|
|
39
39
|
fasting = models.CharField(
|
|
40
40
|
verbose_name="Was this fasting or non-fasting?",
|
|
41
41
|
max_length=25,
|
|
42
42
|
choices=FASTING_CHOICES,
|
|
43
|
-
|
|
43
|
+
default="",
|
|
44
44
|
blank=False,
|
|
45
45
|
)
|
|
46
46
|
|
|
@@ -52,7 +52,7 @@ class GlucoseModelMixin(
|
|
|
52
52
|
|
|
53
53
|
def get_summary_options(self: Any) -> dict:
|
|
54
54
|
opts = super().get_summary_options()
|
|
55
|
-
fasting =
|
|
55
|
+
fasting = self.fasting == FASTING
|
|
56
56
|
opts.update(fasting=fasting)
|
|
57
57
|
return opts
|
|
58
58
|
|
|
@@ -10,18 +10,18 @@ class Hba1cModelMixin(BaseHba1cModelMixin, models.Model):
|
|
|
10
10
|
verbose_name="Was a point-of-care test used?",
|
|
11
11
|
max_length=15,
|
|
12
12
|
choices=YES_NO,
|
|
13
|
-
|
|
13
|
+
default="",
|
|
14
14
|
)
|
|
15
15
|
|
|
16
16
|
hba1c_abnormal = models.CharField(
|
|
17
|
-
verbose_name="abnormal", choices=YES_NO, max_length=25,
|
|
17
|
+
verbose_name="abnormal", choices=YES_NO, max_length=25, default="", blank=True
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
hba1c_reportable = models.CharField(
|
|
21
21
|
verbose_name="reportable",
|
|
22
22
|
choices=REPORTABLE,
|
|
23
23
|
max_length=25,
|
|
24
|
-
|
|
24
|
+
default="",
|
|
25
25
|
blank=True,
|
|
26
26
|
)
|
|
27
27
|
|
edc_label/auths.py
CHANGED
|
@@ -2,4 +2,9 @@ from edc_auth.site_auths import site_auths
|
|
|
2
2
|
|
|
3
3
|
from .auth_objects import LABELING, codenames
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
def update_site_auths():
|
|
7
|
+
site_auths.add_group(*codenames, name=LABELING, no_delete=False)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
update_site_auths()
|
edc_label/label_template.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
from pathlib import Path
|
|
2
2
|
from string import Template
|
|
3
3
|
|
|
4
4
|
from django.apps import apps as django_apps
|
|
@@ -19,27 +19,27 @@ class LabelTemplate:
|
|
|
19
19
|
zpl_label_template = django_apps.get_model(
|
|
20
20
|
"edc_label.zpllabeltemplates"
|
|
21
21
|
).objects.get(name=self.template_name)
|
|
22
|
-
except ObjectDoesNotExist:
|
|
22
|
+
except ObjectDoesNotExist as e:
|
|
23
23
|
if static_files_path:
|
|
24
|
-
path = finders.find(
|
|
24
|
+
path = finders.find(str(Path(static_files_path) / template_name))
|
|
25
25
|
else:
|
|
26
26
|
app_config = django_apps.get_app_config("edc_label")
|
|
27
27
|
try:
|
|
28
28
|
path = app_config.label_templates[template_name]
|
|
29
|
-
except KeyError:
|
|
29
|
+
except KeyError as e:
|
|
30
30
|
raise LabelTemplateError(
|
|
31
31
|
f"Invalid label template name. "
|
|
32
32
|
f"Expected one of {list(app_config.label_templates.keys())}. "
|
|
33
33
|
f"Got '{template_name}'. "
|
|
34
34
|
f"See edc_label.app_config."
|
|
35
|
-
)
|
|
36
|
-
if not
|
|
35
|
+
) from e
|
|
36
|
+
if not path or not Path(path).exists():
|
|
37
37
|
raise LabelTemplateError(
|
|
38
38
|
f"Invalid label template path. "
|
|
39
39
|
f"Looking for template '{template_name}'. "
|
|
40
40
|
f"Got {path}. See edc_label.app_config."
|
|
41
|
-
)
|
|
42
|
-
with
|
|
41
|
+
) from e
|
|
42
|
+
with Path(path).open("r") as f:
|
|
43
43
|
self.template = f.read()
|
|
44
44
|
else:
|
|
45
45
|
self.template = zpl_label_template.zpl_data.strip()
|
|
@@ -7,6 +7,7 @@ import django_audit_fields.fields.uuid_auto_field
|
|
|
7
7
|
import django_audit_fields.models.audit_model_mixin
|
|
8
8
|
import django_revision.revision_field
|
|
9
9
|
from django.db import migrations, models
|
|
10
|
+
import django.utils.timezone
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class Migration(migrations.Migration):
|
|
@@ -33,14 +34,14 @@ class Migration(migrations.Migration):
|
|
|
33
34
|
"created",
|
|
34
35
|
models.DateTimeField(
|
|
35
36
|
blank=True,
|
|
36
|
-
default=
|
|
37
|
+
default=django.utils.timezone.now,
|
|
37
38
|
),
|
|
38
39
|
),
|
|
39
40
|
(
|
|
40
41
|
"modified",
|
|
41
42
|
models.DateTimeField(
|
|
42
43
|
blank=True,
|
|
43
|
-
default=
|
|
44
|
+
default=django.utils.timezone.now,
|
|
44
45
|
),
|
|
45
46
|
),
|
|
46
47
|
(
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Generated by Django 5.2.6 on 2025-09-17 16:53
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
("edc_label", "0006_alter_zpllabeltemplates_revision"),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name="zpllabeltemplates",
|
|
15
|
+
name="device_created",
|
|
16
|
+
field=models.CharField(
|
|
17
|
+
blank=True, default="", max_length=10, verbose_name="Device created"
|
|
18
|
+
),
|
|
19
|
+
),
|
|
20
|
+
migrations.AlterField(
|
|
21
|
+
model_name="zpllabeltemplates",
|
|
22
|
+
name="device_modified",
|
|
23
|
+
field=models.CharField(
|
|
24
|
+
blank=True, default="", max_length=10, verbose_name="Device modified"
|
|
25
|
+
),
|
|
26
|
+
),
|
|
27
|
+
migrations.AlterField(
|
|
28
|
+
model_name="zpllabeltemplates",
|
|
29
|
+
name="locale_created",
|
|
30
|
+
field=models.CharField(
|
|
31
|
+
blank=True,
|
|
32
|
+
default="",
|
|
33
|
+
help_text="Auto-updated by Modeladmin",
|
|
34
|
+
max_length=10,
|
|
35
|
+
verbose_name="Locale created",
|
|
36
|
+
),
|
|
37
|
+
),
|
|
38
|
+
migrations.AlterField(
|
|
39
|
+
model_name="zpllabeltemplates",
|
|
40
|
+
name="locale_modified",
|
|
41
|
+
field=models.CharField(
|
|
42
|
+
blank=True,
|
|
43
|
+
default="",
|
|
44
|
+
help_text="Auto-updated by Modeladmin",
|
|
45
|
+
max_length=10,
|
|
46
|
+
verbose_name="Locale modified",
|
|
47
|
+
),
|
|
48
|
+
),
|
|
49
|
+
]
|
|
@@ -33,7 +33,7 @@ class ListModelMaker:
|
|
|
33
33
|
try:
|
|
34
34
|
self.name, self.display_name = row
|
|
35
35
|
except ValueError as e:
|
|
36
|
-
raise ListModelMakerError(e)
|
|
36
|
+
raise ListModelMakerError(e) from e
|
|
37
37
|
except TypeError as e:
|
|
38
38
|
if "Row" not in str(e):
|
|
39
39
|
raise
|
|
@@ -46,7 +46,7 @@ class ListModelMaker:
|
|
|
46
46
|
opts = dict(
|
|
47
47
|
display_index=self.display_index,
|
|
48
48
|
display_name=self.display_name,
|
|
49
|
-
extra_value=self.extra_value,
|
|
49
|
+
extra_value=self.extra_value or "",
|
|
50
50
|
)
|
|
51
51
|
if "custom_name" in [f.name for f in self.model_cls._meta.get_fields()]:
|
|
52
52
|
opts.update(custom_name=self.custom_name)
|
edc_list_data/load_list_data.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import contextlib
|
|
4
|
+
|
|
3
5
|
from django.apps import AppConfig
|
|
4
6
|
|
|
5
7
|
from .list_model_maker import ListModelMaker, ListModelMakerError
|
|
@@ -10,7 +12,7 @@ class LoadListDataError(Exception):
|
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
def load_list_data(
|
|
13
|
-
list_data: dict = None, model_name: str | None = None, apps: AppConfig | None = None
|
|
15
|
+
list_data: dict | None = None, model_name: str | None = None, apps: AppConfig | None = None
|
|
14
16
|
) -> int:
|
|
15
17
|
"""Loads data into a list model.
|
|
16
18
|
|
|
@@ -24,25 +26,20 @@ def load_list_data(
|
|
|
24
26
|
(name2, display_name),...],
|
|
25
27
|
...}
|
|
26
28
|
"""
|
|
27
|
-
if model_name
|
|
28
|
-
model_names = [model_name]
|
|
29
|
-
else:
|
|
30
|
-
model_names = [k for k in list_data]
|
|
29
|
+
model_names = [model_name] if model_name else [k for k in list_data]
|
|
31
30
|
n = 0
|
|
32
|
-
for
|
|
31
|
+
for _model_name in model_names:
|
|
33
32
|
try:
|
|
34
|
-
data = list_data.get(
|
|
33
|
+
data = list_data.get(_model_name)()
|
|
35
34
|
except TypeError:
|
|
36
|
-
data = list_data.get(
|
|
35
|
+
data = list_data.get(_model_name)
|
|
37
36
|
try:
|
|
38
37
|
for display_index, row in enumerate(data):
|
|
39
|
-
|
|
40
|
-
row = row()
|
|
41
|
-
|
|
42
|
-
pass
|
|
43
|
-
maker = ListModelMaker(display_index, row, model_name, apps=apps)
|
|
38
|
+
with contextlib.suppress(TypeError):
|
|
39
|
+
row = row() # noqa: PLW2901
|
|
40
|
+
maker = ListModelMaker(display_index, row, _model_name, apps=apps)
|
|
44
41
|
maker.create_or_update()
|
|
45
42
|
except ListModelMakerError as e:
|
|
46
|
-
raise LoadListDataError(f"{e} See {list_data.get(
|
|
43
|
+
raise LoadListDataError(f"{e} See {list_data.get(_model_name)}.") from e
|
|
47
44
|
n += 1
|
|
48
45
|
return n
|
edc_list_data/load_model_data.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
|
|
1
3
|
from django.apps import AppConfig
|
|
2
4
|
from django.apps import apps as django_apps
|
|
3
5
|
from django.core.exceptions import ObjectDoesNotExist
|
|
@@ -34,10 +36,8 @@ def load_model_data(model_data: dict, apps: AppConfig | None = None) -> int:
|
|
|
34
36
|
try:
|
|
35
37
|
obj = model.objects.get(**{unique_field: opts.get(unique_field)})
|
|
36
38
|
except ObjectDoesNotExist:
|
|
37
|
-
|
|
39
|
+
with contextlib.suppress(IntegrityError):
|
|
38
40
|
model.objects.create(**opts)
|
|
39
|
-
except IntegrityError:
|
|
40
|
-
pass
|
|
41
41
|
else:
|
|
42
42
|
for key, value in opts.items():
|
|
43
43
|
setattr(obj, key, value)
|
edc_list_data/model_mixins.py
CHANGED
|
@@ -18,7 +18,11 @@ class BaseListModelMixin(models.Model):
|
|
|
18
18
|
help_text="This is the stored value, required",
|
|
19
19
|
)
|
|
20
20
|
|
|
21
|
-
plural_name = models.CharField(
|
|
21
|
+
plural_name = models.CharField(
|
|
22
|
+
verbose_name="Plural name",
|
|
23
|
+
max_length=250,
|
|
24
|
+
default="",
|
|
25
|
+
)
|
|
22
26
|
|
|
23
27
|
display_name = models.CharField(
|
|
24
28
|
verbose_name="Name",
|
|
@@ -34,10 +38,14 @@ class BaseListModelMixin(models.Model):
|
|
|
34
38
|
)
|
|
35
39
|
|
|
36
40
|
field_name = models.CharField(
|
|
37
|
-
max_length=25,
|
|
41
|
+
max_length=25,
|
|
42
|
+
editable=False,
|
|
43
|
+
default="",
|
|
44
|
+
blank=True,
|
|
45
|
+
help_text="Not required",
|
|
38
46
|
)
|
|
39
47
|
|
|
40
|
-
extra_value = models.CharField(max_length=250,
|
|
48
|
+
extra_value = models.CharField(max_length=250, default="")
|
|
41
49
|
|
|
42
50
|
version = models.CharField(max_length=35, editable=False, default="1.0")
|
|
43
51
|
|
|
@@ -85,7 +93,7 @@ class ListModelMixin2(BaseListModelMixin):
|
|
|
85
93
|
|
|
86
94
|
custom_name = models.CharField(
|
|
87
95
|
max_length=25,
|
|
88
|
-
|
|
96
|
+
default="",
|
|
89
97
|
blank=True,
|
|
90
98
|
help_text="A custom name/value to use on export instead of or in addition to `name`",
|
|
91
99
|
)
|
|
@@ -6,7 +6,7 @@ style = color_style()
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def post_migrate_list_data(sender=None, **kwargs):
|
|
9
|
-
from .site_list_data import get_autodiscover_enabled, site_list_data
|
|
9
|
+
from .site_list_data import get_autodiscover_enabled, site_list_data # noqa: PLC0415
|
|
10
10
|
|
|
11
11
|
if get_autodiscover_enabled():
|
|
12
12
|
sys.stdout.write(style.MIGRATE_HEADING("Updating list data:\n"))
|
edc_list_data/preload_data.py
CHANGED
|
@@ -11,9 +11,9 @@ style = color_style()
|
|
|
11
11
|
class PreloadData:
|
|
12
12
|
def __init__(
|
|
13
13
|
self,
|
|
14
|
-
list_data: dict[str, list[tuple[str | int, str]]]
|
|
15
|
-
model_data: dict = None,
|
|
16
|
-
list_data_model_name: str = None,
|
|
14
|
+
list_data: dict[str, list[tuple[str | int, str]]],
|
|
15
|
+
model_data: dict | None = None,
|
|
16
|
+
list_data_model_name: str | None = None,
|
|
17
17
|
apps: AppConfig = None,
|
|
18
18
|
) -> None:
|
|
19
19
|
self.list_data = list_data
|
|
@@ -24,7 +24,7 @@ class PreloadData:
|
|
|
24
24
|
if self.model_data:
|
|
25
25
|
self.item_count += self.load_model_data()
|
|
26
26
|
|
|
27
|
-
def load_list_data(self, model_name: str
|
|
27
|
+
def load_list_data(self, model_name: str, apps: AppConfig | None = None) -> int:
|
|
28
28
|
return load_list_data(self.list_data, model_name=model_name, apps=apps)
|
|
29
29
|
|
|
30
30
|
def load_model_data(self, apps: AppConfig | None = None) -> int:
|
edc_list_data/row.py
CHANGED
|
@@ -24,7 +24,7 @@ class Row:
|
|
|
24
24
|
@dataclass
|
|
25
25
|
class AsListData:
|
|
26
26
|
data: tuple[tuple[str, str, str], ...] | Choices
|
|
27
|
-
rows: list[Row
|
|
27
|
+
rows: list[Row] | None = field(default_factory=list, init=False)
|
|
28
28
|
|
|
29
29
|
def __post_init__(self):
|
|
30
30
|
for tpl in self.data:
|
edc_list_data/site_list_data.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import contextlib
|
|
1
2
|
import copy
|
|
2
3
|
import sys
|
|
3
4
|
from importlib import import_module
|
|
@@ -51,7 +52,7 @@ class SiteListData:
|
|
|
51
52
|
if app_name and app_name in self.app_names:
|
|
52
53
|
raise AlreadyLoaded(f"App already loaded. Got {app_name}.")
|
|
53
54
|
self.app_names.append(app_name)
|
|
54
|
-
opts =
|
|
55
|
+
opts = {k: v for k, v in self._get_options(module).items()}
|
|
55
56
|
sys.stdout.write(f" - registered {self.module_name} from '{module.__name__}'\n")
|
|
56
57
|
if opts.get(self.module_name):
|
|
57
58
|
self._replace_list_data_or_raise_on_duplicate(module, opts)
|
|
@@ -60,6 +61,8 @@ class SiteListData:
|
|
|
60
61
|
def load_data(self) -> None:
|
|
61
62
|
"""Calls `load` class with each list_data dictionary module to
|
|
62
63
|
update database `list` tables.
|
|
64
|
+
|
|
65
|
+
See post_migrate_list_data.
|
|
63
66
|
"""
|
|
64
67
|
style = color_style()
|
|
65
68
|
for module_name, opts in self.registry.items():
|
|
@@ -142,10 +145,8 @@ class SiteListData:
|
|
|
142
145
|
):
|
|
143
146
|
sys.stdout.write(f" * checking sites for `{self.module_name}` ...\n")
|
|
144
147
|
for app_name in django_apps.app_configs:
|
|
145
|
-
|
|
148
|
+
with contextlib.suppress(ModuleNotFoundError):
|
|
146
149
|
self._import_and_register(app_name)
|
|
147
|
-
except ModuleNotFoundError:
|
|
148
|
-
pass
|
|
149
150
|
|
|
150
151
|
def _import_and_register(self, app_name: str) -> None:
|
|
151
152
|
mod = import_module(app_name)
|
|
@@ -155,7 +156,7 @@ class SiteListData:
|
|
|
155
156
|
except ImportError as e:
|
|
156
157
|
site_list_data.registry = before_import_registry
|
|
157
158
|
if module_has_submodule(mod, self.module_name):
|
|
158
|
-
raise SiteListDataError(f"{e} See {app_name}.{self.module_name}")
|
|
159
|
+
raise SiteListDataError(f"{e} See {app_name}.{self.module_name}") from e
|
|
159
160
|
else:
|
|
160
161
|
self.register(module, app_name=app_name)
|
|
161
162
|
|
|
@@ -7,6 +7,7 @@ import django_audit_fields.fields.uuid_auto_field
|
|
|
7
7
|
import django_audit_fields.models.audit_model_mixin
|
|
8
8
|
import django_revision.revision_field
|
|
9
9
|
from django.db import migrations, models
|
|
10
|
+
import django.utils.timezone
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class Migration(migrations.Migration):
|
|
@@ -33,14 +34,14 @@ class Migration(migrations.Migration):
|
|
|
33
34
|
"created",
|
|
34
35
|
models.DateTimeField(
|
|
35
36
|
blank=True,
|
|
36
|
-
default=
|
|
37
|
+
default=django.utils.timezone.now,
|
|
37
38
|
),
|
|
38
39
|
),
|
|
39
40
|
(
|
|
40
41
|
"modified",
|
|
41
42
|
models.DateTimeField(
|
|
42
43
|
blank=True,
|
|
43
|
-
default=
|
|
44
|
+
default=django.utils.timezone.now,
|
|
44
45
|
),
|
|
45
46
|
),
|
|
46
47
|
(
|