refactor
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Application Use Case: ProcessWalletTransactionUseCase
|
||||
*
|
||||
* Processes a wallet transaction (deposit or withdrawal).
|
||||
*/
|
||||
|
||||
import type { IWalletRepository, ITransactionRepository } from '../../domain/repositories/IWalletRepository';
|
||||
import type { Wallet, Transaction, TransactionType, ReferenceType } from '../../domain/entities/Wallet';
|
||||
import type {
|
||||
IProcessWalletTransactionPresenter,
|
||||
ProcessWalletTransactionResultDTO,
|
||||
ProcessWalletTransactionViewModel,
|
||||
} from '../presenters/IProcessWalletTransactionPresenter';
|
||||
import type { UseCase } from '@gridpilot/shared/application/UseCase';
|
||||
|
||||
export interface ProcessWalletTransactionInput {
|
||||
leagueId: string;
|
||||
type: TransactionType;
|
||||
amount: number;
|
||||
description: string;
|
||||
referenceId?: string;
|
||||
referenceType?: ReferenceType;
|
||||
}
|
||||
|
||||
export class ProcessWalletTransactionUseCase
|
||||
implements UseCase<ProcessWalletTransactionInput, ProcessWalletTransactionResultDTO, ProcessWalletTransactionViewModel, IProcessWalletTransactionPresenter>
|
||||
{
|
||||
constructor(
|
||||
private readonly walletRepository: IWalletRepository,
|
||||
private readonly transactionRepository: ITransactionRepository,
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
input: ProcessWalletTransactionInput,
|
||||
presenter: IProcessWalletTransactionPresenter,
|
||||
): Promise<void> {
|
||||
presenter.reset();
|
||||
|
||||
const { leagueId, type, amount, description, referenceId, referenceType } = input;
|
||||
|
||||
if (!leagueId || !type || amount === undefined || !description) {
|
||||
throw new Error('Missing required fields: leagueId, type, amount, description');
|
||||
}
|
||||
|
||||
if (type !== ('deposit' as TransactionType) && type !== ('withdrawal' as TransactionType)) {
|
||||
throw new Error('Type must be "deposit" or "withdrawal"');
|
||||
}
|
||||
|
||||
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 === ('withdrawal' as TransactionType)) {
|
||||
if (amount > wallet.balance) {
|
||||
throw new Error('Insufficient balance');
|
||||
}
|
||||
}
|
||||
|
||||
const transactionId = `txn-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
const transaction: Transaction = {
|
||||
id: transactionId,
|
||||
walletId: wallet.id,
|
||||
type,
|
||||
amount,
|
||||
description,
|
||||
referenceId,
|
||||
referenceType,
|
||||
createdAt: new Date(),
|
||||
};
|
||||
|
||||
const createdTransaction = await this.transactionRepository.create(transaction);
|
||||
|
||||
if (type === ('deposit' as TransactionType)) {
|
||||
wallet.balance += amount;
|
||||
wallet.totalRevenue += amount;
|
||||
} else {
|
||||
wallet.balance -= amount;
|
||||
wallet.totalWithdrawn += amount;
|
||||
}
|
||||
|
||||
const updatedWallet = await this.walletRepository.update(wallet);
|
||||
|
||||
const dto: ProcessWalletTransactionResultDTO = {
|
||||
wallet: {
|
||||
id: updatedWallet.id,
|
||||
leagueId: updatedWallet.leagueId,
|
||||
balance: updatedWallet.balance,
|
||||
totalRevenue: updatedWallet.totalRevenue,
|
||||
totalPlatformFees: updatedWallet.totalPlatformFees,
|
||||
totalWithdrawn: updatedWallet.totalWithdrawn,
|
||||
currency: updatedWallet.currency,
|
||||
createdAt: updatedWallet.createdAt,
|
||||
},
|
||||
transaction: {
|
||||
id: createdTransaction.id,
|
||||
walletId: createdTransaction.walletId,
|
||||
type: createdTransaction.type,
|
||||
amount: createdTransaction.amount,
|
||||
description: createdTransaction.description,
|
||||
referenceId: createdTransaction.referenceId,
|
||||
referenceType: createdTransaction.referenceType,
|
||||
createdAt: createdTransaction.createdAt,
|
||||
},
|
||||
};
|
||||
|
||||
presenter.present(dto);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user