166 lines
5.1 KiB
TypeScript
166 lines
5.1 KiB
TypeScript
/**
|
|
* 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 } from '../presenters/ISponsorSponsorshipsPresenter';
|
|
|
|
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 {
|
|
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,
|
|
private readonly presenter: ISponsorSponsorshipsPresenter,
|
|
) {}
|
|
|
|
async execute(params: GetSponsorSponsorshipsQueryParams): Promise<void> {
|
|
const { sponsorId } = params;
|
|
|
|
const sponsor = await this.sponsorRepository.findById(sponsorId);
|
|
if (!sponsor) {
|
|
this.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,
|
|
seasonStartDate: season.startDate,
|
|
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,
|
|
activatedAt: sponsorship.activatedAt,
|
|
});
|
|
}
|
|
|
|
const activeSponsorships = sponsorships.filter(s => s.status === 'active').length;
|
|
|
|
this.presenter.present({
|
|
sponsorId,
|
|
sponsorName: sponsor.name,
|
|
sponsorships: sponsorshipDetails,
|
|
summary: {
|
|
totalSponsorships: sponsorships.length,
|
|
activeSponsorships,
|
|
totalInvestment,
|
|
totalPlatformFees,
|
|
currency: 'USD',
|
|
},
|
|
});
|
|
}
|
|
} |