""" Calorie entries endpoints """ from datetime import date from typing import Any, Dict, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy.orm import Session from app import models, schemas, services from app.core.deps import get_current_active_user from app.db.session import get_db router = APIRouter() @router.get("/", response_model=List[schemas.CalorieEntryWithFood]) def read_entries( db: Session = Depends(get_db), skip: int = 0, limit: int = 100, start_date: Optional[date] = None, end_date: Optional[date] = None, meal_type: Optional[str] = None, current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Retrieve calorie entries for the current user with optional filtering. """ entries = services.calorie_entry.get_multi_by_user( db, user_id=current_user.id, skip=skip, limit=limit, start_date=start_date, end_date=end_date, meal_type=meal_type, ) # Calculate calories for each entry result = [] for entry in entries: calories = entry.quantity_g / 100 * entry.food.calories_per_100g # Create a CalorieEntryWithFood object entry_with_food = schemas.CalorieEntryWithFood( id=entry.id, user_id=entry.user_id, food_id=entry.food_id, quantity_g=entry.quantity_g, meal_type=entry.meal_type, notes=entry.notes, consumed_at=entry.consumed_at, created_at=entry.created_at, updated_at=entry.updated_at, food=schemas.Food.model_validate(entry.food), calories=round(calories, 1), ) result.append(entry_with_food) return result @router.post("/", response_model=schemas.CalorieEntry) def create_entry( *, db: Session = Depends(get_db), entry_in: schemas.CalorieEntryCreate, current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Create new calorie entry. """ # Verify food exists food = services.food.get(db=db, food_id=entry_in.food_id) if not food: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Food item not found", ) entry = services.calorie_entry.create( db=db, obj_in=entry_in, user_id=current_user.id ) return entry @router.get("/daily-summary", response_model=Dict[str, Any]) def get_daily_summary( date_: date = Query(None, description="Date to get summary for, defaults to today"), db: Session = Depends(get_db), current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Get calorie summary for a specific date. Defaults to today. """ if date_ is None: date_ = date.today() summary = services.calorie_entry.get_daily_summary( db, user_id=current_user.id, date_=date_ ) return summary @router.get("/weekly-summary", response_model=List[Dict[str, Any]]) def get_weekly_summary( end_date: date = Query(None, description="End date for weekly summary, defaults to today"), db: Session = Depends(get_db), current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Get calorie summary for the last 7 days ending on the specified date. Defaults to today. """ if end_date is None: end_date = date.today() summary = services.calorie_entry.get_weekly_summary( db, user_id=current_user.id, end_date=end_date ) return summary @router.get("/{entry_id}", response_model=schemas.CalorieEntryWithFood) def read_entry( *, db: Session = Depends(get_db), entry_id: int, current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Get calorie entry by ID. """ entry = services.calorie_entry.get(db=db, entry_id=entry_id) if not entry: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Calorie entry not found", ) # Verify ownership if entry.user_id != current_user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions", ) # Calculate calories calories = entry.quantity_g / 100 * entry.food.calories_per_100g # Create a CalorieEntryWithFood object entry_with_food = schemas.CalorieEntryWithFood( id=entry.id, user_id=entry.user_id, food_id=entry.food_id, quantity_g=entry.quantity_g, meal_type=entry.meal_type, notes=entry.notes, consumed_at=entry.consumed_at, created_at=entry.created_at, updated_at=entry.updated_at, food=schemas.Food.model_validate(entry.food), calories=round(calories, 1), ) return entry_with_food @router.put("/{entry_id}", response_model=schemas.CalorieEntry) def update_entry( *, db: Session = Depends(get_db), entry_id: int, entry_in: schemas.CalorieEntryUpdate, current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Update a calorie entry. """ entry = services.calorie_entry.get(db=db, entry_id=entry_id) if not entry: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Calorie entry not found", ) # Verify ownership if entry.user_id != current_user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions", ) # Verify food exists if changing food_id if entry_in.food_id and entry_in.food_id != entry.food_id: food = services.food.get(db=db, food_id=entry_in.food_id) if not food: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Food item not found", ) entry = services.calorie_entry.update(db=db, db_obj=entry, obj_in=entry_in) return entry @router.delete("/{entry_id}", response_model=schemas.CalorieEntry) def delete_entry( *, db: Session = Depends(get_db), entry_id: int, current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Delete a calorie entry. """ entry = services.calorie_entry.get(db=db, entry_id=entry_id) if not entry: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Calorie entry not found", ) # Verify ownership if entry.user_id != current_user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions", ) entry = services.calorie_entry.delete(db=db, entry_id=entry_id) return entry