From c0ec42ca8a42886fe3dabdf44a5d620644f5690e Mon Sep 17 00:00:00 2001 From: aaron <> Date: Tue, 25 Feb 2025 12:40:43 +0800 Subject: [PATCH] =?UTF-8?q?coupon=20=E5=A2=9E=E5=8A=A0=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=20=20=E5=92=8C=20=20=E6=A0=B8=E9=94=80=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/endpoints/coupon.py | 27 +++++++++++++++++++++++++++ app/api/endpoints/order.py | 8 ++++++-- app/api/endpoints/user.py | 37 ++++++++++++++++++++++++++----------- app/main.py | 6 ++++-- app/models/coupon.py | 14 +++++++++++++- 5 files changed, 76 insertions(+), 16 deletions(-) diff --git a/app/api/endpoints/coupon.py b/app/api/endpoints/coupon.py index 0f5ff4c..de76c6e 100644 --- a/app/api/endpoints/coupon.py +++ b/app/api/endpoints/coupon.py @@ -36,6 +36,33 @@ async def create_coupon( except Exception as e: db.rollback() return error_response(code=500, message=f"创建优惠券失败: {str(e)}") + + +@router.put("/{coupon_id}/beused", response_model=ResponseModel) +async def beused_coupon( + coupon_id: int, + db: Session = Depends(get_db), + current_user: UserDB = Depends(get_current_user) +): + """ 使用优惠券 """ + + coupon = db.query(UserCouponDB).filter( + UserCouponDB.id == coupon_id, + UserCouponDB.user_id == current_user.userid, + UserCouponDB.status == CouponStatus.UNUSED, + UserCouponDB.expire_time > datetime.now() + ).first() + + if not coupon: + return error_response(code=404, message="优惠券不存在") + + coupon.status = CouponStatus.USED + coupon.used_time = datetime.now() + + db.commit() + + return success_response(data=CouponInfo.model_validate(coupon)) + @router.put("/{coupon_id}", response_model=ResponseModel) async def update_coupon( diff --git a/app/api/endpoints/order.py b/app/api/endpoints/order.py index e929080..2d2e16e 100644 --- a/app/api/endpoints/order.py +++ b/app/api/endpoints/order.py @@ -19,7 +19,7 @@ from app.models.database import get_db from app.api.deps import get_current_user, get_deliveryman_user, get_admin_user from app.models.user import UserDB,UserRole from app.core.response import success_response, error_response, ResponseModel -from app.models.coupon import UserCouponDB, CouponStatus +from app.models.coupon import UserCouponDB, CouponStatus, CouponType from app.models.point_product_order import PointProductOrderDB, PointProductOrderInfo, PointProductOrderStatus from datetime import datetime, timezone from app.core.config import settings @@ -115,6 +115,7 @@ def calculate_price(price_request: OrderPriceCalculateRequest,user: UserDB,db: S # 1. 查找用户可用的优惠券(按金额从大到小排序) available_coupon = db.query(UserCouponDB).filter( UserCouponDB.user_id == user.userid, + UserCouponDB.coupon_type == CouponType.CASH, UserCouponDB.status == CouponStatus.UNUSED, UserCouponDB.expire_time > datetime.now() ).order_by(UserCouponDB.coupon_amount.desc()).first() @@ -192,7 +193,7 @@ async def create_order( # 查询用户优惠券 if coupon_id: user_coupon = db.query(UserCouponDB).filter( - UserCouponDB.id == coupon_id + UserCouponDB.id == coupon_id, ).first() if user_coupon: @@ -268,6 +269,7 @@ async def create_order( ).first() if coupon: coupon.status = CouponStatus.USED + coupon.used_time = datetime.now() # 如果使用了积分,扣减用户积分并记录 if price_result.used_points: @@ -672,6 +674,7 @@ async def cancel_order( ).first() if coupon: coupon.status = CouponStatus.UNUSED + coupon.used_time = None # 检查子订单是否全部取消 sub_orders = db.query(PointProductOrderDB).filter( @@ -877,6 +880,7 @@ async def deliveryman_cancel_order( ).first() if coupon: coupon.status = CouponStatus.UNUSED + coupon.used_time = None # 检查子订单是否全部取消 sub_orders = db.query(PointProductOrderDB).filter( diff --git a/app/api/endpoints/user.py b/app/api/endpoints/user.py index 727ad6e..a2f42b7 100644 --- a/app/api/endpoints/user.py +++ b/app/api/endpoints/user.py @@ -24,6 +24,8 @@ from app.core.qcloud import qcloud_manager from app.models.merchant import MerchantDB from app.models.address import AddressDB, AddressInfo from app.models.user import UserUpdateRoles, UserUpdateDeliveryCommissionRate +from app.models.order import ShippingOrderDB + router = APIRouter() # Redis 连接 @@ -343,6 +345,8 @@ async def password_login( @router.get("/referrals", response_model=ResponseModel) async def get_referral_users( + skip: int = 0, + limit: int = 10, db: Session = Depends(get_db), current_user: UserDB = Depends(get_current_user) ): @@ -351,19 +355,30 @@ async def get_referral_users( UserDB.referral_code == current_user.user_code ).order_by( UserDB.create_time.desc() - ).all() + ).offset(skip).limit(limit).all() - # 处理手机号脱敏 - def mask_phone(phone: str) -> str: - return f"{phone[:3]}****{phone[7:]}" + total = db.query(UserDB).filter( + UserDB.referral_code == current_user.user_code + ).count() + + user_list = [] + + # 获取用户是否下单 + for user in referral_users: + u = ReferralUserInfo.model_validate(user).model_dump() + + order_count = db.query(ShippingOrderDB).filter( + ShippingOrderDB.userid == user.userid + ).count() + + u['is_place_order'] = order_count > 0 + u['phone'] = f"{u['phone'][:3]}****{u['phone'][7:]}" + user_list.append(u) - return success_response(data=[ - ReferralUserInfo( - nickname=user.nickname, - phone=mask_phone(user.phone), - create_time=user.create_time - ) for user in referral_users - ]) + return success_response(data={ + "total": total, + "items": user_list + }) def issue_register_coupons(db: Session, user_id: int): """发放注册优惠券 diff --git a/app/main.py b/app/main.py index 029d6ec..7810562 100644 --- a/app/main.py +++ b/app/main.py @@ -85,7 +85,6 @@ async def exception_handler(request, exc): **请求信息** > 请求方法:{request.method} > 请求URL:{request.url} -> 请求头:{request.headers} > 请求体:{request.body} **异常信息** @@ -96,5 +95,8 @@ async def exception_handler(request, exc): return CustomJSONResponse( status_code=500, - content=str(exc) + content={ + "code": 500, + "message": str(exc) + } ) \ No newline at end of file diff --git a/app/models/coupon.py b/app/models/coupon.py index 45798d4..7a84699 100644 --- a/app/models/coupon.py +++ b/app/models/coupon.py @@ -11,6 +11,10 @@ class CouponStatus(str, enum.Enum): USED = "USED" EXPIRED = "EXPIRED" +class CouponType(str, enum.Enum): + PRODUCT = "PRODUCT" # 商品 + CASH = "CASH" # 现金 + # 数据库模型 class CouponDB(Base): __tablename__ = "coupons" @@ -18,6 +22,7 @@ class CouponDB(Base): id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(100), nullable=False) amount = Column(Float, nullable=False) + coupon_type = Column(Enum(CouponType), nullable=False, default=CouponType.CASH) create_time = Column(DateTime(timezone=True), server_default=func.now()) update_time = Column(DateTime(timezone=True), onupdate=func.now()) @@ -28,8 +33,10 @@ class UserCouponDB(Base): user_id = Column(Integer, ForeignKey("users.userid"), index=True) coupon_id = Column(Integer, ForeignKey("coupons.id"), index=True) coupon_name = Column(String(100), nullable=False) + coupon_type = Column(Enum(CouponType), nullable=False) coupon_amount = Column(Float, nullable=False) expire_time = Column(DateTime(timezone=True), nullable=False) + used_time = Column(DateTime(timezone=True), nullable=True) status = Column(Enum(CouponStatus), default=CouponStatus.UNUSED) create_time = Column(DateTime(timezone=True), server_default=func.now()) update_time = Column(DateTime(timezone=True), onupdate=func.now()) @@ -37,16 +44,19 @@ class UserCouponDB(Base): # Pydantic 模型 class CouponCreate(BaseModel): name: str = Field(..., max_length=100) - amount: float = Field(..., gt=0) + amount: Optional[float] = Field(None, gt=0) + coupon_type: CouponType = Field(CouponType.CASH) class CouponUpdate(BaseModel): name: Optional[str] = Field(None, max_length=100) amount: Optional[float] = Field(None, gt=0) + coupon_type: CouponType = Field(CouponType.CASH) class CouponInfo(BaseModel): id: int name: str amount: float + coupon_type: CouponType create_time: datetime class Config: @@ -64,7 +74,9 @@ class UserCouponInfo(BaseModel): coupon_id: int coupon_name: str coupon_amount: float + coupon_type: CouponType expire_time: datetime + used_time: datetime status: CouponStatus create_time: datetime