from __future__ import annotations from typing import Any, ClassVar, List, Optional from pydantic import Field, field_validator from common import ApiModel from products import Product from units import ALL_UNITS class Ingredient(ApiModel): KEYS: ClassVar[List[str]] = [ "id", "name", "line", "preparation", "unit", "quantity", "product_id", "recipe_id", "meal_id", ] id: int = -1 name: str line: str unit: str = Field( title="Unit", description="Measurement unit (enum values are advisory; runtime accepts any string)", json_schema_extra={"enum": [u.name for u in ALL_UNITS]}, ) quantity: float preparation: str product_id: Optional[int] = None recipe_id: Optional[int] = None meal_id: Optional[int] = None product: Optional[Product] = None # Ensure quantity is stored as a float even if provided as a string in tests @field_validator("quantity", mode="before") @classmethod def _coerce_quantity(cls, v: Any) -> Any: if isinstance(v, str): try: return float(v) except ValueError: return v return v