mirror of
https://github.com/sstent/foodplanner.git
synced 2025-12-06 08:01:47 +00:00
fixing tracker food edits
This commit is contained in:
@@ -154,56 +154,60 @@ async def tracker_remove_meal(tracked_meal_id: int, db: Session = Depends(get_db
|
|||||||
|
|
||||||
@router.post("/tracker/save_template")
|
@router.post("/tracker/save_template")
|
||||||
async def tracker_save_template(request: Request, db: Session = Depends(get_db)):
|
async def tracker_save_template(request: Request, db: Session = Depends(get_db)):
|
||||||
"""Save current day's meals as a template"""
|
"""save current day's meals as a new template"""
|
||||||
try:
|
try:
|
||||||
form_data = await request.form()
|
form_data = await request.form()
|
||||||
person = form_data.get("person")
|
person = form_data.get("person")
|
||||||
date_str = form_data.get("date")
|
date_str = form_data.get("date")
|
||||||
template_name = form_data.get("template_name")
|
template_name = form_data.get("template_name")
|
||||||
|
|
||||||
logging.info(f"DEBUG: Saving template - name={template_name}, person={person}, date={date_str}")
|
if not all([person, date_str, template_name]):
|
||||||
|
raise HTTPException(status_code=400, detail="Missing required form data.")
|
||||||
|
|
||||||
# Parse date
|
logging.info(f"debug: saving template - name={template_name}, person={person}, date={date_str}")
|
||||||
|
|
||||||
|
# 1. Check if template name already exists
|
||||||
|
existing_template = db.query(Template).filter(Template.name == template_name).first()
|
||||||
|
if existing_template:
|
||||||
|
return {"status": "error", "message": f"Template name '{template_name}' already exists."}
|
||||||
|
|
||||||
|
# 2. Find the tracked day and its meals
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
date = datetime.fromisoformat(date_str).date()
|
target_date = datetime.fromisoformat(date_str).date()
|
||||||
|
|
||||||
# Get tracked day and meals
|
|
||||||
tracked_day = db.query(TrackedDay).filter(
|
tracked_day = db.query(TrackedDay).filter(
|
||||||
TrackedDay.person == person,
|
TrackedDay.person == person, TrackedDay.date == target_date
|
||||||
TrackedDay.date == date
|
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
if not tracked_day:
|
if not tracked_day:
|
||||||
return {"status": "error", "message": "No tracked day found"}
|
return {"status": "error", "message": "Tracked day not found for the given person and date."}
|
||||||
|
|
||||||
tracked_meals = db.query(TrackedMeal).filter(
|
tracked_meals = db.query(TrackedMeal).filter(TrackedMeal.tracked_day_id == tracked_day.id).all()
|
||||||
TrackedMeal.tracked_day_id == tracked_day.id
|
|
||||||
).all()
|
|
||||||
|
|
||||||
if not tracked_meals:
|
if not tracked_meals:
|
||||||
return {"status": "error", "message": "No meals to save as template"}
|
return {"status": "error", "message": "No meals found on this day to save as a template."}
|
||||||
|
|
||||||
# Create template
|
# 3. Create the new template
|
||||||
template = Template(name=template_name)
|
new_template = Template(name=template_name)
|
||||||
db.add(template)
|
db.add(new_template)
|
||||||
db.flush()
|
db.flush() # Use flush to get the new_template.id before commit
|
||||||
|
|
||||||
# Add template meals
|
# 4. Create template_meal entries for each tracked meal
|
||||||
for tracked_meal in tracked_meals:
|
for meal in tracked_meals:
|
||||||
template_meal = TemplateMeal(
|
template_meal_entry = TemplateMeal(
|
||||||
template_id=template.id,
|
template_id=new_template.id,
|
||||||
meal_id=tracked_meal.meal_id,
|
meal_id=meal.meal_id,
|
||||||
meal_time=tracked_meal.meal_time
|
meal_time=meal.meal_time
|
||||||
)
|
)
|
||||||
db.add(template_meal)
|
db.add(template_meal_entry)
|
||||||
db.commit()
|
|
||||||
|
|
||||||
logging.info(f"DEBUG: Successfully saved template with {len(tracked_meals)} meals")
|
db.commit()
|
||||||
return {"status": "success"}
|
logging.info(f"debug: successfully saved template '{template_name}' with {len(tracked_meals)} meals.")
|
||||||
|
return {"status": "success", "message": "Template saved successfully."}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
db.rollback()
|
db.rollback()
|
||||||
logging.error(f"DEBUG: Error saving template: {e}")
|
logging.error(f"debug: error saving template: {e}")
|
||||||
return {"status": "error", "message": str(e)}
|
return {"status": "error", "message": str(e)}
|
||||||
|
|
||||||
@router.post("/tracker/apply_template")
|
@router.post("/tracker/apply_template")
|
||||||
|
|||||||
@@ -456,3 +456,23 @@ def calculate_day_nutrition_tracked(tracked_meals, db: Session):
|
|||||||
day_totals['net_carbs'] = 0
|
day_totals['net_carbs'] = 0
|
||||||
|
|
||||||
return day_totals
|
return day_totals
|
||||||
|
|
||||||
|
|
||||||
|
def convert_grams_to_quantity(food_id: int, grams: float, db: Session) -> float:
|
||||||
|
"""
|
||||||
|
Converts a given amount in grams to the corresponding quantity multiplier
|
||||||
|
based on the food's serving size.
|
||||||
|
"""
|
||||||
|
food = db.query(Food).filter(Food.id == food_id).first()
|
||||||
|
if not food:
|
||||||
|
raise ValueError(f"Food with ID {food_id} not found.")
|
||||||
|
|
||||||
|
try:
|
||||||
|
serving_size_value = float(food.serving_size)
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError(f"Invalid serving size '{food.serving_size}' for food ID {food_id}. Must be a number.")
|
||||||
|
|
||||||
|
if serving_size_value == 0:
|
||||||
|
raise ValueError(f"Serving size for food ID {food_id} cannot be zero.")
|
||||||
|
|
||||||
|
return grams / serving_size_value
|
||||||
134
tests/test_save_template.py
Normal file
134
tests/test_save_template.py
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import pytest
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from datetime import date, timedelta
|
||||||
|
from app.database import TrackedDay, TrackedMeal, Meal, Food, Template, TemplateMeal
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def setup_tracker_data(db_session: Session, sample_food: Food):
|
||||||
|
"""Set up tracked day and meals for testing template saving."""
|
||||||
|
person_name = "Test Person"
|
||||||
|
today = date.today()
|
||||||
|
|
||||||
|
# Create a TrackedDay
|
||||||
|
tracked_day = TrackedDay(person=person_name, date=today)
|
||||||
|
db_session.add(tracked_day)
|
||||||
|
db_session.commit()
|
||||||
|
db_session.refresh(tracked_day)
|
||||||
|
|
||||||
|
# Create a Meal
|
||||||
|
meal = Meal(name="Test Meal", meal_type="breakfast", meal_time="08:00")
|
||||||
|
db_session.add(meal)
|
||||||
|
db_session.commit()
|
||||||
|
db_session.refresh(meal)
|
||||||
|
|
||||||
|
# Link food to meal (assuming MealFood is handled by Meal creation or omitted for simplicity here)
|
||||||
|
# For now, let's assume sample_meal already has food linked or we don't need to test food details
|
||||||
|
# If detailed food linking is needed, we'd add MealFood entries here.
|
||||||
|
|
||||||
|
# Create a TrackedMeal
|
||||||
|
tracked_meal = TrackedMeal(tracked_day_id=tracked_day.id, meal_id=meal.id, meal_time="08:00")
|
||||||
|
db_session.add(tracked_meal)
|
||||||
|
db_session.commit()
|
||||||
|
db_session.refresh(tracked_meal)
|
||||||
|
|
||||||
|
return {"person": person_name, "date": today, "tracked_day_id": tracked_day.id, "meal_id": meal.id}
|
||||||
|
|
||||||
|
def test_save_template_no_meals_found(client: TestClient, db_session: Session, setup_tracker_data: dict):
|
||||||
|
"""
|
||||||
|
Test that saving a template fails when no meals are found for the tracked day.
|
||||||
|
"""
|
||||||
|
person = setup_tracker_data["person"]
|
||||||
|
test_date = setup_tracker_data["date"]
|
||||||
|
template_name = "No Meals Template"
|
||||||
|
|
||||||
|
# Clear meals for the tracked day created by the fixture
|
||||||
|
tracked_day = db_session.query(TrackedDay).filter_by(person=person, date=test_date).first()
|
||||||
|
if tracked_day:
|
||||||
|
db_session.query(TrackedMeal).filter_by(tracked_day_id=tracked_day.id).delete()
|
||||||
|
db_session.commit()
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
"/tracker/save_template",
|
||||||
|
data={
|
||||||
|
"person": person,
|
||||||
|
"date": test_date.isoformat(),
|
||||||
|
"template_name": template_name
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
response_data = response.json()
|
||||||
|
assert response_data["status"] == "error"
|
||||||
|
assert "No meals found on this day to save as a template." in response_data["message"]
|
||||||
|
|
||||||
|
# Verify that no template was created
|
||||||
|
templates = db_session.query(Template).filter(Template.name == template_name).all()
|
||||||
|
assert len(templates) == 0
|
||||||
|
|
||||||
|
def test_save_template_success(client: TestClient, db_session: Session, setup_tracker_data: dict):
|
||||||
|
"""
|
||||||
|
Test the "Save as Template" functionality after the fix is applied.
|
||||||
|
This test is expected to pass and create a new template and template meals.
|
||||||
|
"""
|
||||||
|
person = setup_tracker_data["person"]
|
||||||
|
test_date = setup_tracker_data["date"]
|
||||||
|
template_name = "Successful Template"
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
"/tracker/save_template",
|
||||||
|
data={
|
||||||
|
"person": person,
|
||||||
|
"date": test_date.isoformat(),
|
||||||
|
"template_name": template_name
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
response_data = response.json()
|
||||||
|
assert response_data["status"] == "success"
|
||||||
|
assert response_data["message"] == "Template saved successfully."
|
||||||
|
|
||||||
|
# Verify that the template was created
|
||||||
|
new_template = db_session.query(Template).filter(Template.name == template_name).first()
|
||||||
|
assert new_template is not None
|
||||||
|
assert new_template.name == template_name
|
||||||
|
|
||||||
|
# Verify that template meals were created
|
||||||
|
template_meals = db_session.query(TemplateMeal).filter(TemplateMeal.template_id == new_template.id).all()
|
||||||
|
assert len(template_meals) > 0
|
||||||
|
assert template_meals[0].meal_id == setup_tracker_data["meal_id"]
|
||||||
|
|
||||||
|
def test_save_template_duplicate_name(client: TestClient, db_session: Session, setup_tracker_data: dict):
|
||||||
|
"""
|
||||||
|
Test saving a template with a duplicate name, expecting an error.
|
||||||
|
"""
|
||||||
|
person = setup_tracker_data["person"]
|
||||||
|
test_date = setup_tracker_data["date"]
|
||||||
|
template_name = "Duplicate Template"
|
||||||
|
|
||||||
|
# First successful save
|
||||||
|
response = client.post(
|
||||||
|
"/tracker/save_template",
|
||||||
|
data={
|
||||||
|
"person": person,
|
||||||
|
"date": test_date.isoformat(),
|
||||||
|
"template_name": template_name
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json()["status"] == "success"
|
||||||
|
|
||||||
|
# Attempt to save again with the same name
|
||||||
|
response_duplicate = client.post(
|
||||||
|
"/tracker/save_template",
|
||||||
|
data={
|
||||||
|
"person": person,
|
||||||
|
"date": test_date.isoformat(),
|
||||||
|
"template_name": template_name
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert response_duplicate.status_code == 200
|
||||||
|
response_data = response_duplicate.json()
|
||||||
|
assert response_data["status"] == "error"
|
||||||
|
assert f"Template name '{template_name}' already exists." in response_data["message"]
|
||||||
Reference in New Issue
Block a user