fix data flow issues
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Controller, Get, Post, Body, HttpCode, HttpStatus, Param, Query } from '@nestjs/common';
|
||||
import { Controller, Get, Post, Put, Body, HttpCode, HttpStatus, Param, Query } from '@nestjs/common';
|
||||
import { ApiTags, ApiResponse, ApiOperation } from '@nestjs/swagger';
|
||||
import { SponsorService } from './SponsorService';
|
||||
import { GetEntitySponsorshipPricingResultDTO } from './dtos/GetEntitySponsorshipPricingResultDTO';
|
||||
@@ -13,6 +13,16 @@ import { GetSponsorOutputDTO } from './dtos/GetSponsorOutputDTO';
|
||||
import { GetPendingSponsorshipRequestsOutputDTO } from './dtos/GetPendingSponsorshipRequestsOutputDTO';
|
||||
import { AcceptSponsorshipRequestInputDTO } from './dtos/AcceptSponsorshipRequestInputDTO';
|
||||
import { RejectSponsorshipRequestInputDTO } from './dtos/RejectSponsorshipRequestInputDTO';
|
||||
import { PaymentMethodDTO } from './dtos/PaymentMethodDTO';
|
||||
import { InvoiceDTO } from './dtos/InvoiceDTO';
|
||||
import { BillingStatsDTO } from './dtos/BillingStatsDTO';
|
||||
import { AvailableLeagueDTO } from './dtos/AvailableLeagueDTO';
|
||||
import { LeagueDetailDTO } from './dtos/LeagueDetailDTO';
|
||||
import { DriverDTO } from './dtos/DriverDTO';
|
||||
import { RaceDTO } from './dtos/RaceDTO';
|
||||
import { SponsorProfileDTO } from './dtos/SponsorProfileDTO';
|
||||
import { NotificationSettingsDTO } from './dtos/NotificationSettingsDTO';
|
||||
import { PrivacySettingsDTO } from './dtos/PrivacySettingsDTO';
|
||||
import type { AcceptSponsorshipRequestResultPort } from '@core/racing/application/ports/output/AcceptSponsorshipRequestResultPort';
|
||||
import type { RejectSponsorshipRequestResultDTO } from '@core/racing/application/use-cases/RejectSponsorshipRequestUseCase';
|
||||
|
||||
@@ -93,4 +103,59 @@ export class SponsorController {
|
||||
async rejectSponsorshipRequest(@Param('requestId') requestId: string, @Body() input: RejectSponsorshipRequestInputDTO): Promise<RejectSponsorshipRequestResultDTO | null> {
|
||||
return this.sponsorService.rejectSponsorshipRequest(requestId, input.respondedBy, input.reason);
|
||||
}
|
||||
|
||||
@Get('billing/:sponsorId')
|
||||
@ApiOperation({ summary: 'Get sponsor billing information' })
|
||||
@ApiResponse({ status: 200, description: 'Sponsor billing data', type: Object })
|
||||
async getSponsorBilling(@Param('sponsorId') sponsorId: string): Promise<{
|
||||
paymentMethods: PaymentMethodDTO[];
|
||||
invoices: InvoiceDTO[];
|
||||
stats: BillingStatsDTO;
|
||||
}> {
|
||||
return this.sponsorService.getSponsorBilling(sponsorId);
|
||||
}
|
||||
|
||||
@Get('leagues/available')
|
||||
@ApiOperation({ summary: 'Get available leagues for sponsorship' })
|
||||
@ApiResponse({ status: 200, description: 'Available leagues', type: [AvailableLeagueDTO] })
|
||||
async getAvailableLeagues(): Promise<AvailableLeagueDTO[]> {
|
||||
return this.sponsorService.getAvailableLeagues();
|
||||
}
|
||||
|
||||
@Get('leagues/:leagueId/detail')
|
||||
@ApiOperation({ summary: 'Get detailed league information for sponsors' })
|
||||
@ApiResponse({ status: 200, description: 'League detail data', type: Object })
|
||||
async getLeagueDetail(@Param('leagueId') leagueId: string): Promise<{
|
||||
league: LeagueDetailDTO;
|
||||
drivers: DriverDTO[];
|
||||
races: RaceDTO[];
|
||||
}> {
|
||||
return this.sponsorService.getLeagueDetail(leagueId);
|
||||
}
|
||||
|
||||
@Get('settings/:sponsorId')
|
||||
@ApiOperation({ summary: 'Get sponsor settings' })
|
||||
@ApiResponse({ status: 200, description: 'Sponsor settings', type: Object })
|
||||
async getSponsorSettings(@Param('sponsorId') sponsorId: string): Promise<{
|
||||
profile: SponsorProfileDTO;
|
||||
notifications: NotificationSettingsDTO;
|
||||
privacy: PrivacySettingsDTO;
|
||||
}> {
|
||||
return this.sponsorService.getSponsorSettings(sponsorId);
|
||||
}
|
||||
|
||||
@Put('settings/:sponsorId')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: 'Update sponsor settings' })
|
||||
@ApiResponse({ status: 200, description: 'Settings updated successfully' })
|
||||
async updateSponsorSettings(
|
||||
@Param('sponsorId') sponsorId: string,
|
||||
@Body() input: {
|
||||
profile?: Partial<SponsorProfileDTO>;
|
||||
notifications?: Partial<NotificationSettingsDTO>;
|
||||
privacy?: Partial<PrivacySettingsDTO>;
|
||||
}
|
||||
): Promise<void> {
|
||||
return this.sponsorService.updateSponsorSettings(sponsorId, input);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,11 @@ import { ISponsorshipRequestRepository } from '@core/racing/domain/repositories/
|
||||
import { INotificationService } from '@core/notifications/application/ports/INotificationService';
|
||||
import { IPaymentGateway } from '@core/racing/application/ports/IPaymentGateway';
|
||||
import { IWalletRepository } from '@core/payments/domain/repositories/IWalletRepository';
|
||||
import type { IPaymentRepository } from '@core/payments/domain/repositories/IPaymentRepository';
|
||||
import { ILeagueWalletRepository } from '@core/racing/domain/repositories/ILeagueWalletRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
|
||||
// Import use cases
|
||||
// Import use cases / application services
|
||||
import { GetSponsorshipPricingUseCase } from '@core/racing/application/use-cases/GetSponsorshipPricingUseCase';
|
||||
import { GetSponsorsUseCase } from '@core/racing/application/use-cases/GetSponsorsUseCase';
|
||||
import { CreateSponsorUseCase } from '@core/racing/application/use-cases/CreateSponsorUseCase';
|
||||
@@ -27,6 +28,7 @@ import { GetSponsorUseCase } from '@core/racing/application/use-cases/GetSponsor
|
||||
import { GetPendingSponsorshipRequestsUseCase } from '@core/racing/application/use-cases/GetPendingSponsorshipRequestsUseCase';
|
||||
import { AcceptSponsorshipRequestUseCase } from '@core/racing/application/use-cases/AcceptSponsorshipRequestUseCase';
|
||||
import { RejectSponsorshipRequestUseCase } from '@core/racing/application/use-cases/RejectSponsorshipRequestUseCase';
|
||||
import { SponsorBillingService } from '@core/payments/application/services/SponsorBillingService';
|
||||
|
||||
// Import concrete in-memory implementations
|
||||
import { InMemorySponsorRepository } from '@adapters/racing/persistence/inmemory/InMemorySponsorRepository';
|
||||
@@ -37,6 +39,7 @@ import { InMemoryLeagueMembershipRepository } from '@adapters/racing/persistence
|
||||
import { InMemoryRaceRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRepository';
|
||||
import { InMemorySponsorshipPricingRepository } from '@adapters/racing/persistence/inmemory/InMemorySponsorshipPricingRepository';
|
||||
import { InMemorySponsorshipRequestRepository } from '@adapters/racing/persistence/inmemory/InMemorySponsorshipRequestRepository';
|
||||
import { InMemoryPaymentRepository } from '@adapters/payments/persistence/inmemory/InMemoryPaymentRepository';
|
||||
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
|
||||
|
||||
// Define injection tokens
|
||||
@@ -50,7 +53,7 @@ export const SPONSORSHIP_PRICING_REPOSITORY_TOKEN = 'ISponsorshipPricingReposito
|
||||
export const SPONSORSHIP_REQUEST_REPOSITORY_TOKEN = 'ISponsorshipRequestRepository';
|
||||
export const LOGGER_TOKEN = 'Logger';
|
||||
|
||||
// Use case tokens
|
||||
// Use case / application service tokens
|
||||
export const GET_SPONSORSHIP_PRICING_USE_CASE_TOKEN = 'GetSponsorshipPricingUseCase';
|
||||
export const GET_SPONSORS_USE_CASE_TOKEN = 'GetSponsorsUseCase';
|
||||
export const CREATE_SPONSOR_USE_CASE_TOKEN = 'CreateSponsorUseCase';
|
||||
@@ -61,6 +64,7 @@ export const GET_SPONSOR_USE_CASE_TOKEN = 'GetSponsorUseCase';
|
||||
export const GET_PENDING_SPONSORSHIP_REQUESTS_USE_CASE_TOKEN = 'GetPendingSponsorshipRequestsUseCase';
|
||||
export const ACCEPT_SPONSORSHIP_REQUEST_USE_CASE_TOKEN = 'AcceptSponsorshipRequestUseCase';
|
||||
export const REJECT_SPONSORSHIP_REQUEST_USE_CASE_TOKEN = 'RejectSponsorshipRequestUseCase';
|
||||
export const SPONSOR_BILLING_SERVICE_TOKEN = 'SponsorBillingService';
|
||||
|
||||
export const SponsorProviders: Provider[] = [
|
||||
SponsorService,
|
||||
@@ -133,9 +137,28 @@ export const SponsorProviders: Provider[] = [
|
||||
},
|
||||
{
|
||||
provide: GET_SPONSOR_SPONSORSHIPS_USE_CASE_TOKEN,
|
||||
useFactory: (sponsorRepo: ISponsorRepository, seasonSponsorshipRepo: ISeasonSponsorshipRepository, seasonRepo: ISeasonRepository, raceRepo: IRaceRepository) =>
|
||||
new GetSponsorSponsorshipsUseCase(sponsorRepo, seasonSponsorshipRepo, seasonRepo, raceRepo),
|
||||
inject: [SPONSOR_REPOSITORY_TOKEN, SEASON_SPONSORSHIP_REPOSITORY_TOKEN, SEASON_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN],
|
||||
useFactory: (
|
||||
sponsorRepo: ISponsorRepository,
|
||||
seasonSponsorshipRepo: ISeasonSponsorshipRepository,
|
||||
seasonRepo: ISeasonRepository,
|
||||
leagueRepo: ILeagueRepository,
|
||||
leagueMembershipRepo: ILeagueMembershipRepository,
|
||||
raceRepo: IRaceRepository,
|
||||
) => new GetSponsorSponsorshipsUseCase(sponsorRepo, seasonSponsorshipRepo, seasonRepo, leagueRepo, leagueMembershipRepo, raceRepo),
|
||||
inject: [
|
||||
SPONSOR_REPOSITORY_TOKEN,
|
||||
SEASON_SPONSORSHIP_REPOSITORY_TOKEN,
|
||||
SEASON_REPOSITORY_TOKEN,
|
||||
LEAGUE_REPOSITORY_TOKEN,
|
||||
LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
|
||||
RACE_REPOSITORY_TOKEN,
|
||||
],
|
||||
},
|
||||
{
|
||||
provide: SPONSOR_BILLING_SERVICE_TOKEN,
|
||||
useFactory: (paymentRepo: IPaymentRepository, seasonSponsorshipRepo: ISeasonSponsorshipRepository) =>
|
||||
new SponsorBillingService(paymentRepo, seasonSponsorshipRepo),
|
||||
inject: ['IPaymentRepository', SEASON_SPONSORSHIP_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GET_ENTITY_SPONSORSHIP_PRICING_USE_CASE_TOKEN,
|
||||
|
||||
@@ -11,6 +11,16 @@ import { GetSponsorOutputDTO } from './dtos/GetSponsorOutputDTO';
|
||||
import { GetPendingSponsorshipRequestsOutputDTO } from './dtos/GetPendingSponsorshipRequestsOutputDTO';
|
||||
import { AcceptSponsorshipRequestInputDTO } from './dtos/AcceptSponsorshipRequestInputDTO';
|
||||
import { RejectSponsorshipRequestInputDTO } from './dtos/RejectSponsorshipRequestInputDTO';
|
||||
import { PaymentMethodDTO } from './dtos/PaymentMethodDTO';
|
||||
import { InvoiceDTO } from './dtos/InvoiceDTO';
|
||||
import { BillingStatsDTO } from './dtos/BillingStatsDTO';
|
||||
import { AvailableLeagueDTO } from './dtos/AvailableLeagueDTO';
|
||||
import { LeagueDetailDTO } from './dtos/LeagueDetailDTO';
|
||||
import { DriverDTO } from './dtos/DriverDTO';
|
||||
import { RaceDTO } from './dtos/RaceDTO';
|
||||
import { SponsorProfileDTO } from './dtos/SponsorProfileDTO';
|
||||
import { NotificationSettingsDTO } from './dtos/NotificationSettingsDTO';
|
||||
import { PrivacySettingsDTO } from './dtos/PrivacySettingsDTO';
|
||||
|
||||
// Use cases
|
||||
import { GetSponsorshipPricingUseCase } from '@core/racing/application/use-cases/GetSponsorshipPricingUseCase';
|
||||
@@ -144,4 +154,259 @@ export class SponsorService {
|
||||
}
|
||||
return result.value;
|
||||
}
|
||||
|
||||
async getSponsorBilling(sponsorId: string): Promise<{
|
||||
paymentMethods: PaymentMethodDTO[];
|
||||
invoices: InvoiceDTO[];
|
||||
stats: BillingStatsDTO;
|
||||
}> {
|
||||
this.logger.debug('[SponsorService] Fetching sponsor billing.', { sponsorId });
|
||||
|
||||
// Mock data - in real implementation, this would come from repositories
|
||||
const paymentMethods: PaymentMethodDTO[] = [
|
||||
{
|
||||
id: 'pm-1',
|
||||
type: 'card',
|
||||
last4: '4242',
|
||||
brand: 'Visa',
|
||||
isDefault: true,
|
||||
expiryMonth: 12,
|
||||
expiryYear: 2027,
|
||||
},
|
||||
{
|
||||
id: 'pm-2',
|
||||
type: 'card',
|
||||
last4: '5555',
|
||||
brand: 'Mastercard',
|
||||
isDefault: false,
|
||||
expiryMonth: 6,
|
||||
expiryYear: 2026,
|
||||
},
|
||||
{
|
||||
id: 'pm-3',
|
||||
type: 'sepa',
|
||||
last4: '8901',
|
||||
bankName: 'Deutsche Bank',
|
||||
isDefault: false,
|
||||
},
|
||||
];
|
||||
|
||||
const invoices: InvoiceDTO[] = [
|
||||
{
|
||||
id: 'inv-1',
|
||||
invoiceNumber: 'GP-2025-001234',
|
||||
date: '2025-11-01',
|
||||
dueDate: '2025-11-15',
|
||||
amount: 1090.91,
|
||||
vatAmount: 207.27,
|
||||
totalAmount: 1298.18,
|
||||
status: 'paid',
|
||||
description: 'GT3 Pro Championship - Primary Sponsor (Q4 2025)',
|
||||
sponsorshipType: 'league',
|
||||
pdfUrl: '#',
|
||||
},
|
||||
{
|
||||
id: 'inv-2',
|
||||
invoiceNumber: 'GP-2025-001235',
|
||||
date: '2025-10-01',
|
||||
dueDate: '2025-10-15',
|
||||
amount: 363.64,
|
||||
vatAmount: 69.09,
|
||||
totalAmount: 432.73,
|
||||
status: 'paid',
|
||||
description: 'Team Velocity - Gear Sponsor (Q4 2025)',
|
||||
sponsorshipType: 'team',
|
||||
pdfUrl: '#',
|
||||
},
|
||||
{
|
||||
id: 'inv-3',
|
||||
invoiceNumber: 'GP-2025-001236',
|
||||
date: '2025-12-01',
|
||||
dueDate: '2025-12-15',
|
||||
amount: 318.18,
|
||||
vatAmount: 60.45,
|
||||
totalAmount: 378.63,
|
||||
status: 'pending',
|
||||
description: 'Alex Thompson - Driver Sponsorship (Dec 2025)',
|
||||
sponsorshipType: 'driver',
|
||||
pdfUrl: '#',
|
||||
},
|
||||
];
|
||||
|
||||
const stats: BillingStatsDTO = {
|
||||
totalSpent: 12450,
|
||||
pendingAmount: 919.54,
|
||||
nextPaymentDate: '2025-12-15',
|
||||
nextPaymentAmount: 378.63,
|
||||
activeSponsorships: 6,
|
||||
averageMonthlySpend: 2075,
|
||||
};
|
||||
|
||||
return { paymentMethods, invoices, stats };
|
||||
}
|
||||
|
||||
async getAvailableLeagues(): Promise<AvailableLeagueDTO[]> {
|
||||
this.logger.debug('[SponsorService] Fetching available leagues.');
|
||||
|
||||
// Mock data
|
||||
return [
|
||||
{
|
||||
id: 'league-1',
|
||||
name: 'GT3 Masters Championship',
|
||||
game: 'iRacing',
|
||||
drivers: 48,
|
||||
avgViewsPerRace: 8200,
|
||||
mainSponsorSlot: { available: true, price: 1200 },
|
||||
secondarySlots: { available: 1, total: 2, price: 400 },
|
||||
rating: 4.8,
|
||||
tier: 'premium',
|
||||
nextRace: '2025-12-20',
|
||||
seasonStatus: 'active',
|
||||
description: 'Premier GT3 racing with top-tier drivers. Weekly broadcasts and active community.',
|
||||
},
|
||||
{
|
||||
id: 'league-2',
|
||||
name: 'Endurance Pro Series',
|
||||
game: 'ACC',
|
||||
drivers: 72,
|
||||
avgViewsPerRace: 12500,
|
||||
mainSponsorSlot: { available: false, price: 1500 },
|
||||
secondarySlots: { available: 2, total: 2, price: 500 },
|
||||
rating: 4.9,
|
||||
tier: 'premium',
|
||||
nextRace: '2026-01-05',
|
||||
seasonStatus: 'active',
|
||||
description: 'Multi-class endurance racing. High engagement from dedicated endurance fans.',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
async getLeagueDetail(leagueId: string): Promise<{
|
||||
league: LeagueDetailDTO;
|
||||
drivers: DriverDTO[];
|
||||
races: RaceDTO[];
|
||||
}> {
|
||||
this.logger.debug('[SponsorService] Fetching league detail.', { leagueId });
|
||||
|
||||
// Mock data
|
||||
const league: LeagueDetailDTO = {
|
||||
id: leagueId,
|
||||
name: 'GT3 Masters Championship',
|
||||
game: 'iRacing',
|
||||
tier: 'premium',
|
||||
season: 'Season 3',
|
||||
description: 'Premier GT3 racing with top-tier drivers competing across the world\'s most iconic circuits.',
|
||||
drivers: 48,
|
||||
races: 12,
|
||||
completedRaces: 8,
|
||||
totalImpressions: 45200,
|
||||
avgViewsPerRace: 5650,
|
||||
engagement: 4.2,
|
||||
rating: 4.8,
|
||||
seasonStatus: 'active',
|
||||
seasonDates: { start: '2025-10-01', end: '2026-02-28' },
|
||||
nextRace: { name: 'Spa-Francorchamps', date: '2025-12-20' },
|
||||
sponsorSlots: {
|
||||
main: {
|
||||
available: true,
|
||||
price: 1200,
|
||||
benefits: [
|
||||
'Primary logo placement on all liveries',
|
||||
'League page header banner',
|
||||
'Race results page branding',
|
||||
'Social media feature posts',
|
||||
'Newsletter sponsor spot',
|
||||
]
|
||||
},
|
||||
secondary: {
|
||||
available: 1,
|
||||
total: 2,
|
||||
price: 400,
|
||||
benefits: [
|
||||
'Secondary logo on liveries',
|
||||
'League page sidebar placement',
|
||||
'Race results mention',
|
||||
'Social media mentions',
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const drivers: DriverDTO[] = [
|
||||
{ id: 'd1', name: 'Max Verstappen', country: 'NL', position: 1, races: 8, impressions: 4200, team: 'Red Bull Racing' },
|
||||
{ id: 'd2', name: 'Lewis Hamilton', country: 'GB', position: 2, races: 8, impressions: 3980, team: 'Mercedes AMG' },
|
||||
];
|
||||
|
||||
const races: RaceDTO[] = [
|
||||
{ id: 'r1', name: 'Spa-Francorchamps', date: '2025-12-20', views: 0, status: 'upcoming' },
|
||||
{ id: 'r2', name: 'Monza', date: '2025-12-08', views: 5800, status: 'completed' },
|
||||
];
|
||||
|
||||
return { league, drivers, races };
|
||||
}
|
||||
|
||||
async getSponsorSettings(sponsorId: string): Promise<{
|
||||
profile: SponsorProfileDTO;
|
||||
notifications: NotificationSettingsDTO;
|
||||
privacy: PrivacySettingsDTO;
|
||||
}> {
|
||||
this.logger.debug('[SponsorService] Fetching sponsor settings.', { sponsorId });
|
||||
|
||||
// Mock data
|
||||
const profile: SponsorProfileDTO = {
|
||||
companyName: 'Acme Racing Co.',
|
||||
contactName: 'John Smith',
|
||||
contactEmail: 'sponsor@acme-racing.com',
|
||||
contactPhone: '+1 (555) 123-4567',
|
||||
website: 'https://acme-racing.com',
|
||||
description: 'Premium sim racing equipment and accessories for competitive drivers.',
|
||||
logoUrl: null,
|
||||
industry: 'Racing Equipment',
|
||||
address: {
|
||||
street: '123 Racing Boulevard',
|
||||
city: 'Indianapolis',
|
||||
country: 'United States',
|
||||
postalCode: '46222',
|
||||
},
|
||||
taxId: 'US12-3456789',
|
||||
socialLinks: {
|
||||
twitter: '@acmeracing',
|
||||
linkedin: 'acme-racing-co',
|
||||
instagram: '@acmeracing',
|
||||
},
|
||||
};
|
||||
|
||||
const notifications: NotificationSettingsDTO = {
|
||||
emailNewSponsorships: true,
|
||||
emailWeeklyReport: true,
|
||||
emailRaceAlerts: false,
|
||||
emailPaymentAlerts: true,
|
||||
emailNewOpportunities: true,
|
||||
emailContractExpiry: true,
|
||||
};
|
||||
|
||||
const privacy: PrivacySettingsDTO = {
|
||||
publicProfile: true,
|
||||
showStats: false,
|
||||
showActiveSponsorships: true,
|
||||
allowDirectContact: true,
|
||||
};
|
||||
|
||||
return { profile, notifications, privacy };
|
||||
}
|
||||
|
||||
async updateSponsorSettings(
|
||||
sponsorId: string,
|
||||
input: {
|
||||
profile?: Partial<SponsorProfileDTO>;
|
||||
notifications?: Partial<NotificationSettingsDTO>;
|
||||
privacy?: Partial<PrivacySettingsDTO>;
|
||||
}
|
||||
): Promise<void> {
|
||||
this.logger.debug('[SponsorService] Updating sponsor settings.', { sponsorId, input });
|
||||
|
||||
// Mock implementation - in real app, this would persist to database
|
||||
// For now, just log the update
|
||||
this.logger.info('[SponsorService] Settings updated successfully.', { sponsorId });
|
||||
}
|
||||
}
|
||||
|
||||
25
apps/api/src/domain/sponsor/dtos/ActivityItemDTO.ts
Normal file
25
apps/api/src/domain/sponsor/dtos/ActivityItemDTO.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsEnum, IsOptional, IsNumber } from 'class-validator';
|
||||
|
||||
export class ActivityItemDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id: string;
|
||||
|
||||
@ApiProperty({ enum: ['race', 'league', 'team', 'driver', 'platform'] })
|
||||
@IsEnum(['race', 'league', 'team', 'driver', 'platform'])
|
||||
type: 'race' | 'league' | 'team' | 'driver' | 'platform';
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
message: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
time: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
impressions?: number;
|
||||
}
|
||||
58
apps/api/src/domain/sponsor/dtos/AvailableLeagueDTO.ts
Normal file
58
apps/api/src/domain/sponsor/dtos/AvailableLeagueDTO.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsEnum, IsNumber, IsBoolean, IsOptional, IsDateString } from 'class-validator';
|
||||
|
||||
export class AvailableLeagueDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
game: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
drivers: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
avgViewsPerRace: number;
|
||||
|
||||
@ApiProperty({ type: Object })
|
||||
mainSponsorSlot: {
|
||||
available: boolean;
|
||||
price: number;
|
||||
};
|
||||
|
||||
@ApiProperty({ type: Object })
|
||||
secondarySlots: {
|
||||
available: number;
|
||||
total: number;
|
||||
price: number;
|
||||
};
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
rating: number;
|
||||
|
||||
@ApiProperty({ enum: ['premium', 'standard', 'starter'] })
|
||||
@IsEnum(['premium', 'standard', 'starter'])
|
||||
tier: 'premium' | 'standard' | 'starter';
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
nextRace?: string;
|
||||
|
||||
@ApiProperty({ enum: ['active', 'upcoming', 'completed'] })
|
||||
@IsEnum(['active', 'upcoming', 'completed'])
|
||||
seasonStatus: 'active' | 'upcoming' | 'completed';
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
description: string;
|
||||
}
|
||||
28
apps/api/src/domain/sponsor/dtos/BillingStatsDTO.ts
Normal file
28
apps/api/src/domain/sponsor/dtos/BillingStatsDTO.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNumber, IsDateString } from 'class-validator';
|
||||
|
||||
export class BillingStatsDTO {
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
totalSpent: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
pendingAmount: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsDateString()
|
||||
nextPaymentDate: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
nextPaymentAmount: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
activeSponsorships: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
averageMonthlySpend: number;
|
||||
}
|
||||
32
apps/api/src/domain/sponsor/dtos/DriverDTO.ts
Normal file
32
apps/api/src/domain/sponsor/dtos/DriverDTO.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNumber } from 'class-validator';
|
||||
|
||||
export class DriverDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
country: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
position: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
races: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
impressions: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
team: string;
|
||||
}
|
||||
48
apps/api/src/domain/sponsor/dtos/InvoiceDTO.ts
Normal file
48
apps/api/src/domain/sponsor/dtos/InvoiceDTO.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsEnum, IsNumber, IsDateString } from 'class-validator';
|
||||
|
||||
export class InvoiceDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
invoiceNumber: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsDateString()
|
||||
date: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsDateString()
|
||||
dueDate: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
amount: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
vatAmount: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
totalAmount: number;
|
||||
|
||||
@ApiProperty({ enum: ['paid', 'pending', 'overdue', 'failed'] })
|
||||
@IsEnum(['paid', 'pending', 'overdue', 'failed'])
|
||||
status: 'paid' | 'pending' | 'overdue' | 'failed';
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
description: string;
|
||||
|
||||
@ApiProperty({ enum: ['league', 'team', 'driver', 'race', 'platform'] })
|
||||
@IsEnum(['league', 'team', 'driver', 'race', 'platform'])
|
||||
sponsorshipType: 'league' | 'team' | 'driver' | 'race' | 'platform';
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
pdfUrl: string;
|
||||
}
|
||||
88
apps/api/src/domain/sponsor/dtos/LeagueDetailDTO.ts
Normal file
88
apps/api/src/domain/sponsor/dtos/LeagueDetailDTO.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsEnum, IsNumber, IsDateString, IsOptional } from 'class-validator';
|
||||
|
||||
export class LeagueDetailDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
game: string;
|
||||
|
||||
@ApiProperty({ enum: ['premium', 'standard', 'starter'] })
|
||||
@IsEnum(['premium', 'standard', 'starter'])
|
||||
tier: 'premium' | 'standard' | 'starter';
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
season: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
description: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
drivers: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
races: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
completedRaces: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
totalImpressions: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
avgViewsPerRace: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
engagement: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
rating: number;
|
||||
|
||||
@ApiProperty({ enum: ['active', 'upcoming', 'completed'] })
|
||||
@IsEnum(['active', 'upcoming', 'completed'])
|
||||
seasonStatus: 'active' | 'upcoming' | 'completed';
|
||||
|
||||
@ApiProperty({ type: Object })
|
||||
seasonDates: {
|
||||
start: string;
|
||||
end: string;
|
||||
};
|
||||
|
||||
@ApiProperty({ type: Object, required: false })
|
||||
@IsOptional()
|
||||
nextRace?: {
|
||||
name: string;
|
||||
date: string;
|
||||
};
|
||||
|
||||
@ApiProperty({ type: Object })
|
||||
sponsorSlots: {
|
||||
main: {
|
||||
available: boolean;
|
||||
price: number;
|
||||
benefits: string[];
|
||||
};
|
||||
secondary: {
|
||||
available: number;
|
||||
total: number;
|
||||
price: number;
|
||||
benefits: string[];
|
||||
};
|
||||
};
|
||||
}
|
||||
28
apps/api/src/domain/sponsor/dtos/NotificationSettingsDTO.ts
Normal file
28
apps/api/src/domain/sponsor/dtos/NotificationSettingsDTO.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsBoolean } from 'class-validator';
|
||||
|
||||
export class NotificationSettingsDTO {
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
emailNewSponsorships: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
emailWeeklyReport: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
emailRaceAlerts: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
emailPaymentAlerts: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
emailNewOpportunities: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
emailContractExpiry: boolean;
|
||||
}
|
||||
40
apps/api/src/domain/sponsor/dtos/PaymentMethodDTO.ts
Normal file
40
apps/api/src/domain/sponsor/dtos/PaymentMethodDTO.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsEnum, IsBoolean, IsOptional, IsNumber } from 'class-validator';
|
||||
|
||||
export class PaymentMethodDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id: string;
|
||||
|
||||
@ApiProperty({ enum: ['card', 'bank', 'sepa'] })
|
||||
@IsEnum(['card', 'bank', 'sepa'])
|
||||
type: 'card' | 'bank' | 'sepa';
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
last4: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
brand?: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
isDefault: boolean;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
expiryMonth?: number;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
expiryYear?: number;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
bankName?: string;
|
||||
}
|
||||
20
apps/api/src/domain/sponsor/dtos/PrivacySettingsDTO.ts
Normal file
20
apps/api/src/domain/sponsor/dtos/PrivacySettingsDTO.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsBoolean } from 'class-validator';
|
||||
|
||||
export class PrivacySettingsDTO {
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
publicProfile: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
showStats: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
showActiveSponsorships: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
allowDirectContact: boolean;
|
||||
}
|
||||
24
apps/api/src/domain/sponsor/dtos/RaceDTO.ts
Normal file
24
apps/api/src/domain/sponsor/dtos/RaceDTO.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsEnum, IsNumber, IsDateString } from 'class-validator';
|
||||
|
||||
export class RaceDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsDateString()
|
||||
date: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
views: number;
|
||||
|
||||
@ApiProperty({ enum: ['upcoming', 'completed'] })
|
||||
@IsEnum(['upcoming', 'completed'])
|
||||
status: 'upcoming' | 'completed';
|
||||
}
|
||||
24
apps/api/src/domain/sponsor/dtos/RenewalAlertDTO.ts
Normal file
24
apps/api/src/domain/sponsor/dtos/RenewalAlertDTO.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsEnum, IsNumber, IsDateString } from 'class-validator';
|
||||
|
||||
export class RenewalAlertDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@ApiProperty({ enum: ['league', 'team', 'driver', 'race', 'platform'] })
|
||||
@IsEnum(['league', 'team', 'driver', 'race', 'platform'])
|
||||
type: 'league' | 'team' | 'driver' | 'race' | 'platform';
|
||||
|
||||
@ApiProperty()
|
||||
@IsDateString()
|
||||
renewDate: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
price: number;
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString } from 'class-validator';
|
||||
import { IsString, IsArray, IsObject } from 'class-validator';
|
||||
import { SponsorDashboardMetricsDTO } from './SponsorDashboardMetricsDTO';
|
||||
import { SponsoredLeagueDTO } from './SponsoredLeagueDTO';
|
||||
import { SponsorDashboardInvestmentDTO } from './SponsorDashboardInvestmentDTO';
|
||||
import { SponsorshipDTO } from './SponsorshipDTO';
|
||||
import { ActivityItemDTO } from './ActivityItemDTO';
|
||||
import { RenewalAlertDTO } from './RenewalAlertDTO';
|
||||
|
||||
export class SponsorDashboardDTO {
|
||||
@ApiProperty()
|
||||
@@ -21,4 +24,19 @@ export class SponsorDashboardDTO {
|
||||
|
||||
@ApiProperty({ type: SponsorDashboardInvestmentDTO })
|
||||
investment: SponsorDashboardInvestmentDTO;
|
||||
|
||||
@ApiProperty({ type: Object })
|
||||
sponsorships: {
|
||||
leagues: SponsorshipDTO[];
|
||||
teams: SponsorshipDTO[];
|
||||
drivers: SponsorshipDTO[];
|
||||
races: SponsorshipDTO[];
|
||||
platform: SponsorshipDTO[];
|
||||
};
|
||||
|
||||
@ApiProperty({ type: [ActivityItemDTO] })
|
||||
recentActivity: ActivityItemDTO[];
|
||||
|
||||
@ApiProperty({ type: [RenewalAlertDTO] })
|
||||
upcomingRenewals: RenewalAlertDTO[];
|
||||
}
|
||||
56
apps/api/src/domain/sponsor/dtos/SponsorProfileDTO.ts
Normal file
56
apps/api/src/domain/sponsor/dtos/SponsorProfileDTO.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsOptional, IsObject } from 'class-validator';
|
||||
|
||||
export class SponsorProfileDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
companyName: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
contactName: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
contactEmail: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
contactPhone: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
website: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
description: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
logoUrl?: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
industry: string;
|
||||
|
||||
@ApiProperty({ type: Object })
|
||||
address: {
|
||||
street: string;
|
||||
city: string;
|
||||
country: string;
|
||||
postalCode: string;
|
||||
};
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
taxId: string;
|
||||
|
||||
@ApiProperty({ type: Object })
|
||||
socialLinks: {
|
||||
twitter: string;
|
||||
linkedin: string;
|
||||
instagram: string;
|
||||
};
|
||||
}
|
||||
85
apps/api/src/domain/sponsor/dtos/SponsorshipDTO.ts
Normal file
85
apps/api/src/domain/sponsor/dtos/SponsorshipDTO.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsEnum, IsNumber, IsOptional, IsDateString } from 'class-validator';
|
||||
|
||||
export class SponsorshipDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
id: string;
|
||||
|
||||
@ApiProperty({ enum: ['leagues', 'teams', 'drivers', 'races', 'platform'] })
|
||||
@IsEnum(['leagues', 'teams', 'drivers', 'races', 'platform'])
|
||||
type: 'leagues' | 'teams' | 'drivers' | 'races' | 'platform';
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
entityId: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
entityName: string;
|
||||
|
||||
@ApiProperty({ enum: ['main', 'secondary'], required: false })
|
||||
@IsOptional()
|
||||
@IsEnum(['main', 'secondary'])
|
||||
tier?: 'main' | 'secondary';
|
||||
|
||||
@ApiProperty({ enum: ['active', 'pending_approval', 'approved', 'rejected', 'expired'] })
|
||||
@IsEnum(['active', 'pending_approval', 'approved', 'rejected', 'expired'])
|
||||
status: 'active' | 'pending_approval' | 'approved' | 'rejected' | 'expired';
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
applicationDate?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
approvalDate?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
rejectionReason?: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsDateString()
|
||||
startDate: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsDateString()
|
||||
endDate: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
price: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
impressions: number;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
impressionsChange?: number;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
engagement?: number;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
details?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
entityOwner?: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
applicationMessage?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user