Add lessons Phase 5: grading scales with nested levels
Custom grading scales with ordered levels (value, label, numeric score, color). Supports one-default-per-store constraint, deep create with nested levels, lookup endpoint for dropdowns, and search/pagination. 12 new tests (76 total lessons tests).
This commit is contained in:
22
packages/backend/src/db/migrations/0032_grading_scales.sql
Normal file
22
packages/backend/src/db/migrations/0032_grading_scales.sql
Normal file
@@ -0,0 +1,22 @@
|
||||
-- Phase 5: Grading scales — custom grade definitions per store
|
||||
|
||||
CREATE TABLE "grading_scale" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"name" varchar(255) NOT NULL,
|
||||
"description" text,
|
||||
"is_default" boolean NOT NULL DEFAULT false,
|
||||
"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 "grading_scale_level" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"grading_scale_id" uuid NOT NULL REFERENCES "grading_scale"("id"),
|
||||
"value" varchar(50) NOT NULL,
|
||||
"label" varchar(255) NOT NULL,
|
||||
"numeric_value" integer NOT NULL,
|
||||
"color_hex" varchar(7),
|
||||
"sort_order" integer NOT NULL
|
||||
);
|
||||
@@ -225,6 +225,13 @@
|
||||
"when": 1774910000000,
|
||||
"tag": "0031_lesson_sessions",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 32,
|
||||
"version": "7",
|
||||
"when": 1774920000000,
|
||||
"tag": "0032_grading_scales",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -120,6 +120,29 @@ export const lessonSessions = pgTable('lesson_session', {
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
})
|
||||
|
||||
export const gradingScales = pgTable('grading_scale', {
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
name: varchar('name', { length: 255 }).notNull(),
|
||||
description: text('description'),
|
||||
isDefault: boolean('is_default').notNull().default(false),
|
||||
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 gradingScaleLevels = pgTable('grading_scale_level', {
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
gradingScaleId: uuid('grading_scale_id')
|
||||
.notNull()
|
||||
.references(() => gradingScales.id),
|
||||
value: varchar('value', { length: 50 }).notNull(),
|
||||
label: varchar('label', { length: 255 }).notNull(),
|
||||
numericValue: integer('numeric_value').notNull(),
|
||||
colorHex: varchar('color_hex', { length: 7 }),
|
||||
sortOrder: integer('sort_order').notNull(),
|
||||
})
|
||||
|
||||
// --- Type exports ---
|
||||
|
||||
export type Instructor = typeof instructors.$inferSelect
|
||||
@@ -132,3 +155,7 @@ export type Enrollment = typeof enrollments.$inferSelect
|
||||
export type EnrollmentInsert = typeof enrollments.$inferInsert
|
||||
export type LessonSession = typeof lessonSessions.$inferSelect
|
||||
export type LessonSessionInsert = typeof lessonSessions.$inferInsert
|
||||
export type GradingScale = typeof gradingScales.$inferSelect
|
||||
export type GradingScaleInsert = typeof gradingScales.$inferInsert
|
||||
export type GradingScaleLevel = typeof gradingScaleLevels.$inferSelect
|
||||
export type GradingScaleLevelInsert = typeof gradingScaleLevels.$inferInsert
|
||||
|
||||
Reference in New Issue
Block a user