endoreg-db 0.8.6.1__py3-none-any.whl → 0.8.8.9__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 endoreg-db might be problematic. Click here for more details.
- endoreg_db/authz/auth.py +74 -0
- endoreg_db/authz/backends.py +168 -0
- endoreg_db/authz/management/commands/list_routes.py +18 -0
- endoreg_db/authz/middleware.py +83 -0
- endoreg_db/authz/permissions.py +127 -0
- endoreg_db/authz/policy.py +218 -0
- endoreg_db/authz/views_auth.py +66 -0
- endoreg_db/config/env.py +13 -8
- endoreg_db/data/__init__.py +2 -11
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +3 -3
- endoreg_db/data/event_classification/data.yaml +4 -0
- endoreg_db/data/event_classification_choice/data.yaml +9 -0
- endoreg_db/data/examination/examinations/data.yaml +114 -14
- endoreg_db/data/examination/time-type/data.yaml +0 -3
- endoreg_db/data/examination_indication/endoscopy.yaml +108 -173
- endoreg_db/data/examination_indication_classification/endoscopy.yaml +0 -70
- endoreg_db/data/examination_indication_classification_choice/endoscopy.yaml +33 -37
- endoreg_db/data/finding/00_generic.yaml +35 -0
- endoreg_db/data/finding/00_generic_complication.yaml +9 -0
- endoreg_db/data/finding/01_gastroscopy_baseline.yaml +88 -0
- endoreg_db/data/finding/01_gastroscopy_observation.yaml +113 -0
- endoreg_db/data/finding/02_colonoscopy_baseline.yaml +53 -0
- endoreg_db/data/finding/02_colonoscopy_hidden.yaml +119 -0
- endoreg_db/data/finding/02_colonoscopy_observation.yaml +152 -0
- endoreg_db/data/finding_classification/00_generic.yaml +44 -0
- endoreg_db/data/finding_classification/00_generic_histology.yaml +28 -0
- endoreg_db/data/finding_classification/00_generic_lesion.yaml +52 -0
- endoreg_db/data/finding_classification/02_colonoscopy_baseline.yaml +83 -0
- endoreg_db/data/finding_classification/02_colonoscopy_histology.yaml +13 -0
- endoreg_db/data/finding_classification/02_colonoscopy_other.yaml +12 -0
- endoreg_db/data/finding_classification/02_colonoscopy_polyp.yaml +101 -0
- endoreg_db/data/finding_classification_choice/{yes_no_na.yaml → 00_generic.yaml} +5 -1
- endoreg_db/data/finding_classification_choice/{examination_setting_generic_types.yaml → 00_generic_baseline.yaml} +10 -2
- endoreg_db/data/finding_classification_choice/{complication_generic_types.yaml → 00_generic_complication.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{histology.yaml → 00_generic_histology.yaml} +1 -4
- endoreg_db/data/finding_classification_choice/00_generic_lesion.yaml +158 -0
- endoreg_db/data/finding_classification_choice/{bowel_preparation.yaml → 02_colonoscopy_bowel_preparation.yaml} +1 -30
- endoreg_db/data/finding_classification_choice/{colonoscopy_not_complete_reason.yaml → 02_colonoscopy_generic.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{histology_polyp.yaml → 02_colonoscopy_histology.yaml} +1 -1
- endoreg_db/data/finding_classification_choice/{colonoscopy_location.yaml → 02_colonoscopy_location.yaml} +23 -4
- endoreg_db/data/finding_classification_choice/02_colonoscopy_other.yaml +34 -0
- endoreg_db/data/finding_classification_choice/02_colonoscopy_polyp_advanced_imaging.yaml +76 -0
- endoreg_db/data/finding_classification_choice/{colon_lesion_paris.yaml → 02_colonoscopy_polyp_morphology.yaml} +26 -8
- endoreg_db/data/finding_classification_choice/02_colonoscopy_size.yaml +27 -0
- endoreg_db/data/finding_classification_type/{colonoscopy_basic.yaml → 00_generic.yaml} +18 -13
- endoreg_db/data/finding_classification_type/02_colonoscopy.yaml +9 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy.yaml +59 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_ablation.yaml +44 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_bleeding.yaml +55 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_resection.yaml +85 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_stenosis.yaml +17 -0
- endoreg_db/data/finding_intervention/00_generic_endoscopy_stent.yaml +9 -0
- endoreg_db/data/finding_intervention/01_gastroscopy.yaml +19 -0
- endoreg_db/data/finding_intervention/04_eus.yaml +39 -0
- endoreg_db/data/finding_intervention/05_ercp.yaml +3 -0
- endoreg_db/data/finding_type/data.yaml +8 -12
- endoreg_db/data/requirement/01_patient_data.yaml +93 -0
- endoreg_db/data/requirement/old/colon_polyp_intervention.yaml +49 -0
- endoreg_db/data/requirement/old/coloreg_colon_polyp.yaml +49 -0
- endoreg_db/data/requirement_operator/new_operators.yaml +36 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +29 -12
- endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
- endoreg_db/data/requirement_set/{endoscopy_bleeding_risk.yaml → 02_endoscopy_bleeding_risk.yaml} +0 -6
- endoreg_db/data/requirement_set/90_coloreg.yaml +190 -0
- endoreg_db/data/requirement_set/_old_ +109 -0
- endoreg_db/data/requirement_set_type/data.yaml +21 -0
- endoreg_db/data/setup_config.yaml +4 -4
- endoreg_db/data/tag/requirement_set_tags.yaml +21 -0
- endoreg_db/exceptions.py +4 -2
- endoreg_db/forms/examination_form.py +1 -1
- endoreg_db/helpers/data_loader.py +125 -53
- endoreg_db/helpers/default_objects.py +116 -81
- endoreg_db/import_files/__init__.py +27 -0
- endoreg_db/import_files/context/__init__.py +7 -0
- endoreg_db/import_files/context/default_sensitive_meta.py +81 -0
- endoreg_db/import_files/context/ensure_center.py +17 -0
- endoreg_db/import_files/context/file_lock.py +66 -0
- endoreg_db/import_files/context/import_context.py +43 -0
- endoreg_db/import_files/context/validate_directories.py +56 -0
- endoreg_db/import_files/file_storage/__init__.py +15 -0
- endoreg_db/import_files/file_storage/create_report_file.py +76 -0
- endoreg_db/import_files/file_storage/create_video_file.py +75 -0
- endoreg_db/import_files/file_storage/sensitive_meta_storage.py +39 -0
- endoreg_db/import_files/file_storage/state_management.py +400 -0
- endoreg_db/import_files/file_storage/storage.py +36 -0
- endoreg_db/import_files/import_service.md +26 -0
- endoreg_db/import_files/processing/__init__.py +11 -0
- endoreg_db/import_files/processing/report_processing/report_anonymization.py +94 -0
- endoreg_db/import_files/processing/sensitive_meta_adapter.py +51 -0
- endoreg_db/import_files/processing/video_processing/video_anonymization.py +107 -0
- endoreg_db/import_files/processing/video_processing/video_cleanup_on_error.py +119 -0
- endoreg_db/import_files/pseudonymization/fake.py +52 -0
- endoreg_db/import_files/pseudonymization/k_anonymity.py +182 -0
- endoreg_db/import_files/pseudonymization/k_pseudonymity.py +128 -0
- endoreg_db/import_files/report_import_service.py +141 -0
- endoreg_db/import_files/video_import_service.py +150 -0
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +21 -10
- endoreg_db/management/commands/create_multilabel_model_meta.py +299 -129
- endoreg_db/management/commands/import_report.py +130 -65
- endoreg_db/management/commands/import_video.py +9 -10
- endoreg_db/management/commands/import_video_with_classification.py +2 -2
- endoreg_db/management/commands/list_routes.py +18 -0
- endoreg_db/management/commands/load_ai_model_data.py +5 -5
- endoreg_db/management/commands/load_ai_model_label_data.py +9 -7
- endoreg_db/management/commands/load_base_db_data.py +5 -134
- endoreg_db/management/commands/load_center_data.py +12 -12
- endoreg_db/management/commands/load_contraindication_data.py +14 -16
- endoreg_db/management/commands/load_disease_classification_choices_data.py +15 -18
- endoreg_db/management/commands/load_disease_classification_data.py +15 -18
- endoreg_db/management/commands/load_disease_data.py +25 -28
- endoreg_db/management/commands/load_endoscope_data.py +20 -27
- endoreg_db/management/commands/load_event_data.py +14 -16
- endoreg_db/management/commands/load_examination_data.py +31 -44
- endoreg_db/management/commands/load_examination_indication_data.py +20 -21
- endoreg_db/management/commands/load_finding_data.py +52 -80
- endoreg_db/management/commands/load_information_source.py +21 -23
- endoreg_db/management/commands/load_lab_value_data.py +17 -26
- endoreg_db/management/commands/load_medication_data.py +13 -12
- endoreg_db/management/commands/load_organ_data.py +15 -19
- endoreg_db/management/commands/load_pdf_type_data.py +19 -18
- endoreg_db/management/commands/load_profession_data.py +14 -17
- endoreg_db/management/commands/load_qualification_data.py +20 -23
- endoreg_db/management/commands/load_report_reader_flag_data.py +17 -19
- endoreg_db/management/commands/load_requirement_data.py +62 -39
- endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
- endoreg_db/management/commands/load_risk_data.py +7 -6
- endoreg_db/management/commands/load_shift_data.py +20 -23
- endoreg_db/management/commands/load_tag_data.py +8 -11
- endoreg_db/management/commands/load_unit_data.py +17 -19
- endoreg_db/management/commands/setup_endoreg_db.py +3 -3
- endoreg_db/management/commands/start_filewatcher.py +46 -37
- endoreg_db/management/commands/storage_management.py +271 -203
- endoreg_db/management/commands/validate_video_files.py +1 -5
- endoreg_db/migrations/0001_initial.py +297 -250
- endoreg_db/models/__init__.py +78 -123
- endoreg_db/models/administration/__init__.py +21 -42
- endoreg_db/models/administration/ai/active_model.py +2 -2
- endoreg_db/models/administration/ai/ai_model.py +7 -6
- endoreg_db/models/administration/case/__init__.py +1 -15
- endoreg_db/models/administration/case/case.py +3 -3
- endoreg_db/models/administration/case/case_template/__init__.py +2 -14
- endoreg_db/models/administration/case/case_template/case_template.py +2 -124
- endoreg_db/models/administration/case/case_template/case_template_rule.py +2 -268
- endoreg_db/models/administration/case/case_template/case_template_rule_value.py +2 -85
- endoreg_db/models/administration/case/case_template/case_template_type.py +2 -25
- endoreg_db/models/administration/center/center.py +33 -19
- endoreg_db/models/administration/center/center_product.py +12 -9
- endoreg_db/models/administration/center/center_resource.py +25 -19
- endoreg_db/models/administration/center/center_shift.py +21 -17
- endoreg_db/models/administration/center/center_waste.py +16 -8
- endoreg_db/models/administration/person/__init__.py +2 -0
- endoreg_db/models/administration/person/employee/employee.py +10 -5
- endoreg_db/models/administration/person/employee/employee_qualification.py +9 -4
- endoreg_db/models/administration/person/employee/employee_type.py +12 -6
- endoreg_db/models/administration/person/examiner/examiner.py +13 -11
- endoreg_db/models/administration/person/patient/__init__.py +2 -0
- endoreg_db/models/administration/person/patient/patient.py +129 -100
- endoreg_db/models/administration/person/patient/patient_external_id.py +37 -0
- endoreg_db/models/administration/person/person.py +4 -0
- endoreg_db/models/administration/person/profession/__init__.py +8 -4
- endoreg_db/models/administration/person/user/portal_user_information.py +11 -7
- endoreg_db/models/administration/product/product.py +20 -15
- endoreg_db/models/administration/product/product_material.py +17 -18
- endoreg_db/models/administration/product/product_weight.py +12 -8
- endoreg_db/models/administration/product/reference_product.py +23 -55
- endoreg_db/models/administration/qualification/qualification.py +7 -3
- endoreg_db/models/administration/qualification/qualification_type.py +7 -3
- endoreg_db/models/administration/shift/scheduled_days.py +8 -5
- endoreg_db/models/administration/shift/shift.py +16 -12
- endoreg_db/models/administration/shift/shift_type.py +23 -31
- endoreg_db/models/label/__init__.py +8 -9
- endoreg_db/models/label/annotation/image_classification.py +10 -9
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +23 -28
- endoreg_db/models/label/label.py +15 -15
- endoreg_db/models/label/label_set.py +19 -6
- endoreg_db/models/label/label_type.py +1 -1
- endoreg_db/models/label/label_video_segment/_create_from_video.py +5 -8
- endoreg_db/models/label/label_video_segment/label_video_segment.py +98 -102
- endoreg_db/models/label/video_segmentation_label.py +4 -0
- endoreg_db/models/label/video_segmentation_labelset.py +4 -3
- endoreg_db/models/media/frame/frame.py +22 -22
- endoreg_db/models/media/pdf/raw_pdf.py +194 -194
- endoreg_db/models/media/pdf/report_file.py +25 -29
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +55 -47
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
- endoreg_db/models/media/processing_history/__init__.py +5 -0
- endoreg_db/models/media/processing_history/processing_history.py +96 -0
- endoreg_db/models/media/video/__init__.py +1 -0
- endoreg_db/models/media/video/create_from_file.py +139 -77
- endoreg_db/models/media/video/pipe_2.py +8 -9
- endoreg_db/models/media/video/video_file.py +174 -112
- endoreg_db/models/media/video/video_file_ai.py +288 -74
- endoreg_db/models/media/video/video_file_anonymize.py +38 -38
- endoreg_db/models/media/video/video_file_frames/__init__.py +3 -1
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +7 -9
- endoreg_db/models/media/video/video_file_frames/_delete_frames.py +9 -8
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +38 -45
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_get_frame_number.py +4 -18
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -3
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +7 -6
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +6 -8
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +15 -25
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +26 -23
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +23 -14
- endoreg_db/models/media/video/video_file_io.py +113 -61
- endoreg_db/models/media/video/video_file_meta/get_crop_template.py +3 -3
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +5 -3
- endoreg_db/models/media/video/video_file_meta/get_fps.py +37 -34
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +19 -25
- endoreg_db/models/media/video/video_file_meta/text_meta.py +41 -38
- endoreg_db/models/media/video/video_file_meta/video_meta.py +14 -7
- endoreg_db/models/media/video/video_file_segments.py +24 -17
- endoreg_db/models/media/video/video_metadata.py +19 -35
- endoreg_db/models/media/video/video_processing.py +96 -95
- endoreg_db/models/medical/contraindication/README.md +1 -0
- endoreg_db/models/medical/contraindication/__init__.py +13 -3
- endoreg_db/models/medical/disease.py +22 -16
- endoreg_db/models/medical/event.py +31 -18
- endoreg_db/models/medical/examination/__init__.py +13 -6
- endoreg_db/models/medical/examination/examination.py +39 -20
- endoreg_db/models/medical/examination/examination_indication.py +30 -95
- endoreg_db/models/medical/examination/examination_time.py +23 -8
- endoreg_db/models/medical/examination/examination_time_type.py +9 -6
- endoreg_db/models/medical/examination/examination_type.py +3 -4
- endoreg_db/models/medical/finding/finding.py +32 -40
- endoreg_db/models/medical/finding/finding_classification.py +42 -72
- endoreg_db/models/medical/finding/finding_intervention.py +25 -22
- endoreg_db/models/medical/finding/finding_type.py +13 -12
- endoreg_db/models/medical/hardware/endoscope.py +26 -26
- endoreg_db/models/medical/hardware/endoscopy_processor.py +2 -2
- endoreg_db/models/medical/laboratory/lab_value.py +62 -91
- endoreg_db/models/medical/medication/medication.py +22 -10
- endoreg_db/models/medical/medication/medication_indication.py +29 -3
- endoreg_db/models/medical/medication/medication_indication_type.py +25 -14
- endoreg_db/models/medical/medication/medication_intake_time.py +31 -19
- endoreg_db/models/medical/medication/medication_schedule.py +27 -16
- endoreg_db/models/medical/organ/__init__.py +15 -12
- endoreg_db/models/medical/patient/medication_examples.py +6 -6
- endoreg_db/models/medical/patient/patient_disease.py +20 -23
- endoreg_db/models/medical/patient/patient_event.py +19 -22
- endoreg_db/models/medical/patient/patient_examination.py +48 -54
- endoreg_db/models/medical/patient/patient_examination_indication.py +16 -14
- endoreg_db/models/medical/patient/patient_finding.py +122 -139
- endoreg_db/models/medical/patient/patient_finding_classification.py +44 -49
- endoreg_db/models/medical/patient/patient_finding_intervention.py +8 -19
- endoreg_db/models/medical/patient/patient_lab_sample.py +28 -23
- endoreg_db/models/medical/patient/patient_lab_value.py +82 -89
- endoreg_db/models/medical/patient/patient_medication.py +27 -38
- endoreg_db/models/medical/patient/patient_medication_schedule.py +28 -36
- endoreg_db/models/medical/risk/risk.py +7 -6
- endoreg_db/models/medical/risk/risk_type.py +8 -5
- endoreg_db/models/metadata/model_meta.py +60 -29
- endoreg_db/models/metadata/model_meta_logic.py +125 -18
- endoreg_db/models/metadata/pdf_meta.py +31 -24
- endoreg_db/models/metadata/sensitive_meta.py +105 -85
- endoreg_db/models/metadata/sensitive_meta_logic.py +198 -103
- endoreg_db/models/metadata/video_meta.py +51 -31
- endoreg_db/models/metadata/video_prediction_logic.py +16 -23
- endoreg_db/models/metadata/video_prediction_meta.py +29 -33
- endoreg_db/models/other/distribution/date_value_distribution.py +89 -29
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +21 -5
- endoreg_db/models/other/distribution/numeric_value_distribution.py +114 -53
- endoreg_db/models/other/distribution/single_categorical_value_distribution.py +4 -3
- endoreg_db/models/other/emission/emission_factor.py +18 -8
- endoreg_db/models/other/gender.py +10 -5
- endoreg_db/models/other/information_source.py +50 -29
- endoreg_db/models/other/material.py +9 -5
- endoreg_db/models/other/resource.py +6 -4
- endoreg_db/models/other/tag.py +10 -5
- endoreg_db/models/other/transport_route.py +13 -8
- endoreg_db/models/other/unit.py +10 -6
- endoreg_db/models/other/waste.py +6 -5
- endoreg_db/models/report/report.py +6 -0
- endoreg_db/models/requirement/requirement.py +329 -361
- endoreg_db/models/requirement/requirement_error.py +85 -0
- endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +268 -0
- endoreg_db/models/requirement/requirement_evaluation/operator_evaluation_models.py +3 -6
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +90 -64
- endoreg_db/models/requirement/requirement_operator.py +103 -112
- endoreg_db/models/requirement/requirement_set.py +74 -57
- endoreg_db/models/state/__init__.py +4 -4
- endoreg_db/models/state/abstract.py +2 -2
- endoreg_db/models/state/anonymization.py +12 -0
- endoreg_db/models/state/audit_ledger.py +49 -51
- endoreg_db/models/state/label_video_segment.py +9 -0
- endoreg_db/models/state/raw_pdf.py +101 -68
- endoreg_db/models/state/sensitive_meta.py +6 -2
- endoreg_db/models/state/video.py +110 -90
- endoreg_db/models/upload_job.py +35 -34
- endoreg_db/models/utils.py +28 -25
- endoreg_db/queries/__init__.py +3 -1
- endoreg_db/root_urls.py +21 -2
- endoreg_db/schemas/examination_evaluation.py +1 -1
- endoreg_db/serializers/__init__.py +2 -10
- endoreg_db/serializers/anonymization.py +18 -10
- endoreg_db/serializers/label_video_segment/label_video_segment.py +2 -29
- endoreg_db/serializers/meta/__init__.py +1 -6
- endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
- endoreg_db/serializers/misc/file_overview.py +11 -99
- endoreg_db/serializers/misc/sensitive_patient_data.py +50 -26
- endoreg_db/serializers/patient_examination/patient_examination.py +3 -3
- endoreg_db/serializers/pdf/anony_text_validation.py +39 -23
- endoreg_db/serializers/requirements/requirement_sets.py +92 -22
- endoreg_db/serializers/video/segmentation.py +2 -1
- endoreg_db/serializers/video/video_file_list.py +65 -34
- endoreg_db/serializers/video/video_processing_history.py +20 -5
- endoreg_db/services/__old/pdf_import.py +1487 -0
- endoreg_db/services/__old/video_import.py +1306 -0
- endoreg_db/services/anonymization.py +128 -89
- endoreg_db/services/lookup_service.py +65 -52
- endoreg_db/services/lookup_store.py +2 -2
- endoreg_db/services/pdf_import.py +0 -1382
- endoreg_db/services/report_import.py +10 -0
- endoreg_db/services/video_import.py +6 -1255
- endoreg_db/tasks/upload_tasks.py +79 -70
- endoreg_db/tasks/video_ingest.py +8 -4
- endoreg_db/urls/__init__.py +5 -32
- endoreg_db/urls/ai.py +32 -0
- endoreg_db/urls/media.py +121 -83
- endoreg_db/urls/root_urls.py +29 -0
- endoreg_db/utils/__init__.py +15 -5
- endoreg_db/utils/ai/multilabel_classification_net.py +116 -20
- endoreg_db/utils/case_generator/__init__.py +3 -0
- endoreg_db/utils/dataloader.py +142 -40
- endoreg_db/utils/defaults/set_default_center.py +32 -0
- endoreg_db/utils/names.py +22 -16
- endoreg_db/utils/paths.py +110 -46
- endoreg_db/utils/permissions.py +2 -1
- endoreg_db/utils/pipelines/Readme.md +1 -1
- endoreg_db/utils/pipelines/process_video_dir.py +1 -1
- endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +655 -0
- endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +97 -0
- endoreg_db/utils/setup_config.py +8 -5
- endoreg_db/utils/storage.py +115 -0
- endoreg_db/utils/validate_endo_roi.py +8 -2
- endoreg_db/utils/video/ffmpeg_wrapper.py +184 -188
- endoreg_db/views/__init__.py +85 -183
- endoreg_db/views/ai/__init__.py +8 -0
- endoreg_db/views/ai/label.py +155 -0
- endoreg_db/views/anonymization/media_management.py +202 -166
- endoreg_db/views/anonymization/overview.py +99 -67
- endoreg_db/views/anonymization/validate.py +182 -44
- endoreg_db/views/media/__init__.py +7 -20
- endoreg_db/views/media/pdf_media.py +197 -174
- endoreg_db/views/media/sensitive_metadata.py +193 -138
- endoreg_db/views/media/video_media.py +89 -82
- endoreg_db/views/meta/__init__.py +0 -8
- endoreg_db/views/misc/__init__.py +1 -7
- endoreg_db/views/misc/upload_views.py +94 -93
- endoreg_db/views/patient/patient.py +5 -4
- endoreg_db/views/report/__init__.py +5 -7
- endoreg_db/views/{pdf → report}/reimport.py +22 -22
- endoreg_db/views/{pdf/pdf_stream.py → report/report_stream.py} +46 -39
- endoreg_db/views/requirement/evaluate.py +188 -187
- endoreg_db/views/requirement/lookup.py +17 -3
- endoreg_db/views/requirement/lookup_store.py +22 -90
- endoreg_db/views/requirement/requirement_utils.py +89 -0
- endoreg_db/views/video/__init__.py +23 -24
- endoreg_db/views/video/correction.py +201 -172
- endoreg_db/views/video/reimport.py +1 -1
- endoreg_db/views/{media/video_segments.py → video/segments_crud.py} +77 -40
- endoreg_db/views/video/{video_meta.py → video_meta_stats.py} +2 -2
- endoreg_db/views/video/video_stream.py +7 -8
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/METADATA +7 -3
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/RECORD +391 -413
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/WHEEL +1 -1
- endoreg_db/data/finding/anatomy_colon.yaml +0 -128
- endoreg_db/data/finding/colonoscopy.yaml +0 -40
- endoreg_db/data/finding/colonoscopy_bowel_prep.yaml +0 -56
- endoreg_db/data/finding/complication.yaml +0 -16
- endoreg_db/data/finding/data.yaml +0 -105
- endoreg_db/data/finding/examination_setting.yaml +0 -16
- endoreg_db/data/finding/medication_related.yaml +0 -18
- endoreg_db/data/finding/outcome.yaml +0 -12
- endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +0 -95
- endoreg_db/data/finding_classification/colonoscopy_jnet.yaml +0 -22
- endoreg_db/data/finding_classification/colonoscopy_kudo.yaml +0 -25
- endoreg_db/data/finding_classification/colonoscopy_lesion_circularity.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_lesion_planarity.yaml +0 -24
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +0 -68
- endoreg_db/data/finding_classification/colonoscopy_lesion_surface.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +0 -80
- endoreg_db/data/finding_classification/colonoscopy_lst.yaml +0 -21
- endoreg_db/data/finding_classification/colonoscopy_nice.yaml +0 -20
- endoreg_db/data/finding_classification/colonoscopy_paris.yaml +0 -26
- endoreg_db/data/finding_classification/colonoscopy_sano.yaml +0 -22
- endoreg_db/data/finding_classification/colonoscopy_summary.yaml +0 -53
- endoreg_db/data/finding_classification/complication_generic.yaml +0 -25
- endoreg_db/data/finding_classification/examination_setting_generic.yaml +0 -40
- endoreg_db/data/finding_classification/histology_colo.yaml +0 -51
- endoreg_db/data/finding_classification/intervention_required.yaml +0 -26
- endoreg_db/data/finding_classification/medication_related.yaml +0 -23
- endoreg_db/data/finding_classification/visualized.yaml +0 -33
- endoreg_db/data/finding_classification_choice/colon_lesion_circularity_default.yaml +0 -32
- endoreg_db/data/finding_classification_choice/colon_lesion_jnet.yaml +0 -15
- endoreg_db/data/finding_classification_choice/colon_lesion_kudo.yaml +0 -23
- endoreg_db/data/finding_classification_choice/colon_lesion_lst.yaml +0 -15
- endoreg_db/data/finding_classification_choice/colon_lesion_nice.yaml +0 -17
- endoreg_db/data/finding_classification_choice/colon_lesion_planarity_default.yaml +0 -49
- endoreg_db/data/finding_classification_choice/colon_lesion_sano.yaml +0 -14
- endoreg_db/data/finding_classification_choice/colon_lesion_surface_intact_default.yaml +0 -36
- endoreg_db/data/finding_classification_choice/colonoscopy_size.yaml +0 -82
- endoreg_db/data/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +0 -15
- endoreg_db/data/finding_classification_choice/outcome.yaml +0 -19
- endoreg_db/data/finding_intervention/endoscopy.yaml +0 -43
- endoreg_db/data/finding_intervention/endoscopy_colonoscopy.yaml +0 -168
- endoreg_db/data/finding_intervention/endoscopy_egd.yaml +0 -128
- endoreg_db/data/finding_intervention/endoscopy_ercp.yaml +0 -32
- endoreg_db/data/finding_intervention/endoscopy_eus_lower.yaml +0 -9
- endoreg_db/data/finding_intervention/endoscopy_eus_upper.yaml +0 -36
- endoreg_db/data/finding_morphology_classification_type/colonoscopy.yaml +0 -79
- endoreg_db/data/requirement/age.yaml +0 -26
- endoreg_db/data/requirement/gender.yaml +0 -25
- endoreg_db/management/commands/init_default_ai_model.py +0 -112
- endoreg_db/management/commands/reset_celery_schedule.py +0 -9
- endoreg_db/management/commands/validate_video.py +0 -204
- endoreg_db/migrations/0002_add_video_correction_models.py +0 -52
- endoreg_db/migrations/0003_add_center_display_name.py +0 -30
- endoreg_db/models/administration/permissions/__init__.py +0 -44
- endoreg_db/models/rule/__init__.py +0 -13
- endoreg_db/models/rule/rule.py +0 -27
- endoreg_db/models/rule/rule_applicator.py +0 -224
- endoreg_db/models/rule/rule_attribute_dtype.py +0 -17
- endoreg_db/models/rule/rule_type.py +0 -20
- endoreg_db/models/rule/ruleset.py +0 -17
- endoreg_db/renames.yml +0 -8
- endoreg_db/serializers/_old/raw_pdf_meta_validation.py +0 -223
- endoreg_db/serializers/_old/raw_video_meta_validation.py +0 -179
- endoreg_db/serializers/_old/video.py +0 -71
- endoreg_db/serializers/meta/pdf_file_meta_extraction.py +0 -115
- endoreg_db/serializers/meta/report_meta.py +0 -53
- endoreg_db/serializers/report/__init__.py +0 -9
- endoreg_db/serializers/report/mixins.py +0 -45
- endoreg_db/serializers/report/report.py +0 -105
- endoreg_db/serializers/report/report_list.py +0 -22
- endoreg_db/serializers/report/secure_file_url.py +0 -26
- endoreg_db/serializers/video/video_metadata.py +0 -105
- endoreg_db/services/requirements_object.py +0 -147
- endoreg_db/services/storage_aware_video_processor.py +0 -344
- endoreg_db/urls/files.py +0 -6
- endoreg_db/urls/label_video_segment_validate.py +0 -33
- endoreg_db/urls/label_video_segments.py +0 -46
- endoreg_db/urls/report.py +0 -48
- endoreg_db/urls/video.py +0 -61
- endoreg_db/utils/case_generator/case_generator.py +0 -159
- endoreg_db/utils/case_generator/utils.py +0 -30
- endoreg_db/utils/requirement_operator_logic/model_evaluators.py +0 -368
- endoreg_db/views/label/__init__.py +0 -5
- endoreg_db/views/label/label.py +0 -15
- endoreg_db/views/label_video_segment/__init__.py +0 -16
- endoreg_db/views/label_video_segment/create_lvs_from_annotation.py +0 -44
- endoreg_db/views/label_video_segment/get_lvs_by_name_and_video.py +0 -50
- endoreg_db/views/label_video_segment/label_video_segment.py +0 -77
- endoreg_db/views/label_video_segment/label_video_segment_by_label.py +0 -174
- endoreg_db/views/label_video_segment/label_video_segment_detail.py +0 -73
- endoreg_db/views/label_video_segment/update_lvs_from_annotation.py +0 -46
- endoreg_db/views/label_video_segment/validate.py +0 -226
- endoreg_db/views/media/segments.py +0 -71
- endoreg_db/views/meta/available_files_list.py +0 -146
- endoreg_db/views/meta/report_meta.py +0 -53
- endoreg_db/views/meta/sensitive_meta_detail.py +0 -148
- endoreg_db/views/misc/secure_file_serving_view.py +0 -80
- endoreg_db/views/misc/secure_file_url_view.py +0 -84
- endoreg_db/views/misc/secure_url_validate.py +0 -79
- endoreg_db/views/patient_examination/DEPRECATED_video_backup.py +0 -164
- endoreg_db/views/patient_finding_location/__init__.py +0 -5
- endoreg_db/views/patient_finding_location/pfl_create.py +0 -70
- endoreg_db/views/patient_finding_morphology/__init__.py +0 -5
- endoreg_db/views/patient_finding_morphology/pfm_create.py +0 -70
- endoreg_db/views/pdf/__init__.py +0 -8
- endoreg_db/views/report/report_list.py +0 -112
- endoreg_db/views/report/report_with_secure_url.py +0 -28
- endoreg_db/views/report/start_examination.py +0 -7
- endoreg_db/views/video/segmentation.py +0 -274
- endoreg_db/views/video/task_status.py +0 -49
- endoreg_db/views/video/timeline.py +0 -46
- endoreg_db/views/video/video_analyze.py +0 -52
- endoreg_db/views.py +0 -0
- /endoreg_db/data/requirement/{colonoscopy_baseline_austria.yaml → old/colonoscopy_baseline_austria.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_cardiovascular.yaml → old/disease_cardiovascular.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_classification_choice_cardiovascular.yaml → old/disease_classification_choice_cardiovascular.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_hepatology.yaml → old/disease_hepatology.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_misc.yaml → old/disease_misc.yaml} +0 -0
- /endoreg_db/data/requirement/{disease_renal.yaml → old/disease_renal.yaml} +0 -0
- /endoreg_db/data/requirement/{endoscopy_bleeding_risk.yaml → old/endoscopy_bleeding_risk.yaml} +0 -0
- /endoreg_db/data/requirement/{event_cardiology.yaml → old/event_cardiology.yaml} +0 -0
- /endoreg_db/data/requirement/{event_requirements.yaml → old/event_requirements.yaml} +0 -0
- /endoreg_db/data/requirement/{finding_colon_polyp.yaml → old/finding_colon_polyp.yaml} +0 -0
- /endoreg_db/{migrations/__init__.py → data/requirement/old/gender.yaml} +0 -0
- /endoreg_db/data/requirement/{lab_value.yaml → old/lab_value.yaml} +0 -0
- /endoreg_db/data/requirement/{medication.yaml → old/medication.yaml} +0 -0
- /endoreg_db/data/requirement_operator/{age.yaml → _old/age.yaml} +0 -0
- /endoreg_db/data/requirement_operator/{lab_operators.yaml → _old/lab_operators.yaml} +0 -0
- /endoreg_db/data/requirement_operator/{model_operators.yaml → _old/model_operators.yaml} +0 -0
- /endoreg_db/{models/media/video/refactor_plan.md → import_files/pseudonymization/__init__.py} +0 -0
- /endoreg_db/{models/media/video/video_file_frames.py → import_files/pseudonymization/pseudonymize.py} +0 -0
- /endoreg_db/models/{metadata/frame_ocr_result.py → report/__init__.py} +0 -0
- /endoreg_db/{urls/sensitive_meta.py → models/report/images.py} +0 -0
- /endoreg_db/utils/requirement_operator_logic/{lab_value_operators.py → _old/lab_value_operators.py} +0 -0
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.9.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,95 +1,111 @@
|
|
|
1
|
-
|
|
1
|
+
import logging
|
|
2
|
+
|
|
2
3
|
# Removed hash utils, datetime, random, os, timezone, sha256 imports
|
|
3
4
|
# Removed icecream import (was used in old save logic)
|
|
4
|
-
from typing import TYPE_CHECKING, Dict,
|
|
5
|
-
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Dict, Self, Type, cast
|
|
6
|
+
|
|
7
|
+
from django.db import models
|
|
8
|
+
|
|
9
|
+
from ..administration.person.patient import PatientExternalID
|
|
10
|
+
|
|
11
|
+
# Import models needed for type hints and FKs
|
|
12
|
+
from ..state import SensitiveMetaState # Needed for post-save state check
|
|
6
13
|
|
|
7
14
|
# Import logic functions
|
|
8
15
|
from . import sensitive_meta_logic as logic
|
|
9
|
-
# Import models needed for type hints and FKs
|
|
10
|
-
from ..state import SensitiveMetaState # Needed for post-save state check
|
|
11
16
|
|
|
12
17
|
if TYPE_CHECKING:
|
|
13
18
|
from ..administration import (
|
|
14
19
|
Center,
|
|
15
20
|
Examiner,
|
|
16
|
-
Patient,
|
|
17
|
-
FirstName, # Keep for type hinting if needed
|
|
18
|
-
LastName # Keep for type hinting if needed
|
|
21
|
+
Patient, # Keep for type hinting if needed
|
|
19
22
|
)
|
|
20
|
-
from ..other import Gender
|
|
21
23
|
from ..medical import PatientExamination
|
|
24
|
+
from ..other import Gender
|
|
22
25
|
# from ..state import SensitiveMetaState # Already imported above
|
|
23
26
|
|
|
24
|
-
logger = logging.getLogger(__name__)
|
|
27
|
+
logger = logging.getLogger(__name__) # Add logger instance
|
|
25
28
|
|
|
26
29
|
# SECRET_SALT moved to logic
|
|
27
30
|
|
|
31
|
+
|
|
28
32
|
class SensitiveMeta(models.Model):
|
|
29
33
|
"""
|
|
30
34
|
Stores potentially sensitive information extracted from media.
|
|
31
35
|
Logic for creation, hashing, pseudo-anonymization, and saving is in sensitive_meta_logic.py.
|
|
32
36
|
"""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# --- Examination and Patient Info ---
|
|
33
41
|
examination_date = models.DateField(blank=True, null=True)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
examination_time = models.TimeField(blank=True, null=True)
|
|
43
|
+
casenumber = models.CharField(max_length=255, blank=True, null=True)
|
|
44
|
+
file_path = models.CharField(max_length=1024, blank=True, null=True)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# --- Core FKs ---
|
|
48
|
+
pseudo_patient = models.ForeignKey("Patient", on_delete=models.CASCADE, blank=True, null=True, help_text="FK to the pseudo-anonymized Patient record.")
|
|
49
|
+
pseudo_examination = models.ForeignKey(
|
|
50
|
+
"PatientExamination", on_delete=models.CASCADE, blank=True, null=True, help_text="FK to the pseudo-anonymized PatientExamination record."
|
|
51
|
+
)
|
|
52
|
+
patient_gender = models.ForeignKey("Gender", on_delete=models.CASCADE, blank=True, null=True)
|
|
53
|
+
examiners = models.ManyToManyField("Examiner", blank=True, help_text="Pseudo-anonymized examiner(s)")
|
|
54
|
+
center = models.ForeignKey("Center", on_delete=models.CASCADE, blank=True, null=True)
|
|
55
|
+
|
|
56
|
+
# --- Names and DOB ---
|
|
41
57
|
patient_first_name = models.CharField(max_length=255, blank=True, null=True)
|
|
42
58
|
patient_last_name = models.CharField(max_length=255, blank=True, null=True)
|
|
43
|
-
patient_dob = models.DateTimeField(
|
|
44
|
-
|
|
45
|
-
null=True,
|
|
46
|
-
help_text="Date of birth (can be auto-generated if missing)."
|
|
47
|
-
)
|
|
48
|
-
pseudo_examination = models.ForeignKey(
|
|
49
|
-
"PatientExamination",
|
|
50
|
-
on_delete=models.CASCADE,
|
|
51
|
-
blank=True,
|
|
52
|
-
null=True,
|
|
53
|
-
help_text="FK to the pseudo-anonymized PatientExamination record."
|
|
54
|
-
) # type: ignore
|
|
55
|
-
patient_gender = models.ForeignKey(
|
|
56
|
-
"Gender",
|
|
57
|
-
on_delete=models.CASCADE,
|
|
58
|
-
blank=True,
|
|
59
|
-
null=True,
|
|
60
|
-
) # type: ignore
|
|
61
|
-
examiners = models.ManyToManyField(
|
|
62
|
-
"Examiner",
|
|
63
|
-
blank=True,
|
|
64
|
-
help_text="Pseudo-anonymized examiner(s) associated with the examination."
|
|
65
|
-
) # type: ignore
|
|
66
|
-
center = models.ForeignKey(
|
|
67
|
-
"Center",
|
|
68
|
-
on_delete=models.CASCADE,
|
|
69
|
-
blank=True, # Should ideally be False if always required before save
|
|
70
|
-
null=True, # Should ideally be False
|
|
71
|
-
) # type: ignore
|
|
72
|
-
|
|
73
|
-
# Raw examiner names stored temporarily until pseudo-examiner is created/linked
|
|
59
|
+
patient_dob = models.DateTimeField(blank=True, null=True, help_text="Date of birth (can be auto-generated).")
|
|
60
|
+
|
|
74
61
|
examiner_first_name = models.CharField(max_length=255, blank=True, null=True, editable=False)
|
|
75
62
|
examiner_last_name = models.CharField(max_length=255, blank=True, null=True, editable=False)
|
|
76
63
|
|
|
77
|
-
# Hashes
|
|
78
|
-
|
|
79
|
-
|
|
64
|
+
# --- Hashes ---
|
|
65
|
+
patient_hash = models.CharField(max_length=64, blank=True, null=True, editable=False, db_index=True)
|
|
66
|
+
examination_hash = models.CharField(max_length=64, blank=True, null=True, editable=False, db_index=True)
|
|
80
67
|
|
|
68
|
+
# --- Endoscope Info ---
|
|
81
69
|
endoscope_type = models.CharField(max_length=255, blank=True, null=True)
|
|
82
70
|
endoscope_sn = models.CharField(max_length=255, blank=True, null=True)
|
|
83
71
|
|
|
84
|
-
#
|
|
72
|
+
# --- External patient ID ---
|
|
73
|
+
external_id = models.ForeignKey("PatientExternalID", on_delete=models.CASCADE, blank=True, null=True)
|
|
85
74
|
|
|
86
75
|
if TYPE_CHECKING:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
patient_gender: "Gender"
|
|
90
|
-
pseudo_examination: "PatientExamination"
|
|
91
|
-
state: "SensitiveMetaState"
|
|
92
|
-
center: "Center"
|
|
76
|
+
pseudo_patient: models.ForeignKey["Patient|None"]
|
|
77
|
+
|
|
78
|
+
patient_gender: models.ForeignKey["Gender|None"]
|
|
79
|
+
pseudo_examination: models.ForeignKey["PatientExamination|None"]
|
|
80
|
+
state: models.ForeignKey["SensitiveMetaState|None"] # Assuming related_name='state' is defined on SensitiveMetaState.origin
|
|
81
|
+
center: models.ForeignKey["Center|None"]
|
|
82
|
+
|
|
83
|
+
examiners = cast(models.manager.RelatedManager["Examiner"], examiners)
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def external_id_origin(self) -> str | None:
|
|
87
|
+
"""Returns the origin system from the linked external ID, if available."""
|
|
88
|
+
if self.external_id:
|
|
89
|
+
return self.external_id.origin
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
# --- Text Fields ---
|
|
93
|
+
text = models.TextField(blank=True, null=True)
|
|
94
|
+
anonymized_text = models.TextField(blank=True, null=True)
|
|
95
|
+
|
|
96
|
+
# --- Anonymization helper method ---
|
|
97
|
+
create_anonymized_record = logic._create_anonymized_record
|
|
98
|
+
|
|
99
|
+
# --- State ---
|
|
100
|
+
@property
|
|
101
|
+
def state_verified(self) -> bool | None:
|
|
102
|
+
"""
|
|
103
|
+
Convenience alias to check if the related state is verified.
|
|
104
|
+
Returns None if state is not set.
|
|
105
|
+
"""
|
|
106
|
+
if hasattr(self, "state") and self.state is not None:
|
|
107
|
+
return self.state.is_verified
|
|
108
|
+
return None
|
|
93
109
|
|
|
94
110
|
@staticmethod
|
|
95
111
|
def _generate_random_dob():
|
|
@@ -113,10 +129,10 @@ class SensitiveMeta(models.Model):
|
|
|
113
129
|
"""Returns the linked pseudo examiner, if one exists."""
|
|
114
130
|
if self.pk:
|
|
115
131
|
return self.examiners.first()
|
|
116
|
-
return None
|
|
132
|
+
return None # Cannot determine before saving and linking
|
|
117
133
|
|
|
118
134
|
# --- Update method delegates to logic ---
|
|
119
|
-
def update_from_dict(self, data: Dict[str, Any])
|
|
135
|
+
def update_from_dict(self, data: Dict[str, Any]):
|
|
120
136
|
"""Updates the instance from a dictionary using external logic."""
|
|
121
137
|
# Delegate to logic function
|
|
122
138
|
return logic.update_sensitive_meta_from_dict(self, data)
|
|
@@ -126,7 +142,7 @@ class SensitiveMeta(models.Model):
|
|
|
126
142
|
# Keep this method for basic representation, ensure fields are accessed safely
|
|
127
143
|
center_name = self.center.name if self.center else "None"
|
|
128
144
|
gender_str = str(self.patient_gender) if self.patient_gender else "None"
|
|
129
|
-
dob_str = str(self.patient_dob.date()) if self.patient_dob else "None"
|
|
145
|
+
dob_str = str(self.patient_dob.date()) if self.patient_dob else "None" # Show only date part
|
|
130
146
|
exam_date_str = str(self.examination_date) if self.examination_date else "None"
|
|
131
147
|
|
|
132
148
|
examiners_str = "[Not saved yet]"
|
|
@@ -139,21 +155,27 @@ class SensitiveMeta(models.Model):
|
|
|
139
155
|
|
|
140
156
|
state_verified = "Unknown"
|
|
141
157
|
if self.pk:
|
|
142
|
-
|
|
143
|
-
|
|
158
|
+
# Access state verification through the related state object
|
|
159
|
+
state_verified = str(self.is_verified)
|
|
144
160
|
else:
|
|
145
161
|
state_verified = "[Not saved yet]"
|
|
146
162
|
|
|
147
|
-
|
|
148
163
|
return (
|
|
149
164
|
f"SensitiveMeta(pk={self.pk}): "
|
|
150
165
|
f"Patient={self.patient_last_name}, {self.patient_first_name} (*{dob_str}, {gender_str}), "
|
|
151
166
|
f"ExamDate={exam_date_str}, Center={center_name}, "
|
|
152
167
|
f"Examiners={examiners_str}, StateVerified={state_verified}, "
|
|
153
|
-
f"PatientHash={str(self.patient_hash)[-8:] if self.patient_hash else 'None'}, "
|
|
154
|
-
f"ExamHash={str(self.examination_hash)[-8:] if self.examination_hash else 'None'}"
|
|
168
|
+
f"PatientHash={str(self.patient_hash)[-8:] if self.patient_hash else 'None'}, " # Show last 8 chars
|
|
169
|
+
f"ExamHash={str(self.examination_hash)[-8:] if self.examination_hash else 'None'}" # Show last 8 chars
|
|
155
170
|
)
|
|
156
171
|
|
|
172
|
+
@property
|
|
173
|
+
def state_safe(self) -> "SensitiveMetaState":
|
|
174
|
+
state = self.state
|
|
175
|
+
if not state:
|
|
176
|
+
raise SensitiveMetaState.DoesNotExist("SensitiveMetaState does not exist for this SensitiveMeta instance.")
|
|
177
|
+
return state
|
|
178
|
+
|
|
157
179
|
@property
|
|
158
180
|
def is_verified(self):
|
|
159
181
|
"""
|
|
@@ -163,7 +185,7 @@ class SensitiveMeta(models.Model):
|
|
|
163
185
|
try:
|
|
164
186
|
# Access the related state object directly via the 'state' attribute
|
|
165
187
|
# This assumes the related_name on SensitiveMetaState.origin is 'state'
|
|
166
|
-
return self.
|
|
188
|
+
return self.state_safe.is_verified
|
|
167
189
|
except SensitiveMetaState.DoesNotExist:
|
|
168
190
|
# If the state object doesn't exist, it's not verified
|
|
169
191
|
return False
|
|
@@ -177,11 +199,9 @@ class SensitiveMeta(models.Model):
|
|
|
177
199
|
Does not save the SensitiveMeta instance itself.
|
|
178
200
|
"""
|
|
179
201
|
try:
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if self.state:
|
|
184
|
-
return self.state
|
|
202
|
+
state = self.state_safe
|
|
203
|
+
return state
|
|
204
|
+
|
|
185
205
|
except SensitiveMetaState.DoesNotExist:
|
|
186
206
|
# If it doesn't exist, create it
|
|
187
207
|
logger.info("Creating new SensitiveMetaState for SensitiveMeta %s", self.pk)
|
|
@@ -205,9 +225,6 @@ class SensitiveMeta(models.Model):
|
|
|
205
225
|
# Cannot create state if the main instance has no PK
|
|
206
226
|
raise ValueError("Cannot get or create state for an unsaved SensitiveMeta instance.")
|
|
207
227
|
|
|
208
|
-
# If self.state existed initially, return it
|
|
209
|
-
return self.state
|
|
210
|
-
|
|
211
228
|
def __repr__(self):
|
|
212
229
|
return self.__str__()
|
|
213
230
|
|
|
@@ -229,22 +246,22 @@ class SensitiveMeta(models.Model):
|
|
|
229
246
|
def save(self, *args, **kwargs):
|
|
230
247
|
"""
|
|
231
248
|
Saves the SensitiveMeta instance, ensuring data integrity, hash calculation, pseudo-entity linking, and related state management using external logic.
|
|
232
|
-
|
|
249
|
+
|
|
233
250
|
This method performs pre-save operations via external logic, persists the instance, ensures the related SensitiveMetaState exists, and links the appropriate examiner to the instance.
|
|
234
251
|
"""
|
|
235
252
|
# 1. Call the main logic function to perform pre-save checks, data generation,
|
|
236
253
|
# and creation/linking of pseudo patient/examination FKs.
|
|
237
254
|
# This function modifies the instance fields (hashes, FKs, dates).
|
|
238
255
|
# It returns the examiner instance to be linked *after* saving.
|
|
239
|
-
examiner_to_link = logic.perform_save_logic(self)
|
|
256
|
+
examiner_to_link = logic.perform_save_logic(self) # Pass only self
|
|
240
257
|
|
|
241
258
|
# 2. Call the original Django save method to save the instance itself
|
|
242
259
|
# (including updated FKs, hashes, dates).
|
|
243
|
-
super().save(*args, **kwargs)
|
|
260
|
+
super().save(*args, **kwargs) # Pass original args/kwargs
|
|
244
261
|
|
|
245
262
|
# 3. Ensure SensitiveMetaState exists *after* saving the main instance
|
|
246
263
|
# Use related name 'state' if defined, otherwise access via manager.
|
|
247
|
-
if self.pk:
|
|
264
|
+
if self.pk: # Ensure we have a PK
|
|
248
265
|
try:
|
|
249
266
|
# Check if the related state object already exists using the related manager
|
|
250
267
|
_ = self.state
|
|
@@ -252,13 +269,13 @@ class SensitiveMeta(models.Model):
|
|
|
252
269
|
# If not, create a new one, linking it to the saved instance
|
|
253
270
|
SensitiveMetaState.objects.create(origin=self)
|
|
254
271
|
except AttributeError:
|
|
255
|
-
|
|
256
|
-
|
|
272
|
+
# Fallback check if 'state' related_name is missing
|
|
273
|
+
if not SensitiveMetaState.objects.filter(origin=self).exists():
|
|
257
274
|
SensitiveMetaState.objects.create(origin=self)
|
|
258
275
|
|
|
259
276
|
# 4. Handle ManyToMany linking (examiners) *after* the instance has a PK.
|
|
260
277
|
if examiner_to_link and self.pk and not self.examiners.filter(pk=examiner_to_link.pk).exists():
|
|
261
|
-
self.examiners.add(examiner_to_link)
|
|
278
|
+
self.examiners.add(examiner_to_link)
|
|
262
279
|
# Adding to M2M handles its own DB interaction, no second super().save() needed.
|
|
263
280
|
|
|
264
281
|
def mark_dob_verified(self):
|
|
@@ -271,7 +288,7 @@ class SensitiveMeta(models.Model):
|
|
|
271
288
|
def mark_names_verified(self):
|
|
272
289
|
"""
|
|
273
290
|
Mark the patient's names as verified in the associated verification state.
|
|
274
|
-
|
|
291
|
+
|
|
275
292
|
This method ensures the related SensitiveMetaState exists and updates its status to indicate that the patient's names have been verified.
|
|
276
293
|
"""
|
|
277
294
|
state = self.get_or_create_state()
|
|
@@ -282,7 +299,10 @@ class SensitiveMeta(models.Model):
|
|
|
282
299
|
# Delegate to logic
|
|
283
300
|
"""
|
|
284
301
|
Update the name database with the provided first and last names using external logic.
|
|
285
|
-
|
|
302
|
+
|
|
286
303
|
This method delegates the update operation to the external logic module responsible for managing name data.
|
|
287
304
|
"""
|
|
288
|
-
logic.update_name_db(first_name, last_name)
|
|
305
|
+
logic.update_name_db(first_name, last_name)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
|