feat(backend): wire exclude_recipe_ids, verify MealPlan votes schema, add image generation service

- api/meal_plans.py: /regenerate now passes exclude_recipe_ids into generate_meal_plan
- planner/generate.py: filter recipe_dicts by exclude_recipe_ids set
- image_generation.py: OpenAI gpt-image-1 client with prompt building, b64_json handling
- main.py: StaticFiles mount at /static for generated images
- admin.py: POST /api/admin/trigger-images endpoint for batch generation
- scripts/generate_images.py: CLI for batch image generation
- docker-compose.yml + nginx: volume mounts for static/images persistence
- Verify MealPlanItem.votes ↔ MealPlanVote relationship is correct; no model bug exists
This commit is contained in:
2026-05-24 19:31:26 -07:00
parent dcdb88595e
commit ae32e650ce
17 changed files with 348 additions and 3 deletions
+1 -3
View File
@@ -92,9 +92,6 @@ def regenerate(payload: RegenerateRequest, db: Session = Depends(get_db)) -> Gen
if payload.relax_max_meal_cost is not None:
config = replace(config, max_meal_cost=payload.relax_max_meal_cost)
# exclude_recipe_ids accepted for forward-compat but not yet honored.
# See plan §Open items.
db.query(MealPlan).filter(
MealPlan.family_profile_id == payload.family_profile_id,
MealPlan.week_start_date == payload.week_start_date,
@@ -106,6 +103,7 @@ def regenerate(payload: RegenerateRequest, db: Session = Depends(get_db)) -> Gen
family_id=payload.family_profile_id,
week_start_date=payload.week_start_date,
config=config,
exclude_recipe_ids=set(payload.exclude_recipe_ids) if payload.exclude_recipe_ids else None,
)
items = (
db.query(MealPlanItem)