Add Phase 8: lesson plan templates with deep-copy instantiation
- New tables: lesson_plan_template, lesson_plan_template_section, lesson_plan_template_item - skill_level enum: beginner, intermediate, advanced, all_levels - Templates are reusable curriculum definitions independent of any member/enrollment - POST /lesson-plan-templates/:id/create-plan deep-copies the template into a member plan - Instantiation uses template name as default plan title, accepts custom title override - Instantiation deactivates any existing active plan on the enrollment (one-active rule) - Plan items are independent copies — renaming the template does not affect existing plans - 11 new integration tests
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
-- Phase 8: Lesson plan templates — reusable curriculum definitions
|
||||
|
||||
CREATE TYPE "skill_level" AS ENUM ('beginner', 'intermediate', 'advanced', 'all_levels');
|
||||
|
||||
CREATE TABLE "lesson_plan_template" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"name" varchar(255) NOT NULL,
|
||||
"description" text,
|
||||
"instrument" varchar(100),
|
||||
"skill_level" skill_level NOT NULL DEFAULT 'all_levels',
|
||||
"created_by" uuid REFERENCES "user"("id"),
|
||||
"is_active" boolean NOT NULL DEFAULT true,
|
||||
"created_at" timestamptz NOT NULL DEFAULT now(),
|
||||
"updated_at" timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE "lesson_plan_template_section" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"template_id" uuid NOT NULL REFERENCES "lesson_plan_template"("id"),
|
||||
"title" varchar(255) NOT NULL,
|
||||
"description" text,
|
||||
"sort_order" integer NOT NULL,
|
||||
"created_at" timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE "lesson_plan_template_item" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"section_id" uuid NOT NULL REFERENCES "lesson_plan_template_section"("id"),
|
||||
"title" varchar(255) NOT NULL,
|
||||
"description" text,
|
||||
"grading_scale_id" uuid REFERENCES "grading_scale"("id"),
|
||||
"target_grade_value" varchar(50),
|
||||
"sort_order" integer NOT NULL,
|
||||
"created_at" timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
@@ -253,6 +253,13 @@
|
||||
"when": 1774950000000,
|
||||
"tag": "0035_grade_history",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 36,
|
||||
"version": "7",
|
||||
"when": 1774960000000,
|
||||
"tag": "0036_lesson_plan_templates",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -218,6 +218,46 @@ export const lessonPlanItems = pgTable('lesson_plan_item', {
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
})
|
||||
|
||||
// --- Lesson Plan Templates ---
|
||||
|
||||
export const skillLevelEnum = pgEnum('skill_level', ['beginner', 'intermediate', 'advanced', 'all_levels'])
|
||||
|
||||
export const lessonPlanTemplates = pgTable('lesson_plan_template', {
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
name: varchar('name', { length: 255 }).notNull(),
|
||||
description: text('description'),
|
||||
instrument: varchar('instrument', { length: 100 }),
|
||||
skillLevel: skillLevelEnum('skill_level').notNull().default('all_levels'),
|
||||
createdBy: uuid('created_by').references(() => users.id),
|
||||
isActive: boolean('is_active').notNull().default(true),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
})
|
||||
|
||||
export const lessonPlanTemplateSections = pgTable('lesson_plan_template_section', {
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
templateId: uuid('template_id')
|
||||
.notNull()
|
||||
.references(() => lessonPlanTemplates.id),
|
||||
title: varchar('title', { length: 255 }).notNull(),
|
||||
description: text('description'),
|
||||
sortOrder: integer('sort_order').notNull(),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
})
|
||||
|
||||
export const lessonPlanTemplateItems = pgTable('lesson_plan_template_item', {
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
sectionId: uuid('section_id')
|
||||
.notNull()
|
||||
.references(() => lessonPlanTemplateSections.id),
|
||||
title: varchar('title', { length: 255 }).notNull(),
|
||||
description: text('description'),
|
||||
gradingScaleId: uuid('grading_scale_id').references(() => gradingScales.id),
|
||||
targetGradeValue: varchar('target_grade_value', { length: 50 }),
|
||||
sortOrder: integer('sort_order').notNull(),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
})
|
||||
|
||||
export const lessonPlanItemGradeHistory = pgTable('lesson_plan_item_grade_history', {
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
lessonPlanItemId: uuid('lesson_plan_item_id')
|
||||
@@ -268,6 +308,12 @@ export type LessonPlanSection = typeof lessonPlanSections.$inferSelect
|
||||
export type LessonPlanSectionInsert = typeof lessonPlanSections.$inferInsert
|
||||
export type LessonPlanItem = typeof lessonPlanItems.$inferSelect
|
||||
export type LessonPlanItemInsert = typeof lessonPlanItems.$inferInsert
|
||||
export type LessonPlanTemplate = typeof lessonPlanTemplates.$inferSelect
|
||||
export type LessonPlanTemplateInsert = typeof lessonPlanTemplates.$inferInsert
|
||||
export type LessonPlanTemplateSection = typeof lessonPlanTemplateSections.$inferSelect
|
||||
export type LessonPlanTemplateSectionInsert = typeof lessonPlanTemplateSections.$inferInsert
|
||||
export type LessonPlanTemplateItem = typeof lessonPlanTemplateItems.$inferSelect
|
||||
export type LessonPlanTemplateItemInsert = typeof lessonPlanTemplateItems.$inferInsert
|
||||
export type LessonPlanItemGradeHistory = typeof lessonPlanItemGradeHistory.$inferSelect
|
||||
export type LessonPlanItemGradeHistoryInsert = typeof lessonPlanItemGradeHistory.$inferInsert
|
||||
export type LessonSessionPlanItem = typeof lessonSessionPlanItems.$inferSelect
|
||||
|
||||
Reference in New Issue
Block a user