135 lines
4.9 KiB
Python
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)}"
|
|
)
|