mirror of
https://git.oceanpay.cc/danial/kami_apple_exchage.git
synced 2025-12-18 21:23:49 +00:00
- 新增链接权重字段,支持1-100范围设置 - 修改轮询算法为基于权重的选择机制 - 更新链接API接口返回统一使用LinkInfo模型 - 添加更新链接权重的PATCH端点 - 调整链接仓库查询逻辑,只包含激活状态链接 - 迁移链接相关Pydantic模型到task模块统一管理 - 修改分页响应格式为通用PaginatedResponse包装 - 禁用OpenTelemetry监控配置
443 lines
15 KiB
Python
443 lines
15 KiB
Python
"""
|
|
任务相关的Pydantic模型
|
|
包含统一的用户、链接、礼品卡和分页响应模型
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
from typing import Any, Generic, List, TypeVar
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
|
|
from app.enums.task import OrderTaskStatus
|
|
from app.models.orders import OrderStatus
|
|
from app.models.giftcards import GiftCardStatus
|
|
|
|
|
|
class LinkStatus(str, Enum):
|
|
"""链接状态枚举"""
|
|
|
|
ACTIVE = "active"
|
|
INACTIVE = "inactive"
|
|
|
|
T = TypeVar("T")
|
|
|
|
|
|
class ProcessOrderRequest(BaseModel):
|
|
"""处理单个订单请求"""
|
|
|
|
order_id: str
|
|
priority: int | None = 5
|
|
|
|
|
|
class BatchProcessRequest(BaseModel):
|
|
"""批量处理订单请求"""
|
|
|
|
order_ids: list[str]
|
|
batch_size: int | None = 5
|
|
|
|
|
|
class TaskStatusResponse(BaseModel):
|
|
"""任务状态响应"""
|
|
|
|
task_id: str
|
|
status: str
|
|
progress: float
|
|
result: dict[str, Any] | None = None
|
|
error: str | None = None
|
|
|
|
|
|
class WorkerStatusResponse(BaseModel):
|
|
"""工作进程状态响应"""
|
|
|
|
worker_id: str
|
|
status: str
|
|
current_order_id: str | None = None
|
|
progress: float
|
|
start_time: str | None = None
|
|
|
|
|
|
class QueueStatsResponse(BaseModel):
|
|
"""队列统计响应"""
|
|
|
|
success: bool
|
|
stats: dict[str, Any]
|
|
timestamp: str
|
|
|
|
|
|
class TaskControlRequest(BaseModel):
|
|
"""任务控制请求模型"""
|
|
|
|
is_paused: bool = Field(..., description="是否暂停任务")
|
|
reason: str = Field("", description="控制原因")
|
|
|
|
|
|
class TaskControlResponse(BaseModel):
|
|
"""任务控制响应模型"""
|
|
|
|
success: bool = Field(..., description="操作是否成功")
|
|
is_paused: bool = Field(..., description="当前暂停状态")
|
|
reason: str = Field(..., description="控制原因")
|
|
message: str = Field(..., description="响应消息")
|
|
|
|
|
|
class TaskStateResponse(BaseModel):
|
|
"""任务状态响应模型"""
|
|
|
|
success: bool = Field(..., description="操作是否成功")
|
|
is_paused: bool = Field(..., description="当前暂停状态")
|
|
reason: str = Field(..., description="控制原因")
|
|
message: str = Field(..., description="响应消息")
|
|
|
|
|
|
class UserInfo(BaseModel):
|
|
"""统一用户信息响应模型 - 与数据库字段一致"""
|
|
|
|
id: str = Field(..., description="用户数据ID")
|
|
first_name: str = Field(..., description="名字")
|
|
last_name: str = Field(..., description="姓氏")
|
|
email: str = Field(..., description="邮箱")
|
|
phone: str = Field(..., description="电话")
|
|
street_address: str = Field(..., description="街道地址")
|
|
city: str = Field(..., description="城市")
|
|
state: str = Field(..., description="州/省")
|
|
zip_code: str = Field(..., description="邮政编码")
|
|
created_at: str = Field(description="创建时间")
|
|
updated_at: str = Field(description="更新时间")
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
|
|
|
|
class LinkInfo(BaseModel):
|
|
"""统一链接信息响应模型 - 与数据库字段一致"""
|
|
|
|
id: str = Field(..., description="链接ID")
|
|
url: str = Field(..., description="链接地址")
|
|
amount: float = Field(..., description="金额")
|
|
weight: int = Field(..., description="权重(1-100)")
|
|
status: LinkStatus = Field(..., description="链接状态")
|
|
created_at: str = Field(description="创建时间")
|
|
updated_at: str = Field(description="更新时间")
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
|
|
|
|
class CardInfo(BaseModel):
|
|
"""统一礼品卡信息响应模型 - 与数据库字段一致"""
|
|
|
|
id: str = Field(..., description="礼品卡ID")
|
|
card_code: str = Field(..., description="礼品卡号码")
|
|
card_value: float = Field(..., description="卡片面额")
|
|
status: str = Field(..., description="礼品卡状态")
|
|
failure_reason: str | None = Field(None, description="失败原因")
|
|
order_id: str = Field(..., description="关联订单ID")
|
|
created_at: str = Field(description="创建时间")
|
|
updated_at: str = Field(description="更新时间")
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
|
|
|
|
class TaskListItem(BaseModel):
|
|
"""任务列表项模型 - 包含完整的数据库字段"""
|
|
|
|
# 任务状态相关字段
|
|
task_id: str = Field(..., description="任务ID")
|
|
worker_id: str | None = Field(None, description="工作节点ID")
|
|
status: OrderTaskStatus = Field(..., description="任务状态")
|
|
progress: float = Field(..., description="进度")
|
|
created_at: str = Field(..., description="任务创建时间")
|
|
updated_at: str = Field(..., description="任务更新时间")
|
|
completed_at: str | None = Field(None, description="任务完成时间")
|
|
failed_at: str | None = Field(None, description="任务失败时间")
|
|
error_message: str | None = Field(None, description="错误信息")
|
|
|
|
# 订单数据库字段
|
|
order_id: str | None = Field(None, description="订单ID")
|
|
order_status: str | None = Field(None, description="订单状态")
|
|
final_order_url: str | None = Field(None, description="最终订单URL")
|
|
order_failure_reason: str | None = Field(None, description="订单失败原因")
|
|
order_completed_at: str | None = Field(None, description="订单完成时间")
|
|
order_created_at: str | None = Field(None, description="订单创建时间")
|
|
order_updated_at: str | None = Field(None, description="订单更新时间")
|
|
order_is_deleted: bool | None = Field(None, description="订单是否已删除")
|
|
order_deleted_at: str | None = Field(None, description="订单删除时间")
|
|
|
|
# 关联数据
|
|
user_info: UserInfo | None = Field(None, description="用户信息")
|
|
link_info: LinkInfo | None = Field(None, description="链接信息")
|
|
card_info: list[CardInfo] | None = Field(None, description="礼品卡信息列表")
|
|
|
|
|
|
class TaskListResponse(BaseModel):
|
|
"""任务列表响应模型"""
|
|
|
|
success: bool = Field(..., description="操作是否成功")
|
|
tasks: list[TaskListItem] = Field(..., description="任务列表")
|
|
total: int = Field(..., description="任务总数")
|
|
message: str = Field(..., description="响应消息")
|
|
|
|
|
|
class GiftCardRequest(BaseModel):
|
|
"""礼品卡请求模型"""
|
|
|
|
card_code: str = Field(..., description="礼品卡代码")
|
|
card_value: float = Field(..., description="礼品卡面值")
|
|
order_id: str = Field(..., description="关联订单ID")
|
|
metadata: dict[str, Any] = Field(default_factory=dict, description="额外数据")
|
|
|
|
|
|
class GiftCardResponse(BaseModel):
|
|
"""礼品卡响应模型"""
|
|
|
|
success: bool = Field(..., description="操作是否成功")
|
|
task_id: str = Field(..., description="创建的任务ID")
|
|
card_code: str = Field(..., description="礼品卡代码")
|
|
message: str = Field(..., description="响应消息")
|
|
|
|
|
|
class GiftCardSubmissionRequest(BaseModel):
|
|
"""礼品卡提交请求模型"""
|
|
|
|
task_id: str = Field(..., description="任务ID")
|
|
card_code: str = Field(..., description="礼品卡代码")
|
|
card_value: float = Field(..., description="礼品卡面值")
|
|
|
|
|
|
class GiftCardSubmissionResponse(BaseModel):
|
|
"""礼品卡提交响应模型"""
|
|
|
|
success: bool = Field(..., description="操作是否成功")
|
|
task_id: str = Field(..., description="任务ID")
|
|
message: str = Field(..., description="响应消息")
|
|
|
|
|
|
# 合并现有的礼品卡schema
|
|
class GiftCardInfoCreate(BaseModel):
|
|
"""创建礼品卡信息的schema"""
|
|
|
|
order_id: str = Field(..., description="关联订单ID")
|
|
card_code: str = Field(..., description="礼品卡代码")
|
|
card_value: float = Field(..., description="礼品卡面值")
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class GiftCardInfoResponse(BaseModel):
|
|
"""礼品卡信息响应模型 - 与数据表字段完全一致"""
|
|
|
|
id: str = Field(..., description="礼品卡ID")
|
|
card_code: str = Field(..., description="礼品卡号码")
|
|
status: str = Field(..., description="礼品卡状态")
|
|
failure_reason: str | None = Field(None, description="失败原因")
|
|
order_result_id: str = Field(..., description="订单结果ID")
|
|
created_at: str = Field(..., description="创建时间")
|
|
updated_at: str = Field(..., description="更新时间")
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class GiftCardDetailCreate(BaseModel):
|
|
"""礼品卡详细信息输入schema"""
|
|
|
|
task_id: str = Field(..., description="任务ID")
|
|
card_code: str = Field(..., description="礼品卡代码")
|
|
card_value: float = Field(..., description="礼品卡面值")
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class DeleteAllDataResponse(BaseModel):
|
|
"""删除所有数据响应模型"""
|
|
|
|
success: bool = Field(..., description="操作是否成功")
|
|
deleted_tables: dict[str, int] = Field(..., description="各表删除的记录数")
|
|
message: str = Field(..., description="响应消息")
|
|
|
|
|
|
class PaginatedResponse(BaseModel, Generic[T]):
|
|
"""统一分页响应模型"""
|
|
|
|
items: List[T] = Field(..., description="数据项列表")
|
|
total: int = Field(..., description="总记录数")
|
|
page: int = Field(..., description="当前页码")
|
|
size: int = Field(..., description="每页大小")
|
|
pages: int = Field(..., description="总页数")
|
|
|
|
model_config = ConfigDict(from_attributes=True, arbitrary_types_allowed=True)
|
|
|
|
|
|
# 用户数据相关模型
|
|
class UserDataBase(BaseModel):
|
|
"""用户数据基础模型"""
|
|
|
|
first_name: str = Field(..., description="名字", max_length=255)
|
|
last_name: str = Field(..., description="姓氏", max_length=255)
|
|
email: str = Field(..., description="邮箱", max_length=255)
|
|
phone: str = Field(..., description="电话", max_length=50)
|
|
street_address: str = Field(..., description="街道地址", max_length=500)
|
|
city: str = Field(..., description="城市", max_length=255)
|
|
state: str = Field(..., description="州/省", max_length=255)
|
|
zip_code: str = Field(..., description="邮编", max_length=20)
|
|
|
|
@field_validator("email")
|
|
@classmethod
|
|
def validate_email(cls, v):
|
|
"""验证邮箱格式"""
|
|
import re
|
|
|
|
pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
|
|
if not re.match(pattern, v):
|
|
raise ValueError("邮箱格式不正确")
|
|
return v
|
|
|
|
|
|
class UserDataCreate(UserDataBase):
|
|
"""创建用户数据请求模型"""
|
|
pass
|
|
|
|
|
|
class UserDataUpdate(BaseModel):
|
|
"""更新用户数据请求模型"""
|
|
|
|
first_name: str | None = Field(None, description="名字", max_length=255)
|
|
last_name: str | None = Field(None, description="姓氏", max_length=255)
|
|
email: str | None = Field(None, description="邮箱", max_length=255)
|
|
phone: str | None = Field(None, description="电话", max_length=50)
|
|
street_address: str | None = Field(None, description="街道地址", max_length=500)
|
|
city: str | None = Field(None, description="城市", max_length=255)
|
|
state: str | None = Field(None, description="州/省", max_length=255)
|
|
zip_code: str | None = Field(None, description="邮编", max_length=20)
|
|
|
|
|
|
class UserDataResponse(UserDataBase):
|
|
"""用户数据响应模型"""
|
|
|
|
id: str = Field(..., description="用户数据ID")
|
|
created_at: str = Field(..., description="创建时间")
|
|
updated_at: str = Field(..., description="更新时间")
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
class UserDataUploadResponse(BaseModel):
|
|
"""用户数据上传响应模型"""
|
|
|
|
user_data: UserDataResponse
|
|
message: str = Field(..., description="响应消息")
|
|
|
|
|
|
class UserDataStatsResponse(BaseModel):
|
|
"""用户数据统计响应模型"""
|
|
|
|
total_users: int = Field(..., description="总用户数")
|
|
total_orders: int = Field(..., description="总订单数")
|
|
recent_uploads: int = Field(..., description="最近上传数量")
|
|
success_rate: float = Field(..., description="成功率")
|
|
|
|
|
|
class BulkDeleteUserDataResponse(BaseModel):
|
|
"""批量删除用户数据响应模型"""
|
|
|
|
total_users: int = Field(..., description="总用户数")
|
|
deleted_users: int = Field(..., description="已删除用户数")
|
|
skipped_users: int = Field(..., description="跳过的用户数")
|
|
message: str = Field(..., description="响应消息")
|
|
|
|
|
|
# 链接相关模型
|
|
class LinkBase(BaseModel):
|
|
"""链接基础模型"""
|
|
|
|
url: str = Field(..., description="链接URL", max_length=255)
|
|
amount: float = Field(..., description="金额", gt=0)
|
|
weight: int = Field(1, description="权重(1-100)", ge=1, le=100)
|
|
status: LinkStatus = Field(LinkStatus.ACTIVE, description="链接状态")
|
|
|
|
|
|
class LinkCreate(LinkBase):
|
|
"""创建链接请求模型"""
|
|
pass
|
|
|
|
|
|
class LinkUpdate(BaseModel):
|
|
"""更新链接请求模型"""
|
|
|
|
url: str | None = Field(None, description="链接URL", max_length=255)
|
|
amount: float | None = Field(None, description="金额", gt=0)
|
|
weight: int | None = Field(None, description="权重(1-100)", ge=1, le=100)
|
|
status: LinkStatus | None = Field(None, description="链接状态")
|
|
|
|
model_config = ConfigDict(use_enum_values=True)
|
|
|
|
|
|
class LinkPoolResponse(BaseModel):
|
|
"""轮询池响应模型"""
|
|
|
|
link: LinkInfo
|
|
pool_position: int = Field(..., description="在轮询池中的位置")
|
|
|
|
|
|
class LinkStatsResponse(BaseModel):
|
|
"""链接统计响应模型"""
|
|
|
|
total_links: int = Field(..., description="总链接数")
|
|
total_orders: int = Field(..., description="总订单数")
|
|
average_amount: float = Field(..., description="平均金额")
|
|
min_amount: float = Field(..., description="最小金额")
|
|
max_amount: float = Field(..., description="最大金额")
|
|
|
|
|
|
# 订单相关模型
|
|
class OrderStatsResponse(BaseModel):
|
|
"""订单统计响应"""
|
|
|
|
total: int
|
|
pending: int
|
|
processing: int
|
|
success: int
|
|
failed: int
|
|
last_update: str
|
|
|
|
|
|
class OrderDetailResponse(BaseModel):
|
|
"""订单详情响应 - 与数据库结构完全一致"""
|
|
|
|
id: str = Field(..., description="订单ID")
|
|
status: OrderStatus = Field(..., description="订单状态")
|
|
created_at: str = Field(..., description="创建时间")
|
|
updated_at: str = Field(..., description="更新时间")
|
|
final_order_url: str | None = Field(None, description="最终订单URL")
|
|
final_order_id: str | None = Field(None, description="最终苹果订单ID")
|
|
failure_reason: str | None = Field(None, description="失败原因")
|
|
user_data_id: str = Field(..., description="用户数据ID")
|
|
links_id: str = Field(..., description="链接ID")
|
|
|
|
# 关联关系
|
|
user_data: UserInfo = Field(description="用户数据")
|
|
links: LinkInfo = Field(description="链接信息")
|
|
gift_cards: list[CardInfo] = Field(default_factory=list, description="礼品卡列表")
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
class UploadUrlRequest(BaseModel):
|
|
"""上传URL请求"""
|
|
|
|
url: str = Field(..., min_length=1, description="上传URL")
|
|
thread_id: str | None = Field(None, description="线程ID")
|
|
|
|
|
|
class UploadUrlResponse(BaseModel):
|
|
"""上传URL响应"""
|
|
|
|
success: bool
|
|
message: str
|
|
upload_config_id: str
|
|
url: str
|