summaryrefslogtreecommitdiff
path: root/routers/menus.py
diff options
context:
space:
mode:
Diffstat (limited to 'routers/menus.py')
-rw-r--r--routers/menus.py138
1 files changed, 138 insertions, 0 deletions
diff --git a/routers/menus.py b/routers/menus.py
new file mode 100644
index 0000000..49c4654
--- /dev/null
+++ b/routers/menus.py
@@ -0,0 +1,138 @@
+from fastapi import APIRouter, Depends, HTTPException
+from sqlalchemy.orm import Session
+from datetime import datetime, timedelta, date
+import json
+
+from database import get_db
+from schemas import MenuPlanRead
+from models import MenuPlan, Recipe
+from services import pantry_service, ai_service
+from config import settings
+
+router = APIRouter(prefix="/api/menus", tags=["menus"])
+
+
+@router.get("/current")
+async def get_current_menu(db: Session = Depends(get_db)):
+ """Get menu plan for current week."""
+ today = datetime.utcnow().date()
+ monday = today - timedelta(days=today.weekday())
+
+ menu = db.query(MenuPlan).filter(MenuPlan.week_start == monday).first()
+ if not menu:
+ raise HTTPException(status_code=404, detail="No menu plan for current week")
+ return MenuPlanRead.from_orm(menu)
+
+
+@router.post("/generate")
+async def generate_menu(request: dict = None, db: Session = Depends(get_db)):
+ """Generate a weekly menu using AI."""
+ # Parse request body
+ week_start = None
+ if request and isinstance(request, dict):
+ week_start = request.get("week_start")
+
+ # Determine week_start date
+ if week_start:
+ try:
+ if isinstance(week_start, str):
+ week_start = datetime.fromisoformat(week_start).date()
+ else:
+ week_start = week_start
+ except Exception:
+ raise HTTPException(status_code=400, detail="Invalid week_start date")
+ else:
+ today = datetime.utcnow().date()
+ week_start = today - timedelta(days=today.weekday())
+
+ # Build pantry context and generate menu
+ try:
+ pantry_context = pantry_service.build_pantry_context(db)
+ ai_result = await ai_service.generate_weekly_menu(pantry_context)
+ except ValueError as e:
+ raise HTTPException(status_code=503, detail=str(e))
+ except (ConnectionError, Exception) as e:
+ raise HTTPException(status_code=503, detail=f"Ollama service error: {str(e)}")
+
+ # Save recipes and build plan dict
+ week_plan = ai_result.get("week_plan", {})
+ plan_dict = {}
+
+ for day, meals in week_plan.items():
+ plan_dict[day] = {}
+ for meal_type, meal_data in meals.items():
+ if isinstance(meal_data, dict) and "name" in meal_data:
+ meal_name = meal_data["name"]
+
+ # Check if recipe exists by name
+ existing_recipe = db.query(Recipe).filter(Recipe.name == meal_name).first()
+ if existing_recipe:
+ recipe_id = existing_recipe.id
+ else:
+ # Create new recipe
+ new_recipe = Recipe(
+ name=meal_name,
+ meal_type=meal_type,
+ ingredients=json.dumps(meal_data.get("ingredients", [])),
+ instructions=meal_data.get("instructions", ""),
+ estimated_time_minutes=meal_data.get("time_minutes", 30),
+ servings=meal_data.get("serves", 2),
+ source="ai",
+ )
+ db.add(new_recipe)
+ db.flush()
+ recipe_id = new_recipe.id
+
+ plan_dict[day][meal_type] = recipe_id
+
+ # Upsert MenuPlan
+ existing_plan = db.query(MenuPlan).filter(MenuPlan.week_start == week_start).first()
+ if existing_plan:
+ existing_plan.plan = json.dumps(plan_dict)
+ existing_plan.generated_at = datetime.utcnow()
+ existing_plan.model_used = settings.model_name
+ menu = existing_plan
+ else:
+ menu = MenuPlan(
+ week_start=week_start,
+ plan=json.dumps(plan_dict),
+ generated_at=datetime.utcnow(),
+ model_used=settings.model_name,
+ )
+ db.add(menu)
+
+ db.commit()
+ db.refresh(menu)
+
+ return {
+ "menu_plan": MenuPlanRead.from_orm(menu),
+ "week_plan": week_plan,
+ "notes": ai_result.get("notes", ""),
+ }
+
+
+@router.get("")
+async def list_menus(db: Session = Depends(get_db)):
+ """List all menu plans."""
+ menus = db.query(MenuPlan).order_by(MenuPlan.week_start.desc()).all()
+ return [MenuPlanRead.from_orm(m) for m in menus]
+
+
+@router.get("/{week_start}")
+async def get_menu(week_start: date, db: Session = Depends(get_db)):
+ """Get menu plan for a specific week."""
+ menu = db.query(MenuPlan).filter(MenuPlan.week_start == week_start).first()
+ if not menu:
+ raise HTTPException(status_code=404, detail="Menu plan not found")
+ return MenuPlanRead.from_orm(menu)
+
+
+@router.delete("/{id}")
+async def delete_menu(id: int, db: Session = Depends(get_db)):
+ """Delete a menu plan."""
+ menu = db.query(MenuPlan).filter(MenuPlan.id == id).first()
+ if not menu:
+ raise HTTPException(status_code=404, detail="Menu plan not found")
+ db.delete(menu)
+ db.commit()
+ return {"status": "deleted"}