Files
gridpilot.gg/core/payments/application/use-cases/ProcessWalletTransactionUseCase.ts
2026-01-16 13:48:18 +01:00

98 lines
3.3 KiB
TypeScript

/**
* Application Use Case: ProcessWalletTransactionUseCase
*
* Processes a wallet transaction (deposit or withdrawal).
*/
import type { WalletRepository, ITransactionRepository } from '../../domain/repositories/WalletRepository';
import type { Wallet, Transaction } from '../../domain/entities/Wallet';
import { TransactionType, ReferenceType } from '../../domain/entities/Wallet';
import type { UseCase } from '@core/shared/application/UseCase';
import { Result } from '@core/shared/domain/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<ProcessWalletTransactionInput, ProcessWalletTransactionResult, ProcessWalletTransactionErrorCode>
{
constructor(
private readonly walletRepository: IWalletRepository,
private readonly transactionRepository: ITransactionRepository,
) {}
async execute(input: ProcessWalletTransactionInput): Promise<Result<ProcessWalletTransactionResult, ApplicationErrorCode<ProcessWalletTransactionErrorCode>>> {
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);
return Result.ok({ wallet: updatedWallet, transaction: createdTransaction });
}
}