-- ============================================================ -- TPU Survey Database Schema -- ระบบประเมินความพึงพอใจ -- ============================================================ CREATE DATABASE IF NOT EXISTS `tpu_survey_v2` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE `tpu_survey_v2`; -- ============================================================ -- Users Table (Admin & Teacher) -- ============================================================ CREATE TABLE IF NOT EXISTS `users` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `username` VARCHAR(100) NOT NULL UNIQUE, `password_hash` VARCHAR(255) NOT NULL, `role` ENUM('admin', 'teacher') NOT NULL DEFAULT 'teacher', `full_name` VARCHAR(255) NOT NULL, `personnel_code` VARCHAR(50) DEFAULT NULL, `subject_area` VARCHAR(255) DEFAULT NULL, `branch_code` VARCHAR(50) DEFAULT NULL, `email` VARCHAR(255) DEFAULT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB; -- Insert default admin (username=admin, password=admin) INSERT INTO `users` (`username`, `password_hash`, `role`, `full_name`) VALUES ('admin', '$2y$10$ccniLtM2Y/Bx.xW/Q/msMuBYvtScKJcGdUder0nqSKT1WYx2iJHQ6', 'admin', 'ผู้ดูแลระบบ'); -- ============================================================ -- Projects Table -- ============================================================ CREATE TABLE IF NOT EXISTS `projects` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `user_id` INT NOT NULL, `title` VARCHAR(500) NOT NULL, `code` VARCHAR(100) DEFAULT NULL, `description` TEXT DEFAULT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB; -- ============================================================ -- Surveys Table -- ============================================================ CREATE TABLE IF NOT EXISTS `surveys` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `project_id` INT DEFAULT NULL, `user_id` INT NOT NULL, `title` VARCHAR(500) NOT NULL, `description` TEXT DEFAULT NULL, `status` ENUM('draft', 'active', 'closed') NOT NULL DEFAULT 'draft', `has_certificate` TINYINT(1) DEFAULT 0, `certificate_template` VARCHAR(255) DEFAULT NULL, `cert_name_y` DOUBLE DEFAULT 82.5, `cert_code_y` DOUBLE DEFAULT 190.5, `unique_link` VARCHAR(64) NOT NULL UNIQUE, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (`project_id`) REFERENCES `projects`(`id`) ON DELETE SET NULL, FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB; -- ============================================================ -- Survey Sections (Part 1, 2, 3) -- ============================================================ CREATE TABLE IF NOT EXISTS `survey_sections` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `survey_id` INT NOT NULL, `section_number` INT NOT NULL, `title` VARCHAR(255) NOT NULL, `description` TEXT DEFAULT NULL, `category` VARCHAR(50) DEFAULT 'rating', FOREIGN KEY (`survey_id`) REFERENCES `surveys`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB; -- ============================================================ -- Survey Headings (Sub-headings within sections) -- ============================================================ CREATE TABLE IF NOT EXISTS `survey_headings` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `section_id` INT NOT NULL, `title` VARCHAR(255) NOT NULL, `description` TEXT DEFAULT NULL, `order_num` INT NOT NULL DEFAULT 0, FOREIGN KEY (`section_id`) REFERENCES `survey_sections`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB; -- ============================================================ -- Survey Questions -- ============================================================ CREATE TABLE IF NOT EXISTS `survey_questions` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `section_id` INT NOT NULL, `heading_id` INT DEFAULT NULL, `question_text` TEXT NOT NULL, `question_type` ENUM('radio', 'text', 'dropdown', 'checkbox') NOT NULL DEFAULT 'radio', `is_required` TINYINT(1) DEFAULT 1, `order_num` INT NOT NULL DEFAULT 0, `options` JSON DEFAULT NULL, `scale_min` INT DEFAULT 1, `scale_max` INT DEFAULT 5, `description` TEXT DEFAULT NULL, FOREIGN KEY (`section_id`) REFERENCES `survey_sections`(`id`) ON DELETE CASCADE, FOREIGN KEY (`heading_id`) REFERENCES `survey_headings`(`id`) ON DELETE SET NULL ) ENGINE=InnoDB; -- ============================================================ -- Survey Responses (one per respondent submission) -- ============================================================ CREATE TABLE IF NOT EXISTS `survey_responses` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `survey_id` INT NOT NULL, `respondent_info` JSON DEFAULT NULL, `cert_code` VARCHAR(32) UNIQUE DEFAULT NULL, `ip_address` VARCHAR(45) DEFAULT NULL, `submitted_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (`survey_id`) REFERENCES `surveys`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB; -- ============================================================ -- Response Answers (individual answers) -- ============================================================ CREATE TABLE IF NOT EXISTS `response_answers` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `response_id` INT NOT NULL, `question_id` INT NOT NULL, `answer_value` TEXT DEFAULT NULL, FOREIGN KEY (`response_id`) REFERENCES `survey_responses`(`id`) ON DELETE CASCADE, FOREIGN KEY (`question_id`) REFERENCES `survey_questions`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB; -- ============================================================ -- Indexes for performance -- ============================================================ CREATE INDEX idx_surveys_link ON `surveys`(`unique_link`); CREATE INDEX idx_responses_survey ON `survey_responses`(`survey_id`); CREATE INDEX idx_answers_response ON `response_answers`(`response_id`); CREATE INDEX idx_answers_question ON `response_answers`(`question_id`); CREATE INDEX idx_headings_section ON `survey_headings`(`section_id`); CREATE INDEX idx_questions_heading ON `survey_questions`(`heading_id`);