| 1 | DROP SCHEMA IF EXISTS project CASCADE;
|
|---|
| 2 | CREATE SCHEMA project;
|
|---|
| 3 | SET search_path TO project;
|
|---|
| 4 |
|
|---|
| 5 | CREATE TABLE user_types (
|
|---|
| 6 | type_id SERIAL PRIMARY KEY,
|
|---|
| 7 | type_name VARCHAR(128) NOT NULL UNIQUE,
|
|---|
| 8 | description VARCHAR(256) NOT NULL
|
|---|
| 9 | );
|
|---|
| 10 |
|
|---|
| 11 | CREATE TABLE users (
|
|---|
| 12 | user_id SERIAL PRIMARY KEY,
|
|---|
| 13 | first_name VARCHAR(128) NOT NULL,
|
|---|
| 14 | last_name VARCHAR(128) NOT NULL,
|
|---|
| 15 | email VARCHAR(128) NOT NULL UNIQUE,
|
|---|
| 16 | password VARCHAR(128) NOT NULL,
|
|---|
| 17 | type_id INTEGER NOT NULL REFERENCES user_types(type_id) ON UPDATE CASCADE ON DELETE RESTRICT
|
|---|
| 18 | );
|
|---|
| 19 |
|
|---|
| 20 | CREATE INDEX idx_users_email ON users(email);
|
|---|
| 21 | CREATE INDEX idx_users_type ON users(type_id);
|
|---|
| 22 |
|
|---|
| 23 | CREATE TABLE resource_types (
|
|---|
| 24 | type_id SERIAL PRIMARY KEY,
|
|---|
| 25 | type_name VARCHAR(128) NOT NULL UNIQUE,
|
|---|
| 26 | is_physical BOOLEAN NOT NULL
|
|---|
| 27 | );
|
|---|
| 28 |
|
|---|
| 29 | CREATE TABLE locations (
|
|---|
| 30 | location_id SERIAL PRIMARY KEY,
|
|---|
| 31 | building VARCHAR(128) NOT NULL,
|
|---|
| 32 | room VARCHAR(128) NOT NULL,
|
|---|
| 33 | UNIQUE (building, room)
|
|---|
| 34 | );
|
|---|
| 35 |
|
|---|
| 36 | CREATE INDEX idx_locations_building ON locations(building);
|
|---|
| 37 |
|
|---|
| 38 | CREATE TABLE resources (
|
|---|
| 39 | resource_id SERIAL PRIMARY KEY,
|
|---|
| 40 | name VARCHAR(128) NOT NULL,
|
|---|
| 41 | description VARCHAR(512) NOT NULL,
|
|---|
| 42 | available_from TIME NOT NULL DEFAULT '08:00',
|
|---|
| 43 | available_to TIME NOT NULL DEFAULT '20:00',
|
|---|
| 44 | available_weekends BOOLEAN NOT NULL DEFAULT FALSE,
|
|---|
| 45 | type_id INTEGER NOT NULL REFERENCES resource_types(type_id) ON UPDATE CASCADE ON DELETE RESTRICT,
|
|---|
| 46 | location_id INTEGER NULL REFERENCES locations(location_id) ON UPDATE CASCADE ON DELETE SET NULL,
|
|---|
| 47 | CHECK (available_to > available_from)
|
|---|
| 48 | );
|
|---|
| 49 |
|
|---|
| 50 | CREATE INDEX idx_resources_type ON resources(type_id);
|
|---|
| 51 | CREATE INDEX idx_resources_location ON resources(location_id);
|
|---|
| 52 |
|
|---|
| 53 | CREATE TABLE reservations (
|
|---|
| 54 | reservation_id SERIAL PRIMARY KEY,
|
|---|
| 55 | start_time TIMESTAMP NOT NULL,
|
|---|
| 56 | end_time TIMESTAMP NOT NULL,
|
|---|
| 57 | status VARCHAR(32) NOT NULL DEFAULT 'pending',
|
|---|
| 58 | purpose VARCHAR(512) NOT NULL,
|
|---|
| 59 | created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|---|
| 60 | recurrence_group_id UUID NULL,
|
|---|
| 61 | user_id INTEGER NOT NULL REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE RESTRICT,
|
|---|
| 62 | approved_by INTEGER NULL REFERENCES users(user_id) ON UPDATE CASCADE ON DELETE SET NULL,
|
|---|
| 63 | resource_id INTEGER NOT NULL REFERENCES resources(resource_id) ON UPDATE CASCADE ON DELETE RESTRICT,
|
|---|
| 64 | CHECK (end_time > start_time),
|
|---|
| 65 | CHECK (status IN ('pending', 'approved', 'rejected', 'completed', 'cancelled'))
|
|---|
| 66 | );
|
|---|
| 67 |
|
|---|
| 68 | CREATE INDEX idx_reservations_user ON reservations(user_id);
|
|---|
| 69 | CREATE INDEX idx_reservations_approver ON reservations(approved_by);
|
|---|
| 70 | CREATE INDEX idx_reservations_resource ON reservations(resource_id);
|
|---|
| 71 | CREATE INDEX idx_reservations_status ON reservations(status);
|
|---|
| 72 | CREATE INDEX idx_reservations_times ON reservations(start_time, end_time);
|
|---|
| 73 | CREATE INDEX idx_reservations_recurrence ON reservations(recurrence_group_id) WHERE recurrence_group_id IS NOT NULL;
|
|---|