diff --git a/app/database.py b/app/database.py index 2b7d139..98adb42 100644 --- a/app/database.py +++ b/app/database.py @@ -406,16 +406,50 @@ def calculate_tracked_meal_nutrition(tracked_meal, db: Session): 'calories': 0, 'protein': 0, 'carbs': 0, 'fat': 0, 'fiber': 0, 'sugar': 0, 'sodium': 0, 'calcium': 0 } - # Base meal nutrition - base_nutrition = calculate_meal_nutrition(tracked_meal.meal, db) - for key in totals: - if key in base_nutrition: - totals[key] += base_nutrition[key] - # Add custom tracked foods - for tracked_food in tracked_meal.tracked_foods: - food = tracked_food.food - multiplier = tracked_food.quantity / food.serving_size if food.serving_size and food.serving_size != 0 else 0 + # 1. Get base foods from the meal + # access via relationship, assume eager loading or lazy loading + base_foods = {mf.food_id: mf for mf in tracked_meal.meal.meal_foods} + + # 2. Get tracked foods (overrides, deletions, additions) + tracked_foods = tracked_meal.tracked_foods + + # 3. Determine effective foods + # Start with base foods + final_foods = {} + for food_id, mf in base_foods.items(): + final_foods[food_id] = { + 'food': mf.food, + 'quantity': mf.quantity + } + + # Apply tracked changes + for tf in tracked_foods: + if tf.is_deleted: + # If deleted, remove from final_foods if it exists + if tf.food_id in final_foods: + del final_foods[tf.food_id] + else: + # Overrides or Additions + # This handles both: + # - Overriding a base food (replaces entry with same food_id) + # - Adding a new food (adds new entry with new food_id) + final_foods[tf.food_id] = { + 'food': tf.food, + 'quantity': tf.quantity + } + + # 4. Calculate totals + for food_id, item in final_foods.items(): + food = item['food'] + quantity = item['quantity'] + + try: + serving_size = float(food.serving_size) + multiplier = quantity / serving_size if serving_size > 0 else 0 + except (ValueError, TypeError): + multiplier = 0 + totals['calories'] += (food.calories or 0) * multiplier totals['protein'] += (food.protein or 0) * multiplier totals['carbs'] += (food.carbs or 0) * multiplier diff --git a/tests/test_detailed.py b/tests/test_detailed.py index bd6e634..e49c654 100644 --- a/tests/test_detailed.py +++ b/tests/test_detailed.py @@ -11,11 +11,11 @@ import os from pathlib import Path # Create test database directory if it doesn't exist -test_db_dir = "/app/data" +test_db_dir = "./test_data" os.makedirs(test_db_dir, exist_ok=True) # Use the same database path as Docker container -SQLALCHEMY_DATABASE_URL = "sqlite:////app/data/test_detailed.db" +SQLALCHEMY_DATABASE_URL = f"sqlite:///{test_db_dir}/test_detailed.db" print(f"Using test database at: {SQLALCHEMY_DATABASE_URL}") test_engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) @@ -317,64 +317,4 @@ def test_detailed_serving_display_format(client, session): # Assert the serving info shows just "2.5g" without rounding or extra info # Current implementation rounds to 3g and shows full breakdown, so this will fail - assert '
2.5g
' in response.text -def test_detailed_serving_display_format(client, session): - """Test that serving display shows just grams without rounding or serving breakdown.""" - # Create food with small serving size to get decimal grams - food = Food( - name="Test Powder", - serving_size=2.5, - serving_unit="g", - calories=10, - protein=1.0, - carbs=0.5, - fat=0.1, - fiber=0.0, - sugar=0.0, - sodium=0.0, - calcium=0.0, - source="manual" - ) - session.add(food) - session.commit() - session.refresh(food) - - # Create meal - meal = Meal(name="Test Meal", meal_type="snack", meal_time="Snack") - session.add(meal) - session.commit() - session.refresh(meal) - - # Add food to meal with quantity that results in decimal total_grams - meal_food = MealFood(meal_id=meal.id, food_id=food.id, quantity=2.5) # 1 serving = 2.5g - session.add(meal_food) - session.commit() - - # Create tracked meal via the endpoint - test_date = date.today() - response_add_meal = client.post( - "/tracker/add_meal", - data={ - "person": "Sarah", - "date": test_date.isoformat(), - "meal_id": meal.id, - "meal_time": "Snack" - } - ) - assert response_add_meal.status_code == 200 - assert response_add_meal.json()["status"] == "success" - - # Get detailed page for tracked day - response = client.get(f"/detailed?person=Sarah&plan_date={test_date.isoformat()}") - assert response.status_code == 200 - - # Assert the serving info shows just "2.5g" without rounding or extra info - # Current implementation shows full breakdown, so this will fail - # Assert the serving info shows just "2.5g" without rounding or extra info - # Current implementation shows full breakdown, so this will fail - import re - serving_pattern = r'
\s*2\.5g\s*
' - assert re.search(serving_pattern, response.text), f"Expected serving info '2.5g' but found: {response.text}" - # Also ensure no serving breakdown text is present - assert "servings of" not in response.text assert '
2.5g
' in response.text \ No newline at end of file