diff --git a/backend/src/main/java/com/magistr/app/controller/LessonsController.java b/backend/src/main/java/com/magistr/app/controller/LessonsController.java index 3bfc334..3fe103c 100755 --- a/backend/src/main/java/com/magistr/app/controller/LessonsController.java +++ b/backend/src/main/java/com/magistr/app/controller/LessonsController.java @@ -37,10 +37,11 @@ public class LessonsController { this.classroomRepository = classroomRepository; } + //Создание нового занятия @PostMapping("/create") public ResponseEntity createLesson(@RequestBody CreateLessonRequest request) { //Полное логирование входящего запроса - logger.info("Получен запрос на создание занятия: teacherId={}, groupId={}, lessonTypeId={}, day={}, week={}, time={}", + logger.info("Получен запрос на создание занятия: teacherId={}, groupId={}, subjectId={}, day={}, week={}, time={}", request.getTeacherId(), request.getGroupId(), request.getSubjectId(), request.getDay(), request.getWeek(), request.getTime()); //Проверка teacherId @@ -160,6 +161,7 @@ public class LessonsController { } } + //Запрос для получения всего списка занятий @GetMapping public List getAllLessons() { logger.info("Запрос на получение всех занятий"); @@ -218,6 +220,7 @@ public class LessonsController { } } + //Запрос на получение всех занятий для конкретного преподавателя @GetMapping("/{teacherId}") public ResponseEntity getLessonsById(@PathVariable Long teacherId) { logger.info("Запрос на получение занятий для преподавателя с ID: {}", teacherId); @@ -232,18 +235,50 @@ public class LessonsController { )); } - List lessonResponses = lessons.stream() - .map(l -> new LessonResponse( - l.getId(), - l.getTeacherId(), - l.getSubjectId(), - l.getGroupId(), - l.getDay(), - l.getWeek(), - l.getTime() - )) - .toList(); - logger.info("Найдено {} занянтий для преподавателя с ID: {}", lessonResponses.size(), teacherId); + List lessonResponses = lessons.stream() + .map(lesson -> { + String teacherName = teacherRepository.findById(lesson.getTeacherId()) + .map(User::getUsername) + .orElse("Неизвестно"); + + StudentGroup group = groupRepository.findById(lesson.getGroupId()).orElse(null); + String groupName = groupRepository.findById(lesson.getGroupId()) + .map(StudentGroup::getName) + .orElse("Неизвестно"); + + String educationFormName = "Неизвестно"; + if(group != null && group.getEducationForm() != null) { + Long educationFormId = group.getEducationForm().getId(); + educationFormName = educationFormRepository.findById(educationFormId) + .map(EducationForm::getName) + .orElse("Неизвестно"); + } + + String subjectName = subjectRepository.findById(lesson.getSubjectId()) + .map(Subject::getName) + .orElse("Неизвестно"); + + String classroomName = classroomRepository.findById(lesson.getClassroomId()) + .map(Classroom::getName) + .orElse("Неизвестно"); + + return new LessonResponse( + lesson.getId(), + teacherName, + groupName, + classroomName, + educationFormName, + subjectName, + lesson.getTypeLesson(), + lesson.getLessonFormat(), + lesson.getDay(), + lesson.getWeek(), + lesson.getTime() + ); + }) + .toList(); + + logger.info("Найдено {} занятий для преподавателя с ID: {}", lessonResponses.size(), teacherId); return ResponseEntity.ok(lessonResponses); } catch (Exception e ){ logger.error("Ошибка при получении занятий для преподавателя с ID {}: {}", teacherId, e.getMessage(), e); @@ -252,28 +287,6 @@ public class LessonsController { } } - @GetMapping("/debug/subjects") - public ResponseEntity debugSubjects() { - Map result = new HashMap<>(); - - // Через JPA репозиторий - List allSubjects = subjectRepository.findAll(); - result.put("jpa_count", allSubjects.size()); - result.put("jpa_subjects", allSubjects.stream() - .map(s -> Map.of("id", s.getId(), "name", s.getName())) - .toList()); - - // Проверка конкретных ID - Map existenceCheck = new HashMap<>(); - for (long id = 1; id <= 6; id++) { - boolean exists = subjectRepository.existsById(id); - existenceCheck.put(id, exists); - } - result.put("existence_check", existenceCheck); - - return ResponseEntity.ok(result); - } - //Тестовый запрос на проверку доступности контроллера @GetMapping("/ping") public String ping() { @@ -282,4 +295,213 @@ public class LessonsController { logger.debug("Ответ на ping: {}", response); return response; } + + //Удаление занятия по его ID + @DeleteMapping("/delete/{lessonId}") + public ResponseEntity deleteLessonById(@PathVariable Long lessonId){ + logger.info("Запрос на удаление занятия по ID: {}", lessonId); + if(!lessonRepository.existsById(lessonId)) { + return ResponseEntity.badRequest().body(Map.of("message", "Занятие не найдено")); + } + lessonRepository.deleteById(lessonId); + logger.info("Занятие с ID - {} успешно удалено", lessonId); + return ResponseEntity.ok(Map.of("message", "Занятие успешно удалено")); + + } + + //Обновление занятия по его ID + @PutMapping("/update/{lessonId}") + public ResponseEntity updateLessonById(@PathVariable Long lessonId, @RequestBody CreateLessonRequest request) { + logger.info("Получен запрос на обновление занятия с ID - {}", lessonId); + logger.info("Данные для обновления: teacherId={}, groupId={}, subjectId={}, lessonFormat={}, typeLesson={}, classroomId={}, day={}, week={}, time={}", + request.getTeacherId(), request.getGroupId(), request.getSubjectId(), request.getLessonFormat(), request.getTypeLesson(), request.getClassroomId(), + request.getDay(), request.getWeek(), request.getTime()); + + try { + //Проверка на наличие записи + Lesson existingLesson = lessonRepository.findById(lessonId).orElse(null); + + if(existingLesson == null) { + String errorMessage = "Занятие с ID " + lessonId + " не найдено"; + logger.info("Ошибка: {}", errorMessage); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of("message", errorMessage)); + } + + boolean hasChanges = false; + Map changes = new LinkedHashMap<>(); + + //Проверка и обновление teacherId, если он передан и отличается + if(request.getTeacherId() != null) { + if(!request.getTeacherId().equals(existingLesson.getTeacherId())) { + if(request.getTeacherId() == 0) { + return ResponseEntity.badRequest() + .body(Map.of("message", "ID преподавателя не может быть равен 0")); + } + existingLesson.setTeacherId(request.getTeacherId()); + changes.put("teacherId", request.getTeacherId()); + hasChanges = true; + } + } + + //Проверка и обновление groupId, если он передан и отличается + if(request.getGroupId() != null) { + if(!request.getGroupId().equals(existingLesson.getGroupId())) { + if(request.getGroupId() == 0) { + return ResponseEntity.badRequest() + .body(Map.of("message", "ID группы не может быть равен 0")); + } + existingLesson.setGroupId(request.getGroupId()); + changes.put("groupId", request.getGroupId()); + hasChanges = true; + } + } + + //Проверка и обновление subjectId, если он передан и отличается + if(request.getSubjectId() != null) { + if(!request.getSubjectId().equals(existingLesson.getSubjectId())) { + if(request.getSubjectId() == 0) { + return ResponseEntity.badRequest() + .body(Map.of("message", "ID дисциплины не может быть равен 0")); + } + existingLesson.setSubjectId(request.getSubjectId()); + changes.put("subjectId", request.getSubjectId()); + hasChanges = true; + } + } + + //Проверка и обновление lessonFormat, если он передан и отличается + if(request.getLessonFormat() != null) { + if(!request.getLessonFormat().equals(existingLesson.getLessonFormat())) { + if(request.getLessonFormat().isBlank()) { + return ResponseEntity.badRequest() + .body(Map.of("message", "Формат занятия не может быть пустым")); + } + if(!TypeAndFormatLessonValidator.isValidFormat(request.getLessonFormat())) { + String errorMessage = "Некорректный формат занятий. " + TypeAndFormatLessonValidator.getValidFormatsMessage(); + return ResponseEntity.badRequest().body(Map.of("message", errorMessage)); + } + existingLesson.setLessonFormat(request.getLessonFormat()); + changes.put("lessonFormat", request.getLessonFormat()); + hasChanges = true; + } + } + + //Проверка и обновление typeLesson, если он передан и отличается + if(request.getTypeLesson() != null) { + if(!request.getTypeLesson().equals(existingLesson.getTypeLesson())) { + if(request.getTypeLesson().isBlank()) { + return ResponseEntity.badRequest() + .body(Map.of("message", "Тип занятия не может быть пустым")); + } + if(!TypeAndFormatLessonValidator.isValidType(request.getTypeLesson())) { + String errorMessage = "Некорректный тип занятий. " + TypeAndFormatLessonValidator.getValidTypesMessage(); + return ResponseEntity.badRequest().body(Map.of("message", errorMessage)); + } + existingLesson.setLessonFormat(request.getTypeLesson()); + changes.put("typeLesson", request.getTypeLesson()); + hasChanges = true; + } + } + + //Проверка и обновление classroomId, если он передан и отличается + if(request.getClassroomId() != null) { + if(!request.getClassroomId().equals(existingLesson.getClassroomId())) { + if(request.getClassroomId() == 0) { + return ResponseEntity.badRequest() + .body(Map.of("message", "ID аудитории не можеть быть равен 0")); + } + existingLesson.setClassroomId(request.getClassroomId()); + changes.put("classroomId", request.getClassroomId()); + hasChanges = true; + } + } + + //Проверка и обновление day, если он передан и отличается + if(request.getDay() != null){ + if(!request.getDay().equals(existingLesson.getDay())) { + if(request.getDay().isBlank()) { + return ResponseEntity.badRequest() + .body(Map.of("message", "Поле \"День\" не может быть пустым")); + } + if(!DayAndWeekValidator.isValidDay(request.getDay())) { + String errorMessage = "Некорректный день. " + DayAndWeekValidator.getValidDaysMessage(); + return ResponseEntity.badRequest() + .body(Map.of("message", errorMessage)); + } + existingLesson.setDay(request.getDay()); + changes.put("day", request.getDay()); + hasChanges = true; + } + } + + //Проверка и обновление week, если он передан и отличается + if(request.getWeek() != null) { + if(!request.getWeek().equals(existingLesson.getWeek())) { + if (request.getWeek().isBlank()) { + return ResponseEntity.badRequest() + .body(Map.of("message", "Поле \"Неделя\" не может быть пустым")); + } + if (!DayAndWeekValidator.isValidWeek(request.getWeek())) { + String errorMessage = "Некорректная неделя. " + DayAndWeekValidator.getValidWeekMessage(); + return ResponseEntity.badRequest() + .body((Map.of("message", errorMessage))); + } + existingLesson.setWeek(request.getWeek()); + changes.put("week", request.getWeek()); + hasChanges = true; + } + } + + //Проверка и обновление time, если он передан и отличается + if(request.getTime() != null) { + if(!request.getTime().equals(existingLesson.getTime())) { + if(request.getTime().isBlank()){ + return ResponseEntity.badRequest() + .body(Map.of("message", "Поле \"Время\" не может быть пустым")); + } + existingLesson.setTime(request.getTime()); + changes.put("time", request.getTime()); + hasChanges = true; + } + } + + if(!hasChanges) { + logger.info("Обновление не требуется - все полня идентичны существующим для занятия с ID: {}", lessonId); + + Map response = buildResponse(existingLesson); + response.put("message", "Изменений не обнаружено"); + return ResponseEntity.ok(response); + } + + Lesson updatedLesson = lessonRepository.save(existingLesson); + + Map response = buildResponse(updatedLesson); + response.put("updatedFields", changes); + response.put("message", "Занятие успешно обновлено"); + + logger.info("Занятие с ID - {} успешно обновлено. Изменения: {}", lessonId, changes); + + return ResponseEntity.ok(response); + + } catch (Exception e) { + logger.error("Ошибка при обновлении занятия с ID {}: {}", lessonId, e.getMessage(),e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(Map.of("message", "Произошла ошибка при обновлении занятия: " + e.getMessage())); + } + } + + private Map buildResponse(Lesson lesson) { + Map response = new LinkedHashMap<>(); + response.put("id", lesson.getId()); + response.put("teacherId", lesson.getTeacherId()); + response.put("groupId", lesson.getGroupId()); + response.put("subjectId", lesson.getSubjectId()); + response.put("LessonFormat", lesson.getLessonFormat()); + response.put("typeLesson", lesson.getTypeLesson()); + response.put("classroomId", lesson.getClassroomId()); + response.put("day", lesson.getDay()); + response.put("week", lesson.getWeek()); + response.put("time", lesson.getTime()); + return response; + } } \ No newline at end of file diff --git a/backend/src/main/java/com/magistr/app/utils/TypeAndFormatLessonValidator.java b/backend/src/main/java/com/magistr/app/utils/TypeAndFormatLessonValidator.java index 91c7d71..21e3146 100644 --- a/backend/src/main/java/com/magistr/app/utils/TypeAndFormatLessonValidator.java +++ b/backend/src/main/java/com/magistr/app/utils/TypeAndFormatLessonValidator.java @@ -5,7 +5,7 @@ import java.util.Set; public class TypeAndFormatLessonValidator { private static final Set VALID_TYPES = Set.of( - "Лекция", "Лабораторная работа", "Практическая" + "Лекция", "Лабораторная работа", "Практическая работа" ); private static final Set VALID_FORMATS = Set.of( diff --git a/db/init/init.sql b/db/init/init.sql index eac8590..d55142b 100755 --- a/db/init/init.sql +++ b/db/init/init.sql @@ -17,7 +17,8 @@ CREATE TABLE IF NOT EXISTS users ( -- Админ по умолчанию: admin / admin (bcrypt через pgcrypto) INSERT INTO users (username, password, role) -VALUES ('admin', crypt('admin', gen_salt('bf', 10)), 'ADMIN') +VALUES ('admin', crypt('admin', gen_salt('bf', 10)), 'ADMIN'), + ('Тестовый преподаватель', '1234567890', 'TEACHER') ON CONFLICT (username) DO NOTHING; -- ========================================== @@ -194,6 +195,14 @@ CREATE TABLE IF NOT EXISTS lessons ( time VARCHAR(255) NOT NULL ); +INSERT INTO lessons (teacher_id, group_id, subject_id, lesson_format, type_lesson, classroom_id, day, week, time) VALUES + (2, 1, 1, 'Очно', 'Лекция', 1, 'Понедельник', 'Верхняя', '11:40 - 13:10'), + (1, 1, 2, 'Онлайн', 'Практическая работа', 2, 'Вторник', 'Нижняя', '15:00 - 16:30'), + (2, 1, 3, 'Очно', 'Лабораторная работа', 3, 'Среда', 'Верхняя', '8:00 - 9:30'), + (1, 1, 4, 'Онлайн', 'Лекция', 1, 'Четверг', 'Нижняя', '11:40 - 13:10'), + (2, 1, 5, 'Очно', 'Практическая работа', 2, 'Пятница', 'Верхняя', '15:00 - 16:30'), + (1, 1, 3, 'Онлайн', 'Лабораторная работа', 3, 'Суббота', 'Нижняя', '8:00 - 9:30'); + -- ========================================== -- Функция обновления timestamp -- ==========================================