From 03eaf6ab13a1d748b0546f58f6ab805edc42c6cc Mon Sep 17 00:00:00 2001 From: ProstoDenya01 Date: Thu, 12 Mar 2026 14:45:25 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=B3=D1=80=D1=83=D0=BF=D0=BF=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=B5=20=D1=87=D0=B8=D1=81=D0=BB=D0=B5=D0=BD=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B8.=20=D0=92=20=D0=BC=D0=BE=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=BA=D1=83=20=D0=BD=D0=B0=20UI=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=87=D0=B8=D1=81=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D0=B8=20=D0=B3=D1=80=D1=83=D0=BF?= =?UTF-8?q?=D0=BF=20=D0=B8=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=B8=D0=BC?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B8=20=D0=B0=D1=83=D0=B4=D0=B8=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=B9,=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BA=D1=83=20=D0=BD=D0=B0=20=D0=B4=D0=BE=D1=81=D1=82=D1=83?= =?UTF-8?q?=D0=BF=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D0=B8=20=D0=B2=D0=BC?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D1=8C.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/controller/GroupController.java | 6 +++ .../magistr/app/dto/CreateGroupRequest.java | 9 ++++ .../com/magistr/app/dto/GroupResponse.java | 8 +++- .../com/magistr/app/model/StudentGroup.java | 11 +++++ db/init/init.sql | 6 ++- frontend/admin/js/views/groups.js | 5 ++- frontend/admin/js/views/users.js | 45 ++++++++++++++++++- frontend/admin/views/groups.html | 5 +++ 8 files changed, 89 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/magistr/app/controller/GroupController.java b/backend/src/main/java/com/magistr/app/controller/GroupController.java index b8f7795..0365aea 100755 --- a/backend/src/main/java/com/magistr/app/controller/GroupController.java +++ b/backend/src/main/java/com/magistr/app/controller/GroupController.java @@ -32,6 +32,7 @@ public class GroupController { .map(g -> new GroupResponse( g.getId(), g.getName(), + g.getGroupSize(), g.getEducationForm().getId(), g.getEducationForm().getName())) .toList(); @@ -45,6 +46,9 @@ public class GroupController { if (groupRepository.findByName(request.getName().trim()).isPresent()) { return ResponseEntity.badRequest().body(Map.of("message", "Группа с таким названием уже существует")); } + if (request.getGroupSize() == null) { + return ResponseEntity.badRequest().body(Map.of("message", "Численность группы обязательна")); + } if (request.getEducationFormId() == null) { return ResponseEntity.badRequest().body(Map.of("message", "Форма обучения обязательна")); } @@ -56,12 +60,14 @@ public class GroupController { StudentGroup group = new StudentGroup(); group.setName(request.getName().trim()); + group.setGroupSize(request.getGroupSize()); group.setEducationForm(efOpt.get()); groupRepository.save(group); return ResponseEntity.ok(new GroupResponse( group.getId(), group.getName(), + group.getGroupSize(), group.getEducationForm().getId(), group.getEducationForm().getName())); } diff --git a/backend/src/main/java/com/magistr/app/dto/CreateGroupRequest.java b/backend/src/main/java/com/magistr/app/dto/CreateGroupRequest.java index 43e604a..dfbe5a0 100755 --- a/backend/src/main/java/com/magistr/app/dto/CreateGroupRequest.java +++ b/backend/src/main/java/com/magistr/app/dto/CreateGroupRequest.java @@ -3,6 +3,7 @@ package com.magistr.app.dto; public class CreateGroupRequest { private String name; + private Long groupSize; private Long educationFormId; public String getName() { @@ -13,6 +14,14 @@ public class CreateGroupRequest { this.name = name; } + public Long getGroupSize() { + return groupSize; + } + + public void setGroupSize(Long groupSize) { + this.groupSize = groupSize; + } + public Long getEducationFormId() { return educationFormId; } diff --git a/backend/src/main/java/com/magistr/app/dto/GroupResponse.java b/backend/src/main/java/com/magistr/app/dto/GroupResponse.java index 63becb8..7dd7c58 100755 --- a/backend/src/main/java/com/magistr/app/dto/GroupResponse.java +++ b/backend/src/main/java/com/magistr/app/dto/GroupResponse.java @@ -4,12 +4,14 @@ public class GroupResponse { private Long id; private String name; + private Long groupSize; private Long educationFormId; private String educationFormName; - public GroupResponse(Long id, String name, Long educationFormId, String educationFormName) { + public GroupResponse(Long id, String name, Long groupSize, Long educationFormId, String educationFormName) { this.id = id; this.name = name; + this.groupSize = groupSize; this.educationFormId = educationFormId; this.educationFormName = educationFormName; } @@ -22,6 +24,10 @@ public class GroupResponse { return name; } + public Long getGroupSize() { + return groupSize; + } + public Long getEducationFormId() { return educationFormId; } diff --git a/backend/src/main/java/com/magistr/app/model/StudentGroup.java b/backend/src/main/java/com/magistr/app/model/StudentGroup.java index 3ad914a..9deee86 100755 --- a/backend/src/main/java/com/magistr/app/model/StudentGroup.java +++ b/backend/src/main/java/com/magistr/app/model/StudentGroup.java @@ -13,6 +13,9 @@ public class StudentGroup { @Column(unique = true, nullable = false, length = 100) private String name; + @Column(name = "group_size", nullable = false) + private Long groupSize; + @ManyToOne(optional = false) @JoinColumn(name = "education_form_id", nullable = false) private EducationForm educationForm; @@ -36,6 +39,14 @@ public class StudentGroup { this.name = name; } + public Long getGroupSize() { + return groupSize; + } + + public void setGroupSize(Long groupSize) { + this.groupSize = groupSize; + } + public EducationForm getEducationForm() { return educationForm; } diff --git a/db/init/init.sql b/db/init/init.sql index d55142b..3c3339b 100755 --- a/db/init/init.sql +++ b/db/init/init.sql @@ -43,14 +43,16 @@ ON CONFLICT (name) DO NOTHING; CREATE TABLE IF NOT EXISTS student_groups ( id BIGSERIAL PRIMARY KEY, name VARCHAR(100) UNIQUE NOT NULL, + group_size BIGINT NOT NULL, education_form_id BIGINT NOT NULL REFERENCES education_forms(id), course INT CHECK (course BETWEEN 1 AND 6), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Тестовая базовая группа для работы -INSERT INTO student_groups (name, education_form_id, course) -VALUES ('ИВТ-21-1', 1, 3) +INSERT INTO student_groups (name, group_size, education_form_id, course) +VALUES ('ИВТ-21-1', 25, 1, 3), + ('ИБ-41м', 15, 2, 2) ON CONFLICT (name) DO NOTHING; -- ========================================== diff --git a/frontend/admin/js/views/groups.js b/frontend/admin/js/views/groups.js index 1a2b1d6..17301b5 100755 --- a/frontend/admin/js/views/groups.js +++ b/frontend/admin/js/views/groups.js @@ -68,6 +68,7 @@ export async function initGroups() { ${g.id} ${escapeHtml(g.name)} + ${escapeHtml(g.groupSize)} ${escapeHtml(g.educationFormName)} `).join(''); @@ -77,13 +78,15 @@ export async function initGroups() { e.preventDefault(); hideAlert('create-group-alert'); const name = document.getElementById('new-group-name').value.trim(); + const groupSize = document.getElementById('new-group-size').value; const educationFormId = newGroupEfSelect.value; if (!name) { showAlert('create-group-alert', 'Введите название группы', 'error'); return; } + if (!groupSize) { showAlert('create-group-alert', 'Введите размер группы', 'error'); return; } if (!educationFormId) { showAlert('create-group-alert', 'Выберите форму обучения', 'error'); return; } try { - const data = await api.post('/api/groups', { name, educationFormId: Number(educationFormId) }); + const data = await api.post('/api/groups', { name, groupSize, educationFormId: Number(educationFormId) }); showAlert('create-group-alert', `Группа "${escapeHtml(data.name)}" создана`, 'success'); createGroupForm.reset(); loadGroups(); diff --git a/frontend/admin/js/views/users.js b/frontend/admin/js/views/users.js index 921991b..00aad8c 100755 --- a/frontend/admin/js/views/users.js +++ b/frontend/admin/js/views/users.js @@ -79,8 +79,19 @@ export async function initUsers() { // Заполнение select группами function renderGroupOptions() { + if (!groups || groups.length === 0) { + lessonClassroomSelect.innerHTML = ''; + return; + } + lessonGroupSelect.innerHTML = '' + - groups.map(g => ``).join(''); + groups.map(g => { + let optionText = escapeHtml(g.name); + if(g.groupSize) { + optionText += ` (численность: ${g.groupSize} чел.)`; + } + return ``; + }).join(''); } // Заполнение select дисциплинами @@ -90,10 +101,40 @@ export async function initUsers() { } function renderClassroomsOptions() { + if (!classrooms || classrooms.length ===0) { + lessonClassroomSelect.innerHTML = ''; + return; + } + + const selectedGroupId = lessonGroupSelect.value; + const selectedGroup = groups?.find(g => g.id == selectedGroupId); + const groupSize = selectedGroup?.groupSize || 0; + lessonClassroomSelect.innerHTML = '' + - classrooms.map(c => ``).join(''); + classrooms.map(c => { + let optionText = escapeHtml(c.name); + // Добавление текста с инфой о вместимости чел. + if(c.capacity) { + optionText += ` (вместимость: ${c.capacity} чел.)`; + } + + // Если аудитория занята, то рисуем крестик допом + if (c.isAvailable === false) { + optionText += ` ❌ Занята` + // Если свободна, но меньше численности группы, отображаем воскл. знак + } else if (selectedGroupId && groupSize > 0 && c.capacity && groupSize > c.capacity) { + optionText += ` ⚠️ Недостаточно места`; + } + + + return ``; + }).join(''); } + lessonGroupSelect.addEventListener('change', function() { + renderClassroomsOptions(); + }); + // NEW: функция обновления списка времени в зависимости от дня function updateTimeOptions(dayValue) { let times = []; diff --git a/frontend/admin/views/groups.html b/frontend/admin/views/groups.html index 2dc558c..5944cdc 100755 --- a/frontend/admin/views/groups.html +++ b/frontend/admin/views/groups.html @@ -7,6 +7,10 @@ +
+ + +