-- Korea Tourism Agency Database Schema -- Создание основных таблиц для туристического агентства CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- Таблица администраторов CREATE TABLE IF NOT EXISTS admins ( id SERIAL PRIMARY KEY, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, name VARCHAR(100) NOT NULL, email VARCHAR(100) UNIQUE NOT NULL, role VARCHAR(20) DEFAULT 'admin', is_active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Таблица гидов CREATE TABLE IF NOT EXISTS guides ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(100) UNIQUE, phone VARCHAR(20), bio TEXT, specialization VARCHAR(20) NOT NULL CHECK (specialization IN ('city', 'mountain', 'fishing')), languages TEXT[], -- Массив языков experience INTEGER DEFAULT 0, -- Опыт в годах image_url VARCHAR(255), hourly_rate DECIMAL(8,2), is_active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Таблица маршрутов/туров CREATE TABLE IF NOT EXISTS routes ( id SERIAL PRIMARY KEY, title VARCHAR(200) NOT NULL, description TEXT NOT NULL, content TEXT, -- Полное описание type VARCHAR(20) NOT NULL CHECK (type IN ('city', 'mountain', 'fishing')), price DECIMAL(10,2) NOT NULL, duration INTEGER NOT NULL, -- Длительность в часах difficulty_level VARCHAR(10) DEFAULT 'easy' CHECK (difficulty_level IN ('easy', 'moderate', 'hard')), max_group_size INTEGER DEFAULT 10, included_services TEXT[], meeting_point TEXT, image_url VARCHAR(255), guide_id INTEGER REFERENCES guides(id), is_featured BOOLEAN DEFAULT false, is_active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Таблица статей CREATE TABLE IF NOT EXISTS articles ( id SERIAL PRIMARY KEY, title VARCHAR(200) NOT NULL, excerpt TEXT, content TEXT NOT NULL, category VARCHAR(50) NOT NULL CHECK (category IN ('travel-tips', 'culture', 'food', 'nature', 'history')), image_url VARCHAR(255), author_id INTEGER REFERENCES admins(id), views INTEGER DEFAULT 0, is_published BOOLEAN DEFAULT false, meta_description TEXT, meta_keywords TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Таблица бронирований CREATE TABLE IF NOT EXISTS bookings ( id SERIAL PRIMARY KEY, route_id INTEGER REFERENCES routes(id) NOT NULL, guide_id INTEGER REFERENCES guides(id), customer_name VARCHAR(100) NOT NULL, customer_email VARCHAR(100) NOT NULL, customer_phone VARCHAR(20), preferred_date DATE, group_size INTEGER DEFAULT 1, total_price DECIMAL(10,2), special_requirements TEXT, status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'confirmed', 'cancelled', 'completed')), notes TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Таблица отзывов CREATE TABLE IF NOT EXISTS reviews ( id SERIAL PRIMARY KEY, route_id INTEGER REFERENCES routes(id), guide_id INTEGER REFERENCES guides(id), booking_id INTEGER REFERENCES bookings(id), customer_name VARCHAR(100) NOT NULL, customer_email VARCHAR(100), rating INTEGER CHECK (rating >= 1 AND rating <= 5) NOT NULL, comment TEXT, is_approved BOOLEAN DEFAULT false, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Таблица сообщений с формы контактов CREATE TABLE IF NOT EXISTS contact_messages ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(100) NOT NULL, phone VARCHAR(20), subject VARCHAR(200), message TEXT NOT NULL, status VARCHAR(20) DEFAULT 'unread' CHECK (status IN ('unread', 'read', 'replied')), admin_notes TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Таблица настроек сайта CREATE TABLE IF NOT EXISTS site_settings ( id SERIAL PRIMARY KEY, setting_key VARCHAR(100) UNIQUE NOT NULL, setting_value TEXT, setting_type VARCHAR(20) DEFAULT 'text' CHECK (setting_type IN ('text', 'number', 'boolean', 'json')), description TEXT, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Создание индексов для производительности CREATE INDEX IF NOT EXISTS idx_routes_type ON routes(type); CREATE INDEX IF NOT EXISTS idx_routes_active ON routes(is_active); CREATE INDEX IF NOT EXISTS idx_routes_featured ON routes(is_featured); CREATE INDEX IF NOT EXISTS idx_guides_specialization ON guides(specialization); CREATE INDEX IF NOT EXISTS idx_guides_active ON guides(is_active); CREATE INDEX IF NOT EXISTS idx_articles_category ON articles(category); CREATE INDEX IF NOT EXISTS idx_articles_published ON articles(is_published); CREATE INDEX IF NOT EXISTS idx_bookings_status ON bookings(status); CREATE INDEX IF NOT EXISTS idx_bookings_date ON bookings(preferred_date); CREATE INDEX IF NOT EXISTS idx_reviews_rating ON reviews(rating); -- Создание триггеров для автоматического обновления updated_at CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = CURRENT_TIMESTAMP; RETURN NEW; END; $$ language 'plpgsql'; CREATE TRIGGER update_admins_updated_at BEFORE UPDATE ON admins FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_guides_updated_at BEFORE UPDATE ON guides FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_routes_updated_at BEFORE UPDATE ON routes FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_articles_updated_at BEFORE UPDATE ON articles FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_bookings_updated_at BEFORE UPDATE ON bookings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_site_settings_updated_at BEFORE UPDATE ON site_settings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();