From 07419d541ef0e268a94a72a89d32b63e8959ede4 Mon Sep 17 00:00:00 2001 From: Zuev Date: Fri, 20 Feb 2026 01:56:05 +0300 Subject: [PATCH] feat(db): update init.sql with subjects, lesson types, classrooms, and schedules tables --- .agent/rules/main.md | 60 ++++++++++++++++++++- .agent/workflows/deploy-server.md | 13 ++++- db/init/init.sql | 86 +++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 3 deletions(-) diff --git a/.agent/rules/main.md b/.agent/rules/main.md index e27a4c3..f354340 100644 --- a/.agent/rules/main.md +++ b/.agent/rules/main.md @@ -43,4 +43,62 @@ trigger: always_on 3. **Маршрутизация/Прокси**: Если возникают проблемы с доменом или внешним доступом, проверьте конфигурацию в `../caddy-proxy/Caddyfile`. ## Языковые предпочтения -- **Всегда отвечайте на русском**: Это строгое требование пользователя. Все объяснения, комментарии и взаимодействия должны быть на русском языке, если только не будет специально запрошено иное. \ No newline at end of file +- **Всегда отвечайте на русском**: Это строгое требование пользователя. Все объяснения, комментарии и взаимодействия должны быть на русском языке, если только не будет специально запрошено иное. + +## Функциональные требования к системе + +### 1. Ролевая модель +- **Администратор (Деканат)**: Полный доступ, настройка топологии университета, управление аудиторным фондом, подтверждение переносов, регистрация инцидентов. +- **Преподаватель**: Просмотр своего расписания, подача заявок на перенос, отметка о своём отсутствии. +- **Студент**: Только просмотр расписания (Read-only). + +### 2. Управление ресурсами и топология +- **Управление аудиториями**: + - Указание вместимости. + - Указание тэгов оборудования (Проектор, ПК, Лаборатория). + - Установка статуса "Не доступно" (блокирует назначение пар в этот период). +- **Управление группами**: + - Управление списком студентов (и возможность деления на подгруппы). +- **Управление дисциплинами**: + - Создание предметов и привязка их к преподавателям (какие дисциплины имеет право вести конкретный преподаватель). + +### 3. Логика расписания +- **Проверка конфликтов**: + - *Критический конфликт*: Преподаватель не может находиться в двух разных аудиториях одновременно. + - *Уточнение по преподавателям*: Преподаватель может иметь несколько пар одновременно (для разных групп), только если они проходят в одной и той же аудитории (потоковая лекция). +- **Потоковые занятия**: + - Возможность назначить одну лекцию сразу нескольким группам (технически — несколько записей в БД или одна запись со списком групп). + - Проверка вместимости: вместимость аудитории должна покрывать суммарную численность всех групп, находящихся в этой аудитории в данный слот. + +### 4. Управление инцидентами (Инклюзия отсутствия) +- **Отсутствие (Sickness/Business Trip)**: Регистрация отсутствия преподавателя (с указанием причины и периода дат). +- **Обнаружение коллизий**: Автоматическая подсветка конфликтующих пар в расписании (Red Zone). +- **Система разрешения конфликтов (Resolution Wizard)**: + - Предложение подходящей замены преподавателя на этот слот. + - Предложение переноса занятия на другое время или в другую аудиторию. + +## Технологический стек (Tech Stack) +- **Backend**: Java 17, Spring Boot 3.2.5 (Starter Web, Data JPA), кастомная токен-авторизация (используется BCrypt, без полной автоконфигурации Spring Security). +- **Database**: PostgreSQL. +- **Frontend**: Vanilla JavaScript + HTML/CSS (без тяжеловесных фреймворков). + +## Специфика времени и сетка расписания (Time Management) +- **Гибкие временные слоты**: По умолчанию слоты по 1.5 часа: + 1. 08:00 - 09:30 + 2. 09:40 - 11:10 + 3. 11:40 - 13:10 + 4. 13:20 - 14:50 + 5. 15:00 - 16:30 + 6. 16:50 - 18:20 + 7. 18:30 - 20:00 +- **Кастомное время**: Система должна позволять устанавливать кастомное время начала и конца пары. +- **Тип расписания**: Календарное расписание, строящееся по принципу чётной / нечётной недели. + +## Основные сущности базы данных (Data Entities) +- **Users**: Хранение пользователей и их ролей (Администратор, Преподаватель, Студент) для управления доступом. +- **Groups**: Группы студентов, их привязка к формам обучения. (Могут делиться на **подгруппы** для лабораторных и практик). +- **Classrooms**: Аудиторный фонд (название, вместимость, статус доступности, тэги оборудования). +- **Subjects**: Предметы/Дисциплины (Высшая математика, Физика, Базы данных и т.д.). +- **Teacher_Subjects**: Связующая таблица (Many-to-Many), определяющая, какие дисциплины ведет конкретный преподаватель. +- **Lesson_Types**: Типы занятий для валидации (Лекция, Практика, Лабораторная работа). +- **Lessons / Schedules**: Сами занятия (пары). Каждая запись связывает преподавателя, аудиторию, группу (или подгруппу), предмет (`subject_id`), тип занятия (`lesson_type`) и конкретное время. \ No newline at end of file diff --git a/.agent/workflows/deploy-server.md b/.agent/workflows/deploy-server.md index 08d425b..9e535f1 100644 --- a/.agent/workflows/deploy-server.md +++ b/.agent/workflows/deploy-server.md @@ -7,7 +7,16 @@ description: Деплой на удаленный сервер 192.168.1.87 (Git Этот воркфлоу позволяет быстро обновить проект на удаленном сервере после того, как вы запушили изменения в Git. // turbo-all -1. Синхронизировать код и перезапустить контейнеры: +1. Синхронизировать код и, если изменился init.sql, пересобрать базу данных: ```bash -ssh root@192.168.1.87 "cd /root/magistr/program/ && git fetch origin main && git reset --hard origin/main && docker compose up -d --build" +ssh root@192.168.1.87 "cd /root/magistr/program/ && \ + git fetch origin main && \ + CHANGED=\$(git diff --name-only HEAD origin/main | grep db/init/init.sql || true) && \ + git reset --hard origin/main && \ + if [ ! -z \"\$CHANGED\" ]; then \ + echo 'Обнаружены изменения в init.sql, удаляем базу данных...'; \ + docker compose down -v; \ + sudo rm -rf db/data; \ + fi && \ + docker compose up -d --build" ``` diff --git a/db/init/init.sql b/db/init/init.sql index a504d82..4855da3 100644 --- a/db/init/init.sql +++ b/db/init/init.sql @@ -25,3 +25,89 @@ CREATE TABLE IF NOT EXISTS student_groups ( name VARCHAR(100) UNIQUE NOT NULL, education_form_id BIGINT NOT NULL REFERENCES education_forms(id) ); +-- ========================================== +-- Справочники +-- ========================================== + +-- Дисциплины +CREATE TABLE IF NOT EXISTS subjects ( + id BIGSERIAL PRIMARY KEY, + name VARCHAR(200) UNIQUE NOT NULL +); + +INSERT INTO subjects (name) VALUES +('Высшая математика'), +('Философия'), +('Информатика'), +('Базы данных'), +('Английский язык') +ON CONFLICT (name) DO NOTHING; + +-- Типы занятий +CREATE TABLE IF NOT EXISTS lesson_types ( + id BIGSERIAL PRIMARY KEY, + name VARCHAR(50) UNIQUE NOT NULL +); + +INSERT INTO lesson_types (name) VALUES +('Лекция'), +('Практика'), +('Лабораторная работа') +ON CONFLICT (name) DO NOTHING; + +-- Аудитории +CREATE TABLE IF NOT EXISTS classrooms ( + id BIGSERIAL PRIMARY KEY, + name VARCHAR(50) UNIQUE NOT NULL, + capacity INT NOT NULL, + is_available BOOLEAN DEFAULT TRUE, + hardware_tags VARCHAR(255) -- например: "Проектор, ПК, Лаборатория" +); + +INSERT INTO classrooms (name, capacity, hardware_tags) VALUES +('101 Ленинская', 120, 'Проектор, Доска'), +('202 IT Lab', 20, 'ПК, Проектор, Лаборатория'), +('303 Обычная', 30, 'Доска') +ON CONFLICT (name) DO NOTHING; + +-- ========================================== +-- Связи для преподавателей и студентов +-- ========================================== + +-- Подгруппы (например: "ИВТ-21-1 Подгруппа 1") +CREATE TABLE IF NOT EXISTS subgroups ( + id BIGSERIAL PRIMARY KEY, + group_id BIGINT NOT NULL REFERENCES student_groups(id) ON DELETE CASCADE, + name VARCHAR(100) NOT NULL, + UNIQUE(group_id, name) +); + +-- Тестовая базовая группа для работы +INSERT INTO student_groups (name, education_form_id) +VALUES ('ИВТ-21-1', 1) +ON CONFLICT (name) DO NOTHING; + +-- Привязка преподавателей к дисциплинам +CREATE TABLE IF NOT EXISTS teacher_subjects ( + user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, + subject_id BIGINT NOT NULL REFERENCES subjects(id) ON DELETE CASCADE, + PRIMARY KEY(user_id, subject_id) +); + +-- ========================================== +-- Основная таблица Расписания (Lessons) +-- ========================================== +CREATE TABLE IF NOT EXISTS lessons ( + id BIGSERIAL PRIMARY KEY, + teacher_id BIGINT NOT NULL REFERENCES users(id), + subject_id BIGINT NOT NULL REFERENCES subjects(id), + lesson_type_id BIGINT NOT NULL REFERENCES lesson_types(id), + classroom_id BIGINT NOT NULL REFERENCES classrooms(id), + group_id BIGINT NOT NULL REFERENCES student_groups(id), -- первичная группа + subgroup_id BIGINT REFERENCES subgroups(id), -- необязательно (если делим группу) + + day_of_week INT NOT NULL CHECK (day_of_week BETWEEN 1 AND 7), -- 1=Понедельник, 7=Воскресенье + is_even_week BOOLEAN NOT NULL, -- Четная/нечетная неделя + start_time TIME NOT NULL, -- Напр. '08:00:00' + end_time TIME NOT NULL -- Напр. '09:30:00' +);