diff --git a/reading-platform-backend/prisma/migrations/20260227180846_init/migration.sql b/reading-platform-backend/prisma/migrations/20260227180846_init/migration.sql new file mode 100644 index 0000000..73375fa --- /dev/null +++ b/reading-platform-backend/prisma/migrations/20260227180846_init/migration.sql @@ -0,0 +1,634 @@ +-- CreateTable +CREATE TABLE "tenants" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "name" TEXT NOT NULL, + "login_account" TEXT, + "password_hash" TEXT, + "address" TEXT, + "contact_person" TEXT, + "contact_phone" TEXT, + "logo_url" TEXT, + "package_type" TEXT NOT NULL DEFAULT 'STANDARD', + "teacher_quota" INTEGER NOT NULL DEFAULT 20, + "student_quota" INTEGER NOT NULL DEFAULT 200, + "storage_quota" BIGINT NOT NULL DEFAULT 5368709120, + "start_date" TEXT NOT NULL, + "expire_date" TEXT NOT NULL, + "teacher_count" INTEGER NOT NULL DEFAULT 0, + "student_count" INTEGER NOT NULL DEFAULT 0, + "storage_used" BIGINT NOT NULL DEFAULT 0, + "status" TEXT NOT NULL DEFAULT 'ACTIVE', + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL +); + +-- CreateTable +CREATE TABLE "teachers" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "name" TEXT NOT NULL, + "phone" TEXT NOT NULL, + "email" TEXT, + "login_account" TEXT NOT NULL, + "password_hash" TEXT NOT NULL, + "class_ids" TEXT DEFAULT '[]', + "status" TEXT NOT NULL DEFAULT 'ACTIVE', + "lesson_count" INTEGER NOT NULL DEFAULT 0, + "feedback_count" INTEGER NOT NULL DEFAULT 0, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + "last_login_at" DATETIME, + CONSTRAINT "teachers_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "classes" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "name" TEXT NOT NULL, + "grade" TEXT NOT NULL, + "teacher_id" INTEGER, + "student_count" INTEGER NOT NULL DEFAULT 0, + "lesson_count" INTEGER NOT NULL DEFAULT 0, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + CONSTRAINT "classes_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "classes_teacher_id_fkey" FOREIGN KEY ("teacher_id") REFERENCES "teachers" ("id") ON DELETE SET NULL ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "students" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "class_id" INTEGER NOT NULL, + "name" TEXT NOT NULL, + "gender" TEXT, + "birth_date" DATETIME, + "parent_phone" TEXT, + "parent_name" TEXT, + "reading_count" INTEGER NOT NULL DEFAULT 0, + "lesson_count" INTEGER NOT NULL DEFAULT 0, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + CONSTRAINT "students_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "students_class_id_fkey" FOREIGN KEY ("class_id") REFERENCES "classes" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "courses" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "name" TEXT NOT NULL, + "description" TEXT, + "picture_book_id" INTEGER, + "picture_book_name" TEXT, + "cover_image_path" TEXT, + "ebook_paths" TEXT, + "audio_paths" TEXT, + "video_paths" TEXT, + "other_resources" TEXT, + "ppt_path" TEXT, + "ppt_name" TEXT, + "poster_paths" TEXT, + "tools" TEXT, + "student_materials" TEXT, + "lesson_plan_data" TEXT, + "activities_data" TEXT, + "assessment_data" TEXT, + "grade_tags" TEXT NOT NULL DEFAULT '[]', + "domain_tags" TEXT NOT NULL DEFAULT '[]', + "duration" INTEGER NOT NULL DEFAULT 25, + "status" TEXT NOT NULL DEFAULT 'DRAFT', + "version" TEXT NOT NULL DEFAULT '1.0', + "submitted_at" DATETIME, + "submitted_by" INTEGER, + "reviewed_at" DATETIME, + "reviewed_by" INTEGER, + "review_comment" TEXT, + "review_checklist" TEXT, + "parent_id" INTEGER, + "isLatest" BOOLEAN NOT NULL DEFAULT true, + "usage_count" INTEGER NOT NULL DEFAULT 0, + "teacher_count" INTEGER NOT NULL DEFAULT 0, + "avg_rating" REAL NOT NULL DEFAULT 0, + "created_by" INTEGER, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + "published_at" DATETIME +); + +-- CreateTable +CREATE TABLE "course_versions" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "course_id" INTEGER NOT NULL, + "version" TEXT NOT NULL, + "snapshotData" TEXT NOT NULL, + "changeLog" TEXT, + "published_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "published_by" INTEGER NOT NULL, + CONSTRAINT "course_versions_course_id_fkey" FOREIGN KEY ("course_id") REFERENCES "courses" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "course_resources" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "course_id" INTEGER NOT NULL, + "resource_type" TEXT NOT NULL, + "resource_name" TEXT NOT NULL, + "file_url" TEXT NOT NULL, + "file_size" INTEGER, + "mime_type" TEXT, + "metadata" TEXT, + "sort_order" INTEGER NOT NULL DEFAULT 0, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "course_resources_course_id_fkey" FOREIGN KEY ("course_id") REFERENCES "courses" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "course_scripts" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "course_id" INTEGER NOT NULL, + "step_index" INTEGER NOT NULL, + "step_name" TEXT NOT NULL, + "step_type" TEXT NOT NULL, + "duration" INTEGER NOT NULL, + "objective" TEXT, + "teacher_script" TEXT, + "interaction_points" TEXT, + "resource_ids" TEXT, + "sort_order" INTEGER NOT NULL DEFAULT 0, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + CONSTRAINT "course_scripts_course_id_fkey" FOREIGN KEY ("course_id") REFERENCES "courses" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "course_script_pages" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "script_id" INTEGER NOT NULL, + "page_number" INTEGER NOT NULL, + "questions" TEXT, + "interaction_component" TEXT, + "teacher_notes" TEXT, + "resource_ids" TEXT, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + CONSTRAINT "course_script_pages_script_id_fkey" FOREIGN KEY ("script_id") REFERENCES "course_scripts" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "course_activities" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "course_id" INTEGER NOT NULL, + "name" TEXT NOT NULL, + "domain" TEXT, + "domain_tag_id" INTEGER, + "activity_type" TEXT NOT NULL, + "duration" INTEGER, + "online_materials" TEXT, + "offlineMaterials" TEXT, + "activityGuide" TEXT, + "objectives" TEXT, + "sort_order" INTEGER NOT NULL DEFAULT 0, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "course_activities_course_id_fkey" FOREIGN KEY ("course_id") REFERENCES "courses" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "lessons" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "teacher_id" INTEGER NOT NULL, + "class_id" INTEGER NOT NULL, + "course_id" INTEGER NOT NULL, + "schedule_plan_id" INTEGER, + "planned_datetime" DATETIME, + "start_datetime" DATETIME, + "end_datetime" DATETIME, + "actual_duration" INTEGER, + "status" TEXT NOT NULL DEFAULT 'PLANNED', + "overall_rating" TEXT, + "participation_rating" TEXT, + "completion_note" TEXT, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + CONSTRAINT "lessons_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "lessons_teacher_id_fkey" FOREIGN KEY ("teacher_id") REFERENCES "teachers" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "lessons_class_id_fkey" FOREIGN KEY ("class_id") REFERENCES "classes" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "lessons_course_id_fkey" FOREIGN KEY ("course_id") REFERENCES "courses" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "lessons_schedule_plan_id_fkey" FOREIGN KEY ("schedule_plan_id") REFERENCES "schedule_plans" ("id") ON DELETE SET NULL ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "lesson_feedbacks" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "lesson_id" INTEGER NOT NULL, + "teacher_id" INTEGER NOT NULL, + "design_quality" INTEGER, + "participation" INTEGER, + "goal_achievement" INTEGER, + "step_feedbacks" TEXT, + "pros" TEXT, + "suggestions" TEXT, + "activities_done" TEXT, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + CONSTRAINT "lesson_feedbacks_lesson_id_fkey" FOREIGN KEY ("lesson_id") REFERENCES "lessons" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "lesson_feedbacks_teacher_id_fkey" FOREIGN KEY ("teacher_id") REFERENCES "teachers" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "student_records" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "lesson_id" INTEGER NOT NULL, + "student_id" INTEGER NOT NULL, + "focus" INTEGER, + "participation" INTEGER, + "interest" INTEGER, + "understanding" INTEGER, + "domainAchievements" TEXT, + "notes" TEXT, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + CONSTRAINT "student_records_lesson_id_fkey" FOREIGN KEY ("lesson_id") REFERENCES "lessons" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "student_records_student_id_fkey" FOREIGN KEY ("student_id") REFERENCES "students" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "tags" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "level" INTEGER NOT NULL, + "code" TEXT NOT NULL, + "name" TEXT NOT NULL, + "parent_id" INTEGER, + "description" TEXT, + "metadata" TEXT, + "sort_order" INTEGER NOT NULL DEFAULT 0, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +-- CreateTable +CREATE TABLE "tenant_courses" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "course_id" INTEGER NOT NULL, + "authorized" BOOLEAN NOT NULL DEFAULT true, + "authorized_at" DATETIME, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "tenant_courses_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "tenant_courses_course_id_fkey" FOREIGN KEY ("course_id") REFERENCES "courses" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "growth_records" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "student_id" INTEGER NOT NULL, + "class_id" INTEGER, + "record_type" TEXT NOT NULL, + "title" TEXT NOT NULL, + "content" TEXT, + "images" TEXT, + "record_date" DATETIME NOT NULL, + "created_by" INTEGER NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + CONSTRAINT "growth_records_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "growth_records_student_id_fkey" FOREIGN KEY ("student_id") REFERENCES "students" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "growth_records_class_id_fkey" FOREIGN KEY ("class_id") REFERENCES "classes" ("id") ON DELETE SET NULL ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "tasks" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "title" TEXT NOT NULL, + "description" TEXT, + "task_type" TEXT NOT NULL, + "target_type" TEXT NOT NULL, + "related_course_id" INTEGER, + "created_by" INTEGER NOT NULL, + "start_date" DATETIME NOT NULL, + "end_date" DATETIME NOT NULL, + "status" TEXT NOT NULL DEFAULT 'PUBLISHED', + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + CONSTRAINT "tasks_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "tasks_related_course_id_fkey" FOREIGN KEY ("related_course_id") REFERENCES "courses" ("id") ON DELETE SET NULL ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "task_targets" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "task_id" INTEGER NOT NULL, + "class_id" INTEGER, + "student_id" INTEGER, + CONSTRAINT "task_targets_task_id_fkey" FOREIGN KEY ("task_id") REFERENCES "tasks" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "task_completions" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "task_id" INTEGER NOT NULL, + "student_id" INTEGER NOT NULL, + "status" TEXT NOT NULL DEFAULT 'PENDING', + "completed_at" DATETIME, + "feedback" TEXT, + "parent_feedback" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "task_completions_task_id_fkey" FOREIGN KEY ("task_id") REFERENCES "tasks" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "task_completions_student_id_fkey" FOREIGN KEY ("student_id") REFERENCES "students" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "task_templates" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "task_type" TEXT NOT NULL, + "related_course_id" INTEGER, + "default_duration" INTEGER NOT NULL DEFAULT 7, + "is_default" BOOLEAN NOT NULL DEFAULT false, + "status" TEXT NOT NULL DEFAULT 'ACTIVE', + "created_by" INTEGER NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + CONSTRAINT "task_templates_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "task_templates_related_course_id_fkey" FOREIGN KEY ("related_course_id") REFERENCES "courses" ("id") ON DELETE SET NULL ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "resource_libraries" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "name" TEXT NOT NULL, + "library_type" TEXT NOT NULL, + "description" TEXT, + "cover_image" TEXT, + "tenant_id" INTEGER, + "created_by" INTEGER NOT NULL, + "status" TEXT NOT NULL DEFAULT 'PUBLISHED', + "sort_order" INTEGER NOT NULL DEFAULT 0, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); + +-- CreateTable +CREATE TABLE "resource_items" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "library_id" INTEGER NOT NULL, + "title" TEXT NOT NULL, + "description" TEXT, + "file_type" TEXT NOT NULL, + "file_path" TEXT NOT NULL, + "file_size" INTEGER, + "tags" TEXT, + "sort_order" INTEGER NOT NULL DEFAULT 0, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "resource_items_library_id_fkey" FOREIGN KEY ("library_id") REFERENCES "resource_libraries" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "system_settings" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "school_name" TEXT, + "school_logo" TEXT, + "address" TEXT, + "notify_on_lesson" BOOLEAN NOT NULL DEFAULT true, + "notify_on_task" BOOLEAN NOT NULL DEFAULT true, + "notify_on_growth" BOOLEAN NOT NULL DEFAULT false, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + CONSTRAINT "system_settings_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "parents" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "name" TEXT NOT NULL, + "phone" TEXT NOT NULL, + "email" TEXT, + "login_account" TEXT NOT NULL, + "password_hash" TEXT NOT NULL, + "status" TEXT NOT NULL DEFAULT 'ACTIVE', + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + "last_login_at" DATETIME, + CONSTRAINT "parents_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "parent_students" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "parent_id" INTEGER NOT NULL, + "student_id" INTEGER NOT NULL, + "relationship" TEXT NOT NULL, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "parent_students_parent_id_fkey" FOREIGN KEY ("parent_id") REFERENCES "parents" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "parent_students_student_id_fkey" FOREIGN KEY ("student_id") REFERENCES "students" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "notifications" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "recipient_type" TEXT NOT NULL, + "recipient_id" INTEGER NOT NULL, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "notification_type" TEXT NOT NULL, + "related_type" TEXT, + "related_id" INTEGER, + "is_read" BOOLEAN NOT NULL DEFAULT false, + "read_at" DATETIME, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "notifications_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "class_teachers" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "class_id" INTEGER NOT NULL, + "teacher_id" INTEGER NOT NULL, + "role" TEXT NOT NULL DEFAULT 'MAIN', + "isPrimary" BOOLEAN NOT NULL DEFAULT false, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + CONSTRAINT "class_teachers_class_id_fkey" FOREIGN KEY ("class_id") REFERENCES "classes" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "class_teachers_teacher_id_fkey" FOREIGN KEY ("teacher_id") REFERENCES "teachers" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "student_class_history" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "student_id" INTEGER NOT NULL, + "from_class_id" INTEGER, + "to_class_id" INTEGER NOT NULL, + "reason" TEXT, + "operated_by" INTEGER, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "student_class_history_student_id_fkey" FOREIGN KEY ("student_id") REFERENCES "students" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "student_class_history_from_class_id_fkey" FOREIGN KEY ("from_class_id") REFERENCES "classes" ("id") ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT "student_class_history_to_class_id_fkey" FOREIGN KEY ("to_class_id") REFERENCES "classes" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "schedule_plans" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "class_id" INTEGER NOT NULL, + "course_id" INTEGER NOT NULL, + "teacher_id" INTEGER, + "scheduled_date" DATETIME, + "scheduled_time" TEXT, + "week_day" INTEGER, + "repeat_type" TEXT NOT NULL DEFAULT 'NONE', + "repeat_end_date" DATETIME, + "source" TEXT NOT NULL DEFAULT 'SCHOOL', + "created_by" INTEGER NOT NULL, + "status" TEXT NOT NULL DEFAULT 'ACTIVE', + "note" TEXT, + "reminder_sent" BOOLEAN NOT NULL DEFAULT false, + "reminder_sent_at" DATETIME, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + CONSTRAINT "schedule_plans_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "schedule_plans_class_id_fkey" FOREIGN KEY ("class_id") REFERENCES "classes" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "schedule_plans_course_id_fkey" FOREIGN KEY ("course_id") REFERENCES "courses" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "schedule_plans_teacher_id_fkey" FOREIGN KEY ("teacher_id") REFERENCES "teachers" ("id") ON DELETE SET NULL ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "schedule_templates" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER NOT NULL, + "name" TEXT NOT NULL, + "course_id" INTEGER NOT NULL, + "class_id" INTEGER, + "teacher_id" INTEGER, + "scheduled_time" TEXT, + "week_day" INTEGER, + "duration" INTEGER NOT NULL DEFAULT 25, + "is_default" BOOLEAN NOT NULL DEFAULT false, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" DATETIME NOT NULL, + CONSTRAINT "schedule_templates_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "schedule_templates_course_id_fkey" FOREIGN KEY ("course_id") REFERENCES "courses" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "schedule_templates_class_id_fkey" FOREIGN KEY ("class_id") REFERENCES "classes" ("id") ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT "schedule_templates_teacher_id_fkey" FOREIGN KEY ("teacher_id") REFERENCES "teachers" ("id") ON DELETE SET NULL ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "operation_logs" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "tenant_id" INTEGER, + "user_id" INTEGER NOT NULL, + "user_type" TEXT NOT NULL, + "action" TEXT NOT NULL, + "module" TEXT NOT NULL, + "description" TEXT NOT NULL, + "target_id" INTEGER, + "old_value" TEXT, + "new_value" TEXT, + "ip_address" TEXT, + "user_agent" TEXT, + "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "operation_logs_tenant_id_fkey" FOREIGN KEY ("tenant_id") REFERENCES "tenants" ("id") ON DELETE SET NULL ON UPDATE CASCADE +); + +-- CreateIndex +CREATE UNIQUE INDEX "tenants_login_account_key" ON "tenants"("login_account"); + +-- CreateIndex +CREATE UNIQUE INDEX "teachers_login_account_key" ON "teachers"("login_account"); + +-- CreateIndex +CREATE INDEX "courses_status_idx" ON "courses"("status"); + +-- CreateIndex +CREATE INDEX "course_versions_course_id_idx" ON "course_versions"("course_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "course_scripts_course_id_step_index_key" ON "course_scripts"("course_id", "step_index"); + +-- CreateIndex +CREATE UNIQUE INDEX "course_script_pages_script_id_page_number_key" ON "course_script_pages"("script_id", "page_number"); + +-- CreateIndex +CREATE UNIQUE INDEX "lesson_feedbacks_lesson_id_teacher_id_key" ON "lesson_feedbacks"("lesson_id", "teacher_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "student_records_lesson_id_student_id_key" ON "student_records"("lesson_id", "student_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "tags_code_key" ON "tags"("code"); + +-- CreateIndex +CREATE UNIQUE INDEX "tenant_courses_tenant_id_course_id_key" ON "tenant_courses"("tenant_id", "course_id"); + +-- CreateIndex +CREATE INDEX "growth_records_tenant_id_student_id_idx" ON "growth_records"("tenant_id", "student_id"); + +-- CreateIndex +CREATE INDEX "growth_records_tenant_id_class_id_idx" ON "growth_records"("tenant_id", "class_id"); + +-- CreateIndex +CREATE INDEX "tasks_tenant_id_status_idx" ON "tasks"("tenant_id", "status"); + +-- CreateIndex +CREATE INDEX "task_targets_task_id_class_id_idx" ON "task_targets"("task_id", "class_id"); + +-- CreateIndex +CREATE INDEX "task_targets_task_id_student_id_idx" ON "task_targets"("task_id", "student_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "task_completions_task_id_student_id_key" ON "task_completions"("task_id", "student_id"); + +-- CreateIndex +CREATE INDEX "task_templates_tenant_id_status_idx" ON "task_templates"("tenant_id", "status"); + +-- CreateIndex +CREATE INDEX "resource_libraries_library_type_status_idx" ON "resource_libraries"("library_type", "status"); + +-- CreateIndex +CREATE INDEX "resource_items_library_id_idx" ON "resource_items"("library_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "system_settings_tenant_id_key" ON "system_settings"("tenant_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "parents_login_account_key" ON "parents"("login_account"); + +-- CreateIndex +CREATE UNIQUE INDEX "parent_students_parent_id_student_id_key" ON "parent_students"("parent_id", "student_id"); + +-- CreateIndex +CREATE INDEX "notifications_tenant_id_recipient_type_recipient_id_idx" ON "notifications"("tenant_id", "recipient_type", "recipient_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "class_teachers_class_id_teacher_id_key" ON "class_teachers"("class_id", "teacher_id"); + +-- CreateIndex +CREATE INDEX "schedule_plans_tenant_id_class_id_idx" ON "schedule_plans"("tenant_id", "class_id"); + +-- CreateIndex +CREATE INDEX "schedule_plans_tenant_id_teacher_id_idx" ON "schedule_plans"("tenant_id", "teacher_id"); + +-- CreateIndex +CREATE INDEX "schedule_plans_tenant_id_scheduled_date_idx" ON "schedule_plans"("tenant_id", "scheduled_date"); + +-- CreateIndex +CREATE INDEX "schedule_templates_tenant_id_idx" ON "schedule_templates"("tenant_id"); + +-- CreateIndex +CREATE INDEX "schedule_templates_tenant_id_course_id_idx" ON "schedule_templates"("tenant_id", "course_id"); + +-- CreateIndex +CREATE INDEX "operation_logs_tenant_id_user_id_idx" ON "operation_logs"("tenant_id", "user_id"); + +-- CreateIndex +CREATE INDEX "operation_logs_tenant_id_created_at_idx" ON "operation_logs"("tenant_id", "created_at"); + +-- CreateIndex +CREATE INDEX "operation_logs_action_module_idx" ON "operation_logs"("action", "module"); diff --git a/reading-platform-backend/prisma/seed.ts b/reading-platform-backend/prisma/seed.ts index 306db17..73d4efd 100644 --- a/reading-platform-backend/prisma/seed.ts +++ b/reading-platform-backend/prisma/seed.ts @@ -1,6 +1,7 @@ +// npx prisma migrate dev --name init + import { PrismaClient } from '@prisma/client'; import * as bcrypt from 'bcrypt'; - const prisma = new PrismaClient(); async function main() { diff --git a/reading-platform-frontend/package-lock.json b/reading-platform-frontend/package-lock.json index 4acc361..391244c 100644 --- a/reading-platform-frontend/package-lock.json +++ b/reading-platform-frontend/package-lock.json @@ -555,7 +555,6 @@ "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.20.tgz", "integrity": "sha512-1cukXLlePFiJ8YKXn/4tMKsy0etxYLCkXk8nUCFi11nRONF2Ba2CD5b21/ovtOO2tL6afTJfwmc1ed3HG7eB1g==", "license": "MIT", - "peer": true, "dependencies": { "preact": "~10.12.1" } @@ -1367,7 +1366,6 @@ "integrity": "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -2875,7 +2873,6 @@ "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -2977,7 +2974,6 @@ "integrity": "sha512-eKzFy13Nk+IRHhlAwP3sfuv+PzOrvzUkwJK2hdoCKYcWGSdmwFpeGpWmyewdw8EgBnsKaSBtgf/0b2K635ecSA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@bufbuild/protobuf": "^2.5.0", "colorjs.io": "^0.5.0", @@ -3489,7 +3485,6 @@ "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3705,7 +3700,6 @@ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -3787,7 +3781,6 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.28.tgz", "integrity": "sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==", "license": "MIT", - "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.28", "@vue/compiler-sfc": "3.5.28", diff --git a/reading-platform-frontend/src/components.d.ts b/reading-platform-frontend/src/components.d.ts index b64ad8b..bdd3aa4 100644 --- a/reading-platform-frontend/src/components.d.ts +++ b/reading-platform-frontend/src/components.d.ts @@ -36,8 +36,6 @@ declare module 'vue' { AModal: typeof import('ant-design-vue/es')['Modal'] APageHeader: typeof import('ant-design-vue/es')['PageHeader'] APopconfirm: typeof import('ant-design-vue/es')['Popconfirm'] - ARadio: typeof import('ant-design-vue/es')['Radio'] - ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup'] ARangePicker: typeof import('ant-design-vue/es')['RangePicker'] ARow: typeof import('ant-design-vue/es')['Row'] ASelect: typeof import('ant-design-vue/es')['Select'] @@ -45,10 +43,7 @@ declare module 'vue' { ASkeleton: typeof import('ant-design-vue/es')['Skeleton'] ASpace: typeof import('ant-design-vue/es')['Space'] AStatistic: typeof import('ant-design-vue/es')['Statistic'] - ASwitch: typeof import('ant-design-vue/es')['Switch'] ATable: typeof import('ant-design-vue/es')['Table'] - ATabPane: typeof import('ant-design-vue/es')['TabPane'] - ATabs: typeof import('ant-design-vue/es')['Tabs'] ATag: typeof import('ant-design-vue/es')['Tag'] ATextarea: typeof import('ant-design-vue/es')['Textarea'] ATooltip: typeof import('ant-design-vue/es')['Tooltip']