179 lines
6.2 KiB
Python
179 lines
6.2 KiB
Python
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() |