from fastapi import HTTPException from sqlalchemy.orm import Session from models.credit import CreditAccount, CreditTransaction from models.user import User DEFAULT_CREDIT_BALANCE = 130 DAILY_CHECKIN_CREDITS = 10 CREDIT_COSTS = { "courseware_generate": 8, "animation_generate": 6, "exercise_generate": 4, "lesson_plan_generate": 5, "exam_generate": 5, "essay_grade": 2, "chat_generate": 1, "material_parse": 1, } def ensure_credit_account(db: Session, user: User) -> CreditAccount: account = db.query(CreditAccount).filter(CreditAccount.user_id == user.id).first() if account: return account account = CreditAccount( user_id=user.id, balance=DEFAULT_CREDIT_BALANCE, total_granted=DEFAULT_CREDIT_BALANCE, total_used=0, ) db.add(account) db.flush() return account def spend_credits(db: Session, user: User, action: str, description: str = "") -> CreditAccount: cost = CREDIT_COSTS.get(action, 1) account = ensure_credit_account(db, user) if account.balance < cost: raise HTTPException(status_code=402, detail=f"积分不足,本次需要 {cost} 分,当前剩余 {account.balance} 分") account.balance -= cost account.total_used += cost db.add(CreditTransaction( user_id=user.id, amount=-cost, action=action, description=description, balance_after=account.balance, )) db.flush() return account def credits_payload(account: CreditAccount, action: str) -> dict: return { "balance": account.balance, "cost": CREDIT_COSTS.get(action, 1), "action": action, } def grant_credits(db: Session, user: User, amount: int, action: str = "grant", description: str = "") -> CreditAccount: if amount <= 0: raise HTTPException(status_code=400, detail="积分数量必须大于 0") account = ensure_credit_account(db, user) account.balance += amount account.total_granted += amount db.add(CreditTransaction( user_id=user.id, amount=amount, action=action, description=description, balance_after=account.balance, )) db.flush() return account def has_credit_transaction_today(db: Session, user: User, action: str) -> bool: from datetime import datetime, time today = datetime.now().date() start = datetime.combine(today, time.min) end = datetime.combine(today, time.max) return db.query(CreditTransaction).filter( CreditTransaction.user_id == user.id, CreditTransaction.action == action, CreditTransaction.created_at >= start, CreditTransaction.created_at <= end, ).first() is not None def grant_daily_checkin(db: Session, user: User) -> CreditAccount: if has_credit_transaction_today(db, user, "daily_checkin"): raise HTTPException(status_code=409, detail="今日积分已领取") return grant_credits( db, user, DAILY_CHECKIN_CREDITS, action="daily_checkin", description="每日登录领取积分", )