fixed quantitoes

This commit is contained in:
2025-09-30 18:22:34 -07:00
parent 6572cdb5a9
commit c79b42867b
7 changed files with 424 additions and 70 deletions

View File

@@ -6,7 +6,7 @@ import logging
from typing import List, Optional
# Import from the database module
from app.database import get_db, Food, Meal, MealFood
from app.database import get_db, Food, Meal, MealFood, convert_grams_to_quantity
from main import templates
router = APIRouter()
@@ -46,7 +46,8 @@ async def bulk_upload_meals(file: UploadFile = File(...), db: Session = Depends(
continue
food_name = row[i].strip()
quantity = round(float(row[i+1].strip()) / 100, 3) # Convert grams to 100g units and round to 3 decimal places
grams = float(row[i+1].strip())
quantity = convert_grams_to_quantity(food.id, grams, db)
# Try multiple matching strategies for food names
food = None
@@ -178,14 +179,18 @@ async def get_meal_foods(meal_id: int, db: Session = Depends(get_db)):
return {"status": "error", "message": str(e)}
@router.post("/meals/{meal_id}/add_food")
async def add_food_to_meal(meal_id: int, food_id: int = Form(...),
quantity: float = Form(...), db: Session = Depends(get_db)):
async def add_food_to_meal(meal_id: int, food_id: int = Form(...),
grams: float = Form(..., alias="quantity"), db: Session = Depends(get_db)):
try:
quantity = convert_grams_to_quantity(food_id, grams, db)
meal_food = MealFood(meal_id=meal_id, food_id=food_id, quantity=quantity)
db.add(meal_food)
db.commit()
return {"status": "success"}
except ValueError as ve:
db.rollback()
return {"status": "error", "message": str(ve)}
except Exception as e:
db.rollback()
return {"status": "error", "message": str(e)}
@@ -206,16 +211,20 @@ async def remove_food_from_meal(meal_food_id: int, db: Session = Depends(get_db)
return {"status": "error", "message": str(e)}
@router.post("/meals/update_food_quantity")
async def update_meal_food_quantity(meal_food_id: int = Form(...), quantity: float = Form(...), db: Session = Depends(get_db)):
async def update_meal_food_quantity(meal_food_id: int = Form(...), grams: float = Form(..., alias="quantity"), db: Session = Depends(get_db)):
"""Update the quantity of a food in a meal"""
try:
meal_food = db.query(MealFood).filter(MealFood.id == meal_food_id).first()
if not meal_food:
return {"status": "error", "message": "Meal food not found"}
quantity = convert_grams_to_quantity(meal_food.food_id, grams, db)
meal_food.quantity = quantity
db.commit()
return {"status": "success"}
except ValueError as ve:
db.rollback()
return {"status": "error", "message": str(ve)}
except Exception as e:
db.rollback()
return {"status": "error", "message": str(e)}

View File

@@ -6,7 +6,7 @@ import logging
from typing import List, Optional
# Import from the database module
from app.database import get_db, Meal, Template, TemplateMeal, TrackedDay, TrackedMeal, calculate_meal_nutrition, MealFood, TrackedMealFood, Food, calculate_day_nutrition_tracked
from app.database import get_db, Meal, Template, TemplateMeal, TrackedDay, TrackedMeal, calculate_meal_nutrition, MealFood, TrackedMealFood, Food, calculate_day_nutrition_tracked, convert_grams_to_quantity
from main import templates
router = APIRouter()
@@ -448,6 +448,93 @@ async def add_food_to_tracked_meal(data: dict = Body(...), db: Session = Depends
logging.error(f"DEBUG: Error adding food to tracked meal: {e}")
return {"status": "error", "message": str(e)}
@router.post("/tracker/update_tracked_meal_foods")
async def update_tracked_meal_foods(data: dict = Body(...), db: Session = Depends(get_db)):
"""Update quantities of multiple foods in a tracked meal"""
try:
tracked_meal_id = data.get("tracked_meal_id")
foods_data = data.get("foods", [])
tracked_meal = db.query(TrackedMeal).filter(TrackedMeal.id == tracked_meal_id).first()
if not tracked_meal:
raise HTTPException(status_code=404, detail="Tracked meal not found")
for food_data in foods_data:
food_id = food_data.get("food_id")
grams = float(food_data.get("quantity", 1.0)) # Assuming quantity is now grams
is_custom = food_data.get("is_custom", False)
item_id = food_data.get("id") # This could be MealFood.id or TrackedMealFood.id
quantity = convert_grams_to_quantity(food_id, grams, db)
if is_custom:
tracked_food = db.query(TrackedMealFood).filter(TrackedMealFood.id == item_id).first()
if tracked_food:
tracked_food.quantity = quantity
else:
# If it's a new custom food being added
new_tracked_food = TrackedMealFood(
tracked_meal_id=tracked_meal.id,
food_id=food_id,
quantity=quantity
)
db.add(new_tracked_food)
else:
# This is a food from the original meal definition
# We need to check if it's already a TrackedMealFood (meaning it was overridden)
# Or if it's still a MealFood
existing_tracked_food = db.query(TrackedMealFood).filter(
TrackedMealFood.tracked_meal_id == tracked_meal.id,
TrackedMealFood.food_id == food_id
).first()
if existing_tracked_food:
existing_tracked_food.quantity = quantity
else:
# If it's not a TrackedMealFood, it must be a MealFood
meal_food = db.query(MealFood).filter(
MealFood.meal_id == tracked_meal.meal_id,
MealFood.food_id == food_id
).first()
if meal_food:
# If quantity changed, convert to TrackedMealFood
# NOTE: meal_food.quantity is already a multiplier,
# but the incoming 'quantity' is a multiplier derived from grams.
# So, we compare the incoming multiplier with the existing multiplier.
if meal_food.quantity != quantity:
new_tracked_food = TrackedMealFood(
tracked_meal_id=tracked_meal.id,
food_id=food_id,
quantity=quantity,
is_override=True
)
db.add(new_tracked_food)
db.delete(meal_food) # Remove original MealFood
else:
# This case should ideally not happen if data is consistent,
# but as a fallback, add as a new TrackedMealFood
new_tracked_food = TrackedMealFood(
tracked_meal_id=tracked_meal.id,
food_id=food_id,
quantity=quantity
)
db.add(new_tracked_food)
# Mark the tracked day as modified
tracked_meal.tracked_day.is_modified = True
db.commit()
return {"status": "success"}
except HTTPException as he:
db.rollback()
logging.error(f"DEBUG: HTTP Error updating tracked meal foods: {he.detail}")
return {"status": "error", "message": he.detail}
except Exception as e:
db.rollback()
logging.error(f"DEBUG: Error updating tracked meal foods: {e}")
return {"status": "error", "message": str(e)}
@router.delete("/tracker/remove_food_from_tracked_meal/{meal_food_id}")
async def remove_food_from_tracked_meal(meal_food_id: int, db: Session = Depends(get_db)):
"""Remove a food from a tracked meal"""
@@ -567,10 +654,10 @@ async def tracker_add_food(data: dict = Body(...), db: Session = Depends(get_db)
person = data.get("person")
date_str = data.get("date")
food_id = data.get("food_id")
quantity = float(data.get("quantity", 1.0))
grams = float(data.get("quantity", 1.0)) # Assuming quantity is now grams
meal_time = data.get("meal_time")
logging.info(f"DEBUG: Adding single food to tracker - person={person}, date={date_str}, food_id={food_id}, quantity={quantity}, meal_time={meal_time}")
logging.info(f"DEBUG: Adding single food to tracker - person={person}, date={date_str}, food_id={food_id}, grams={grams}, meal_time={meal_time}")
# Parse date
from datetime import datetime
@@ -588,19 +675,21 @@ async def tracker_add_food(data: dict = Body(...), db: Session = Depends(get_db)
db.commit()
db.refresh(tracked_day)
# Get the food
food = db.query(Food).filter(Food.id == food_id).first()
if not food:
return {"status": "error", "message": "Food not found"}
# Get the food and convert grams to quantity multiplier
quantity = convert_grams_to_quantity(food_id, grams, db)
# Create a new Meal for this single food entry
# This allows it to be treated like any other meal in the tracker view
new_meal = Meal(name=food.name, meal_type="single_food", meal_time=meal_time)
food_item = db.query(Food).filter(Food.id == food_id).first()
if not food_item:
return {"status": "error", "message": "Food not found"}
new_meal = Meal(name=food_item.name, meal_type="single_food", meal_time=meal_time)
db.add(new_meal)
db.flush() # Flush to get the new meal ID
# Link the food to the new meal
meal_food = MealFood(meal_id=new_meal.id, food_id=food.id, quantity=quantity)
meal_food = MealFood(meal_id=new_meal.id, food_id=food_id, quantity=quantity)
db.add(meal_food)
# Create tracked meal entry
@@ -619,6 +708,10 @@ async def tracker_add_food(data: dict = Body(...), db: Session = Depends(get_db)
logging.info(f"DEBUG: Successfully added single food to tracker")
return {"status": "success"}
except ValueError as ve:
db.rollback()
logging.error(f"DEBUG: Error adding single food to tracker: {ve}")
return {"status": "error", "message": str(ve)}
except Exception as e:
db.rollback()
logging.error(f"DEBUG: Error adding single food to tracker: {e}")

View File

@@ -309,8 +309,43 @@ def get_db():
db.close()
# Utility functions
def convert_grams_to_quantity(food_id: int, grams: float, db: Session) -> float:
"""
Converts a given gram value to the quantity multiplier based on the food's serving size.
Args:
food_id: The ID of the food item.
grams: The desired weight in grams.
db: The database session.
Returns:
The quantity multiplier.
Raises:
ValueError: If the food is not found or its serving size is invalid.
"""
food = db.query(Food).filter(Food.id == food_id).first()
if not food:
raise ValueError(f"Food with ID {food_id} not found.")
try:
# Assuming serving_size is stored in grams for simplicity as per the plan
# If serving_size can be other units, more complex conversion is needed.
serving_size_value = float(food.serving_size)
except ValueError:
raise ValueError(f"Invalid serving_size '{food.serving_size}' for food ID {food_id}. Expected a numeric value.")
if serving_size_value == 0:
raise ValueError(f"Serving size for food ID {food_id} cannot be zero.")
return grams / serving_size_value
def calculate_meal_nutrition(meal, db: Session):
"""Calculate total nutrition for a meal"""
"""
Calculate total nutrition for a meal.
Quantities in MealFood are now multipliers based on the Food's serving_size,
where serving_size is assumed to be in grams.
"""
totals = {
'calories': 0, 'protein': 0, 'carbs': 0, 'fat': 0,
'fiber': 0, 'sugar': 0, 'sodium': 0, 'calcium': 0