много всего и тестовые данные
This commit is contained in:
@@ -19,11 +19,6 @@ CREATE TABLE IF NOT EXISTS departments (
|
||||
archive_reason TEXT
|
||||
);
|
||||
|
||||
INSERT INTO departments (name, code) VALUES
|
||||
('Кафедра ИБ', 1),
|
||||
('Кафедра ВТ', 2),
|
||||
('Кафедра КТ', 3);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS specialties (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
@@ -36,12 +31,6 @@ CREATE TABLE IF NOT EXISTS specialties (
|
||||
archive_reason TEXT
|
||||
);
|
||||
|
||||
INSERT INTO specialties (name, specialty_code) VALUES
|
||||
('Информационная безопасность', '10.03.01'),
|
||||
('Информатика и вычислительная техника', '09.03.01'),
|
||||
('Программная инженерия', '09.03.04')
|
||||
ON CONFLICT (specialty_code) DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS specialty_profiles (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
specialty_id BIGINT NOT NULL REFERENCES specialties(id) ON DELETE CASCADE,
|
||||
@@ -57,11 +46,6 @@ CREATE TABLE IF NOT EXISTS specialty_profiles (
|
||||
CONSTRAINT uq_specialty_profiles_name UNIQUE (specialty_id, name)
|
||||
);
|
||||
|
||||
INSERT INTO specialty_profiles (specialty_id, name)
|
||||
SELECT id, 'Без профиля'
|
||||
FROM specialties
|
||||
ON CONFLICT (specialty_id, name) DO NOTHING;
|
||||
|
||||
-- ==========================================
|
||||
-- Пользователи и роли
|
||||
-- ==========================================
|
||||
@@ -83,15 +67,6 @@ CREATE TABLE IF NOT EXISTS users (
|
||||
archive_reason TEXT
|
||||
);
|
||||
|
||||
-- Админ по умолчанию: admin / admin (bcrypt через pgcrypto)
|
||||
INSERT INTO users (username, password, role, full_name, job_title, department_id)
|
||||
VALUES ('admin', crypt('admin', gen_salt('bf', 10)), 'ADMIN', 'Иванов Админ Иванович', 'Доцент', 1),
|
||||
('Тестовый преподаватель', crypt('1234567890', gen_salt('bf', 10)), 'TEACHER', 'Петров Препод Петрович', 'Профессор', 2),
|
||||
('учебный_отдел', crypt('1234567890', gen_salt('bf', 10)), 'EDUCATION_OFFICE', 'Оператор учебного отдела', 'Учебный отдел', 1),
|
||||
('кафедра_иб', crypt('1234567890', gen_salt('bf', 10)), 'DEPARTMENT', 'Оператор кафедры ИБ', 'Кафедра', 1),
|
||||
('просмотр_расписаний', crypt('1234567890', gen_salt('bf', 10)), 'SCHEDULE_VIEWER', 'Оператор просмотра расписаний', 'Просмотр расписаний', 1)
|
||||
ON CONFLICT (username) DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS auth_refresh_tokens (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
@@ -189,16 +164,6 @@ CREATE UNIQUE INDEX IF NOT EXISTS uq_teacher_department_open_pair
|
||||
ON teacher_department_assignments(teacher_id, department_id)
|
||||
WHERE valid_to IS NULL;
|
||||
|
||||
INSERT INTO teacher_department_assignments (teacher_id, department_id, valid_from, is_primary, comment)
|
||||
SELECT u.id, u.department_id, COALESCE(u.created_at::DATE, CURRENT_DATE), TRUE, 'Начальная кафедра из users.department_id'
|
||||
FROM users u
|
||||
WHERE u.role = 'TEACHER'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM teacher_department_assignments existing
|
||||
WHERE existing.teacher_id = u.id
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS teacher_creation_requests (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
department_id BIGINT NOT NULL REFERENCES departments(id),
|
||||
@@ -243,12 +208,6 @@ CREATE TABLE IF NOT EXISTS education_forms (
|
||||
archive_reason TEXT
|
||||
);
|
||||
|
||||
INSERT INTO education_forms (name) VALUES
|
||||
('Бакалавриат'),
|
||||
('Магистратура'),
|
||||
('Специалитет')
|
||||
ON CONFLICT (name) DO NOTHING;
|
||||
|
||||
-- ==========================================
|
||||
-- Учебные группы
|
||||
-- ==========================================
|
||||
@@ -272,19 +231,6 @@ CREATE TABLE IF NOT EXISTS student_groups (
|
||||
archive_reason TEXT
|
||||
);
|
||||
|
||||
-- Тестовая базовая группа для работы
|
||||
INSERT INTO student_groups (name, group_size, education_form_id, department_id, specialty_id, specialty_profile_id, year_start_study)
|
||||
SELECT data.name, data.group_size, ef.id, dept.id, specialty.id, profile.id, data.year_start_study
|
||||
FROM (VALUES
|
||||
('ИВТ-21-1', 25::BIGINT, 'Бакалавриат', 'Кафедра ИБ', '09.03.01', 2025::BIGINT),
|
||||
('ИБ-41м', 15::BIGINT, 'Магистратура', 'Кафедра ИБ', '10.03.01', 2024::BIGINT)
|
||||
) AS data(name, group_size, education_form_name, department_name, specialty_code, year_start_study)
|
||||
JOIN education_forms ef ON ef.name = data.education_form_name
|
||||
JOIN departments dept ON dept.name = data.department_name
|
||||
JOIN specialties specialty ON specialty.specialty_code = data.specialty_code
|
||||
JOIN specialty_profiles profile ON profile.specialty_id = specialty.id AND profile.name = 'Без профиля'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM student_groups existing WHERE existing.name = data.name);
|
||||
|
||||
-- ==========================================
|
||||
-- Подгруппы (например: "ИВТ-21-1 Подгруппа 1")
|
||||
-- ==========================================
|
||||
@@ -373,22 +319,6 @@ CREATE TRIGGER validate_subgroup_student_capacity
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION validate_subgroup_student_capacity();
|
||||
|
||||
INSERT INTO subgroups (group_id, name, student_capacity)
|
||||
SELECT
|
||||
sg.id,
|
||||
data.name,
|
||||
CASE
|
||||
WHEN data.part_number = 1 THEN CEIL(sg.group_size::NUMERIC / 2)::INT
|
||||
ELSE FLOOR(sg.group_size::NUMERIC / 2)::INT
|
||||
END
|
||||
FROM student_groups sg
|
||||
CROSS JOIN (VALUES
|
||||
('Подгруппа 1', 1),
|
||||
('Подгруппа 2', 2)
|
||||
) AS data(name, part_number)
|
||||
WHERE sg.name IN ('ИВТ-21-1', 'ИБ-41м')
|
||||
ON CONFLICT (group_id, name) DO NOTHING;
|
||||
|
||||
-- ==========================================
|
||||
-- Справочники
|
||||
-- ==========================================
|
||||
@@ -414,14 +344,6 @@ CREATE UNIQUE INDEX IF NOT EXISTS uq_subjects_name_ci
|
||||
COMMENT ON INDEX uq_subjects_name_ci IS
|
||||
'Глобально уникальное название дисциплины без учёта регистра';
|
||||
|
||||
INSERT INTO subjects (name, department_id) VALUES
|
||||
('Высшая математика', 1),
|
||||
('Философия', 1),
|
||||
('Информатика', 1),
|
||||
('Базы данных', 1),
|
||||
('Английский язык', 1)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS subject_comments (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
subject_id BIGINT NOT NULL REFERENCES subjects(id),
|
||||
@@ -441,12 +363,6 @@ CREATE TABLE IF NOT EXISTS lesson_types (
|
||||
duration_minutes INT DEFAULT 90
|
||||
);
|
||||
|
||||
INSERT INTO lesson_types (name, color_code) VALUES
|
||||
('Лекция', '#FF6B6B'),
|
||||
('Практика', '#4ECDC4'),
|
||||
('Лабораторная работа', '#45B7D1')
|
||||
ON CONFLICT (name) DO NOTHING;
|
||||
|
||||
-- Оборудование
|
||||
CREATE TABLE IF NOT EXISTS equipments (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
@@ -461,15 +377,6 @@ CREATE TABLE IF NOT EXISTS equipments (
|
||||
archive_reason TEXT
|
||||
);
|
||||
|
||||
INSERT INTO equipments (name) VALUES
|
||||
('Проектор'),
|
||||
('ПК'),
|
||||
('Лаборатория'),
|
||||
('Интерактивная доска'),
|
||||
('Документ-камера'),
|
||||
('Аудиосистема')
|
||||
ON CONFLICT (name) DO NOTHING;
|
||||
|
||||
-- Аудитории
|
||||
CREATE TABLE IF NOT EXISTS classrooms (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
@@ -488,12 +395,6 @@ CREATE TABLE IF NOT EXISTS classrooms (
|
||||
archive_reason TEXT
|
||||
);
|
||||
|
||||
INSERT INTO classrooms (name, capacity, building, floor) VALUES
|
||||
('101 Ленинская', 120, 'Главный корпус', 1),
|
||||
('202 IT Lab', 20, 'Корпус IT', 2),
|
||||
('303 Обычная', 30, 'Главный корпус', 3)
|
||||
ON CONFLICT (name) DO NOTHING;
|
||||
|
||||
-- Привязка оборудования к аудиториям (Many-to-Many)
|
||||
CREATE TABLE IF NOT EXISTS classroom_equipments (
|
||||
classroom_id BIGINT NOT NULL REFERENCES classrooms(id) ON DELETE CASCADE,
|
||||
@@ -503,20 +404,6 @@ CREATE TABLE IF NOT EXISTS classroom_equipments (
|
||||
PRIMARY KEY (classroom_id, equipment_id)
|
||||
);
|
||||
|
||||
INSERT INTO classroom_equipments (classroom_id, equipment_id, quantity)
|
||||
SELECT c.id, e.id,
|
||||
CASE
|
||||
WHEN e.name = 'ПК' AND c.name = '202 IT Lab' THEN 15
|
||||
WHEN e.name = 'ПК' THEN 1
|
||||
ELSE 1
|
||||
END
|
||||
FROM classrooms c, equipments e
|
||||
WHERE
|
||||
(c.name = '101 Ленинская' AND e.name IN ('Проектор', 'Интерактивная доска', 'Аудиосистема'))
|
||||
OR (c.name = '202 IT Lab' AND e.name IN ('ПК', 'Проектор', 'Лаборатория', 'Интерактивная доска'))
|
||||
OR (c.name = '303 Обычная' AND e.name IN ('Проектор'))
|
||||
ON CONFLICT (classroom_id, equipment_id) DO NOTHING;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_departments_status ON departments(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_specialties_status ON specialties(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_specialty_profiles_status ON specialty_profiles(status);
|
||||
@@ -575,11 +462,6 @@ CREATE UNIQUE INDEX IF NOT EXISTS uq_time_slot_scopes_weekday
|
||||
ON time_slot_scopes(day_of_week)
|
||||
WHERE apply_mode = 'WEEKDAY';
|
||||
|
||||
INSERT INTO time_slot_scopes (code, name, apply_mode, day_of_week, system_scope, display_order) VALUES
|
||||
('default', 'Базовая сетка', 'DEFAULT', NULL, TRUE, 10),
|
||||
('saturday', 'Субботняя сетка', 'WEEKDAY', 6, TRUE, 20)
|
||||
ON CONFLICT (code) DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS time_slots (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
time_slot_scope_id BIGINT NOT NULL REFERENCES time_slot_scopes(id) ON DELETE CASCADE,
|
||||
@@ -597,21 +479,6 @@ CREATE UNIQUE INDEX IF NOT EXISTS uq_time_slots_scope_order
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_time_slots_scope ON time_slots(time_slot_scope_id, order_number);
|
||||
|
||||
INSERT INTO time_slots (time_slot_scope_id, order_number, start_time, end_time, duration_minutes)
|
||||
SELECT scope.id, data.order_number, data.start_time::TIME, data.end_time::TIME, data.duration_minutes
|
||||
FROM (VALUES
|
||||
(1, '08:00', '09:30', 90),
|
||||
(2, '09:40', '11:10', 90),
|
||||
(3, '11:40', '13:10', 90),
|
||||
(4, '13:20', '14:50', 90),
|
||||
(5, '15:00', '16:30', 90),
|
||||
(6, '16:50', '18:20', 90),
|
||||
(7, '18:30', '20:00', 90)
|
||||
) AS data(order_number, start_time, end_time, duration_minutes)
|
||||
CROSS JOIN time_slot_scopes scope
|
||||
WHERE scope.code IN ('default', 'saturday')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS time_slot_date_assignments (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
assignment_date DATE NOT NULL UNIQUE,
|
||||
@@ -629,11 +496,6 @@ CREATE TABLE IF NOT EXISTS academic_years (
|
||||
CONSTRAINT chk_academic_years_dates CHECK (start_date <= end_date)
|
||||
);
|
||||
|
||||
INSERT INTO academic_years (title, start_date, end_date) VALUES
|
||||
('2024-2025', '2024-09-01', '2025-06-30'),
|
||||
('2025-2026', '2025-09-01', '2026-06-30')
|
||||
ON CONFLICT (title) DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS semesters (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
academic_year_id BIGINT NOT NULL REFERENCES academic_years(id) ON DELETE CASCADE,
|
||||
@@ -645,16 +507,6 @@ CREATE TABLE IF NOT EXISTS semesters (
|
||||
CONSTRAINT uq_semesters_year_type UNIQUE (academic_year_id, semester_type)
|
||||
);
|
||||
|
||||
INSERT INTO semesters (academic_year_id, semester_type, start_date, end_date)
|
||||
SELECT id, 'autumn', start_date, MAKE_DATE(SPLIT_PART(title, '-', 2)::INT, 1, 31)
|
||||
FROM academic_years
|
||||
ON CONFLICT (academic_year_id, semester_type) DO NOTHING;
|
||||
|
||||
INSERT INTO semesters (academic_year_id, semester_type, start_date, end_date)
|
||||
SELECT id, 'spring', MAKE_DATE(SPLIT_PART(title, '-', 2)::INT, 2, 1), end_date
|
||||
FROM academic_years
|
||||
ON CONFLICT (academic_year_id, semester_type) DO NOTHING;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_semesters_dates ON semesters(start_date, end_date);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS academic_calendar_activity_types (
|
||||
@@ -667,22 +519,6 @@ CREATE TABLE IF NOT EXISTS academic_calendar_activity_types (
|
||||
description TEXT
|
||||
);
|
||||
|
||||
INSERT INTO academic_calendar_activity_types (code, name, allow_schedule, color_code, display_order, description) VALUES
|
||||
('Т', 'Теоретическое обучение', TRUE, '#10b981', 10, 'Обычные занятия динамического расписания разрешены'),
|
||||
('Э', 'Экзаменационная сессия', FALSE, '#f59e0b', 20, 'Обычные занятия не генерируются'),
|
||||
('К', 'Каникулы', FALSE, '#38bdf8', 30, 'Обычные занятия не генерируются'),
|
||||
('У', 'Учебная практика', FALSE, '#a78bfa', 40, 'Обычные занятия не генерируются'),
|
||||
('П', 'Производственная практика', FALSE, '#fb7185', 50, 'Обычные занятия не генерируются'),
|
||||
('Пд', 'Преддипломная практика', FALSE, '#f97316', 60, 'Обычные занятия не генерируются'),
|
||||
('Н', 'Научно-исследовательская работа', FALSE, '#22c55e', 70, 'Обычные занятия не генерируются'),
|
||||
('Г', 'Подготовка к сдаче и сдача государственного экзамена', FALSE, '#ef4444', 80, 'Обычные занятия не генерируются'),
|
||||
('Д', 'Подготовка к защите и защита выпускной квалификационной работы', FALSE, '#dc2626', 90, 'Обычные занятия не генерируются'),
|
||||
('ПА', 'Повторная промежуточная аттестация', FALSE, '#eab308', 100, 'Обычные занятия не генерируются'),
|
||||
('С', 'Симуляционный курс', FALSE, '#06b6d4', 110, 'Обычные занятия не генерируются'),
|
||||
('*', 'Нерабочий праздничный день', FALSE, '#64748b', 120, 'День исключается из генерации расписания'),
|
||||
('=', 'День вне учебного года', FALSE, '#475569', 130, 'День исключается из генерации расписания')
|
||||
ON CONFLICT (code) DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS academic_calendars (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
@@ -700,21 +536,6 @@ CREATE TABLE IF NOT EXISTS academic_calendars (
|
||||
CREATE INDEX IF NOT EXISTS idx_academic_calendars_context
|
||||
ON academic_calendars(academic_year_id, specialty_id, specialty_profile_id, study_form_id);
|
||||
|
||||
INSERT INTO academic_calendars (title, academic_year_id, specialty_id, specialty_profile_id, study_form_id, course_count)
|
||||
SELECT
|
||||
specialty.specialty_code || ' ' || profile.name || ' ' || study_form.name || ' ' || ay.title,
|
||||
ay.id,
|
||||
specialty.id,
|
||||
profile.id,
|
||||
study_form.id,
|
||||
4
|
||||
FROM academic_years ay
|
||||
CROSS JOIN education_forms study_form
|
||||
JOIN specialties specialty ON specialty.specialty_code IN ('09.03.01', '10.03.01')
|
||||
JOIN specialty_profiles profile ON profile.specialty_id = specialty.id AND profile.name = 'Без профиля'
|
||||
WHERE ay.title = '2025-2026'
|
||||
ON CONFLICT (academic_year_id, specialty_profile_id, study_form_id, title) DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS academic_calendar_periods (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
calendar_id BIGINT NOT NULL REFERENCES academic_calendars(id) ON DELETE CASCADE,
|
||||
@@ -754,24 +575,6 @@ AS $$
|
||||
) + 1
|
||||
$$;
|
||||
|
||||
INSERT INTO academic_calendar_periods (
|
||||
calendar_id,
|
||||
course_number,
|
||||
start_date,
|
||||
end_date,
|
||||
activity_type_id
|
||||
)
|
||||
SELECT
|
||||
calendar.id,
|
||||
course.course_number,
|
||||
ay.start_date,
|
||||
ay.end_date,
|
||||
activity.id
|
||||
FROM academic_calendars calendar
|
||||
JOIN academic_years ay ON ay.id = calendar.academic_year_id
|
||||
JOIN academic_calendar_activity_types activity ON activity.code = 'Т'
|
||||
CROSS JOIN GENERATE_SERIES(1, calendar.course_count) AS course(course_number);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS academic_calendar_subjects (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
calendar_id BIGINT NOT NULL REFERENCES academic_calendars(id) ON DELETE CASCADE,
|
||||
@@ -800,21 +603,6 @@ CREATE TABLE IF NOT EXISTS student_group_calendar_assignments (
|
||||
CREATE INDEX IF NOT EXISTS idx_group_calendar_assignments_lookup
|
||||
ON student_group_calendar_assignments(group_id, academic_year_id);
|
||||
|
||||
INSERT INTO student_group_calendar_assignments (group_id, academic_year_id, calendar_id)
|
||||
SELECT
|
||||
sg.id,
|
||||
ay.id,
|
||||
calendar.id
|
||||
FROM student_groups sg
|
||||
JOIN academic_years ay ON ay.title = '2025-2026'
|
||||
JOIN academic_calendars calendar
|
||||
ON calendar.academic_year_id = ay.id
|
||||
AND calendar.specialty_id = sg.specialty_id
|
||||
AND calendar.specialty_profile_id = sg.specialty_profile_id
|
||||
AND calendar.study_form_id = sg.education_form_id
|
||||
WHERE sg.name IN ('ИВТ-21-1', 'ИБ-41м')
|
||||
ON CONFLICT (group_id, academic_year_id) DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS schedule_rules (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
subject_id BIGINT NOT NULL REFERENCES subjects(id),
|
||||
@@ -991,121 +779,6 @@ CREATE TRIGGER validate_schedule_rule_slot_subgroups
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION validate_schedule_rule_slot_subgroups();
|
||||
|
||||
CREATE TEMP TABLE tmp_default_rules AS
|
||||
SELECT
|
||||
NEXTVAL(PG_GET_SERIAL_SEQUENCE('schedule_rules', 'id')) AS schedule_rule_id,
|
||||
rule_key,
|
||||
subject_id,
|
||||
semester_id,
|
||||
lecture_academic_hours,
|
||||
laboratory_academic_hours,
|
||||
practice_academic_hours,
|
||||
lecture_start_week,
|
||||
laboratory_start_week,
|
||||
practice_start_week
|
||||
FROM (
|
||||
SELECT
|
||||
data.rule_key,
|
||||
subj.id AS subject_id,
|
||||
sem.id AS semester_id,
|
||||
data.lecture_academic_hours,
|
||||
data.laboratory_academic_hours,
|
||||
data.practice_academic_hours,
|
||||
data.lecture_start_week,
|
||||
data.laboratory_start_week,
|
||||
data.practice_start_week
|
||||
FROM (VALUES
|
||||
('stream_math', 'Высшая математика', '2025-2026', 'spring', 72, 0, 0, 1, 1, 1),
|
||||
('ivt_informatics_lab', 'Информатика', '2025-2026', 'spring', 0, 72, 0, 1, 1, 1),
|
||||
('ivt_databases_practice', 'Базы данных', '2025-2026', 'spring', 0, 0, 72, 1, 1, 1),
|
||||
('ib_philosophy', 'Философия', '2025-2026', 'spring', 54, 0, 0, 1, 1, 1)
|
||||
) AS data(
|
||||
rule_key,
|
||||
subject_name,
|
||||
year_title,
|
||||
semester_type,
|
||||
lecture_academic_hours,
|
||||
laboratory_academic_hours,
|
||||
practice_academic_hours,
|
||||
lecture_start_week,
|
||||
laboratory_start_week,
|
||||
practice_start_week
|
||||
)
|
||||
JOIN subjects subj ON subj.name = data.subject_name
|
||||
JOIN academic_years ay ON ay.title = data.year_title
|
||||
JOIN semesters sem ON sem.academic_year_id = ay.id AND sem.semester_type = data.semester_type
|
||||
) prepared_rules;
|
||||
|
||||
INSERT INTO schedule_rules (
|
||||
id,
|
||||
subject_id,
|
||||
semester_id,
|
||||
lecture_academic_hours,
|
||||
laboratory_academic_hours,
|
||||
practice_academic_hours,
|
||||
lecture_start_week,
|
||||
laboratory_start_week,
|
||||
practice_start_week
|
||||
)
|
||||
SELECT
|
||||
schedule_rule_id,
|
||||
subject_id,
|
||||
semester_id,
|
||||
lecture_academic_hours,
|
||||
laboratory_academic_hours,
|
||||
practice_academic_hours,
|
||||
lecture_start_week,
|
||||
laboratory_start_week,
|
||||
practice_start_week
|
||||
FROM tmp_default_rules;
|
||||
|
||||
INSERT INTO schedule_rule_groups (schedule_rule_id, group_id)
|
||||
SELECT
|
||||
rules.schedule_rule_id,
|
||||
sg.id
|
||||
FROM (VALUES
|
||||
('stream_math', 'ИВТ-21-1'),
|
||||
('stream_math', 'ИБ-41м'),
|
||||
('ivt_informatics_lab', 'ИВТ-21-1'),
|
||||
('ivt_databases_practice', 'ИВТ-21-1'),
|
||||
('ib_philosophy', 'ИБ-41м')
|
||||
) AS data(rule_key, group_name)
|
||||
JOIN tmp_default_rules rules ON rules.rule_key = data.rule_key
|
||||
JOIN student_groups sg ON sg.name = data.group_name
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
INSERT INTO schedule_rule_slots (
|
||||
schedule_rule_id,
|
||||
day_of_week,
|
||||
parity,
|
||||
time_slot_id,
|
||||
teacher_id,
|
||||
classroom_id,
|
||||
lesson_type_id,
|
||||
lesson_format
|
||||
)
|
||||
SELECT
|
||||
rules.schedule_rule_id,
|
||||
data.day_of_week,
|
||||
data.parity,
|
||||
ts.id,
|
||||
teacher.id,
|
||||
classroom.id,
|
||||
lt.id,
|
||||
data.lesson_format
|
||||
FROM (VALUES
|
||||
('stream_math', 1, 'BOTH', 3, 'Тестовый преподаватель', '101 Ленинская', 'Лекция', 'Очно'),
|
||||
('ivt_informatics_lab', 3, 'BOTH', 1, 'Тестовый преподаватель', '202 IT Lab', 'Лабораторная работа', 'Очно'),
|
||||
('ivt_databases_practice', 5, 'EVEN', 5, 'Тестовый преподаватель', '303 Обычная', 'Практика', 'Онлайн'),
|
||||
('ib_philosophy', 2, 'ODD', 2, 'Тестовый преподаватель', '101 Ленинская', 'Лекция', 'Онлайн')
|
||||
) AS data(rule_key, day_of_week, parity, time_slot_order, teacher_username, classroom_name, lesson_type_name, lesson_format)
|
||||
JOIN tmp_default_rules rules ON rules.rule_key = data.rule_key
|
||||
JOIN time_slot_scopes scope ON scope.code = 'default'
|
||||
JOIN time_slots ts ON ts.time_slot_scope_id = scope.id AND ts.order_number = data.time_slot_order
|
||||
JOIN users teacher ON teacher.username = data.teacher_username
|
||||
JOIN classrooms classroom ON classroom.name = data.classroom_name
|
||||
JOIN lesson_types lt ON lt.name = data.lesson_type_name;
|
||||
|
||||
-- ==========================================
|
||||
-- Функция обновления timestamp
|
||||
-- ==========================================
|
||||
@@ -1371,7 +1044,7 @@ BEGIN
|
||||
RAISE EXCEPTION USING
|
||||
ERRCODE = '23514',
|
||||
MESSAGE = format(
|
||||
'Невозможно создать baseline: невалидные точечные изменения CANCEL=%s, MOVE=%s, REPLACE=%s, формат=%s, целевая дата=%s. Исправьте seed-данные V1 и повторите создание схемы.',
|
||||
'Невозможно создать baseline: невалидные точечные изменения CANCEL=%s, MOVE=%s, REPLACE=%s, формат=%s, целевая дата=%s. Исправьте исходные данные и повторите создание схемы.',
|
||||
cancel_violations,
|
||||
move_violations,
|
||||
replace_violations,
|
||||
@@ -1470,7 +1143,7 @@ BEGIN
|
||||
RAISE EXCEPTION USING
|
||||
ERRCODE = '23514',
|
||||
MESSAGE = format(
|
||||
'Невозможно создать baseline: нечётные академические часы правил расписания — лекции=%s, лабораторные=%s, практики=%s. Исправьте seed-данные V1 и повторите создание схемы.',
|
||||
'Невозможно создать baseline: нечётные академические часы правил расписания — лекции=%s, лабораторные=%s, практики=%s. Исправьте исходные данные и повторите создание схемы.',
|
||||
lecture_violations,
|
||||
laboratory_violations,
|
||||
practice_violations
|
||||
@@ -1511,7 +1184,7 @@ BEGIN
|
||||
RAISE EXCEPTION USING
|
||||
ERRCODE = '23505',
|
||||
MESSAGE = format(
|
||||
'Невозможно создать baseline: найдено групп точных дублей слотов правил=%s. Исправьте seed-данные V1 и повторите создание схемы.',
|
||||
'Невозможно создать baseline: найдено групп точных дублей слотов правил=%s. Исправьте исходные данные и повторите создание схемы.',
|
||||
duplicate_slot_groups
|
||||
);
|
||||
END IF;
|
||||
@@ -1577,7 +1250,7 @@ BEGIN
|
||||
RAISE EXCEPTION USING
|
||||
ERRCODE = '23514',
|
||||
MESSAGE = format(
|
||||
'Невозможно создать baseline: неверная длительность слотов=%s, пересекающиеся интервалы=%s, слоты правил вне базовой сетки=%s. Исправьте seed-данные V1 и повторите создание схемы.',
|
||||
'Невозможно создать baseline: неверная длительность слотов=%s, пересекающиеся интервалы=%s, слоты правил вне базовой сетки=%s. Исправьте исходные данные и повторите создание схемы.',
|
||||
duration_violations,
|
||||
overlap_violations,
|
||||
scope_violations
|
||||
@@ -1733,7 +1406,7 @@ BEGIN
|
||||
RAISE EXCEPTION USING
|
||||
ERRCODE = '23514',
|
||||
MESSAGE = format(
|
||||
'Невозможно создать baseline: пересечения учебных годов=%s, семестры вне границ года=%s, пересечения семестров=%s. Исправьте seed-данные V1 и повторите создание схемы.',
|
||||
'Невозможно создать baseline: пересечения учебных годов=%s, семестры вне границ года=%s, пересечения семестров=%s. Исправьте исходные данные и повторите создание схемы.',
|
||||
academic_year_overlap_violations,
|
||||
semester_bounds_violations,
|
||||
semester_overlap_violations
|
||||
@@ -1864,7 +1537,7 @@ BEGIN
|
||||
RAISE EXCEPTION USING
|
||||
ERRCODE = '23514',
|
||||
MESSAGE = format(
|
||||
'Невозможно создать baseline: несовместимые назначения графиков=%s, периоды активности вне измерений=%s, дисциплины вне измерений=%s. Исправьте seed-данные V1 и повторите создание схемы.',
|
||||
'Невозможно создать baseline: несовместимые назначения графиков=%s, периоды активности вне измерений=%s, дисциплины вне измерений=%s. Исправьте исходные данные и повторите создание схемы.',
|
||||
assignment_violations,
|
||||
calendar_period_violations,
|
||||
calendar_subject_violations
|
||||
@@ -2430,33 +2103,9 @@ CREATE UNIQUE INDEX uq_schedule_versions_published_semester
|
||||
CREATE INDEX idx_schedule_versions_semester_history
|
||||
ON schedule_versions(semester_id, version_number DESC);
|
||||
|
||||
INSERT INTO schedule_versions (
|
||||
semester_id,
|
||||
version_number,
|
||||
name,
|
||||
status,
|
||||
created_at,
|
||||
published_at
|
||||
)
|
||||
SELECT
|
||||
semester.id,
|
||||
1,
|
||||
'Опубликованная версия 1',
|
||||
'PUBLISHED',
|
||||
CURRENT_TIMESTAMP,
|
||||
CURRENT_TIMESTAMP
|
||||
FROM semesters semester;
|
||||
|
||||
ALTER TABLE schedule_rules
|
||||
ADD COLUMN schedule_version_id BIGINT;
|
||||
|
||||
UPDATE schedule_rules rule
|
||||
SET schedule_version_id = version.id,
|
||||
version_group_id = COALESCE(rule.version_group_id, rule.id)
|
||||
FROM schedule_versions version
|
||||
WHERE version.semester_id = rule.semester_id
|
||||
AND version.status = 'PUBLISHED';
|
||||
|
||||
ALTER TABLE schedule_rules
|
||||
ALTER COLUMN schedule_version_id SET NOT NULL,
|
||||
ADD CONSTRAINT fk_schedule_rules_version
|
||||
@@ -2487,14 +2136,6 @@ CREATE TABLE schedule_version_history (
|
||||
CREATE INDEX idx_schedule_version_history_version
|
||||
ON schedule_version_history(version_id, created_at DESC, id DESC);
|
||||
|
||||
INSERT INTO schedule_version_history (version_id, action, reason, created_at)
|
||||
SELECT id, 'CREATED', 'Начальная версия расписания', created_at
|
||||
FROM schedule_versions;
|
||||
|
||||
INSERT INTO schedule_version_history (version_id, action, reason, created_at)
|
||||
SELECT id, 'PUBLISHED', 'Начальная публикация расписания', published_at
|
||||
FROM schedule_versions;
|
||||
|
||||
COMMENT ON TABLE schedule_versions IS 'Изолированные черновики и опубликованные версии правил расписания';
|
||||
COMMENT ON COLUMN schedule_versions.status IS 'DRAFT, PUBLISHED или ARCHIVED';
|
||||
COMMENT ON COLUMN schedule_versions.based_on_version_id IS 'Версия, из которой был скопирован черновик';
|
||||
|
||||
Reference in New Issue
Block a user