import { Injectable, Logger, Module } from '@nestjs/common'; import { ModuleRef } from '@nestjs/core'; import { OnEvent } from '@nestjs/event-emitter'; import { AuditModule } from '../../common/audit.module'; import { BookingsModule } from '../bookings/bookings.module'; import { SeatsModule } from '../seats/seats.module'; import { SegmentsModule } from '../segments/segments.module'; import { TicketsModule } from '../tickets/tickets.module'; import { PaymentsModule } from '../payments/payments.module'; import { CurrencyModule } from '../currency/currency.module'; import { SystemConfigModule } from '../system-config/system-config.module'; import { SUPPLEMENTARY_CHARGE_PAID_EVENT } from '../reschedule/reschedule.service'; import { UpgradeController } from './upgrade.controller'; import { UpgradeService } from './upgrade.service'; /** * Same shape and same reason as RescheduleEventsListener: UpgradeService is request-scoped by * transitivity (AuditService injects REQUEST), and Nest never fires @OnEvent on request-scoped * providers — so the listener is a singleton that resolves the service per event. * * Two listeners on one event is fine: each looks its charge up by its own unique * `supplementaryChargeId` and returns silently when the charge is not theirs. */ @Injectable() export class UpgradeEventsListener { private readonly logger = new Logger(UpgradeEventsListener.name); constructor(private readonly moduleRef: ModuleRef) {} @OnEvent(SUPPLEMENTARY_CHARGE_PAID_EVENT, { async: true }) async onChargePaid(payload: { chargeId: string }) { try { const service = await this.moduleRef.resolve(UpgradeService, undefined, { strict: false }); await service.applyForCharge(payload.chargeId); } catch (err) { this.logger.error(`Failed to apply upgrade for charge ${payload.chargeId}: ${err instanceof Error ? err.message : err}`); } } } @Module({ imports: [AuditModule, BookingsModule, SeatsModule, SegmentsModule, TicketsModule, PaymentsModule, CurrencyModule, SystemConfigModule], controllers: [UpgradeController], providers: [UpgradeService, UpgradeEventsListener], exports: [UpgradeService], }) export class UpgradeModule {}