"""资金账户服务:余额查询 + 余额加减(路由层只编排,不碰数据/逻辑)。""" from __future__ import annotations from decimal import Decimal from sqlalchemy.ext.asyncio import AsyncSession from model.fin_account import FinAccount from model.sys_user import SysUser from repositories.fin_account import FinAccountRepo from schemas.account import BalanceResp from utils.exceptions import ForbiddenError, NotFoundError, ParamError _ZERO = Decimal("0.00") _DEFAULT_CURRENCY = "CNY" def _build_balance_resp(account: FinAccount) -> BalanceResp: return BalanceResp( customer_id=account.customer_id, balance=account.balance, available_balance=account.balance - account.frozen_amount, frozen_amount=account.frozen_amount, currency=account.currency, status=account.status, update_time=account.update_time, ) async def get_balance(db: AsyncSession, user: SysUser) -> BalanceResp: """查询当前用户现金余额。 - 仅客户账号可查(员工共用 sys_user,但无资金账户); - 未开资金户时按零余额返回,不报错。 """ if user.user_type != "CUSTOMER": raise ForbiddenError("仅客户账号可查询资金余额") account = await FinAccountRepo(db).get_by_customer_id(user.id) if account is None: return BalanceResp( customer_id=user.id, balance=_ZERO, available_balance=_ZERO, frozen_amount=_ZERO, currency=_DEFAULT_CURRENCY, status="正常", ) return _build_balance_resp(account) async def adjust_balance( db: AsyncSession, user: SysUser, direction: str, amount: Decimal ) -> BalanceResp: """加减余额:direction=add 入账 / sub 出账。 - add:balance += amount,未开资金户时自动开户入账; - sub:balance -= amount,可用余额(balance - frozen_amount)不足时报错。 """ if user.user_type != "CUSTOMER": raise ForbiddenError("仅客户账号可调整余额") repo = FinAccountRepo(db) account = await repo.get_by_customer_id(user.id) if direction == "add": if account is None: account = await repo.create(user.id, amount) else: account = await repo.add_balance(user.id, amount) else: # sub if account is None: raise NotFoundError("资金账户不存在") updated = await repo.subtract_balance(user.id, amount) if updated is None: raise ParamError("可用余额不足") account = updated return _build_balance_resp(account)