61 lines
1.7 KiB
Python
61 lines
1.7 KiB
Python
import uuid
|
|
from decimal import Decimal
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.models import User, Transaction
|
|
from app.core.exceptions import BadRequestError
|
|
|
|
# MVP: hardcoded redeem codes → amount mapping
|
|
REDEEM_CODES = {
|
|
"SUPERDREAM10": Decimal("10"),
|
|
"SUPERDREAM50": Decimal("50"),
|
|
"SUPERDREAM100": Decimal("100"),
|
|
}
|
|
|
|
|
|
class WalletService:
|
|
|
|
@staticmethod
|
|
async def get_balance(db: AsyncSession, user_id: str) -> Decimal:
|
|
user = await db.get(User, user_id)
|
|
return user.balance
|
|
|
|
@staticmethod
|
|
async def redeem_code(db: AsyncSession, user_id: str, code: str) -> Transaction:
|
|
amount = REDEEM_CODES.get(code.upper())
|
|
if not amount:
|
|
raise BadRequestError("无效的兑换码")
|
|
|
|
user = await db.get(User, user_id)
|
|
user.balance += amount
|
|
new_balance = user.balance
|
|
|
|
txn = Transaction(
|
|
id=str(uuid.uuid4()),
|
|
user_id=user_id,
|
|
type="topup",
|
|
amount=amount,
|
|
balance_after=new_balance,
|
|
reference_id=f"redeem:{code.upper()}",
|
|
)
|
|
db.add(txn)
|
|
await db.commit()
|
|
await db.refresh(txn)
|
|
return txn
|
|
|
|
@staticmethod
|
|
async def list_transactions(
|
|
db: AsyncSession, user_id: str, page: int = 1, size: int = 20
|
|
) -> list:
|
|
offset = (page - 1) * size
|
|
result = await db.execute(
|
|
select(Transaction)
|
|
.where(Transaction.user_id == user_id)
|
|
.order_by(Transaction.created_at.desc())
|
|
.offset(offset)
|
|
.limit(size)
|
|
)
|
|
return result.scalars().all()
|