fix(planner): correct set_size to 3 dinners and switch cost filter to per-serving

- set_size 21→3, top_k 20→10: generate 3 weekly dinners not full 3×7 matrix
- All 3 items assigned MealType.DINNER on Mon/Wed/Fri
- RecipeCost gains servings field + cost_per_serving property
- compute_recipe_cost accepts servings param (default 4)
- filter.py gates on cost_per_serving instead of total_cost
- max_meal_cost 500→50 (now a meaningful $/serving threshold)
- Email displays ~$X/serving instead of inflated raw total
- select_set: candidate_pool uses max(top_k, set_size) to prevent
  combinations(n<set_size) returning empty iterator

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-22 07:20:17 -07:00
co-authored by Claude Sonnet 4.6
parent 16069bfa92
commit 35f736a052
7 changed files with 27 additions and 13 deletions
+5 -3
View File
@@ -113,6 +113,7 @@ def generate_meal_plan(
"protein_type": r.protein_type,
"cuisine_tags": list(r.cuisine_tags or []),
"ingredients": list(r.ingredients or []),
"servings": r.servings or 4,
}
for r in recipes
]
@@ -139,6 +140,7 @@ def generate_meal_plan(
ingredients=r["ingredients"],
match_index=match_index,
pantry_ingredient_ids=pantry_ids,
servings=r["servings"],
)
for r in recipe_dicts
}
@@ -176,10 +178,10 @@ def generate_meal_plan(
db.add(plan)
db.flush()
_dinner_days = [1, 3, 5] # Mon, Wed, Fri — spread across the week
for index, scored_recipe in enumerate(chosen):
day = (index % 7) + 1 # 1..7 (Mon..Sun)
meal_type_index = index // 7 # 0=breakfast, 1=lunch, 2=dinner
meal_type = [MealType.BREAKFAST, MealType.LUNCH, MealType.DINNER][meal_type_index]
day = _dinner_days[index] if index < len(_dinner_days) else index + 1
meal_type = MealType.DINNER
item = MealPlanItem(
meal_plan_id=plan.id,
recipe_id=scored_recipe.recipe_id,