TorbatYar/backend/services/loyalty/app/repositories/wallet.py
Mortezakoohjani 071c484530 Ship Loyalty phases 7.2-7.6 (points through wallet) with production deploy.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-26 21:27:22 +03:30

106 lines
3.7 KiB
Python

"""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())