fix data flow issues
This commit is contained in:
93
apps/website/lib/services/leagues/LeagueStewardingService.ts
Normal file
93
apps/website/lib/services/leagues/LeagueStewardingService.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { RaceService } from '../races/RaceService';
|
||||
import { ProtestService } from '../protests/ProtestService';
|
||||
import { PenaltyService } from '../penalties/PenaltyService';
|
||||
import { DriverService } from '../drivers/DriverService';
|
||||
import { LeagueMembershipService } from './LeagueMembershipService';
|
||||
import { LeagueStewardingViewModel, RaceWithProtests } from '../../view-models/LeagueStewardingViewModel';
|
||||
|
||||
/**
|
||||
* League Stewarding Service
|
||||
*
|
||||
* Orchestrates league stewarding operations by coordinating calls to race, protest, penalty, driver, and membership services.
|
||||
* All dependencies are injected via constructor.
|
||||
*/
|
||||
export class LeagueStewardingService {
|
||||
constructor(
|
||||
private readonly raceService: RaceService,
|
||||
private readonly protestService: ProtestService,
|
||||
private readonly penaltyService: PenaltyService,
|
||||
private readonly driverService: DriverService,
|
||||
private readonly leagueMembershipService: LeagueMembershipService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Get league stewarding data for all races in a league
|
||||
*/
|
||||
async getLeagueStewardingData(leagueId: string): Promise<LeagueStewardingViewModel> {
|
||||
// Get all races for this league
|
||||
const leagueRaces = await this.raceService.findByLeagueId(leagueId);
|
||||
|
||||
// Get protests and penalties for each race
|
||||
const protestsMap: Record<string, any[]> = {};
|
||||
const penaltiesMap: Record<string, any[]> = {};
|
||||
const driverIds = new Set<string>();
|
||||
|
||||
for (const race of leagueRaces) {
|
||||
const raceProtests = await this.protestService.findByRaceId(race.id);
|
||||
const racePenalties = await this.penaltyService.findByRaceId(race.id);
|
||||
|
||||
protestsMap[race.id] = raceProtests;
|
||||
penaltiesMap[race.id] = racePenalties;
|
||||
|
||||
// Collect driver IDs
|
||||
raceProtests.forEach((p: any) => {
|
||||
driverIds.add(p.protestingDriverId);
|
||||
driverIds.add(p.accusedDriverId);
|
||||
});
|
||||
racePenalties.forEach((p: any) => {
|
||||
driverIds.add(p.driverId);
|
||||
});
|
||||
}
|
||||
|
||||
// Load driver info
|
||||
const driverEntities = await this.driverService.findByIds(Array.from(driverIds));
|
||||
const driverMap: Record<string, any> = {};
|
||||
driverEntities.forEach((driver) => {
|
||||
if (driver) {
|
||||
driverMap[driver.id] = driver;
|
||||
}
|
||||
});
|
||||
|
||||
// Compute race data with protest/penalty info
|
||||
const racesWithData: RaceWithProtests[] = leagueRaces.map(race => {
|
||||
const protests = protestsMap[race.id] || [];
|
||||
const penalties = penaltiesMap[race.id] || [];
|
||||
return {
|
||||
race: {
|
||||
id: race.id,
|
||||
track: race.track,
|
||||
scheduledAt: new Date(race.scheduledAt),
|
||||
},
|
||||
pendingProtests: protests.filter(p => p.status === 'pending' || p.status === 'under_review'),
|
||||
resolvedProtests: protests.filter(p => p.status === 'upheld' || p.status === 'dismissed' || p.status === 'withdrawn'),
|
||||
penalties
|
||||
};
|
||||
}).sort((a, b) => b.race.scheduledAt.getTime() - a.race.scheduledAt.getTime());
|
||||
|
||||
return new LeagueStewardingViewModel(racesWithData, driverMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Review a protest
|
||||
*/
|
||||
async reviewProtest(input: { protestId: string; stewardId: string; decision: string; decisionNotes: string }): Promise<void> {
|
||||
await this.protestService.reviewProtest(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a penalty
|
||||
*/
|
||||
async applyPenalty(input: any): Promise<void> {
|
||||
await this.penaltyService.applyPenalty(input);
|
||||
}
|
||||
}
|
||||
71
apps/website/lib/services/leagues/LeagueWalletService.ts
Normal file
71
apps/website/lib/services/leagues/LeagueWalletService.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { WalletsApiClient, LeagueWalletDTO, WithdrawRequestDTO, WithdrawResponseDTO } from '@/lib/api/wallets/WalletsApiClient';
|
||||
import { LeagueWalletViewModel } from '@/lib/view-models/LeagueWalletViewModel';
|
||||
import { WalletTransactionViewModel } from '@/lib/view-models/WalletTransactionViewModel';
|
||||
import { SubmitBlocker, ThrottleBlocker } from '@/lib/blockers';
|
||||
|
||||
/**
|
||||
* League Wallet Service
|
||||
*
|
||||
* Orchestrates league wallet operations by coordinating API calls and view model creation.
|
||||
* All dependencies are injected via constructor.
|
||||
*/
|
||||
export class LeagueWalletService {
|
||||
private readonly submitBlocker = new SubmitBlocker();
|
||||
private readonly throttle = new ThrottleBlocker(500);
|
||||
|
||||
constructor(
|
||||
private readonly apiClient: WalletsApiClient
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Get wallet for a league
|
||||
*/
|
||||
async getWalletForLeague(leagueId: string): Promise<LeagueWalletViewModel> {
|
||||
const dto = await this.apiClient.getLeagueWallet(leagueId);
|
||||
const transactions = dto.transactions.map(t => new WalletTransactionViewModel({
|
||||
id: t.id,
|
||||
type: t.type,
|
||||
description: t.description,
|
||||
amount: t.amount,
|
||||
fee: t.fee,
|
||||
netAmount: t.netAmount,
|
||||
date: new Date(t.date),
|
||||
status: t.status,
|
||||
reference: t.reference,
|
||||
}));
|
||||
return new LeagueWalletViewModel({
|
||||
balance: dto.balance,
|
||||
currency: dto.currency,
|
||||
totalRevenue: dto.totalRevenue,
|
||||
totalFees: dto.totalFees,
|
||||
totalWithdrawals: dto.totalWithdrawals,
|
||||
pendingPayouts: dto.pendingPayouts,
|
||||
transactions,
|
||||
canWithdraw: dto.canWithdraw,
|
||||
withdrawalBlockReason: dto.withdrawalBlockReason,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Withdraw from league wallet
|
||||
*/
|
||||
async withdraw(leagueId: string, amount: number, currency: string, seasonId: string, destinationAccount: string): Promise<WithdrawResponseDTO> {
|
||||
if (!this.submitBlocker.canExecute() || !this.throttle.canExecute()) {
|
||||
throw new Error('Request blocked due to rate limiting');
|
||||
}
|
||||
|
||||
this.submitBlocker.block();
|
||||
this.throttle.block();
|
||||
try {
|
||||
const request: WithdrawRequestDTO = {
|
||||
amount,
|
||||
currency,
|
||||
seasonId,
|
||||
destinationAccount,
|
||||
};
|
||||
return await this.apiClient.withdrawFromLeagueWallet(leagueId, request);
|
||||
} finally {
|
||||
this.submitBlocker.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user