import { describe, it, expect, beforeEach } from 'vitest'; import { GetSponsorBillingUseCase } from '../../../../core/payments/application/use-cases/GetSponsorBillingUseCase'; import { Sponsor } from '../../../../core/racing/domain/entities/sponsor/Sponsor'; import { SeasonSponsorship } from '../../../../core/racing/domain/entities/season/SeasonSponsorship'; import { Payment, PaymentType, PaymentStatus, PayerType } from '../../../../core/payments/domain/entities/Payment'; import { Money } from '../../../../core/racing/domain/value-objects/Money'; import { SponsorTestContext } from '../SponsorTestContext'; describe('Sponsor Billing Use Case Orchestration', () => { let context: SponsorTestContext; let getSponsorBillingUseCase: GetSponsorBillingUseCase; beforeEach(() => { context = new SponsorTestContext(); getSponsorBillingUseCase = new GetSponsorBillingUseCase( context.paymentRepository, context.seasonSponsorshipRepository, context.sponsorRepository, ); }); describe('GetSponsorBillingUseCase - Success Path', () => { it('should retrieve billing statistics for a sponsor with paid invoices', async () => { const sponsor = Sponsor.create({ id: 'sponsor-123', name: 'Test Company', contactEmail: 'test@example.com', }); await context.sponsorRepository.create(sponsor); const sponsorship1 = SeasonSponsorship.create({ id: 'sponsorship-1', sponsorId: 'sponsor-123', seasonId: 'season-1', tier: 'main', pricing: Money.create(1000, 'USD'), status: 'active', }); await context.seasonSponsorshipRepository.create(sponsorship1); const sponsorship2 = SeasonSponsorship.create({ id: 'sponsorship-2', sponsorId: 'sponsor-123', seasonId: 'season-2', tier: 'secondary', pricing: Money.create(500, 'USD'), status: 'active', }); await context.seasonSponsorshipRepository.create(sponsorship2); const payment1: Payment = { id: 'payment-1', type: PaymentType.SPONSORSHIP, amount: 1000, platformFee: 100, netAmount: 900, payerId: 'sponsor-123', payerType: 'team', leagueId: 'league-1', seasonId: 'season-1', status: PaymentStatus.COMPLETED, createdAt: new Date('2025-01-15'), completedAt: new Date('2025-01-15'), }; await context.paymentRepository.create(payment1); const payment2: Payment = { id: 'payment-2', type: PaymentType.SPONSORSHIP, amount: 2000, platformFee: 200, netAmount: 1800, payerId: 'sponsor-123', payerType: 'team', leagueId: 'league-2', seasonId: 'season-2', status: PaymentStatus.COMPLETED, createdAt: new Date('2025-02-15'), completedAt: new Date('2025-02-15'), }; await context.paymentRepository.create(payment2); const payment3: Payment = { id: 'payment-3', type: PaymentType.SPONSORSHIP, amount: 3000, platformFee: 300, netAmount: 2700, payerId: 'sponsor-123', payerType: 'team', leagueId: 'league-3', seasonId: 'season-3', status: PaymentStatus.COMPLETED, createdAt: new Date('2025-03-15'), completedAt: new Date('2025-03-15'), }; await context.paymentRepository.create(payment3); const result = await getSponsorBillingUseCase.execute({ sponsorId: 'sponsor-123' }); expect(result.isOk()).toBe(true); const billing = result.unwrap(); expect(billing.invoices).toHaveLength(3); // Total spent = (1000 + 190) + (2000 + 380) + (3000 + 570) = 1190 + 2380 + 3570 = 7140 expect(billing.stats.totalSpent).toBe(7140); expect(billing.stats.pendingAmount).toBe(0); expect(billing.stats.activeSponsorships).toBe(2); }); it('should retrieve billing statistics with pending invoices', async () => { const sponsor = Sponsor.create({ id: 'sponsor-123', name: 'Test Company', contactEmail: 'test@example.com', }); await context.sponsorRepository.create(sponsor); const sponsorship = SeasonSponsorship.create({ id: 'sponsorship-1', sponsorId: 'sponsor-123', seasonId: 'season-1', tier: 'main', pricing: Money.create(1000, 'USD'), status: 'active', }); await context.seasonSponsorshipRepository.create(sponsorship); const payment1: Payment = { id: 'payment-1', type: PaymentType.SPONSORSHIP, amount: 1000, platformFee: 100, netAmount: 900, payerId: 'sponsor-123', payerType: 'team', leagueId: 'league-1', seasonId: 'season-1', status: PaymentStatus.COMPLETED, createdAt: new Date('2025-01-15'), completedAt: new Date('2025-01-15'), }; await context.paymentRepository.create(payment1); const payment2: Payment = { id: 'payment-2', type: PaymentType.SPONSORSHIP, amount: 500, platformFee: 50, netAmount: 450, payerId: 'sponsor-123', payerType: 'team', leagueId: 'league-2', seasonId: 'season-2', status: PaymentStatus.PENDING, createdAt: new Date('2025-02-15'), }; await context.paymentRepository.create(payment2); const result = await getSponsorBillingUseCase.execute({ sponsorId: 'sponsor-123' }); expect(result.isOk()).toBe(true); const billing = result.unwrap(); expect(billing.invoices).toHaveLength(2); expect(billing.stats.totalSpent).toBe(1190); expect(billing.stats.pendingAmount).toBe(595); expect(billing.stats.nextPaymentAmount).toBe(595); }); }); describe('GetSponsorBillingUseCase - Error Handling', () => { it('should return error when sponsor does not exist', async () => { const result = await getSponsorBillingUseCase.execute({ sponsorId: 'non-existent-sponsor' }); expect(result.isErr()).toBe(true); const error = result.unwrapErr(); expect(error.code).toBe('SPONSOR_NOT_FOUND'); }); }); });