-- 恭学教育 MySQL 初始化脚本
-- 用途：在 DB_SYNCHRONIZE=false 时初始化空 MySQL 8.x 数据库，使当前项目可直接运行。
-- 默认管理员：admin / admin123（首次登录后请立即修改密码）。
-- 如果用 docker-entrypoint-initdb.d 自动初始化，可直接挂载本文件。

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

CREATE DATABASE IF NOT EXISTS `dorm_billing_v2` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE `dorm_billing_v2`;

-- ---------- 重置旧表 ----------
DROP TABLE IF EXISTS `archive_attachments`;
DROP TABLE IF EXISTS `result_archives`;
DROP TABLE IF EXISTS `learning_records`;
DROP TABLE IF EXISTS `exam_scores`;
DROP TABLE IF EXISTS `student_enrollments`;
DROP TABLE IF EXISTS `student_profiles`;
DROP TABLE IF EXISTS `notifications`;
DROP TABLE IF EXISTS `ding_attendance_raw`;
DROP TABLE IF EXISTS `attendance_devices`;
DROP TABLE IF EXISTS `attendance_records`;
DROP TABLE IF EXISTS `attendance_sessions`;
DROP TABLE IF EXISTS `class_schedule`;
DROP TABLE IF EXISTS `class_teacher`;
DROP TABLE IF EXISTS `class_student`;
DROP TABLE IF EXISTS `classes`;
DROP TABLE IF EXISTS `classroom_rentals`;
DROP TABLE IF EXISTS `classrooms`;
DROP TABLE IF EXISTS `deposit_installments`;
DROP TABLE IF EXISTS `deposits`;
DROP TABLE IF EXISTS `operation_logs`;
DROP TABLE IF EXISTS `student_wallets`;
DROP TABLE IF EXISTS `wallet_transactions`;
DROP TABLE IF EXISTS `student_ding_mapping`;
DROP TABLE IF EXISTS `students`;
DROP TABLE IF EXISTS `user_roles`;
DROP TABLE IF EXISTS `role_permissions`;
DROP TABLE IF EXISTS `users`;
DROP TABLE IF EXISTS `roles`;
DROP TABLE IF EXISTS `permissions`;
DROP TABLE IF EXISTS `bills`;
DROP TABLE IF EXISTS `bill_items`;
DROP TABLE IF EXISTS `personal_expenses`;
DROP TABLE IF EXISTS `room_expenses`;
DROP TABLE IF EXISTS `occupancies`;
DROP TABLE IF EXISTS `beds`;
DROP TABLE IF EXISTS `lockers`;
DROP TABLE IF EXISTS `rooms`;
DROP TABLE IF EXISTS `organizations`;
DROP TABLE IF EXISTS `sync_state`;
DROP TABLE IF EXISTS `sync_logs`;
DROP TABLE IF EXISTS `expense_types`;
DROP TABLE IF EXISTS `ai_config`;
DROP TABLE IF EXISTS `integration_config_detail`;
DROP TABLE IF EXISTS `integration_config`;

