Files
Mutual_Fund/repositories/fin_account.py
T

98 lines
3.6 KiB
Python
Raw Normal View History

2026-09-10 23:21:30 +08:00
"""fin_account 仓储:按客户 ID 取资金账户 + 余额加减(原子 UPDATE)。
注:本表主键为 customer_id(非 id),故不复用 BaseRepository.delete/count 中的 id 约定。
余额增减用原子 UPDATE(balance = balance ± delta)防并发丢更新,不依赖乐观锁重试。
"""
from __future__ import annotations
from decimal import Decimal
from sqlalchemy import select, update
from model.fin_account import FinAccount
from repositories.base import BaseRepository
class FinAccountRepo(BaseRepository):
model = FinAccount
async def get_by_customer_id(self, customer_id: int) -> FinAccount | None:
return await self.db.scalar(
select(FinAccount).where(FinAccount.customer_id == customer_id)
)
async def create(self, customer_id: int, balance: Decimal) -> FinAccount:
"""开资金户(充值时账户不存在则自动开户入账)。"""
account = FinAccount(customer_id=customer_id, balance=balance)
self.db.add(account)
await self.db.commit()
await self.db.refresh(account)
return account
async def add_balance(self, customer_id: int, delta: Decimal) -> FinAccount:
"""入账:balance += delta,原子自增后回读最新余额。"""
await self.db.execute(
update(FinAccount)
.where(FinAccount.customer_id == customer_id)
.values(
balance=FinAccount.balance + delta,
version=FinAccount.version + 1,
)
)
await self.db.commit()
return await self.get_by_customer_id(customer_id)
async def subtract_balance(
self, customer_id: int, delta: Decimal
) -> FinAccount | None:
"""出账:balance -= delta,可用余额(balance - frozen_amount)不足时返回 None。"""
result = await self.db.execute(
update(FinAccount)
.where(
FinAccount.customer_id == customer_id,
FinAccount.balance - FinAccount.frozen_amount >= delta,
)
.values(
balance=FinAccount.balance - delta,
version=FinAccount.version + 1,
)
)
await self.db.commit()
if result.rowcount == 0:
return None
return await self.get_by_customer_id(customer_id)
async def deduct_balance(self, customer_id: int, delta: Decimal) -> bool:
"""申购事务内扣款:balance -= delta(可用余额不足则不动)。
不 commit,由 service 层事务统一提交,保证「扣款 + 加仓」原子性。
可用余额(balance - frozen_amount)不足时返回 False。
"""
result = await self.db.execute(
update(FinAccount)
.where(
FinAccount.customer_id == customer_id,
FinAccount.balance - FinAccount.frozen_amount >= delta,
)
.values(
balance=FinAccount.balance - delta,
version=FinAccount.version + 1,
)
)
return result.rowcount > 0
async def credit_balance(self, customer_id: int, delta: Decimal) -> bool:
"""赎回事务内入账:balance += delta。
不 commit,由 service 层事务统一提交,保证「减仓 + 入账」原子性。
"""
result = await self.db.execute(
update(FinAccount)
.where(FinAccount.customer_id == customer_id)
.values(
balance=FinAccount.balance + delta,
version=FinAccount.version + 1,
)
)
return result.rowcount > 0