feat(backend): persist plan scores on MealPlanItem

- Migration 0012 adds score (float) and components (jsonb) to meal_plan_item
- generate.py: populates score and components at create time
- schemas/MealPlanItemResponse: include score + components fields
- GET /api/meal-plans/{id}: returns persisted values instead of zeros
This commit is contained in:
2026-05-24 20:20:11 -07:00
parent c96b41ec26
commit e22eae1ecd
5 changed files with 32 additions and 5 deletions
+3 -4
View File
@@ -125,8 +125,7 @@ def get_plan(plan_id: UUID, db: Session = Depends(get_db)) -> GenerationResponse
.order_by(MealPlanItem.day_of_week)
.all()
)
# Read-after-create: scores not stored on MealPlanItem, so we return zeros
# for score/components. The original generate response is authoritative.
# Read-after-create: scores now stored on MealPlanItem
return GenerationResponse(
meal_plan_id=plan.id,
week_start_date=plan.week_start_date,
@@ -135,8 +134,8 @@ def get_plan(plan_id: UUID, db: Session = Depends(get_db)) -> GenerationResponse
recipe_id=it.recipe_id,
day_of_week=it.day_of_week,
estimated_cost=it.estimated_cost or 0,
score=0.0,
components={},
score=it.score or 0.0,
components={k: float(v) for k, v in (it.components.items() if it.components else [])},
)
for it in items
],
+3 -1
View File
@@ -1,5 +1,5 @@
from sqlalchemy import (
Column, String, Integer, Numeric, Text, Boolean, Date, DateTime,
Column, String, Integer, Numeric, Float, Text, Boolean, Date, DateTime,
ForeignKey, CheckConstraint, UniqueConstraint, Enum as SQLEnum
)
from sqlalchemy.dialects.postgresql import UUID, JSONB, ARRAY
@@ -228,6 +228,8 @@ class MealPlanItem(Base):
denial_reason = Column(SQLEnum(DenialReason, name="denial_reason_enum", create_type=False, values_callable=lambda obj: [e.value for e in obj]))
denial_details = Column(Text)
estimated_cost = Column(Numeric(10, 2))
score = Column(Float)
components = Column(JSONB)
used_pantry_items = Column(ARRAY(UUID(as_uuid=True)))
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
+2
View File
@@ -188,6 +188,8 @@ class MealPlanItemResponse(MealPlanItemBase):
denial_reason: Optional[DenialReason] = None
denial_details: Optional[str] = None
used_pantry_items: Optional[List[UUID]] = []
score: Optional[float] = None
components: Optional[Dict[str, float]] = None
created_at: Optional[datetime] = None
updated_at: Optional[datetime] = None
recipe: Optional[RecipeResponse] = None
+2
View File
@@ -196,6 +196,8 @@ def generate_meal_plan(
meal_type=meal_type,
approval_status=MealPlanItemStatus.pending,
estimated_cost=scored_recipe.cost.total_cost,
score=scored_recipe.score,
components=scored_recipe.components,
)
db.add(item)