endoreg-db 0.8.8.9__py3-none-any.whl → 0.8.9.10__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/admin.py +10 -5
- endoreg_db/apps.py +4 -7
- endoreg_db/authz/auth.py +1 -0
- endoreg_db/authz/backends.py +1 -1
- endoreg_db/authz/management/commands/list_routes.py +2 -0
- endoreg_db/authz/middleware.py +8 -7
- endoreg_db/authz/permissions.py +21 -10
- endoreg_db/authz/policy.py +14 -19
- endoreg_db/authz/views_auth.py +14 -10
- endoreg_db/codemods/rename_datetime_fields.py +8 -1
- endoreg_db/exceptions.py +5 -2
- endoreg_db/forms/__init__.py +0 -1
- endoreg_db/forms/examination_form.py +4 -3
- endoreg_db/forms/patient_finding_intervention_form.py +30 -8
- endoreg_db/forms/patient_form.py +9 -13
- endoreg_db/forms/questionnaires/__init__.py +1 -1
- endoreg_db/forms/settings/__init__.py +4 -1
- endoreg_db/forms/unit.py +2 -1
- endoreg_db/helpers/count_db.py +17 -14
- endoreg_db/helpers/default_objects.py +2 -1
- endoreg_db/helpers/download_segmentation_model.py +4 -3
- endoreg_db/helpers/interact.py +0 -5
- endoreg_db/helpers/test_video_helper.py +33 -25
- endoreg_db/import_files/__init__.py +1 -1
- endoreg_db/import_files/context/__init__.py +1 -1
- endoreg_db/import_files/context/default_sensitive_meta.py +11 -9
- endoreg_db/import_files/context/ensure_center.py +4 -4
- endoreg_db/import_files/context/file_lock.py +3 -3
- endoreg_db/import_files/context/import_context.py +11 -12
- endoreg_db/import_files/context/validate_directories.py +1 -0
- endoreg_db/import_files/file_storage/create_report_file.py +57 -34
- endoreg_db/import_files/file_storage/create_video_file.py +64 -35
- endoreg_db/import_files/file_storage/sensitive_meta_storage.py +5 -2
- endoreg_db/import_files/file_storage/state_management.py +146 -83
- endoreg_db/import_files/file_storage/storage.py +5 -1
- endoreg_db/import_files/processing/report_processing/report_anonymization.py +24 -19
- endoreg_db/import_files/processing/sensitive_meta_adapter.py +3 -3
- endoreg_db/import_files/processing/video_processing/video_anonymization.py +18 -18
- endoreg_db/import_files/pseudonymization/k_anonymity.py +8 -9
- endoreg_db/import_files/pseudonymization/k_pseudonymity.py +16 -5
- endoreg_db/import_files/report_import_service.py +36 -30
- endoreg_db/import_files/video_import_service.py +27 -23
- endoreg_db/logger_conf.py +56 -40
- endoreg_db/management/__init__.py +1 -1
- endoreg_db/management/commands/__init__.py +1 -1
- endoreg_db/management/commands/check_auth.py +45 -38
- endoreg_db/management/commands/create_model_meta_from_huggingface.py +53 -2
- endoreg_db/management/commands/create_multilabel_model_meta.py +54 -19
- endoreg_db/management/commands/fix_missing_patient_data.py +105 -71
- endoreg_db/management/commands/fix_video_paths.py +75 -54
- endoreg_db/management/commands/import_report.py +1 -3
- endoreg_db/management/commands/list_routes.py +2 -0
- endoreg_db/management/commands/load_ai_model_data.py +8 -2
- endoreg_db/management/commands/load_ai_model_label_data.py +0 -1
- endoreg_db/management/commands/load_center_data.py +3 -3
- endoreg_db/management/commands/load_distribution_data.py +35 -38
- endoreg_db/management/commands/load_endoscope_data.py +0 -3
- endoreg_db/management/commands/load_examination_data.py +20 -4
- endoreg_db/management/commands/load_finding_data.py +18 -3
- endoreg_db/management/commands/load_gender_data.py +17 -24
- endoreg_db/management/commands/load_green_endoscopy_wuerzburg_data.py +95 -85
- endoreg_db/management/commands/load_information_source.py +0 -3
- endoreg_db/management/commands/load_lab_value_data.py +14 -3
- endoreg_db/management/commands/load_legacy_data.py +303 -0
- endoreg_db/management/commands/load_name_data.py +1 -2
- endoreg_db/management/commands/load_pdf_type_data.py +4 -8
- endoreg_db/management/commands/load_profession_data.py +0 -1
- endoreg_db/management/commands/load_report_reader_flag_data.py +0 -4
- endoreg_db/management/commands/load_requirement_data.py +6 -2
- endoreg_db/management/commands/load_unit_data.py +0 -4
- endoreg_db/management/commands/load_user_groups.py +5 -7
- endoreg_db/management/commands/model_input.py +169 -0
- endoreg_db/management/commands/register_ai_model.py +22 -16
- endoreg_db/management/commands/setup_endoreg_db.py +110 -32
- endoreg_db/management/commands/storage_management.py +14 -8
- endoreg_db/management/commands/summarize_db_content.py +154 -63
- endoreg_db/management/commands/train_image_multilabel_model.py +144 -0
- endoreg_db/management/commands/validate_video_files.py +82 -50
- endoreg_db/management/commands/video_validation.py +4 -6
- endoreg_db/migrations/0001_initial.py +112 -63
- endoreg_db/migrations/__init__.py +0 -0
- endoreg_db/models/__init__.py +8 -0
- endoreg_db/models/administration/ai/active_model.py +5 -5
- endoreg_db/models/administration/ai/ai_model.py +41 -18
- endoreg_db/models/administration/ai/model_type.py +1 -0
- endoreg_db/models/administration/case/case.py +22 -22
- endoreg_db/models/administration/center/__init__.py +5 -5
- endoreg_db/models/administration/center/center.py +6 -2
- endoreg_db/models/administration/center/center_resource.py +18 -4
- endoreg_db/models/administration/center/center_shift.py +3 -1
- endoreg_db/models/administration/center/center_waste.py +6 -2
- endoreg_db/models/administration/person/__init__.py +1 -1
- endoreg_db/models/administration/person/employee/__init__.py +1 -1
- endoreg_db/models/administration/person/employee/employee_type.py +3 -1
- endoreg_db/models/administration/person/examiner/__init__.py +1 -1
- endoreg_db/models/administration/person/examiner/examiner.py +10 -2
- endoreg_db/models/administration/person/names/first_name.py +6 -4
- endoreg_db/models/administration/person/names/last_name.py +4 -3
- endoreg_db/models/administration/person/patient/__init__.py +1 -1
- endoreg_db/models/administration/person/patient/patient.py +0 -1
- endoreg_db/models/administration/person/patient/patient_external_id.py +0 -1
- endoreg_db/models/administration/person/person.py +1 -1
- endoreg_db/models/administration/product/__init__.py +7 -6
- endoreg_db/models/administration/product/product.py +6 -2
- endoreg_db/models/administration/product/product_group.py +9 -7
- endoreg_db/models/administration/product/product_material.py +9 -2
- endoreg_db/models/administration/product/reference_product.py +64 -15
- endoreg_db/models/administration/qualification/qualification.py +3 -1
- endoreg_db/models/administration/shift/shift.py +3 -1
- endoreg_db/models/administration/shift/shift_type.py +12 -4
- endoreg_db/models/aidataset/__init__.py +5 -0
- endoreg_db/models/aidataset/aidataset.py +193 -0
- endoreg_db/models/label/__init__.py +1 -1
- endoreg_db/models/label/label.py +10 -2
- endoreg_db/models/label/label_set.py +3 -1
- endoreg_db/models/label/label_video_segment/_create_from_video.py +6 -2
- endoreg_db/models/label/label_video_segment/label_video_segment.py +148 -44
- endoreg_db/models/media/__init__.py +12 -5
- endoreg_db/models/media/frame/__init__.py +1 -1
- endoreg_db/models/media/frame/frame.py +34 -8
- endoreg_db/models/media/pdf/__init__.py +2 -1
- endoreg_db/models/media/pdf/raw_pdf.py +11 -4
- endoreg_db/models/media/pdf/report_file.py +6 -2
- endoreg_db/models/media/pdf/report_reader/__init__.py +3 -3
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +15 -5
- endoreg_db/models/media/video/create_from_file.py +20 -41
- endoreg_db/models/media/video/pipe_1.py +75 -30
- endoreg_db/models/media/video/pipe_2.py +37 -12
- endoreg_db/models/media/video/video_file.py +36 -24
- endoreg_db/models/media/video/video_file_ai.py +235 -70
- endoreg_db/models/media/video/video_file_anonymize.py +240 -65
- endoreg_db/models/media/video/video_file_frames/_bulk_create_frames.py +6 -1
- endoreg_db/models/media/video/video_file_frames/_create_frame_object.py +3 -1
- endoreg_db/models/media/video/video_file_frames/_delete_frames.py +30 -9
- endoreg_db/models/media/video/video_file_frames/_extract_frames.py +95 -29
- endoreg_db/models/media/video/video_file_frames/_get_frame.py +13 -3
- endoreg_db/models/media/video/video_file_frames/_get_frame_path.py +4 -1
- endoreg_db/models/media/video/video_file_frames/_get_frame_paths.py +15 -3
- endoreg_db/models/media/video/video_file_frames/_get_frame_range.py +15 -3
- endoreg_db/models/media/video/video_file_frames/_get_frames.py +7 -2
- endoreg_db/models/media/video/video_file_frames/_initialize_frames.py +109 -23
- endoreg_db/models/media/video/video_file_frames/_manage_frame_range.py +111 -27
- endoreg_db/models/media/video/video_file_frames/_mark_frames_extracted_status.py +46 -13
- endoreg_db/models/media/video/video_file_io.py +85 -33
- endoreg_db/models/media/video/video_file_meta/__init__.py +6 -6
- endoreg_db/models/media/video/video_file_meta/get_crop_template.py +17 -4
- endoreg_db/models/media/video/video_file_meta/get_endo_roi.py +28 -7
- endoreg_db/models/media/video/video_file_meta/get_fps.py +46 -13
- endoreg_db/models/media/video/video_file_meta/initialize_video_specs.py +81 -20
- endoreg_db/models/media/video/video_file_meta/text_meta.py +61 -20
- endoreg_db/models/media/video/video_file_meta/video_meta.py +40 -12
- endoreg_db/models/media/video/video_file_segments.py +118 -27
- endoreg_db/models/media/video/video_metadata.py +25 -6
- endoreg_db/models/media/video/video_processing.py +54 -15
- endoreg_db/models/medical/__init__.py +3 -13
- endoreg_db/models/medical/contraindication/__init__.py +3 -1
- endoreg_db/models/medical/disease.py +18 -6
- endoreg_db/models/medical/event.py +6 -2
- endoreg_db/models/medical/examination/__init__.py +5 -1
- endoreg_db/models/medical/examination/examination.py +22 -6
- endoreg_db/models/medical/examination/examination_indication.py +23 -7
- endoreg_db/models/medical/examination/examination_time.py +6 -2
- endoreg_db/models/medical/finding/__init__.py +3 -1
- endoreg_db/models/medical/finding/finding.py +37 -12
- endoreg_db/models/medical/finding/finding_classification.py +27 -8
- endoreg_db/models/medical/finding/finding_intervention.py +19 -6
- endoreg_db/models/medical/finding/finding_type.py +3 -1
- endoreg_db/models/medical/hardware/__init__.py +1 -1
- endoreg_db/models/medical/hardware/endoscope.py +14 -2
- endoreg_db/models/medical/laboratory/__init__.py +1 -1
- endoreg_db/models/medical/laboratory/lab_value.py +139 -39
- endoreg_db/models/medical/medication/__init__.py +7 -3
- endoreg_db/models/medical/medication/medication.py +3 -1
- endoreg_db/models/medical/medication/medication_indication.py +3 -1
- endoreg_db/models/medical/medication/medication_indication_type.py +11 -3
- endoreg_db/models/medical/medication/medication_intake_time.py +3 -1
- endoreg_db/models/medical/medication/medication_schedule.py +3 -1
- endoreg_db/models/medical/patient/__init__.py +2 -10
- endoreg_db/models/medical/patient/medication_examples.py +3 -14
- endoreg_db/models/medical/patient/patient_disease.py +17 -5
- endoreg_db/models/medical/patient/patient_event.py +12 -4
- endoreg_db/models/medical/patient/patient_examination.py +52 -15
- endoreg_db/models/medical/patient/patient_examination_indication.py +15 -4
- endoreg_db/models/medical/patient/patient_finding.py +105 -29
- endoreg_db/models/medical/patient/patient_finding_classification.py +41 -12
- endoreg_db/models/medical/patient/patient_finding_intervention.py +11 -3
- endoreg_db/models/medical/patient/patient_lab_sample.py +6 -2
- endoreg_db/models/medical/patient/patient_lab_value.py +42 -10
- endoreg_db/models/medical/patient/patient_medication.py +25 -7
- endoreg_db/models/medical/patient/patient_medication_schedule.py +34 -10
- endoreg_db/models/metadata/model_meta.py +40 -12
- endoreg_db/models/metadata/model_meta_logic.py +51 -16
- endoreg_db/models/metadata/sensitive_meta.py +65 -28
- endoreg_db/models/metadata/sensitive_meta_logic.py +28 -26
- endoreg_db/models/metadata/video_meta.py +146 -39
- endoreg_db/models/metadata/video_prediction_logic.py +70 -21
- endoreg_db/models/metadata/video_prediction_meta.py +80 -27
- endoreg_db/models/operation_log.py +63 -0
- endoreg_db/models/other/__init__.py +10 -10
- endoreg_db/models/other/distribution/__init__.py +9 -7
- endoreg_db/models/other/distribution/base_value_distribution.py +3 -1
- endoreg_db/models/other/distribution/date_value_distribution.py +19 -5
- endoreg_db/models/other/distribution/multiple_categorical_value_distribution.py +3 -1
- endoreg_db/models/other/distribution/numeric_value_distribution.py +34 -9
- endoreg_db/models/other/emission/__init__.py +1 -1
- endoreg_db/models/other/emission/emission_factor.py +9 -3
- endoreg_db/models/other/information_source.py +15 -5
- endoreg_db/models/other/material.py +3 -1
- endoreg_db/models/other/transport_route.py +3 -1
- endoreg_db/models/other/unit.py +6 -2
- endoreg_db/models/report/report.py +0 -1
- endoreg_db/models/requirement/requirement.py +84 -27
- endoreg_db/models/requirement/requirement_error.py +5 -6
- endoreg_db/models/requirement/requirement_evaluation/__init__.py +1 -1
- endoreg_db/models/requirement/requirement_evaluation/evaluate_with_dependencies.py +8 -8
- endoreg_db/models/requirement/requirement_evaluation/get_values.py +3 -3
- endoreg_db/models/requirement/requirement_evaluation/requirement_type_parser.py +24 -8
- endoreg_db/models/requirement/requirement_operator.py +28 -8
- endoreg_db/models/requirement/requirement_set.py +34 -11
- endoreg_db/models/state/__init__.py +1 -0
- endoreg_db/models/state/audit_ledger.py +9 -2
- endoreg_db/models/{media → state}/processing_history/__init__.py +1 -3
- endoreg_db/models/state/processing_history/processing_history.py +136 -0
- endoreg_db/models/state/raw_pdf.py +0 -1
- endoreg_db/models/state/video.py +2 -3
- endoreg_db/models/utils.py +4 -2
- endoreg_db/queries/__init__.py +2 -6
- endoreg_db/queries/annotations/__init__.py +1 -3
- endoreg_db/queries/annotations/legacy.py +37 -26
- endoreg_db/root_urls.py +3 -4
- endoreg_db/schemas/examination_evaluation.py +3 -0
- endoreg_db/serializers/Frames_NICE_and_PARIS_classifications.py +249 -163
- endoreg_db/serializers/__init__.py +2 -8
- endoreg_db/serializers/administration/__init__.py +1 -2
- endoreg_db/serializers/administration/ai/__init__.py +0 -1
- endoreg_db/serializers/administration/ai/active_model.py +3 -1
- endoreg_db/serializers/administration/ai/ai_model.py +5 -3
- endoreg_db/serializers/administration/ai/model_type.py +3 -1
- endoreg_db/serializers/administration/center.py +7 -2
- endoreg_db/serializers/administration/gender.py +4 -2
- endoreg_db/serializers/anonymization.py +13 -13
- endoreg_db/serializers/evaluation/examination_evaluation.py +0 -1
- endoreg_db/serializers/examination/__init__.py +1 -1
- endoreg_db/serializers/examination/base.py +12 -13
- endoreg_db/serializers/examination/dropdown.py +6 -7
- endoreg_db/serializers/examination_serializer.py +3 -6
- endoreg_db/serializers/finding/__init__.py +1 -1
- endoreg_db/serializers/finding/finding.py +14 -7
- endoreg_db/serializers/finding_classification/__init__.py +3 -3
- endoreg_db/serializers/finding_classification/choice.py +3 -3
- endoreg_db/serializers/finding_classification/classification.py +2 -4
- endoreg_db/serializers/label_video_segment/__init__.py +5 -3
- endoreg_db/serializers/{label → label_video_segment}/image_classification_annotation.py +5 -5
- endoreg_db/serializers/label_video_segment/label/__init__.py +6 -0
- endoreg_db/serializers/{label → label_video_segment/label}/label.py +1 -1
- endoreg_db/serializers/label_video_segment/label_video_segment.py +338 -228
- endoreg_db/serializers/meta/__init__.py +1 -2
- endoreg_db/serializers/meta/sensitive_meta_detail.py +28 -13
- endoreg_db/serializers/meta/sensitive_meta_update.py +51 -46
- endoreg_db/serializers/meta/sensitive_meta_verification.py +19 -16
- endoreg_db/serializers/misc/__init__.py +2 -2
- endoreg_db/serializers/misc/file_overview.py +11 -7
- endoreg_db/serializers/misc/stats.py +10 -8
- endoreg_db/serializers/misc/translatable_field_mix_in.py +6 -6
- endoreg_db/serializers/misc/upload_job.py +32 -29
- endoreg_db/serializers/patient/__init__.py +2 -1
- endoreg_db/serializers/patient/patient.py +32 -15
- endoreg_db/serializers/patient/patient_dropdown.py +11 -3
- endoreg_db/serializers/patient_examination/__init__.py +1 -1
- endoreg_db/serializers/patient_examination/patient_examination.py +67 -40
- endoreg_db/serializers/patient_finding/__init__.py +1 -1
- endoreg_db/serializers/patient_finding/patient_finding.py +2 -1
- endoreg_db/serializers/patient_finding/patient_finding_classification.py +17 -9
- endoreg_db/serializers/patient_finding/patient_finding_detail.py +26 -17
- endoreg_db/serializers/patient_finding/patient_finding_intervention.py +7 -5
- endoreg_db/serializers/patient_finding/patient_finding_list.py +10 -11
- endoreg_db/serializers/patient_finding/patient_finding_write.py +36 -27
- endoreg_db/serializers/pdf/__init__.py +1 -3
- endoreg_db/serializers/requirements/requirement_schema.py +1 -6
- endoreg_db/serializers/sensitive_meta_serializer.py +100 -81
- endoreg_db/serializers/video/__init__.py +2 -2
- endoreg_db/serializers/video/{segmentation.py → video_file.py} +66 -47
- endoreg_db/serializers/video/video_file_brief.py +6 -2
- endoreg_db/serializers/video/video_file_detail.py +36 -23
- endoreg_db/serializers/video/video_file_list.py +4 -2
- endoreg_db/serializers/video/video_processing_history.py +54 -50
- endoreg_db/services/__init__.py +1 -1
- endoreg_db/services/anonymization.py +2 -2
- endoreg_db/services/examination_evaluation.py +40 -17
- endoreg_db/services/model_meta_from_hf.py +76 -0
- endoreg_db/services/polling_coordinator.py +101 -70
- endoreg_db/services/pseudonym_service.py +27 -22
- endoreg_db/services/report_import.py +6 -3
- endoreg_db/services/segment_sync.py +75 -59
- endoreg_db/services/video_import.py +6 -7
- endoreg_db/urls/__init__.py +2 -2
- endoreg_db/urls/ai.py +7 -25
- endoreg_db/urls/anonymization.py +61 -15
- endoreg_db/urls/auth.py +4 -4
- endoreg_db/urls/classification.py +4 -9
- endoreg_db/urls/examination.py +27 -18
- endoreg_db/urls/media.py +27 -34
- endoreg_db/urls/patient.py +11 -7
- endoreg_db/urls/requirements.py +3 -1
- endoreg_db/urls/root_urls.py +2 -3
- endoreg_db/urls/stats.py +24 -16
- endoreg_db/urls/upload.py +3 -11
- endoreg_db/utils/__init__.py +14 -15
- endoreg_db/utils/ai/__init__.py +1 -1
- endoreg_db/utils/ai/data_loader_for_model_input.py +262 -0
- endoreg_db/utils/ai/data_loader_for_model_training.py +262 -0
- endoreg_db/utils/ai/get.py +2 -1
- endoreg_db/utils/ai/inference_dataset.py +14 -15
- endoreg_db/utils/ai/model_training/config.py +117 -0
- endoreg_db/utils/ai/model_training/dataset.py +74 -0
- endoreg_db/utils/ai/model_training/losses.py +68 -0
- endoreg_db/utils/ai/model_training/metrics.py +78 -0
- endoreg_db/utils/ai/model_training/model_backbones.py +155 -0
- endoreg_db/utils/ai/model_training/model_gastronet_resnet.py +118 -0
- endoreg_db/utils/ai/model_training/trainer_gastronet_multilabel.py +771 -0
- endoreg_db/utils/ai/multilabel_classification_net.py +21 -6
- endoreg_db/utils/ai/predict.py +4 -4
- endoreg_db/utils/ai/preprocess.py +19 -11
- endoreg_db/utils/calc_duration_seconds.py +4 -4
- endoreg_db/utils/case_generator/lab_sample_factory.py +3 -4
- endoreg_db/utils/check_video_files.py +74 -47
- endoreg_db/utils/cropping.py +10 -9
- endoreg_db/utils/dataloader.py +11 -3
- endoreg_db/utils/dates.py +3 -4
- endoreg_db/utils/defaults/set_default_center.py +7 -6
- endoreg_db/utils/env.py +6 -2
- endoreg_db/utils/extract_specific_frames.py +24 -9
- endoreg_db/utils/file_operations.py +30 -18
- endoreg_db/utils/fix_video_path_direct.py +57 -41
- endoreg_db/utils/frame_anonymization_utils.py +157 -157
- endoreg_db/utils/hashs.py +3 -18
- endoreg_db/utils/links/requirement_link.py +96 -52
- endoreg_db/utils/ocr.py +30 -25
- endoreg_db/utils/operation_log.py +61 -0
- endoreg_db/utils/parse_and_generate_yaml.py +12 -13
- endoreg_db/utils/paths.py +6 -6
- endoreg_db/utils/permissions.py +40 -24
- endoreg_db/utils/pipelines/process_video_dir.py +50 -26
- endoreg_db/utils/product/sum_emissions.py +5 -3
- endoreg_db/utils/product/sum_weights.py +4 -2
- endoreg_db/utils/pydantic_models/__init__.py +3 -4
- endoreg_db/utils/requirement_operator_logic/_old/lab_value_operators.py +207 -107
- endoreg_db/utils/requirement_operator_logic/_old/model_evaluators.py +252 -65
- endoreg_db/utils/requirement_operator_logic/new_operator_logic.py +27 -10
- endoreg_db/utils/setup_config.py +21 -5
- endoreg_db/utils/storage.py +3 -1
- endoreg_db/utils/translation.py +19 -15
- endoreg_db/utils/uuid.py +1 -0
- endoreg_db/utils/validate_endo_roi.py +12 -4
- endoreg_db/utils/validate_subcategory_dict.py +26 -24
- endoreg_db/utils/validate_video_detailed.py +207 -149
- endoreg_db/utils/video/__init__.py +7 -3
- endoreg_db/utils/video/extract_frames.py +30 -18
- endoreg_db/utils/video/ffmpeg_wrapper.py +217 -52
- endoreg_db/utils/video/names.py +11 -6
- endoreg_db/utils/video/streaming_processor.py +175 -101
- endoreg_db/utils/video/video_splitter.py +30 -19
- endoreg_db/views/Frames_NICE_and_PARIS_classifications_views.py +59 -50
- endoreg_db/views/__init__.py +0 -20
- endoreg_db/views/anonymization/__init__.py +6 -2
- endoreg_db/views/anonymization/media_management.py +2 -6
- endoreg_db/views/anonymization/overview.py +34 -1
- endoreg_db/views/anonymization/validate.py +79 -18
- endoreg_db/views/auth/__init__.py +1 -1
- endoreg_db/views/auth/keycloak.py +16 -14
- endoreg_db/views/examination/__init__.py +12 -15
- endoreg_db/views/examination/examination.py +5 -5
- endoreg_db/views/examination/examination_manifest_cache.py +5 -5
- endoreg_db/views/examination/get_finding_classification_choices.py +8 -5
- endoreg_db/views/examination/get_finding_classifications.py +9 -7
- endoreg_db/views/examination/get_findings.py +8 -10
- endoreg_db/views/examination/get_instruments.py +3 -2
- endoreg_db/views/examination/get_interventions.py +1 -1
- endoreg_db/views/finding/__init__.py +2 -2
- endoreg_db/views/finding/finding.py +58 -54
- endoreg_db/views/finding/get_classifications.py +1 -1
- endoreg_db/views/finding/get_interventions.py +1 -1
- endoreg_db/views/finding_classification/__init__.py +5 -5
- endoreg_db/views/finding_classification/finding_classification.py +5 -6
- endoreg_db/views/finding_classification/get_classification_choices.py +3 -4
- endoreg_db/views/media/__init__.py +13 -13
- endoreg_db/views/media/pdf_media.py +9 -9
- endoreg_db/views/media/sensitive_metadata.py +10 -7
- endoreg_db/views/media/video_media.py +4 -4
- endoreg_db/views/meta/__init__.py +1 -1
- endoreg_db/views/meta/sensitive_meta_list.py +20 -22
- endoreg_db/views/meta/sensitive_meta_verification.py +14 -11
- endoreg_db/views/misc/__init__.py +6 -34
- endoreg_db/views/misc/center.py +2 -1
- endoreg_db/views/misc/csrf.py +2 -1
- endoreg_db/views/misc/gender.py +2 -1
- endoreg_db/views/misc/stats.py +141 -106
- endoreg_db/views/patient/__init__.py +1 -3
- endoreg_db/views/patient/patient.py +141 -99
- endoreg_db/views/patient_examination/__init__.py +5 -5
- endoreg_db/views/patient_examination/patient_examination.py +43 -42
- endoreg_db/views/patient_examination/patient_examination_create.py +10 -15
- endoreg_db/views/patient_examination/patient_examination_detail.py +12 -15
- endoreg_db/views/patient_examination/patient_examination_list.py +21 -17
- endoreg_db/views/patient_examination/video.py +114 -80
- endoreg_db/views/patient_finding/__init__.py +1 -1
- endoreg_db/views/patient_finding/patient_finding.py +17 -10
- endoreg_db/views/patient_finding/patient_finding_optimized.py +127 -95
- endoreg_db/views/patient_finding_classification/__init__.py +1 -1
- endoreg_db/views/patient_finding_classification/pfc_create.py +35 -27
- endoreg_db/views/report/reimport.py +1 -1
- endoreg_db/views/report/report_stream.py +5 -8
- endoreg_db/views/requirement/__init__.py +2 -1
- endoreg_db/views/requirement/evaluate.py +7 -9
- endoreg_db/views/requirement/lookup.py +2 -3
- endoreg_db/views/requirement/lookup_store.py +0 -1
- endoreg_db/views/requirement/requirement_utils.py +2 -4
- endoreg_db/views/stats/__init__.py +4 -4
- endoreg_db/views/stats/stats_views.py +152 -115
- endoreg_db/views/video/__init__.py +18 -27
- endoreg_db/views/{ai → video/ai}/__init__.py +2 -2
- endoreg_db/views/{ai → video/ai}/label.py +20 -16
- endoreg_db/views/video/correction.py +5 -6
- endoreg_db/views/video/reimport.py +134 -99
- endoreg_db/views/video/segments_crud.py +134 -44
- endoreg_db/views/video/video_apply_mask.py +13 -12
- endoreg_db/views/video/video_correction.py +2 -1
- endoreg_db/views/video/video_download_processed.py +15 -15
- endoreg_db/views/video/video_meta_stats.py +7 -6
- endoreg_db/views/video/video_processing_history.py +3 -2
- endoreg_db/views/video/video_remove_frames.py +13 -12
- endoreg_db/views/video/video_stream.py +110 -82
- {endoreg_db-0.8.8.9.dist-info → endoreg_db-0.8.9.10.dist-info}/METADATA +9 -3
- {endoreg_db-0.8.8.9.dist-info → endoreg_db-0.8.9.10.dist-info}/RECORD +436 -433
- endoreg_db/import_files/processing/video_processing/video_cleanup_on_error.py +0 -119
- endoreg_db/management/commands/import_fallback_video.py +0 -203
- endoreg_db/management/commands/import_video.py +0 -422
- endoreg_db/management/commands/import_video_with_classification.py +0 -367
- endoreg_db/models/media/processing_history/processing_history.py +0 -96
- endoreg_db/serializers/label/__init__.py +0 -7
- endoreg_db/serializers/label_video_segment/_lvs_create.py +0 -149
- endoreg_db/serializers/label_video_segment/_lvs_update.py +0 -138
- endoreg_db/serializers/label_video_segment/_lvs_validate.py +0 -149
- endoreg_db/serializers/label_video_segment/label_video_segment_annotation.py +0 -99
- endoreg_db/serializers/label_video_segment/label_video_segment_update.py +0 -163
- endoreg_db/services/__old/pdf_import.py +0 -1487
- endoreg_db/services/__old/video_import.py +0 -1306
- endoreg_db/tasks/upload_tasks.py +0 -216
- endoreg_db/tasks/video_ingest.py +0 -161
- endoreg_db/tasks/video_processing_tasks.py +0 -327
- endoreg_db/views/misc/translation.py +0 -182
- {endoreg_db-0.8.8.9.dist-info → endoreg_db-0.8.9.10.dist-info}/WHEEL +0 -0
- {endoreg_db-0.8.8.9.dist-info → endoreg_db-0.8.9.10.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
from endoreg_db.models import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
from endoreg_db.models import PatientFinding, PatientFindingIntervention
|
|
2
|
+
from endoreg_db.serializers.patient_finding.patient_finding_classification import (
|
|
3
|
+
PatientFindingClassificationSerializer,
|
|
4
|
+
)
|
|
5
|
+
from endoreg_db.serializers.patient_finding.patient_finding_intervention import (
|
|
6
|
+
PatientFindingInterventionSerializer,
|
|
4
7
|
)
|
|
5
|
-
from endoreg_db.serializers.patient_finding.patient_finding_classification import PatientFindingClassificationSerializer
|
|
6
|
-
from endoreg_db.serializers.patient_finding.patient_finding_intervention import PatientFindingInterventionSerializer
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
from rest_framework import serializers
|
|
@@ -18,38 +19,43 @@ class PatientFindingWriteSerializer(serializers.ModelSerializer):
|
|
|
18
19
|
class Meta:
|
|
19
20
|
model = PatientFinding
|
|
20
21
|
fields = [
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
"id",
|
|
23
|
+
"patient_examination",
|
|
24
|
+
"finding",
|
|
25
|
+
"classifications",
|
|
26
|
+
"interventions",
|
|
23
27
|
]
|
|
24
28
|
|
|
25
29
|
def create(self, validated_data):
|
|
26
30
|
"""
|
|
27
31
|
Create a new PatientFinding instance along with any provided nested classifications and interventions.
|
|
28
|
-
|
|
32
|
+
|
|
29
33
|
Parameters:
|
|
30
34
|
validated_data (dict): Data validated by the serializer, potentially including nested classifications and interventions.
|
|
31
|
-
|
|
35
|
+
|
|
32
36
|
Returns:
|
|
33
37
|
PatientFinding: The newly created PatientFinding instance with related nested objects.
|
|
34
38
|
"""
|
|
35
|
-
classifications_data = validated_data.pop(
|
|
36
|
-
interventions_data = validated_data.pop(
|
|
39
|
+
classifications_data = validated_data.pop("classifications", [])
|
|
40
|
+
interventions_data = validated_data.pop("interventions", [])
|
|
37
41
|
|
|
38
42
|
patient_finding = PatientFinding.objects.create(**validated_data)
|
|
39
43
|
|
|
40
44
|
# Erstelle verschachtelte Objekte
|
|
41
|
-
self._create_nested_objects(
|
|
45
|
+
self._create_nested_objects(
|
|
46
|
+
patient_finding, classifications_data, interventions_data
|
|
47
|
+
)
|
|
42
48
|
|
|
43
49
|
return patient_finding
|
|
44
50
|
|
|
45
51
|
def update(self, instance, validated_data):
|
|
46
52
|
"""
|
|
47
53
|
Update a PatientFinding instance and its nested classifications and interventions.
|
|
48
|
-
|
|
54
|
+
|
|
49
55
|
If new classification or intervention data is provided, existing related objects are deleted and replaced with the new data. Returns the updated PatientFinding instance.
|
|
50
56
|
"""
|
|
51
|
-
classifications_data = validated_data.pop(
|
|
52
|
-
interventions_data = validated_data.pop(
|
|
57
|
+
classifications_data = validated_data.pop("classifications", None)
|
|
58
|
+
interventions_data = validated_data.pop("interventions", None)
|
|
53
59
|
|
|
54
60
|
# Update Hauptobjekt
|
|
55
61
|
for attr, value in validated_data.items():
|
|
@@ -67,10 +73,12 @@ class PatientFindingWriteSerializer(serializers.ModelSerializer):
|
|
|
67
73
|
|
|
68
74
|
return instance
|
|
69
75
|
|
|
70
|
-
def _create_nested_objects(
|
|
76
|
+
def _create_nested_objects(
|
|
77
|
+
self, patient_finding, classifications_data, interventions_data
|
|
78
|
+
):
|
|
71
79
|
"""
|
|
72
80
|
Create nested classification and intervention objects linked to a PatientFinding instance.
|
|
73
|
-
|
|
81
|
+
|
|
74
82
|
This helper method delegates the creation of related classification and intervention objects using the provided data, associating them with the specified PatientFinding.
|
|
75
83
|
"""
|
|
76
84
|
self._create_classifications(patient_finding, classifications_data)
|
|
@@ -79,11 +87,13 @@ class PatientFindingWriteSerializer(serializers.ModelSerializer):
|
|
|
79
87
|
def _create_classifications(self, patient_finding, classifications_data):
|
|
80
88
|
"""
|
|
81
89
|
Create and associate classification objects with a given PatientFinding instance using provided data.
|
|
82
|
-
|
|
90
|
+
|
|
83
91
|
Each classification in `classifications_data` is validated and saved as a related object to `patient_finding`. Validation errors are printed but do not interrupt processing.
|
|
84
92
|
"""
|
|
85
93
|
for classification_data in classifications_data:
|
|
86
|
-
serializer = PatientFindingClassificationSerializer(
|
|
94
|
+
serializer = PatientFindingClassificationSerializer(
|
|
95
|
+
data=classification_data, context={"patient_finding": patient_finding}
|
|
96
|
+
)
|
|
87
97
|
if serializer.is_valid():
|
|
88
98
|
serializer.save(patient_finding=patient_finding)
|
|
89
99
|
else:
|
|
@@ -93,28 +103,27 @@ class PatientFindingWriteSerializer(serializers.ModelSerializer):
|
|
|
93
103
|
def _create_interventions(self, patient_finding, interventions_data):
|
|
94
104
|
"""
|
|
95
105
|
Create and associate intervention objects with a given patient finding using provided intervention data.
|
|
96
|
-
|
|
106
|
+
|
|
97
107
|
Parameters:
|
|
98
108
|
patient_finding: The PatientFinding instance to associate interventions with.
|
|
99
109
|
interventions_data: Iterable of dictionaries containing intervention attributes.
|
|
100
110
|
"""
|
|
101
111
|
for intervention_data in interventions_data:
|
|
102
112
|
PatientFindingIntervention.objects.create(
|
|
103
|
-
finding=patient_finding,
|
|
104
|
-
**intervention_data
|
|
113
|
+
finding=patient_finding, **intervention_data
|
|
105
114
|
)
|
|
106
115
|
|
|
107
116
|
def validate(self, data):
|
|
108
117
|
"""
|
|
109
118
|
Validate that the selected finding is permitted for the specified patient examination.
|
|
110
|
-
|
|
119
|
+
|
|
111
120
|
Raises a ValidationError if the finding is not among the allowed findings for the examination.
|
|
112
|
-
|
|
121
|
+
|
|
113
122
|
Returns:
|
|
114
123
|
dict: The validated data if the finding is permitted.
|
|
115
124
|
"""
|
|
116
|
-
patient_examination = data.get(
|
|
117
|
-
finding = data.get(
|
|
125
|
+
patient_examination = data.get("patient_examination")
|
|
126
|
+
finding = data.get("finding")
|
|
118
127
|
|
|
119
128
|
# Prüfe ob Finding für diese Examination erlaubt ist
|
|
120
129
|
if finding and patient_examination:
|
|
@@ -123,4 +132,4 @@ class PatientFindingWriteSerializer(serializers.ModelSerializer):
|
|
|
123
132
|
f"Finding '{finding.name}' ist nicht für Examination '{patient_examination.examination.name}' erlaubt."
|
|
124
133
|
)
|
|
125
134
|
|
|
126
|
-
return data
|
|
135
|
+
return data
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
from email import message
|
|
2
|
-
from django.contrib import messages
|
|
3
1
|
from pydantic import BaseModel
|
|
4
2
|
from typing import List
|
|
5
3
|
|
|
6
|
-
class ExaminationSchema(BaseModel):
|
|
7
4
|
|
|
8
5
|
class RequirementSchema(BaseModel):
|
|
9
6
|
id: int
|
|
@@ -12,6 +9,7 @@ class RequirementSchema(BaseModel):
|
|
|
12
9
|
satisfied: bool
|
|
13
10
|
message: str
|
|
14
11
|
|
|
12
|
+
|
|
15
13
|
class RequirementSetSchema(BaseModel):
|
|
16
14
|
id: int
|
|
17
15
|
name: str
|
|
@@ -20,6 +18,3 @@ class RequirementSetSchema(BaseModel):
|
|
|
20
18
|
requirements: List[RequirementSchema]
|
|
21
19
|
linked_sets: List["RequirementSetSchema"]
|
|
22
20
|
messages: List[str]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
from rest_framework import serializers
|
|
2
2
|
from django.db import transaction
|
|
3
|
-
from typing import Dict, Any
|
|
4
3
|
import logging
|
|
5
4
|
|
|
6
|
-
from ..models import SensitiveMeta,
|
|
5
|
+
from ..models import SensitiveMeta, Center, Gender
|
|
7
6
|
|
|
8
7
|
logger = logging.getLogger(__name__)
|
|
9
8
|
|
|
@@ -13,23 +12,25 @@ class SensitiveMetaDetailSerializer(serializers.ModelSerializer):
|
|
|
13
12
|
Serializer for displaying SensitiveMeta details with verification state.
|
|
14
13
|
Includes all relevant fields for annotation and verification.
|
|
15
14
|
"""
|
|
16
|
-
|
|
15
|
+
|
|
17
16
|
# State verification fields
|
|
18
17
|
is_verified = serializers.SerializerMethodField()
|
|
19
18
|
dob_verified = serializers.SerializerMethodField()
|
|
20
19
|
names_verified = serializers.SerializerMethodField()
|
|
21
|
-
|
|
20
|
+
|
|
22
21
|
# Related fields for better display
|
|
23
22
|
center_name = serializers.CharField(source="center.name", read_only=True)
|
|
24
|
-
patient_gender_name = serializers.CharField(
|
|
25
|
-
|
|
23
|
+
patient_gender_name = serializers.CharField(
|
|
24
|
+
source="patient_gender.name", read_only=True
|
|
25
|
+
)
|
|
26
|
+
|
|
26
27
|
# Examiner information
|
|
27
28
|
examiners_display = serializers.SerializerMethodField()
|
|
28
|
-
|
|
29
|
+
|
|
29
30
|
# Formatted dates for display
|
|
30
31
|
patient_dob_display = serializers.SerializerMethodField()
|
|
31
32
|
examination_date_display = serializers.SerializerMethodField()
|
|
32
|
-
|
|
33
|
+
|
|
33
34
|
# Hash displays (last 8 characters for security)
|
|
34
35
|
patient_hash_display = serializers.SerializerMethodField()
|
|
35
36
|
examination_hash_display = serializers.SerializerMethodField()
|
|
@@ -37,28 +38,28 @@ class SensitiveMetaDetailSerializer(serializers.ModelSerializer):
|
|
|
37
38
|
class Meta:
|
|
38
39
|
model = SensitiveMeta
|
|
39
40
|
fields = [
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
41
|
+
"id",
|
|
42
|
+
"patient_first_name",
|
|
43
|
+
"patient_last_name",
|
|
44
|
+
"patient_dob",
|
|
45
|
+
"patient_dob_display",
|
|
46
|
+
"examination_date",
|
|
47
|
+
"examination_date_display",
|
|
48
|
+
"center_name",
|
|
49
|
+
"patient_gender_name",
|
|
50
|
+
"endoscope_type",
|
|
51
|
+
"endoscope_sn",
|
|
52
|
+
"patient_hash_display",
|
|
53
|
+
"examination_hash_display",
|
|
54
|
+
"examiners_display",
|
|
55
|
+
"is_verified",
|
|
56
|
+
"dob_verified",
|
|
57
|
+
"names_verified",
|
|
57
58
|
]
|
|
58
59
|
read_only_fields = [
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
"id",
|
|
61
|
+
"patient_hash_display",
|
|
62
|
+
"examination_hash_display",
|
|
62
63
|
]
|
|
63
64
|
|
|
64
65
|
def get_is_verified(self, obj):
|
|
@@ -68,7 +69,9 @@ class SensitiveMetaDetailSerializer(serializers.ModelSerializer):
|
|
|
68
69
|
except AttributeError:
|
|
69
70
|
return False
|
|
70
71
|
except Exception as e:
|
|
71
|
-
logger.exception(
|
|
72
|
+
logger.exception(
|
|
73
|
+
f"Unexpected error in get_is_verified for SensitiveMeta {getattr(obj, 'pk', None)}: {e}"
|
|
74
|
+
)
|
|
72
75
|
raise
|
|
73
76
|
|
|
74
77
|
def get_dob_verified(self, obj):
|
|
@@ -126,32 +129,32 @@ class SensitiveMetaUpdateSerializer(serializers.ModelSerializer):
|
|
|
126
129
|
Serializer for updating SensitiveMeta fields including verification state.
|
|
127
130
|
Handles partial updates and state management.
|
|
128
131
|
"""
|
|
129
|
-
|
|
132
|
+
|
|
130
133
|
# Verification state fields
|
|
131
134
|
dob_verified = serializers.BooleanField(required=False)
|
|
132
135
|
names_verified = serializers.BooleanField(required=False)
|
|
133
|
-
|
|
136
|
+
|
|
134
137
|
# Center can be updated by name
|
|
135
138
|
center_name = serializers.CharField(write_only=True, required=False)
|
|
136
|
-
|
|
139
|
+
|
|
137
140
|
# Gender can be updated by name
|
|
138
141
|
patient_gender_name = serializers.CharField(write_only=True, required=False)
|
|
139
142
|
|
|
140
143
|
class Meta:
|
|
141
144
|
model = SensitiveMeta
|
|
142
145
|
fields = [
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
146
|
+
"patient_first_name",
|
|
147
|
+
"patient_last_name",
|
|
148
|
+
"patient_dob",
|
|
149
|
+
"examination_date",
|
|
150
|
+
"center_name",
|
|
151
|
+
"patient_gender_name",
|
|
152
|
+
"endoscope_type",
|
|
153
|
+
"endoscope_sn",
|
|
154
|
+
"examiner_first_name",
|
|
155
|
+
"examiner_last_name",
|
|
156
|
+
"dob_verified",
|
|
157
|
+
"names_verified",
|
|
155
158
|
]
|
|
156
159
|
|
|
157
160
|
def validate_center_name(self, value):
|
|
@@ -177,17 +180,17 @@ class SensitiveMetaUpdateSerializer(serializers.ModelSerializer):
|
|
|
177
180
|
def validate(self, data):
|
|
178
181
|
"""Custom validation for the entire data set."""
|
|
179
182
|
# Guard against None values before calling strip()
|
|
180
|
-
first_name = data.get(
|
|
183
|
+
first_name = data.get("patient_first_name")
|
|
181
184
|
if first_name is not None and not first_name.strip():
|
|
182
|
-
raise serializers.ValidationError(
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
last_name = data.get(
|
|
185
|
+
raise serializers.ValidationError(
|
|
186
|
+
{"patient_first_name": "First name cannot be empty."}
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
last_name = data.get("patient_last_name")
|
|
187
190
|
if last_name is not None and not last_name.strip():
|
|
188
|
-
raise serializers.ValidationError(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
+
raise serializers.ValidationError(
|
|
192
|
+
{"patient_last_name": "Last name cannot be empty."}
|
|
193
|
+
)
|
|
191
194
|
|
|
192
195
|
return data
|
|
193
196
|
|
|
@@ -198,32 +201,36 @@ class SensitiveMetaUpdateSerializer(serializers.ModelSerializer):
|
|
|
198
201
|
Handles both model fields and verification state.
|
|
199
202
|
"""
|
|
200
203
|
# Extract verification state data
|
|
201
|
-
dob_verified = validated_data.pop(
|
|
202
|
-
names_verified = validated_data.pop(
|
|
203
|
-
|
|
204
|
+
dob_verified = validated_data.pop("dob_verified", None)
|
|
205
|
+
names_verified = validated_data.pop("names_verified", None)
|
|
206
|
+
|
|
204
207
|
# -- center -------------------------------------------------
|
|
205
|
-
center = validated_data.pop(
|
|
206
|
-
if isinstance(center, Center):
|
|
208
|
+
center = validated_data.pop("center_name", None)
|
|
209
|
+
if isinstance(center, Center): # returned by validate_center_name
|
|
207
210
|
instance.center = center
|
|
208
211
|
|
|
209
212
|
# -- gender -------------------------------------------------
|
|
210
|
-
gender = validated_data.pop(
|
|
211
|
-
if isinstance(gender, Gender):
|
|
213
|
+
gender = validated_data.pop("patient_gender_name", None)
|
|
214
|
+
if isinstance(gender, Gender): # returned by validate_patient_gender_name
|
|
212
215
|
instance.patient_gender = gender
|
|
213
216
|
|
|
214
217
|
# -- ordinary fields ---------------------------------------
|
|
215
218
|
if validated_data:
|
|
216
|
-
instance.update_from_dict(validated_data)
|
|
219
|
+
instance.update_from_dict(validated_data) # should NOT call save()
|
|
217
220
|
|
|
218
221
|
# -- verification state ------------------------------------
|
|
219
222
|
if dob_verified is not None or names_verified is not None:
|
|
220
223
|
state = instance.get_or_create_state()
|
|
221
224
|
if dob_verified is not None:
|
|
222
225
|
state.dob_verified = dob_verified
|
|
223
|
-
logger.info(
|
|
226
|
+
logger.info(
|
|
227
|
+
f"Updated DOB verification for SensitiveMeta {instance.pk}: {dob_verified}"
|
|
228
|
+
)
|
|
224
229
|
if names_verified is not None:
|
|
225
230
|
state.names_verified = names_verified
|
|
226
|
-
logger.info(
|
|
231
|
+
logger.info(
|
|
232
|
+
f"Updated names verification for SensitiveMeta {instance.pk}: {names_verified}"
|
|
233
|
+
)
|
|
227
234
|
state.save()
|
|
228
235
|
|
|
229
236
|
# -- finally persist the model itself ----------------------
|
|
@@ -236,47 +243,59 @@ class SensitiveMetaVerificationSerializer(serializers.Serializer):
|
|
|
236
243
|
Simple serializer for bulk verification state updates.
|
|
237
244
|
Used when only updating verification flags.
|
|
238
245
|
"""
|
|
239
|
-
|
|
246
|
+
|
|
240
247
|
sensitive_meta_id = serializers.IntegerField()
|
|
241
248
|
dob_verified = serializers.BooleanField(required=False)
|
|
242
249
|
names_verified = serializers.BooleanField(required=False)
|
|
243
|
-
|
|
250
|
+
|
|
244
251
|
def validate_sensitive_meta_id(self, value):
|
|
245
252
|
"""Ensure SensitiveMeta exists."""
|
|
246
253
|
try:
|
|
247
254
|
SensitiveMeta.objects.get(id=value)
|
|
248
255
|
return value
|
|
249
256
|
except SensitiveMeta.DoesNotExist:
|
|
250
|
-
raise serializers.ValidationError(
|
|
257
|
+
raise serializers.ValidationError(
|
|
258
|
+
f"SensitiveMeta with ID {value} does not exist."
|
|
259
|
+
)
|
|
251
260
|
|
|
252
261
|
@transaction.atomic
|
|
253
262
|
def save(self):
|
|
254
263
|
"""Update verification state for the specified SensitiveMeta with proper locking."""
|
|
255
|
-
sensitive_meta_id = self.validated_data[
|
|
256
|
-
dob_verified = self.validated_data.get(
|
|
257
|
-
names_verified = self.validated_data.get(
|
|
258
|
-
|
|
264
|
+
sensitive_meta_id = self.validated_data["sensitive_meta_id"]
|
|
265
|
+
dob_verified = self.validated_data.get("dob_verified")
|
|
266
|
+
names_verified = self.validated_data.get("names_verified")
|
|
267
|
+
|
|
259
268
|
try:
|
|
260
269
|
# Use select_for_update for strong consistency in concurrent environments
|
|
261
|
-
sensitive_meta = SensitiveMeta.objects.select_for_update().get(
|
|
270
|
+
sensitive_meta = SensitiveMeta.objects.select_for_update().get(
|
|
271
|
+
id=sensitive_meta_id
|
|
272
|
+
)
|
|
262
273
|
state = sensitive_meta.get_or_create_state()
|
|
263
|
-
|
|
274
|
+
|
|
264
275
|
if dob_verified is not None:
|
|
265
276
|
state.dob_verified = dob_verified
|
|
266
|
-
|
|
277
|
+
|
|
267
278
|
if names_verified is not None:
|
|
268
279
|
state.names_verified = names_verified
|
|
269
|
-
|
|
280
|
+
|
|
270
281
|
state.save()
|
|
271
|
-
|
|
282
|
+
|
|
272
283
|
# Only log the ID to avoid potential PII leakage
|
|
273
|
-
logger.info(
|
|
284
|
+
logger.info(
|
|
285
|
+
f"Updated verification state for SensitiveMeta ID {sensitive_meta_id}"
|
|
286
|
+
)
|
|
274
287
|
return state
|
|
275
|
-
|
|
288
|
+
|
|
276
289
|
except SensitiveMeta.DoesNotExist:
|
|
277
|
-
logger.error(
|
|
278
|
-
|
|
290
|
+
logger.error(
|
|
291
|
+
f"SensitiveMeta ID {sensitive_meta_id} not found during verification update"
|
|
292
|
+
)
|
|
293
|
+
raise serializers.ValidationError(
|
|
294
|
+
f"SensitiveMeta with ID {sensitive_meta_id} does not exist."
|
|
295
|
+
)
|
|
279
296
|
except Exception as e:
|
|
280
297
|
# Log the exception class but not the full details to avoid PII leakage
|
|
281
|
-
logger.error(
|
|
282
|
-
|
|
298
|
+
logger.error(
|
|
299
|
+
f"Error updating verification state for ID {sensitive_meta_id}: {type(e).__name__}"
|
|
300
|
+
)
|
|
301
|
+
raise serializers.ValidationError("Failed to update verification state.")
|