73 lines
2.1 KiB
Python
73 lines
2.1 KiB
Python
from sqlalchemy.orm import Session
|
|
from app.models.user_account import UserAccountDB, AccountDetailDB, AccountDetailType
|
|
from decimal import Decimal
|
|
from typing import Optional
|
|
|
|
class AccountManager:
|
|
"""用户账户管理类"""
|
|
|
|
def __init__(self, db: Session):
|
|
self.db = db
|
|
|
|
def get_or_create_account(self, user_id: int) -> UserAccountDB:
|
|
"""获取或创建用户账户"""
|
|
account = self.db.query(UserAccountDB).filter(
|
|
UserAccountDB.user_id == user_id
|
|
).first()
|
|
|
|
if not account:
|
|
account = UserAccountDB(
|
|
user_id=user_id,
|
|
balance=0
|
|
)
|
|
self.db.add(account)
|
|
self.db.flush()
|
|
|
|
return account
|
|
|
|
def change_balance(
|
|
self,
|
|
user_id: int,
|
|
amount: float,
|
|
description: str,
|
|
transaction_id: Optional[str] = None
|
|
) -> UserAccountDB:
|
|
"""
|
|
变更用户余额
|
|
|
|
Args:
|
|
user_id: 用户ID
|
|
amount: 变更金额(正数为收入,负数为支出)
|
|
description: 变更说明
|
|
transaction_id: 关联订单号
|
|
|
|
Returns:
|
|
更新后的账户信息
|
|
|
|
Raises:
|
|
Exception: 余额不足等异常
|
|
"""
|
|
# 转换为 Decimal 以确保精确计算
|
|
decimal_amount = Decimal(str(amount))
|
|
|
|
# 获取或创建账户
|
|
account = self.get_or_create_account(user_id)
|
|
|
|
# 检查余额是否充足(支出时)
|
|
if decimal_amount < 0 and account.balance + decimal_amount < 0:
|
|
raise Exception("账户余额不足")
|
|
|
|
# 更新余额
|
|
account.balance += decimal_amount
|
|
|
|
# 记录账户明细
|
|
detail = AccountDetailDB(
|
|
user_id=user_id,
|
|
amount=decimal_amount,
|
|
type=AccountDetailType.INCOME if decimal_amount > 0 else AccountDetailType.EXPENSE,
|
|
description=description,
|
|
transaction_id=transaction_id
|
|
)
|
|
self.db.add(detail)
|
|
|
|
return account |