CREATE TABLE services ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), executor_id UUID NOT NULL REFERENCES users(id), title VARCHAR(255) NOT NULL, description TEXT, price INT NOT NULL, currency VARCHAR(3) DEFAULT 'RUB', duration_minutes INT, status VARCHAR(20) NOT NULL DEFAULT 'published' CHECK (status IN ('draft', 'published', 'archived')), rating DECIMAL(2,1) DEFAULT 0, reviews_count INT DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ ); CREATE INDEX idx_services_executor_id ON services(executor_id); CREATE INDEX idx_services_status ON services(status); CREATE INDEX idx_services_rating ON services(rating); CREATE TABLE service_images ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), service_id UUID NOT NULL REFERENCES services(id) ON DELETE CASCADE, url TEXT NOT NULL, alt VARCHAR(255), sort_order INT DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX idx_service_images_service_id ON service_images(service_id); CREATE TABLE service_tags ( service_id UUID NOT NULL REFERENCES services(id) ON DELETE CASCADE, tag_id VARCHAR(50) NOT NULL REFERENCES tags(id), PRIMARY KEY (service_id, tag_id) ); CREATE TABLE reviews ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id), target_type VARCHAR(10) NOT NULL CHECK (target_type IN ('place', 'service')), target_id UUID NOT NULL, rating SMALLINT NOT NULL CHECK (rating >= 1 AND rating <= 5), text TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ, UNIQUE (user_id, target_type, target_id) ); CREATE INDEX idx_reviews_target ON reviews(target_type, target_id); CREATE INDEX idx_reviews_user_id ON reviews(user_id); CREATE TABLE bookings ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), place_id UUID NOT NULL REFERENCES places(id), user_id UUID NOT NULL REFERENCES users(id), start_time TIMESTAMPTZ NOT NULL, end_time TIMESTAMPTZ NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'confirmed', 'cancelled', 'completed')), total_price INT, currency VARCHAR(3) DEFAULT 'RUB', comment TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX idx_bookings_place_id ON bookings(place_id); CREATE INDEX idx_bookings_user_id ON bookings(user_id); CREATE INDEX idx_bookings_time ON bookings(start_time, end_time);