Major UX improvements across multiple pages
Шахматка: - Date/period picker dropdown on navigation button (choose start date + days window) - Cancelled bookings fade out with animation after 1 second Бронирования: - Clickable column headers with sort asc/desc (Гость, Заезд, Выезд, Статус, Источник, Сумма) Страница входа: - Removed role-based account selector — just email + password - System auto-detects role/hotel from credentials Настройки: - New "Бронирование" section with room assignment strategy (spread/together/sequential/manual) - Notifications: SMTP email config + SMS provider config (SMSC, SMS.ru, МТС, etc.) Модули: - Added Housekeeping and Channel Manager as proper modules - Channel Manager lists: Booking.com, Airbnb, Яндекс Путешествия, Островок, Суточно.ру, OneTwoTrip - Housekeeping visible to all roles (including housekeeper) via module status - Sidebar now uses module status to show/hide Уборка and Каналы Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
109
backend/migrations/001_schema.sql
Normal file
109
backend/migrations/001_schema.sql
Normal file
@@ -0,0 +1,109 @@
|
||||
-- HotelSync Database Schema
|
||||
-- Migration 001 — Initial Schema
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
||||
|
||||
-- ── Hotels ─────────────────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS hotels (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
slug VARCHAR(100) NOT NULL UNIQUE,
|
||||
plan VARCHAR(20) NOT NULL DEFAULT 'starter'
|
||||
CHECK (plan IN ('starter', 'pro', 'enterprise')),
|
||||
timezone VARCHAR(50) NOT NULL DEFAULT 'Europe/Moscow',
|
||||
currency VARCHAR(3) NOT NULL DEFAULT 'RUB',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ── Users ──────────────────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
hotel_id UUID REFERENCES hotels(id) ON DELETE SET NULL,
|
||||
email VARCHAR(255) NOT NULL UNIQUE,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(20) NOT NULL DEFAULT 'manager'
|
||||
CHECK (role IN ('manager', 'housekeeper', 'super_admin')),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ── Rooms ──────────────────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS rooms (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
hotel_id UUID NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
|
||||
number VARCHAR(20) NOT NULL,
|
||||
type VARCHAR(50) NOT NULL,
|
||||
floor INTEGER NOT NULL DEFAULT 1,
|
||||
capacity INTEGER NOT NULL DEFAULT 2,
|
||||
price_per_night DECIMAL(10,2) NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'clean'
|
||||
CHECK (status IN ('clean', 'dirty', 'maintenance', 'out_of_order')),
|
||||
amenities TEXT[] NOT NULL DEFAULT '{}',
|
||||
notes TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE(hotel_id, number)
|
||||
);
|
||||
|
||||
-- ── Bookings ───────────────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS bookings (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
hotel_id UUID NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
|
||||
room_id UUID NOT NULL REFERENCES rooms(id),
|
||||
guest_name VARCHAR(255) NOT NULL,
|
||||
guest_email VARCHAR(255),
|
||||
guest_phone VARCHAR(50),
|
||||
check_in DATE NOT NULL,
|
||||
check_out DATE NOT NULL,
|
||||
adults INTEGER NOT NULL DEFAULT 1,
|
||||
children INTEGER NOT NULL DEFAULT 0,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'confirmed'
|
||||
CHECK (status IN ('confirmed', 'checked_in', 'checked_out', 'cancelled', 'no_show')),
|
||||
source VARCHAR(20) NOT NULL DEFAULT 'direct'
|
||||
CHECK (source IN ('direct', 'booking_com', 'airbnb', 'expedia', 'vrbo')),
|
||||
total_amount DECIMAL(10,2),
|
||||
notes TEXT,
|
||||
external_id VARCHAR(255),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ── Housekeeping Tasks ─────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS housekeeping_tasks (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
hotel_id UUID NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
|
||||
room_id UUID REFERENCES rooms(id) ON DELETE SET NULL,
|
||||
type VARCHAR(30) NOT NULL DEFAULT 'cleaning'
|
||||
CHECK (type IN ('cleaning', 'turnover', 'inspection', 'maintenance', 'amenities')),
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending'
|
||||
CHECK (status IN ('pending', 'in_progress', 'done', 'skipped')),
|
||||
priority VARCHAR(10) NOT NULL DEFAULT 'medium'
|
||||
CHECK (priority IN ('low', 'medium', 'high', 'urgent')),
|
||||
assignee_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
notes TEXT,
|
||||
due_date DATE,
|
||||
completed_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ── Channels ───────────────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS channels (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
hotel_id UUID NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
|
||||
name VARCHAR(50) NOT NULL
|
||||
CHECK (name IN ('booking_com', 'airbnb', 'expedia', 'vrbo')),
|
||||
enabled BOOLEAN NOT NULL DEFAULT false,
|
||||
api_key_encrypted TEXT,
|
||||
hotel_external_id VARCHAR(255),
|
||||
last_synced_at TIMESTAMPTZ,
|
||||
UNIQUE(hotel_id, name)
|
||||
);
|
||||
|
||||
-- ── Indexes ────────────────────────────────────────────────────────────────
|
||||
CREATE INDEX IF NOT EXISTS idx_bookings_hotel_dates ON bookings(hotel_id, check_in, check_out);
|
||||
CREATE INDEX IF NOT EXISTS idx_bookings_room ON bookings(room_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_rooms_hotel ON rooms(hotel_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_tasks_hotel ON housekeeping_tasks(hotel_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_hotel ON users(hotel_id);
|
||||
Reference in New Issue
Block a user