-- ---------- 表结构 ----------
CREATE TABLE IF NOT EXISTS `room_expenses` (`id` int NOT NULL AUTO_INCREMENT, `room_id` int NOT NULL, `expense_type` varchar(20) NOT NULL, `amount` decimal(10,2) NOT NULL, `period_start` date NOT NULL, `period_end` date NOT NULL, `description` text NULL, `recorded_by` int NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `rooms` (`id` int NOT NULL AUTO_INCREMENT, `room_number` varchar(20) NOT NULL, `building` varchar(50) NULL, `floor` int NULL, `capacity` int NOT NULL, `status` varchar(20) NOT NULL DEFAULT 'available', `room_type` varchar(20) NULL, `rental_category` varchar(10) NOT NULL DEFAULT 'short', `monthly_rate` decimal(10,2) NOT NULL DEFAULT 0.00, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_8f7c6fa4c469bab1a06fe3e49f` (`room_number`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `organizations` (`id` int NOT NULL AUTO_INCREMENT, `public_id` varchar(36) NOT NULL, `code` varchar(50) NOT NULL, `name` varchar(100) NOT NULL, `is_host` tinyint NOT NULL DEFAULT 0, `contact_name` varchar(50) NULL, `phone` varchar(30) NULL, `color` varchar(20) NULL, `notes` text NULL, `status` varchar(20) NOT NULL DEFAULT 'active', `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_0db5eda192bf60a02bd41931f8` (`public_id`), UNIQUE INDEX `IDX_7e27c3b62c681fbe3e2322535f` (`code`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `beds` (`id` int NOT NULL AUTO_INCREMENT, `room_id` int NOT NULL, `bed_number` varchar(20) NOT NULL, `status` varchar(20) NOT NULL DEFAULT 'available', `notes` text NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_95e9ba0a907346ef7b0d5ca488` (`room_id`, `bed_number`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `lockers` (`id` int NOT NULL AUTO_INCREMENT, `room_id` int NOT NULL, `locker_number` varchar(20) NOT NULL, `status` varchar(20) NOT NULL DEFAULT 'available', `notes` text NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_8bc984d80d58c6909f738d8282` (`room_id`, `locker_number`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `occupancies` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `room_id` int NOT NULL, `check_in_date` date NOT NULL, `check_out_date` date NULL, `billing_start_date` date NOT NULL, `billing_end_date` date NULL, `check_out_reason` varchar(100) NULL, `notes` text NULL, `bed_id` int NULL, `locker_id` int NULL, `stay_type` varchar(10) NOT NULL DEFAULT 'short', `responsible_organization_id` int NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `personal_expenses` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `room_id` int NULL, `expense_type` varchar(20) NOT NULL, `amount` decimal(10,2) NOT NULL, `expense_date` date NOT NULL, `description` text NULL, `recorded_by` int NULL, `bill_id` int NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `bill_items` (`id` int NOT NULL AUTO_INCREMENT, `bill_id` int NOT NULL, `room_id` int NULL, `expense_type` varchar(20) NULL, `description` varchar(200) NULL, `days` int NULL, `total_room_days` int NULL, `room_total_amount` decimal(10,2) NULL, `student_amount` decimal(10,2) NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `bills` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `period_start` date NOT NULL, `period_end` date NOT NULL, `shared_amount` decimal(10,2) NOT NULL DEFAULT 0.00, `personal_amount` decimal(10,2) NOT NULL DEFAULT 0.00, `total_amount` decimal(10,2) NOT NULL DEFAULT 0.00, `source` varchar(30) NOT NULL DEFAULT 'batch', `paid_amount` decimal(10,2) NOT NULL DEFAULT 0.00, `outstanding_amount` decimal(10,2) NOT NULL DEFAULT 0.00, `status` varchar(20) NOT NULL DEFAULT 'unpaid', `cancelled_at` datetime NULL, `cancel_reason` varchar(300) NULL, `generated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `permissions` (`id` int NOT NULL AUTO_INCREMENT, `code` varchar(50) NOT NULL, `name` varchar(50) NOT NULL, `group` varchar(30) NOT NULL, `description` varchar(200) NULL, UNIQUE INDEX `IDX_8dad765629e83229da6feda1c1` (`code`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `roles` (`id` int NOT NULL AUTO_INCREMENT, `name` varchar(30) NOT NULL, `code` varchar(30) NULL, `description` varchar(200) NULL, `is_system` tinyint NOT NULL DEFAULT 0, `status` tinyint NOT NULL DEFAULT 1, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_648e3f5447f725579d7d4ffdfb` (`name`), UNIQUE INDEX `IDX_f6d54f95c31b73fb1bdd8e91d0` (`code`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `users` (`id` int NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password_hash` varchar(255) NOT NULL, `name` varchar(50) NULL, `is_active` tinyint NOT NULL DEFAULT 1, `last_login_at` datetime NULL, `is_archived` tinyint NOT NULL DEFAULT 0, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `profile` text NULL, UNIQUE INDEX `IDX_fe0bb3f6520ee0469504521e71` (`username`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `students` (`id` int NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `student_no` varchar(30) NULL, `phone` varchar(20) NULL, `id_number` varchar(30) NULL, `gender` varchar(10) NULL, `ethnicity` varchar(20) NULL, `emergency_contact` varchar(50) NULL, `emergency_phone` varchar(20) NULL, `status` varchar(20) NOT NULL DEFAULT 'active', `supervisor` varchar(50) NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), `user_id` int NULL, `organization_id` int NULL, UNIQUE INDEX `IDX_fb3eff90b11bddf7285f9b4e28` (`user_id`), UNIQUE INDEX `REL_fb3eff90b11bddf7285f9b4e28` (`user_id`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `operation_logs` (`id` int NOT NULL AUTO_INCREMENT, `user_id` int NULL, `username` varchar(50) NULL, `module` varchar(50) NOT NULL, `action` varchar(50) NOT NULL, `target_id` int NULL, `target_type` varchar(50) NULL, `detail` text NULL, `ip_address` varchar(50) NULL, `user_agent` varchar(500) NULL, `status` varchar(20) NULL DEFAULT 'success', `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `deposit_installments` (`id` int NOT NULL AUTO_INCREMENT, `deposit_id` int NOT NULL, `amount` decimal(10,2) NOT NULL, `due_date` date NOT NULL, `paid_date` date NULL, `status` varchar(20) NOT NULL DEFAULT 'pending', `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `deposits` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `amount` decimal(10,2) NOT NULL DEFAULT '500.00', `status` varchar(20) NOT NULL DEFAULT 'paid', `paid_date` date NOT NULL, `refund_date` date NULL, `refund_amount` decimal(10,2) NULL, `deduction_amount` decimal(10,2) NOT NULL DEFAULT 0.00, `deduction_reason` text NULL, `notes` text NULL, `recorded_by` int NULL, `refunded_by` int NULL, `refunded_at` datetime NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `classrooms` (`id` int NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `building` varchar(50) NULL, `floor` int NULL, `capacity` int NOT NULL DEFAULT '30', `room_type` varchar(20) NOT NULL DEFAULT '大', `status` varchar(20) NOT NULL DEFAULT 'available', `notes` text NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `attendance_devices` (`id` int NOT NULL AUTO_INCREMENT, `device_sn` varchar(100) NOT NULL, `device_name` varchar(100) NOT NULL, `classroom_id` int NOT NULL, `status` varchar(20) NOT NULL DEFAULT 'active', `location` varchar(200) NULL, `notes` text NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_attendance_devices_device_sn` (`device_sn`), INDEX `IDX_attendance_devices_classroom_id` (`classroom_id`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `classroom_rentals` (`id` int NOT NULL AUTO_INCREMENT, `classroom_id` int NOT NULL, `lessor_organization_id` int NULL, `lessee_organization_id` int NULL, `start_date` date NOT NULL, `end_date` date NOT NULL, `contract_path` varchar(255) NULL, `contract_original_name` varchar(255) NULL, `daily_rate` decimal(10,2) NULL, `total_amount` decimal(10,2) NULL, `status` varchar(20) NOT NULL DEFAULT 'active', `notes` text NULL, `created_by` int NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), INDEX `IDX_b748a951d00b3f0c2090d10397` (`classroom_id`, `start_date`, `end_date`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `classes` (`id` int NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL, `code` varchar(50) NOT NULL, `class_type` varchar(20) NOT NULL, `start_date` date NULL, `end_date` date NULL, `status` varchar(20) NOT NULL DEFAULT 'enrolling', `head_teacher_id` int NULL, `life_teacher_id` int NULL, `academic_teacher_id` int NULL, `max_students` int NOT NULL DEFAULT 0, `notes` text NULL, `is_archived` tinyint NOT NULL DEFAULT 0, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_cf7491878e0fca859943862998` (`code`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `class_student` (`id` int NOT NULL AUTO_INCREMENT, `class_id` int NOT NULL, `student_id` int NOT NULL, `join_date` date NULL, `leave_date` date NULL, `status` varchar(10) NOT NULL DEFAULT 'active', `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_b0ed786e05e93dd9bf77189af1` (`class_id`, `student_id`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `class_teacher` (`id` int NOT NULL AUTO_INCREMENT, `class_id` int NOT NULL, `user_id` int NOT NULL, `role_type` varchar(30) NOT NULL, `subject` varchar(50) NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_0117e9171e1533ff7b5c63f5d6` (`class_id`, `user_id`, `role_type`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `class_schedule` (`id` int NOT NULL AUTO_INCREMENT, `class_id` int NULL, `classroom_id` int NOT NULL, `week_day` int NOT NULL, `start_time` varchar(5) NOT NULL, `end_time` varchar(5) NOT NULL, `attendance_advance_minutes` int NOT NULL DEFAULT '30', `start_date` date NOT NULL, `end_date` date NOT NULL, `subject` varchar(50) NOT NULL, `teacher_id` int NULL, `schedule_type` varchar(20) NOT NULL DEFAULT 'INTERNAL', `rental_id` int NULL, `status` varchar(20) NOT NULL DEFAULT 'active', `notes` text NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `attendance_sessions` (`id` int NOT NULL AUTO_INCREMENT, `schedule_id` int NOT NULL, `class_id` int NOT NULL, `lesson_date` date NOT NULL, `status` varchar(20) NOT NULL DEFAULT 'in_progress', `started_by` int NULL, `started_at` datetime NULL, `completed_by` int NULL, `completed_at` datetime NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_d4288982a2baaa6085cf872990` (`schedule_id`, `lesson_date`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `attendance_records` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `class_id` int NULL, `schedule_id` int NULL, `attendance_session_id` int NULL, `attendance_date` date NOT NULL, `session` varchar(20) NOT NULL, `status` varchar(20) NOT NULL, `remark` varchar(200) NULL, `source` varchar(20) NOT NULL DEFAULT 'manual', `punch_time` datetime NULL, `punch_source` varchar(40) NULL, `punch_device_name` varchar(100) NULL, `punch_device_id` varchar(100) NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_43ac61c4ffa4117b738dd3a1e4` (`attendance_session_id`, `student_id`), INDEX `IDX_6b8f69a76bea22962e54bd21f5` (`student_id`, `attendance_date`), INDEX `IDX_a8eee7b8a0e0af27e79cb27ccc` (`class_id`, `attendance_date`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `ding_attendance_raw` (`id` int NOT NULL AUTO_INCREMENT, `ding_user_id` varchar(100) NOT NULL, `user_name` varchar(100) NOT NULL, `attendance_date` date NOT NULL, `ding_id` varchar(100) NOT NULL, `check_in_time` datetime NULL, `check_out_time` datetime NULL, `attendance_type` varchar(20) NOT NULL, `time_result` varchar(20) NOT NULL, `location_result` varchar(20) NULL, `punch_source` varchar(40) NULL, `punch_device_name` varchar(100) NULL, `punch_device_id` varchar(100) NULL, `match_status` varchar(20) NOT NULL DEFAULT 'unmatched', `matched_student_id` int NULL, `raw_data` text NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), INDEX `IDX_d6680d5150f0bfa47dbc1fe96f` (`match_status`), INDEX `IDX_088de070f537b15ab7da255e5b` (`attendance_date`), UNIQUE INDEX `IDX_997849bb04ff69149fcf00a8d3` (`ding_id`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `sync_logs` (`id` int NOT NULL AUTO_INCREMENT, `platform` varchar(20) NOT NULL, `sync_type` varchar(20) NOT NULL, `status` varchar(20) NOT NULL, `records_count` int NOT NULL DEFAULT 0, `error_message` text NULL, `started_at` datetime NULL, `finished_at` datetime NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `sync_state` (`platform` varchar(20) NOT NULL, `last_sync_at` datetime NULL, PRIMARY KEY (`platform`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `expense_types` (`id` int NOT NULL AUTO_INCREMENT, `code` varchar(30) NOT NULL, `name` varchar(30) NOT NULL, `category` varchar(20) NOT NULL DEFAULT 'room', `sort_order` int NOT NULL DEFAULT 0, `enabled` tinyint NOT NULL DEFAULT 1, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_36eda3eb0f6740ecf2ba906012` (`code`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `notifications` (`id` int NOT NULL AUTO_INCREMENT, `recipient_id` int NOT NULL, `type` varchar(30) NOT NULL, `title` varchar(200) NOT NULL, `content` text NULL, `link` varchar(500) NULL, `is_read` tinyint NOT NULL DEFAULT 0, `read_at` datetime NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `student_profiles` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `target_college` varchar(100) NULL, `target_major` varchar(100) NULL, `subject_direction` varchar(50) NULL, `grade` varchar(20) NULL, `profile_date` date NULL, `notes` text NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_4cedc08d3dc1f2c2da8a12f7a8` (`student_id`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `student_enrollments` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `course_category` varchar(50) NULL, `class_type` varchar(50) NULL, `class_name` varchar(100) NULL, `head_teacher` varchar(50) NULL, `subject_teacher` varchar(50) NULL, `start_date` date NULL, `end_date` date NULL, `status` varchar(20) NOT NULL DEFAULT 'active', `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `exam_scores` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `enrollment_id` int NULL, `exam_type` varchar(50) NULL, `exam_name` varchar(100) NULL, `subject` varchar(50) NULL, `score` decimal(5,2) NULL, `class_avg` decimal(5,2) NULL, `rank` int NULL, `exam_date` date NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `learning_records` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `record_date` date NULL, `record_type` varchar(50) NULL, `content` text NULL, `follow_up_method` varchar(50) NULL, `next_step` text NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `result_archives` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `culture_final_score` decimal(5,2) NULL, `professional_final_score` decimal(5,2) NULL, `admission_status` varchar(50) NULL, `admitted_college` varchar(100) NULL, `admitted_major` varchar(100) NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_377bba8eb6a027eecd9737d4ed` (`student_id`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `archive_attachments` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `category` varchar(50) NULL, `file_name` varchar(255) NULL, `file_path` varchar(500) NULL, `file_size` int NULL, `mime_type` varchar(100) NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `student_ding_mapping` (`id` int NOT NULL AUTO_INCREMENT, `ding_user_id` varchar(100) NOT NULL, `student_id` int NOT NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_0d1ec47e2f901d37e3b6e56331` (`ding_user_id`), UNIQUE INDEX `IDX_f9ba15ff04de8ffbd8679ae9db` (`student_id`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `ai_config` (`id` int NOT NULL AUTO_INCREMENT, `singleton_key` varchar(20) NOT NULL DEFAULT 'GLOBAL', `provider` varchar(50) NOT NULL DEFAULT 'OPENAI', `base_url` varchar(500) NULL, `encrypted_api_key` text NULL, `api_key_iv` varchar(50) NULL, `api_key_auth_tag` varchar(50) NULL, `key_last4` varchar(4) NULL, `default_model` varchar(100) NULL, `enabled` tinyint NOT NULL DEFAULT 0, `timeout_ms` int NOT NULL DEFAULT '30000', `verified` tinyint NOT NULL DEFAULT 0, `last_tested_at` datetime NULL, `last_test_latency_ms` int NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `uq_ai_config_singleton` (`singleton_key`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `student_wallets` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `balance` decimal(12,2) NOT NULL DEFAULT 0.00, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX `IDX_07a434ad1a960d506386754d59` (`student_id`), UNIQUE INDEX `REL_07a434ad1a960d506386754d59` (`student_id`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `wallet_transactions` (`id` int NOT NULL AUTO_INCREMENT, `student_id` int NOT NULL, `bill_id` int NULL, `type` varchar(30) NOT NULL, `amount` decimal(12,2) NOT NULL, `balance_after` decimal(12,2) NOT NULL, `description` varchar(300) NULL, `recorded_by` int NULL, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), INDEX `IDX_680bbd0275ac5e06c179f9b84c` (`student_id`, `created_at`), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `integration_config` (`id` int NOT NULL AUTO_INCREMENT, `type` varchar(50) NOT NULL, `sync_resource` varchar(50) NULL, `is_sync` tinyint NOT NULL DEFAULT 0, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `integration_config_detail` (`id` int NOT NULL AUTO_INCREMENT, `config_id` int NOT NULL, `name` varchar(100) NULL, `type` varchar(50) NOT NULL, `content` text NULL, `enable` tinyint NOT NULL DEFAULT 0, `created_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updated_at` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), INDEX `IDX_a58106c4b876c86a5e085e4f42` (`config_id`), PRIMARY KEY (`id`)) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `role_permissions` (`role_id` int NOT NULL, `permission_id` int NOT NULL, INDEX `IDX_178199805b901ccd220ab7740e` (`role_id`), INDEX `IDX_17022daf3f885f7d35423e9971` (`permission_id`), PRIMARY KEY (`role_id`, `permission_id`)) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `user_roles` (`user_id` int NOT NULL, `role_id` int NOT NULL, INDEX `IDX_87b8888186ca9769c960e92687` (`user_id`), INDEX `IDX_b23c65e50a758245a33ee35fda` (`role_id`), PRIMARY KEY (`user_id`, `role_id`)) ENGINE=InnoDB;

-- ---------- 外键 ----------
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_178199805b901ccd220ab7740ec' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `role_permissions` ADD CONSTRAINT `FK_178199805b901ccd220ab7740ec` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE CASCADE ON UPDATE CASCADE', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_17022daf3f885f7d35423e9971e' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `role_permissions` ADD CONSTRAINT `FK_17022daf3f885f7d35423e9971e` FOREIGN KEY (`permission_id`) REFERENCES `permissions`(`id`) ON DELETE CASCADE ON UPDATE CASCADE', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_87b8888186ca9769c960e926870' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `user_roles` ADD CONSTRAINT `FK_87b8888186ca9769c960e926870` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_b23c65e50a758245a33ee35fda1' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `user_roles` ADD CONSTRAINT `FK_b23c65e50a758245a33ee35fda1` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_7bb1ca73f8161af27e538917a55' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `room_expenses` ADD CONSTRAINT `FK_7bb1ca73f8161af27e538917a55` FOREIGN KEY (`room_id`) REFERENCES `rooms`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_fd7413faee42749f1b2e8270394' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `beds` ADD CONSTRAINT `FK_fd7413faee42749f1b2e8270394` FOREIGN KEY (`room_id`) REFERENCES `rooms`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_344ae29b9cacbee1e24da7c07ea' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `lockers` ADD CONSTRAINT `FK_344ae29b9cacbee1e24da7c07ea` FOREIGN KEY (`room_id`) REFERENCES `rooms`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_bed301f5a4e2135dd14b55fec0e' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `occupancies` ADD CONSTRAINT `FK_bed301f5a4e2135dd14b55fec0e` FOREIGN KEY (`bed_id`) REFERENCES `beds`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_ea80244bd95c8c04334931e39a2' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `occupancies` ADD CONSTRAINT `FK_ea80244bd95c8c04334931e39a2` FOREIGN KEY (`locker_id`) REFERENCES `lockers`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_3c80232a56303a75ffd544b982f' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `occupancies` ADD CONSTRAINT `FK_3c80232a56303a75ffd544b982f` FOREIGN KEY (`responsible_organization_id`) REFERENCES `organizations`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_dc062720596049470b56ce06973' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `occupancies` ADD CONSTRAINT `FK_dc062720596049470b56ce06973` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_9f7acc7567e42dda281ead9a75a' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `occupancies` ADD CONSTRAINT `FK_9f7acc7567e42dda281ead9a75a` FOREIGN KEY (`room_id`) REFERENCES `rooms`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_5e5bcfb70705c2c349c74b70912' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `personal_expenses` ADD CONSTRAINT `FK_5e5bcfb70705c2c349c74b70912` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_b424156152a3230b034bdb51db4' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `bill_items` ADD CONSTRAINT `FK_b424156152a3230b034bdb51db4` FOREIGN KEY (`bill_id`) REFERENCES `bills`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_65a6cb602ebcbac1bf7a995e0c9' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `bills` ADD CONSTRAINT `FK_65a6cb602ebcbac1bf7a995e0c9` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_fb3eff90b11bddf7285f9b4e281' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `students` ADD CONSTRAINT `FK_fb3eff90b11bddf7285f9b4e281` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE SET NULL ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_9571384818ecf499779d3a9d141' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `students` ADD CONSTRAINT `FK_9571384818ecf499779d3a9d141` FOREIGN KEY (`organization_id`) REFERENCES `organizations`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_fba3c52b86d51fff34593877ff5' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `deposit_installments` ADD CONSTRAINT `FK_fba3c52b86d51fff34593877ff5` FOREIGN KEY (`deposit_id`) REFERENCES `deposits`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_ec1b340d2963ed907421696fc33' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `deposits` ADD CONSTRAINT `FK_ec1b340d2963ed907421696fc33` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_6a0af46fe476070c4c660307641' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `classroom_rentals` ADD CONSTRAINT `FK_6a0af46fe476070c4c660307641` FOREIGN KEY (`classroom_id`) REFERENCES `classrooms`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_40a46e95470ff454ffdcbb1e902' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `classroom_rentals` ADD CONSTRAINT `FK_40a46e95470ff454ffdcbb1e902` FOREIGN KEY (`lessor_organization_id`) REFERENCES `organizations`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_f60533a91f16a331c9388308418' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `classroom_rentals` ADD CONSTRAINT `FK_f60533a91f16a331c9388308418` FOREIGN KEY (`lessee_organization_id`) REFERENCES `organizations`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_60674dc4f23b794de0a3560e200' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `class_student` ADD CONSTRAINT `FK_60674dc4f23b794de0a3560e200` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_451334295b9cf221d55aca7cac1' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `class_student` ADD CONSTRAINT `FK_451334295b9cf221d55aca7cac1` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_9b647c8d8894a661dc1dac40361' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `class_teacher` ADD CONSTRAINT `FK_9b647c8d8894a661dc1dac40361` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_a9f0e77d193b015b6d5ca6637f5' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `class_teacher` ADD CONSTRAINT `FK_a9f0e77d193b015b6d5ca6637f5` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_attendance_devices_classroom' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `attendance_devices` ADD CONSTRAINT `FK_attendance_devices_classroom` FOREIGN KEY (`classroom_id`) REFERENCES `classrooms`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_0aa74ee427967d4c82f298511bc' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `class_schedule` ADD CONSTRAINT `FK_0aa74ee427967d4c82f298511bc` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_c1d5d50c871fdf563be13d6e93a' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `class_schedule` ADD CONSTRAINT `FK_c1d5d50c871fdf563be13d6e93a` FOREIGN KEY (`classroom_id`) REFERENCES `classrooms`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_f1e761cac59f2d0a3d7949468c5' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `class_schedule` ADD CONSTRAINT `FK_f1e761cac59f2d0a3d7949468c5` FOREIGN KEY (`teacher_id`) REFERENCES `users`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_107206b64415a644d571d597ca3' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `attendance_sessions` ADD CONSTRAINT `FK_107206b64415a644d571d597ca3` FOREIGN KEY (`schedule_id`) REFERENCES `class_schedule`(`id`) ON DELETE RESTRICT ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_6fc552e07b31ac92445cd3e21fa' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `attendance_sessions` ADD CONSTRAINT `FK_6fc552e07b31ac92445cd3e21fa` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE RESTRICT ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_dbace05c012526710663f8d8911' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `attendance_records` ADD CONSTRAINT `FK_dbace05c012526710663f8d8911` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_cc48ccbd03396874857ab06ac3b' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `attendance_records` ADD CONSTRAINT `FK_cc48ccbd03396874857ab06ac3b` FOREIGN KEY (`class_id`) REFERENCES `classes`(`id`) ON DELETE SET NULL ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_0dfe6d219c4a7a162ca0f84243c' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `attendance_records` ADD CONSTRAINT `FK_0dfe6d219c4a7a162ca0f84243c` FOREIGN KEY (`schedule_id`) REFERENCES `class_schedule`(`id`) ON DELETE SET NULL ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_32a57ba853da6939ceaccf8cfc8' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `attendance_records` ADD CONSTRAINT `FK_32a57ba853da6939ceaccf8cfc8` FOREIGN KEY (`attendance_session_id`) REFERENCES `attendance_sessions`(`id`) ON DELETE SET NULL ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_2b06491a70540db69e78e57ecf2' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `ding_attendance_raw` ADD CONSTRAINT `FK_2b06491a70540db69e78e57ecf2` FOREIGN KEY (`matched_student_id`) REFERENCES `students`(`id`) ON DELETE SET NULL ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_5332a4daa46fd3f4e6625dd275d' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `notifications` ADD CONSTRAINT `FK_5332a4daa46fd3f4e6625dd275d` FOREIGN KEY (`recipient_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_4cedc08d3dc1f2c2da8a12f7a88' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `student_profiles` ADD CONSTRAINT `FK_4cedc08d3dc1f2c2da8a12f7a88` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_08caafd8a026a19ecf54db0e958' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `student_enrollments` ADD CONSTRAINT `FK_08caafd8a026a19ecf54db0e958` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_925e4f79518c947512cb600b452' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `exam_scores` ADD CONSTRAINT `FK_925e4f79518c947512cb600b452` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_b0d812b639f32939ea57b81a89f' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `exam_scores` ADD CONSTRAINT `FK_b0d812b639f32939ea57b81a89f` FOREIGN KEY (`enrollment_id`) REFERENCES `student_enrollments`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_61f4664f02d86245e1231493951' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `learning_records` ADD CONSTRAINT `FK_61f4664f02d86245e1231493951` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_377bba8eb6a027eecd9737d4ed6' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `result_archives` ADD CONSTRAINT `FK_377bba8eb6a027eecd9737d4ed6` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_0bc7365c2629d0c6dae8052fc25' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `archive_attachments` ADD CONSTRAINT `FK_0bc7365c2629d0c6dae8052fc25` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_f9ba15ff04de8ffbd8679ae9dbb' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `student_ding_mapping` ADD CONSTRAINT `FK_f9ba15ff04de8ffbd8679ae9dbb` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_07a434ad1a960d506386754d592' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `student_wallets` ADD CONSTRAINT `FK_07a434ad1a960d506386754d592` FOREIGN KEY (`student_id`) REFERENCES `students`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @fk_exists := (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'FK_a58106c4b876c86a5e085e4f42b' AND CONSTRAINT_TYPE = 'FOREIGN KEY');
SET @sql := IF(@fk_exists = 0, 'ALTER TABLE `integration_config_detail` ADD CONSTRAINT `FK_a58106c4b876c86a5e085e4f42b` FOREIGN KEY (`config_id`) REFERENCES `integration_config`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET FOREIGN_KEY_CHECKS = 1;

-- ---------- 初始化数据 ----------

INSERT INTO `permissions` (`id`, `code`, `name`, `group`) VALUES
('1', 'dashboard:view', '查看数据面板', 'dashboard'),
('2', 'profile:view', '查看个人资料', 'profile'),
('3', 'notification:view', '查看通知', 'notification'),
('4', 'student:view', '查看学生管理', 'student'),
('5', 'student:basic-view', '查看学生基础信息', 'student-scope'),
('6', 'teacher-workspace:view', '查看教师工作台', 'teacher-workspace'),
('7', 'teacher:view', '查看教师', 'teacher'),
('8', 'teacher:edit', '编辑教师', 'teacher'),
('9', 'student:create', '新增学生', 'student'),
('10', 'student:edit', '编辑学生', 'student'),
('11', 'student:delete', '删除学生', 'student'),
('12', 'student:import', '导入学生', 'student'),
('13', 'student:export', '导出学生', 'student'),
('14', 'room:view', '查看宿舍', 'room'),
('15', 'room:create', '新增宿舍', 'room'),
('16', 'room:edit', '编辑宿舍', 'room'),
('17', 'room:delete', '删除宿舍', 'room'),
('18', 'occupancy:view', '查看入住', 'occupancy'),
('19', 'occupancy:checkin', '办理入住', 'occupancy'),
('20', 'occupancy:checkout', '办理退宿', 'occupancy'),
('21', 'occupancy:transfer', '调换宿舍', 'occupancy'),
('22', 'occupancy:delete', '删除入住记录', 'occupancy'),
('23', 'expense:view', '查看费用', 'expense'),
('24', 'expense:create', '录入费用', 'expense'),
('25', 'expense:edit', '编辑费用', 'expense'),
('26', 'expense:delete', '删除费用', 'expense'),
('27', 'bill:view', '查看账单', 'bill'),
('28', 'bill:generate', '生成账单', 'bill'),
('29', 'bill:confirm', '确认账单', 'bill'),
('30', 'bill:delete', '删除账单', 'bill'),
('31', 'bill:export-excel', '导出 Excel', 'bill'),
('32', 'bill:export-pdf', '导出 PDF', 'bill'),
('33', 'deposit:view', '查看押金', 'deposit'),
('34', 'deposit:create', '新增押金', 'deposit'),
('35', 'deposit:edit', '编辑押金', 'deposit'),
('36', 'deposit:delete', '删除押金', 'deposit'),
('37', 'deposit:refund', '直接退还押金', 'deposit'),
('38', 'wallet:view', '查看学生余额', 'wallet'),
('39', 'wallet:edit', '充值和调账', 'wallet'),
('40', 'classroom:view', '查看教室', 'classroom'),
('41', 'classroom:create', '新增教室', 'classroom'),
('42', 'classroom:edit', '编辑教室', 'classroom'),
('43', 'classroom:delete', '删除教室', 'classroom'),
('44', 'organization:view', '查看机构', 'organization'),
('45', 'organization:create', '新增机构', 'organization'),
('46', 'organization:edit', '编辑机构', 'organization'),
('47', 'organization:delete', '归档机构', 'organization'),
('48', 'rental:view', '查看租赁订单', 'rental'),
('49', 'rental:create', '新增租赁订单', 'rental'),
('50', 'rental:edit', '编辑租赁订单', 'rental'),
('51', 'rental:delete', '删除租赁订单', 'rental'),
('52', 'log:view', '查看操作日志', 'log'),
('53', 'log:create', '写入操作日志', 'log'),
('54', 'user:view', '查看用户', 'user'),
('55', 'user:create', '创建用户', 'user'),
('56', 'user:edit', '编辑用户', 'user'),
('57', 'user:delete', '删除用户', 'user'),
('58', 'user:reset-password', '重置密码', 'user'),
('59', 'role:view', '查看角色', 'role'),
('60', 'role:create', '创建角色', 'role'),
('61', 'role:edit', '编辑角色', 'role'),
('62', 'role:delete', '删除角色', 'role'),
('63', 'class:view', '查看班级', 'class'),
('64', 'class:create', '创建班级', 'class'),
('65', 'class:edit', '编辑班级', 'class'),
('66', 'class:delete', '删除班级', 'class'),
('67', 'schedule:view', '查看排课', 'schedule'),
('68', 'schedule:create', '创建排课', 'schedule'),
('69', 'schedule:edit', '编辑排课', 'schedule'),
('70', 'schedule:delete', '删除排课', 'schedule'),
('71', 'attendance:view', '查看考勤', 'attendance'),
('72', 'attendance:create', '新增考勤', 'attendance'),
('73', 'attendance:edit', '编辑全部考勤', 'attendance'),
('74', 'attendance:self-edit', '编辑任教班级考勤', 'attendance-scope'),
('75', 'attendance:export', '导出考勤', 'attendance'),
('76', 'attendance:generate', '按课表生成考勤', 'attendance'),
('77', 'learning:create', '创建学习任务', 'learning'),
('78', 'learning:edit', '编辑学习任务', 'learning'),
('79', 'learning:delete', '删除学习任务', 'learning'),
('80', 'exam:create', '创建考试', 'exam'),
('81', 'exam:edit', '编辑考试', 'exam'),
('82', 'exam:delete', '删除考试', 'exam'),
('83', 'sync:trigger', '触发数据同步', 'sync'),
('84', 'sync:read', '查看同步状态', 'sync'),
('85', 'integration:trigger', '触发集成', 'integration'),
('86', 'integration:read', '查看集成状态', 'integration'),
('87', 'department:view', '查看部门', 'department'),
('88', 'department:edit', '编辑部门', 'department'),
('89', 'department:delete', '删除部门', 'department'),
('90', 'ai:config:read', '查看 AI 配置', 'ai'),
('91', 'ai:config:write', '修改 AI 配置', 'ai'),
('92', 'ai:config:test', '测试 AI 连接', 'ai')
ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `group` = VALUES(`group`);

INSERT INTO `roles` (`id`, `name`, `code`, `description`, `is_system`, `status`) VALUES
('1', '超级管理员', 'super_admin', '系统初始化、应急维护和全局权限处理', '1', '1'),
('2', '任课老师', 'teacher', '查看自己的排课、今日课程和任教班级考勤', '1', '1'),
('3', '教务管理员', 'academic', '管理学生、班级、教师、全局排课和历史考勤', '1', '1'),
('4', '住宿运营管理员', 'accommodation_operations', '管理宿舍、入住、住宿费用、账单、押金和退宿结算', '1', '1'),
('5', '教室运营管理员', 'classroom_operations', '管理教室、教室排期、外部机构和租赁订单', '1', '1'),
('6', '系统管理员', 'system_admin', '管理账号、角色、日志、同步和系统配置', '1', '1')
ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `description` = VALUES(`description`), `is_system` = VALUES(`is_system`), `status` = VALUES(`status`);

INSERT IGNORE INTO `role_permissions` (`role_id`, `permission_id`) VALUES
('1', '1'),
('1', '2'),
('1', '3'),
('1', '4'),
('1', '5'),
('1', '6'),
('1', '7'),
('1', '8'),
('1', '9'),
('1', '10'),
('1', '11'),
('1', '12'),
('1', '13'),
('1', '14'),
('1', '15'),
('1', '16'),
('1', '17'),
('1', '18'),
('1', '19'),
('1', '20'),
('1', '21'),
('1', '22'),
('1', '23'),
('1', '24'),
('1', '25'),
('1', '26'),
('1', '27'),
('1', '28'),
('1', '29'),
('1', '30'),
('1', '31'),
('1', '32'),
('1', '33'),
('1', '34'),
('1', '35'),
('1', '36'),
('1', '37'),
('1', '38'),
('1', '39'),
('1', '40'),
('1', '41'),
('1', '42'),
('1', '43'),
('1', '44'),
('1', '45'),
('1', '46'),
('1', '47'),
('1', '48'),
('1', '49'),
('1', '50'),
('1', '51'),
('1', '52'),
('1', '53'),
('1', '54'),
('1', '55'),
('1', '56'),
('1', '57'),
('1', '58'),
('1', '59'),
('1', '60'),
('1', '61'),
('1', '62'),
('1', '63'),
('1', '64'),
('1', '65'),
('1', '66'),
('1', '67'),
('1', '68'),
('1', '69'),
('1', '70'),
('1', '71'),
('1', '72'),
('1', '73'),
('1', '74'),
('1', '75'),
('1', '76'),
('1', '77'),
('1', '78'),
('1', '79'),
('1', '80'),
('1', '81'),
('1', '82'),
('1', '83'),
('1', '84'),
('1', '85'),
('1', '86'),
('1', '87'),
('1', '88'),
('1', '89'),
('1', '90'),
('1', '91'),
('1', '92'),
('2', '6'),
('2', '67'),
('2', '71'),
('2', '72'),
('2', '74'),
('2', '2'),
('2', '3'),
('3', '6'),
('3', '7'),
('3', '8'),
('3', '84'),
('3', '83'),
('3', '1'),
('3', '2'),
('3', '3'),
('3', '4'),
('3', '9'),
('3', '10'),
('3', '11'),
('3', '12'),
('3', '13'),
('3', '40'),
('3', '41'),
('3', '42'),
('3', '43'),
('3', '63'),
('3', '64'),
('3', '65'),
('3', '66'),
('3', '67'),
('3', '68'),
('3', '69'),
('3', '70'),
('3', '71'),
('3', '72'),
('3', '73'),
('3', '75'),
('3', '76'),
('3', '77'),
('3', '78'),
('3', '79'),
('3', '80'),
('3', '81'),
('3', '82'),
('4', '5'),
('4', '1'),
('4', '2'),
('4', '3'),
('4', '14'),
('4', '15'),
('4', '16'),
('4', '17'),
('4', '18'),
('4', '19'),
('4', '20'),
('4', '21'),
('4', '22'),
('4', '23'),
('4', '24'),
('4', '25'),
('4', '26'),
('4', '27'),
('4', '28'),
('4', '29'),
('4', '30'),
('4', '31'),
('4', '32'),
('4', '33'),
('4', '34'),
('4', '35'),
('4', '36'),
('4', '37'),
('4', '38'),
('4', '39'),
('5', '2'),
('5', '3'),
('5', '40'),
('5', '41'),
('5', '42'),
('5', '43'),
('5', '44'),
('5', '45'),
('5', '46'),
('5', '47'),
('5', '48'),
('5', '49'),
('5', '50'),
('5', '51'),
('6', '2'),
('6', '3'),
('6', '52'),
('6', '53'),
('6', '54'),
('6', '55'),
('6', '56'),
('6', '57'),
('6', '58'),
('6', '59'),
('6', '60'),
('6', '61'),
('6', '62'),
('6', '83'),
('6', '84'),
('6', '85'),
('6', '86'),
('6', '87'),
('6', '88'),
('6', '89'),
('6', '90'),
('6', '91'),
('6', '92');

INSERT INTO `users` (`id`, `username`, `password_hash`, `name`, `is_active`, `is_archived`) VALUES
('1', 'admin', '$2b$10$vu8/qt4UCb6QnbmgQdbUtexPZWieuok030ZF0bI6xfpcf49MEML62', '管理员', '1', '0')
ON DUPLICATE KEY UPDATE `username` = `username`;
INSERT IGNORE INTO `user_roles` (`user_id`, `role_id`) VALUES (1, 1);

INSERT INTO `organizations` (`id`, `public_id`, `code`, `name`, `is_host`, `color`, `notes`, `status`) VALUES
('1', '01900000-0000-7000-8000-000000000001', 'HOST', '本机构', '1', '#1677ff', '系统默认运营主体', 'active')
ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `is_host` = VALUES(`is_host`), `status` = VALUES(`status`);

INSERT INTO `expense_types` (`code`, `name`, `category`, `sort_order`, `enabled`) VALUES
('water', '水费', 'room', '1', '1'),
('electricity', '电费', 'room', '2', '1'),
('cleaning', '保洁费', 'room', '3', '1'),
('damage', '损坏赔偿', 'both', '4', '1'),
('penalty', '罚款', 'personal', '5', '1'),
('key', '钥匙费', 'personal', '6', '1'),
('remote', '空调遥控器', 'personal', '7', '1'),
('deposit_deduction', '押金扣除', 'personal', '8', '1'),
('other', '其他', 'both', '99', '1')
ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `category` = VALUES(`category`), `sort_order` = VALUES(`sort_order`), `enabled` = VALUES(`enabled`);

INSERT INTO `ai_config` (`singleton_key`, `provider`, `enabled`, `timeout_ms`, `verified`) VALUES
('GLOBAL', 'OPENAI', '0', '30000', '0')
ON DUPLICATE KEY UPDATE `singleton_key` = `singleton_key`;

INSERT INTO `integration_config` (`id`, `type`, `is_sync`) VALUES
('1', 'THIRD', '0')
ON DUPLICATE KEY UPDATE `type` = VALUES(`type`);

-- 让后续 AUTO_INCREMENT 从安全位置继续。
ALTER TABLE `permissions` AUTO_INCREMENT = 1000;
ALTER TABLE `roles` AUTO_INCREMENT = 100;
ALTER TABLE `users` AUTO_INCREMENT = 100;
ALTER TABLE `organizations` AUTO_INCREMENT = 100;
ALTER TABLE `attendance_devices` AUTO_INCREMENT = 100;
