136 lines
4.1 KiB
TypeScript
136 lines
4.1 KiB
TypeScript
import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository';
|
|
import type { ILeagueWalletRepository } from '../../domain/repositories/ILeagueWalletRepository';
|
|
import type { ITransactionRepository } from '../../domain/repositories/ITransactionRepository';
|
|
import type { Transaction } from '../../domain/entities/league-wallet/Transaction';
|
|
import type { LeagueWallet } from '../../domain/entities/league-wallet/LeagueWallet';
|
|
import type { UseCaseOutputPort } from '@core/shared/application';
|
|
import { Result } from '@core/shared/application/Result';
|
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
|
import { Money } from '../../domain/value-objects/Money';
|
|
|
|
export type GetLeagueWalletErrorCode =
|
|
| 'LEAGUE_NOT_FOUND'
|
|
| 'WALLET_NOT_FOUND'
|
|
| 'REPOSITORY_ERROR';
|
|
|
|
export interface GetLeagueWalletInput {
|
|
leagueId: string;
|
|
}
|
|
|
|
export interface GetLeagueWalletAggregates {
|
|
balance: Money;
|
|
totalRevenue: Money;
|
|
totalFees: Money;
|
|
totalWithdrawals: Money;
|
|
pendingPayouts: Money;
|
|
}
|
|
|
|
export interface GetLeagueWalletResult {
|
|
wallet: LeagueWallet;
|
|
transactions: Transaction[];
|
|
aggregates: GetLeagueWalletAggregates;
|
|
}
|
|
|
|
/**
|
|
* Use Case for retrieving league wallet information.
|
|
*/
|
|
export class GetLeagueWalletUseCase {
|
|
constructor(
|
|
private readonly leagueRepository: ILeagueRepository,
|
|
private readonly leagueWalletRepository: ILeagueWalletRepository,
|
|
private readonly transactionRepository: ITransactionRepository,
|
|
private readonly output: UseCaseOutputPort<GetLeagueWalletResult>,
|
|
) {}
|
|
|
|
async execute(
|
|
input: GetLeagueWalletInput,
|
|
): Promise<
|
|
Result<void, ApplicationErrorCode<GetLeagueWalletErrorCode, { message: string }>>
|
|
> {
|
|
try {
|
|
const leagueExists = await this.leagueRepository.exists(input.leagueId);
|
|
if (!leagueExists) {
|
|
return Result.err({
|
|
code: 'LEAGUE_NOT_FOUND',
|
|
details: { message: 'League not found' },
|
|
});
|
|
}
|
|
|
|
const wallet = await this.leagueWalletRepository.findByLeagueId(input.leagueId);
|
|
|
|
if (!wallet) {
|
|
return Result.err({
|
|
code: 'WALLET_NOT_FOUND',
|
|
details: { message: 'League wallet not found' },
|
|
});
|
|
}
|
|
|
|
const transactions = await this.transactionRepository.findByWalletId(
|
|
wallet.id.toString(),
|
|
);
|
|
|
|
const { aggregates } = this.computeAggregates(wallet.balance, transactions);
|
|
|
|
const result: GetLeagueWalletResult = {
|
|
wallet,
|
|
transactions: transactions
|
|
.slice()
|
|
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()),
|
|
aggregates,
|
|
};
|
|
|
|
this.output.present(result);
|
|
|
|
return Result.ok(undefined);
|
|
} catch (error) {
|
|
return Result.err({
|
|
code: 'REPOSITORY_ERROR',
|
|
details: {
|
|
message:
|
|
error instanceof Error
|
|
? error.message
|
|
: 'Failed to fetch league wallet',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
private computeAggregates(
|
|
balance: Money,
|
|
transactions: Transaction[],
|
|
): { aggregates: GetLeagueWalletAggregates } {
|
|
let totalRevenue = Money.create(0, balance.currency);
|
|
let totalFees = Money.create(0, balance.currency);
|
|
let totalWithdrawals = Money.create(0, balance.currency);
|
|
let pendingPayouts = Money.create(0, balance.currency);
|
|
|
|
for (const transaction of transactions) {
|
|
if (
|
|
transaction.type === 'sponsorship_payment' ||
|
|
transaction.type === 'membership_payment' ||
|
|
transaction.type === 'prize_payout'
|
|
) {
|
|
totalRevenue = totalRevenue.add(transaction.amount);
|
|
totalFees = totalFees.add(transaction.platformFee);
|
|
}
|
|
|
|
if (transaction.type === 'withdrawal' && transaction.status === 'completed') {
|
|
totalWithdrawals = totalWithdrawals.add(transaction.netAmount);
|
|
}
|
|
|
|
if (transaction.type === 'prize_payout' && transaction.status === 'pending') {
|
|
pendingPayouts = pendingPayouts.add(transaction.netAmount);
|
|
}
|
|
}
|
|
|
|
return {
|
|
aggregates: {
|
|
balance,
|
|
totalRevenue,
|
|
totalFees,
|
|
totalWithdrawals,
|
|
pendingPayouts,
|
|
},
|
|
};
|
|
}
|
|
} |