schemas.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. from pydantic import BaseModel, EmailStr, Field, ConfigDict
  2. from typing import Optional, List
  3. from datetime import datetime
  4. # Response models
  5. class MaterialBase(BaseModel):
  6. id: int
  7. name_en: Optional[str] = None
  8. name_ru: Optional[str] = None
  9. name_ua: Optional[str] = None
  10. name_me: Optional[str] = None
  11. desc_en: Optional[str] = None
  12. desc_ru: Optional[str] = None
  13. desc_ua: Optional[str] = None
  14. desc_me: Optional[str] = None
  15. price_per_cm3: float
  16. is_active: bool
  17. class ServiceBase(BaseModel):
  18. id: int
  19. name_en: Optional[str] = None
  20. name_ru: Optional[str] = None
  21. name_ua: Optional[str] = None
  22. name_me: Optional[str] = None
  23. desc_en: Optional[str] = None
  24. desc_ru: Optional[str] = None
  25. desc_ua: Optional[str] = None
  26. desc_me: Optional[str] = None
  27. tech_type: Optional[str] = None
  28. is_active: bool
  29. # Management models
  30. class MaterialCreate(BaseModel):
  31. name_en: str
  32. name_ru: str
  33. name_ua: str
  34. name_me: str
  35. desc_en: str
  36. desc_ru: str
  37. desc_ua: str
  38. desc_me: str
  39. price_per_cm3: float
  40. is_active: bool = True
  41. class MaterialUpdate(BaseModel):
  42. name_en: Optional[str] = None
  43. name_ru: Optional[str] = None
  44. name_ua: Optional[str] = None
  45. name_me: Optional[str] = None
  46. desc_en: Optional[str] = None
  47. desc_ru: Optional[str] = None
  48. desc_ua: Optional[str] = None
  49. desc_me: Optional[str] = None
  50. price_per_cm3: Optional[float] = None
  51. is_active: Optional[bool] = None
  52. class ServiceCreate(BaseModel):
  53. name_en: str
  54. name_ru: str
  55. name_ua: str
  56. name_me: str
  57. desc_en: str
  58. desc_ru: str
  59. desc_ua: str
  60. desc_me: str
  61. tech_type: Optional[str] = None
  62. is_active: bool = True
  63. class ServiceUpdate(BaseModel):
  64. name_en: Optional[str] = None
  65. name_ru: Optional[str] = None
  66. name_ua: Optional[str] = None
  67. name_me: Optional[str] = None
  68. desc_en: Optional[str] = None
  69. desc_ru: Optional[str] = None
  70. desc_ua: Optional[str] = None
  71. desc_me: Optional[str] = None
  72. tech_type: Optional[str] = None
  73. is_active: Optional[bool] = None
  74. # Order creation models
  75. class OrderFileBase(BaseModel):
  76. filename: str
  77. file_size: Optional[int]
  78. class OrderCreate(BaseModel):
  79. first_name: str = Field(..., min_length=1)
  80. last_name: str = Field(..., min_length=1)
  81. phone: str = Field(..., min_length=5)
  82. email: EmailStr
  83. shipping_address: str = Field(..., min_length=10)
  84. model_link: Optional[str] = None
  85. quantity: int = Field(1, ge=1)
  86. notes: Optional[str] = None
  87. # User models
  88. class UserCreate(BaseModel):
  89. email: EmailStr
  90. password: str = Field(..., min_length=6)
  91. first_name: Optional[str] = None
  92. last_name: Optional[str] = None
  93. phone: Optional[str] = None
  94. shipping_address: Optional[str] = None
  95. preferred_language: Optional[str] = "en"
  96. class UserUpdate(BaseModel):
  97. first_name: Optional[str] = None
  98. last_name: Optional[str] = None
  99. phone: Optional[str] = None
  100. shipping_address: Optional[str] = None
  101. preferred_language: Optional[str] = None
  102. class UserLogin(BaseModel):
  103. email: EmailStr
  104. password: str
  105. class UserResponse(BaseModel):
  106. id: int
  107. email: EmailStr
  108. first_name: Optional[str] = None
  109. last_name: Optional[str] = None
  110. phone: Optional[str] = None
  111. shipping_address: Optional[str] = None
  112. preferred_language: str = "en"
  113. role: str
  114. ip_address: Optional[str] = None
  115. created_at: datetime
  116. model_config = ConfigDict(from_attributes=True)
  117. class AdminOrderUpdate(BaseModel):
  118. status: Optional[str] = None
  119. total_price: Optional[float] = None
  120. send_notification: Optional[bool] = False
  121. class EstimateRequest(BaseModel):
  122. material_id: int
  123. file_sizes: List[int] # in bytes
  124. file_quantities: Optional[List[int]] = None
  125. # Possible to add density or other params later
  126. class Token(BaseModel):
  127. access_token: str
  128. token_type: str
  129. class SocialLogin(BaseModel):
  130. provider: str # 'google' or 'facebook'
  131. token: str
  132. email: EmailStr
  133. first_name: Optional[str] = None
  134. last_name: Optional[str] = None
  135. preferred_language: Optional[str] = "en"
  136. class ForgotPassword(BaseModel):
  137. email: EmailStr
  138. class ResetPassword(BaseModel):
  139. token: str
  140. new_password: str = Field(..., min_length=6)
  141. class PhotoUpdate(BaseModel):
  142. is_public: bool
  143. class OrderResponse(OrderCreate):
  144. id: int
  145. status: str
  146. total_price: Optional[float] = None
  147. estimated_price: Optional[float] = None
  148. material_name: Optional[str] = None
  149. material_price: Optional[float] = None
  150. created_at: datetime
  151. model_config = ConfigDict(from_attributes=True)
  152. class MessageCreate(BaseModel):
  153. message: str