Files
Mutual_Fund/repositories/fin_account.py
T
2026-09-10 23:21:30 +08:00

98 lines
3.6 KiB
Python
Raw 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.
"""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