from pydantic import BaseModel, EmailStr, Field, ConfigDict from typing import Optional, List from datetime import datetime # Response models class MaterialBase(BaseModel): id: int name_en: Optional[str] = None name_ru: Optional[str] = None name_ua: Optional[str] = None name_me: Optional[str] = None desc_en: Optional[str] = None desc_ru: Optional[str] = None desc_ua: Optional[str] = None desc_me: Optional[str] = None long_desc_en: Optional[str] = None long_desc_ru: Optional[str] = None long_desc_ua: Optional[str] = None long_desc_me: Optional[str] = None price_per_cm3: float available_colors: Optional[List[str]] = None is_active: bool class ServiceBase(BaseModel): id: int name_en: Optional[str] = None name_ru: Optional[str] = None name_ua: Optional[str] = None name_me: Optional[str] = None desc_en: Optional[str] = None desc_ru: Optional[str] = None desc_ua: Optional[str] = None desc_me: Optional[str] = None tech_type: Optional[str] = None is_active: bool # Management models class MaterialCreate(BaseModel): name_en: str name_ru: str name_ua: str name_me: str desc_en: str desc_ru: str desc_ua: str desc_me: str long_desc_en: Optional[str] = "" long_desc_ru: Optional[str] = "" long_desc_ua: Optional[str] = "" long_desc_me: Optional[str] = "" price_per_cm3: float available_colors: Optional[List[str]] = None is_active: bool = True class MaterialUpdate(BaseModel): name_en: Optional[str] = None name_ru: Optional[str] = None name_ua: Optional[str] = None name_me: Optional[str] = None desc_en: Optional[str] = None desc_ru: Optional[str] = None desc_ua: Optional[str] = None desc_me: Optional[str] = None long_desc_en: Optional[str] = None long_desc_ru: Optional[str] = None long_desc_ua: Optional[str] = None long_desc_me: Optional[str] = None price_per_cm3: Optional[float] = None available_colors: Optional[List[str]] = None is_active: Optional[bool] = None class ServiceCreate(BaseModel): name_en: str name_ru: str name_ua: str name_me: str desc_en: str desc_ru: str desc_ua: str desc_me: str tech_type: Optional[str] = None is_active: bool = True class ServiceUpdate(BaseModel): name_en: Optional[str] = None name_ru: Optional[str] = None name_ua: Optional[str] = None name_me: Optional[str] = None desc_en: Optional[str] = None desc_ru: Optional[str] = None desc_ua: Optional[str] = None desc_me: Optional[str] = None tech_type: Optional[str] = None is_active: Optional[bool] = None # Order creation models class OrderFileBase(BaseModel): filename: str file_size: Optional[int] class OrderCreate(BaseModel): first_name: str = Field(..., min_length=1) last_name: str = Field(..., min_length=1) phone: str = Field(..., min_length=5) email: EmailStr shipping_address: str = Field(..., min_length=10) model_link: Optional[str] = None quantity: int = Field(1, ge=1) notes: Optional[str] = None material_id: int color_name: Optional[str] = None # User models class UserCreate(BaseModel): email: EmailStr password: str = Field(..., min_length=6) first_name: Optional[str] = None last_name: Optional[str] = None phone: Optional[str] = None shipping_address: Optional[str] = None preferred_language: Optional[str] = "en" is_company: bool = False company_name: Optional[str] = None company_pib: Optional[str] = None company_address: Optional[str] = None class UserUpdate(BaseModel): first_name: Optional[str] = None last_name: Optional[str] = None phone: Optional[str] = None shipping_address: Optional[str] = None preferred_language: Optional[str] = None can_chat: Optional[bool] = None is_active: Optional[bool] = None is_company: Optional[bool] = None company_name: Optional[str] = None company_pib: Optional[str] = None company_address: Optional[str] = None class AdminUserUpdate(UserUpdate): role: Optional[str] = None password: Optional[str] = Field(None, min_length=6) class UserLogin(BaseModel): email: EmailStr password: str captcha_token: Optional[str] = None class UserResponse(BaseModel): id: int email: EmailStr first_name: Optional[str] = None last_name: Optional[str] = None phone: Optional[str] = None shipping_address: Optional[str] = None preferred_language: str = "en" role: str can_chat: bool is_active: bool is_company: bool company_name: Optional[str] = None company_pib: Optional[str] = None company_address: Optional[str] = None ip_address: Optional[str] = None created_at: datetime model_config = ConfigDict(from_attributes=True) class AdminOrderUpdate(BaseModel): status: Optional[str] = None total_price: Optional[float] = None material_id: Optional[int] = None material_name: Optional[str] = None color_name: Optional[str] = None quantity: Optional[int] = None send_notification: Optional[bool] = False fiscal_qr_url: Optional[str] = None ikof: Optional[str] = None jikr: Optional[str] = None class EstimateRequest(BaseModel): material_id: int file_sizes: List[int] # in bytes file_quantities: Optional[List[int]] = None # Possible to add density or other params later class Token(BaseModel): access_token: str token_type: str from typing import Optional, List, Any class SocialLogin(BaseModel): provider: str # 'google' token: str email: Any = None first_name: Any = None last_name: Any = None preferred_language: Any = "en" class ForgotPassword(BaseModel): email: EmailStr class ResetPassword(BaseModel): token: str new_password: str = Field(..., min_length=6) class PhotoUpdate(BaseModel): is_public: bool class OrderResponse(OrderCreate): id: int status: str total_price: Optional[float] = None estimated_price: Optional[float] = None material_name: Optional[str] = None material_price: Optional[float] = None material_id: Optional[int] = None color_name: Optional[str] = None original_params: Optional[str] = None created_at: datetime # Review fields review_text: Optional[str] = None rating: Optional[int] = 0 review_approved: bool = False model_config = ConfigDict(from_attributes=True) class OrderReview(BaseModel): rating: int = Field(..., ge=1, le=5) review_text: str = Field(..., min_length=2) class MessageCreate(BaseModel): message: str class ContactRequest(BaseModel): name: str = Field(..., min_length=1) email: EmailStr subject: str = Field(..., min_length=1) message: str = Field(..., min_length=1) class TokenVerify(BaseModel): token: str