endoreg-db 0.8.6.1__py3-none-any.whl → 0.8.8.0__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 +8 -31
- endoreg_db/data/_examples/disease.yaml +55 -0
- endoreg_db/data/_examples/disease_classification.yaml +13 -0
- endoreg_db/data/_examples/disease_classification_choice.yaml +62 -0
- endoreg_db/data/_examples/event.yaml +64 -0
- endoreg_db/data/_examples/examination.yaml +72 -0
- endoreg_db/data/_examples/finding/anatomy_colon.yaml +128 -0
- endoreg_db/data/_examples/finding/colonoscopy.yaml +40 -0
- endoreg_db/data/_examples/finding/colonoscopy_bowel_prep.yaml +56 -0
- endoreg_db/data/_examples/finding/complication.yaml +16 -0
- endoreg_db/data/_examples/finding/data.yaml +105 -0
- endoreg_db/data/_examples/finding/examination_setting.yaml +16 -0
- endoreg_db/data/_examples/finding/medication_related.yaml +18 -0
- endoreg_db/data/_examples/finding/outcome.yaml +12 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_bowel_preparation.yaml +68 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_jnet.yaml +22 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_kudo.yaml +25 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_circularity.yaml +20 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_planarity.yaml +24 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_size.yaml +68 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lesion_surface.yaml +20 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_location.yaml +80 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_lst.yaml +21 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_nice.yaml +20 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_paris.yaml +26 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_sano.yaml +22 -0
- endoreg_db/data/_examples/finding_classification/colonoscopy_summary.yaml +53 -0
- endoreg_db/data/_examples/finding_classification/complication_generic.yaml +25 -0
- endoreg_db/data/_examples/finding_classification/examination_setting_generic.yaml +40 -0
- endoreg_db/data/_examples/finding_classification/histology_colo.yaml +51 -0
- endoreg_db/data/_examples/finding_classification/intervention_required.yaml +26 -0
- endoreg_db/data/_examples/finding_classification/medication_related.yaml +23 -0
- endoreg_db/data/_examples/finding_classification/visualized.yaml +33 -0
- endoreg_db/data/_examples/finding_classification_choice/bowel_preparation.yaml +78 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_circularity_default.yaml +32 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_jnet.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_kudo.yaml +23 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_lst.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_nice.yaml +17 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_paris.yaml +57 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_planarity_default.yaml +49 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_sano.yaml +14 -0
- endoreg_db/data/_examples/finding_classification_choice/colon_lesion_surface_intact_default.yaml +36 -0
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_location.yaml +229 -0
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_not_complete_reason.yaml +19 -0
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_size.yaml +82 -0
- endoreg_db/data/_examples/finding_classification_choice/colonoscopy_summary_worst_finding.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/complication_generic_types.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/examination_setting_generic_types.yaml +15 -0
- endoreg_db/data/_examples/finding_classification_choice/histology.yaml +24 -0
- endoreg_db/data/_examples/finding_classification_choice/histology_polyp.yaml +20 -0
- endoreg_db/data/_examples/finding_classification_choice/outcome.yaml +19 -0
- endoreg_db/data/_examples/finding_classification_choice/yes_no_na.yaml +11 -0
- endoreg_db/data/_examples/finding_classification_type/colonoscopy_basic.yaml +48 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy.yaml +43 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_colonoscopy.yaml +168 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_egd.yaml +128 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_ercp.yaml +32 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_eus_lower.yaml +9 -0
- endoreg_db/data/_examples/finding_intervention/endoscopy_eus_upper.yaml +36 -0
- endoreg_db/data/_examples/finding_intervention_type/endoscopy.yaml +15 -0
- endoreg_db/data/_examples/finding_type/data.yaml +43 -0
- endoreg_db/data/_examples/requirement/age.yaml +26 -0
- endoreg_db/data/_examples/requirement/colonoscopy_baseline_austria.yaml +45 -0
- endoreg_db/data/_examples/requirement/disease_cardiovascular.yaml +79 -0
- endoreg_db/data/_examples/requirement/disease_classification_choice_cardiovascular.yaml +41 -0
- endoreg_db/data/_examples/requirement/disease_hepatology.yaml +12 -0
- endoreg_db/data/_examples/requirement/disease_misc.yaml +12 -0
- endoreg_db/data/_examples/requirement/disease_renal.yaml +96 -0
- endoreg_db/data/_examples/requirement/endoscopy_bleeding_risk.yaml +59 -0
- endoreg_db/data/_examples/requirement/event_cardiology.yaml +251 -0
- endoreg_db/data/_examples/requirement/event_requirements.yaml +145 -0
- endoreg_db/data/_examples/requirement/finding_colon_polyp.yaml +50 -0
- endoreg_db/data/_examples/requirement/gender.yaml +25 -0
- endoreg_db/data/_examples/requirement/lab_value.yaml +441 -0
- endoreg_db/data/_examples/requirement/medication.yaml +93 -0
- endoreg_db/data/_examples/requirement_operator/age.yaml +13 -0
- endoreg_db/data/_examples/requirement_operator/lab_operators.yaml +129 -0
- endoreg_db/data/_examples/requirement_operator/model_operators.yaml +96 -0
- endoreg_db/data/_examples/requirement_set/01_endoscopy_generic.yaml +48 -0
- endoreg_db/data/_examples/requirement_set/colonoscopy_austria_screening.yaml +57 -0
- endoreg_db/data/_examples/yaml_examples.xlsx +0 -0
- endoreg_db/data/ai_model_meta/default_multilabel_classification.yaml +4 -3
- endoreg_db/data/event_classification/data.yaml +4 -0
- endoreg_db/data/event_classification_choice/data.yaml +9 -0
- endoreg_db/data/finding_classification/colonoscopy_bowel_preparation.yaml +43 -70
- endoreg_db/data/finding_classification/colonoscopy_lesion_size.yaml +22 -52
- endoreg_db/data/finding_classification/colonoscopy_location.yaml +31 -62
- endoreg_db/data/finding_classification/histology_colo.yaml +28 -36
- endoreg_db/data/requirement/colon_polyp_intervention.yaml +49 -0
- endoreg_db/data/requirement/coloreg_colon_polyp.yaml +49 -0
- endoreg_db/data/requirement_set/01_endoscopy_generic.yaml +31 -12
- endoreg_db/data/requirement_set/01_laboratory.yaml +13 -0
- endoreg_db/data/requirement_set/02_endoscopy_bleeding_risk.yaml +46 -0
- endoreg_db/data/requirement_set/90_coloreg.yaml +178 -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 +5 -2
- endoreg_db/helpers/data_loader.py +1 -1
- 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_video.py +9 -10
- endoreg_db/management/commands/import_video_with_classification.py +1 -1
- endoreg_db/management/commands/init_default_ai_model.py +1 -1
- endoreg_db/management/commands/list_routes.py +18 -0
- endoreg_db/management/commands/load_center_data.py +12 -12
- endoreg_db/management/commands/load_requirement_data.py +60 -31
- endoreg_db/management/commands/load_requirement_set_tags.py +95 -0
- endoreg_db/management/commands/setup_endoreg_db.py +3 -3
- endoreg_db/management/commands/storage_management.py +271 -203
- endoreg_db/migrations/0001_initial.py +1799 -1300
- endoreg_db/migrations/0002_requirementset_depends_on.py +18 -0
- endoreg_db/migrations/_old/0001_initial.py +1857 -0
- endoreg_db/migrations/_old/0004_employee_city_employee_post_code_employee_street_and_more.py +68 -0
- endoreg_db/migrations/_old/0004_remove_casetemplate_rules_and_more.py +77 -0
- endoreg_db/migrations/_old/0005_merge_20251111_1003.py +14 -0
- endoreg_db/migrations/_old/0006_sensitivemeta_anonymized_text_and_more.py +68 -0
- endoreg_db/migrations/_old/0007_remove_rule_attribute_dtype_remove_rule_rule_type_and_more.py +89 -0
- endoreg_db/migrations/_old/0008_remove_event_event_classification_and_more.py +27 -0
- endoreg_db/migrations/_old/0009_alter_modelmeta_options_and_more.py +21 -0
- 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 +103 -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 +7 -8
- endoreg_db/models/label/annotation/image_classification.py +10 -9
- endoreg_db/models/label/annotation/video_segmentation_annotation.py +8 -5
- 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 +76 -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 +110 -182
- endoreg_db/models/media/pdf/report_file.py +25 -29
- endoreg_db/models/media/pdf/report_reader/report_reader_config.py +30 -46
- endoreg_db/models/media/pdf/report_reader/report_reader_flag.py +23 -7
- endoreg_db/models/media/video/__init__.py +1 -0
- endoreg_db/models/media/video/create_from_file.py +48 -56
- endoreg_db/models/media/video/pipe_2.py +8 -9
- endoreg_db/models/media/video/video_file.py +150 -108
- 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 +109 -62
- 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/__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 +17 -18
- endoreg_db/models/medical/examination/examination_indication.py +26 -25
- endoreg_db/models/medical/examination/examination_time.py +16 -6
- 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 +38 -39
- endoreg_db/models/medical/finding/finding_classification.py +37 -48
- endoreg_db/models/medical/finding/finding_intervention.py +27 -22
- endoreg_db/models/medical/finding/finding_type.py +13 -12
- endoreg_db/models/medical/hardware/endoscope.py +20 -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 +1 -5
- 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 +19 -24
- endoreg_db/models/metadata/sensitive_meta.py +102 -85
- endoreg_db/models/metadata/sensitive_meta_logic.py +192 -173
- 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 +25 -25
- 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/requirement/requirement.py +580 -272
- 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 +36 -33
- 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 +46 -47
- endoreg_db/models/state/label_video_segment.py +9 -0
- endoreg_db/models/state/raw_pdf.py +40 -46
- endoreg_db/models/state/sensitive_meta.py +6 -2
- endoreg_db/models/state/video.py +58 -53
- endoreg_db/models/upload_job.py +32 -55
- endoreg_db/models/utils.py +1 -2
- endoreg_db/root_urls.py +21 -2
- endoreg_db/serializers/__init__.py +0 -2
- endoreg_db/serializers/anonymization.py +18 -10
- endoreg_db/serializers/meta/report_meta.py +1 -1
- endoreg_db/serializers/meta/sensitive_meta_detail.py +63 -118
- endoreg_db/serializers/misc/file_overview.py +11 -99
- endoreg_db/serializers/requirements/requirement_sets.py +92 -22
- endoreg_db/serializers/video/segmentation.py +2 -1
- endoreg_db/serializers/video/video_processing_history.py +20 -5
- endoreg_db/services/anonymization.py +75 -73
- endoreg_db/services/lookup_service.py +37 -24
- endoreg_db/services/pdf_import.py +166 -68
- endoreg_db/services/storage_aware_video_processor.py +140 -114
- endoreg_db/services/video_import.py +193 -283
- endoreg_db/urls/__init__.py +7 -20
- endoreg_db/urls/media.py +108 -67
- 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 +88 -16
- endoreg_db/utils/defaults/set_default_center.py +32 -0
- endoreg_db/utils/names.py +22 -16
- endoreg_db/utils/permissions.py +2 -1
- endoreg_db/utils/pipelines/process_video_dir.py +1 -1
- endoreg_db/utils/requirement_operator_logic/model_evaluators.py +414 -127
- 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 +0 -10
- endoreg_db/views/anonymization/media_management.py +198 -163
- endoreg_db/views/anonymization/overview.py +4 -1
- endoreg_db/views/anonymization/validate.py +174 -40
- endoreg_db/views/media/__init__.py +2 -0
- endoreg_db/views/media/pdf_media.py +131 -152
- endoreg_db/views/media/sensitive_metadata.py +46 -6
- endoreg_db/views/media/video_media.py +89 -82
- endoreg_db/views/media/video_segments.py +2 -3
- endoreg_db/views/meta/sensitive_meta_detail.py +0 -63
- endoreg_db/views/patient/patient.py +5 -4
- endoreg_db/views/pdf/pdf_stream.py +20 -21
- endoreg_db/views/pdf/reimport.py +11 -32
- endoreg_db/views/requirement/evaluate.py +188 -187
- endoreg_db/views/requirement/lookup.py +17 -3
- endoreg_db/views/requirement/requirement_utils.py +89 -0
- endoreg_db/views/video/__init__.py +0 -2
- endoreg_db/views/video/correction.py +2 -2
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.0.dist-info}/METADATA +7 -3
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.0.dist-info}/RECORD +341 -245
- endoreg_db/models/administration/permissions/__init__.py +0 -44
- endoreg_db/models/media/video/video_file_frames.py +0 -0
- endoreg_db/models/metadata/frame_ocr_result.py +0 -0
- 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/serializers/video/video_metadata.py +0 -105
- 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/views/report/__init__.py +0 -9
- 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.py +0 -0
- /endoreg_db/data/{requirement_set → _examples/requirement_set}/endoscopy_bleeding_risk.yaml +0 -0
- /endoreg_db/migrations/{0002_add_video_correction_models.py → _old/0002_add_video_correction_models.py} +0 -0
- /endoreg_db/migrations/{0003_add_center_display_name.py → _old/0003_add_center_display_name.py} +0 -0
- /endoreg_db/{models/media/video/refactor_plan.md → views/pdf/pdf_stream_views.py} +0 -0
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.0.dist-info}/WHEEL +0 -0
- {endoreg_db-0.8.6.1.dist-info → endoreg_db-0.8.8.0.dist-info}/licenses/LICENSE +0 -0
endoreg_db/views/pdf/reimport.py
CHANGED
|
@@ -53,13 +53,9 @@ class PdfReimportView(APIView):
|
|
|
53
53
|
raw_file_path = pdf.get_raw_file_path()
|
|
54
54
|
|
|
55
55
|
if not raw_file_path or not raw_file_path.exists():
|
|
56
|
-
logger.error(
|
|
57
|
-
f"Raw PDF file not found for hash {pdf.pdf_hash}: {raw_file_path}"
|
|
58
|
-
)
|
|
56
|
+
logger.error(f"Raw PDF file not found for hash {pdf.pdf_hash}: {raw_file_path}")
|
|
59
57
|
return Response(
|
|
60
|
-
{
|
|
61
|
-
"error": f"Raw PDF file not found for PDF {pdf.pdf_hash}. Please upload the original file again."
|
|
62
|
-
},
|
|
58
|
+
{"error": f"Raw PDF file not found for PDF {pdf.pdf_hash}. Please upload the original file again."},
|
|
63
59
|
status=status.HTTP_404_NOT_FOUND,
|
|
64
60
|
)
|
|
65
61
|
|
|
@@ -79,10 +75,8 @@ class PdfReimportView(APIView):
|
|
|
79
75
|
old_meta_id = None
|
|
80
76
|
if pdf.sensitive_meta:
|
|
81
77
|
old_meta_id = pdf.sensitive_meta.pk
|
|
82
|
-
logger.info(
|
|
83
|
-
|
|
84
|
-
)
|
|
85
|
-
pdf.sensitive_meta = None # type: ignore
|
|
78
|
+
logger.info(f"Clearing existing SensitiveMeta {old_meta_id} for PDF {pdf.pdf_hash}")
|
|
79
|
+
pdf.sensitive_meta = None
|
|
86
80
|
pdf.save(update_fields=["sensitive_meta"])
|
|
87
81
|
|
|
88
82
|
# Delete the old SensitiveMeta record
|
|
@@ -90,15 +84,11 @@ class PdfReimportView(APIView):
|
|
|
90
84
|
SensitiveMeta.objects.filter(pk=old_meta_id).delete()
|
|
91
85
|
logger.info(f"Deleted old SensitiveMeta {old_meta_id}")
|
|
92
86
|
except Exception as e:
|
|
93
|
-
logger.warning(
|
|
94
|
-
f"Could not delete old SensitiveMeta {old_meta_id}: {e}"
|
|
95
|
-
)
|
|
87
|
+
logger.warning(f"Could not delete old SensitiveMeta {old_meta_id}: {e}")
|
|
96
88
|
|
|
97
89
|
# Use PdfImportService for reprocessing
|
|
98
90
|
try:
|
|
99
|
-
logger.info(
|
|
100
|
-
f"Starting reprocessing using PdfImportService for {pdf.pdf_hash}"
|
|
101
|
-
)
|
|
91
|
+
logger.info(f"Starting reprocessing using PdfImportService for {pdf.pdf_hash}")
|
|
102
92
|
self.pdf_service.import_and_anonymize(
|
|
103
93
|
file_path=raw_file_path,
|
|
104
94
|
center_name=pdf.center.name,
|
|
@@ -106,9 +96,7 @@ class PdfReimportView(APIView):
|
|
|
106
96
|
retry=True, # Mark as retry attempt
|
|
107
97
|
)
|
|
108
98
|
|
|
109
|
-
logger.info(
|
|
110
|
-
f"PdfImportService reprocessing completed for {pdf.pdf_hash}"
|
|
111
|
-
)
|
|
99
|
+
logger.info(f"PdfImportService reprocessing completed for {pdf.pdf_hash}")
|
|
112
100
|
|
|
113
101
|
# Refresh to get updated state
|
|
114
102
|
pdf.refresh_from_db()
|
|
@@ -119,9 +107,7 @@ class PdfReimportView(APIView):
|
|
|
119
107
|
"pdf_id": pdf_id,
|
|
120
108
|
"pdf_hash": str(pdf.pdf_hash),
|
|
121
109
|
"sensitive_meta_created": pdf.sensitive_meta is not None,
|
|
122
|
-
"sensitive_meta_id": pdf.sensitive_meta.pk
|
|
123
|
-
if pdf.sensitive_meta
|
|
124
|
-
else None,
|
|
110
|
+
"sensitive_meta_id": pdf.sensitive_meta.pk if pdf.sensitive_meta else None,
|
|
125
111
|
"text_extracted": bool(pdf.text),
|
|
126
112
|
"anonymized": pdf.anonymized,
|
|
127
113
|
"status": "done",
|
|
@@ -130,9 +116,7 @@ class PdfReimportView(APIView):
|
|
|
130
116
|
)
|
|
131
117
|
|
|
132
118
|
except Exception as e:
|
|
133
|
-
logger.exception(
|
|
134
|
-
f"PdfImportService reprocessing failed for PDF {pdf.pdf_hash}: {e}"
|
|
135
|
-
)
|
|
119
|
+
logger.exception(f"PdfImportService reprocessing failed for PDF {pdf.pdf_hash}: {e}")
|
|
136
120
|
return Response(
|
|
137
121
|
{
|
|
138
122
|
"error": f"Reprocessing failed: {str(e)}",
|
|
@@ -144,16 +128,11 @@ class PdfReimportView(APIView):
|
|
|
144
128
|
)
|
|
145
129
|
|
|
146
130
|
except Exception as e:
|
|
147
|
-
logger.error(
|
|
148
|
-
f"Failed to re-import PDF {pdf.pdf_hash}: {str(e)}", exc_info=True
|
|
149
|
-
)
|
|
131
|
+
logger.error(f"Failed to re-import PDF {pdf.pdf_hash}: {str(e)}", exc_info=True)
|
|
150
132
|
|
|
151
133
|
# Handle specific error types
|
|
152
134
|
error_msg = str(e)
|
|
153
|
-
if any(
|
|
154
|
-
phrase in error_msg.lower()
|
|
155
|
-
for phrase in ["insufficient storage", "no space left", "disk full"]
|
|
156
|
-
):
|
|
135
|
+
if any(phrase in error_msg.lower() for phrase in ["insufficient storage", "no space left", "disk full"]):
|
|
157
136
|
# Storage error - return specific error message
|
|
158
137
|
return Response(
|
|
159
138
|
{
|
|
@@ -1,52 +1,31 @@
|
|
|
1
1
|
from endoreg_db.models.requirement.requirement import Requirement
|
|
2
|
+
from endoreg_db.views.requirement.requirement_utils import safe_evaluate_requirement
|
|
2
3
|
from endoreg_db.models.requirement.requirement_set import RequirementSet
|
|
4
|
+
from endoreg_db.models.requirement.requirement_evaluation.evaluate_with_dependencies import (
|
|
5
|
+
evaluate_requirement_sets_with_dependencies,
|
|
6
|
+
RequirementStatus, # if you export it there, otherwise re-declare in view
|
|
7
|
+
)
|
|
3
8
|
from endoreg_db.models.medical.patient.patient_examination import PatientExamination
|
|
4
|
-
|
|
5
|
-
|
|
6
9
|
from rest_framework import status
|
|
7
10
|
from rest_framework.decorators import api_view
|
|
8
11
|
from rest_framework.response import Response
|
|
12
|
+
import json
|
|
9
13
|
import logging
|
|
10
14
|
|
|
11
15
|
logger = logging.getLogger(__name__)
|
|
12
|
-
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@api_view(["POST"])
|
|
13
19
|
def evaluate_requirements(request):
|
|
14
20
|
"""
|
|
15
|
-
Evaluate requirements and always return 200 with structured results.
|
|
16
|
-
Payload:
|
|
17
|
-
{
|
|
18
|
-
"requirement_set_ids": [<int>, ...], // optional; evaluates all if omitted
|
|
19
|
-
"patient_examination_id": <int> // required
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
Response (HTTP 200 always):
|
|
23
|
-
{
|
|
24
|
-
"ok": <bool>, // false if any errors occurred
|
|
25
|
-
"errors": [<str>, ...], // high-level problems (e.g. invalid input, missing PE)
|
|
26
|
-
"meta": {
|
|
27
|
-
"patientExaminationId": <int|null>,
|
|
28
|
-
"setsEvaluated": <int>,
|
|
29
|
-
"requirementsEvaluated": <int>,
|
|
30
|
-
"status": "ok" | "partial" | "failed"
|
|
31
|
-
},
|
|
32
|
-
"results": [
|
|
33
|
-
{
|
|
34
|
-
"requirement_set_id": <int>,
|
|
35
|
-
"requirement_set_name": <str>,
|
|
36
|
-
"requirement_name": <str>,
|
|
37
|
-
"met": <bool>,
|
|
38
|
-
"details": <str>, // always a string for UI display
|
|
39
|
-
"error": <str|null> // per-item error if evaluation failed
|
|
40
|
-
}
|
|
41
|
-
]
|
|
42
|
-
}
|
|
21
|
+
Evaluate requirements (all selected sets) and always return 200 with structured results.
|
|
43
22
|
"""
|
|
44
23
|
payload = request.data or {}
|
|
45
24
|
req_set_ids = payload.get("requirement_set_ids")
|
|
46
25
|
pe_id = payload.get("patient_examination_id")
|
|
47
26
|
|
|
48
|
-
results = []
|
|
49
|
-
errors = []
|
|
27
|
+
results: list[dict] = []
|
|
28
|
+
errors: list[str] = []
|
|
50
29
|
sets_evaluated = 0
|
|
51
30
|
requirements_evaluated = 0
|
|
52
31
|
|
|
@@ -55,53 +34,63 @@ def evaluate_requirements(request):
|
|
|
55
34
|
msg = "patient_examination_id is required"
|
|
56
35
|
errors.append(msg)
|
|
57
36
|
logger.warning("evaluate_requirements: %s; payload=%s", msg, payload)
|
|
58
|
-
return Response(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
37
|
+
return Response(
|
|
38
|
+
{
|
|
39
|
+
"ok": False,
|
|
40
|
+
"errors": errors,
|
|
41
|
+
"meta": {
|
|
42
|
+
"patientExaminationId": None,
|
|
43
|
+
"setsEvaluated": 0,
|
|
44
|
+
"requirementsEvaluated": 0,
|
|
45
|
+
"status": "failed",
|
|
46
|
+
},
|
|
47
|
+
"results": [],
|
|
66
48
|
},
|
|
67
|
-
|
|
68
|
-
|
|
49
|
+
status=status.HTTP_200_OK,
|
|
50
|
+
)
|
|
69
51
|
|
|
70
52
|
# ---- fetch PatientExamination
|
|
71
53
|
try:
|
|
72
|
-
pe = (
|
|
73
|
-
|
|
74
|
-
|
|
54
|
+
pe = (
|
|
55
|
+
PatientExamination.objects.select_related("patient")
|
|
56
|
+
.get(id=pe_id)
|
|
57
|
+
)
|
|
75
58
|
except PatientExamination.DoesNotExist:
|
|
76
59
|
msg = f"PatientExamination with id {pe_id} does not exist"
|
|
77
60
|
errors.append(msg)
|
|
78
61
|
logger.warning("evaluate_requirements: %s", msg)
|
|
79
|
-
return Response(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
"
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
62
|
+
return Response(
|
|
63
|
+
{
|
|
64
|
+
"ok": False,
|
|
65
|
+
"errors": errors,
|
|
66
|
+
"meta": {
|
|
67
|
+
"patientExaminationId": pe_id,
|
|
68
|
+
"setsEvaluated": 0,
|
|
69
|
+
"requirementsEvaluated": 0,
|
|
70
|
+
"status": "failed",
|
|
71
|
+
},
|
|
72
|
+
"results": [],
|
|
87
73
|
},
|
|
88
|
-
|
|
89
|
-
|
|
74
|
+
status=status.HTTP_200_OK,
|
|
75
|
+
)
|
|
90
76
|
except Exception as e:
|
|
91
77
|
msg = f"Unexpected error retrieving PatientExamination {pe_id}: {e}"
|
|
92
78
|
errors.append(msg)
|
|
93
79
|
logger.exception("evaluate_requirements: %s", msg)
|
|
94
|
-
return Response(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
80
|
+
return Response(
|
|
81
|
+
{
|
|
82
|
+
"ok": False,
|
|
83
|
+
"errors": errors,
|
|
84
|
+
"meta": {
|
|
85
|
+
"patientExaminationId": pe_id,
|
|
86
|
+
"setsEvaluated": 0,
|
|
87
|
+
"requirementsEvaluated": 0,
|
|
88
|
+
"status": "failed",
|
|
89
|
+
},
|
|
90
|
+
"results": [],
|
|
102
91
|
},
|
|
103
|
-
|
|
104
|
-
|
|
92
|
+
status=status.HTTP_200_OK,
|
|
93
|
+
)
|
|
105
94
|
|
|
106
95
|
# ---- determine requirement sets
|
|
107
96
|
try:
|
|
@@ -120,75 +109,152 @@ def evaluate_requirements(request):
|
|
|
120
109
|
msg = f"Error loading RequirementSets: {e}"
|
|
121
110
|
errors.append(msg)
|
|
122
111
|
logger.exception("evaluate_requirements: %s", msg)
|
|
123
|
-
return Response(
|
|
124
|
-
|
|
112
|
+
return Response(
|
|
113
|
+
{
|
|
114
|
+
"ok": False,
|
|
115
|
+
"errors": errors,
|
|
116
|
+
"meta": {
|
|
117
|
+
"patientExaminationId": pe_id,
|
|
118
|
+
"setsEvaluated": 0,
|
|
119
|
+
"requirementsEvaluated": 0,
|
|
120
|
+
"status": "failed",
|
|
121
|
+
},
|
|
122
|
+
"results": [],
|
|
123
|
+
},
|
|
124
|
+
status=status.HTTP_200_OK,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# nothing to evaluate → still return 200
|
|
128
|
+
if not requirement_sets:
|
|
129
|
+
response_payload = {
|
|
130
|
+
"ok": len(errors) == 0,
|
|
125
131
|
"errors": errors,
|
|
126
132
|
"meta": {
|
|
127
133
|
"patientExaminationId": pe_id,
|
|
128
134
|
"setsEvaluated": 0,
|
|
129
135
|
"requirementsEvaluated": 0,
|
|
130
|
-
"status": "failed",
|
|
136
|
+
"status": "failed" if errors else "ok",
|
|
131
137
|
},
|
|
132
|
-
"results": []
|
|
133
|
-
}
|
|
138
|
+
"results": [],
|
|
139
|
+
}
|
|
140
|
+
return Response(response_payload, status=status.HTTP_200_OK)
|
|
141
|
+
|
|
142
|
+
# mapping from IDs to objects for later lookup
|
|
143
|
+
sets_by_id: dict[int, RequirementSet] = {s.id: s for s in requirement_sets}
|
|
144
|
+
|
|
145
|
+
# ---- main evaluation with set dependencies
|
|
146
|
+
try:
|
|
147
|
+
# returns: { set_id: { req_id: (status, details) } }
|
|
148
|
+
set_results = evaluate_requirement_sets_with_dependencies(
|
|
149
|
+
requirement_sets,
|
|
150
|
+
pe.patient,
|
|
151
|
+
mode="strict",
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
for set_id, req_dict in set_results.items():
|
|
155
|
+
req_set = sets_by_id.get(set_id)
|
|
156
|
+
set_name = getattr(
|
|
157
|
+
req_set, "name", str(set_id)
|
|
158
|
+
) if req_set is not None else str(set_id)
|
|
134
159
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
# fall back to the prefetched instance
|
|
143
|
-
requirement_obj = req
|
|
160
|
+
for req_id, (status_value, details) in req_dict.items():
|
|
161
|
+
try:
|
|
162
|
+
requirement_obj = Requirement.objects.get(id=req_id)
|
|
163
|
+
req_name = getattr(requirement_obj, "name", f"#{req_id}")
|
|
164
|
+
except Requirement.DoesNotExist:
|
|
165
|
+
requirement_obj = None
|
|
166
|
+
req_name = f"#{req_id}"
|
|
144
167
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
168
|
+
# map RequirementStatus → met + error
|
|
169
|
+
if status_value == "PASSED":
|
|
170
|
+
met = True
|
|
171
|
+
error_str = None
|
|
172
|
+
elif status_value in ("FAILED", "BLOCKED"):
|
|
173
|
+
met = False
|
|
174
|
+
error_str = None
|
|
175
|
+
else: # "ERROR"
|
|
176
|
+
met = False
|
|
177
|
+
error_str = "Technischer Fehler bei der Auswertung"
|
|
178
|
+
|
|
179
|
+
# normalize details to string
|
|
148
180
|
if isinstance(details, str):
|
|
149
181
|
details_str = details
|
|
150
182
|
else:
|
|
151
183
|
try:
|
|
152
|
-
details_str = json.dumps(
|
|
184
|
+
details_str = json.dumps(
|
|
185
|
+
details, ensure_ascii=False, default=str
|
|
186
|
+
)
|
|
153
187
|
except Exception:
|
|
154
188
|
details_str = str(details)
|
|
155
189
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
+
# default fallback text if details are empty
|
|
191
|
+
if not details_str:
|
|
192
|
+
details_str = (
|
|
193
|
+
"Voraussetzung erfüllt"
|
|
194
|
+
if met
|
|
195
|
+
else "Voraussetzung nicht erfüllt"
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
if status_value == "ERROR":
|
|
199
|
+
# add a high-level error for meta if there was an internal error
|
|
200
|
+
msg = (
|
|
201
|
+
f"Technischer Fehler bei der Auswertung von "
|
|
202
|
+
f"Voraussetzung '{req_name}' in Set '{set_name}'."
|
|
203
|
+
)
|
|
204
|
+
errors.append(msg)
|
|
205
|
+
|
|
206
|
+
results.append(
|
|
207
|
+
{
|
|
208
|
+
"requirement_set_id": set_id,
|
|
209
|
+
"requirement_set_name": set_name,
|
|
210
|
+
"requirement_name": req_name,
|
|
211
|
+
"met": bool(met),
|
|
212
|
+
"details": details_str,
|
|
213
|
+
"error": error_str,
|
|
214
|
+
"status": status_value,
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
requirements_evaluated += 1
|
|
218
|
+
|
|
219
|
+
except Exception as e:
|
|
220
|
+
# hard failure of the orchestrator → log and fall back to per-requirement evaluation
|
|
221
|
+
msg = f"Unerwarteter Fehler bei der gruppenbasierten Bewertung: {e}"
|
|
222
|
+
errors.append(msg)
|
|
223
|
+
logger.exception("evaluate_requirements: %s", msg)
|
|
224
|
+
|
|
225
|
+
for req_set in requirement_sets:
|
|
226
|
+
for req in req_set.requirements.all():
|
|
227
|
+
met, details, error = safe_evaluate_requirement(
|
|
228
|
+
req, pe.patient, mode="strict"
|
|
229
|
+
)
|
|
230
|
+
# normalize details to string
|
|
231
|
+
if not isinstance(details, str):
|
|
232
|
+
try:
|
|
233
|
+
details = json.dumps(details, ensure_ascii=False, default=str)
|
|
234
|
+
except Exception:
|
|
235
|
+
details = str(details)
|
|
236
|
+
|
|
237
|
+
if not details:
|
|
238
|
+
details = (
|
|
239
|
+
"Voraussetzung erfüllt"
|
|
240
|
+
if met
|
|
241
|
+
else "Voraussetzung nicht erfüllt"
|
|
242
|
+
)
|
|
190
243
|
|
|
191
|
-
|
|
244
|
+
results.append(
|
|
245
|
+
{
|
|
246
|
+
"requirement_set_id": req_set.id,
|
|
247
|
+
"requirement_set_name": getattr(
|
|
248
|
+
req_set, "name", str(req_set.id)
|
|
249
|
+
),
|
|
250
|
+
"requirement_name": getattr(req, "name", "unknown"),
|
|
251
|
+
"met": bool(met),
|
|
252
|
+
"details": details,
|
|
253
|
+
"error": error,
|
|
254
|
+
"status": "PASSED" if met else "FAILED",
|
|
255
|
+
}
|
|
256
|
+
)
|
|
257
|
+
requirements_evaluated += 1
|
|
192
258
|
|
|
193
259
|
# ---- response meta & status summary
|
|
194
260
|
any_errors = len(errors) > 0
|
|
@@ -201,79 +267,14 @@ def evaluate_requirements(request):
|
|
|
201
267
|
|
|
202
268
|
response_payload = {
|
|
203
269
|
"ok": not any_errors,
|
|
204
|
-
"errors": errors,
|
|
270
|
+
"errors": errors,
|
|
205
271
|
"meta": {
|
|
206
272
|
"patientExaminationId": pe_id,
|
|
207
273
|
"setsEvaluated": sets_evaluated,
|
|
208
274
|
"requirementsEvaluated": requirements_evaluated,
|
|
209
|
-
"status": status_label
|
|
275
|
+
"status": status_label,
|
|
210
276
|
},
|
|
211
|
-
"results": results
|
|
277
|
+
"results": results,
|
|
212
278
|
}
|
|
213
279
|
|
|
214
280
|
return Response(response_payload, status=status.HTTP_200_OK)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
def evaluate_requirement_set(request) -> Response:
|
|
218
|
-
"""
|
|
219
|
-
Evaluate a specific RequirementSet based on provided RequirementLinks data.
|
|
220
|
-
|
|
221
|
-
Expects a JSON payload with the following structure:
|
|
222
|
-
{
|
|
223
|
-
"requirement_set_ids": [<requirement_set_ids>],
|
|
224
|
-
"patient_examination_id": <patient_examination_id>
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
Returns a JSON response with the evaluation results for the specified RequirementSet:
|
|
228
|
-
{
|
|
229
|
-
"results": [
|
|
230
|
-
{
|
|
231
|
-
"requirement_name": <requirement_name>,
|
|
232
|
-
"met": <true/false>,
|
|
233
|
-
"details": <additional_details>
|
|
234
|
-
},
|
|
235
|
-
...
|
|
236
|
-
]
|
|
237
|
-
}
|
|
238
|
-
"""
|
|
239
|
-
try:
|
|
240
|
-
data = request.data
|
|
241
|
-
requirement_set_ids = data.get("requirement_set_ids", None)
|
|
242
|
-
patient_examination_id = data.get("patient_examination_id")
|
|
243
|
-
|
|
244
|
-
if not requirement_set_ids:
|
|
245
|
-
return Response({"error": "requirement_set_ids is required"}, status=status.HTTP_400_BAD_REQUEST)
|
|
246
|
-
|
|
247
|
-
if not patient_examination_id:
|
|
248
|
-
return Response({"error": "patient_examination_id is required"}, status=status.HTTP_400_BAD_REQUEST)
|
|
249
|
-
|
|
250
|
-
# Get the patient examination
|
|
251
|
-
try:
|
|
252
|
-
patient_examination = PatientExamination.objects.get(id=patient_examination_id)
|
|
253
|
-
except PatientExamination.DoesNotExist:
|
|
254
|
-
return Response({"error": f"PatientExamination with id {patient_examination_id} does not exist"}, status=status.HTTP_404_NOT_FOUND)
|
|
255
|
-
|
|
256
|
-
results = []
|
|
257
|
-
|
|
258
|
-
# Construct RequirementLinks from the provided data
|
|
259
|
-
for requirement_set_id in requirement_set_ids:
|
|
260
|
-
# Fetch the specified RequirementSet
|
|
261
|
-
try:
|
|
262
|
-
req_set = RequirementSet.objects.get(id=requirement_set_id)
|
|
263
|
-
except RequirementSet.DoesNotExist:
|
|
264
|
-
return Response({"error": f"RequirementSet with id {requirement_set_id} does not exist"}, status=status.HTTP_404_NOT_FOUND)
|
|
265
|
-
|
|
266
|
-
for requirement in req_set.requirements.all():
|
|
267
|
-
met, details = requirement.evaluate(patient_examination.patient, mode="strict")
|
|
268
|
-
results.append({
|
|
269
|
-
"requirement_name": requirement.name,
|
|
270
|
-
"met": met,
|
|
271
|
-
"details": details
|
|
272
|
-
})
|
|
273
|
-
|
|
274
|
-
return Response({
|
|
275
|
-
"results": results
|
|
276
|
-
}, status=status.HTTP_200_OK)
|
|
277
|
-
|
|
278
|
-
except Exception as e:
|
|
279
|
-
return Response({"results": str(e), details: "Fehler bei der Bewertung der Voraussetzung"}, status=status.HTTP_400_BAD_REQUEST)
|
|
@@ -13,6 +13,7 @@ from rest_framework.response import Response
|
|
|
13
13
|
from endoreg_db.services import lookup_service as ls
|
|
14
14
|
from endoreg_db.services.lookup_store import DEFAULT_TTL_SECONDS, LookupStore
|
|
15
15
|
from endoreg_db.utils.permissions import EnvironmentAwarePermission
|
|
16
|
+
from endoreg_db.models.other.tag import Tag
|
|
16
17
|
|
|
17
18
|
ORIGIN_MAP_PREFIX = "lookup:origin:"
|
|
18
19
|
ISSUED_MAP_PREFIX = "lookup:issued_for_internal:"
|
|
@@ -53,6 +54,8 @@ class LookupViewSet(viewsets.ViewSet):
|
|
|
53
54
|
"selectedRequirementSetIds",
|
|
54
55
|
"selectedChoices",
|
|
55
56
|
}
|
|
57
|
+
|
|
58
|
+
user_tags = Tag
|
|
56
59
|
|
|
57
60
|
@action(detail=False, methods=["post"])
|
|
58
61
|
def init(self, request):
|
|
@@ -131,7 +134,10 @@ class LookupViewSet(viewsets.ViewSet):
|
|
|
131
134
|
|
|
132
135
|
except Exception:
|
|
133
136
|
pass
|
|
134
|
-
|
|
137
|
+
|
|
138
|
+
user_tags = request.data.get("user_tags", None)
|
|
139
|
+
if user_tags and not isinstance(user_tags, list):
|
|
140
|
+
user_tags = [user_tags]
|
|
135
141
|
# Fallback to query params
|
|
136
142
|
if raw_pe is None:
|
|
137
143
|
raw_pe = request.query_params.get("patient_examination_id")
|
|
@@ -167,7 +173,11 @@ class LookupViewSet(viewsets.ViewSet):
|
|
|
167
173
|
|
|
168
174
|
try:
|
|
169
175
|
# Create internal session via service (may seed its own token/cache)
|
|
170
|
-
|
|
176
|
+
service_kwargs = {}
|
|
177
|
+
if user_tags:
|
|
178
|
+
service_kwargs["user_tags"] = user_tags
|
|
179
|
+
|
|
180
|
+
internal_token = ls.create_lookup_token_for_pe(pe_id, **service_kwargs)
|
|
171
181
|
internal_data = LookupStore(token=internal_token).get_all()
|
|
172
182
|
|
|
173
183
|
issued_key = f"{ISSUED_MAP_PREFIX}{internal_token}"
|
|
@@ -254,7 +264,11 @@ class LookupViewSet(viewsets.ViewSet):
|
|
|
254
264
|
status=status.HTTP_404_NOT_FOUND,
|
|
255
265
|
)
|
|
256
266
|
|
|
257
|
-
|
|
267
|
+
# Hydrate the original token with recovered data and refresh origin TTL
|
|
268
|
+
store.set_many(new_data)
|
|
269
|
+
cache.set(f"{ORIGIN_MAP_PREFIX}{pk}", pe_id, DEFAULT_TTL_SECONDS)
|
|
270
|
+
return Response(store.get_all(), status=status.HTTP_200_OK)
|
|
271
|
+
|
|
258
272
|
|
|
259
273
|
except Exception:
|
|
260
274
|
pass
|