feat: 优化排课管理

This commit is contained in:
richarjiang
2026-04-15 23:25:09 +08:00
parent 6ab16f508a
commit 4dacd908a6
14 changed files with 71 additions and 765 deletions

View File

@@ -6,14 +6,10 @@ import {
BookingStatus,
SLOT_GENERATION_DAYS,
DEFAULT_SLOT_CAPACITY,
getDefaultTimeSlots,
} from '@mp-pilates/shared'
import { PrismaService } from '../prisma/prisma.service'
/** Convert JS getDay() (0=Sun … 6=Sat) to ISO weekday (1=Mon … 7=Sun) */
function toIsoWeekday(jsDay: number): number {
return jsDay === 0 ? 7 : jsDay
}
/** Build a UTC Date for midnight of a local calendar date */
function toUtcMidnight(date: Date): Date {
const d = new Date(date)
@@ -28,20 +24,14 @@ export class SlotGeneratorService {
constructor(private readonly prisma: PrismaService) {}
/**
* Generate time slots for the next `daysAhead` days based on active
* WeekTemplates. Uses `createMany` with `skipDuplicates` so re-runs are safe.
* Generate time slots for the next `daysAhead` days based on the fixed
* default schedule (Mon-Sun, 08:00-22:00 hourly).
* Uses `createMany` with `skipDuplicates` so re-runs are safe.
*
* @returns Number of newly created slots
*/
async generateSlots(daysAhead: number = SLOT_GENERATION_DAYS): Promise<number> {
const templates = await this.prisma.weekTemplate.findMany({
where: { isActive: true },
})
if (templates.length === 0) {
this.logger.log('No active week templates found skipping slot generation')
return 0
}
const defaultSlots = getDefaultTimeSlots()
const tomorrow = new Date()
tomorrow.setDate(tomorrow.getDate() + 1)
@@ -53,27 +43,19 @@ export class SlotGeneratorService {
endTime: string
capacity: number
source: TimeSlotSource
templateId: string
}> = []
for (let offset = 0; offset < daysAhead; offset++) {
const target = new Date(tomorrow)
target.setDate(target.getDate() + offset)
const isoWeekday = toIsoWeekday(target.getDay())
const matchingTemplates = templates.filter(
(t) => t.dayOfWeek === isoWeekday,
)
for (const template of matchingTemplates) {
for (const slot of defaultSlots) {
slotsToCreate.push({
date: toUtcMidnight(target),
startTime: template.startTime,
endTime: template.endTime,
capacity: template.capacity ?? DEFAULT_SLOT_CAPACITY,
startTime: slot.startTime,
endTime: slot.endTime,
capacity: DEFAULT_SLOT_CAPACITY,
source: TimeSlotSource.TEMPLATE,
templateId: template.id,
})
}
}