summaryrefslogtreecommitdiff
path: root/schemas.py
diff options
context:
space:
mode:
authorTyler Hoang <tyler@tylerhoang.xyz>2026-05-08 01:58:48 -0700
committerTyler Hoang <tyler@tylerhoang.xyz>2026-05-08 01:58:48 -0700
commit2e0a94e88c847a5ed8dc6ad5fa49715cd631bdfe (patch)
tree0c27fc5a8d8cbba60e571bb6690a13c0c0060ff4 /schemas.py
Initial commit — Commis personal chef app
AI-powered local chef tool: pantry tracking, meal logging, rotating weekly menu generation, and grocery list optimization via Ollama (llama3). FastAPI backend, SQLite, vanilla JS frontend. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'schemas.py')
-rw-r--r--schemas.py203
1 files changed, 203 insertions, 0 deletions
diff --git a/schemas.py b/schemas.py
new file mode 100644
index 0000000..0d16826
--- /dev/null
+++ b/schemas.py
@@ -0,0 +1,203 @@
+from pydantic import BaseModel, ConfigDict
+from datetime import datetime, date
+from typing import Optional, List, Dict
+
+
+# Ingredient Schemas
+class IngredientCreate(BaseModel):
+ name: str
+ quantity: float
+ unit: str
+ category: Optional[str] = None
+ expiry_date: Optional[date] = None
+
+
+class IngredientRead(BaseModel):
+ id: int
+ name: str
+ quantity: float
+ unit: str
+ category: Optional[str]
+ expiry_date: Optional[date]
+ added_at: datetime
+ updated_at: datetime
+
+ model_config = ConfigDict(from_attributes=True)
+
+
+class IngredientUpdate(BaseModel):
+ name: Optional[str] = None
+ quantity: Optional[float] = None
+ unit: Optional[str] = None
+ category: Optional[str] = None
+ expiry_date: Optional[date] = None
+
+
+# MealIngredient Schemas
+class MealIngredientCreate(BaseModel):
+ ingredient_name: str
+ quantity_used: Optional[float] = None
+ unit: Optional[str] = None
+
+
+class MealIngredientRead(BaseModel):
+ id: int
+ meal_log_id: int
+ ingredient_name: str
+ quantity_used: Optional[float]
+ unit: Optional[str]
+
+ model_config = ConfigDict(from_attributes=True)
+
+
+class MealIngredientUpdate(BaseModel):
+ ingredient_name: Optional[str] = None
+ quantity_used: Optional[float] = None
+ unit: Optional[str] = None
+
+
+# MealLog Schemas
+class MealLogCreate(BaseModel):
+ meal_name: str
+ meal_type: str
+ eaten_at: Optional[datetime] = None
+ notes: Optional[str] = None
+ servings: int = 1
+ ingredients: Optional[List[MealIngredientCreate]] = None
+
+
+class MealLogRead(BaseModel):
+ id: int
+ meal_name: str
+ meal_type: str
+ eaten_at: datetime
+ notes: Optional[str]
+ servings: int
+ ingredients: List[MealIngredientRead]
+
+ model_config = ConfigDict(from_attributes=True)
+
+
+class MealLogUpdate(BaseModel):
+ meal_name: Optional[str] = None
+ meal_type: Optional[str] = None
+ eaten_at: Optional[datetime] = None
+ notes: Optional[str] = None
+ servings: Optional[int] = None
+
+
+# Recipe Schemas
+class RecipeCreate(BaseModel):
+ name: str
+ meal_type: str
+ ingredients: str
+ instructions: Optional[str] = None
+ estimated_time_minutes: Optional[int] = None
+ servings: int = 2
+ source: str = "ai"
+
+
+class RecipeRead(BaseModel):
+ id: int
+ name: str
+ meal_type: str
+ ingredients: str
+ instructions: Optional[str]
+ estimated_time_minutes: Optional[int]
+ servings: int
+ source: str
+ created_at: datetime
+
+ model_config = ConfigDict(from_attributes=True)
+
+
+class RecipeUpdate(BaseModel):
+ name: Optional[str] = None
+ meal_type: Optional[str] = None
+ ingredients: Optional[str] = None
+ instructions: Optional[str] = None
+ estimated_time_minutes: Optional[int] = None
+ servings: Optional[int] = None
+ source: Optional[str] = None
+
+
+# MenuPlan Schemas
+class MenuPlanCreate(BaseModel):
+ week_start: date
+ plan: str
+ model_used: Optional[str] = None
+
+
+class MenuPlanRead(BaseModel):
+ id: int
+ week_start: date
+ plan: str
+ generated_at: datetime
+ model_used: Optional[str]
+
+ model_config = ConfigDict(from_attributes=True)
+
+
+class MenuPlanUpdate(BaseModel):
+ week_start: Optional[date] = None
+ plan: Optional[str] = None
+ model_used: Optional[str] = None
+
+
+# GroceryList Schemas
+class GroceryListCreate(BaseModel):
+ generated_for: date
+ items: str
+ total_estimate: Optional[float] = None
+ notes: Optional[str] = None
+
+
+class GroceryListRead(BaseModel):
+ id: int
+ generated_for: date
+ items: str
+ total_estimate: Optional[float]
+ generated_at: datetime
+ is_purchased: bool
+ notes: Optional[str]
+
+ model_config = ConfigDict(from_attributes=True)
+
+
+class GroceryListUpdate(BaseModel):
+ generated_for: Optional[date] = None
+ items: Optional[str] = None
+ total_estimate: Optional[float] = None
+ is_purchased: Optional[bool] = None
+ notes: Optional[str] = None
+
+
+# Complex domain schemas
+class GroceryItem(BaseModel):
+ name: str
+ quantity: float
+ unit: str
+ store_section: Optional[str] = None
+ estimated_cost: Optional[float] = None
+ used_in_meals: List[str] = []
+ reason: Optional[str] = None
+
+
+class PantryContext(BaseModel):
+ available_ingredients: List[IngredientRead] = []
+ expiring_soon: List[IngredientRead] = []
+ recent_meals: List[MealLogRead] = []
+ meal_frequency: Dict[str, int] = {}
+
+
+class WeeklyMenuSlot(BaseModel):
+ name: str
+ ingredients: List[str] = []
+ instructions: Optional[str] = None
+ time_minutes: Optional[int] = None
+
+
+class WeeklyMenuDay(BaseModel):
+ breakfast: Optional[WeeklyMenuSlot] = None
+ lunch: Optional[WeeklyMenuSlot] = None
+ dinner: Optional[WeeklyMenuSlot] = None