vision: ricetta DXF riapribile, immagine salvata, rotte source e files, soglia segue la quota (Refs #105)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jbf7qKuxsnAVjxthRy7dnB
This commit is contained in:
2026-10-25 16:25:37 +01:00
parent 711abc96df
commit 6080e6aebc
3 changed files with 365 additions and 0 deletions
+43
View File
@@ -8,6 +8,7 @@ import base64
import binascii
import io
import json
import mimetypes
from typing import Literal
from fastapi.responses import FileResponse
@@ -447,8 +448,50 @@ async def create_dxf_compare_recipe(
placed, errors = vision_service.match_recipe_files(body["graph"], uploads)
if errors:
raise _422(errors)
# #105: l'immagine di riferimento resta nella cartella (non e' in meta, quindi
# /validate e l'esecuzione la ignorano) e il wizard puo' riaprirla; entra nel digest.
placed[f"riferimento.{_IMAGE_EXTENSIONS.get(image.content_type, 'png')}"] = image_bytes
recipe_dir, check = await _store_validate_assign(task, body["graph"], placed)
await vision_service.ensure_points_quote(db, task, min_points_pct)
await db.commit()
response.update(saved=True, recipe_dir=recipe_dir, outputs=check["outputs"])
return response
@router.get("/tasks/{task_id}/recipe/dxf-compare/source")
async def get_dxf_compare_source(
task_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(require_maker),
) -> dict:
"""#105: i parametri della ricetta fatta con «Crea ricetta da DXF», per modificarla.
404 se il task non ha una ricetta del wizard (nessuna, o caricata a mano).
"""
task = await _task_or_404(db, task_id)
source = vision_service.dxf_compare_source(task.vision_json, task.vision_recipe_dir)
if source is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="nessuna ricetta da DXF su questo task",
)
return source
@router.get("/tasks/{task_id}/recipe/files/{path:path}")
async def get_recipe_file(
task_id: int,
path: str,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(require_maker),
) -> FileResponse:
"""#105: un file della cartella ricetta del task (DXF, immagine di riferimento).
Percorso non sicuro, file assente o task senza ricetta: sempre 404.
"""
task = await _task_or_404(db, task_id)
target = vision_service.recipe_file_path(task.vision_recipe_dir, path)
if target is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="file not found")
media_type = mimetypes.guess_type(target.name)[0] or "application/octet-stream"
return FileResponse(target, media_type=media_type)