231 lines
6.7 KiB
Python
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 |