table_game/backend/app/services/user_coupon_service.py

179 lines
6.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from fastapi import HTTPException
from datetime import datetime
from ..db import get_connection
from ..utils.jwt_handler import verify_token
def get_user_coupons_service(token: str):
"""获取用户所有优惠券"""
try:
payload = verify_token(token)
# 新增通过phone_number查询用户ID
connection = get_connection()
cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT user_id FROM users WHERE phone_number = %s", (payload["sub"],))
user = cursor.fetchone()
if not user:
raise HTTPException(status_code=404, detail="用户不存在")
user_id = user['user_id']
# 获取有效期内且未被使用的优惠券
cursor.execute("""
SELECT c.*
FROM user_coupons uc
JOIN coupons c ON uc.coupon_id = c.coupon_id
WHERE uc.user_id = %s
AND c.valid_from <= NOW()
AND c.valid_to >= NOW()
""", (user_id,))
coupons = []
for coupon in cursor.fetchall():
# 生成描述文字
if coupon['discount_type'] == 'fixed':
desc = f"{coupon['min_order_amount'] or 0}元,减{coupon['discount_amount']}"
else:
# 转换百分比折扣为中文如85 -> 八五折)
discount = int(coupon['discount_amount'])
chinese_num = ''.join(['〇一二三四五六七八九'[int(d)] for d in str(discount)])
desc = f"{coupon['min_order_amount'] or 0}元,打{chinese_num}"
coupons.append({
"coupon_id": coupon['coupon_id'],
"description": desc
})
return coupons
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
def apply_coupon_service(token: str, coupon_id: int, order_id: float):
"""使用优惠券计算价格"""
try:
payload = verify_token(token)
# 新增通过phone_number查询用户ID
connection = get_connection()
cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT user_id FROM users WHERE phone_number = %s", (payload["sub"],))
user = cursor.fetchone()
if not user:
raise HTTPException(status_code=404, detail="用户不存在")
user_id = user['user_id']
# 验证优惠券归属
cursor.execute("""
SELECT c.*
FROM user_coupons uc
JOIN coupons c ON uc.coupon_id = c.coupon_id
WHERE uc.user_id = %s
AND uc.coupon_id = %s
AND c.valid_from <= NOW()
AND c.valid_to >= NOW()
LIMIT 1
""", (user_id, coupon_id))
coupon = cursor.fetchone()
if not coupon:
raise HTTPException(status_code=400, detail="无效优惠券")
# print(coupon)
discount_amount = float(coupon['discount_amount'])
min_order_amount = float(coupon['min_order_amount']) if coupon['min_order_amount'] else None
# discount_amount = 0.0
# min_order_amount = 0.0
cursor.execute("""
SELECT payable_price
FROM orders
WHERE order_id = %s
AND user_id = %s
AND order_status = 'pending'
""", (order_id, user['user_id']))
order = cursor.fetchone()
price = float(order['payable_price'])
# 检查最低消费
if coupon['min_order_amount'] and price < min_order_amount:
raise HTTPException(status_code=400, detail="未达到最低消费金额")
# 计算折扣
if coupon['discount_type'] == 'fixed':
final_price = max(price - discount_amount, 0)
else:
discount = price * (discount_amount / 100)
final_price = max(discount, 0)
return {"final_price": round(final_price, 2)}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
finally:
cursor.close()
connection.close()
def redeem_coupon_service(token: str, code: str):
"""用户兑换优惠券"""
try:
# 验证用户身份
payload = verify_token(token)
connection = get_connection()
cursor = connection.cursor(dictionary=True)
# 获取用户ID
cursor.execute("SELECT user_id FROM users WHERE phone_number = %s", (payload["sub"],))
user = cursor.fetchone()
if not user:
raise HTTPException(status_code=404, detail="用户不存在")
user_id = user['user_id']
# 查询优惠券
cursor.execute("""
SELECT coupon_id, valid_from, valid_to, quantity
FROM coupons
WHERE coupon_code = %s
FOR UPDATE
""", (code,))
coupon = cursor.fetchone()
if not coupon:
raise HTTPException(status_code=201, detail="券码不存在")
# 检查有效期
current_time = datetime.now()
if current_time < coupon['valid_from']:
raise HTTPException(status_code=202, detail="券码已过期")
if current_time > coupon['valid_to']:
raise HTTPException(status_code=202, detail="券码已过期")
# 检查库存并减少
cursor.execute("""
UPDATE coupons
SET quantity = quantity - 1
WHERE coupon_id = %s
AND quantity > 0
""", (coupon['coupon_id'],))
if cursor.rowcount == 0:
raise HTTPException(status_code=203, detail="券码库存不足")
# 添加用户优惠券关联
cursor.execute("""
INSERT INTO user_coupons (user_id, coupon_id)
VALUES (%s, %s)
""", (user_id, coupon['coupon_id']))
connection.commit()
print("coupon redeemed successfully")
return {"code": 200, "message": "优惠券发放成功"}
except HTTPException:
# 直接重新抛出已捕获的HTTPException
raise
except Exception as e:
connection.rollback()
raise HTTPException(status_code=500, detail=str(e))
finally:
cursor.close()
connection.close()