from datetime import date, datetime from decimal import Decimal from typing import Optional from pydantic import BaseModel, Field # ── Egg Collections ─────────────────────────────────────────────────────────── class EggCollectionCreate(BaseModel): date: date eggs: int = Field(ge=0) notes: Optional[str] = None class EggCollectionUpdate(BaseModel): date: Optional[date] = None eggs: Optional[int] = Field(default=None, ge=0) notes: Optional[str] = None class EggCollectionOut(BaseModel): id: int date: date eggs: int notes: Optional[str] created_at: datetime model_config = {"from_attributes": True} # ── Flock History ───────────────────────────────────────────────────────────── class FlockHistoryCreate(BaseModel): date: date chicken_count: int = Field(ge=0) notes: Optional[str] = None class FlockHistoryUpdate(BaseModel): date: Optional[date] = None chicken_count: Optional[int] = Field(default=None, ge=0) notes: Optional[str] = None class FlockHistoryOut(BaseModel): id: int date: date chicken_count: int notes: Optional[str] created_at: datetime model_config = {"from_attributes": True} # ── Feed Purchases ──────────────────────────────────────────────────────────── class FeedPurchaseCreate(BaseModel): date: date bags: Decimal = Field(gt=0, decimal_places=2) price_per_bag: Decimal = Field(gt=0, decimal_places=2) notes: Optional[str] = None class FeedPurchaseUpdate(BaseModel): date: Optional[date] = None bags: Optional[Decimal] = Field(default=None, gt=0, decimal_places=2) price_per_bag: Optional[Decimal] = Field(default=None, gt=0, decimal_places=2) notes: Optional[str] = None class FeedPurchaseOut(BaseModel): id: int date: date bags: Decimal price_per_bag: Decimal notes: Optional[str] created_at: datetime model_config = {"from_attributes": True} # ── Stats ───────────────────────────────────────────────────────────────────── class MonthlySummary(BaseModel): year: int month: int month_label: str total_eggs: int days_logged: int avg_eggs_per_day: Optional[float] flock_at_month_end: Optional[int] avg_eggs_per_hen_per_day: Optional[float] feed_cost: Optional[Decimal] cost_per_egg: Optional[Decimal] cost_per_dozen: Optional[Decimal] class DashboardStats(BaseModel): current_flock: Optional[int] total_eggs_alltime: int total_eggs_30d: int total_eggs_7d: int avg_eggs_per_day_30d: Optional[float] avg_eggs_per_hen_day_30d: Optional[float] days_tracked: int class BudgetStats(BaseModel): total_feed_cost: Optional[Decimal] total_feed_cost_30d: Optional[Decimal] total_eggs_alltime: int total_eggs_30d: int cost_per_egg: Optional[Decimal] cost_per_dozen: Optional[Decimal] cost_per_egg_30d: Optional[Decimal] cost_per_dozen_30d: Optional[Decimal]