# -*- coding: utf-8 -*- """크레딧 충전/차감 (원장 기록). castad credit_service 패턴 축약.""" from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from .models import CreditTransaction, User class InsufficientCreditError(Exception): pass async def _record(session, user_uuid, amount, balance_after, type_, reason): tx = CreditTransaction( user_uuid=user_uuid, amount=amount, balance_after=balance_after, type=type_, reason=reason, ) session.add(tx) return tx async def charge(session: AsyncSession, user_uuid: str, amount: int, type_: str = "charge", reason: str | None = None): user = (await session.execute(select(User).where(User.user_uuid == user_uuid).with_for_update())).scalar_one_or_none() if user is None: raise ValueError("user not found") user.credits += amount await session.flush() return await _record(session, user_uuid, amount, user.credits, type_, reason) async def deduct(session: AsyncSession, user_uuid: str, amount: int, type_: str = "consume", reason: str | None = None): user = (await session.execute(select(User).where(User.user_uuid == user_uuid).with_for_update())).scalar_one_or_none() if user is None: raise ValueError("user not found") if user.credits < amount: raise InsufficientCreditError() user.credits -= amount await session.flush() return await _record(session, user_uuid, -amount, user.credits, type_, reason)