122 lines
2.8 KiB
Python
122 lines
2.8 KiB
Python
import re
|
|
from datetime import datetime
|
|
from decimal import Decimal
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field, field_serializer, field_validator
|
|
|
|
|
|
def money(value: Decimal) -> str:
|
|
return f"{value.quantize(Decimal('0.01')):.2f}"
|
|
|
|
|
|
class CategoryOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
name: str
|
|
|
|
|
|
class ProductOut(BaseModel):
|
|
id: int
|
|
category_id: int
|
|
category_name: str
|
|
title: str
|
|
description: str
|
|
price: Decimal
|
|
|
|
@field_serializer("price")
|
|
def serialize_price(self, value: Decimal) -> str:
|
|
return money(value)
|
|
|
|
|
|
class CatalogOut(BaseModel):
|
|
categories: list[CategoryOut]
|
|
products: list[ProductOut]
|
|
|
|
|
|
class CartAdd(BaseModel):
|
|
product_id: int
|
|
qty: int = Field(default=1, ge=1, le=99)
|
|
|
|
|
|
class CartItemOut(BaseModel):
|
|
product_id: int
|
|
title: str
|
|
price: str
|
|
qty: int
|
|
line_total: str
|
|
|
|
|
|
class CartOut(BaseModel):
|
|
items: list[CartItemOut]
|
|
total: str
|
|
|
|
|
|
class OrderCreate(BaseModel):
|
|
customer_name: str = Field(min_length=1, max_length=120)
|
|
customer_phone: str = Field(min_length=5, max_length=32)
|
|
|
|
@field_validator("customer_name", "customer_phone", mode="before")
|
|
@classmethod
|
|
def strip_value(cls, value: object) -> object:
|
|
if isinstance(value, str):
|
|
return value.strip()
|
|
return value
|
|
|
|
@field_validator("customer_phone")
|
|
@classmethod
|
|
def check_phone(cls, value: str) -> str:
|
|
if re.fullmatch(r"[0-9+()\-\s]{5,32}", value) is None:
|
|
raise ValueError("Телефон: цифры, пробелы и символы +()-")
|
|
return value
|
|
|
|
|
|
class OrderItemOut(BaseModel):
|
|
product_id: int
|
|
title: str
|
|
price: str
|
|
qty: int
|
|
|
|
|
|
class OrderOut(BaseModel):
|
|
id: int
|
|
status: str
|
|
customer_name: str
|
|
customer_phone: str
|
|
total: str
|
|
created_at: datetime
|
|
items: list[OrderItemOut]
|
|
|
|
@field_serializer("created_at")
|
|
def serialize_created_at(self, value: datetime) -> str:
|
|
return value.isoformat()
|
|
|
|
|
|
class DialogIn(BaseModel):
|
|
step: str = Field(pattern=r"^(name|phone)$")
|
|
name: str | None = Field(default=None, max_length=120)
|
|
|
|
@field_validator("name", mode="before")
|
|
@classmethod
|
|
def strip_name(cls, value: object) -> object:
|
|
if isinstance(value, str):
|
|
stripped = value.strip()
|
|
return stripped or None
|
|
return value
|
|
|
|
|
|
class DialogOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
telegram_user_id: int
|
|
step: str
|
|
name: str | None
|
|
|
|
|
|
class BotOrderCreate(OrderCreate):
|
|
telegram_user_id: int = Field(gt=0)
|
|
|
|
|
|
class BotCartAdd(CartAdd):
|
|
telegram_user_id: int = Field(gt=0)
|