mirror of
https://git.oceanpay.cc/danial/kami_apple_exchage.git
synced 2025-12-18 22:29:09 +00:00
- 新增链接权重字段,支持1-100范围设置 - 修改轮询算法为基于权重的选择机制 - 更新链接API接口返回统一使用LinkInfo模型 - 添加更新链接权重的PATCH端点 - 调整链接仓库查询逻辑,只包含激活状态链接 - 迁移链接相关Pydantic模型到task模块统一管理 - 修改分页响应格式为通用PaginatedResponse包装 - 禁用OpenTelemetry监控配置
234 lines
8.3 KiB
Python
234 lines
8.3 KiB
Python
"""
|
||
用户数据相关的API接口
|
||
"""
|
||
|
||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
|
||
from app.core.database import get_async_db
|
||
from app.core.log import get_logger
|
||
from app.schemas.user_data import (
|
||
UserDataCreate,
|
||
UserDataResponse,
|
||
UserDataUploadResponse,
|
||
)
|
||
from app.schemas.task import (
|
||
BulkDeleteUserDataResponse,
|
||
PaginatedResponse,
|
||
)
|
||
from app.services.user_data_service import UserDataService
|
||
|
||
logger = get_logger(__name__)
|
||
router = APIRouter()
|
||
|
||
|
||
def get_user_data_service(db: AsyncSession = Depends(get_async_db)) -> UserDataService:
|
||
"""获取用户数据服务实例"""
|
||
return UserDataService(db)
|
||
|
||
|
||
@router.post("/upload", response_model=UserDataUploadResponse, summary="上传用户数据")
|
||
async def upload_user_data(
|
||
user_data: UserDataCreate, service: UserDataService = Depends(get_user_data_service)
|
||
):
|
||
"""
|
||
上传用户数据并自动触发订单创建任务
|
||
|
||
- **first_name**: 名字(必填)
|
||
- **last_name**: 姓氏(必填)
|
||
- **email**: 邮箱(必填,唯一)
|
||
- **phone**: 电话(必填)
|
||
- **address**: 地址(必填)
|
||
- **city**: 城市(必填)
|
||
- **state**: 州/省(必填)
|
||
- **zip_code**: 邮编(必填)
|
||
- **country**: 国家(必填)
|
||
|
||
上传成功后,如果存在可用链接,系统会自动创建订单任务。
|
||
"""
|
||
try:
|
||
result = await service.upload_user_data(user_data)
|
||
logger.info(f"用户数据上传成功: email={user_data.email}")
|
||
return result
|
||
except ValueError as e:
|
||
logger.warning(
|
||
f"上传用户数据失败 - 参数验证错误: {str(e)}", email=user_data.email
|
||
)
|
||
raise HTTPException(status_code=400, detail=str(e))
|
||
|
||
|
||
@router.get(
|
||
"/detail/{user_id}", response_model=UserDataResponse, summary="获取用户数据详情"
|
||
)
|
||
async def get_user_data(
|
||
user_id: str, service: UserDataService = Depends(get_user_data_service)
|
||
):
|
||
"""
|
||
根据ID获取用户数据详情
|
||
|
||
- **user_id**: 用户数据ID
|
||
"""
|
||
try:
|
||
user_data = await service.get_user_data(user_id)
|
||
if not user_data:
|
||
logger.warning(f"获取用户数据详情失败 - 用户数据不存在: {user_id}")
|
||
raise HTTPException(status_code=404, detail="用户数据不存在")
|
||
logger.info(f"获取用户数据详情成功: {user_id}")
|
||
return user_data
|
||
except HTTPException:
|
||
raise
|
||
except Exception as e:
|
||
logger.error(f"获取用户数据详情失败: {str(e)}", user_id=user_id, exc_info=True)
|
||
raise HTTPException(status_code=500, detail="获取用户数据详情失败")
|
||
|
||
|
||
@router.delete("/all", response_model=BulkDeleteUserDataResponse, summary="批量删除所有用户数据")
|
||
async def bulk_delete_all_user_data(
|
||
skip_orders: bool = Query(False, description="是否跳过有关联订单的用户数据"),
|
||
service: UserDataService = Depends(get_user_data_service),
|
||
):
|
||
"""
|
||
批量软删除所有用户数据
|
||
|
||
- **skip_orders**: 是否跳过有关联订单的用户数据(默认false,会删除包括有关联订单的所有数据)
|
||
|
||
返回删除统计信息,包括总用户数、删除用户数和跳过用户数
|
||
"""
|
||
try:
|
||
result = await service.delete_all_user_data(skip_orders=skip_orders)
|
||
logger.info(
|
||
f"批量删除用户数据完成: total={result['total_users']}, "
|
||
f"deleted={result['deleted_users']}, skipped={result['skipped_users']}"
|
||
)
|
||
return result
|
||
except Exception as e:
|
||
logger.error(f"批量删除用户数据失败: {str(e)}", exc_info=True)
|
||
raise HTTPException(status_code=500, detail="批量删除用户数据失败")
|
||
|
||
|
||
@router.delete("/{user_id}", summary="删除用户数据")
|
||
async def delete_user_data(
|
||
user_id: str, service: UserDataService = Depends(get_user_data_service)
|
||
):
|
||
"""
|
||
删除用户数据
|
||
|
||
- **user_id**: 用户数据ID
|
||
|
||
注意:有关联订单的用户数据无法删除
|
||
"""
|
||
try:
|
||
success = await service.delete_user_data(user_id)
|
||
if not success:
|
||
logger.warning(f"删除用户数据失败 - 用户数据不存在: {user_id}")
|
||
raise HTTPException(status_code=404, detail="用户数据不存在")
|
||
logger.info(f"删除用户数据成功: {user_id}")
|
||
return {"message": "用户数据删除成功"}
|
||
except ValueError as e:
|
||
logger.warning(f"删除用户数据失败 - 参数验证错误: {str(e)}", user_id=user_id)
|
||
raise HTTPException(status_code=400, detail=str(e))
|
||
except Exception as e:
|
||
logger.error(f"删除用户数据失败: {str(e)}", user_id=user_id, exc_info=True)
|
||
raise HTTPException(status_code=500, detail="删除用户数据失败")
|
||
|
||
|
||
@router.get("/list", response_model=PaginatedResponse[UserDataResponse], summary="获取用户数据列表")
|
||
async def get_user_data_list(
|
||
page: int = Query(1, ge=1, description="页码"),
|
||
size: int = Query(20, ge=1, le=100, description="每页大小"),
|
||
city: str | None = Query(None, description="城市过滤"),
|
||
state: str | None = Query(None, description="州/省过滤"),
|
||
country: str | None = Query(None, description="国家过滤"),
|
||
name_pattern: str | None = Query(None, description="姓名模糊搜索"),
|
||
service: UserDataService = Depends(get_user_data_service),
|
||
):
|
||
"""
|
||
获取用户数据列表,支持分页和过滤
|
||
|
||
- **page**: 页码(从1开始)
|
||
- **size**: 每页大小(1-100)
|
||
- **city**: 城市过滤
|
||
- **state**: 州/省过滤
|
||
- **country**: 国家过滤
|
||
- **name_pattern**: 姓名模糊搜索
|
||
"""
|
||
try:
|
||
result = await service.get_user_data_list(
|
||
page=page,
|
||
size=size,
|
||
city=city,
|
||
state=state,
|
||
country=country,
|
||
name_pattern=name_pattern,
|
||
)
|
||
return result
|
||
except Exception as e:
|
||
logger.error(f"获取用户数据列表失败: {str(e)}", exc_info=True)
|
||
raise HTTPException(status_code=500, detail="获取用户数据列表失败")
|
||
|
||
|
||
@router.get("/task/{task_id}/status", summary="获取任务状态")
|
||
async def get_task_status(
|
||
task_id: str, service: UserDataService = Depends(get_user_data_service)
|
||
):
|
||
"""
|
||
获取订单创建任务的状态
|
||
|
||
- **task_id**: 任务ID(从上传接口返回)
|
||
"""
|
||
try:
|
||
result = await service.get_task_status(task_id)
|
||
logger.info(f"获取任务状态成功: task_id={task_id}")
|
||
return result
|
||
except Exception as e:
|
||
logger.error(f"获取任务状态失败: {str(e)}", task_id=task_id, exc_info=True)
|
||
raise HTTPException(status_code=500, detail="获取任务状态失败")
|
||
|
||
|
||
@router.post("/batch-upload", summary="批量上传用户数据")
|
||
async def batch_upload_user_data(
|
||
user_data_list: list[UserDataCreate],
|
||
service: UserDataService = Depends(get_user_data_service),
|
||
):
|
||
"""
|
||
批量上传用户数据
|
||
|
||
接受用户数据列表,批量创建并触发订单任务
|
||
"""
|
||
if len(user_data_list) > 100:
|
||
logger.warning(f"批量上传用户数据失败 - 超出最大限制: {len(user_data_list)}")
|
||
raise HTTPException(status_code=400, detail="批量上传最多支持100条数据")
|
||
|
||
try:
|
||
results = []
|
||
for user_data in user_data_list:
|
||
try:
|
||
result = await service.upload_user_data(user_data)
|
||
results.append(
|
||
{
|
||
"success": True,
|
||
"user_data": result.user_data,
|
||
"message": result.message,
|
||
}
|
||
)
|
||
except Exception as e:
|
||
results.append(
|
||
{"success": False, "error": str(e), "email": user_data.email}
|
||
)
|
||
|
||
success_count = sum(1 for r in results if r["success"])
|
||
logger.info(
|
||
f"批量上传用户数据完成: total={len(user_data_list)}, success={success_count}"
|
||
)
|
||
return {
|
||
"total": len(user_data_list),
|
||
"success": success_count,
|
||
"failed": len(user_data_list) - success_count,
|
||
"results": results,
|
||
}
|
||
except Exception as e:
|
||
logger.error(f"批量上传用户数据失败: {str(e)}", exc_info=True)
|
||
raise HTTPException(status_code=500, detail="批量上传用户数据失败")
|
||
|
||
|