From 07ddec792c4f29cc7f51d4a1553b8a0e09d2e779 Mon Sep 17 00:00:00 2001 From: Peter Woolery Date: Wed, 6 May 2026 06:33:55 -0700 Subject: [PATCH] feat: seed 30 starter recipes spanning chicken/beef/pork/fish/vegetarian --- backend/alembic/versions/0007_seed_recipes.py | 721 +++++++++++++++++- 1 file changed, 717 insertions(+), 4 deletions(-) diff --git a/backend/alembic/versions/0007_seed_recipes.py b/backend/alembic/versions/0007_seed_recipes.py index 622c4b4..0cd83fd 100644 --- a/backend/alembic/versions/0007_seed_recipes.py +++ b/backend/alembic/versions/0007_seed_recipes.py @@ -4,6 +4,7 @@ Revision ID: 0007 Revises: 0006 Create Date: 2026-05-05 """ +import json from decimal import Decimal from alembic import op @@ -106,14 +107,726 @@ def _upsert_ingredients() -> None: ) +# 30 starter recipes. Each entry: +# (name, prep_min, cook_min, servings, cuisine_tags, dietary_tags, +# protein_type, calories_per_serving, +# ingredients [(canonical_name, qty, unit), ...], +# instructions [str, ...]) +RECIPES = [ + # ---------- Chicken (8) ---------- + ( + "Sheet-Pan Chicken Thighs with Roasted Vegetables", + 10, 30, 4, ["american"], [], "chicken", 520, + [ + ("Chicken Thighs, Boneless Skinless", 2.0, "lb"), + ("Olive Oil", 2.0, "tbsp"), + ("Broccoli", 1.0, "lb"), + ("Sweet Potato", 2.0, "ea"), + ("Salt, Kosher", 1.0, "tsp"), + ("Black Pepper", 0.5, "tsp"), + ], + [ + "Preheat oven to 425F.", + "Toss chicken and vegetables with olive oil, salt, and pepper on a sheet pan.", + "Roast 30 minutes until chicken reads 165F internal.", + "Rest 5 minutes before serving.", + ], + ), + ( + "Chicken Tikka Masala", + 15, 25, 4, ["indian"], [], "chicken", 610, + [ + ("Chicken Breast, Boneless Skinless", 1.5, "lb"), + ("Greek Yogurt, Plain", 0.5, "cup"), + ("Curry Powder", 2.0, "tsp"), + ("Diced Tomatoes, Canned", 1.0, "can"), + ("Coconut Milk, Canned", 1.0, "can"), + ("Garlic", 3.0, "clove"), + ("Ginger, Fresh", 1.0, "tbsp"), + ("Yellow Onion", 1.0, "ea"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Marinate diced chicken in yogurt and curry powder 10 minutes.", + "Saute onion, garlic, and ginger until soft.", + "Add chicken; brown 5 minutes.", + "Stir in tomatoes and coconut milk; simmer 15 minutes.", + "Season with salt; serve over rice.", + ], + ), + ( + "Lemon Garlic Chicken Piccata", + 10, 20, 4, ["italian"], [], "chicken", 480, + [ + ("Chicken Breast, Boneless Skinless", 1.5, "lb"), + ("Butter, Unsalted", 3.0, "tbsp"), + ("Garlic", 3.0, "clove"), + ("Lemon", 2.0, "ea"), + ("Chicken Broth", 1.0, "cup"), + ("Parsley, Italian", 0.25, "bunch"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Pound chicken to even thickness; season with salt.", + "Sear in butter 4 minutes per side; remove.", + "Add garlic, lemon juice, and broth to pan; reduce 5 minutes.", + "Return chicken to pan; spoon sauce over.", + "Garnish with parsley.", + ], + ), + ( + "Thai Basil Chicken Stir-Fry", + 10, 12, 4, ["thai", "asian"], [], "chicken", 460, + [ + ("Chicken Thighs, Boneless Skinless", 1.5, "lb"), + ("Soy Sauce", 3.0, "tbsp"), + ("Garlic", 4.0, "clove"), + ("Bell Pepper, Red", 1.0, "ea"), + ("Ginger, Fresh", 1.0, "tbsp"), + ("Olive Oil", 2.0, "tbsp"), + ("Rice, Long-Grain White", 1.5, "cup"), + ], + [ + "Cook rice per package directions.", + "Heat oil in wok; add garlic and ginger 30 seconds.", + "Add diced chicken; stir-fry 6 minutes.", + "Add bell pepper and soy sauce; cook 4 minutes more.", + "Serve over rice.", + ], + ), + ( + "Chicken Fajitas", + 10, 15, 4, ["mexican"], [], "chicken", 510, + [ + ("Chicken Breast, Boneless Skinless", 1.5, "lb"), + ("Bell Pepper, Red", 1.0, "ea"), + ("Bell Pepper, Green", 1.0, "ea"), + ("Yellow Onion", 1.0, "ea"), + ("Cumin, Ground", 1.5, "tsp"), + ("Paprika, Smoked", 1.0, "tsp"), + ("Olive Oil", 2.0, "tbsp"), + ("Tortilla, Flour", 8.0, "ea"), + ("Lime", 1.0, "ea"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Slice chicken and vegetables into strips.", + "Toss with cumin, paprika, salt, and oil.", + "Sear chicken in hot skillet 6 minutes; remove.", + "Cook peppers and onions 6 minutes.", + "Combine, squeeze lime, and serve in warm tortillas.", + ], + ), + ( + "Mediterranean Chicken Bowls", + 15, 20, 4, ["mediterranean"], [], "chicken", 540, + [ + ("Chicken Breast, Boneless Skinless", 1.25, "lb"), + ("Olive Oil", 2.0, "tbsp"), + ("Lemon", 1.0, "ea"), + ("Chickpeas, Canned", 1.0, "can"), + ("Spinach, Fresh", 4.0, "oz"), + ("Tomato, Roma", 2.0, "ea"), + ("Greek Yogurt, Plain", 0.5, "cup"), + ("Garlic", 2.0, "clove"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Marinate chicken in olive oil, lemon juice, garlic, and salt 10 minutes.", + "Grill or pan-sear chicken 6 minutes per side; slice.", + "Warm chickpeas in skillet 3 minutes.", + "Assemble bowls with spinach, tomato, chickpeas, chicken.", + "Top with yogurt and a lemon wedge.", + ], + ), + ( + "Honey Soy Glazed Chicken", + 10, 20, 4, ["asian"], [], "chicken", 500, + [ + ("Chicken Thighs, Boneless Skinless", 2.0, "lb"), + ("Soy Sauce", 4.0, "tbsp"), + ("Garlic", 3.0, "clove"), + ("Ginger, Fresh", 1.0, "tbsp"), + ("Rice, Long-Grain White", 1.5, "cup"), + ("Broccoli", 0.75, "lb"), + ], + [ + "Cook rice per package directions; steam broccoli.", + "Whisk soy sauce, garlic, and ginger.", + "Sear chicken 4 minutes per side.", + "Pour sauce over; simmer 6 minutes until glazed.", + "Slice and serve over rice with broccoli.", + ], + ), + ( + "Creamy Tuscan Chicken", + 10, 20, 4, ["italian"], [], "chicken", 620, + [ + ("Chicken Breast, Boneless Skinless", 1.5, "lb"), + ("Butter, Unsalted", 2.0, "tbsp"), + ("Garlic", 3.0, "clove"), + ("Spinach, Fresh", 4.0, "oz"), + ("Tomato, Roma", 2.0, "ea"), + ("Milk, Whole", 1.0, "cup"), + ("Parmesan, Grated", 4.0, "tbsp"), + ("Italian Seasoning", 1.0, "tsp"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Season chicken with salt and Italian seasoning; sear in butter 5 minutes per side.", + "Remove chicken; add garlic and tomato to pan 2 minutes.", + "Stir in milk and parmesan; simmer 4 minutes.", + "Add spinach until wilted.", + "Return chicken to sauce and serve.", + ], + ), + + # ---------- Beef (4) ---------- + ( + "Spaghetti Bolognese", + 10, 30, 4, ["italian"], [], "beef", 640, + [ + ("Ground Beef, 85/15", 1.0, "lb"), + ("Pasta, Spaghetti", 1.0, "lb"), + ("Yellow Onion", 1.0, "ea"), + ("Carrot", 2.0, "ea"), + ("Celery", 2.0, "stalk"), + ("Garlic", 3.0, "clove"), + ("Diced Tomatoes, Canned", 1.0, "can"), + ("Italian Seasoning", 1.0, "tsp"), + ("Olive Oil", 2.0, "tbsp"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Saute onion, carrot, celery, and garlic in olive oil 6 minutes.", + "Add ground beef; brown 8 minutes.", + "Stir in tomatoes and Italian seasoning; simmer 20 minutes.", + "Cook spaghetti to al dente; drain.", + "Toss pasta with sauce; season with salt.", + ], + ), + ( + "Classic Beef Tacos", + 10, 15, 4, ["mexican"], [], "beef", 560, + [ + ("Ground Beef, 85/15", 1.0, "lb"), + ("Yellow Onion", 1.0, "ea"), + ("Cumin, Ground", 1.5, "tsp"), + ("Paprika, Smoked", 1.0, "tsp"), + ("Tortilla, Corn", 8.0, "ea"), + ("Cheddar Cheese, Sharp", 4.0, "oz"), + ("Salsa, Jarred", 4.0, "tbsp"), + ("Cilantro", 0.25, "bunch"), + ("Lime", 1.0, "ea"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Brown beef and diced onion 8 minutes.", + "Add cumin, paprika, salt; cook 2 minutes more.", + "Warm tortillas in dry skillet.", + "Assemble tacos with beef, cheese, salsa, cilantro.", + "Squeeze lime over and serve.", + ], + ), + ( + "Korean-Style Beef Bowls", + 10, 12, 4, ["asian", "korean"], [], "beef", 580, + [ + ("Ground Beef, 85/15", 1.0, "lb"), + ("Soy Sauce", 4.0, "tbsp"), + ("Garlic", 3.0, "clove"), + ("Ginger, Fresh", 1.0, "tbsp"), + ("Rice, Long-Grain White", 1.5, "cup"), + ("Broccoli", 0.75, "lb"), + ], + [ + "Cook rice and steam broccoli.", + "Brown beef 5 minutes; drain excess fat.", + "Add garlic, ginger, soy sauce; simmer 4 minutes.", + "Spoon over rice with broccoli alongside.", + ], + ), + ( + "Slow-Braised Beef Stew", + 15, 120, 6, ["american"], [], "beef", 560, + [ + ("Ground Beef, 85/15", 1.5, "lb"), + ("Yellow Onion", 1.0, "ea"), + ("Carrot", 3.0, "ea"), + ("Celery", 2.0, "stalk"), + ("Sweet Potato", 2.0, "ea"), + ("Diced Tomatoes, Canned", 1.0, "can"), + ("Chicken Broth", 3.0, "cup"), + ("Olive Oil", 2.0, "tbsp"), + ("Salt, Kosher", 1.5, "tsp"), + ("Black Pepper", 0.5, "tsp"), + ], + [ + "Brown beef in olive oil; remove.", + "Saute onion, carrot, celery 6 minutes.", + "Return beef; add tomatoes, broth, sweet potato, salt, pepper.", + "Cover; simmer low 2 hours until tender.", + "Adjust seasoning and serve.", + ], + ), + + # ---------- Turkey (3) ---------- + ( + "Turkey Chili", + 10, 30, 6, ["american"], [], "turkey", 430, + [ + ("Ground Turkey", 1.25, "lb"), + ("Black Beans, Canned", 2.0, "can"), + ("Diced Tomatoes, Canned", 1.0, "can"), + ("Yellow Onion", 1.0, "ea"), + ("Bell Pepper, Red", 1.0, "ea"), + ("Cumin, Ground", 2.0, "tsp"), + ("Paprika, Smoked", 1.0, "tsp"), + ("Garlic", 3.0, "clove"), + ("Olive Oil", 2.0, "tbsp"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Saute onion, pepper, garlic in oil 6 minutes.", + "Add turkey; brown 8 minutes.", + "Stir in cumin, paprika, salt.", + "Add tomatoes and beans; simmer 20 minutes.", + "Adjust seasoning and serve.", + ], + ), + ( + "Turkey Meatballs in Marinara", + 15, 25, 4, ["italian"], [], "turkey", 540, + [ + ("Ground Turkey", 1.25, "lb"), + ("Eggs, Large", 1.0, "ea"), + ("Parmesan, Grated", 4.0, "tbsp"), + ("Italian Seasoning", 1.0, "tsp"), + ("Garlic", 3.0, "clove"), + ("Diced Tomatoes, Canned", 1.0, "can"), + ("Pasta, Spaghetti", 0.75, "lb"), + ("Olive Oil", 2.0, "tbsp"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Mix turkey, egg, parmesan, half the garlic, salt; form 16 meatballs.", + "Brown meatballs in oil 6 minutes.", + "Add remaining garlic, tomatoes, Italian seasoning; simmer 18 minutes.", + "Cook spaghetti to al dente; drain.", + "Serve meatballs and sauce over pasta.", + ], + ), + ( + "Turkey Lettuce Wraps", + 10, 12, 4, ["asian"], [], "turkey", 380, + [ + ("Ground Turkey", 1.0, "lb"), + ("Soy Sauce", 3.0, "tbsp"), + ("Garlic", 2.0, "clove"), + ("Ginger, Fresh", 1.0, "tbsp"), + ("Bell Pepper, Red", 1.0, "ea"), + ("Cilantro", 0.25, "bunch"), + ("Lime", 1.0, "ea"), + ("Olive Oil", 1.0, "tbsp"), + ], + [ + "Heat oil; saute garlic and ginger 30 seconds.", + "Add turkey; brown 6 minutes.", + "Stir in diced bell pepper and soy sauce; cook 4 minutes.", + "Spoon into lettuce leaves; top with cilantro and lime.", + ], + ), + + # ---------- Pork (3) ---------- + ( + "Pan-Seared Pork Chops with Apple Glaze", + 10, 18, 4, ["american"], [], "pork", 520, + [ + ("Pork Chops, Bone-In", 2.0, "lb"), + ("Butter, Unsalted", 2.0, "tbsp"), + ("Garlic", 2.0, "clove"), + ("Chicken Broth", 0.5, "cup"), + ("Salt, Kosher", 1.0, "tsp"), + ("Black Pepper", 0.5, "tsp"), + ], + [ + "Season chops with salt and pepper.", + "Sear in butter 5 minutes per side.", + "Add garlic and broth; simmer 4 minutes.", + "Spoon pan sauce over chops and serve.", + ], + ), + ( + "Pork Carnitas Tacos", + 15, 150, 6, ["mexican"], [], "pork", 580, + [ + ("Pork Chops, Bone-In", 2.5, "lb"), + ("Yellow Onion", 1.0, "ea"), + ("Garlic", 4.0, "clove"), + ("Cumin, Ground", 1.5, "tsp"), + ("Lime", 2.0, "ea"), + ("Tortilla, Corn", 12.0, "ea"), + ("Cilantro", 0.5, "bunch"), + ("Salt, Kosher", 1.5, "tsp"), + ("Chicken Broth", 1.0, "cup"), + ], + [ + "Cube pork; season with salt and cumin.", + "Combine pork, onion, garlic, broth, and lime juice in pot.", + "Cover; simmer 2.5 hours until shreddable.", + "Shred pork; broil 4 minutes for crispy edges.", + "Serve in warm tortillas with cilantro and lime.", + ], + ), + ( + "Pork Stir-Fry with Bell Peppers", + 10, 12, 4, ["asian"], [], "pork", 470, + [ + ("Pork Chops, Bone-In", 1.25, "lb"), + ("Bell Pepper, Red", 1.0, "ea"), + ("Bell Pepper, Green", 1.0, "ea"), + ("Soy Sauce", 3.0, "tbsp"), + ("Garlic", 3.0, "clove"), + ("Ginger, Fresh", 1.0, "tbsp"), + ("Olive Oil", 2.0, "tbsp"), + ("Rice, Long-Grain White", 1.5, "cup"), + ], + [ + "Cook rice per package directions.", + "Slice pork off bone into strips.", + "Stir-fry pork in oil 5 minutes; remove.", + "Cook peppers, garlic, ginger 4 minutes.", + "Return pork; add soy sauce; cook 2 minutes; serve over rice.", + ], + ), + + # ---------- Fish / Seafood (3) ---------- + ( + "Lemon Herb Baked Salmon", + 5, 18, 4, ["mediterranean"], [], "fish", 480, + [ + ("Salmon Fillet", 1.5, "lb"), + ("Lemon", 1.0, "ea"), + ("Olive Oil", 2.0, "tbsp"), + ("Garlic", 2.0, "clove"), + ("Parsley, Italian", 0.25, "bunch"), + ("Salt, Kosher", 1.0, "tsp"), + ("Black Pepper", 0.5, "tsp"), + ], + [ + "Preheat oven to 400F.", + "Place salmon on lined sheet; drizzle with oil and lemon juice.", + "Top with minced garlic, salt, pepper.", + "Bake 15 minutes until flaky.", + "Garnish with parsley.", + ], + ), + ( + "Garlic Shrimp Scampi", + 5, 12, 4, ["italian"], [], "fish", 520, + [ + ("Shrimp, Peeled", 1.25, "lb"), + ("Pasta, Spaghetti", 0.75, "lb"), + ("Butter, Unsalted", 3.0, "tbsp"), + ("Garlic", 4.0, "clove"), + ("Lemon", 1.0, "ea"), + ("Parsley, Italian", 0.25, "bunch"), + ("Olive Oil", 1.0, "tbsp"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Cook pasta to al dente; reserve 0.5 cup water.", + "Saute garlic in butter and oil 1 minute.", + "Add shrimp; cook 4 minutes until pink.", + "Toss with pasta, lemon juice, reserved water, salt.", + "Top with parsley.", + ], + ), + ( + "Shrimp Tacos with Cilantro Lime Slaw", + 15, 8, 4, ["mexican"], [], "fish", 460, + [ + ("Shrimp, Peeled", 1.0, "lb"), + ("Cumin, Ground", 1.0, "tsp"), + ("Paprika, Smoked", 1.0, "tsp"), + ("Olive Oil", 1.0, "tbsp"), + ("Tortilla, Corn", 8.0, "ea"), + ("Cilantro", 0.5, "bunch"), + ("Lime", 2.0, "ea"), + ("Sour Cream", 4.0, "tbsp"), + ("Avocado", 1.0, "ea"), + ("Salt, Kosher", 0.75, "tsp"), + ], + [ + "Toss shrimp with cumin, paprika, salt, oil.", + "Sear 3 minutes per side.", + "Mix cilantro and lime juice with sour cream for slaw.", + "Warm tortillas; fill with shrimp, slaw, sliced avocado.", + ], + ), + + # ---------- Vegetarian (5) ---------- + ( + "Black Bean Tacos", + 5, 10, 4, ["mexican"], ["vegetarian"], "vegetarian", 410, + [ + ("Black Beans, Canned", 2.0, "can"), + ("Cumin, Ground", 1.0, "tsp"), + ("Paprika, Smoked", 1.0, "tsp"), + ("Tortilla, Corn", 8.0, "ea"), + ("Avocado", 1.0, "ea"), + ("Salsa, Jarred", 4.0, "tbsp"), + ("Cilantro", 0.25, "bunch"), + ("Lime", 1.0, "ea"), + ("Salt, Kosher", 0.5, "tsp"), + ], + [ + "Drain beans; warm with cumin, paprika, salt 6 minutes.", + "Mash slightly with fork.", + "Warm tortillas in dry skillet.", + "Fill with beans, avocado, salsa, cilantro.", + "Squeeze lime over and serve.", + ], + ), + ( + "Chickpea Curry", + 10, 25, 4, ["indian"], ["vegetarian", "vegan"], "vegetarian", 480, + [ + ("Chickpeas, Canned", 2.0, "can"), + ("Coconut Milk, Canned", 1.0, "can"), + ("Yellow Onion", 1.0, "ea"), + ("Garlic", 3.0, "clove"), + ("Ginger, Fresh", 1.0, "tbsp"), + ("Curry Powder", 2.0, "tsp"), + ("Diced Tomatoes, Canned", 1.0, "can"), + ("Spinach, Fresh", 4.0, "oz"), + ("Rice, Long-Grain White", 1.5, "cup"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Cook rice per package directions.", + "Saute onion, garlic, ginger 5 minutes.", + "Stir in curry powder, tomatoes, coconut milk; simmer 15 minutes.", + "Add chickpeas and spinach; cook 5 minutes.", + "Season with salt; serve over rice.", + ], + ), + ( + "Caprese Pasta", + 10, 15, 4, ["italian"], ["vegetarian"], "vegetarian", 540, + [ + ("Pasta, Penne", 1.0, "lb"), + ("Tomato, Roma", 4.0, "ea"), + ("Mozzarella, Shredded", 6.0, "oz"), + ("Olive Oil", 3.0, "tbsp"), + ("Garlic", 2.0, "clove"), + ("Italian Seasoning", 1.0, "tsp"), + ("Parsley, Italian", 0.25, "bunch"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Cook penne to al dente; drain.", + "Saute garlic and diced tomato in oil 5 minutes.", + "Toss with pasta, Italian seasoning, salt.", + "Top with mozzarella; cover 2 minutes to melt.", + "Garnish with parsley.", + ], + ), + ( + "Zucchini and Spinach Frittata", + 10, 20, 4, ["mediterranean"], ["vegetarian"], "vegetarian", 360, + [ + ("Eggs, Large", 8.0, "ea"), + ("Zucchini", 1.0, "ea"), + ("Spinach, Fresh", 3.0, "oz"), + ("Yellow Onion", 0.5, "ea"), + ("Parmesan, Grated", 4.0, "tbsp"), + ("Olive Oil", 2.0, "tbsp"), + ("Salt, Kosher", 0.75, "tsp"), + ("Black Pepper", 0.25, "tsp"), + ], + [ + "Preheat oven to 375F.", + "Saute onion and zucchini in oil 5 minutes; add spinach.", + "Whisk eggs, parmesan, salt, pepper; pour over vegetables.", + "Cook 3 minutes on stovetop, then bake 12 minutes until set.", + ], + ), + ( + "Roasted Sweet Potato and Chickpea Bowl", + 10, 30, 4, ["mediterranean"], ["vegetarian", "vegan"], "vegetarian", 470, + [ + ("Sweet Potato", 3.0, "ea"), + ("Chickpeas, Canned", 1.0, "can"), + ("Olive Oil", 2.0, "tbsp"), + ("Cumin, Ground", 1.0, "tsp"), + ("Paprika, Smoked", 1.0, "tsp"), + ("Spinach, Fresh", 4.0, "oz"), + ("Greek Yogurt, Plain", 0.5, "cup"), + ("Lemon", 1.0, "ea"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Preheat oven to 425F.", + "Toss diced sweet potato and drained chickpeas with oil, cumin, paprika, salt.", + "Roast 30 minutes.", + "Whisk yogurt with lemon juice.", + "Plate over spinach; drizzle with yogurt sauce.", + ], + ), + + # ---------- Mixed / Other (4) ---------- + ( + "Veggie Fried Rice with Egg", + 10, 12, 4, ["asian"], ["vegetarian"], "vegetarian", 440, + [ + ("Rice, Long-Grain White", 2.0, "cup"), + ("Eggs, Large", 3.0, "ea"), + ("Soy Sauce", 3.0, "tbsp"), + ("Carrot", 2.0, "ea"), + ("Bell Pepper, Red", 1.0, "ea"), + ("Garlic", 2.0, "clove"), + ("Ginger, Fresh", 1.0, "tbsp"), + ("Olive Oil", 2.0, "tbsp"), + ], + [ + "Cook rice; spread on tray to cool (or use day-old rice).", + "Scramble eggs in oil; remove.", + "Stir-fry carrot, pepper, garlic, ginger 4 minutes.", + "Add rice and soy sauce; toss 4 minutes.", + "Fold eggs back in and serve.", + ], + ), + ( + "Breakfast-for-Dinner Veggie Scramble", + 5, 12, 4, ["american"], ["vegetarian"], "vegetarian", 380, + [ + ("Eggs, Large", 8.0, "ea"), + ("Bell Pepper, Green", 1.0, "ea"), + ("Tomato, Roma", 2.0, "ea"), + ("Cheddar Cheese, Sharp", 3.0, "oz"), + ("Butter, Unsalted", 2.0, "tbsp"), + ("Salt, Kosher", 0.5, "tsp"), + ("Black Pepper", 0.25, "tsp"), + ("Tortilla, Flour", 4.0, "ea"), + ], + [ + "Saute diced pepper and tomato in butter 4 minutes.", + "Whisk eggs with salt and pepper; add to pan.", + "Stir gently 4 minutes until just set.", + "Fold in cheese; serve with warm tortillas.", + ], + ), + ( + "Chicken and Rice Soup", + 10, 30, 6, ["american"], [], "chicken", 360, + [ + ("Chicken Breast, Boneless Skinless", 1.0, "lb"), + ("Chicken Broth", 6.0, "cup"), + ("Carrot", 3.0, "ea"), + ("Celery", 2.0, "stalk"), + ("Yellow Onion", 1.0, "ea"), + ("Garlic", 2.0, "clove"), + ("Rice, Long-Grain White", 0.75, "cup"), + ("Parsley, Italian", 0.25, "bunch"), + ("Olive Oil", 1.0, "tbsp"), + ("Salt, Kosher", 1.0, "tsp"), + ], + [ + "Saute onion, carrot, celery, garlic 6 minutes.", + "Add broth and chicken; simmer 15 minutes.", + "Remove chicken; shred. Add rice; cook 12 minutes.", + "Return chicken; season with salt.", + "Garnish with parsley.", + ], + ), + ( + "Loaded Veggie Quesadillas", + 10, 12, 4, ["mexican"], ["vegetarian"], "vegetarian", 520, + [ + ("Tortilla, Flour", 8.0, "ea"), + ("Cheddar Cheese, Sharp", 6.0, "oz"), + ("Black Beans, Canned", 1.0, "can"), + ("Bell Pepper, Red", 1.0, "ea"), + ("Yellow Onion", 0.5, "ea"), + ("Cumin, Ground", 0.5, "tsp"), + ("Olive Oil", 1.0, "tbsp"), + ("Salsa, Jarred", 4.0, "tbsp"), + ("Sour Cream", 4.0, "tbsp"), + ], + [ + "Saute pepper and onion in oil 5 minutes; stir in beans and cumin.", + "Layer cheese and filling on tortillas; top with second tortilla.", + "Toast in dry skillet 2 minutes per side until golden.", + "Cut into wedges; serve with salsa and sour cream.", + ], + ), +] + + def _insert_recipes() -> None: - """Populated in P4-14.""" - pass + bind = op.get_bind() + + # Build a name_lower -> id map once. + rows = bind.execute(sa.text("SELECT id, name_lower FROM ingredient")).fetchall() + name_to_id = {row.name_lower: str(row.id) for row in rows} + + for ( + name, prep, cook, servings, cuisine_tags, dietary_tags, + protein, calories, ingredients, instructions, + ) in RECIPES: + ingredient_payload = [] + for ing_name, qty, unit in ingredients: + ing_id = name_to_id.get(ing_name.lower()) + if ing_id is None: + raise RuntimeError( + f"Recipe {name!r} references unknown ingredient {ing_name!r}. " + f"Add it to INGREDIENTS or fix the name." + ) + ingredient_payload.append({ + "ingredient_id": ing_id, + "qty": float(qty), + "unit": unit, + }) + + bind.execute( + sa.text( + """ + INSERT INTO recipe ( + id, name, prep_time_minutes, cook_time_minutes, servings, + cuisine_tags, dietary_tags, protein_type, calories_per_serving, + ingredients, instructions, is_manually_added + ) + VALUES ( + gen_random_uuid(), :name, :prep, :cook, :servings, + :cuisine_tags, :dietary_tags, :protein, :calories, + CAST(:ingredients AS jsonb), :instructions, false + ) + ON CONFLICT DO NOTHING + """ + ), + { + "name": name, + "prep": prep, + "cook": cook, + "servings": servings, + "cuisine_tags": cuisine_tags, + "dietary_tags": dietary_tags, + "protein": protein, + "calories": calories, + "ingredients": json.dumps(ingredient_payload), + "instructions": instructions, + }, + ) def _delete_recipes() -> None: - """Populated in P4-14.""" - pass + bind = op.get_bind() + names = [row[0] for row in RECIPES] + bind.execute( + sa.text("DELETE FROM recipe WHERE name = ANY(:names) AND is_manually_added = false"), + {"names": names}, + ) def _delete_ingredients() -> None: