| 1 |
|
|---|
| 2 |
|
|---|
| 3 | DROP TABLE IF EXISTS Review CASCADE;
|
|---|
| 4 | DROP TABLE IF EXISTS AppointmentService CASCADE;
|
|---|
| 5 | DROP TABLE IF EXISTS PackageService CASCADE;
|
|---|
| 6 | DROP TABLE IF EXISTS UserRole CASCADE;
|
|---|
| 7 | DROP TABLE IF EXISTS Payment CASCADE;
|
|---|
| 8 | DROP TABLE IF EXISTS LoyaltyCard CASCADE;
|
|---|
| 9 | DROP TABLE IF EXISTS Appointment CASCADE;
|
|---|
| 10 | DROP TABLE IF EXISTS Service CASCADE;
|
|---|
| 11 | DROP TABLE IF EXISTS Package CASCADE;
|
|---|
| 12 | DROP TABLE IF EXISTS Status CASCADE;
|
|---|
| 13 | DROP TABLE IF EXISTS Category CASCADE;
|
|---|
| 14 | DROP TABLE IF EXISTS Role CASCADE;
|
|---|
| 15 | DROP TABLE IF EXISTS "User" CASCADE;
|
|---|
| 16 |
|
|---|
| 17 | DROP TYPE IF EXISTS appointment_type CASCADE;
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 | CREATE TYPE appointment_type AS ENUM ('pre-booked', 'walk-in');
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 | -- User table
|
|---|
| 25 | CREATE TABLE "User" (
|
|---|
| 26 | user_id SERIAL PRIMARY KEY,
|
|---|
| 27 | full_name VARCHAR(255) NOT NULL,
|
|---|
| 28 | email VARCHAR(255) NOT NULL UNIQUE,
|
|---|
| 29 | phone VARCHAR(20),
|
|---|
| 30 | created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|---|
| 31 | );
|
|---|
| 32 |
|
|---|
| 33 | -- Role table
|
|---|
| 34 | CREATE TABLE Role (
|
|---|
| 35 | role_id SERIAL PRIMARY KEY,
|
|---|
| 36 | name VARCHAR(100) NOT NULL UNIQUE
|
|---|
| 37 | );
|
|---|
| 38 |
|
|---|
| 39 | -- Category table
|
|---|
| 40 | CREATE TABLE Category (
|
|---|
| 41 | category_id SERIAL PRIMARY KEY,
|
|---|
| 42 | name VARCHAR(100) NOT NULL UNIQUE
|
|---|
| 43 | );
|
|---|
| 44 |
|
|---|
| 45 | -- Status table
|
|---|
| 46 | CREATE TABLE Status (
|
|---|
| 47 | status_id SERIAL PRIMARY KEY,
|
|---|
| 48 | name VARCHAR(50) NOT NULL UNIQUE
|
|---|
| 49 | );
|
|---|
| 50 |
|
|---|
| 51 | -- Service table
|
|---|
| 52 | CREATE TABLE Service (
|
|---|
| 53 | service_id SERIAL PRIMARY KEY,
|
|---|
| 54 | name VARCHAR(255) NOT NULL,
|
|---|
| 55 | price DECIMAL(10, 2) NOT NULL CHECK (price >= 0),
|
|---|
| 56 | duration_minutes INTEGER NOT NULL CHECK (duration_minutes > 0),
|
|---|
| 57 | category_id INTEGER NOT NULL,
|
|---|
| 58 | CONSTRAINT fk_service_category FOREIGN KEY (category_id)
|
|---|
| 59 | REFERENCES Category(category_id) ON DELETE RESTRICT
|
|---|
| 60 | );
|
|---|
| 61 |
|
|---|
| 62 | -- Package table
|
|---|
| 63 | CREATE TABLE Package (
|
|---|
| 64 | package_id SERIAL PRIMARY KEY,
|
|---|
| 65 | name VARCHAR(255) NOT NULL,
|
|---|
| 66 | max_usage INTEGER NOT NULL CHECK (max_usage > 0)
|
|---|
| 67 | );
|
|---|
| 68 |
|
|---|
| 69 | -- Appointment table
|
|---|
| 70 | CREATE TABLE Appointment (
|
|---|
| 71 | appointment_id SERIAL PRIMARY KEY,
|
|---|
| 72 | appointment_time TIMESTAMP NOT NULL,
|
|---|
| 73 | end_time TIMESTAMP NOT NULL,
|
|---|
| 74 | notes TEXT,
|
|---|
| 75 | type appointment_type NOT NULL,
|
|---|
| 76 | total_price DECIMAL(10, 2) NOT NULL CHECK (total_price >= 0),
|
|---|
| 77 | user_id INTEGER NOT NULL,
|
|---|
| 78 | status_id INTEGER NOT NULL,
|
|---|
| 79 | CONSTRAINT fk_appointment_user FOREIGN KEY (user_id)
|
|---|
| 80 | REFERENCES "User"(user_id) ON DELETE CASCADE,
|
|---|
| 81 | CONSTRAINT fk_appointment_status FOREIGN KEY (status_id)
|
|---|
| 82 | REFERENCES Status(status_id) ON DELETE RESTRICT,
|
|---|
| 83 | CONSTRAINT chk_appointment_times CHECK (end_time > appointment_time)
|
|---|
| 84 | );
|
|---|
| 85 |
|
|---|
| 86 | -- LoyaltyCard table
|
|---|
| 87 | CREATE TABLE LoyaltyCard (
|
|---|
| 88 | card_id SERIAL PRIMARY KEY,
|
|---|
| 89 | points INTEGER NOT NULL DEFAULT 0 CHECK (points >= 0),
|
|---|
| 90 | user_id INTEGER NOT NULL UNIQUE,
|
|---|
| 91 | CONSTRAINT fk_loyaltycard_user FOREIGN KEY (user_id)
|
|---|
| 92 | REFERENCES "User"(user_id) ON DELETE CASCADE
|
|---|
| 93 | );
|
|---|
| 94 |
|
|---|
| 95 | -- Payment table
|
|---|
| 96 | CREATE TABLE Payment (
|
|---|
| 97 | payment_id SERIAL PRIMARY KEY,
|
|---|
| 98 | amount DECIMAL(10, 2) NOT NULL CHECK (amount >= 0),
|
|---|
| 99 | method VARCHAR(50) NOT NULL,
|
|---|
| 100 | timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|---|
| 101 | status VARCHAR(50) NOT NULL,
|
|---|
| 102 | appointment_id INTEGER NOT NULL,
|
|---|
| 103 | CONSTRAINT fk_payment_appointment FOREIGN KEY (appointment_id)
|
|---|
| 104 | REFERENCES Appointment(appointment_id) ON DELETE CASCADE
|
|---|
| 105 | );
|
|---|
| 106 |
|
|---|
| 107 | -- Review table (with UNIQUE constraint on payment_id)
|
|---|
| 108 | CREATE TABLE Review (
|
|---|
| 109 | review_id SERIAL PRIMARY KEY,
|
|---|
| 110 | rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5),
|
|---|
| 111 | comment TEXT,
|
|---|
| 112 | created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|---|
| 113 | payment_id INTEGER NOT NULL UNIQUE,
|
|---|
| 114 | CONSTRAINT fk_review_payment FOREIGN KEY (payment_id)
|
|---|
| 115 | REFERENCES Payment(payment_id) ON DELETE CASCADE
|
|---|
| 116 | );
|
|---|
| 117 |
|
|---|
| 118 | -- UserRole table (junction table)
|
|---|
| 119 | CREATE TABLE UserRole (
|
|---|
| 120 | user_id INTEGER NOT NULL,
|
|---|
| 121 | role_id INTEGER NOT NULL,
|
|---|
| 122 | PRIMARY KEY (user_id, role_id),
|
|---|
| 123 | CONSTRAINT fk_userrole_user FOREIGN KEY (user_id)
|
|---|
| 124 | REFERENCES "User"(user_id) ON DELETE CASCADE,
|
|---|
| 125 | CONSTRAINT fk_userrole_role FOREIGN KEY (role_id)
|
|---|
| 126 | REFERENCES Role(role_id) ON DELETE CASCADE
|
|---|
| 127 | );
|
|---|
| 128 |
|
|---|
| 129 | -- PackageService table (junction table)
|
|---|
| 130 | CREATE TABLE PackageService (
|
|---|
| 131 | package_id INTEGER NOT NULL,
|
|---|
| 132 | service_id INTEGER NOT NULL,
|
|---|
| 133 | discounted_price DECIMAL(10, 2) NOT NULL CHECK (discounted_price >= 0),
|
|---|
| 134 | PRIMARY KEY (package_id, service_id),
|
|---|
| 135 | CONSTRAINT fk_packageservice_package FOREIGN KEY (package_id)
|
|---|
| 136 | REFERENCES Package(package_id) ON DELETE CASCADE,
|
|---|
| 137 | CONSTRAINT fk_packageservice_service FOREIGN KEY (service_id)
|
|---|
| 138 | REFERENCES Service(service_id) ON DELETE CASCADE
|
|---|
| 139 | );
|
|---|
| 140 |
|
|---|
| 141 | -- AppointmentService table (junction table)
|
|---|
| 142 | CREATE TABLE AppointmentService (
|
|---|
| 143 | appointment_id INTEGER NOT NULL,
|
|---|
| 144 | service_id INTEGER NOT NULL,
|
|---|
| 145 | PRIMARY KEY (appointment_id, service_id),
|
|---|
| 146 | CONSTRAINT fk_appointmentservice_appointment FOREIGN KEY (appointment_id)
|
|---|
| 147 | REFERENCES Appointment(appointment_id) ON DELETE CASCADE,
|
|---|
| 148 | CONSTRAINT fk_appointmentservice_service FOREIGN KEY (service_id)
|
|---|
| 149 | REFERENCES Service(service_id) ON DELETE CASCADE
|
|---|
| 150 | );
|
|---|
| 151 |
|
|---|
| 152 |
|
|---|
| 153 |
|
|---|
| 154 | CREATE INDEX idx_appointment_user ON Appointment(user_id);
|
|---|
| 155 | CREATE INDEX idx_appointment_status ON Appointment(status_id);
|
|---|
| 156 | CREATE INDEX idx_appointment_time ON Appointment(appointment_time);
|
|---|
| 157 | CREATE INDEX idx_payment_appointment ON Payment(appointment_id);
|
|---|
| 158 | CREATE INDEX idx_service_category ON Service(category_id);
|
|---|
| 159 | CREATE INDEX idx_user_email ON "User"(email);
|
|---|