clinicedc 2.0.5__py3-none-any.whl → 2.0.7__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.5.dist-info → clinicedc-2.0.7.dist-info}/METADATA +2 -2
- {clinicedc-2.0.5.dist-info → clinicedc-2.0.7.dist-info}/RECORD +387 -336
- edc_action_item/action.py +1 -1
- edc_action_item/action_item_notification.py +2 -2
- 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 +4 -4
- edc_action_item/models/reference.py +2 -2
- edc_action_item/post_migrate_signals.py +1 -1
- edc_action_item/send_email.py +0 -85
- edc_adherence/migrations/0005_alter_nonadherencereasons_extra_value_and_more.py +36 -0
- edc_adherence/model_mixins.py +1 -1
- 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/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/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/window_period_model_mixin.py +6 -7
- edc_appointment/models/signals.py +44 -35
- edc_appointment/view_utils/appointment_button.py +2 -2
- edc_auth/admin/user_admin.py +1 -1
- 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/post_migrate_signals.py +1 -1
- edc_consent/actions.py +4 -5
- 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_crf/migrations/0001_initial.py +3 -2
- edc_crf/migrations/0009_alter_crfstatus_device_created_and_more.py +54 -0
- 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_data_manager/action_items.py +4 -6
- edc_data_manager/admin/actions.py +5 -5
- 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/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 +4 -3
- 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 +13 -14
- 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/facility.py +10 -15
- 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_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_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/simple_identifier.py +1 -3
- edc_identifier/subject_identifier.py +3 -2
- 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 +7 -8
- 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/box.py +1 -1
- edc_lab/models/box_item.py +6 -7
- edc_lab/models/manifest/manifest.py +1 -1
- edc_lab/models/manifest/manifest_item.py +6 -6
- 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/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/model_mixins/blood_result_model_mixin.py +7 -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/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/model_mixins.py +12 -4
- edc_list_data/preload_data.py +3 -3
- edc_listboard/migrations/0001_initial.py +3 -2
- edc_listboard/migrations/0007_alter_listboard_device_created_and_more.py +49 -0
- 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/metadata_rules/decorators.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 +1 -1
- edc_metadata/model_mixins/updates/updates_requisition_metadata_model_mixin.py +1 -1
- 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/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/migrations/0004_auto_20220825_0451.py +3 -2
- edc_navbar/migrations/0009_alter_edcpermissions_device_created_and_more.py +49 -0
- 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/notification.py +12 -12
- 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 +2 -1
- 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/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/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/utils/allocate_stock.py +2 -3
- edc_pharmacy/utils/confirm_stock.py +2 -3
- edc_pharmacy/utils/confirm_stock_at_site.py +3 -4
- 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/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_protocol/research_protocol_config.py +2 -3
- 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/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/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/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/utils.py +2 -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 +3 -3
- 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 +2 -3
- edc_registration/models/registered_subject.py +27 -26
- 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/load_data.py +4 -4
- edc_reportable/utils/update_grading_data.py +5 -5
- 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 +3 -3
- 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 -4
- edc_screening/model_mixins/screening_fields_model_mixin.py +6 -8
- edc_search/model_mixins.py +2 -3
- edc_search/search_slug.py +9 -8
- edc_search/updater.py +2 -2
- 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/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/model_mixins.py +22 -20
- edc_transfer/model_mixins.py +4 -4
- edc_transfer/modeladmin_mixins.py +1 -1
- 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/age.py +10 -16
- 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/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 +1 -1
- edc_visit_tracking/models/subject_visit.py +1 -1
- edc_vitals/calculators/bmi.py +7 -5
- edc_vitals/form_validators/blood_pressure_form_validator_mixin.py +3 -1
- edc_vitals/utils.py +1 -1
- {clinicedc-2.0.5.dist-info → clinicedc-2.0.7.dist-info}/WHEEL +0 -0
- {clinicedc-2.0.5.dist-info → clinicedc-2.0.7.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import csv
|
|
2
|
-
import os
|
|
3
2
|
import uuid
|
|
3
|
+
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
from django.apps import apps as django_apps
|
|
6
6
|
from django.core.exceptions import ValidationError
|
|
7
|
-
|
|
8
|
-
from edc_utils import get_utcnow
|
|
7
|
+
from django.utils import timezone
|
|
9
8
|
|
|
10
9
|
from ..utils import get_export_folder
|
|
11
10
|
from .file_history_updater import FileHistoryUpdater
|
|
@@ -17,11 +16,11 @@ class ModelExporterError(Exception):
|
|
|
17
16
|
pass
|
|
18
17
|
|
|
19
18
|
|
|
20
|
-
class ModelExporterInvalidLookup(Exception):
|
|
19
|
+
class ModelExporterInvalidLookup(Exception): # noqa: N818
|
|
21
20
|
pass
|
|
22
21
|
|
|
23
22
|
|
|
24
|
-
class ModelExporterUnknownField(ValidationError):
|
|
23
|
+
class ModelExporterUnknownField(ValidationError): # noqa: N818
|
|
25
24
|
pass
|
|
26
25
|
|
|
27
26
|
|
|
@@ -40,14 +39,14 @@ class ModelExporter:
|
|
|
40
39
|
value_getter_cls = ValueGetter
|
|
41
40
|
additional_values_cls = AdditionalValues
|
|
42
41
|
|
|
43
|
-
export_fields =
|
|
42
|
+
export_fields = (
|
|
44
43
|
"export_uuid",
|
|
45
44
|
"timestamp",
|
|
46
45
|
"export_datetime",
|
|
47
46
|
"export_change_type",
|
|
48
|
-
|
|
49
|
-
required_fields =
|
|
50
|
-
audit_fields =
|
|
47
|
+
)
|
|
48
|
+
required_fields = ("subject_identifier", "report_datetime")
|
|
49
|
+
audit_fields = (
|
|
51
50
|
"hostname_created",
|
|
52
51
|
"hostname_modified",
|
|
53
52
|
"created",
|
|
@@ -55,7 +54,7 @@ class ModelExporter:
|
|
|
55
54
|
"user_created",
|
|
56
55
|
"user_modified",
|
|
57
56
|
"revision",
|
|
58
|
-
|
|
57
|
+
)
|
|
59
58
|
|
|
60
59
|
def __init__(
|
|
61
60
|
self,
|
|
@@ -117,13 +116,13 @@ class ModelExporter:
|
|
|
117
116
|
self._model_cls = self.queryset.model
|
|
118
117
|
return self._model_cls
|
|
119
118
|
|
|
120
|
-
def export(self, queryset=None):
|
|
119
|
+
def export(self, queryset=None) -> Path:
|
|
121
120
|
"""Writes the export file and returns the file name."""
|
|
122
121
|
self.queryset = queryset or self.queryset
|
|
123
|
-
exported_datetime =
|
|
122
|
+
exported_datetime = timezone.now()
|
|
124
123
|
filename = self.get_filename(exported_datetime)
|
|
125
|
-
path =
|
|
126
|
-
with open(
|
|
124
|
+
path = get_export_folder() / filename
|
|
125
|
+
with path.open("w") as f:
|
|
127
126
|
csv_writer = csv.DictWriter(
|
|
128
127
|
f, fieldnames=self.field_names, delimiter=self.delimiter
|
|
129
128
|
)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from django.apps import apps as django_apps
|
|
2
2
|
from django.core import serializers
|
|
3
3
|
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
|
|
4
|
+
from django.utils import timezone
|
|
4
5
|
|
|
5
6
|
from edc_constants.constants import NEW
|
|
6
|
-
from edc_utils import get_utcnow
|
|
7
7
|
|
|
8
8
|
from ..constants import EXPORTED, INSERT, UPDATE
|
|
9
9
|
|
|
@@ -24,7 +24,7 @@ class ObjectHistoryCreator(Base):
|
|
|
24
24
|
def create(self, model_obj=None, change_type=None, using=None):
|
|
25
25
|
if not change_type:
|
|
26
26
|
change_type = self.get_change_type(model_obj=model_obj)
|
|
27
|
-
export_datetime =
|
|
27
|
+
export_datetime = timezone.now()
|
|
28
28
|
if model_obj._meta.proxy_for_model: # if proxy model, get main model
|
|
29
29
|
model_obj = model_obj._meta.proxy_for_model.objects.get(id=model_obj.id)
|
|
30
30
|
obj = self.model_cls.objects.using(using).create(
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from django.db import models
|
|
2
2
|
from django.db.models import Index
|
|
3
3
|
from django.db.models.deletion import PROTECT
|
|
4
|
+
from django.utils import timezone
|
|
4
5
|
|
|
5
6
|
from edc_model.models import BaseUuidModel
|
|
6
7
|
from edc_sites.model_mixins import SiteModelMixin
|
|
7
|
-
from edc_utils import get_utcnow
|
|
8
8
|
|
|
9
9
|
from .data_request import DataRequest
|
|
10
10
|
|
|
@@ -12,15 +12,15 @@ from .data_request import DataRequest
|
|
|
12
12
|
class DataRequestHistory(SiteModelMixin, BaseUuidModel):
|
|
13
13
|
data_request = models.ForeignKey(DataRequest, on_delete=PROTECT)
|
|
14
14
|
|
|
15
|
-
archive_filename = models.CharField(max_length=200,
|
|
15
|
+
archive_filename = models.CharField(max_length=200, default="")
|
|
16
16
|
|
|
17
|
-
emailed_to = models.EmailField(
|
|
17
|
+
emailed_to = models.EmailField(default="")
|
|
18
18
|
|
|
19
19
|
emailed_datetime = models.DateTimeField(null=True)
|
|
20
20
|
|
|
21
21
|
summary = models.TextField(default="")
|
|
22
22
|
|
|
23
|
-
exported_datetime = models.DateTimeField(default=
|
|
23
|
+
exported_datetime = models.DateTimeField(default=timezone.now)
|
|
24
24
|
|
|
25
25
|
class Meta:
|
|
26
26
|
verbose_name = "Data Request History"
|
edc_export/utils.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import os
|
|
4
3
|
import re
|
|
5
4
|
from collections.abc import Iterable
|
|
5
|
+
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
from django import forms
|
|
8
|
+
from django.conf import settings
|
|
8
9
|
from django.utils.html import format_html
|
|
9
10
|
|
|
10
11
|
from edc_protocol.research_protocol_config import ResearchProtocolConfig
|
|
@@ -13,15 +14,13 @@ from .constants import EXPORT_PII
|
|
|
13
14
|
from .exceptions import ExporterExportFolder
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
def get_export_folder() ->
|
|
17
|
-
from django.conf import settings
|
|
18
|
-
|
|
17
|
+
def get_export_folder() -> Path:
|
|
19
18
|
if path := getattr(settings, "EDC_EXPORT_EXPORT_FOLDER", None):
|
|
20
|
-
return
|
|
21
|
-
return
|
|
19
|
+
return Path(path).expanduser()
|
|
20
|
+
return Path(settings.MEDIA_ROOT) / "data_folder" / "export"
|
|
22
21
|
|
|
23
22
|
|
|
24
|
-
def get_base_dir() ->
|
|
23
|
+
def get_base_dir() -> Path:
|
|
25
24
|
"""Returns the base_dir used by, for example,
|
|
26
25
|
shutil.make_archive.
|
|
27
26
|
|
|
@@ -37,20 +36,16 @@ def get_base_dir() -> str:
|
|
|
37
36
|
"Invalid base_dir, invalid characters. Using `protocol_lower_name`. "
|
|
38
37
|
f"Got `{base_dir}`."
|
|
39
38
|
)
|
|
40
|
-
return base_dir
|
|
41
|
-
|
|
39
|
+
return Path(base_dir)
|
|
42
40
|
|
|
43
|
-
def get_upload_folder() -> str:
|
|
44
|
-
from django.conf import settings
|
|
45
41
|
|
|
42
|
+
def get_upload_folder() -> Path:
|
|
46
43
|
if path := getattr(settings, "EDC_EXPORT_UPLOAD_FOLDER", None):
|
|
47
|
-
return
|
|
48
|
-
return
|
|
44
|
+
return Path(path).expanduser()
|
|
45
|
+
return Path(settings.MEDIA_ROOT) / "data_folder" / "upload"
|
|
49
46
|
|
|
50
47
|
|
|
51
48
|
def get_export_pii_users() -> list[str]:
|
|
52
|
-
from django.conf import settings
|
|
53
|
-
|
|
54
49
|
return getattr(settings, "EDC_EXPORT_EXPORT_PII_USERS", [])
|
|
55
50
|
|
|
56
51
|
|
edc_facility/facility.py
CHANGED
|
@@ -10,14 +10,15 @@ from arrow import Arrow
|
|
|
10
10
|
from dateutil._common import weekday
|
|
11
11
|
from dateutil.relativedelta import relativedelta
|
|
12
12
|
from django.conf import settings
|
|
13
|
+
from django.utils import timezone
|
|
13
14
|
|
|
14
|
-
from edc_utils import convert_php_dateformat,
|
|
15
|
+
from edc_utils import convert_php_dateformat, to_utc
|
|
15
16
|
|
|
16
17
|
from .exceptions import FacilityError
|
|
17
18
|
from .holidays import Holidays
|
|
18
19
|
|
|
19
20
|
if TYPE_CHECKING:
|
|
20
|
-
|
|
21
|
+
pass
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class Facility:
|
|
@@ -34,9 +35,9 @@ class Facility:
|
|
|
34
35
|
|
|
35
36
|
def __init__(
|
|
36
37
|
self,
|
|
37
|
-
name: str = None,
|
|
38
|
-
days: list = None,
|
|
39
|
-
slots: list[int] = None,
|
|
38
|
+
name: str | None = None,
|
|
39
|
+
days: list | None = None,
|
|
40
|
+
slots: list[int] | None = None,
|
|
40
41
|
best_effort_available_datetime: datetime | None = None,
|
|
41
42
|
):
|
|
42
43
|
self.days = []
|
|
@@ -47,11 +48,7 @@ class Facility:
|
|
|
47
48
|
True if best_effort_available_datetime is None else best_effort_available_datetime
|
|
48
49
|
)
|
|
49
50
|
for day in days:
|
|
50
|
-
|
|
51
|
-
day.weekday
|
|
52
|
-
except AttributeError:
|
|
53
|
-
day = weekday(day)
|
|
54
|
-
self.days.append(day)
|
|
51
|
+
self.days.append(getattr(day, "weekday", weekday(day)))
|
|
55
52
|
self.slots = slots or [99999 for _ in self.days]
|
|
56
53
|
self.config = dict(zip([str(d) for d in self.days], self.slots, strict=False))
|
|
57
54
|
self.holidays = self.holiday_cls()
|
|
@@ -112,7 +109,7 @@ class Facility:
|
|
|
112
109
|
span_gt = [arw for arw in span if arw.date() > suggested_arr.date()]
|
|
113
110
|
arr_span = []
|
|
114
111
|
max_len = max(len(span_lt), len(span_gt))
|
|
115
|
-
for
|
|
112
|
+
for _ in range(0, max_len):
|
|
116
113
|
try:
|
|
117
114
|
item = span_lt.pop()
|
|
118
115
|
except IndexError:
|
|
@@ -135,7 +132,6 @@ class Facility:
|
|
|
135
132
|
reverse_delta=None,
|
|
136
133
|
taken_datetimes=None,
|
|
137
134
|
schedule_on_holidays=None,
|
|
138
|
-
site: Site = None,
|
|
139
135
|
):
|
|
140
136
|
"""Returns an arrow object for a datetime equal to or
|
|
141
137
|
close to the suggested datetime.
|
|
@@ -153,7 +149,7 @@ class Facility:
|
|
|
153
149
|
if suggested_datetime:
|
|
154
150
|
suggested_arr = arrow.Arrow.fromdatetime(suggested_datetime)
|
|
155
151
|
else:
|
|
156
|
-
suggested_arr = arrow.Arrow.fromdatetime(
|
|
152
|
+
suggested_arr = arrow.Arrow.fromdatetime(timezone.now())
|
|
157
153
|
arr_span_range, min_arr, max_arr = self.get_arr_span(
|
|
158
154
|
suggested_arr,
|
|
159
155
|
forward_delta,
|
|
@@ -185,7 +181,6 @@ class Facility:
|
|
|
185
181
|
f"{forward_delta.days} days of {formatted_date}. "
|
|
186
182
|
f"Facility is {self!r}."
|
|
187
183
|
)
|
|
188
|
-
|
|
184
|
+
return arrow.Arrow.fromdatetime(
|
|
189
185
|
datetime.combine(available_arr.date(), suggested_arr.time())
|
|
190
186
|
)
|
|
191
|
-
return available_arr
|
edc_facility/import_holidays.py
CHANGED
|
@@ -9,10 +9,10 @@ from typing import TYPE_CHECKING
|
|
|
9
9
|
from django.conf import settings
|
|
10
10
|
from django.core.exceptions import ObjectDoesNotExist
|
|
11
11
|
from django.db import transaction
|
|
12
|
+
from django.utils import timezone
|
|
12
13
|
from tqdm import tqdm
|
|
13
14
|
|
|
14
15
|
from edc_sites.site import sites
|
|
15
|
-
from edc_utils import get_utcnow
|
|
16
16
|
|
|
17
17
|
from .exceptions import HolidayFileNotFoundError, HolidayImportError
|
|
18
18
|
from .utils import get_holiday_model_cls
|
|
@@ -30,14 +30,14 @@ def import_holidays(verbose: bool | None = None, test: bool | None = None) -> No
|
|
|
30
30
|
if test:
|
|
31
31
|
import_for_tests(model_cls)
|
|
32
32
|
else:
|
|
33
|
-
path = settings.HOLIDAY_FILE
|
|
33
|
+
path = Path(settings.HOLIDAY_FILE)
|
|
34
34
|
try:
|
|
35
35
|
if not Path(path).exists():
|
|
36
36
|
raise HolidayFileNotFoundError(path)
|
|
37
|
-
except TypeError:
|
|
37
|
+
except TypeError as e:
|
|
38
38
|
raise HolidayImportError(
|
|
39
39
|
f"Invalid path importing holiday file. See settings.HOLIDAY_FILE. Got {path}."
|
|
40
|
-
)
|
|
40
|
+
) from e
|
|
41
41
|
if verbose:
|
|
42
42
|
sys.stdout.write(
|
|
43
43
|
f"\nImporting holidays from '{path}' into {model_cls._meta.label_lower}\n"
|
|
@@ -52,9 +52,9 @@ def import_holidays(verbose: bool | None = None, test: bool | None = None) -> No
|
|
|
52
52
|
sys.stdout.write("Done.\n")
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
def check_for_duplicates_in_file(path) -> list:
|
|
55
|
+
def check_for_duplicates_in_file(path: Path) -> list:
|
|
56
56
|
"""Returns a list of records."""
|
|
57
|
-
with open(
|
|
57
|
+
with path.open("r") as f:
|
|
58
58
|
reader = csv.DictReader(f, fieldnames=["local_date", "label", "country"])
|
|
59
59
|
recs = [(row["local_date"], row["country"]) for row in reader]
|
|
60
60
|
if len(recs) != len(list(set(recs))):
|
|
@@ -62,18 +62,18 @@ def check_for_duplicates_in_file(path) -> list:
|
|
|
62
62
|
return recs
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
def import_file(path:
|
|
66
|
-
with open(
|
|
65
|
+
def import_file(path: Path, recs: list, model_cls: Holiday):
|
|
66
|
+
with path.open("r") as f:
|
|
67
67
|
reader = csv.DictReader(f, fieldnames=["local_date", "label", "country"])
|
|
68
68
|
for index, row in tqdm(enumerate(reader), total=len(recs)):
|
|
69
69
|
if index == 0:
|
|
70
70
|
continue
|
|
71
71
|
try:
|
|
72
|
-
local_date = datetime.strptime(row["local_date"], "%Y-%m-%d").date()
|
|
72
|
+
local_date = datetime.strptime(row["local_date"], "%Y-%m-%d").date() # noqa: DTZ007
|
|
73
73
|
except ValueError as e:
|
|
74
74
|
raise HolidayImportError(
|
|
75
75
|
f"Invalid format when importing from {path}. Got '{e}'"
|
|
76
|
-
)
|
|
76
|
+
) from e
|
|
77
77
|
else:
|
|
78
78
|
try:
|
|
79
79
|
obj = model_cls.objects.get(country=row["country"], local_date=local_date)
|
|
@@ -87,7 +87,7 @@ def import_file(path: str, recs: list, model_cls: Holiday):
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
def import_for_tests(model_cls: type[Holiday]):
|
|
90
|
-
year =
|
|
90
|
+
year = timezone.now().year
|
|
91
91
|
country = sites.get_current_country()
|
|
92
92
|
if not country:
|
|
93
93
|
raise HolidayImportError(
|
|
@@ -112,11 +112,11 @@ def import_for_tests(model_cls: type[Holiday]):
|
|
|
112
112
|
if index == 0:
|
|
113
113
|
continue
|
|
114
114
|
try:
|
|
115
|
-
local_date = datetime.strptime(row[LOCAL_DATE], "%Y-%m-%d").date()
|
|
115
|
+
local_date = datetime.strptime(row[LOCAL_DATE], "%Y-%m-%d").date() # noqa: DTZ007
|
|
116
116
|
except ValueError as e:
|
|
117
117
|
raise HolidayImportError(
|
|
118
118
|
f"Invalid format when importing holidays (test). Got '{e}'"
|
|
119
|
-
)
|
|
119
|
+
) from e
|
|
120
120
|
else:
|
|
121
121
|
objs.append(
|
|
122
122
|
model_cls(country=row[COUNTRY], local_date=local_date, name=row[LABEL])
|
|
@@ -17,7 +17,8 @@ from django.db import migrations, models
|
|
|
17
17
|
import edc_facility.model_mixins
|
|
18
18
|
import edc_model_fields.fields.other_charfield
|
|
19
19
|
import edc_sites.models
|
|
20
|
-
import
|
|
20
|
+
import django.utils.timezone
|
|
21
|
+
import django.utils.timezone
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class Migration(migrations.Migration):
|
|
@@ -46,14 +47,14 @@ class Migration(migrations.Migration):
|
|
|
46
47
|
"created",
|
|
47
48
|
models.DateTimeField(
|
|
48
49
|
blank=True,
|
|
49
|
-
default=
|
|
50
|
+
default=django.utils.timezone.now,
|
|
50
51
|
),
|
|
51
52
|
),
|
|
52
53
|
(
|
|
53
54
|
"modified",
|
|
54
55
|
models.DateTimeField(
|
|
55
56
|
blank=True,
|
|
56
|
-
default=
|
|
57
|
+
default=django.utils.timezone.now,
|
|
57
58
|
),
|
|
58
59
|
),
|
|
59
60
|
(
|
|
@@ -105,7 +106,7 @@ class Migration(migrations.Migration):
|
|
|
105
106
|
),
|
|
106
107
|
(
|
|
107
108
|
"report_datetime",
|
|
108
|
-
models.DateTimeField(default=
|
|
109
|
+
models.DateTimeField(default=django.utils.timezone.now),
|
|
109
110
|
),
|
|
110
111
|
("name", models.CharField(max_length=25, unique=True)),
|
|
111
112
|
(
|
|
@@ -265,14 +266,14 @@ class Migration(migrations.Migration):
|
|
|
265
266
|
"created",
|
|
266
267
|
models.DateTimeField(
|
|
267
268
|
blank=True,
|
|
268
|
-
default=
|
|
269
|
+
default=django.utils.timezone.now,
|
|
269
270
|
),
|
|
270
271
|
),
|
|
271
272
|
(
|
|
272
273
|
"modified",
|
|
273
274
|
models.DateTimeField(
|
|
274
275
|
blank=True,
|
|
275
|
-
default=
|
|
276
|
+
default=django.utils.timezone.now,
|
|
276
277
|
),
|
|
277
278
|
),
|
|
278
279
|
(
|
|
@@ -323,7 +324,7 @@ class Migration(migrations.Migration):
|
|
|
323
324
|
),
|
|
324
325
|
(
|
|
325
326
|
"report_datetime",
|
|
326
|
-
models.DateTimeField(default=
|
|
327
|
+
models.DateTimeField(default=django.utils.timezone.now),
|
|
327
328
|
),
|
|
328
329
|
("name", models.CharField(db_index=True, max_length=25)),
|
|
329
330
|
(
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Generated by Django 5.2.6 on 2025-09-17 16:53
|
|
2
|
+
|
|
3
|
+
import edc_model_fields.fields.other_charfield
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
("edc_facility", "0015_alter_healthfacility_revision_and_more"),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AlterField(
|
|
15
|
+
model_name="healthfacility",
|
|
16
|
+
name="device_created",
|
|
17
|
+
field=models.CharField(
|
|
18
|
+
blank=True, default="", max_length=10, verbose_name="Device created"
|
|
19
|
+
),
|
|
20
|
+
),
|
|
21
|
+
migrations.AlterField(
|
|
22
|
+
model_name="healthfacility",
|
|
23
|
+
name="device_modified",
|
|
24
|
+
field=models.CharField(
|
|
25
|
+
blank=True, default="", max_length=10, verbose_name="Device modified"
|
|
26
|
+
),
|
|
27
|
+
),
|
|
28
|
+
migrations.AlterField(
|
|
29
|
+
model_name="healthfacility",
|
|
30
|
+
name="health_facility_type_other",
|
|
31
|
+
field=edc_model_fields.fields.other_charfield.OtherCharField(
|
|
32
|
+
blank=True,
|
|
33
|
+
default="",
|
|
34
|
+
max_length=35,
|
|
35
|
+
verbose_name="If other, please specify ...",
|
|
36
|
+
),
|
|
37
|
+
),
|
|
38
|
+
migrations.AlterField(
|
|
39
|
+
model_name="healthfacility",
|
|
40
|
+
name="locale_created",
|
|
41
|
+
field=models.CharField(
|
|
42
|
+
blank=True,
|
|
43
|
+
default="",
|
|
44
|
+
help_text="Auto-updated by Modeladmin",
|
|
45
|
+
max_length=10,
|
|
46
|
+
verbose_name="Locale created",
|
|
47
|
+
),
|
|
48
|
+
),
|
|
49
|
+
migrations.AlterField(
|
|
50
|
+
model_name="healthfacility",
|
|
51
|
+
name="locale_modified",
|
|
52
|
+
field=models.CharField(
|
|
53
|
+
blank=True,
|
|
54
|
+
default="",
|
|
55
|
+
help_text="Auto-updated by Modeladmin",
|
|
56
|
+
max_length=10,
|
|
57
|
+
verbose_name="Locale modified",
|
|
58
|
+
),
|
|
59
|
+
),
|
|
60
|
+
migrations.AlterField(
|
|
61
|
+
model_name="healthfacility",
|
|
62
|
+
name="notes",
|
|
63
|
+
field=models.TextField(blank=True, default=""),
|
|
64
|
+
),
|
|
65
|
+
migrations.AlterField(
|
|
66
|
+
model_name="healthfacilitytypes",
|
|
67
|
+
name="extra_value",
|
|
68
|
+
field=models.CharField(default="", max_length=250),
|
|
69
|
+
),
|
|
70
|
+
migrations.AlterField(
|
|
71
|
+
model_name="healthfacilitytypes",
|
|
72
|
+
name="field_name",
|
|
73
|
+
field=models.CharField(
|
|
74
|
+
blank=True,
|
|
75
|
+
default="",
|
|
76
|
+
editable=False,
|
|
77
|
+
help_text="Not required",
|
|
78
|
+
max_length=25,
|
|
79
|
+
),
|
|
80
|
+
),
|
|
81
|
+
migrations.AlterField(
|
|
82
|
+
model_name="healthfacilitytypes",
|
|
83
|
+
name="plural_name",
|
|
84
|
+
field=models.CharField(
|
|
85
|
+
default="", max_length=250, verbose_name="Plural name"
|
|
86
|
+
),
|
|
87
|
+
),
|
|
88
|
+
migrations.AlterField(
|
|
89
|
+
model_name="historicalhealthfacility",
|
|
90
|
+
name="device_created",
|
|
91
|
+
field=models.CharField(
|
|
92
|
+
blank=True, default="", max_length=10, verbose_name="Device created"
|
|
93
|
+
),
|
|
94
|
+
),
|
|
95
|
+
migrations.AlterField(
|
|
96
|
+
model_name="historicalhealthfacility",
|
|
97
|
+
name="device_modified",
|
|
98
|
+
field=models.CharField(
|
|
99
|
+
blank=True, default="", max_length=10, verbose_name="Device modified"
|
|
100
|
+
),
|
|
101
|
+
),
|
|
102
|
+
migrations.AlterField(
|
|
103
|
+
model_name="historicalhealthfacility",
|
|
104
|
+
name="health_facility_type_other",
|
|
105
|
+
field=edc_model_fields.fields.other_charfield.OtherCharField(
|
|
106
|
+
blank=True,
|
|
107
|
+
default="",
|
|
108
|
+
max_length=35,
|
|
109
|
+
verbose_name="If other, please specify ...",
|
|
110
|
+
),
|
|
111
|
+
),
|
|
112
|
+
migrations.AlterField(
|
|
113
|
+
model_name="historicalhealthfacility",
|
|
114
|
+
name="locale_created",
|
|
115
|
+
field=models.CharField(
|
|
116
|
+
blank=True,
|
|
117
|
+
default="",
|
|
118
|
+
help_text="Auto-updated by Modeladmin",
|
|
119
|
+
max_length=10,
|
|
120
|
+
verbose_name="Locale created",
|
|
121
|
+
),
|
|
122
|
+
),
|
|
123
|
+
migrations.AlterField(
|
|
124
|
+
model_name="historicalhealthfacility",
|
|
125
|
+
name="locale_modified",
|
|
126
|
+
field=models.CharField(
|
|
127
|
+
blank=True,
|
|
128
|
+
default="",
|
|
129
|
+
help_text="Auto-updated by Modeladmin",
|
|
130
|
+
max_length=10,
|
|
131
|
+
verbose_name="Locale modified",
|
|
132
|
+
),
|
|
133
|
+
),
|
|
134
|
+
migrations.AlterField(
|
|
135
|
+
model_name="historicalhealthfacility",
|
|
136
|
+
name="notes",
|
|
137
|
+
field=models.TextField(blank=True, default=""),
|
|
138
|
+
),
|
|
139
|
+
]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Generated by Django 5.2.6 on 2025-09-18 00:24
|
|
2
|
+
|
|
3
|
+
import django.utils.timezone
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
("edc_facility", "0016_alter_healthfacility_device_created_and_more"),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AlterField(
|
|
15
|
+
model_name="healthfacility",
|
|
16
|
+
name="gps",
|
|
17
|
+
field=models.CharField(
|
|
18
|
+
blank=True,
|
|
19
|
+
default="",
|
|
20
|
+
help_text="copy and paste directly from google maps",
|
|
21
|
+
max_length=50,
|
|
22
|
+
),
|
|
23
|
+
),
|
|
24
|
+
migrations.AlterField(
|
|
25
|
+
model_name="healthfacility",
|
|
26
|
+
name="report_datetime",
|
|
27
|
+
field=models.DateTimeField(default=django.utils.timezone.now),
|
|
28
|
+
),
|
|
29
|
+
migrations.AlterField(
|
|
30
|
+
model_name="healthfacility",
|
|
31
|
+
name="title",
|
|
32
|
+
field=models.CharField(blank=True, default="", max_length=150),
|
|
33
|
+
),
|
|
34
|
+
migrations.AlterField(
|
|
35
|
+
model_name="historicalhealthfacility",
|
|
36
|
+
name="gps",
|
|
37
|
+
field=models.CharField(
|
|
38
|
+
blank=True,
|
|
39
|
+
default="",
|
|
40
|
+
help_text="copy and paste directly from google maps",
|
|
41
|
+
max_length=50,
|
|
42
|
+
),
|
|
43
|
+
),
|
|
44
|
+
migrations.AlterField(
|
|
45
|
+
model_name="historicalhealthfacility",
|
|
46
|
+
name="report_datetime",
|
|
47
|
+
field=models.DateTimeField(default=django.utils.timezone.now),
|
|
48
|
+
),
|
|
49
|
+
migrations.AlterField(
|
|
50
|
+
model_name="historicalhealthfacility",
|
|
51
|
+
name="title",
|
|
52
|
+
field=models.CharField(blank=True, default="", max_length=150),
|
|
53
|
+
),
|
|
54
|
+
]
|
edc_facility/model_mixins.py
CHANGED
|
@@ -2,10 +2,10 @@ import calendar
|
|
|
2
2
|
|
|
3
3
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
|
4
4
|
from django.db import models
|
|
5
|
+
from django.utils import timezone
|
|
5
6
|
|
|
6
7
|
from edc_model.models import BaseUuidModel
|
|
7
8
|
from edc_model_fields.fields import OtherCharField
|
|
8
|
-
from edc_utils import get_utcnow
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class HealthFacilityCalendarError(Exception):
|
|
@@ -28,11 +28,11 @@ class HealthFacilityModelMixin(models.Model):
|
|
|
28
28
|
See also edc_appointment.
|
|
29
29
|
"""
|
|
30
30
|
|
|
31
|
-
report_datetime = models.DateTimeField(default=
|
|
31
|
+
report_datetime = models.DateTimeField(default=timezone.now)
|
|
32
32
|
|
|
33
33
|
name = models.CharField(max_length=25, unique=True)
|
|
34
34
|
|
|
35
|
-
title = models.CharField(max_length=150,
|
|
35
|
+
title = models.CharField(max_length=150, default="", blank=True)
|
|
36
36
|
|
|
37
37
|
health_facility_type = models.ForeignKey(
|
|
38
38
|
"edc_facility.HealthFacilityTypes",
|
|
@@ -45,7 +45,7 @@ class HealthFacilityModelMixin(models.Model):
|
|
|
45
45
|
|
|
46
46
|
gps = models.CharField(
|
|
47
47
|
max_length=50,
|
|
48
|
-
|
|
48
|
+
default="",
|
|
49
49
|
blank=True,
|
|
50
50
|
help_text="copy and paste directly from google maps",
|
|
51
51
|
)
|
|
@@ -115,7 +115,7 @@ class HealthFacilityModelMixin(models.Model):
|
|
|
115
115
|
days = []
|
|
116
116
|
mapping = {k: v for k, v in enumerate(calendar.weekheader(3).split(" "))}
|
|
117
117
|
for day_int in self.clinic_days:
|
|
118
|
-
days.append(mapping.get(day_int))
|
|
118
|
+
days.append(mapping.get(day_int)) # noqa: PERF401
|
|
119
119
|
return ",".join(days)
|
|
120
120
|
|
|
121
121
|
class Meta(BaseUuidModel.Meta):
|
edc_form_runners/form_runner.py
CHANGED
|
@@ -8,10 +8,9 @@ from bs4 import BeautifulSoup
|
|
|
8
8
|
from django.apps import apps as django_apps
|
|
9
9
|
from django.db.models import ForeignKey, ManyToManyField, Model, OneToOneField, QuerySet
|
|
10
10
|
from django.forms import ModelForm
|
|
11
|
+
from django.utils import timezone
|
|
11
12
|
from tqdm import tqdm
|
|
12
13
|
|
|
13
|
-
from edc_utils import get_utcnow
|
|
14
|
-
|
|
15
14
|
from .exceptions import FormRunnerModelAdminNotFound, FormRunnerModelFormNotFound
|
|
16
15
|
from .utils import get_modeladmin_cls
|
|
17
16
|
|
|
@@ -37,7 +36,7 @@ class FormRunner:
|
|
|
37
36
|
) -> None:
|
|
38
37
|
self.messages = {}
|
|
39
38
|
self.session_id = uuid.uuid4()
|
|
40
|
-
self.session_datetime =
|
|
39
|
+
self.session_datetime = timezone.now()
|
|
41
40
|
self.verbose = verbose
|
|
42
41
|
self.model_name = self.model_name or model_name
|
|
43
42
|
self.modeladmin_cls = get_modeladmin_cls(self.model_name)
|
|
@@ -48,8 +47,7 @@ class FormRunner:
|
|
|
48
47
|
)
|
|
49
48
|
if self.modeladmin_cls.form == ModelForm:
|
|
50
49
|
raise FormRunnerModelFormNotFound(
|
|
51
|
-
"ModelAdmin does not have a custom form. Nothing to do. "
|
|
52
|
-
f"Got `{model_name}`."
|
|
50
|
+
f"ModelAdmin does not have a custom form. Nothing to do. Got `{model_name}`."
|
|
53
51
|
)
|
|
54
52
|
self.src_model_cls = self.modeladmin_cls.model
|
|
55
53
|
|