""" Pydantic models for mapping Notion Food Inventory database entries. Rationale: - Notion databases are flexible and do not enforce required fields or strict type validation beyond basic property types (text, number, select, etc.). - Pydantic is used here to enforce type safety, required/optional fields, and value constraints in Python code. - This ensures that data from Notion is validated and well-typed before use in the application. """ from pydantic import BaseModel, Field, ConfigDict from typing import Optional, List from datetime import date class FoodInventoryItem(BaseModel): """Pydantic model for a single item in the Food Inventory Notion database. This model enforces types and requirements for each Notion property: - Text fields are mapped to str - Select/multi-select fields are mapped to str or List[str] - Number fields are mapped to float - Boolean fields are mapped to bool - Date fields are mapped to date """ name: str = Field(..., description="Name of the food item (Notion: Text, required in app)") category: Optional[str] = Field(None, description="Category of the food (Notion: Select)") quantity: Optional[float] = Field(None, description="Quantity of the item (Notion: Number)") best_by_date: Optional[date] = Field(None, description="Best by/expiration date (Notion: Date)") purchase_date: Optional[date] = Field(None, description="Purchase date (Notion: Date)") opened_date: Optional[date] = Field(None, description="Opened date (Notion: Date)") freeze_date: Optional[date] = Field(None, description="Freeze date (Notion: Date)") tags: Optional[List[str]] = Field(None, description="Tags for the item (Notion: Multi-select)") prep_notes: Optional[str] = Field(None, description="Preparation notes (Notion: Text)") unit: Optional[str] = Field(None, description="Unit of measurement (Notion: Select)") fridge_zone: Optional[str] = Field(None, description="Location in fridge (Notion: Select)") temperature_sensitive: Optional[bool] = Field(None, description="Temperature sensitive (Notion: Checkbox/Boolean)") location_shelf: Optional[str] = Field(None, description="Storage location/shelf (Notion: Select)") storage_type: Optional[str] = Field(None, description="Storage type (Notion: Select)") cooked_raw_status: Optional[str] = Field(None, description="Cooking status (Notion: Select)") id: Optional[str] = Field(None, description="Unique identifier (Notion: id)") url: Optional[str] = Field(None, description="Notion page URL") # Pydantic v2 config model_config = ConfigDict(from_attributes=True) class PartialFoodInventoryItem(BaseModel): """Partial model for updating inventory items, with all fields optional.""" name: Optional[str] = Field(default=None, description="Name of the food item (Notion: Text, required in app)") category: Optional[str] = Field(default=None, description="Category of the food (Notion: Select)") quantity: Optional[float] = Field(default=None, description="Quantity of the item (Notion: Number)") best_by_date: Optional[date] = Field(default=None, description="Best by/expiration date (Notion: Date)") purchase_date: Optional[date] = Field(default=None, description="Purchase date (Notion: Date)") opened_date: Optional[date] = Field(default=None, description="Opened date (Notion: Date)") freeze_date: Optional[date] = Field(default=None, description="Freeze date (Notion: Date)") tags: Optional[List[str]] = Field(default=None, description="Tags for the item (Notion: Multi-select)") prep_notes: Optional[str] = Field(default=None, description="Preparation notes (Notion: Text)") unit: Optional[str] = Field(default=None, description="Unit of measurement (Notion: Select)") fridge_zone: Optional[str] = Field(default=None, description="Location in fridge (Notion: Select)") temperature_sensitive: Optional[bool] = Field(default=None, description="Temperature sensitive (Notion: Checkbox/Boolean)") location_shelf: Optional[str] = Field(default=None, description="Storage location/shelf (Notion: Select)") storage_type: Optional[str] = Field(default=None, description="Storage type (Notion: Select)") cooked_raw_status: Optional[str] = Field(default=None, description="Cooking status (Notion: Select)") id: Optional[str] = Field(default=None, description="Unique identifier (Notion: id)") url: Optional[str] = Field(default=None, description="Notion page URL") # Pydantic v2 config model_config = ConfigDict(from_attributes=True) class ShoppingListItem(BaseModel): """Pydantic model for a single item in the Shopping List Notion database. Fields align with the shopping tools and planning docs. This model is used for validation and for generating JSON schema to assist prompt construction. """ item_name: str = Field(..., description="Name of the item to buy (Notion: Title)") quantity: float = Field(..., description="Desired quantity (Notion: Number)") unit: str = Field(..., description="Measurement unit (pieces, lbs, gallons, etc.) (Notion: Text/Select)") store: Optional[str] = Field(None, description="Preferred store (Costco, Trader Joe's, Safeway, Whole Foods, Target) (Notion: Select)") priority: str = Field(default="Essential", description="Priority level (Essential, Nice to Have, Stock Up) (Notion: Select)") category: Optional[str] = Field(None, description="Food category (Produce, Dairy, Meat, Pantry, etc.) (Notion: Select)") estimated_price: Optional[float] = Field(None, description="Estimated price for budgeting (Notion: Number)") brand_preference: Optional[str] = Field(None, description="Preferred brand if applicable (Notion: Text)") size_package: Optional[str] = Field(None, description="Package size details (e.g., 24-pack, family size) (Notion: Text)") notes: Optional[str] = Field(None, description="Additional notes (Notion: Rich text)") recipe_source: Optional[str] = Field(None, description="Recipe or context that requires this item (Notion: Text/Relation)") status: str = Field(default="Needed", description="Current status (Needed, Purchased, Skipped) (Notion: Select)") id: Optional[str] = Field(None, description="Unique identifier (Notion: id)") url: Optional[str] = Field(None, description="Notion page URL") # Pydantic v2 config model_config = ConfigDict(from_attributes=True) class PartialShoppingListItem(BaseModel): """Partial model for updating shopping list items, with all fields optional.""" item_name: Optional[str] = Field(default=None, description="Name of the item to buy (Notion: Title)") quantity: Optional[float] = Field(default=None, description="Desired quantity (Notion: Number)") unit: Optional[str] = Field(default=None, description="Measurement unit (Notion: Text/Select)") store: Optional[str] = Field(default=None, description="Preferred store (Notion: Select)") priority: Optional[str] = Field(default=None, description="Priority level (Notion: Select)") category: Optional[str] = Field(default=None, description="Food category (Notion: Select)") estimated_price: Optional[float] = Field(default=None, description="Estimated price (Notion: Number)") brand_preference: Optional[str] = Field(default=None, description="Preferred brand (Notion: Text)") size_package: Optional[str] = Field(default=None, description="Package size (Notion: Text)") notes: Optional[str] = Field(default=None, description="Additional notes (Notion: Rich text)") recipe_source: Optional[str] = Field(default=None, description="Recipe or context (Notion: Text/Relation)") status: Optional[str] = Field(default=None, description="Current status (Notion: Select)") id: Optional[str] = Field(default=None, description="Unique identifier (Notion: id)") url: Optional[str] = Field(default=None, description="Notion page URL") # Pydantic v2 config model_config = ConfigDict(from_attributes=True)