/** * Use Case: AcceptSponsorshipRequestUseCase * * Allows an entity owner to accept a sponsorship request. * This creates an active sponsorship and notifies the sponsor. */ import type { ILogger } from '../../../shared/src/logging/ILogger'; import type { ISponsorshipRequestRepository } from '../../domain/repositories/ISponsorshipRequestRepository'; import type { ISeasonSponsorshipRepository } from '../../domain/repositories/ISeasonSponsorshipRepository'; import type { ISeasonRepository } from '../../domain/repositories/ISeasonRepository'; import { SeasonSponsorship } from '../../domain/entities/SeasonSponsorship'; import type { AsyncUseCase } from '@gridpilot/shared/application'; export interface AcceptSponsorshipRequestDTO { requestId: string; respondedBy: string; // driverId of the person accepting } export interface AcceptSponsorshipRequestResultDTO { requestId: string; sponsorshipId: string; status: 'accepted'; acceptedAt: Date; platformFee: number; netAmount: number; } export class AcceptSponsorshipRequestUseCase implements AsyncUseCase { constructor( private readonly sponsorshipRequestRepo: ISponsorshipRequestRepository, private readonly seasonSponsorshipRepo: ISeasonSponsorshipRepository, private readonly seasonRepository: ISeasonRepository, private readonly logger: ILogger, ) {} async execute(dto: AcceptSponsorshipRequestDTO): Promise { this.logger.debug(`Attempting to accept sponsorship request: ${dto.requestId}`, { requestId: dto.requestId, respondedBy: dto.respondedBy }); try { // Find the request const request = await this.sponsorshipRequestRepo.findById(dto.requestId); if (!request) { this.logger.warn(`Sponsorship request not found: ${dto.requestId}`, { requestId: dto.requestId }); throw new Error('Sponsorship request not found'); } if (!request.isPending()) { this.logger.warn(`Cannot accept a ${request.status} sponsorship request: ${dto.requestId}`, { requestId: dto.requestId, status: request.status }); throw new Error(`Cannot accept a ${request.status} sponsorship request`); } this.logger.info(`Sponsorship request ${dto.requestId} found and is pending. Proceeding with acceptance.`, { requestId: dto.requestId }); // Accept the request const acceptedRequest = request.accept(dto.respondedBy); await this.sponsorshipRequestRepo.update(acceptedRequest); this.logger.debug(`Sponsorship request ${dto.requestId} accepted and updated in repository.`, { requestId: dto.requestId }); // If this is a season sponsorship, create the SeasonSponsorship record let sponsorshipId = `spons_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; if (request.entityType === 'season') { this.logger.debug(`Sponsorship request ${dto.requestId} is for a season. Creating SeasonSponsorship record.`, { requestId: dto.requestId, entityType: request.entityType }); const season = await this.seasonRepository.findById(request.entityId); if (!season) { this.logger.warn(`Season not found for sponsorship request ${dto.requestId} and entityId ${request.entityId}`, { requestId: dto.requestId, entityId: request.entityId }); throw new Error('Season not found for sponsorship request'); } const sponsorship = SeasonSponsorship.create({ id: sponsorshipId, seasonId: season.id, leagueId: season.leagueId, sponsorId: request.sponsorId, tier: request.tier, pricing: request.offeredAmount, status: 'active', }); await this.seasonSponsorshipRepo.create(sponsorship); this.logger.info(`Season sponsorship ${sponsorshipId} created for request ${dto.requestId}.`, { sponsorshipId, requestId: dto.requestId }); } // TODO: In a real implementation, we would: // 1. Create notification for the sponsor // 2. Process payment // 3. Update wallet balances this.logger.info(`Sponsorship request ${acceptedRequest.id} successfully accepted.`, { requestId: acceptedRequest.id, sponsorshipId }); return { requestId: acceptedRequest.id, sponsorshipId, status: 'accepted', acceptedAt: acceptedRequest.respondedAt!, platformFee: acceptedRequest.getPlatformFee().amount, netAmount: acceptedRequest.getNetAmount().amount, }; } catch (error: any) { this.logger.error(`Failed to accept sponsorship request ${dto.requestId}: ${error.message}`, { requestId: dto.requestId, error: error.message, stack: error.stack }); throw error; } } }