72 lines
2.5 KiB
TypeScript
72 lines
2.5 KiB
TypeScript
import { Injectable, Logger } from '@nestjs/common'
|
|
import { Cron } from '@nestjs/schedule'
|
|
import { SlotGeneratorService } from '../time-slot/slot-generator.service'
|
|
import { FlashSaleService } from '../flash-sale/flash-sale.service'
|
|
|
|
@Injectable()
|
|
export class SchedulerService {
|
|
private readonly logger = new Logger(SchedulerService.name)
|
|
|
|
constructor(
|
|
private readonly slotGenerator: SlotGeneratorService,
|
|
private readonly flashSaleService: FlashSaleService,
|
|
) {}
|
|
|
|
/** 02:00 daily — generate slots 14 days ahead from week templates */
|
|
@Cron('0 2 * * *')
|
|
async handleSlotGeneration(): Promise<void> {
|
|
try {
|
|
const count = await this.slotGenerator.generateSlots(14)
|
|
this.logger.log(`[handleSlotGeneration] Created ${count} new time slots`)
|
|
} catch (err) {
|
|
this.logger.error('[handleSlotGeneration] Failed to generate slots', err)
|
|
}
|
|
}
|
|
|
|
/** 02:30 daily — close past OPEN slots */
|
|
@Cron('30 2 * * *')
|
|
async handleCleanupSlots(): Promise<void> {
|
|
try {
|
|
const count = await this.slotGenerator.cleanupExpiredSlots()
|
|
this.logger.log(`[handleCleanupSlots] Closed ${count} expired slots`)
|
|
} catch (err) {
|
|
this.logger.error('[handleCleanupSlots] Failed to clean up slots', err)
|
|
}
|
|
}
|
|
|
|
/** 03:00 daily — expire memberships past their end date or with 0 sessions */
|
|
@Cron('0 3 * * *')
|
|
async handleCheckMemberships(): Promise<void> {
|
|
try {
|
|
const count = await this.slotGenerator.checkExpiredMemberships()
|
|
this.logger.log(`[handleCheckMemberships] Updated ${count} memberships`)
|
|
} catch (err) {
|
|
this.logger.error('[handleCheckMemberships] Failed to check memberships', err)
|
|
}
|
|
}
|
|
|
|
/** 22:00 daily — mark past CONFIRMED bookings as COMPLETED */
|
|
@Cron('0 22 * * *')
|
|
async handleCompleteBookings(): Promise<void> {
|
|
try {
|
|
const count = await this.slotGenerator.completeBookings()
|
|
this.logger.log(`[handleCompleteBookings] Completed ${count} bookings`)
|
|
} catch (err) {
|
|
this.logger.error('[handleCompleteBookings] Failed to complete bookings', err)
|
|
}
|
|
}
|
|
|
|
/** Every 5 min — expire unpaid flash sale reservations older than 15min */
|
|
@Cron('*/5 * * * *')
|
|
async handleExpireFlashSaleReservations(): Promise<void> {
|
|
try {
|
|
const count = await this.flashSaleService.expireUnpaidReservations(15)
|
|
if (count > 0) {
|
|
this.logger.log(`[handleExpireFlashSaleReservations] Expired ${count} unpaid reservations`)
|
|
}
|
|
} catch (err) {
|
|
this.logger.error('[handleExpireFlashSaleReservations] Failed', err)
|
|
}
|
|
}
|
|
}
|