"""Wallet Engine validators — Phase 7.6.""" from __future__ import annotations from shared.exceptions import AppError from app.models.types import WalletAccountStatus, WalletLedgerEntryType def validate_wallet_account_status( status: WalletAccountStatus | str, ) -> WalletAccountStatus: if isinstance(status, WalletAccountStatus): return status try: return WalletAccountStatus(status) except ValueError as exc: raise AppError( "وضعیت کیف پول نامعتبر است", status_code=422, error_code="invalid_wallet_account_status", ) from exc def ensure_wallet_open(status: WalletAccountStatus) -> None: if status == WalletAccountStatus.CLOSED: raise AppError( "کیف پول بسته است", status_code=409, error_code="wallet_account_closed", ) if status == WalletAccountStatus.FROZEN: raise AppError( "کیف پول مسدود است", status_code=409, error_code="wallet_account_frozen", ) def validate_positive_amount(amount: int, *, field: str = "amount") -> int: if amount is None or amount <= 0: raise AppError( f"{field} باید بزرگ‌تر از صفر باشد", status_code=422, error_code="invalid_wallet_amount", details={"field": field}, ) return amount def validate_adjust_amount(amount: int) -> int: if amount == 0: raise AppError( "مقدار تعدیل نمی‌تواند صفر باشد", status_code=422, error_code="invalid_wallet_adjust_amount", ) return amount def signed_amount(entry_type: WalletLedgerEntryType, amount: int) -> int: if entry_type in {WalletLedgerEntryType.CREDIT, WalletLedgerEntryType.TRANSFER_IN}: return abs(amount) if entry_type in {WalletLedgerEntryType.DEBIT, WalletLedgerEntryType.TRANSFER_OUT}: return -abs(amount) # ADJUST: caller supplies signed amount return amount def ensure_sufficient_funds(balance: int, new_balance: int, *, requested: int) -> None: if new_balance < 0: raise AppError( "موجودی کیف پول کافی نیست", status_code=409, error_code="wallet_insufficient_funds", details={"balance": balance, "requested": requested}, ) def ensure_same_currency(source_currency: str, target_currency: str) -> None: if source_currency != target_currency: raise AppError( "انتقال بین ارزهای متفاوت مجاز نیست", status_code=422, error_code="wallet_currency_mismatch", details={"source": source_currency, "target": target_currency}, ) def ensure_not_same_account(source_id, target_id) -> None: if source_id == target_id: raise AppError( "انتقال به همان کیف پول مجاز نیست", status_code=422, error_code="wallet_transfer_same_account", )