from pydantic import BaseModel, Field, EmailStr, field_validator, ConfigDict from typing import List, Optional from bson import ObjectId from datetime import datetime class MongoBaseModel(BaseModel): id: Optional[str] = Field( default_factory=lambda: str(ObjectId()), alias="_id") model_config = ConfigDict( populate_by_name=True, arbitrary_types_allowed=True, json_encoders={ObjectId: str} ) @field_validator('id', mode='before') @classmethod def convert_object_id_to_string(cls, v): if isinstance(v, ObjectId): return str(v) return v class Item(MongoBaseModel): name: str price: float quantity: int unit: str related_items: List[str] = [] class OrderItem(BaseModel): item_id: str quantity: int price_at_order: float @field_validator("item_id") def validate_id(cls, v): if isinstance(v, ObjectId): return str(v) return v class Order(MongoBaseModel): user_id: str items: List[OrderItem] total_amount: float payment_method: Optional[str] = None payment_status: str = "pending" order_status: str = "created" created_at: datetime = Field(default_factory=datetime.utcnow) updated_at: Optional[datetime] = None discount_applied: Optional[float] = None notes: Optional[str] = None class UserBase(BaseModel): username: str email: EmailStr full_name: str is_active: bool = True is_superuser: bool = False class UserCreate(UserBase): password: str class UserInDB(UserBase, MongoBaseModel): hashed_password: str class User(UserBase, MongoBaseModel): pass class Token(BaseModel): access_token: str token_type: str class TokenData(BaseModel): username: Optional[str] = None