105 lines
3.6 KiB
TypeScript
105 lines
3.6 KiB
TypeScript
import type { ILeagueWalletRepository } from '../../domain/repositories/ILeagueWalletRepository';
|
|
import type { ITransactionRepository } from '../../domain/repositories/ITransactionRepository';
|
|
import type { GetLeagueWalletOutputPort, WalletTransactionOutputPort } from '../ports/output/GetLeagueWalletOutputPort';
|
|
import type { TransactionType } from '../../domain/entities/league-wallet/Transaction';
|
|
import { Result } from '@core/shared/application/Result';
|
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
|
|
|
export interface GetLeagueWalletUseCaseParams {
|
|
leagueId: string;
|
|
}
|
|
|
|
/**
|
|
* Use Case for retrieving league wallet information.
|
|
*/
|
|
export class GetLeagueWalletUseCase {
|
|
constructor(
|
|
private readonly leagueWalletRepository: ILeagueWalletRepository,
|
|
private readonly transactionRepository: ITransactionRepository,
|
|
) {}
|
|
|
|
async execute(
|
|
params: GetLeagueWalletUseCaseParams,
|
|
): Promise<Result<GetLeagueWalletOutputPort, ApplicationErrorCode<'REPOSITORY_ERROR'>>> {
|
|
try {
|
|
const wallet = await this.leagueWalletRepository.findByLeagueId(params.leagueId);
|
|
|
|
if (!wallet) {
|
|
return Result.err({ code: 'REPOSITORY_ERROR', message: 'Wallet not found' });
|
|
}
|
|
|
|
const transactions = await this.transactionRepository.findByWalletId(wallet.id.toString());
|
|
|
|
let totalRevenue = 0;
|
|
let totalFees = 0;
|
|
let totalWithdrawals = 0;
|
|
let pendingPayouts = 0;
|
|
|
|
const transactionViewModels: WalletTransactionOutputPort[] = transactions
|
|
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
|
|
.map(transaction => {
|
|
const amount = transaction.amount.amount;
|
|
const fee = transaction.platformFee.amount;
|
|
const netAmount = transaction.netAmount.amount;
|
|
|
|
if (
|
|
transaction.type === 'sponsorship_payment' ||
|
|
transaction.type === 'membership_payment' ||
|
|
transaction.type === 'prize_payout'
|
|
) {
|
|
totalRevenue += amount;
|
|
totalFees += fee;
|
|
}
|
|
|
|
if (transaction.type === 'withdrawal' && transaction.status === 'completed') {
|
|
totalWithdrawals += netAmount;
|
|
}
|
|
|
|
if (transaction.type === 'prize_payout' && transaction.status === 'pending') {
|
|
pendingPayouts += netAmount;
|
|
}
|
|
|
|
return {
|
|
id: transaction.id.toString(),
|
|
type: this.mapTransactionType(transaction.type),
|
|
description: transaction.description ?? '',
|
|
amount,
|
|
fee,
|
|
netAmount,
|
|
date: transaction.createdAt.toISOString(),
|
|
status: transaction.status === 'cancelled' ? 'failed' : transaction.status,
|
|
};
|
|
});
|
|
|
|
const output: GetLeagueWalletOutputPort = {
|
|
balance: wallet.balance.amount,
|
|
currency: wallet.balance.currency,
|
|
totalRevenue,
|
|
totalFees,
|
|
totalWithdrawals,
|
|
pendingPayouts,
|
|
canWithdraw: true,
|
|
transactions: transactionViewModels,
|
|
};
|
|
|
|
return Result.ok(output);
|
|
} catch {
|
|
return Result.err({ code: 'REPOSITORY_ERROR', message: 'Failed to fetch league wallet' });
|
|
}
|
|
}
|
|
|
|
private mapTransactionType(type: TransactionType): WalletTransactionOutputPort['type'] {
|
|
switch (type) {
|
|
case 'sponsorship_payment':
|
|
return 'sponsorship';
|
|
case 'membership_payment':
|
|
return 'membership';
|
|
case 'prize_payout':
|
|
return 'prize';
|
|
case 'withdrawal':
|
|
return 'withdrawal';
|
|
case 'refund':
|
|
return 'sponsorship';
|
|
}
|
|
}
|
|
} |