Add lessons Phase 3: enrollments with capacity and time conflict checks

Links members to schedule slots via enrollments. Enforces max_students
capacity on slots and prevents members from double-booking the same
day/time. Supports status transitions and filtering. 11 new tests
(51 total lessons tests).
This commit is contained in:
Ryan Moon
2026-03-30 09:23:43 -05:00
parent f777ce5184
commit 93405af3b2
8 changed files with 489 additions and 3 deletions

View File

@@ -108,6 +108,10 @@ export {
LessonTypeUpdateSchema,
ScheduleSlotCreateSchema,
ScheduleSlotUpdateSchema,
EnrollmentStatus,
EnrollmentCreateSchema,
EnrollmentUpdateSchema,
EnrollmentStatusUpdateSchema,
} from './lessons.schema.js'
export type {
InstructorCreateInput,
@@ -116,4 +120,7 @@ export type {
LessonTypeUpdateInput,
ScheduleSlotCreateInput,
ScheduleSlotUpdateInput,
EnrollmentCreateInput,
EnrollmentUpdateInput,
EnrollmentStatusUpdateInput,
} from './lessons.schema.js'

View File

@@ -51,3 +51,33 @@ export type ScheduleSlotCreateInput = z.infer<typeof ScheduleSlotCreateSchema>
export const ScheduleSlotUpdateSchema = ScheduleSlotCreateSchema.partial()
export type ScheduleSlotUpdateInput = z.infer<typeof ScheduleSlotUpdateSchema>
// --- Enrollment schemas ---
export const EnrollmentStatus = z.enum(['active', 'paused', 'cancelled', 'completed'])
export type EnrollmentStatus = z.infer<typeof EnrollmentStatus>
export const EnrollmentCreateSchema = z.object({
memberId: z.string().uuid(),
accountId: z.string().uuid(),
scheduleSlotId: z.string().uuid(),
instructorId: z.string().uuid(),
startDate: z.string().min(1),
endDate: opt(z.string()),
monthlyRate: z.coerce.number().min(0).optional(),
notes: opt(z.string()),
})
export type EnrollmentCreateInput = z.infer<typeof EnrollmentCreateSchema>
export const EnrollmentUpdateSchema = EnrollmentCreateSchema.omit({
memberId: true,
accountId: true,
scheduleSlotId: true,
instructorId: true,
}).partial()
export type EnrollmentUpdateInput = z.infer<typeof EnrollmentUpdateSchema>
export const EnrollmentStatusUpdateSchema = z.object({
status: EnrollmentStatus,
})
export type EnrollmentStatusUpdateInput = z.infer<typeof EnrollmentStatusUpdateSchema>