"""Wallet Engine repositories — Phase 7.6.""" from __future__ import annotations from uuid import UUID from sqlalchemy import func, select from app.models.types import WalletLedgerEntryType from app.models.wallet import WalletAccount, WalletLedgerEntry from app.repositories.base import TenantBaseRepository class WalletAccountRepository(TenantBaseRepository[WalletAccount]): model = WalletAccount async def get_by_member_program( self, tenant_id: UUID, program_id: UUID, member_id: UUID ) -> WalletAccount | None: stmt = select(WalletAccount).where( WalletAccount.tenant_id == tenant_id, WalletAccount.program_id == program_id, WalletAccount.member_id == member_id, WalletAccount.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() async def get_by_account_number( self, tenant_id: UUID, account_number: str ) -> WalletAccount | None: stmt = select(WalletAccount).where( WalletAccount.tenant_id == tenant_id, WalletAccount.account_number == account_number, WalletAccount.is_deleted.is_(False), ) result = await self.session.execute(stmt) return result.scalar_one_or_none() class WalletLedgerRepository(TenantBaseRepository[WalletLedgerEntry]): model = WalletLedgerEntry async def balance_for_account( self, tenant_id: UUID, wallet_account_id: UUID ) -> int: stmt = select(func.coalesce(func.sum(WalletLedgerEntry.amount), 0)).where( WalletLedgerEntry.tenant_id == tenant_id, WalletLedgerEntry.wallet_account_id == wallet_account_id, ) result = await self.session.execute(stmt) return int(result.scalar_one()) async def get_by_idempotency( self, tenant_id: UUID, idempotency_key: str | None ) -> WalletLedgerEntry | None: if not idempotency_key: return None stmt = select(WalletLedgerEntry).where( WalletLedgerEntry.tenant_id == tenant_id, WalletLedgerEntry.idempotency_key == idempotency_key, ) result = await self.session.execute(stmt) return result.scalar_one_or_none() async def list_for_account( self, tenant_id: UUID, wallet_account_id: UUID, *, entry_type: WalletLedgerEntryType | None = None, offset: int = 0, limit: int = 50, ): clauses = [ WalletLedgerEntry.tenant_id == tenant_id, WalletLedgerEntry.wallet_account_id == wallet_account_id, ] if entry_type is not None: clauses.append(WalletLedgerEntry.entry_type == entry_type) stmt = ( select(WalletLedgerEntry) .where(*clauses) .order_by(WalletLedgerEntry.created_at.desc()) .offset(offset) .limit(limit) ) result = await self.session.execute(stmt) return result.scalars().all() async def count_for_account( self, tenant_id: UUID, wallet_account_id: UUID, *, entry_type: WalletLedgerEntryType | None = None, ) -> int: clauses = [ WalletLedgerEntry.tenant_id == tenant_id, WalletLedgerEntry.wallet_account_id == wallet_account_id, ] if entry_type is not None: clauses.append(WalletLedgerEntry.entry_type == entry_type) stmt = select(func.count()).select_from(WalletLedgerEntry).where(*clauses) result = await self.session.execute(stmt) return int(result.scalar_one())