Files
survey/database.sql

146 lines
6.2 KiB
SQL

-- ============================================================
-- 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`);