| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- CREATE TABLE TourFirm (
- firm_id SERIAL PRIMARY KEY,
- firm_name VARCHAR(100) NOT NULL,
- people_count INT NOT NULL CHECK (people_count > 0)
- );
- CREATE TABLE RoomType (
- room_type_id SERIAL PRIMARY KEY,
- type_name VARCHAR(50) NOT NULL UNIQUE
- );
- CREATE TABLE Room (
- room_id SERIAL PRIMARY KEY,
- room_type_id INT NOT NULL REFERENCES RoomType(room_type_id)
- ON DELETE RESTRICT ON UPDATE CASCADE,
- room_number INT NOT NULL UNIQUE CHECK (room_number > 0),
- occupancy INT NOT NULL CHECK (occupancy > 0),
- rating DECIMAL(3,1) NOT NULL DEFAULT 0.0
- CHECK (rating >= 0.0 AND rating <= 5.0)
- );
- CREATE TABLE Client (
- client_id SERIAL PRIMARY KEY,
- firm_id INT NOT NULL REFERENCES TourFirm(firm_id)
- ON DELETE RESTRICT ON UPDATE CASCADE,
- last_name VARCHAR(60) NOT NULL,
- first_name VARCHAR(60) NOT NULL,
- patronymic VARCHAR(60),
- phone_number VARCHAR(20) NOT NULL
- );
- CREATE TABLE Booking (
- booking_id SERIAL PRIMARY KEY,
- client_id INT NOT NULL REFERENCES Client(client_id)
- ON DELETE RESTRICT ON UPDATE CASCADE,
- room_id INT NOT NULL REFERENCES Room(room_id)
- ON DELETE RESTRICT ON UPDATE CASCADE,
- check_in_date DATE NOT NULL,
- check_out_date DATE NOT NULL,
- price_per_night DECIMAL(10,2) NOT NULL CHECK (price_per_night > 0),s
- CHECK (check_out_date > check_in_date)
- );
- CREATE TABLE Service (
- service_id SERIAL PRIMARY KEY,
- service_name VARCHAR(100) NOT NULL UNIQUE
- );
- CREATE TABLE RoomTypeService (
- room_type_id INT NOT NULL REFERENCES RoomType(room_type_id)
- ON DELETE RESTRICT ON UPDATE CASCADE,
- service_id INT NOT NULL REFERENCES Service(service_id)
- ON DELETE RESTRICT ON UPDATE CASCADE,
- PRIMARY KEY (room_type_id, service_id)
- );
- SELECT * FROM booking
- --Расчетный атрибут — итоговая стоимость бронирования
- --total_cost = price_per_night * (check_out_date - check_in_date)
-
- CREATE OR REPLACE VIEW BookingCostView AS
- SELECT
- b.booking_id,
- c.last_name || ' ' || c.first_name || ' ' || COALESCE(c.patronymic, '') AS client_full_name,
- r.room_number,
- rt.type_name AS room_type,
- b.check_in_date,
- b.check_out_date,
- (b.check_out_date - b.check_in_date) AS nights,
- b.price_per_night,
- b.price_per_night * (b.check_out_date - b.check_in_date) AS total_cost
- FROM Booking b
- JOIN Client c ON c.client_id = b.client_id
- JOIN Room r ON r.room_id = b.room_id
- JOIN RoomType rt ON rt.room_type_id = r.room_type_id;
- --Проверочный запрос
- SELECT * FROM BookingCostView ORDER BY total_cost DESC LIMIT 10;
- --Возвращает итоговую стоимость конкретного бронирования
- --Использование в приложении: при отображении карточки брони
- CREATE OR REPLACE FUNCTION get_booking_cost(p_booking_id INT)
- RETURNS DECIMAL(10,2)
- LANGUAGE plpgsql
- AS $$
- DECLARE
- v_cost DECIMAL(10,2);
- BEGIN
- SELECT price_per_night * (check_out_date - check_in_date)
- INTO v_cost
- FROM Booking
- WHERE booking_id = p_booking_id;
- IF NOT FOUND THEN
- RAISE EXCEPTION 'Бронирование с ID % не найдено', p_booking_id;
- END IF;
- RETURN v_cost;
- END;
- $$;
- SELECT get_booking_cost(2);
- -- Создаёт новое бронирование
- CREATE OR REPLACE PROCEDURE create_booking(
- p_client_id INT,
- p_room_id INT,
- p_check_in_date DATE,
- p_check_out_date DATE,
- p_price_per_night DECIMAL(10,2)
- )
- LANGUAGE plpgsql
- AS $$
- BEGIN
- IF p_check_out_date <= p_check_in_date THEN
- RAISE EXCEPTION 'Дата выезда должна быть позже даты заезда';
- END IF;
-
- IF NOT EXISTS (SELECT 1 FROM Client WHERE client_id = p_client_id) THEN
- RAISE EXCEPTION 'Клиент с ID % не найден', p_client_id;
- END IF;
- IF NOT EXISTS (SELECT 1 FROM Room WHERE room_id = p_room_id) THEN
- RAISE EXCEPTION 'Комната с ID % не найдена', p_room_id;
- END IF;
-
- IF EXISTS (
- SELECT 1 FROM Booking
- WHERE room_id = p_room_id
- AND check_in_date < p_check_out_date
- AND check_out_date > p_check_in_date
- ) THEN
- RAISE EXCEPTION 'Комната % уже забронирована на указанные даты', p_room_id;
- END IF;
-
- INSERT INTO Booking (client_id, room_id, check_in_date, check_out_date, price_per_night)
- VALUES (p_client_id, p_room_id, p_check_in_date, p_check_out_date, p_price_per_night);
-
- RAISE NOTICE 'Бронирование успешно создано для клиента ID %', p_client_id;
- END;
- $$;
- CALL create_booking(3, 5, '2026-03-01', '2026-03-014', 2500.00);
- SELECT setval('tourfirm_firm_id_seq', (SELECT MAX(firm_id) FROM TourFirm));
- SELECT setval('client_client_id_seq', (SELECT MAX(client_id) FROM Client));
- SELECT setval('room_room_id_seq', (SELECT MAX(room_id) FROM Room));
- SELECT setval('roomtype_room_type_id_seq',(SELECT MAX(room_type_id) FROM RoomType));
- SELECT setval('service_service_id_seq', (SELECT MAX(service_id) FROM Service));
- SELECT setval('booking_booking_id_seq', (SELECT MAX(booking_id) FROM Booking));
- --Логирование бронирований
- CREATE TABLE AuditLog (
- log_id SERIAL PRIMARY KEY,
- tbl_name VARCHAR(50),
- action VARCHAR(10),
- changed_at TIMESTAMP DEFAULT NOW(),
- old_data JSONB,
- new_data JSONB
- );
- CREATE OR REPLACE FUNCTION audit_booking()
- RETURNS TRIGGER LANGUAGE plpgsql AS $$
- BEGIN
- INSERT INTO AuditLog (tbl_name, action, old_data, new_data)
- VALUES (
- TG_TABLE_NAME, TG_OP,
- CASE WHEN TG_OP = 'DELETE' THEN row_to_json(OLD)::jsonb ELSE NULL END,
- CASE WHEN TG_OP != 'DELETE' THEN row_to_json(NEW)::jsonb ELSE NULL END
- );
- RETURN NEW;
- END;
- $$;
- CREATE TRIGGER trg_audit_booking
- AFTER INSERT OR UPDATE OR DELETE ON Booking
- FOR EACH ROW EXECUTE FUNCTION audit_booking();
|