mirror of
https://git.oceanpay.cc/danial/kami_apple_exchage.git
synced 2025-12-18 21:23:49 +00:00
- 新增 CODEBUDDY.md、GEMINI.md、GEMINI_CN.md 等项目文档 - 更新 Dockerfile 和其他配置文件 - 优化部分代码结构,如 orders.py、tasks.py 等 - 新增 .dockerignore 文件
187 lines
7.2 KiB
Python
187 lines
7.2 KiB
Python
"""
|
|
订单管理API端点
|
|
"""
|
|
|
|
import traceback
|
|
from fastapi import APIRouter, Depends, HTTPException, status, Response
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.core.database import get_async_db
|
|
from app.core.log import get_logger
|
|
from app.models.orders import OrderResultStatus
|
|
from app.schemas.link import LinkResponse
|
|
from app.schemas.task import GiftCardInfoResponse
|
|
from app.schemas.user_data import UserInfoResponse
|
|
from app.services.order_business_service import OrderService
|
|
from app.schemas.order import (
|
|
OrderStatsResponse,
|
|
OrderDetailResponse,
|
|
)
|
|
|
|
router = APIRouter()
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
@router.get("/stats", summary="获取订单统计", response_model=OrderStatsResponse)
|
|
async def get_order_stats(
|
|
db: AsyncSession = Depends(get_async_db),
|
|
) -> OrderStatsResponse:
|
|
"""获取订单统计信息"""
|
|
try:
|
|
result = await OrderService(db).get_order_statistics()
|
|
logger.info("获取订单统计成功")
|
|
return result
|
|
except Exception as e:
|
|
logger.error(f"获取订单统计失败: {traceback.format_exc()}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"获取订单统计失败: {str(e)}",
|
|
)
|
|
|
|
|
|
@router.get("/list", summary="获取订单列表")
|
|
async def get_orders(
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
status_filter: OrderResultStatus | None = None,
|
|
db: AsyncSession = Depends(get_async_db),
|
|
) -> list[OrderDetailResponse]:
|
|
"""获取订单列表"""
|
|
try:
|
|
orders = await OrderService(db).get_order_list(skip, limit, status_filter)
|
|
# Convert SQLAlchemy models to Pydantic response schemas
|
|
result = []
|
|
for order in orders:
|
|
link_response = LinkResponse(
|
|
id=order.links.id,
|
|
url=order.links.url,
|
|
amount=order.links.amount,
|
|
created_at=order.links.created_at.isoformat(),
|
|
updated_at=order.links.updated_at.isoformat(),
|
|
)
|
|
gift_cards = []
|
|
if order.gift_cards:
|
|
for gc in order.gift_cards:
|
|
gift_cards.append(GiftCardInfoResponse(
|
|
id=gc.id,
|
|
card_code=gc.card_code,
|
|
status=gc.status.value,
|
|
failure_reason=gc.failure_reason,
|
|
order_result_id=order.id,
|
|
created_at=gc.created_at.isoformat(),
|
|
updated_at=gc.updated_at.isoformat()
|
|
))
|
|
|
|
user_data = UserInfoResponse(
|
|
id=order.user_data.id,
|
|
email=order.user_data.email,
|
|
phone=order.user_data.phone,
|
|
created_at=order.user_data.created_at.isoformat(),
|
|
updated_at=order.user_data.updated_at.isoformat(),
|
|
full_name=order.user_data.full_name,
|
|
full_address=order.user_data.full_address,
|
|
first_name=order.user_data.first_name,
|
|
last_name=order.user_data.last_name,
|
|
street_address=order.user_data.street_address,
|
|
city=order.user_data.city,
|
|
state=order.user_data.state,
|
|
zip_code=order.user_data.zip_code
|
|
)
|
|
|
|
# Handle gift_cards being None by converting to empty list
|
|
gift_cards = order.gift_cards if order.gift_cards is not None else []
|
|
order_detail = OrderDetailResponse(
|
|
id=order.id,
|
|
status=order.status.value,
|
|
created_at=order.created_at.isoformat(),
|
|
updated_at=order.updated_at.isoformat(),
|
|
final_order_url=order.final_order_url,
|
|
failure_reason=order.failure_reason,
|
|
user_data_id=order.user_data_id,
|
|
links_id=order.links_id,
|
|
user_data=user_data,
|
|
links=link_response,
|
|
gift_cards=gift_cards
|
|
)
|
|
result.append(order_detail)
|
|
return result
|
|
except ValueError as e:
|
|
logger.warning(f"获取订单列表失败 - 参数验证错误: {str(e)}")
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
|
except Exception as e:
|
|
logger.error(f"获取订单列表失败: {traceback.format_exc()}")
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"获取订单列表失败: {str(e)}",
|
|
)
|
|
|
|
|
|
@router.get("/export", summary="导出订单数据")
|
|
async def export_orders(
|
|
status_filter: str | None = None, db: AsyncSession = Depends(get_async_db)
|
|
):
|
|
"""导出订单数据为Excel文件"""
|
|
try:
|
|
excel_content, filename = await OrderService(
|
|
db,
|
|
).export_orders_to_excel(status_filter)
|
|
logger.info(f"导出订单数据成功: filename={filename}")
|
|
|
|
return Response(
|
|
content=excel_content,
|
|
media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
headers={"Content-Disposition": f"attachment; filename={filename}"},
|
|
)
|
|
|
|
except ValueError as e:
|
|
logger.warning(f"导出订单数据失败 - 参数验证错误: {str(e)}")
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
|
except Exception as e:
|
|
logger.error(f"导出订单数据失败: {e}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"导出订单数据失败: {str(e)}",
|
|
)
|
|
|
|
|
|
@router.get("/{order_id}", summary="获取订单详情", response_model=OrderDetailResponse)
|
|
async def get_order(order_id: str, db: AsyncSession = Depends(get_async_db)) -> OrderDetailResponse:
|
|
"""获取订单详情"""
|
|
try:
|
|
order = await OrderService(db).get_order_detail(order_id)
|
|
|
|
if not order:
|
|
logger.warning(f"获取订单详情失败 - 订单不存在: {order_id}")
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND, detail="订单不存在"
|
|
)
|
|
|
|
# Convert SQLAlchemy model to Pydantic response schema
|
|
# Handle gift_cards being None by converting to empty list
|
|
gift_cards = order.gift_cards if order.gift_cards is not None else []
|
|
order_detail = OrderDetailResponse(
|
|
id=order.id,
|
|
status=order.status.value,
|
|
created_at=order.created_at.isoformat(),
|
|
updated_at=order.updated_at.isoformat(),
|
|
final_order_url=order.final_order_url,
|
|
failure_reason=order.failure_reason,
|
|
user_data_id=order.user_data_id,
|
|
links_id=order.links_id,
|
|
user_data=order.user_data,
|
|
links=order.links,
|
|
gift_cards=gift_cards
|
|
)
|
|
|
|
logger.info(f"获取订单详情成功: {order_id}")
|
|
return order_detail
|
|
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"获取订单详情失败: {e}", order_id=order_id, exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"获取订单详情失败: {str(e)}",
|
|
)
|