Files
2026-07-27 09:57:35 +08:00

283 lines
9.4 KiB
Python

from pydantic import BaseModel, Field, field_validator
class TodoCreate(BaseModel):
title: str = Field(..., min_length=1, max_length=100)
class TodoUpdate(BaseModel):
title: str | None = Field(default=None, min_length=1, max_length=100)
done: bool | None = None
class Todo(BaseModel):
id: int
title: str
done: bool = False
class UserCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=80)
phone: str = Field(..., min_length=5, max_length=20, pattern=r"^[0-9+\-\s]+$")
nickname: str | None = Field(default=None, max_length=60)
avatar: str | None = Field(default=None, max_length=300)
is_admin: bool = False
total_spent: float = Field(default=0, ge=0)
class UserUpdate(BaseModel):
name: str | None = Field(default=None, min_length=1, max_length=80)
phone: str | None = Field(default=None, min_length=5, max_length=20, pattern=r"^[0-9+\-\s]+$")
nickname: str | None = Field(default=None, max_length=60)
avatar: str | None = Field(default=None, max_length=300)
is_admin: bool | None = None
total_spent: float | None = Field(default=None, ge=0)
class User(BaseModel):
id: int
registered_at: str
name: str
phone: str | None = None
nickname: str | None = None
avatar: str | None = None
is_admin: bool = False
total_spent: float = 0
class AuthUser(BaseModel):
id: int
username: str
name: str
is_admin: bool = False
class CaptchaResponse(BaseModel):
captcha_id: str
challenge: str
expires_in: int
class LoginRequest(BaseModel):
username: str = Field(..., min_length=1, max_length=80)
password: str = Field(..., min_length=1, max_length=128)
captcha_id: str | None = Field(default=None, max_length=80)
captcha_code: str | None = Field(default=None, max_length=20)
class LoginResponse(BaseModel):
expires_in: int
user: AuthUser
requires_second_verification: bool = False
security_notice: str | None = None
class TempleCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
location: str | None = Field(default=None, max_length=160)
contact_phone: str | None = Field(default=None, max_length=30)
description: str | None = Field(default=None, max_length=500)
is_active: bool = True
class TempleUpdate(BaseModel):
name: str | None = Field(default=None, min_length=1, max_length=100)
location: str | None = Field(default=None, max_length=160)
contact_phone: str | None = Field(default=None, max_length=30)
description: str | None = Field(default=None, max_length=500)
is_active: bool | None = None
class Temple(BaseModel):
id: int
name: str
location: str | None = None
contact_phone: str | None = None
description: str | None = None
is_active: bool = True
class ProductSpec(BaseModel):
name: str = Field(..., min_length=1, max_length=80)
price: float = Field(default=0, ge=0)
stock: int = Field(default=0, ge=0)
sort_order: int = Field(default=0, ge=0)
is_chaodu: bool = False
class ProductBase(BaseModel):
name: str = Field(..., min_length=1, max_length=120)
alias: str | None = Field(default=None, max_length=80)
description: str | None = Field(default=None, max_length=500)
payment_button_name: str = Field(default="立即支付", min_length=1, max_length=30)
donation_button_name: str = Field(default="随喜", min_length=1, max_length=30)
sort_order: int = Field(default=0, ge=0)
show_participant_count: bool = False
cover_image: str | None = Field(default=None, max_length=500)
images: list[str] = Field(default_factory=list, max_length=10)
listed_at: str | None = Field(default=None, max_length=30)
sale_starts_at: str | None = Field(default=None, max_length=30)
sale_ends_at: str | None = Field(default=None, max_length=30)
delisted_at: str | None = Field(default=None, max_length=30)
show_countdown: bool = False
show_on_home: bool = False
specs: list[ProductSpec] = Field(default_factory=list)
details_html: str | None = None
share_title: str | None = Field(default=None, max_length=120)
share_description: str | None = Field(default=None, max_length=300)
share_image: str | None = Field(default=None, max_length=500)
merit_certificate_reserved: bool = False
auto_process: bool = False
is_active: bool = True
sales_count: int = Field(default=0, ge=0)
@field_validator("images")
@classmethod
def validate_images_count(cls, value: list[str]) -> list[str]:
if len(value) > 10:
raise ValueError("Product images cannot exceed 10")
return value
class ProductCreate(ProductBase):
pass
class ProductUpdate(BaseModel):
name: str | None = Field(default=None, min_length=1, max_length=120)
alias: str | None = Field(default=None, max_length=80)
description: str | None = Field(default=None, max_length=500)
payment_button_name: str | None = Field(default=None, min_length=1, max_length=30)
donation_button_name: str | None = Field(default=None, min_length=1, max_length=30)
sort_order: int | None = Field(default=None, ge=0)
show_participant_count: bool | None = None
cover_image: str | None = Field(default=None, max_length=500)
images: list[str] | None = Field(default=None, max_length=10)
listed_at: str | None = Field(default=None, max_length=30)
sale_starts_at: str | None = Field(default=None, max_length=30)
sale_ends_at: str | None = Field(default=None, max_length=30)
delisted_at: str | None = Field(default=None, max_length=30)
show_countdown: bool | None = None
show_on_home: bool | None = None
specs: list[ProductSpec] | None = None
details_html: str | None = None
share_title: str | None = Field(default=None, max_length=120)
share_description: str | None = Field(default=None, max_length=300)
share_image: str | None = Field(default=None, max_length=500)
merit_certificate_reserved: bool | None = None
auto_process: bool | None = None
is_active: bool | None = None
sales_count: int | None = Field(default=None, ge=0)
@field_validator("images")
@classmethod
def validate_images_count(cls, value: list[str] | None) -> list[str] | None:
if value is not None and len(value) > 10:
raise ValueError("Product images cannot exceed 10")
return value
class Product(BaseModel):
id: int
temple_id: int
name: str
alias: str | None = None
description: str | None = None
payment_button_name: str = "立即支付"
donation_button_name: str = "随喜"
sort_order: int = 0
show_participant_count: bool = False
cover_image: str | None = None
images: list[str] = Field(default_factory=list)
listed_at: str | None = None
sale_starts_at: str | None = None
sale_ends_at: str | None = None
delisted_at: str | None = None
show_countdown: bool = False
show_on_home: bool = False
specs: list[ProductSpec] = Field(default_factory=list)
details_html: str | None = None
share_title: str | None = None
share_description: str | None = None
share_image: str | None = None
merit_certificate_reserved: bool = False
auto_process: bool = False
is_active: bool = True
sales_count: int = 0
status: str
class UploadResponse(BaseModel):
url: str
object_key: str
class RitualServiceCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=120)
description: str | None = Field(default=None, max_length=500)
price: float = Field(default=0, ge=0)
is_active: bool = True
class RitualServiceUpdate(BaseModel):
name: str | None = Field(default=None, min_length=1, max_length=120)
description: str | None = Field(default=None, max_length=500)
price: float | None = Field(default=None, ge=0)
is_active: bool | None = None
class RitualService(BaseModel):
id: int
temple_id: int
name: str
description: str | None = None
price: float = 0
is_active: bool = True
class OrderCreate(BaseModel):
customer_name: str = Field(..., min_length=1, max_length=80)
customer_phone: str | None = Field(default=None, max_length=30)
order_type: str = Field(default="product", pattern=r"^(product|ritual)$")
item_name: str = Field(..., min_length=1, max_length=120)
amount: float = Field(default=0, ge=0)
status: str = Field(default="pending", pattern=r"^(pending|paid|completed|cancelled)$")
class OrderUpdate(BaseModel):
customer_name: str | None = Field(default=None, min_length=1, max_length=80)
customer_phone: str | None = Field(default=None, max_length=30)
order_type: str | None = Field(default=None, pattern=r"^(product|ritual)$")
item_name: str | None = Field(default=None, min_length=1, max_length=120)
amount: float | None = Field(default=None, ge=0)
status: str | None = Field(default=None, pattern=r"^(pending|paid|completed|cancelled)$")
class Order(BaseModel):
id: int
temple_id: int
customer_name: str
customer_phone: str | None = None
order_type: str
item_name: str
amount: float = 0
status: str
created_at: str
class WeChatJSAPIPayRequest(BaseModel):
order_id: int
openid: str = Field(..., min_length=1, max_length=128)
description: str | None = Field(default=None, max_length=127)
class WeChatJSAPIPayResponse(BaseModel):
appId: str
timeStamp: str
nonceStr: str
package: str
signType: str
paySign: str
out_trade_no: str
prepay_id: str