/** * Application Use Case: GetSponsorDashboardUseCase * * Returns sponsor dashboard metrics including sponsorships, impressions, and investment data. */ import type { ISponsorRepository } from '../../domain/repositories/ISponsorRepository'; 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 type { SponsorDashboardViewModel } from '../presenters/ISponsorDashboardPresenter'; import { Result } from '@core/shared/application/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; export interface GetSponsorDashboardQueryParams { sponsorId: string; } export interface SponsoredLeagueDTO { id: string; name: string; tier: 'main' | 'secondary'; drivers: number; races: number; impressions: number; status: 'active' | 'upcoming' | 'completed'; } export interface SponsorDashboardDTO { sponsorId: string; sponsorName: string; metrics: { impressions: number; impressionsChange: number; uniqueViewers: number; viewersChange: number; races: number; drivers: number; exposure: number; exposureChange: number; }; sponsoredLeagues: SponsoredLeagueDTO[]; investment: { activeSponsorships: number; totalInvestment: number; costPerThousandViews: number; }; } export class GetSponsorDashboardUseCase { constructor( private readonly sponsorRepository: ISponsorRepository, private readonly seasonSponsorshipRepository: ISeasonSponsorshipRepository, private readonly seasonRepository: ISeasonRepository, private readonly leagueRepository: ILeagueRepository, private readonly leagueMembershipRepository: ILeagueMembershipRepository, private readonly raceRepository: IRaceRepository, ) {} async execute( params: GetSponsorDashboardQueryParams, ): Promise>> { try { const { sponsorId } = params; const sponsor = await this.sponsorRepository.findById(sponsorId); if (!sponsor) { return Result.ok(null); } // Get all sponsorships for this sponsor const sponsorships = await this.seasonSponsorshipRepository.findBySponsorId(sponsorId); // Aggregate data across all sponsorships let totalImpressions = 0; let totalDrivers = 0; let totalRaces = 0; let totalInvestment = 0; const sponsoredLeagues: SponsoredLeagueDTO[] = []; const seenLeagues = new Set(); for (const sponsorship of sponsorships) { // Get season to find league const season = await this.seasonRepository.findById(sponsorship.seasonId); if (!season) continue; // Only process each league once if (seenLeagues.has(season.leagueId)) continue; seenLeagues.add(season.leagueId); const league = await this.leagueRepository.findById(season.leagueId); if (!league) continue; // Get membership count for this league const memberships = await this.leagueMembershipRepository.getLeagueMembers(season.leagueId); const driverCount = memberships.length; totalDrivers += driverCount; // Get races for this league const races = await this.raceRepository.findByLeagueId(season.leagueId); const raceCount = races.length; totalRaces += raceCount; // Calculate impressions based on completed races and drivers // This is a simplified calculation - in production would come from analytics const completedRaces = races.filter(r => r.status === 'completed').length; const leagueImpressions = completedRaces * driverCount * 100; // Simplified: 100 views per driver per race totalImpressions += leagueImpressions; // Determine status based on season dates const now = new Date(); let status: 'active' | 'upcoming' | 'completed' = 'active'; if (season.endDate && season.endDate < now) { status = 'completed'; } else if (season.startDate && season.startDate > now) { status = 'upcoming'; } // Add investment totalInvestment += sponsorship.pricing.amount; sponsoredLeagues.push({ id: league.id, name: league.name, tier: sponsorship.tier, drivers: driverCount, races: raceCount, impressions: leagueImpressions, status, }); } const activeSponsorships = sponsorships.filter(s => s.status === 'active').length; const costPerThousandViews = totalImpressions > 0 ? (totalInvestment / (totalImpressions / 1000)) : 0; // Calculate unique viewers (simplified: assume 70% of impressions are unique) const uniqueViewers = Math.round(totalImpressions * 0.7); // Calculate exposure score (0-100 based on tier distribution) const mainSponsorships = sponsorships.filter(s => s.tier === 'main').length; const exposure = sponsorships.length > 0 ? Math.min(100, (mainSponsorships * 30) + (sponsorships.length * 10)) : 0; const dto: SponsorDashboardDTO = { sponsorId, sponsorName: sponsor.name, metrics: { impressions: totalImpressions, impressionsChange: 0, uniqueViewers, viewersChange: 0, races: totalRaces, drivers: totalDrivers, exposure, exposureChange: 0, }, sponsoredLeagues, investment: { activeSponsorships, totalInvestment, costPerThousandViews: Math.round(costPerThousandViews * 100) / 100, }, }; return Result.ok(dto); } catch { return Result.err({ code: 'REPOSITORY_ERROR', message: 'Failed to fetch sponsor dashboard' }); } } }