2025-05-30 20:35:55 +00:00

231 lines
6.7 KiB
Python

"""
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