新增优惠券发放功能
This commit is contained in:
parent
02dcebd28e
commit
623a1f97c4
@ -9,7 +9,10 @@ from app.models.coupon import (
|
||||
CouponInfo,
|
||||
UserCouponCreate,
|
||||
UserCouponInfo,
|
||||
CouponStatus
|
||||
CouponStatus,
|
||||
CouponIssueRecordDB,
|
||||
CouponIssueRecordCreate,
|
||||
CouponIssueRecordInfo
|
||||
)
|
||||
from app.models.database import get_db
|
||||
from app.api.deps import get_admin_user, get_current_user
|
||||
@ -101,20 +104,55 @@ async def issue_coupon(
|
||||
if not coupon:
|
||||
return error_response(code=404, message="优惠券不存在")
|
||||
|
||||
# 查询用户信息
|
||||
user = db.query(UserDB).filter(UserDB.userid == user_coupon.user_id).first()
|
||||
if not user:
|
||||
return error_response(code=404, message="用户不存在")
|
||||
|
||||
# 创建发放记录
|
||||
issue_record = CouponIssueRecordDB(
|
||||
coupon_id=coupon.id,
|
||||
user_id=user_coupon.user_id,
|
||||
operator_id=admin.userid,
|
||||
count=user_coupon.count,
|
||||
remark=f"{admin.nickname}: {user_coupon.remark}" if user_coupon.remark else f"{admin.nickname} 手动发放"
|
||||
)
|
||||
db.add(issue_record)
|
||||
|
||||
# 批量创建用户优惠券
|
||||
manager = CouponManager(coupon)
|
||||
user_coupons = []
|
||||
|
||||
for _ in range(user_coupon.count):
|
||||
manager = CouponManager(coupon)
|
||||
manager.add_coupon(
|
||||
user_coupon_obj = manager.add_coupon(
|
||||
user_id=user_coupon.user_id,
|
||||
coupon_id=coupon.id,
|
||||
count=user_coupon.count,
|
||||
expire_time=user_coupon.expire_time
|
||||
)
|
||||
db.add(user_coupon_obj)
|
||||
user_coupons.append(user_coupon_obj)
|
||||
|
||||
try:
|
||||
db.commit()
|
||||
db.refresh(issue_record)
|
||||
|
||||
return success_response(
|
||||
message=f"成功发放 {user_coupon.count} 张优惠券"
|
||||
message=f"成功发放 {user_coupon.count} 张优惠券",
|
||||
data={
|
||||
"issue_record": CouponIssueRecordInfo(
|
||||
id=issue_record.id,
|
||||
coupon_id=issue_record.coupon_id,
|
||||
user_id=issue_record.user_id,
|
||||
operator_id=issue_record.operator_id,
|
||||
count=issue_record.count,
|
||||
issue_time=issue_record.issue_time,
|
||||
remark=issue_record.remark,
|
||||
coupon_name=coupon.name,
|
||||
user_nickname=user.nickname,
|
||||
operator_nickname=admin.nickname
|
||||
),
|
||||
"coupon_count": len(user_coupons)
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
@ -164,10 +202,71 @@ async def get_all_coupons(
|
||||
admin: UserDB = Depends(get_admin_user)
|
||||
):
|
||||
"""获取所有优惠券列表(管理员)"""
|
||||
coupons = db.query(CouponDB).order_by(
|
||||
query = db.query(CouponDB).order_by(
|
||||
CouponDB.create_time.desc()
|
||||
).offset(skip).limit(limit).all()
|
||||
)
|
||||
|
||||
total = query.count()
|
||||
items = query.offset(skip).limit(limit).all()
|
||||
|
||||
return success_response(
|
||||
data=[CouponInfo.model_validate(c) for c in coupons]
|
||||
data={
|
||||
"total": total,
|
||||
"items": [CouponInfo.model_validate(c) for c in items]
|
||||
}
|
||||
)
|
||||
|
||||
@router.get("/issue/records", response_model=ResponseModel)
|
||||
async def get_issue_records(
|
||||
skip: int = 0,
|
||||
limit: int = 10,
|
||||
coupon_id: Optional[int] = None,
|
||||
user_id: Optional[int] = None,
|
||||
db: Session = Depends(get_db),
|
||||
admin: UserDB = Depends(get_admin_user)
|
||||
):
|
||||
"""获取优惠券发放记录(管理员)"""
|
||||
query = db.query(CouponIssueRecordDB)
|
||||
|
||||
# 添加过滤条件
|
||||
if coupon_id:
|
||||
query = query.filter(CouponIssueRecordDB.coupon_id == coupon_id)
|
||||
if user_id:
|
||||
query = query.filter(CouponIssueRecordDB.user_id == user_id)
|
||||
|
||||
# 计算总数
|
||||
total = query.count()
|
||||
|
||||
# 获取数据
|
||||
records = query.order_by(
|
||||
CouponIssueRecordDB.issue_time.desc()
|
||||
).offset(skip).limit(limit).all()
|
||||
|
||||
# 构建响应数据
|
||||
result = []
|
||||
for record in records:
|
||||
# 获取关联信息
|
||||
coupon = db.query(CouponDB).filter(CouponDB.id == record.coupon_id).first()
|
||||
user = db.query(UserDB).filter(UserDB.userid == record.user_id).first()
|
||||
operator = db.query(UserDB).filter(UserDB.userid == record.operator_id).first()
|
||||
|
||||
record_info = CouponIssueRecordInfo(
|
||||
id=record.id,
|
||||
coupon_id=record.coupon_id,
|
||||
user_id=record.user_id,
|
||||
operator_id=record.operator_id,
|
||||
count=record.count,
|
||||
issue_time=record.issue_time,
|
||||
remark=record.remark,
|
||||
coupon_name=coupon.name if coupon else None,
|
||||
user_nickname=user.nickname if user else None,
|
||||
operator_nickname=operator.nickname if operator else None
|
||||
)
|
||||
result.append(record_info)
|
||||
|
||||
return success_response(
|
||||
data={
|
||||
"total": total,
|
||||
"items": result
|
||||
}
|
||||
)
|
||||
@ -1,47 +1,47 @@
|
||||
from sqlalchemy.orm import Session
|
||||
from app.models.coupon import CouponDB,UserCouponDB
|
||||
from app.models.coupon import CouponDB, UserCouponDB
|
||||
from app.models.user import UserDB
|
||||
from datetime import datetime
|
||||
from typing import Optional, List
|
||||
|
||||
class CouponManager:
|
||||
def __init__(self, db: Session):
|
||||
self.db = db
|
||||
def __init__(self, coupon: CouponDB = None):
|
||||
self.coupon = coupon
|
||||
|
||||
# 发放优惠券
|
||||
def add_coupon(
|
||||
self,
|
||||
user_id: int,
|
||||
coupon_id: int,
|
||||
count: int,
|
||||
expire_time: datetime
|
||||
):
|
||||
try:
|
||||
# 检查优惠券是否存在
|
||||
coupon = self.db.query(CouponDB).filter(CouponDB.id == coupon_id).first()
|
||||
if not coupon:
|
||||
raise ValueError("优惠券不存在")
|
||||
count: int = 1,
|
||||
expire_time: datetime = None
|
||||
) -> UserCouponDB:
|
||||
"""
|
||||
为用户发放优惠券
|
||||
|
||||
# 检查用户是否存在
|
||||
user = self.db.query(UserDB).filter(UserDB.userid == user_id).first()
|
||||
if not user:
|
||||
raise ValueError("用户不存在")
|
||||
Args:
|
||||
user_id: 用户ID
|
||||
coupon_id: 优惠券ID
|
||||
count: 发放数量
|
||||
expire_time: 过期时间
|
||||
|
||||
for _ in range(count):
|
||||
# 发放优惠券
|
||||
user_coupon = UserCouponDB(
|
||||
user_id=user_id,
|
||||
coupon_id=coupon_id,
|
||||
coupon_name=coupon.name,
|
||||
coupon_amount=coupon.amount,
|
||||
coupon_type=coupon.coupon_type,
|
||||
expire_time=expire_time,
|
||||
)
|
||||
self.db.add(user_coupon)
|
||||
Returns:
|
||||
UserCouponDB: 创建的用户优惠券对象
|
||||
"""
|
||||
# 使用传入的优惠券对象
|
||||
coupon = self.coupon
|
||||
|
||||
self.db.commit()
|
||||
except Exception as e:
|
||||
self.db.rollback()
|
||||
raise e
|
||||
# 发放优惠券
|
||||
user_coupon = UserCouponDB(
|
||||
user_id=user_id,
|
||||
coupon_id=coupon_id,
|
||||
coupon_name=coupon.name,
|
||||
coupon_amount=coupon.amount,
|
||||
coupon_type=coupon.coupon_type,
|
||||
expire_time=expire_time,
|
||||
)
|
||||
|
||||
return user_coupon
|
||||
|
||||
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ from sqlalchemy.sql import func
|
||||
from pydantic import BaseModel, Field
|
||||
from .database import Base
|
||||
import enum
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
class CouponStatus(str, enum.Enum):
|
||||
UNUSED = "UNUSED"
|
||||
@ -41,6 +42,23 @@ class UserCouponDB(Base):
|
||||
create_time = Column(DateTime(timezone=True), server_default=func.now())
|
||||
update_time = Column(DateTime(timezone=True), onupdate=func.now())
|
||||
|
||||
class CouponIssueRecordDB(Base):
|
||||
"""优惠券发放记录表"""
|
||||
__tablename__ = "coupon_issue_records"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
coupon_id = Column(Integer, ForeignKey("coupons.id"), nullable=False)
|
||||
user_id = Column(Integer, ForeignKey("users.userid"), nullable=False)
|
||||
operator_id = Column(Integer, ForeignKey("users.userid"), nullable=False) # 操作人ID
|
||||
count = Column(Integer, nullable=False, default=1) # 发放数量
|
||||
issue_time = Column(DateTime(timezone=True), nullable=False, server_default=func.now())
|
||||
remark = Column(String(200), nullable=True) # 备注信息
|
||||
|
||||
# 关联关系
|
||||
coupon = relationship("CouponDB", backref="issue_records")
|
||||
user = relationship("UserDB", foreign_keys=[user_id], backref="received_coupon_records")
|
||||
operator = relationship("UserDB", foreign_keys=[operator_id], backref="operated_coupon_records")
|
||||
|
||||
# Pydantic 模型
|
||||
class CouponCreate(BaseModel):
|
||||
name: str = Field(..., max_length=100)
|
||||
@ -66,6 +84,7 @@ class UserCouponCreate(BaseModel):
|
||||
user_id: int
|
||||
coupon_id: int
|
||||
expire_time: datetime
|
||||
remark: Optional[str] = None
|
||||
count: int = Field(..., gt=0, description="发放数量")
|
||||
|
||||
class UserCouponInfo(BaseModel):
|
||||
@ -82,3 +101,24 @@ class UserCouponInfo(BaseModel):
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
class CouponIssueRecordCreate(BaseModel):
|
||||
coupon_id: int
|
||||
user_id: int
|
||||
count: int = 1
|
||||
remark: Optional[str] = None
|
||||
|
||||
class CouponIssueRecordInfo(BaseModel):
|
||||
id: int
|
||||
coupon_id: int
|
||||
user_id: int
|
||||
operator_id: int
|
||||
count: int
|
||||
issue_time: datetime
|
||||
remark: Optional[str] = None
|
||||
coupon_name: Optional[str] = None
|
||||
user_nickname: Optional[str] = None
|
||||
operator_nickname: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
BIN
jobs.sqlite
BIN
jobs.sqlite
Binary file not shown.
Loading…
Reference in New Issue
Block a user