This commit is contained in:
2025-12-14 18:11:59 +01:00
parent acc15e8d8d
commit 217337862c
91 changed files with 5919 additions and 1999 deletions

View File

@@ -16,6 +16,7 @@ import {
EntityNotFoundError,
BusinessRuleViolationError,
} from '../errors/RacingApplicationError';
import type { ILogger } from '../../../shared/src/logging/ILogger';
export interface ApplyForSponsorshipDTO {
sponsorId: string;
@@ -40,22 +41,28 @@ export class ApplyForSponsorshipUseCase
private readonly sponsorshipRequestRepo: ISponsorshipRequestRepository,
private readonly sponsorshipPricingRepo: ISponsorshipPricingRepository,
private readonly sponsorRepo: ISponsorRepository,
private readonly logger: ILogger,
) {}
async execute(dto: ApplyForSponsorshipDTO): Promise<ApplyForSponsorshipResultDTO> {
this.logger.debug('Attempting to apply for sponsorship', { dto });
// Validate sponsor exists
const sponsor = await this.sponsorRepo.findById(dto.sponsorId);
if (!sponsor) {
this.logger.error('Sponsor not found', { sponsorId: dto.sponsorId });
throw new EntityNotFoundError({ entity: 'sponsor', id: dto.sponsorId });
}
// Check if entity accepts sponsorship applications
const pricing = await this.sponsorshipPricingRepo.findByEntity(dto.entityType, dto.entityId);
if (!pricing) {
this.logger.warn('Sponsorship pricing not set up for this entity', { entityType: dto.entityType, entityId: dto.entityId });
throw new BusinessRuleViolationError('This entity has not set up sponsorship pricing');
}
if (!pricing.acceptingApplications) {
this.logger.warn('Entity not accepting sponsorship applications', { entityType: dto.entityType, entityId: dto.entityId });
throw new BusinessRuleViolationError(
'This entity is not currently accepting sponsorship applications',
);
@@ -64,6 +71,7 @@ export class ApplyForSponsorshipUseCase
// Check if the requested tier slot is available
const slotAvailable = pricing.isSlotAvailable(dto.tier);
if (!slotAvailable) {
this.logger.warn(`No ${dto.tier} sponsorship slots are available for entity ${dto.entityId}`);
throw new BusinessRuleViolationError(
`No ${dto.tier} sponsorship slots are available`,
);
@@ -76,6 +84,7 @@ export class ApplyForSponsorshipUseCase
dto.entityId,
);
if (hasPending) {
this.logger.warn('Sponsor already has a pending request for this entity', { sponsorId: dto.sponsorId, entityType: dto.entityType, entityId: dto.entityId });
throw new BusinessRuleViolationError(
'You already have a pending sponsorship request for this entity',
);
@@ -84,6 +93,7 @@ export class ApplyForSponsorshipUseCase
// Validate offered amount meets minimum price
const minPrice = pricing.getPrice(dto.tier);
if (minPrice && dto.offeredAmount < minPrice.amount) {
this.logger.warn(`Offered amount ${dto.offeredAmount} is less than minimum ${minPrice.amount} for entity ${dto.entityId}, tier ${dto.tier}`);
throw new BusinessRuleViolationError(
`Offered amount must be at least ${minPrice.format()}`,
);