Recipe corpus (#108): - Add _MAIN_INGREDIENT_SIGNALS to tag_inferrer.py (Chicken/Beef/Pork/Fish/Pasta/ Vegetables/Eggs/Legumes/Grains/Cheese) — infers main:* tags from ingredient names - Update browser_domains.py main_ingredient categories to use main:* tag queries instead of raw food terms; recipe_browser_fts now has full 3.19M row coverage (was ~1.2K before backfill) Bug fixes: - Fix community posts response shape (#96): add total/page/page_size fields - Fix export endpoint arg types (#92) - Fix household invite store leak (#93) - Fix receipts endpoint issues - Fix saved_recipes endpoint - Add session endpoint (app/api/endpoints/session.py) Shopping list: - Add migration 033_shopping_list.sql - Add shopping schemas (app/models/schemas/shopping.py) - Add ShoppingView.vue, ShoppingItemRow.vue, shopping.ts store Frontend: - InventoryList, RecipesView, RecipeDetailPanel polish - App.vue routing updates for shopping view Docs: - Add user-facing docs under docs/ (getting-started, user-guide, reference) - Add screenshots
60 lines
1.5 KiB
Python
60 lines
1.5 KiB
Python
"""Pydantic schemas for the shopping list endpoints."""
|
|
from __future__ import annotations
|
|
|
|
from typing import Optional
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class ShoppingItemCreate(BaseModel):
|
|
name: str = Field(..., min_length=1, max_length=200)
|
|
quantity: Optional[float] = None
|
|
unit: Optional[str] = None
|
|
category: Optional[str] = None
|
|
notes: Optional[str] = None
|
|
source: str = "manual"
|
|
recipe_id: Optional[int] = None
|
|
sort_order: int = 0
|
|
|
|
|
|
class ShoppingItemUpdate(BaseModel):
|
|
name: Optional[str] = Field(None, min_length=1, max_length=200)
|
|
quantity: Optional[float] = None
|
|
unit: Optional[str] = None
|
|
category: Optional[str] = None
|
|
checked: Optional[bool] = None
|
|
notes: Optional[str] = None
|
|
sort_order: Optional[int] = None
|
|
|
|
|
|
class GroceryLinkOut(BaseModel):
|
|
ingredient: str
|
|
retailer: str
|
|
url: str
|
|
|
|
|
|
class ShoppingItemResponse(BaseModel):
|
|
id: int
|
|
name: str
|
|
quantity: Optional[float]
|
|
unit: Optional[str]
|
|
category: Optional[str]
|
|
checked: bool
|
|
notes: Optional[str]
|
|
source: str
|
|
recipe_id: Optional[int]
|
|
sort_order: int
|
|
created_at: str
|
|
updated_at: str
|
|
grocery_links: list[GroceryLinkOut] = []
|
|
|
|
|
|
class BulkAddFromRecipeRequest(BaseModel):
|
|
recipe_id: int
|
|
include_covered: bool = False # if True, add pantry-covered items too
|
|
|
|
|
|
class ConfirmPurchaseRequest(BaseModel):
|
|
"""Move a checked item into pantry inventory."""
|
|
location: str = "pantry"
|
|
quantity: Optional[float] = None # override the list quantity
|
|
unit: Optional[str] = None
|