refactor: 迁移脚本系统重构 + 新增 db 脚本 + 工作日志

- 清理全部旧迁移文件(0000-0011)和 meta 目录
- 使用 drizzle-kit generate 从 schema 重新生成单一迁移文件
  - 0000_perfect_pestilence.sql: 包含全部 49 张表
  - 修复 0011_ai_providers.sql 未在 journal 注册导致 migrate 失败的问题
  - 修复缺少 snapshot 文件的问题
  - 移除复杂 PREPARE/EXECUTE 条件 SQL,使用标准 CREATE TABLE
- package.json 新增脚本:
  - db:create: 创建数据库
  - db:push: 直接同步 schema(开发用)
  - db:setup: 一键 create → migrate → seed
- 干净数据库全流程测试通过: create → migrate → seed
- 更新工作日志(docs/work_log.md)
This commit is contained in:
SpecialX
2026-06-17 14:21:24 +08:00
parent f013337ff7
commit baf8f679bf
18 changed files with 3751 additions and 3406 deletions

View File

@@ -1,5 +1,58 @@
# Work Log # Work Log
## 2026-06-17
### 1. Next.js 16 Proxy 修复
- `src/proxy.ts` 导出函数从 `middleware` 重命名为 `proxy`Next.js 16 要求)
- 修复 `getToken()` 在 edge 运行时缺少 `secret` 导致的 `MissingSecret` 错误
- 显式传入 `secret: process.env.NEXTAUTH_SECRET`
- 主要修改:[proxy.ts](file:///e:/Desktop/CICD/src/proxy.ts)
### 2. MySQL 端口切换 + 数据库创建脚本
- `.env` 中 MySQL 端口从 13002 改为 14013
- 新增 `scripts/create-db.ts`:连接 MySQL不指定库后执行 `CREATE DATABASE IF NOT EXISTS next_edu`,字符集 utf8mb4_unicode_ci
- 主要修改:[.env](file:///e:/Desktop/CICD/.env)、[create-db.ts](file:///e:/Desktop/CICD/scripts/create-db.ts)
### 3. 种子脚本完全重写(小学场景)
- 完全重写 `scripts/seed.ts`,实现小学完整场景初始化
- 数据规模:
- 1 所学校实验小学、2 个年级(一/二年级)、每年级 2 个班级
- 8 名教师(每班 2 名1 班主任 + 1 科任,跨班覆盖语数外 3 科)
- 24 名学生(每班 6 名)+ 24 名家长
- 3 科教材(语数外各 1 本)+ 章节 + 知识点
- 15 道题目(每科 5 道:单选/文本/判断)
- 2 套试卷(语文/数学)+ 24 份提交 + 120 个答案
- 2 套作业 + 6 份提交 + 30 个答案
- 课表、成绩、考勤、课程计划、公告等完整数据
- 6 个角色 + 47 个权限点的 RBAC 映射149 条记录)
- 17 个顺序步骤,耗时约 127s
- 主要修改:[seed.ts](file:///e:/Desktop/CICD/scripts/seed.ts)
### 4. 迁移脚本系统重构
- **问题**:旧迁移系统存在多个缺陷
- `0011_ai_providers.sql` 未在 `_journal.json` 中注册,导致 `drizzle-kit migrate` 失败
- 缺少多数 snapshot 文件(仅存 0008、0009
- 迁移 SQL 使用复杂 PREPARE/EXECUTE 条件模式,维护困难
- **修复**:清理全部旧迁移文件与 meta 目录,使用 `drizzle-kit generate` 从 schema 重新生成
- 生成单一迁移文件 `0000_perfect_pestilence.sql`,包含全部 49 张表
- journal 重置为单条记录snapshot 完整
- **新增 npm 脚本**package.json
- `db:create`:创建数据库
- `db:push`:直接同步 schema开发用
- `db:setup`:一键 create → migrate → seed
- 主要修改:[package.json](file:///e:/Desktop/CICD/package.json)、drizzle/ 目录
### 5. 验证
- 干净数据库全流程测试:`db:create``db:migrate``db:seed` 全部通过
- 49 张表成功创建,种子数据完整写入
- 测试账号(密码均为 123456
- 管理员: admin@xiaoxue.edu.cn
- 语文老师/一年级1班班主任: t_chinese_1@xiaoxue.edu.cn
- 数学老师: t_math_1@xiaoxue.edu.cn
- 英语老师: t_english_1@xiaoxue.edu.cn
- 学生: student_g1c1_1@xiaoxue.edu.cn
- 家长: parent_g1c1_1@xiaoxue.edu.cn
## 2026-03-19 ## 2026-03-19
### 1. 作业与权限测试覆盖补齐(第二阶段) ### 1. 作业与权限测试覆盖补齐(第二阶段)

View File

@@ -1 +0,0 @@
SELECT 1;--> statement-breakpoint

View File

@@ -0,0 +1,816 @@
CREATE TABLE `academic_years` (
`id` varchar(128) NOT NULL,
`name` varchar(100) NOT NULL,
`start_date` timestamp NOT NULL,
`end_date` timestamp NOT NULL,
`is_active` boolean NOT NULL DEFAULT false,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `academic_years_id` PRIMARY KEY(`id`),
CONSTRAINT `academic_years_name_unique` UNIQUE(`name`)
);
--> statement-breakpoint
CREATE TABLE `accounts` (
`userId` varchar(128) NOT NULL,
`type` varchar(255) NOT NULL,
`provider` varchar(255) NOT NULL,
`providerAccountId` varchar(255) NOT NULL,
`refresh_token` text,
`access_token` text,
`expires_at` int,
`token_type` varchar(255),
`scope` varchar(255),
`id_token` text,
`session_state` varchar(255),
CONSTRAINT `accounts_provider_providerAccountId_pk` PRIMARY KEY(`provider`,`providerAccountId`)
);
--> statement-breakpoint
CREATE TABLE `ai_providers` (
`id` varchar(128) NOT NULL,
`provider` enum('zhipu','openai','gemini','custom') NOT NULL,
`base_url` varchar(512),
`model` varchar(128) NOT NULL,
`api_key_encrypted` text NOT NULL,
`api_key_last4` varchar(4),
`is_default` boolean NOT NULL DEFAULT false,
`created_by` varchar(128),
`updated_by` varchar(128),
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `ai_providers_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `announcements` (
`id` varchar(128) NOT NULL,
`title` varchar(255) NOT NULL,
`content` text NOT NULL,
`type` enum('school','grade','class') NOT NULL DEFAULT 'school',
`status` enum('draft','published','archived') NOT NULL DEFAULT 'draft',
`target_grade_id` varchar(128),
`target_class_id` varchar(128),
`author_id` varchar(128) NOT NULL,
`published_at` datetime,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `announcements_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `attendance_records` (
`id` varchar(128) NOT NULL,
`student_id` varchar(128) NOT NULL,
`class_id` varchar(128) NOT NULL,
`schedule_id` varchar(128),
`date` date NOT NULL,
`status` enum('present','absent','late','early_leave','excused') NOT NULL,
`remark` text,
`recorded_by` varchar(128) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `attendance_records_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `attendance_rules` (
`id` varchar(128) NOT NULL,
`class_id` varchar(128),
`late_threshold_minutes` int DEFAULT 15,
`early_leave_threshold_minutes` int DEFAULT 15,
`enable_auto_mark` boolean DEFAULT false,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `attendance_rules_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `audit_logs` (
`id` varchar(128) NOT NULL,
`user_id` varchar(128) NOT NULL,
`user_name` varchar(255) NOT NULL,
`action` varchar(255) NOT NULL,
`module` varchar(128) NOT NULL,
`target_id` varchar(128),
`target_type` varchar(128),
`detail` text,
`ip_address` varchar(45),
`user_agent` varchar(512),
`status` enum('success','failure') NOT NULL DEFAULT 'success',
`created_at` timestamp NOT NULL DEFAULT (now()),
CONSTRAINT `audit_logs_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `chapters` (
`id` varchar(128) NOT NULL,
`textbook_id` varchar(128) NOT NULL,
`title` varchar(255) NOT NULL,
`order` int DEFAULT 0,
`parent_id` varchar(128),
`content` text,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `chapters_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `class_enrollments` (
`class_id` varchar(128) NOT NULL,
`student_id` varchar(128) NOT NULL,
`class_enrollment_status` enum('active','inactive') NOT NULL DEFAULT 'active',
`created_at` timestamp NOT NULL DEFAULT (now()),
CONSTRAINT `class_enrollments_class_id_student_id_pk` PRIMARY KEY(`class_id`,`student_id`)
);
--> statement-breakpoint
CREATE TABLE `class_schedule` (
`id` varchar(128) NOT NULL,
`class_id` varchar(128) NOT NULL,
`weekday` int NOT NULL,
`start_time` varchar(5) NOT NULL,
`end_time` varchar(5) NOT NULL,
`course` varchar(255) NOT NULL,
`location` varchar(100),
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `class_schedule_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `class_subject_teachers` (
`class_id` varchar(128) NOT NULL,
`subject_id` varchar(128) NOT NULL,
`teacher_id` varchar(128),
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `class_subject_teachers_class_id_subject_id_pk` PRIMARY KEY(`class_id`,`subject_id`)
);
--> statement-breakpoint
CREATE TABLE `classes` (
`id` varchar(128) NOT NULL,
`school_name` varchar(255),
`school_id` varchar(128),
`name` varchar(255) NOT NULL,
`grade` varchar(50) NOT NULL,
`grade_id` varchar(128),
`homeroom` varchar(50),
`room` varchar(50),
`invitation_code` varchar(6),
`teacher_id` varchar(128) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `classes_id` PRIMARY KEY(`id`),
CONSTRAINT `classes_invitation_code_unique` UNIQUE(`invitation_code`)
);
--> statement-breakpoint
CREATE TABLE `classrooms` (
`id` varchar(128) NOT NULL,
`name` varchar(255) NOT NULL,
`building` varchar(100),
`floor` int,
`capacity` int,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `classrooms_id` PRIMARY KEY(`id`),
CONSTRAINT `classrooms_name_unique` UNIQUE(`name`)
);
--> statement-breakpoint
CREATE TABLE `course_plan_items` (
`id` varchar(128) NOT NULL,
`plan_id` varchar(128) NOT NULL,
`week` int NOT NULL,
`topic` varchar(255) NOT NULL,
`content` text,
`hours` int NOT NULL DEFAULT 2,
`textbook_chapter` varchar(255),
`notes` text,
`is_completed` boolean NOT NULL DEFAULT false,
`completed_at` date,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `course_plan_items_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `course_plans` (
`id` varchar(128) NOT NULL,
`class_id` varchar(128) NOT NULL,
`subject_id` varchar(128) NOT NULL,
`teacher_id` varchar(128) NOT NULL,
`academic_year_id` varchar(128),
`semester` enum('1','2') NOT NULL DEFAULT '1',
`total_hours` int NOT NULL DEFAULT 0,
`completed_hours` int NOT NULL DEFAULT 0,
`weekly_hours` int NOT NULL DEFAULT 0,
`start_date` date,
`end_date` date,
`syllabus` text,
`objectives` text,
`status` enum('planning','active','completed','paused') NOT NULL DEFAULT 'planning',
`created_by` varchar(128) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `course_plans_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `data_change_logs` (
`id` varchar(128) NOT NULL,
`table_name` varchar(128) NOT NULL,
`record_id` varchar(128) NOT NULL,
`action` enum('create','update','delete') NOT NULL,
`old_value` text,
`new_value` text,
`changed_by` varchar(128) NOT NULL,
`changed_by_name` varchar(255) NOT NULL,
`ip_address` varchar(45),
`created_at` timestamp NOT NULL DEFAULT (now()),
CONSTRAINT `data_change_logs_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `departments` (
`id` varchar(128) NOT NULL,
`name` varchar(255) NOT NULL,
`description` text,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `departments_id` PRIMARY KEY(`id`),
CONSTRAINT `departments_name_unique` UNIQUE(`name`)
);
--> statement-breakpoint
CREATE TABLE `exam_questions` (
`exam_id` varchar(128) NOT NULL,
`question_id` varchar(128) NOT NULL,
`score` int DEFAULT 0,
`order` int DEFAULT 0,
CONSTRAINT `exam_questions_exam_id_question_id_pk` PRIMARY KEY(`exam_id`,`question_id`)
);
--> statement-breakpoint
CREATE TABLE `exam_submissions` (
`id` varchar(128) NOT NULL,
`exam_id` varchar(128) NOT NULL,
`student_id` varchar(128) NOT NULL,
`score` int,
`status` varchar(50) DEFAULT 'started',
`submitted_at` timestamp,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `exam_submissions_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `exams` (
`id` varchar(128) NOT NULL,
`title` varchar(255) NOT NULL,
`description` text,
`structure` json,
`creator_id` varchar(128) NOT NULL,
`subject_id` varchar(128),
`grade_id` varchar(128),
`start_time` timestamp,
`end_time` timestamp,
`status` varchar(50) DEFAULT 'draft',
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `exams_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `file_attachments` (
`id` varchar(128) NOT NULL,
`filename` varchar(255) NOT NULL,
`original_name` varchar(255) NOT NULL,
`mime_type` varchar(128) NOT NULL,
`size` bigint NOT NULL,
`storage_path` varchar(512) NOT NULL,
`url` varchar(512),
`uploader_id` varchar(128) NOT NULL,
`target_type` varchar(128),
`target_id` varchar(128),
`created_at` timestamp NOT NULL DEFAULT (now()),
CONSTRAINT `file_attachments_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `grade_records` (
`id` varchar(128) NOT NULL,
`student_id` varchar(128) NOT NULL,
`class_id` varchar(128) NOT NULL,
`subject_id` varchar(128) NOT NULL,
`exam_id` varchar(128),
`academic_year_id` varchar(128),
`title` varchar(255) NOT NULL,
`score` decimal(6,2) NOT NULL,
`full_score` decimal(6,2) NOT NULL DEFAULT '100',
`type` enum('exam','quiz','homework','other') NOT NULL DEFAULT 'exam',
`semester` enum('1','2') NOT NULL DEFAULT '1',
`recorded_by` varchar(128) NOT NULL,
`remark` text,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `grade_records_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `grades` (
`id` varchar(128) NOT NULL,
`school_id` varchar(128) NOT NULL,
`name` varchar(100) NOT NULL,
`order` int NOT NULL DEFAULT 0,
`grade_head_id` varchar(128),
`teaching_head_id` varchar(128),
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `grades_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `homework_answers` (
`id` varchar(128) NOT NULL,
`submission_id` varchar(128) NOT NULL,
`question_id` varchar(128) NOT NULL,
`answer_content` json,
`score` int,
`feedback` text,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `homework_answers_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `homework_assignment_questions` (
`assignment_id` varchar(128) NOT NULL,
`question_id` varchar(128) NOT NULL,
`score` int DEFAULT 0,
`order` int DEFAULT 0,
CONSTRAINT `homework_assignment_questions_assignment_id_question_id_pk` PRIMARY KEY(`assignment_id`,`question_id`)
);
--> statement-breakpoint
CREATE TABLE `homework_assignment_targets` (
`assignment_id` varchar(128) NOT NULL,
`student_id` varchar(128) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT (now()),
CONSTRAINT `homework_assignment_targets_assignment_id_student_id_pk` PRIMARY KEY(`assignment_id`,`student_id`)
);
--> statement-breakpoint
CREATE TABLE `homework_assignments` (
`id` varchar(128) NOT NULL,
`source_exam_id` varchar(128) NOT NULL,
`title` varchar(255) NOT NULL,
`description` text,
`structure` json,
`status` varchar(50) DEFAULT 'draft',
`creator_id` varchar(128) NOT NULL,
`available_at` timestamp,
`due_at` timestamp,
`allow_late` boolean NOT NULL DEFAULT false,
`late_due_at` timestamp,
`max_attempts` int NOT NULL DEFAULT 1,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `homework_assignments_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `homework_submissions` (
`id` varchar(128) NOT NULL,
`assignment_id` varchar(128) NOT NULL,
`student_id` varchar(128) NOT NULL,
`attempt_no` int NOT NULL DEFAULT 1,
`score` int,
`status` varchar(50) DEFAULT 'started',
`started_at` timestamp NOT NULL DEFAULT (now()),
`submitted_at` timestamp,
`is_late` boolean NOT NULL DEFAULT false,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `homework_submissions_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `knowledge_points` (
`id` varchar(128) NOT NULL,
`name` varchar(255) NOT NULL,
`description` text,
`anchor_text` varchar(255),
`parent_id` varchar(128),
`chapter_id` varchar(128),
`level` int DEFAULT 0,
`order` int DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `knowledge_points_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `login_logs` (
`id` varchar(128) NOT NULL,
`user_id` varchar(128),
`user_email` varchar(255) NOT NULL,
`action` enum('signin','signout','signup') NOT NULL,
`status` enum('success','failure') NOT NULL DEFAULT 'success',
`ip_address` varchar(45),
`user_agent` varchar(512),
`error_message` text,
`created_at` timestamp NOT NULL DEFAULT (now()),
CONSTRAINT `login_logs_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `message_notifications` (
`id` varchar(128) NOT NULL,
`user_id` varchar(128) NOT NULL,
`type` varchar(128) NOT NULL,
`title` varchar(255) NOT NULL,
`content` text,
`link` varchar(512),
`is_read` boolean NOT NULL DEFAULT false,
`created_at` timestamp NOT NULL DEFAULT (now()),
CONSTRAINT `message_notifications_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `messages` (
`id` varchar(128) NOT NULL,
`sender_id` varchar(128) NOT NULL,
`receiver_id` varchar(128) NOT NULL,
`subject` varchar(255),
`content` text NOT NULL,
`is_read` boolean NOT NULL DEFAULT false,
`read_at` timestamp,
`parent_message_id` varchar(128),
`created_at` timestamp NOT NULL DEFAULT (now()),
CONSTRAINT `messages_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `notification_preferences` (
`id` varchar(128) NOT NULL,
`user_id` varchar(128) NOT NULL,
`email_enabled` boolean NOT NULL DEFAULT false,
`sms_enabled` boolean NOT NULL DEFAULT false,
`push_enabled` boolean NOT NULL DEFAULT true,
`homework_notifications` boolean NOT NULL DEFAULT true,
`grade_notifications` boolean NOT NULL DEFAULT true,
`announcement_notifications` boolean NOT NULL DEFAULT true,
`message_notifications` boolean NOT NULL DEFAULT true,
`attendance_notifications` boolean NOT NULL DEFAULT true,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `notification_preferences_id` PRIMARY KEY(`id`),
CONSTRAINT `notification_preferences_user_id_unique` UNIQUE(`user_id`)
);
--> statement-breakpoint
CREATE TABLE `parent_student_relations` (
`id` varchar(128) NOT NULL,
`parent_id` varchar(128) NOT NULL,
`student_id` varchar(128) NOT NULL,
`relation` varchar(50),
`created_at` timestamp NOT NULL DEFAULT (now()),
CONSTRAINT `parent_student_relations_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `password_security` (
`id` varchar(128) NOT NULL,
`user_id` varchar(128) NOT NULL,
`failed_login_attempts` int NOT NULL DEFAULT 0,
`locked_until` timestamp,
`password_changed_at` timestamp NOT NULL DEFAULT (now()),
`must_change_password` boolean NOT NULL DEFAULT false,
`last_password_change` timestamp,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `password_security_id` PRIMARY KEY(`id`),
CONSTRAINT `password_security_user_id_unique` UNIQUE(`user_id`)
);
--> statement-breakpoint
CREATE TABLE `questions` (
`id` varchar(128) NOT NULL,
`content` json NOT NULL,
`type` enum('single_choice','multiple_choice','text','judgment','composite') NOT NULL,
`difficulty` int DEFAULT 1,
`parent_id` varchar(128),
`author_id` varchar(128) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `questions_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `questions_to_knowledge_points` (
`question_id` varchar(128) NOT NULL,
`knowledge_point_id` varchar(128) NOT NULL,
CONSTRAINT `questions_to_knowledge_points_question_id_knowledge_point_id_pk` PRIMARY KEY(`question_id`,`knowledge_point_id`)
);
--> statement-breakpoint
CREATE TABLE `role_permissions` (
`role_id` varchar(128) NOT NULL,
`permission` varchar(100) NOT NULL,
CONSTRAINT `role_permissions_role_id_permission_pk` PRIMARY KEY(`role_id`,`permission`)
);
--> statement-breakpoint
CREATE TABLE `roles` (
`id` varchar(128) NOT NULL,
`name` varchar(50) NOT NULL,
`description` varchar(255),
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `roles_id` PRIMARY KEY(`id`),
CONSTRAINT `roles_name_unique` UNIQUE(`name`)
);
--> statement-breakpoint
CREATE TABLE `schedule_changes` (
`id` varchar(128) NOT NULL,
`original_schedule_id` varchar(128),
`class_id` varchar(128) NOT NULL,
`original_teacher_id` varchar(128),
`substitute_teacher_id` varchar(128),
`original_date` date,
`new_date` date,
`new_start_time` varchar(10),
`new_end_time` varchar(10),
`reason` text,
`status` enum('pending','approved','rejected','completed') NOT NULL DEFAULT 'pending',
`requested_by` varchar(128) NOT NULL,
`approved_by` varchar(128),
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `schedule_changes_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `scheduling_rules` (
`id` varchar(128) NOT NULL,
`class_id` varchar(128),
`max_daily_hours` int DEFAULT 8,
`max_continuous_hours` int DEFAULT 2,
`lunch_break_start` varchar(10) DEFAULT '12:00',
`lunch_break_end` varchar(10) DEFAULT '13:00',
`morning_start` varchar(10) DEFAULT '08:00',
`afternoon_end` varchar(10) DEFAULT '17:00',
`avoid_back_to_back` boolean DEFAULT false,
`balanced_subjects` boolean DEFAULT true,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `scheduling_rules_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `schools` (
`id` varchar(128) NOT NULL,
`name` varchar(255) NOT NULL,
`code` varchar(50),
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `schools_id` PRIMARY KEY(`id`),
CONSTRAINT `schools_name_unique` UNIQUE(`name`),
CONSTRAINT `schools_code_unique` UNIQUE(`code`)
);
--> statement-breakpoint
CREATE TABLE `sessions` (
`sessionToken` varchar(255) NOT NULL,
`userId` varchar(128) NOT NULL,
`expires` timestamp NOT NULL,
CONSTRAINT `sessions_sessionToken` PRIMARY KEY(`sessionToken`)
);
--> statement-breakpoint
CREATE TABLE `subjects` (
`id` varchar(128) NOT NULL,
`name` varchar(100) NOT NULL,
`code` varchar(50),
`order` int DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `subjects_id` PRIMARY KEY(`id`),
CONSTRAINT `subjects_name_unique` UNIQUE(`name`),
CONSTRAINT `subjects_code_unique` UNIQUE(`code`)
);
--> statement-breakpoint
CREATE TABLE `submission_answers` (
`id` varchar(128) NOT NULL,
`submission_id` varchar(128) NOT NULL,
`question_id` varchar(128) NOT NULL,
`answer_content` json,
`score` int,
`feedback` text,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `submission_answers_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `textbooks` (
`id` varchar(128) NOT NULL,
`title` varchar(255) NOT NULL,
`subject` varchar(100) NOT NULL,
`grade` varchar(50),
`publisher` varchar(100),
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `textbooks_id` PRIMARY KEY(`id`)
);
--> statement-breakpoint
CREATE TABLE `users` (
`id` varchar(128) NOT NULL,
`name` varchar(255),
`email` varchar(255) NOT NULL,
`emailVerified` timestamp,
`image` varchar(255),
`password` varchar(255),
`phone` varchar(30),
`address` varchar(255),
`gender` varchar(20),
`age` int,
`grade_id` varchar(128),
`department_id` varchar(128),
`onboarded_at` timestamp,
`birth_date` date,
`guardian_name` varchar(255),
`guardian_phone` varchar(20),
`guardian_relation` varchar(50),
`consent_accepted_at` datetime,
`created_at` timestamp NOT NULL DEFAULT (now()),
`updated_at` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `users_id` PRIMARY KEY(`id`),
CONSTRAINT `users_email_unique` UNIQUE(`email`)
);
--> statement-breakpoint
CREATE TABLE `users_to_roles` (
`user_id` varchar(128) NOT NULL,
`role_id` varchar(128) NOT NULL,
CONSTRAINT `users_to_roles_user_id_role_id_pk` PRIMARY KEY(`user_id`,`role_id`)
);
--> statement-breakpoint
CREATE TABLE `verificationTokens` (
`identifier` varchar(255) NOT NULL,
`token` varchar(255) NOT NULL,
`expires` timestamp NOT NULL,
CONSTRAINT `verificationTokens_identifier_token_pk` PRIMARY KEY(`identifier`,`token`)
);
--> statement-breakpoint
ALTER TABLE `accounts` ADD CONSTRAINT `accounts_userId_users_id_fk` FOREIGN KEY (`userId`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `announcements` ADD CONSTRAINT `announcements_author_id_users_id_fk` FOREIGN KEY (`author_id`) REFERENCES `users`(`id`) ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `attendance_records` ADD CONSTRAINT `attendance_records_student_id_users_id_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `attendance_records` ADD CONSTRAINT `attendance_records_class_id_classes_id_fk` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `attendance_records` ADD CONSTRAINT `attendance_records_recorded_by_users_id_fk` FOREIGN KEY (`recorded_by`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `attendance_records` ADD CONSTRAINT `ar_c_fk` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `attendance_records` ADD CONSTRAINT `ar_s_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `attendance_records` ADD CONSTRAINT `ar_rb_fk` FOREIGN KEY (`recorded_by`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `attendance_rules` ADD CONSTRAINT `attendance_rules_class_id_classes_id_fk` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `attendance_rules` ADD CONSTRAINT `atr_c_fk` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `chapters` ADD CONSTRAINT `chapters_textbook_id_textbooks_id_fk` FOREIGN KEY (`textbook_id`) REFERENCES `textbooks`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `class_enrollments` ADD CONSTRAINT `ce_c_fk` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `class_enrollments` ADD CONSTRAINT `ce_s_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `class_schedule` ADD CONSTRAINT `cs_c_fk` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `class_subject_teachers` ADD CONSTRAINT `class_subject_teachers_teacher_id_users_id_fk` FOREIGN KEY (`teacher_id`) REFERENCES `users`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `class_subject_teachers` ADD CONSTRAINT `cst_c_fk` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `class_subject_teachers` ADD CONSTRAINT `cst_s_fk` FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `classes` ADD CONSTRAINT `classes_teacher_id_users_id_fk` FOREIGN KEY (`teacher_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `classes` ADD CONSTRAINT `c_s_fk` FOREIGN KEY (`school_id`) REFERENCES `schools`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `classes` ADD CONSTRAINT `c_g_fk` FOREIGN KEY (`grade_id`) REFERENCES `grades`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `course_plan_items` ADD CONSTRAINT `course_plan_items_plan_id_course_plans_id_fk` FOREIGN KEY (`plan_id`) REFERENCES `course_plans`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `course_plan_items` ADD CONSTRAINT `cpi_p_fk` FOREIGN KEY (`plan_id`) REFERENCES `course_plans`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `course_plans` ADD CONSTRAINT `course_plans_class_id_classes_id_fk` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `course_plans` ADD CONSTRAINT `course_plans_subject_id_subjects_id_fk` FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `course_plans` ADD CONSTRAINT `course_plans_teacher_id_users_id_fk` FOREIGN KEY (`teacher_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `course_plans` ADD CONSTRAINT `course_plans_created_by_users_id_fk` FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `course_plans` ADD CONSTRAINT `cp_c_fk` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `course_plans` ADD CONSTRAINT `cp_s_fk` FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `course_plans` ADD CONSTRAINT `cp_t_fk` FOREIGN KEY (`teacher_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `course_plans` ADD CONSTRAINT `cp_cb_fk` FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `exam_questions` ADD CONSTRAINT `exam_questions_exam_id_exams_id_fk` FOREIGN KEY (`exam_id`) REFERENCES `exams`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `exam_questions` ADD CONSTRAINT `exam_questions_question_id_questions_id_fk` FOREIGN KEY (`question_id`) REFERENCES `questions`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `exam_submissions` ADD CONSTRAINT `exam_submissions_exam_id_exams_id_fk` FOREIGN KEY (`exam_id`) REFERENCES `exams`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `exam_submissions` ADD CONSTRAINT `exam_submissions_student_id_users_id_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `exams` ADD CONSTRAINT `exams_creator_id_users_id_fk` FOREIGN KEY (`creator_id`) REFERENCES `users`(`id`) ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `exams` ADD CONSTRAINT `exams_subject_id_subjects_id_fk` FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`id`) ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `exams` ADD CONSTRAINT `exams_grade_id_grades_id_fk` FOREIGN KEY (`grade_id`) REFERENCES `grades`(`id`) ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `file_attachments` ADD CONSTRAINT `file_attachments_uploader_id_users_id_fk` FOREIGN KEY (`uploader_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `grade_records` ADD CONSTRAINT `grade_records_student_id_users_id_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `grade_records` ADD CONSTRAINT `grade_records_class_id_classes_id_fk` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `grade_records` ADD CONSTRAINT `grade_records_subject_id_subjects_id_fk` FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `grade_records` ADD CONSTRAINT `grade_records_recorded_by_users_id_fk` FOREIGN KEY (`recorded_by`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `grade_records` ADD CONSTRAINT `gr_c_fk` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `grade_records` ADD CONSTRAINT `gr_s_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `grade_records` ADD CONSTRAINT `gr_sub_fk` FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `grade_records` ADD CONSTRAINT `gr_rb_fk` FOREIGN KEY (`recorded_by`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `grades` ADD CONSTRAINT `g_s_fk` FOREIGN KEY (`school_id`) REFERENCES `schools`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `grades` ADD CONSTRAINT `g_gh_fk` FOREIGN KEY (`grade_head_id`) REFERENCES `users`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `grades` ADD CONSTRAINT `g_th_fk` FOREIGN KEY (`teaching_head_id`) REFERENCES `users`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `homework_answers` ADD CONSTRAINT `hw_ans_sub_fk` FOREIGN KEY (`submission_id`) REFERENCES `homework_submissions`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `homework_answers` ADD CONSTRAINT `hw_ans_q_fk` FOREIGN KEY (`question_id`) REFERENCES `questions`(`id`) ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `homework_assignment_questions` ADD CONSTRAINT `hw_aq_a_fk` FOREIGN KEY (`assignment_id`) REFERENCES `homework_assignments`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `homework_assignment_questions` ADD CONSTRAINT `hw_aq_q_fk` FOREIGN KEY (`question_id`) REFERENCES `questions`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `homework_assignment_targets` ADD CONSTRAINT `hw_at_a_fk` FOREIGN KEY (`assignment_id`) REFERENCES `homework_assignments`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `homework_assignment_targets` ADD CONSTRAINT `hw_at_s_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `homework_assignments` ADD CONSTRAINT `hw_asg_exam_fk` FOREIGN KEY (`source_exam_id`) REFERENCES `exams`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `homework_assignments` ADD CONSTRAINT `hw_asg_creator_fk` FOREIGN KEY (`creator_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `homework_submissions` ADD CONSTRAINT `hw_sub_a_fk` FOREIGN KEY (`assignment_id`) REFERENCES `homework_assignments`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `homework_submissions` ADD CONSTRAINT `hw_sub_student_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `message_notifications` ADD CONSTRAINT `message_notifications_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `messages` ADD CONSTRAINT `messages_sender_id_users_id_fk` FOREIGN KEY (`sender_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `messages` ADD CONSTRAINT `messages_receiver_id_users_id_fk` FOREIGN KEY (`receiver_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `notification_preferences` ADD CONSTRAINT `notification_preferences_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `notification_preferences` ADD CONSTRAINT `np_u_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `parent_student_relations` ADD CONSTRAINT `parent_student_relations_parent_id_users_id_fk` FOREIGN KEY (`parent_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `parent_student_relations` ADD CONSTRAINT `parent_student_relations_student_id_users_id_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `parent_student_relations` ADD CONSTRAINT `psr_p_fk` FOREIGN KEY (`parent_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `parent_student_relations` ADD CONSTRAINT `psr_s_fk` FOREIGN KEY (`student_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `password_security` ADD CONSTRAINT `password_security_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `password_security` ADD CONSTRAINT `ps_u_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `questions` ADD CONSTRAINT `questions_author_id_users_id_fk` FOREIGN KEY (`author_id`) REFERENCES `users`(`id`) ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `questions_to_knowledge_points` ADD CONSTRAINT `q_kp_qid_fk` FOREIGN KEY (`question_id`) REFERENCES `questions`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `questions_to_knowledge_points` ADD CONSTRAINT `q_kp_kpid_fk` FOREIGN KEY (`knowledge_point_id`) REFERENCES `knowledge_points`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `role_permissions` ADD CONSTRAINT `role_permissions_role_id_roles_id_fk` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `sessions` ADD CONSTRAINT `sessions_userId_users_id_fk` FOREIGN KEY (`userId`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `submission_answers` ADD CONSTRAINT `submission_answers_submission_id_exam_submissions_id_fk` FOREIGN KEY (`submission_id`) REFERENCES `exam_submissions`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `submission_answers` ADD CONSTRAINT `submission_answers_question_id_questions_id_fk` FOREIGN KEY (`question_id`) REFERENCES `questions`(`id`) ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `users_to_roles` ADD CONSTRAINT `users_to_roles_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE `users_to_roles` ADD CONSTRAINT `users_to_roles_role_id_roles_id_fk` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX `academic_years_name_idx` ON `academic_years` (`name`);--> statement-breakpoint
CREATE INDEX `academic_years_active_idx` ON `academic_years` (`is_active`);--> statement-breakpoint
CREATE INDEX `account_userId_idx` ON `accounts` (`userId`);--> statement-breakpoint
CREATE INDEX `ai_provider_idx` ON `ai_providers` (`provider`);--> statement-breakpoint
CREATE INDEX `ai_provider_default_idx` ON `ai_providers` (`is_default`);--> statement-breakpoint
CREATE INDEX `announcements_author_idx` ON `announcements` (`author_id`);--> statement-breakpoint
CREATE INDEX `announcements_status_idx` ON `announcements` (`status`);--> statement-breakpoint
CREATE INDEX `announcements_type_idx` ON `announcements` (`type`);--> statement-breakpoint
CREATE INDEX `announcements_target_grade_idx` ON `announcements` (`target_grade_id`);--> statement-breakpoint
CREATE INDEX `announcements_target_class_idx` ON `announcements` (`target_class_id`);--> statement-breakpoint
CREATE INDEX `attendance_records_student_idx` ON `attendance_records` (`student_id`);--> statement-breakpoint
CREATE INDEX `attendance_records_class_idx` ON `attendance_records` (`class_id`);--> statement-breakpoint
CREATE INDEX `attendance_records_date_idx` ON `attendance_records` (`date`);--> statement-breakpoint
CREATE INDEX `attendance_records_class_date_idx` ON `attendance_records` (`class_id`,`date`);--> statement-breakpoint
CREATE INDEX `attendance_records_student_date_idx` ON `attendance_records` (`student_id`,`date`);--> statement-breakpoint
CREATE INDEX `attendance_records_schedule_idx` ON `attendance_records` (`schedule_id`);--> statement-breakpoint
CREATE INDEX `attendance_records_recorded_by_idx` ON `attendance_records` (`recorded_by`);--> statement-breakpoint
CREATE INDEX `attendance_rules_class_idx` ON `attendance_rules` (`class_id`);--> statement-breakpoint
CREATE INDEX `audit_logs_user_id_idx` ON `audit_logs` (`user_id`);--> statement-breakpoint
CREATE INDEX `audit_logs_module_idx` ON `audit_logs` (`module`);--> statement-breakpoint
CREATE INDEX `audit_logs_action_idx` ON `audit_logs` (`action`);--> statement-breakpoint
CREATE INDEX `audit_logs_status_idx` ON `audit_logs` (`status`);--> statement-breakpoint
CREATE INDEX `audit_logs_created_at_idx` ON `audit_logs` (`created_at`);--> statement-breakpoint
CREATE INDEX `textbook_idx` ON `chapters` (`textbook_id`);--> statement-breakpoint
CREATE INDEX `parent_id_idx` ON `chapters` (`parent_id`);--> statement-breakpoint
CREATE INDEX `class_enrollments_class_idx` ON `class_enrollments` (`class_id`);--> statement-breakpoint
CREATE INDEX `class_enrollments_student_idx` ON `class_enrollments` (`student_id`);--> statement-breakpoint
CREATE INDEX `class_schedule_class_idx` ON `class_schedule` (`class_id`);--> statement-breakpoint
CREATE INDEX `class_schedule_class_day_idx` ON `class_schedule` (`class_id`,`weekday`);--> statement-breakpoint
CREATE INDEX `class_subject_teachers_class_idx` ON `class_subject_teachers` (`class_id`);--> statement-breakpoint
CREATE INDEX `class_subject_teachers_teacher_idx` ON `class_subject_teachers` (`teacher_id`);--> statement-breakpoint
CREATE INDEX `class_subject_teachers_subject_id_idx` ON `class_subject_teachers` (`subject_id`);--> statement-breakpoint
CREATE INDEX `classes_teacher_idx` ON `classes` (`teacher_id`);--> statement-breakpoint
CREATE INDEX `classes_grade_idx` ON `classes` (`grade`);--> statement-breakpoint
CREATE INDEX `classes_school_idx` ON `classes` (`school_id`);--> statement-breakpoint
CREATE INDEX `classes_grade_id_idx` ON `classes` (`grade_id`);--> statement-breakpoint
CREATE INDEX `classrooms_name_idx` ON `classrooms` (`name`);--> statement-breakpoint
CREATE INDEX `course_plan_items_plan_idx` ON `course_plan_items` (`plan_id`);--> statement-breakpoint
CREATE INDEX `course_plan_items_plan_week_idx` ON `course_plan_items` (`plan_id`,`week`);--> statement-breakpoint
CREATE INDEX `course_plans_class_idx` ON `course_plans` (`class_id`);--> statement-breakpoint
CREATE INDEX `course_plans_teacher_idx` ON `course_plans` (`teacher_id`);--> statement-breakpoint
CREATE INDEX `course_plans_subject_idx` ON `course_plans` (`subject_id`);--> statement-breakpoint
CREATE INDEX `course_plans_status_idx` ON `course_plans` (`status`);--> statement-breakpoint
CREATE INDEX `course_plans_class_subject_idx` ON `course_plans` (`class_id`,`subject_id`);--> statement-breakpoint
CREATE INDEX `data_change_logs_table_name_idx` ON `data_change_logs` (`table_name`);--> statement-breakpoint
CREATE INDEX `data_change_logs_record_id_idx` ON `data_change_logs` (`record_id`);--> statement-breakpoint
CREATE INDEX `data_change_logs_action_idx` ON `data_change_logs` (`action`);--> statement-breakpoint
CREATE INDEX `data_change_logs_changed_by_idx` ON `data_change_logs` (`changed_by`);--> statement-breakpoint
CREATE INDEX `data_change_logs_created_at_idx` ON `data_change_logs` (`created_at`);--> statement-breakpoint
CREATE INDEX `departments_name_idx` ON `departments` (`name`);--> statement-breakpoint
CREATE INDEX `exam_student_idx` ON `exam_submissions` (`exam_id`,`student_id`);--> statement-breakpoint
CREATE INDEX `exams_subject_idx` ON `exams` (`subject_id`);--> statement-breakpoint
CREATE INDEX `exams_grade_idx` ON `exams` (`grade_id`);--> statement-breakpoint
CREATE INDEX `file_attachments_uploader_idx` ON `file_attachments` (`uploader_id`);--> statement-breakpoint
CREATE INDEX `file_attachments_target_idx` ON `file_attachments` (`target_type`,`target_id`);--> statement-breakpoint
CREATE INDEX `file_attachments_created_at_idx` ON `file_attachments` (`created_at`);--> statement-breakpoint
CREATE INDEX `grade_records_student_idx` ON `grade_records` (`student_id`);--> statement-breakpoint
CREATE INDEX `grade_records_class_idx` ON `grade_records` (`class_id`);--> statement-breakpoint
CREATE INDEX `grade_records_subject_idx` ON `grade_records` (`subject_id`);--> statement-breakpoint
CREATE INDEX `grade_records_exam_idx` ON `grade_records` (`exam_id`);--> statement-breakpoint
CREATE INDEX `grade_records_class_subject_idx` ON `grade_records` (`class_id`,`subject_id`);--> statement-breakpoint
CREATE INDEX `grade_records_recorded_by_idx` ON `grade_records` (`recorded_by`);--> statement-breakpoint
CREATE INDEX `grades_school_idx` ON `grades` (`school_id`);--> statement-breakpoint
CREATE INDEX `grades_school_name_uniq` ON `grades` (`school_id`,`name`);--> statement-breakpoint
CREATE INDEX `grades_grade_head_idx` ON `grades` (`grade_head_id`);--> statement-breakpoint
CREATE INDEX `grades_teaching_head_idx` ON `grades` (`teaching_head_id`);--> statement-breakpoint
CREATE INDEX `hw_answer_submission_idx` ON `homework_answers` (`submission_id`);--> statement-breakpoint
CREATE INDEX `hw_answer_submission_question_idx` ON `homework_answers` (`submission_id`,`question_id`);--> statement-breakpoint
CREATE INDEX `hw_assignment_questions_assignment_idx` ON `homework_assignment_questions` (`assignment_id`);--> statement-breakpoint
CREATE INDEX `hw_assignment_targets_assignment_idx` ON `homework_assignment_targets` (`assignment_id`);--> statement-breakpoint
CREATE INDEX `hw_assignment_targets_student_idx` ON `homework_assignment_targets` (`student_id`);--> statement-breakpoint
CREATE INDEX `hw_assignment_creator_idx` ON `homework_assignments` (`creator_id`);--> statement-breakpoint
CREATE INDEX `hw_assignment_source_exam_idx` ON `homework_assignments` (`source_exam_id`);--> statement-breakpoint
CREATE INDEX `hw_assignment_status_idx` ON `homework_assignments` (`status`);--> statement-breakpoint
CREATE INDEX `hw_assignment_student_idx` ON `homework_submissions` (`assignment_id`,`student_id`);--> statement-breakpoint
CREATE INDEX `parent_id_idx` ON `knowledge_points` (`parent_id`);--> statement-breakpoint
CREATE INDEX `kp_chapter_id_idx` ON `knowledge_points` (`chapter_id`);--> statement-breakpoint
CREATE INDEX `login_logs_user_id_idx` ON `login_logs` (`user_id`);--> statement-breakpoint
CREATE INDEX `login_logs_user_email_idx` ON `login_logs` (`user_email`);--> statement-breakpoint
CREATE INDEX `login_logs_action_idx` ON `login_logs` (`action`);--> statement-breakpoint
CREATE INDEX `login_logs_status_idx` ON `login_logs` (`status`);--> statement-breakpoint
CREATE INDEX `login_logs_created_at_idx` ON `login_logs` (`created_at`);--> statement-breakpoint
CREATE INDEX `message_notifications_user_idx` ON `message_notifications` (`user_id`);--> statement-breakpoint
CREATE INDEX `message_notifications_is_read_idx` ON `message_notifications` (`is_read`);--> statement-breakpoint
CREATE INDEX `message_notifications_user_read_idx` ON `message_notifications` (`user_id`,`is_read`);--> statement-breakpoint
CREATE INDEX `message_notifications_created_at_idx` ON `message_notifications` (`created_at`);--> statement-breakpoint
CREATE INDEX `messages_sender_idx` ON `messages` (`sender_id`);--> statement-breakpoint
CREATE INDEX `messages_receiver_idx` ON `messages` (`receiver_id`);--> statement-breakpoint
CREATE INDEX `messages_is_read_idx` ON `messages` (`is_read`);--> statement-breakpoint
CREATE INDEX `messages_parent_idx` ON `messages` (`parent_message_id`);--> statement-breakpoint
CREATE INDEX `messages_receiver_read_idx` ON `messages` (`receiver_id`,`is_read`);--> statement-breakpoint
CREATE INDEX `notification_preferences_user_idx` ON `notification_preferences` (`user_id`);--> statement-breakpoint
CREATE INDEX `parent_student_relations_parent_idx` ON `parent_student_relations` (`parent_id`);--> statement-breakpoint
CREATE INDEX `parent_student_relations_student_idx` ON `parent_student_relations` (`student_id`);--> statement-breakpoint
CREATE INDEX `password_security_user_idx` ON `password_security` (`user_id`);--> statement-breakpoint
CREATE INDEX `parent_id_idx` ON `questions` (`parent_id`);--> statement-breakpoint
CREATE INDEX `author_id_idx` ON `questions` (`author_id`);--> statement-breakpoint
CREATE INDEX `kp_idx` ON `questions_to_knowledge_points` (`knowledge_point_id`);--> statement-breakpoint
CREATE INDEX `role_permissions_role_idx` ON `role_permissions` (`role_id`);--> statement-breakpoint
CREATE INDEX `schedule_changes_class_idx` ON `schedule_changes` (`class_id`);--> statement-breakpoint
CREATE INDEX `schedule_changes_status_idx` ON `schedule_changes` (`status`);--> statement-breakpoint
CREATE INDEX `schedule_changes_requested_by_idx` ON `schedule_changes` (`requested_by`);--> statement-breakpoint
CREATE INDEX `schedule_changes_original_schedule_idx` ON `schedule_changes` (`original_schedule_id`);--> statement-breakpoint
CREATE INDEX `scheduling_rules_class_idx` ON `scheduling_rules` (`class_id`);--> statement-breakpoint
CREATE INDEX `schools_name_idx` ON `schools` (`name`);--> statement-breakpoint
CREATE INDEX `schools_code_idx` ON `schools` (`code`);--> statement-breakpoint
CREATE INDEX `session_userId_idx` ON `sessions` (`userId`);--> statement-breakpoint
CREATE INDEX `subjects_name_idx` ON `subjects` (`name`);--> statement-breakpoint
CREATE INDEX `submission_idx` ON `submission_answers` (`submission_id`);--> statement-breakpoint
CREATE INDEX `email_idx` ON `users` (`email`);--> statement-breakpoint
CREATE INDEX `users_grade_id_idx` ON `users` (`grade_id`);--> statement-breakpoint
CREATE INDEX `users_department_id_idx` ON `users` (`department_id`);--> statement-breakpoint
CREATE INDEX `user_id_idx` ON `users_to_roles` (`user_id`);

View File

@@ -1 +0,0 @@
SELECT 1;--> statement-breakpoint

View File

@@ -1 +0,0 @@
SELECT 1;--> statement-breakpoint

View File

@@ -1 +0,0 @@
SELECT 1;--> statement-breakpoint

View File

@@ -1 +0,0 @@
SELECT 1;--> statement-breakpoint

View File

@@ -1 +0,0 @@
SELECT 1;--> statement-breakpoint

View File

@@ -1 +0,0 @@
SELECT 1;--> statement-breakpoint

View File

@@ -1 +0,0 @@
SELECT 1;--> statement-breakpoint

View File

@@ -1 +0,0 @@
SELECT 1;--> statement-breakpoint

View File

@@ -1,88 +0,0 @@
SET @has_exams_subject := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'exams'
AND COLUMN_NAME = 'subject_id'
);--> statement-breakpoint
SET @sql := IF(@has_exams_subject = 0, 'ALTER TABLE `exams` ADD `subject_id` varchar(128);', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @has_exams_grade := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'exams'
AND COLUMN_NAME = 'grade_id'
);--> statement-breakpoint
SET @sql := IF(@has_exams_grade = 0, 'ALTER TABLE `exams` ADD `grade_id` varchar(128);', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @has_kp_anchor := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'knowledge_points'
AND COLUMN_NAME = 'anchor_text'
);--> statement-breakpoint
SET @sql := IF(@has_kp_anchor = 0, 'ALTER TABLE `knowledge_points` ADD `anchor_text` varchar(255);', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @has_exams_subject_fk := (
SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'exams'
AND CONSTRAINT_NAME = 'exams_subject_id_subjects_id_fk'
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
);--> statement-breakpoint
SET @sql := IF(@has_exams_subject_fk = 0, 'ALTER TABLE `exams` ADD CONSTRAINT `exams_subject_id_subjects_id_fk` FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`id`) ON DELETE no action ON UPDATE no action;', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @has_exams_grade_fk := (
SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'exams'
AND CONSTRAINT_NAME = 'exams_grade_id_grades_id_fk'
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
);--> statement-breakpoint
SET @sql := IF(@has_exams_grade_fk = 0, 'ALTER TABLE `exams` ADD CONSTRAINT `exams_grade_id_grades_id_fk` FOREIGN KEY (`grade_id`) REFERENCES `grades`(`id`) ON DELETE no action ON UPDATE no action;', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @has_exams_subject_idx := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'exams'
AND INDEX_NAME = 'exams_subject_idx'
);--> statement-breakpoint
SET @sql := IF(@has_exams_subject_idx = 0, 'CREATE INDEX `exams_subject_idx` ON `exams` (`subject_id`);', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @has_exams_grade_idx := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'exams'
AND INDEX_NAME = 'exams_grade_idx'
);--> statement-breakpoint
SET @sql := IF(@has_exams_grade_idx = 0, 'CREATE INDEX `exams_grade_idx` ON `exams` (`grade_id`);', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
INSERT IGNORE INTO `roles` (`id`, `name`, `created_at`, `updated_at`)
SELECT UUID(), LOWER(TRIM(`role`)), NOW(), NOW()
FROM `users`
WHERE `role` IS NOT NULL AND TRIM(`role`) <> '';--> statement-breakpoint
INSERT IGNORE INTO `users_to_roles` (`user_id`, `role_id`)
SELECT `users`.`id`, `roles`.`id`
FROM `users`
INNER JOIN `roles` ON `roles`.`name` = LOWER(TRIM(`users`.`role`))
WHERE `users`.`role` IS NOT NULL AND TRIM(`users`.`role`) <> '';--> statement-breakpoint
ALTER TABLE `users` DROP COLUMN `role`;

View File

@@ -1,110 +0,0 @@
SET @has_subject_id := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'class_subject_teachers'
AND COLUMN_NAME = 'subject_id'
);--> statement-breakpoint
SET @sql := IF(@has_subject_id = 0, 'ALTER TABLE `class_subject_teachers` ADD COLUMN `subject_id` VARCHAR(128) NULL;', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
INSERT INTO `subjects` (`id`, `name`, `code`)
SELECT UUID(), '语文', 'CHINESE' FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `subjects` WHERE `name` = '语文' OR `code` = 'CHINESE')
UNION ALL
SELECT UUID(), '数学', 'MATH' FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `subjects` WHERE `name` = '数学' OR `code` = 'MATH')
UNION ALL
SELECT UUID(), '英语', 'ENG' FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `subjects` WHERE `name` = '英语' OR `code` = 'ENG')
UNION ALL
SELECT UUID(), '美术', 'ART' FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `subjects` WHERE `name` = '美术' OR `code` = 'ART')
UNION ALL
SELECT UUID(), '体育', 'PE' FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `subjects` WHERE `name` = '体育' OR `code` = 'PE')
UNION ALL
SELECT UUID(), '科学', 'SCI' FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `subjects` WHERE `name` = '科学' OR `code` = 'SCI')
UNION ALL
SELECT UUID(), '社会', 'SOC' FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `subjects` WHERE `name` = '社会' OR `code` = 'SOC')
UNION ALL
SELECT UUID(), '音乐', 'MUSIC' FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `subjects` WHERE `name` = '音乐' OR `code` = 'MUSIC');--> statement-breakpoint
SET @has_subject_col := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'class_subject_teachers'
AND COLUMN_NAME = 'subject'
);--> statement-breakpoint
SET @sql := IF(@has_subject_col = 1, '
UPDATE `class_subject_teachers` cst
JOIN `subjects` s ON (
s.`name` = cst.`subject`
OR s.`code` = CASE cst.`subject`
WHEN ''语文'' THEN ''CHINESE''
WHEN ''数学'' THEN ''MATH''
WHEN ''英语'' THEN ''ENG''
WHEN ''美术'' THEN ''ART''
WHEN ''体育'' THEN ''PE''
WHEN ''科学'' THEN ''SCI''
WHEN ''社会'' THEN ''SOC''
WHEN ''音乐'' THEN ''MUSIC''
ELSE NULL
END
)
SET cst.`subject_id` = s.`id`
WHERE cst.`subject_id` IS NULL;
', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @subject_id_nulls := (
SELECT COUNT(*) FROM `class_subject_teachers`
WHERE `subject_id` IS NULL
);--> statement-breakpoint
SET @sql := IF(@subject_id_nulls = 0, 'ALTER TABLE `class_subject_teachers` MODIFY COLUMN `subject_id` VARCHAR(128) NOT NULL;', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @sql := IF(@subject_id_nulls = 0, 'ALTER TABLE `class_subject_teachers` DROP PRIMARY KEY;', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @sql := IF(@subject_id_nulls = 0, 'ALTER TABLE `class_subject_teachers` ADD PRIMARY KEY (`class_id`, `subject_id`);', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @sql := IF(@subject_id_nulls = 0 AND @has_subject_col = 1, 'ALTER TABLE `class_subject_teachers` DROP COLUMN `subject`;', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @has_subject_id_idx := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'class_subject_teachers'
AND INDEX_NAME = 'class_subject_teachers_subject_id_idx'
);--> statement-breakpoint
SET @sql := IF(@subject_id_nulls = 0 AND @has_subject_id_idx = 0, 'CREATE INDEX `class_subject_teachers_subject_id_idx` ON `class_subject_teachers` (`subject_id`);', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @has_subject_fk := (
SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'class_subject_teachers'
AND CONSTRAINT_NAME = 'cst_s_fk'
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
);--> statement-breakpoint
SET @sql := IF(@subject_id_nulls = 0 AND @has_subject_fk = 0, 'ALTER TABLE `class_subject_teachers` ADD CONSTRAINT `cst_s_fk` FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`id`) ON DELETE CASCADE;', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;

View File

@@ -1,46 +0,0 @@
SET @has_ai_providers := (
SELECT COUNT(*) FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'ai_providers'
);--> statement-breakpoint
SET @sql := IF(@has_ai_providers = 0, '
CREATE TABLE `ai_providers` (
`id` varchar(128) NOT NULL,
`provider` enum(''zhipu'',''openai'',''gemini'',''custom'') NOT NULL,
`base_url` varchar(512),
`model` varchar(128) NOT NULL,
`api_key_encrypted` text NOT NULL,
`api_key_last4` varchar(4),
`is_default` boolean NOT NULL DEFAULT false,
`created_by` varchar(128),
`updated_by` varchar(128),
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);
', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @has_ai_provider_idx := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'ai_providers'
AND INDEX_NAME = 'ai_provider_idx'
);--> statement-breakpoint
SET @sql := IF(@has_ai_provider_idx = 0, 'CREATE INDEX `ai_provider_idx` ON `ai_providers` (`provider`);', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint
SET @has_ai_provider_default_idx := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'ai_providers'
AND INDEX_NAME = 'ai_provider_default_idx'
);--> statement-breakpoint
SET @sql := IF(@has_ai_provider_default_idx = 0, 'CREATE INDEX `ai_provider_default_idx` ON `ai_providers` (`is_default`);', 'SELECT 1');--> statement-breakpoint
PREPARE stmt FROM @sql;--> statement-breakpoint
EXECUTE stmt;--> statement-breakpoint
DEALLOCATE PREPARE stmt;--> statement-breakpoint

File diff suppressed because it is too large Load Diff

View File

@@ -5,79 +5,9 @@
{ {
"idx": 0, "idx": 0,
"version": "5", "version": "5",
"when": 1766460456274, "when": 1781676504560,
"tag": "0000_aberrant_cobalt_man", "tag": "0000_perfect_pestilence",
"breakpoints": true
},
{
"idx": 1,
"version": "5",
"when": 1767004087964,
"tag": "0001_flawless_texas_twister",
"breakpoints": true
},
{
"idx": 2,
"version": "5",
"when": 1767145757594,
"tag": "0002_equal_wolfpack",
"breakpoints": true
},
{
"idx": 3,
"version": "5",
"when": 1767166769676,
"tag": "0003_petite_newton_destine",
"breakpoints": true
},
{
"idx": 4,
"version": "5",
"when": 1767169003334,
"tag": "0004_add_chapter_content_and_kp_chapter",
"breakpoints": true
},
{
"idx": 5,
"version": "5",
"when": 1767751916045,
"tag": "0005_add_class_school_subject_teachers",
"breakpoints": true
},
{
"idx": 6,
"version": "5",
"when": 1767760693171,
"tag": "0006_faithful_king_bedlam",
"breakpoints": true
},
{
"idx": 7,
"version": "5",
"when": 1768205524480,
"tag": "0007_talented_bromley",
"breakpoints": true
},
{
"idx": 8,
"version": "5",
"when": 1768470966367,
"tag": "0008_thin_madrox",
"breakpoints": true
},
{
"idx": 9,
"version": "5",
"when": 1772162908476,
"tag": "0009_smart_mephistopheles",
"breakpoints": true
},
{
"idx": 10,
"version": "5",
"when": 1772439600000,
"tag": "0010_subject_id_switch",
"breakpoints": true "breakpoints": true
} }
] ]
} }

View File

@@ -18,9 +18,12 @@
"test:e2e": "playwright test", "test:e2e": "playwright test",
"test:e2e:smoke": "playwright test tests/e2e/smoke-auth.spec.ts", "test:e2e:smoke": "playwright test tests/e2e/smoke-auth.spec.ts",
"test:e2e:full-routes": "playwright test tests/e2e/full-route-regression.spec.ts", "test:e2e:full-routes": "playwright test tests/e2e/full-route-regression.spec.ts",
"db:create": "npx tsx scripts/create-db.ts",
"db:seed": "npx tsx scripts/seed.ts", "db:seed": "npx tsx scripts/seed.ts",
"db:generate": "drizzle-kit generate", "db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate", "db:migrate": "drizzle-kit migrate",
"db:push": "drizzle-kit push",
"db:setup": "npx tsx scripts/create-db.ts && drizzle-kit migrate && npx tsx scripts/seed.ts",
"audit": "npm audit --audit-level=moderate", "audit": "npm audit --audit-level=moderate",
"audit:report": "npm audit --json > audit-report.json", "audit:report": "npm audit --json > audit-report.json",
"backup": "bash scripts/backup-db.sh", "backup": "bash scripts/backup-db.sh",