/** * Application Use Case: ProcessWalletTransactionUseCase * * Processes a wallet transaction (deposit or withdrawal). */ import type { IWalletRepository, ITransactionRepository } from '../../domain/repositories/IWalletRepository'; import type { Wallet, Transaction } from '../../domain/entities/Wallet'; import { TransactionType, ReferenceType } from '../../domain/entities/Wallet'; import type { UseCase } from '@core/shared/application/UseCase'; import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort'; import { Result } from '@core/shared/application/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; export interface ProcessWalletTransactionInput { leagueId: string; type: TransactionType; amount: number; description: string; referenceId?: string; referenceType?: ReferenceType; } export interface ProcessWalletTransactionResult { wallet: Wallet; transaction: Transaction; } export type ProcessWalletTransactionErrorCode = 'MISSING_REQUIRED_FIELDS' | 'INVALID_TYPE' | 'INSUFFICIENT_BALANCE'; export class ProcessWalletTransactionUseCase implements UseCase { constructor( private readonly walletRepository: IWalletRepository, private readonly transactionRepository: ITransactionRepository, private readonly output: UseCaseOutputPort, ) {} async execute(input: ProcessWalletTransactionInput): Promise>> { const { leagueId, type, amount, description, referenceId, referenceType } = input; if (!leagueId || !type || amount === undefined || !description) { return Result.err({ code: 'MISSING_REQUIRED_FIELDS' as const }); } if (type !== TransactionType.DEPOSIT && type !== TransactionType.WITHDRAWAL) { return Result.err({ code: 'INVALID_TYPE' as const }); } let wallet = await this.walletRepository.findByLeagueId(leagueId); if (!wallet) { const id = `wallet-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const newWallet: Wallet = { id, leagueId, balance: 0, totalRevenue: 0, totalPlatformFees: 0, totalWithdrawn: 0, currency: 'USD', createdAt: new Date(), }; wallet = await this.walletRepository.create(newWallet); } if (type === TransactionType.WITHDRAWAL) { if (amount > wallet.balance) { return Result.err({ code: 'INSUFFICIENT_BALANCE' as const }); } } const transactionId = `txn-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const transaction: Transaction = { id: transactionId, walletId: wallet.id, type, amount, description, createdAt: new Date(), ...(referenceId !== undefined ? { referenceId } : {}), ...(referenceType !== undefined ? { referenceType } : {}), }; const createdTransaction = await this.transactionRepository.create(transaction); if (type === TransactionType.DEPOSIT) { wallet.balance += amount; wallet.totalRevenue += amount; } else { wallet.balance -= amount; wallet.totalWithdrawn += amount; } const updatedWallet = await this.walletRepository.update(wallet); this.output.present({ wallet: updatedWallet, transaction: createdTransaction }); return Result.ok(undefined); } }