cosmoguard-bd/src/pif_compiler/api/routes/api_esposition.py
2026-03-12 22:24:43 +01:00

135 lines
4.9 KiB
Python

from fastapi import APIRouter, HTTPException, status
from pydantic import BaseModel, Field
from typing import List, Optional
from pif_compiler.classes.models import Esposition
from pif_compiler.functions.common_log import get_logger
logger = get_logger()
router = APIRouter()
class EspositionRequest(BaseModel):
preset_name: str = Field(..., description="Nome del preset")
tipo_prodotto: str = Field(..., description="Tipo di prodotto cosmetico")
luogo_applicazione: str = Field(..., description="Luogo di applicazione")
esp_normali: List[str] = Field(..., description="Vie di esposizione normali")
esp_secondarie: List[str] = Field(..., description="Vie di esposizione secondarie")
esp_nano: List[str] = Field(..., description="Vie di esposizione nano")
sup_esposta: int = Field(..., ge=1, le=17500, description="Area di applicazione in cm2")
freq_applicazione: float = Field(default=1, description="Numero di applicazioni al giorno")
qta_giornaliera: float = Field(..., description="Quantità di prodotto applicata (g/die)")
ritenzione: float = Field(default=1.0, ge=0, le=1.0, description="Fattore di ritenzione")
class Config:
json_schema_extra = {
"example": {
"preset_name": "Crema viso leave-on",
"tipo_prodotto": "Crema",
"luogo_applicazione": "Viso",
"esp_normali": ["Dermal"],
"esp_secondarie": ["Oral", "Inhalation"],
"esp_nano": ["Dermal"],
"sup_esposta": 565,
"freq_applicazione": 2,
"qta_giornaliera": 1.54,
"ritenzione": 1.0
}
}
class EspositionResponse(BaseModel):
success: bool
data: Optional[dict] = None
error: Optional[str] = None
class EspositionListResponse(BaseModel):
success: bool
total: int
data: Optional[List[dict]] = None
error: Optional[str] = None
@router.post("/esposition/create", response_model=EspositionResponse, tags=["Esposition"])
async def create_esposition(request: EspositionRequest):
"""Crea un nuovo preset di esposizione e lo salva su PostgreSQL."""
logger.info(f"Creazione preset esposizione: {request.preset_name}")
try:
esposition = Esposition(**request.model_dump())
id_preset = esposition.save_to_postgres()
if not id_preset:
logger.warning(f"Salvataggio fallito per preset: {request.preset_name}")
return EspositionResponse(
success=False,
error=f"Errore nel salvataggio del preset '{request.preset_name}'"
)
logger.info(f"Preset '{request.preset_name}' creato con id_preset={id_preset}")
return EspositionResponse(
success=True,
data={"id_preset": id_preset, **esposition.model_dump()}
)
except Exception as e:
logger.error(f"Errore creazione preset {request.preset_name}: {str(e)}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Errore interno: {str(e)}"
)
@router.delete("/esposition/delete/{preset_name}", response_model=EspositionResponse, tags=["Esposition"])
async def delete_esposition(preset_name: str):
"""Elimina un preset di esposizione tramite il nome."""
logger.info(f"Eliminazione preset esposizione: {preset_name}")
try:
deleted = Esposition.delete_by_name(preset_name)
if not deleted:
logger.warning(f"Preset '{preset_name}' non trovato")
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Preset '{preset_name}' non trovato"
)
logger.info(f"Preset '{preset_name}' eliminato con successo")
return EspositionResponse(
success=True,
data={"preset_name": preset_name, "deleted": True}
)
except HTTPException:
raise
except Exception as e:
logger.error(f"Errore eliminazione preset {preset_name}: {str(e)}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Errore interno: {str(e)}"
)
@router.get("/esposition/presets", response_model=EspositionListResponse, tags=["Esposition"])
async def get_all_presets():
"""Recupera tutti i preset di esposizione da PostgreSQL."""
logger.info("Recupero tutti i preset di esposizione")
try:
presets = Esposition.get_presets()
logger.info(f"Recuperati {len(presets)} preset")
return EspositionListResponse(
success=True,
total=len(presets),
data=[p.model_dump() for p in presets]
)
except Exception as e:
logger.error(f"Errore recupero preset: {str(e)}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Errore interno: {str(e)}"
)