Files
gridpilot.gg/core/racing/application/use-cases/GetSeasonSponsorshipsUseCase.ts
2025-12-28 12:04:12 +01:00

158 lines
5.1 KiB
TypeScript

import type { ISeasonSponsorshipRepository } from '../../domain/repositories/ISeasonSponsorshipRepository';
import type { ISeasonRepository } from '../../domain/repositories/ISeasonRepository';
import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository';
import type { ILeagueMembershipRepository } from '../../domain/repositories/ILeagueMembershipRepository';
import type { IRaceRepository } from '../../domain/repositories/IRaceRepository';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
export type GetSeasonSponsorshipsInput = {
seasonId: string;
};
export type SeasonSponsorshipMetrics = {
drivers: number;
races: number;
completedRaces: number;
impressions: number;
};
export type SeasonSponsorshipFinancials = {
amount: number;
currency: string;
};
export type SeasonSponsorshipDetail = {
id: string;
leagueId: string;
leagueName: string;
seasonId: string;
seasonName: string;
seasonStartDate?: Date;
seasonEndDate?: Date;
tier: string;
status: string;
pricing: SeasonSponsorshipFinancials;
platformFee: SeasonSponsorshipFinancials;
netAmount: SeasonSponsorshipFinancials;
metrics: SeasonSponsorshipMetrics;
createdAt: Date;
activatedAt?: Date;
};
export type GetSeasonSponsorshipsResult = {
seasonId: string;
sponsorships: SeasonSponsorshipDetail[];
};
export type GetSeasonSponsorshipsErrorCode =
| 'SEASON_NOT_FOUND'
| 'LEAGUE_NOT_FOUND'
| 'REPOSITORY_ERROR';
export class GetSeasonSponsorshipsUseCase {
constructor(
private readonly seasonSponsorshipRepository: ISeasonSponsorshipRepository,
private readonly seasonRepository: ISeasonRepository,
private readonly leagueRepository: ILeagueRepository,
private readonly leagueMembershipRepository: ILeagueMembershipRepository,
private readonly raceRepository: IRaceRepository,
private readonly output: UseCaseOutputPort<GetSeasonSponsorshipsResult>,
) {}
async execute(
input: GetSeasonSponsorshipsInput,
): Promise<Result<void, ApplicationErrorCode<GetSeasonSponsorshipsErrorCode, { message: string }>>> {
try {
const { seasonId } = input;
const season = await this.seasonRepository.findById(seasonId);
if (!season) {
return Result.err({
code: 'SEASON_NOT_FOUND',
details: {
message: 'Season not found',
},
});
}
const league = await this.leagueRepository.findById(season.leagueId);
if (!league) {
return Result.err({
code: 'LEAGUE_NOT_FOUND',
details: {
message: 'League not found for season',
},
});
}
const sponsorships = await this.seasonSponsorshipRepository.findBySeasonId(seasonId);
// Pre-compute metrics shared across all sponsorships in this season
const memberships = await this.leagueMembershipRepository.getLeagueMembers(season.leagueId);
const driverCount = memberships.length;
const races = await this.raceRepository.findByLeagueId(season.leagueId);
const raceCount = races.length;
const completedRaces = races.filter(r => r.status.isCompleted()).length;
const impressions = completedRaces * driverCount * 100;
const sponsorshipDetails: SeasonSponsorshipDetail[] = sponsorships.map((sponsorship) => {
const platformFee = sponsorship.getPlatformFee();
const netAmount = sponsorship.getNetAmount();
const detail: SeasonSponsorshipDetail = {
id: sponsorship.id,
leagueId: league.id.toString(),
leagueName: league.name.toString(),
seasonId: season.id,
seasonName: season.name,
tier: sponsorship.tier.toString(),
status: sponsorship.status.toString(),
pricing: {
amount: sponsorship.pricing.amount,
currency: sponsorship.pricing.currency,
},
platformFee: {
amount: platformFee.amount,
currency: platformFee.currency,
},
netAmount: {
amount: netAmount.amount,
currency: netAmount.currency,
},
metrics: {
drivers: driverCount,
races: raceCount,
completedRaces,
impressions,
},
createdAt: sponsorship.createdAt,
...(season.startDate ? { seasonStartDate: season.startDate } : {}),
...(season.endDate ? { seasonEndDate: season.endDate } : {}),
...(sponsorship.activatedAt ? { activatedAt: sponsorship.activatedAt } : {}),
};
return detail;
});
this.output.present({
seasonId,
sponsorships: sponsorshipDetails,
});
return Result.ok(undefined);
} catch (err) {
const error = err as { message?: string } | undefined;
return Result.err({
code: 'REPOSITORY_ERROR',
details: {
message: error?.message ?? 'Failed to fetch season sponsorships',
},
});
}
}
}