Files
tourrism_site/database/schema.sql
Andrey K. Choi 409e6c146b Initial commit: Korea Tourism Agency website with AdminJS
- Full-stack Node.js/Express application with PostgreSQL
- Modern ES modules architecture
- AdminJS admin panel with Sequelize ORM
- Tourism routes, guides, articles, bookings management
- Responsive Bootstrap 5 frontend
- Docker containerization with docker-compose
- Complete database schema with migrations
- Authentication system for admin panel
- Dynamic placeholder images for tour categories
2025-11-29 18:13:17 +09:00

155 lines
6.3 KiB
PL/PgSQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 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();