From b7cf022622341c5d4597532f0e7ad9cb9d217089 Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 23 Feb 2026 13:16:32 +0000 Subject: [PATCH] Refactor import_dicoms_helper to accept explicit queryset and enhance upload_dicom_case with detailed upload status reporting --- atlas/api.py | 62 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/atlas/api.py b/atlas/api.py index edf00440..b2f1c5ba 100644 --- a/atlas/api.py +++ b/atlas/api.py @@ -203,13 +203,15 @@ def uncategorised_dicoms(request): return data -def import_dicoms_helper(request, case_id: int | None = None): - if "selection" in request.POST: - dicoms = UncategorisedDicom.objects.filter( - series_instance_uid__in=request.POST.getlist("selection") - ) - else: - dicoms = UncategorisedDicom.objects.filter(user=request.user) +def import_dicoms_helper(request, case_id: int | None = None, dicoms=None): + # Allow callers to pass an explicit queryset of UncategorisedDicom objects + if dicoms is None: + if "selection" in request.POST: + dicoms = UncategorisedDicom.objects.filter( + series_instance_uid__in=request.POST.getlist("selection") + ) + else: + dicoms = UncategorisedDicom.objects.filter(user=request.user) if "order-series" in request.POST: order = request.POST["order-series"] @@ -304,7 +306,7 @@ def import_dicoms_case(request, case_id: int): return import_dicoms_helper(request, case_id=case_id) -@router.post("/upload_dicom_case/{case_id}", auth=BearerAuth(), response=List[Tuple[SeriesSchema, str]]) +@router.post("/upload_dicom_case/{case_id}", auth=BearerAuth()) def upload_dicom_case(request, case_id: int, files: List[UploadedFile] = File(...)): """Upload DICOM files and immediately import them into the given case. @@ -312,16 +314,50 @@ def upload_dicom_case(request, case_id: int, files: List[UploadedFile] = File(.. then calls the existing import helper which will create Series/SeriesImage objects and attach them to the specified case. """ + uploaded = [] + duplicate = [] + failed = [] + duplicate_series = set() + + created_ids = [] + for file in files: try: ud = UncategorisedDicom(image=file, user=request.user) ud.save() - except DuplicateDicom: - # skip duplicates - continue - # Now reuse import helper which will consume UncategorisedDicom for this user - return import_dicoms_helper(request, case_id=case_id) + uploaded.append((file.name, ud.image_blake3_hash)) + created_ids.append(ud.pk) + except DuplicateDicom as e: + duplicate.append((file.name, getattr(ud, "image_blake3_hash", None))) + + dup_obj = getattr(e, "duplicate", None) + if isinstance(dup_obj, SeriesImage): + try: + if dup_obj.series is not None: + duplicate_series.add(dup_obj.series.get_absolute_url()) + except Exception: + pass + + continue + except InvalidDicomError: + failed.append(file.name) + + # Import into the target case (consume only the uploaded UncategorisedDicom objects) + if created_ids: + try: + dicom_qs = UncategorisedDicom.objects.filter(pk__in=created_ids) + import_dicoms_helper(request, case_id=case_id, dicoms=dicom_qs) + except Exception: + # don't let import errors prevent returning upload status + logger.error("Error importing dicoms after upload", exc_info=True) + + return { + "uploaded": uploaded, + "duplicates": duplicate, + "failed": failed, + "duplicate_series": list(duplicate_series), + } @router.get("/orphan_series", auth=BearerAuth(), response=List[SeriesSchema])