deliveryman-api/app/api/endpoints/coupon_activity.py
2025-02-26 14:12:12 +08:00

256 lines
9.2 KiB
Python

from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from sqlalchemy import func, and_
from app.models.coupon_activity import (
CouponActivityDB,
CouponActivityCreate,
CouponActivityUpdate,
CouponActivityInfo
)
from app.models.coupon_receive_record import CouponReceiveRecordDB
from app.models.coupon import CouponDB, UserCouponDB, CouponStatus, CouponInfo
from app.models.database import get_db
from app.api.deps import get_current_user, get_admin_user
from app.models.user import UserDB
from app.core.response import success_response, error_response, ResponseModel
from typing import Optional, List
from datetime import datetime, time
from app.core.coupon_manager import CouponManager
router = APIRouter()
@router.post("", response_model=ResponseModel)
async def create_coupon_activity(
activity: CouponActivityCreate,
db: Session = Depends(get_db),
admin: UserDB = Depends(get_admin_user)
):
"""创建优惠券活动(管理员)"""
# 检查优惠券是否存在
for coupon_id in activity.coupon_config.keys():
coupon = db.query(CouponDB).filter(CouponDB.id == coupon_id).first()
if not coupon:
return error_response(code=404, message=f"优惠券ID {coupon_id} 不存在")
# 检查数量是否大于0
if activity.coupon_config[coupon_id] <= 0:
return error_response(code=400, message=f"优惠券ID {coupon_id} 的数量必须大于0")
db_activity = CouponActivityDB(**activity.model_dump())
db.add(db_activity)
try:
db.commit()
db.refresh(db_activity)
return success_response(data=CouponActivityInfo.model_validate(db_activity))
except Exception as e:
db.rollback()
return error_response(code=500, message=f"创建失败: {str(e)}")
@router.get("/{activity_id}", response_model=ResponseModel)
async def get_coupon_activity(
activity_id: int,
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""获取优惠券活动详情"""
activity = db.query(CouponActivityDB).filter(
CouponActivityDB.id == activity_id
).first()
if not activity:
return error_response(code=404, message="活动不存在")
# 获取活动对应的优惠券,并设置数量
coupons = db.query(CouponDB).filter(
CouponDB.id.in_(activity.coupon_config.keys())
).all()
activity_data = CouponActivityInfo.model_validate(activity).model_dump()
coupon_list = []
for coupon in coupons:
coupon_info = CouponInfo.model_validate(coupon).model_dump()
coupon_info.update({'count': activity_data['coupon_config'][coupon.id]})
coupon_list.append(coupon_info)
activity_data.update({'coupons': coupon_list})
# 检查总领取次数是否超过限制
can_receive = True
if activity.total_limit > 0:
user_receive_count = db.query(func.count(CouponReceiveRecordDB.id)).filter(
CouponReceiveRecordDB.activity_id == activity_id,
CouponReceiveRecordDB.user_id == current_user.userid
).scalar()
if user_receive_count >= activity.total_limit:
can_receive = False
# 检查当前是否可以领取
current_time = datetime.now().time()
if current_time < activity.daily_start_time or current_time > activity.daily_end_time:
can_receive = False
activity_data.update({'can_receive': can_receive})
# 检查活动是否结束
is_end = activity.end_time < datetime.now()
activity_data.update({'can_receive': not is_end})
activity_data.update({'is_end': is_end})
return success_response(data=activity_data)
@router.get("", response_model=ResponseModel)
async def get_coupon_activities(
is_active: Optional[bool] = None,
skip: int = Query(0, ge=0),
limit: int = Query(20, ge=1, le=100),
db: Session = Depends(get_db)
):
"""获取优惠券活动列表"""
query = db.query(CouponActivityDB)
if is_active is not None:
query = query.filter(CouponActivityDB.is_active == is_active)
total = query.count()
activities = query.order_by(CouponActivityDB.create_time.desc())\
.offset(skip)\
.limit(limit)\
.all()
# 查询每个活动被领取的次数
activities_data = []
for activity in activities:
receive_count = db.query(func.sum(CouponReceiveRecordDB.receive_count)).filter(
CouponReceiveRecordDB.activity_id == activity.id,
).scalar()
activity_data = CouponActivityInfo.model_validate(activity).model_dump()
activity_data.update({'receive_count': receive_count})
activities_data.append(activity_data)
return success_response(data={
"total": total,
"items": activities_data
})
@router.post("/{activity_id}/receive", response_model=ResponseModel)
async def receive_coupons(
activity_id: int,
db: Session = Depends(get_db),
current_user: UserDB = Depends(get_current_user)
):
"""领取优惠券"""
# 查询活动
activity = db.query(CouponActivityDB).filter(
CouponActivityDB.id == activity_id,
CouponActivityDB.is_active == True
).first()
if not activity:
return error_response(code=404, message="活动不存在或已结束")
# 检查领取时间
current_time = datetime.now().time()
if current_time < activity.daily_start_time or current_time > activity.daily_end_time:
return error_response(code=400, message="不在领取时间范围内")
# 检查总领取次数
total_receive_count = db.query(func.count(CouponReceiveRecordDB.id)).filter(
CouponReceiveRecordDB.user_id == current_user.userid,
CouponReceiveRecordDB.activity_id == activity_id
).scalar()
if activity.total_limit > 0 and total_receive_count >= activity.total_limit:
return error_response(code=400, message=f"您只能领取 {activity.total_limit}")
# 检查今日领取次数
today = datetime.now().date()
today_receive_count = db.query(func.count(CouponReceiveRecordDB.id)).filter(
CouponReceiveRecordDB.user_id == current_user.userid,
CouponReceiveRecordDB.activity_id == activity_id,
CouponReceiveRecordDB.receive_date == today
).scalar()
if today_receive_count >= activity.daily_limit:
return error_response(code=400, message="今日领取次数已达上限")
try:
# 发放优惠券
for coupon_id, count in activity.coupon_config.items():
coupon = db.query(CouponDB).filter(CouponDB.id == coupon_id).first()
if coupon:
expire_time = datetime.combine(today, datetime.max.time())
manager = CouponManager(db)
manager.add_coupon(
user_id=current_user.userid,
coupon_id=coupon.id,
expire_time= expire_time,
count=count
)
# 检查是否领取过优惠券
receive_record = db.query(CouponReceiveRecordDB).filter(
CouponReceiveRecordDB.user_id == current_user.userid,
CouponReceiveRecordDB.activity_id == activity_id,
CouponReceiveRecordDB.receive_date == today
).first()
if receive_record:
receive_record.receive_count += 1
else:
record = CouponReceiveRecordDB(
user_id=current_user.userid,
activity_id=activity_id,
receive_date=today,
receive_count=1
)
db.add(record)
db.commit()
return success_response(message="领取成功")
except Exception as e:
db.rollback()
return error_response(code=500, message=f"领取失败: {str(e)}")
@router.put("/{activity_id}", response_model=ResponseModel)
async def update_coupon_activity(
activity_id: int,
activity: CouponActivityUpdate,
db: Session = Depends(get_db),
admin: UserDB = Depends(get_admin_user)
):
"""更新优惠券活动(管理员)"""
db_activity = db.query(CouponActivityDB).filter(
CouponActivityDB.id == activity_id
).first()
if not db_activity:
return error_response(code=404, message="活动不存在")
# 检查优惠券是否存在
if activity.coupon_config:
for coupon_id, count in activity.coupon_config.items():
coupon = db.query(CouponDB).filter(CouponDB.id == coupon_id).first()
if not coupon:
return error_response(code=404, message=f"优惠券ID {coupon_id} 不存在")
# 检查数量是否大于0
if count <= 0:
return error_response(code=400, message=f"优惠券ID {coupon_id} 的数量必须大于0")
update_data = activity.model_dump(exclude_unset=True)
for key, value in update_data.items():
setattr(db_activity, key, value)
try:
db.commit()
db.refresh(db_activity)
return success_response(data=CouponActivityInfo.model_validate(db_activity))
except Exception as e:
db.rollback()
return error_response(code=500, message=f"更新失败: {str(e)}")