/** * Application Use Case: GetSponsorSponsorshipsUseCase * * Returns detailed sponsorship information for a sponsor's campaigns/sponsorships page. */ 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 { SponsorshipTier, SponsorshipStatus } from '../../domain/entities/SeasonSponsorship'; import type { ISponsorSponsorshipsPresenter, SponsorSponsorshipsViewModel, } from '../presenters/ISponsorSponsorshipsPresenter'; import type { UseCase } from '@gridpilot/shared/application/UseCase'; export interface GetSponsorSponsorshipsQueryParams { sponsorId: string; } export interface SponsorshipDetailDTO { id: string; leagueId: string; leagueName: string; seasonId: string; seasonName: string; seasonStartDate?: Date; seasonEndDate?: Date; tier: SponsorshipTier; status: SponsorshipStatus; pricing: { amount: number; currency: string; }; platformFee: { amount: number; currency: string; }; netAmount: { amount: number; currency: string; }; metrics: { drivers: number; races: number; completedRaces: number; impressions: number; }; createdAt: Date; activatedAt?: Date; } export interface SponsorSponsorshipsDTO { sponsorId: string; sponsorName: string; sponsorships: SponsorshipDetailDTO[]; summary: { totalSponsorships: number; activeSponsorships: number; totalInvestment: number; totalPlatformFees: number; currency: string; }; } export class GetSponsorSponsorshipsUseCase implements UseCase { 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: GetSponsorSponsorshipsQueryParams, presenter: ISponsorSponsorshipsPresenter, ): Promise { presenter.reset(); const { sponsorId } = params; const sponsor = await this.sponsorRepository.findById(sponsorId); if (!sponsor) { presenter.present(null); return; } // Get all sponsorships for this sponsor const sponsorships = await this.seasonSponsorshipRepository.findBySponsorId(sponsorId); const sponsorshipDetails: SponsorshipDetailDTO[] = []; let totalInvestment = 0; let totalPlatformFees = 0; for (const sponsorship of sponsorships) { // Get season to find league const season = await this.seasonRepository.findById(sponsorship.seasonId); if (!season) continue; 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; // Get races for this league const races = await this.raceRepository.findByLeagueId(season.leagueId); const completedRaces = races.filter(r => r.status === 'completed').length; // Calculate impressions const impressions = completedRaces * driverCount * 100; // Calculate platform fee (10%) const platformFee = sponsorship.getPlatformFee(); const netAmount = sponsorship.getNetAmount(); totalInvestment += sponsorship.pricing.amount; totalPlatformFees += platformFee.amount; sponsorshipDetails.push({ id: sponsorship.id, leagueId: league.id, leagueName: league.name, seasonId: season.id, seasonName: season.name, ...(season.startDate !== undefined ? { seasonStartDate: season.startDate } : {}), ...(season.endDate !== undefined ? { seasonEndDate: season.endDate } : {}), tier: sponsorship.tier, status: sponsorship.status, 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: races.length, completedRaces, impressions, }, createdAt: sponsorship.createdAt, ...(sponsorship.activatedAt !== undefined ? { activatedAt: sponsorship.activatedAt } : {}), }); } const activeSponsorships = sponsorships.filter(s => s.status === 'active').length; const dto: SponsorSponsorshipsDTO = { sponsorId, sponsorName: sponsor.name, sponsorships: sponsorshipDetails, summary: { totalSponsorships: sponsorships.length, activeSponsorships, totalInvestment, totalPlatformFees, currency: 'USD', }, }; presenter.present(dto); } }