Files
DP/Server/app/api/v1/feature.py

133 lines
4.6 KiB
Python
Raw Permalink 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.
# -*- coding: utf-8 -*-
"""
通用功能使用接口
核心动态扣费逻辑SVIP免费、VIP配额、普通积分
"""
from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel
from datetime import date
from sqlalchemy.orm import Session
from app.db import get_db
from app.models.user import User
from app.models.business import FeatureConfig, VipConfig, PointsHistory
from app.core.security import get_current_user
router = APIRouter()
# ==================== 数据模型 ====================
class UseFeatureRequest(BaseModel):
feature_key: str
# ==================== 通用功能使用 ====================
@router.post("/feature/use")
async def use_feature(data: UseFeatureRequest, db: Session = Depends(get_db), current_username: str = Depends(get_current_user)):
"""
通用功能使用接口
逻辑:
1. SVIP用户免费使用
2. VIP用户优先使用配额配额用完后扣积分
3. 普通用户:扣除积分
"""
# 1. 获取功能配置
feature = db.query(FeatureConfig).filter(FeatureConfig.feature_key == data.feature_key).first()
if not feature or not feature.enabled:
raise HTTPException(status_code=400, detail="功能不存在或已禁用")
# 2. 获取用户信息
user = db.query(User).filter(User.username == current_username).first()
if not user:
raise HTTPException(status_code=404, detail="用户不存在")
current_points = user.points if user.points else 0
vip_type = user.vip_type
vip_quota = user.vip_daily_quota if user.vip_daily_quota else 0
quota_reset_date = user.vip_quota_reset_date
# 3. 检查并重置VIP配额
today = date.today()
if vip_type in ['vip', 'svip'] and quota_reset_date != today:
# 重置配额
vip_config = db.query(VipConfig).filter(VipConfig.vip_type == vip_type).first()
if vip_config:
vip_quota = vip_config.daily_quota
user.vip_daily_quota = vip_quota
user.vip_quota_reset_date = today
db.commit()
# 4. 判断消耗类型
cost_type = "points"
points_cost = 0
remaining_quota = vip_quota
# SVIP免费
if vip_type == 'svip' and feature.svip_points_cost == 0:
cost_type = "free"
message = "SVIP用户免费使用"
# VIP配额
elif vip_type == 'vip' and vip_quota > 0 and feature.vip_points_cost == 0:
cost_type = "vip_quota"
remaining_quota = vip_quota - 1
user.vip_daily_quota = remaining_quota
db.commit()
message = f"VIP配额使用剩余{remaining_quota}"
# 扣积分
else:
# 计算实际消耗
if vip_type == 'vip' and feature.vip_points_cost > 0:
points_cost = feature.vip_points_cost
elif vip_type == 'svip' and feature.svip_points_cost > 0:
points_cost = feature.svip_points_cost
else:
points_cost = feature.points_cost
# 检查余额
if current_points < points_cost:
raise HTTPException(
status_code=402,
detail=f"积分不足。当前: {current_points},需要: {points_cost}。请签到获取积分或开通VIP"
)
# 扣除积分
new_balance = current_points - points_cost
user.points = new_balance
# 记录积分历史
points_history = PointsHistory(
user_id=user.id,
username=current_username,
type='consume',
amount=-points_cost,
balance=new_balance,
description=f"使用{feature.feature_name}"
)
db.add(points_history)
db.commit()
message = f"消耗{points_cost}积分,剩余{new_balance}积分"
# 5. 记录使用日志 (TODO: Add FeatureUsageLogs model if needed, currently skipping or adding to PointsHistory if consumed)
# For now, we only log if points consumed. If we need separate usage log table, we need to create it.
# The SQL version inserted into feature_usage_logs.
# Let's assume PointsHistory covers financial aspect.
# If we need analytics, we have analytics API.
# 6. 返回结果
return {
"code": 200,
"data": {
"success": True,
"feature_name": feature.feature_name,
"cost_type": cost_type,
"points_cost": points_cost,
"vip_remaining_quota": remaining_quota if vip_type in ['vip', 'svip'] else None,
"points_remaining": user.points,
"message": message
}
}