deliveryman-api/app/api/endpoints/point_product_order.py
2025-02-20 17:44:39 +08:00

229 lines
7.4 KiB
Python

from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from app.models.point_product_order import (
PointProductOrderDB,
PointProductOrderCreate,
PointProductOrderInfo,
PointProductOrderStatus
)
from app.models.point_product import PointProductDB
from app.models.database import get_db
from app.api.deps import get_current_user, get_admin_user, get_deliveryman_user
from app.models.user import UserDB
from app.core.response import success_response, error_response, ResponseModel
from app.core.point_manager import PointManager
from typing import Optional
from datetime import datetime
from app.models.order import ShippingOrderDB, OrderStatus
router = APIRouter()
@router.get("/pre_order", response_model=ResponseModel)
async def pre_order(
order: PointProductOrderCreate,
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""预下单"""
# 检查今日是否有配送订单
orders = db.query(ShippingOrderDB).filter(
ShippingOrderDB.userid == current_user.userid,
ShippingOrderDB.status.in_([OrderStatus.CREATED, OrderStatus.RECEIVED]),
ShippingOrderDB.create_time.date() == datetime.now().date()
).all()
if len(orders) == 0:
return error_response(code=400, message="今日暂无配送订单")
product = db.query(PointProductDB).filter(
PointProductDB.id == order.product_id,
PointProductDB.is_active == True
).first()
if not product:
return error_response(code=404, message="商品不存在或已下架")
# 计算所需总积分
order_point_amount = product.point_amount * order.quantity
return success_response(data={
"order_point_amount": order_point_amount,
"orders": orders
})
@router.post("", response_model=ResponseModel)
async def create_point_product_order(
order: PointProductOrderCreate,
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""创建积分商品订单"""
# 查询商品信息
product = db.query(PointProductDB).filter(
PointProductDB.id == order.product_id,
PointProductDB.is_active == True
).first()
if not product:
return error_response(code=404, message="商品不存在或已下架")
# 计算所需总积分
total_points = product.point_amount * order.quantity
# 检查用户积分是否足够
if current_user.points < total_points:
return error_response(code=400, message="积分不足")
# 检查配送订单是否存在
if order.delivery_order_id is None:
return error_response(code=400, message="配送订单不能为空")
delivery_order = db.query(ShippingOrderDB).filter(
ShippingOrderDB.orderid == order.delivery_order_id,
ShippingOrderDB.status.in_([OrderStatus.CREATED, OrderStatus.RECEIVED]),
ShippingOrderDB.create_time.date() == datetime.now().date()
).first()
if not delivery_order:
return error_response(code=404, message="配送订单不存在")
# 检查配送订单是否已支付
if delivery_order.status != OrderStatus.UNPAID:
return error_response(code=400, message="配送订单已支付")
# 创建订单
db_order = PointProductOrderDB(
orderid=PointProductOrderDB.generate_order_id(),
user_id=current_user.userid,
product_id=product.id,
product_name=product.name,
product_image=product.product_image,
product_description=product.description,
product_point_amount=product.point_amount,
quantity=order.quantity,
order_point_amount=total_points,
delivery_order_id=order.delivery_order_id,
status=PointProductOrderStatus.PENDING
)
try:
# 保存订单
db.add(db_order)
db.commit()
db.refresh(db_order)
# 扣减用户积分
point_manager = PointManager(db)
point_manager.deduct_points(
user_id=current_user.userid,
points=total_points,
description=f"兑换积分商品",
order_id=db_order.orderid
)
return success_response(data=PointProductOrderInfo.model_validate(db_order))
except Exception as e:
db.rollback()
return error_response(code=500, message=f"创建订单失败: {str(e)}")
@router.get("", response_model=ResponseModel)
async def get_point_product_orders(
status: Optional[PointProductOrderStatus] = None,
skip: int = Query(0, ge=0),
limit: int = Query(20, ge=1, le=100),
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""获取积分商品订单列表"""
query = db.query(PointProductOrderDB).filter(
PointProductOrderDB.user_id == current_user.userid
)
if status:
query = query.filter(PointProductOrderDB.status == status)
total = query.count()
orders = query.order_by(PointProductOrderDB.create_time.desc())\
.offset(skip)\
.limit(limit)\
.all()
return success_response(data={
"total": total,
"items": [PointProductOrderInfo.model_validate(o) for o in orders]
})
@router.get("/{orderid}", response_model=ResponseModel)
async def get_point_product_order(
orderid: str,
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""获取积分商品订单详情"""
order = db.query(PointProductOrderDB).filter(
PointProductOrderDB.orderid == orderid,
PointProductOrderDB.user_id == current_user.userid
).first()
if not order:
return error_response(code=404, message="订单不存在")
return success_response(data=PointProductOrderInfo.model_validate(order))
# 接受订单
@router.post("/{orderid}/accept", response_model=ResponseModel)
async def accept_point_product_order(
orderid: str,
db: Session = Depends(get_db),
deliveryman: UserDB = Depends(get_deliveryman_user)
):
order = db.query(PointProductOrderDB).filter(
PointProductOrderDB.orderid == orderid,
PointProductOrderDB.status == PointProductOrderStatus.PENDING
).first()
if not order:
return error_response(code=404, message="订单不存在")
if order.status != PointProductOrderStatus.PENDING:
return error_response(code=400, message="订单状态不正确")
# 更新订单状态
order.status = PointProductOrderStatus.CONFIRMED
db.commit()
db.refresh(order)
return success_response(data=PointProductOrderInfo.model_validate(order))
# 拒绝订单
@router.post("/{orderid}/reject", response_model=ResponseModel)
async def reject_point_product_order(
orderid: str,
db: Session = Depends(get_db),
deliveryman: UserDB = Depends(get_deliveryman_user)
):
order = db.query(PointProductOrderDB).filter(
PointProductOrderDB.orderid == orderid,
PointProductOrderDB.status == PointProductOrderStatus.PENDING
).first()
if not order:
return error_response(code=404, message="订单不存在")
if order.status != PointProductOrderStatus.PENDING:
return error_response(code=400, message="订单状态不正确")
# 更新订单状态
order.status = PointProductOrderStatus.CANCELLED
db.commit()
db.refresh(order)
return success_response(data=PointProductOrderInfo.model_validate(order))