You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
9.2 KiB
260 lines
9.2 KiB
from fastapi import APIRouter, Depends, HTTPException, Query, status |
|
from typing import List, Optional, Dict, Any |
|
import json |
|
from datetime import datetime |
|
|
|
from core.database import get_database, DatabaseManager |
|
from models.pietanze import PietanzaCreate, PietanzaUpdate, PietanzaResponse |
|
from models.common import ErrorResponse |
|
from core.auth import get_current_user, get_current_admin_user |
|
from core.exceptions import PietanzaNotFoundError, DatabaseError |
|
|
|
router = APIRouter(prefix="/pietanze", tags=["Pietanze"]) |
|
|
|
@router.get("/", response_model=List[PietanzaResponse]) |
|
async def list_pietanze( |
|
skip: int = Query(0, ge=0, description="Numero di elementi da saltare per la paginazione"), |
|
limit: int = Query(20, ge=1, le=100, description="Numero di elementi da restituire"), |
|
search: Optional[str] = Query(None, description="Ricerca in nome e descrizione"), |
|
allergeni: Optional[str] = Query(None, description="Filtra per allergeni (separati da virgola)"), |
|
db: DatabaseManager = Depends(get_database) |
|
): |
|
"""Ottieni lista delle pietanze disponibili con filtri opzionali""" |
|
try: |
|
# Costruisci query con filtri |
|
where_conditions = [] |
|
params = [] |
|
param_count = 0 |
|
|
|
if search: |
|
param_count += 1 |
|
where_conditions.append(f"(nome ILIKE ${param_count} OR descrizione ILIKE ${param_count})") |
|
params.append(f"%{search}%") |
|
|
|
if allergeni: |
|
allergen_list = [a.strip() for a in allergeni.split(",")] |
|
param_count += 1 |
|
where_conditions.append(f"allergeni ?| ${param_count}") |
|
params.append(allergen_list) |
|
|
|
where_clause = "" |
|
if where_conditions: |
|
where_clause = "WHERE " + " AND ".join(where_conditions) |
|
|
|
# Conta il totale degli elementi |
|
count_query = f"SELECT COUNT(*) FROM pietanze {where_clause}" |
|
count_result = await db.execute_one(count_query, *params) |
|
total = count_result[0] if count_result else 0 |
|
|
|
# Ottieni elementi con paginazione |
|
param_count += 1 |
|
limit_param = param_count |
|
param_count += 1 |
|
offset_param = param_count |
|
|
|
query = f""" |
|
SELECT id, nome, descrizione, allergeni, created_at, updated_at |
|
FROM pietanze |
|
{where_clause} |
|
ORDER BY nome |
|
LIMIT ${limit_param} OFFSET ${offset_param} |
|
""" |
|
params.extend([limit, skip]) |
|
|
|
rows = await db.execute_query(query, *params) |
|
|
|
pietanze = [] |
|
for row in rows: |
|
pietanze.append(PietanzaResponse( |
|
id=row['id'], |
|
nome=row['nome'], |
|
descrizione=row['descrizione'], |
|
allergeni=row['allergeni'] or [], |
|
created_at=row['created_at'], |
|
updated_at=row['updated_at'] |
|
)) |
|
|
|
return pietanze |
|
|
|
except Exception as e: |
|
raise DatabaseError(f"Errore nel recupero delle pietanze: {str(e)}") |
|
|
|
@router.get("/{pietanza_id}", response_model=PietanzaResponse) |
|
async def get_pietanza( |
|
pietanza_id: int, |
|
db: DatabaseManager = Depends(get_database) |
|
): |
|
"""Ottieni pietanza specifica per ID""" |
|
try: |
|
query = """ |
|
SELECT id, nome, descrizione, allergeni, created_at, updated_at |
|
FROM pietanze |
|
WHERE id = $1 |
|
""" |
|
row = await db.execute_one(query, pietanza_id) |
|
|
|
if not row: |
|
raise PietanzaNotFoundError(pietanza_id) |
|
|
|
return PietanzaResponse( |
|
id=row['id'], |
|
nome=row['nome'], |
|
descrizione=row['descrizione'], |
|
allergeni=row['allergeni'] or [], |
|
created_at=row['created_at'], |
|
updated_at=row['updated_at'] |
|
) |
|
|
|
except PietanzaNotFoundError: |
|
raise |
|
except Exception as e: |
|
raise DatabaseError(f"Errore nel recupero della pietanza: {str(e)}") |
|
|
|
@router.post("/", response_model=PietanzaResponse, status_code=status.HTTP_201_CREATED) |
|
async def create_pietanza( |
|
pietanza: PietanzaCreate, |
|
current_user: Dict[str, Any] = Depends(get_current_admin_user), |
|
db: DatabaseManager = Depends(get_database) |
|
): |
|
"""Crea nuova pietanza (solo amministratori)""" |
|
try: |
|
query = """ |
|
INSERT INTO pietanze (nome, descrizione, allergeni, created_at, updated_at) |
|
VALUES ($1, $2, $3, $4, $4) |
|
RETURNING id, nome, descrizione, allergeni, created_at, updated_at |
|
""" |
|
|
|
now = datetime.utcnow() |
|
allergeni_json = json.dumps(pietanza.allergeni) if pietanza.allergeni else None |
|
|
|
row = await db.execute_one( |
|
query, |
|
pietanza.nome, |
|
pietanza.descrizione, |
|
allergeni_json, |
|
now |
|
) |
|
|
|
if not row: |
|
raise DatabaseError("Errore nella creazione della pietanza") |
|
|
|
return PietanzaResponse( |
|
id=row['id'], |
|
nome=row['nome'], |
|
descrizione=row['descrizione'], |
|
allergeni=row['allergeni'] or [], |
|
created_at=row['created_at'], |
|
updated_at=row['updated_at'] |
|
) |
|
|
|
except Exception as e: |
|
raise DatabaseError(f"Errore nella creazione della pietanza: {str(e)}") |
|
|
|
@router.put("/{pietanza_id}", response_model=PietanzaResponse) |
|
async def update_pietanza( |
|
pietanza_id: int, |
|
pietanza_update: PietanzaUpdate, |
|
current_user: Dict[str, Any] = Depends(get_current_admin_user), |
|
db: DatabaseManager = Depends(get_database) |
|
): |
|
"""Aggiorna pietanza esistente (solo amministratori)""" |
|
try: |
|
# Verifica se la pietanza esiste |
|
existing = await db.execute_one("SELECT id FROM pietanze WHERE id = $1", pietanza_id) |
|
if not existing: |
|
raise PietanzaNotFoundError(pietanza_id) |
|
|
|
# Costruisci query di aggiornamento dinamicamente |
|
update_fields = [] |
|
params = [] |
|
param_count = 0 |
|
|
|
if pietanza_update.nome is not None: |
|
param_count += 1 |
|
update_fields.append(f"nome = ${param_count}") |
|
params.append(pietanza_update.nome) |
|
|
|
if pietanza_update.descrizione is not None: |
|
param_count += 1 |
|
update_fields.append(f"descrizione = ${param_count}") |
|
params.append(pietanza_update.descrizione) |
|
|
|
if pietanza_update.allergeni is not None: |
|
param_count += 1 |
|
update_fields.append(f"allergeni = ${param_count}") |
|
params.append(json.dumps(pietanza_update.allergeni)) |
|
|
|
if not update_fields: |
|
# Nessun campo da aggiornare, restituisci pietanza corrente |
|
return await get_pietanza(pietanza_id, db) |
|
|
|
# Aggiungi updated_at e pietanza_id |
|
param_count += 1 |
|
update_fields.append(f"updated_at = ${param_count}") |
|
params.append(datetime.utcnow()) |
|
|
|
param_count += 1 |
|
params.append(pietanza_id) |
|
|
|
query = f""" |
|
UPDATE pietanze |
|
SET {', '.join(update_fields)} |
|
WHERE id = ${param_count} |
|
RETURNING id, nome, descrizione, allergeni, created_at, updated_at |
|
""" |
|
|
|
row = await db.execute_one(query, *params) |
|
|
|
return PietanzaResponse( |
|
id=row['id'], |
|
nome=row['nome'], |
|
descrizione=row['descrizione'], |
|
allergeni=row['allergeni'] or [], |
|
created_at=row['created_at'], |
|
updated_at=row['updated_at'] |
|
) |
|
|
|
except PietanzaNotFoundError: |
|
raise |
|
except Exception as e: |
|
raise DatabaseError(f"Errore nell'aggiornamento della pietanza: {str(e)}") |
|
|
|
@router.delete("/{pietanza_id}", status_code=status.HTTP_204_NO_CONTENT) |
|
async def delete_pietanza( |
|
pietanza_id: int, |
|
current_user: Dict[str, Any] = Depends(get_current_admin_user), |
|
db: DatabaseManager = Depends(get_database) |
|
): |
|
"""Elimina pietanza (solo amministratori)""" |
|
try: |
|
# Verifica se la pietanza è associata a qualche pasto usando operatori JSONB |
|
# Controlla se l'ID della pietanza (come stringa) appare come chiave in qualsiasi portata |
|
pasto_check = await db.execute_one(""" |
|
SELECT COUNT(*) |
|
FROM pasti |
|
WHERE EXISTS ( |
|
SELECT 1 |
|
FROM jsonb_each(portate) AS p |
|
WHERE jsonb_typeof(p.value) = 'object' |
|
AND p.value ? $1 |
|
) |
|
""", str(pietanza_id)) |
|
|
|
if pasto_check and pasto_check[0] > 0: |
|
raise HTTPException( |
|
status_code=status.HTTP_409_CONFLICT, |
|
detail="Impossibile eliminare la pietanza: è ancora associata a uno o più pasti" |
|
) |
|
|
|
# Elimina la pietanza e verifica se esisteva |
|
result = await db.execute_one("DELETE FROM pietanze WHERE id = $1 RETURNING id", pietanza_id) |
|
|
|
if not result: |
|
raise PietanzaNotFoundError(pietanza_id) |
|
|
|
except PietanzaNotFoundError: |
|
raise |
|
except HTTPException: |
|
raise |
|
except Exception as e: |
|
raise DatabaseError(f"Errore nell'eliminazione della pietanza: {str(e)}")
|
|
|