feat: add subjects & teacher-subjects management tab in admin panel

This commit is contained in:
Zuev
2026-02-25 17:34:01 +03:00
parent 0ac81284fa
commit df6ddeecd5
14 changed files with 698 additions and 2 deletions

View File

@@ -0,0 +1,51 @@
package com.magistr.app.controller;
import com.magistr.app.model.Subject;
import com.magistr.app.repository.SubjectRepository;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/subjects")
public class SubjectController {
private final SubjectRepository subjectRepository;
public SubjectController(SubjectRepository subjectRepository) {
this.subjectRepository = subjectRepository;
}
@GetMapping
public List<Subject> getAllSubjects() {
return subjectRepository.findAll();
}
@PostMapping
public ResponseEntity<?> createSubject(@RequestBody Map<String, String> request) {
String name = request.get("name");
if (name == null || name.isBlank()) {
return ResponseEntity.badRequest().body(Map.of("message", "Название обязательно"));
}
if (subjectRepository.findByName(name.trim()).isPresent()) {
return ResponseEntity.badRequest().body(Map.of("message", "Дисциплина с таким названием уже существует"));
}
Subject subject = new Subject();
subject.setName(name.trim());
subjectRepository.save(subject);
return ResponseEntity.ok(subject);
}
@DeleteMapping("/{id}")
public ResponseEntity<?> deleteSubject(@PathVariable Long id) {
if (!subjectRepository.existsById(id)) {
return ResponseEntity.notFound().build();
}
subjectRepository.deleteById(id);
return ResponseEntity.ok(Map.of("message", "Дисциплина удалена"));
}
}

View File

@@ -0,0 +1,85 @@
package com.magistr.app.controller;
import com.magistr.app.dto.TeacherSubjectResponse;
import com.magistr.app.model.TeacherSubject;
import com.magistr.app.model.TeacherSubjectId;
import com.magistr.app.repository.SubjectRepository;
import com.magistr.app.repository.TeacherSubjectRepository;
import com.magistr.app.repository.UserRepository;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/teacher-subjects")
public class TeacherSubjectController {
private final TeacherSubjectRepository teacherSubjectRepository;
private final UserRepository userRepository;
private final SubjectRepository subjectRepository;
public TeacherSubjectController(TeacherSubjectRepository teacherSubjectRepository,
UserRepository userRepository,
SubjectRepository subjectRepository) {
this.teacherSubjectRepository = teacherSubjectRepository;
this.userRepository = userRepository;
this.subjectRepository = subjectRepository;
}
@GetMapping
public List<TeacherSubjectResponse> getAll() {
return teacherSubjectRepository.findAll().stream()
.map(ts -> new TeacherSubjectResponse(
ts.getUserId(),
ts.getUser().getUsername(),
ts.getSubjectId(),
ts.getSubject().getName()
))
.toList();
}
@PostMapping
public ResponseEntity<?> create(@RequestBody Map<String, Long> request) {
Long userId = request.get("userId");
Long subjectId = request.get("subjectId");
if (userId == null || subjectId == null) {
return ResponseEntity.badRequest().body(Map.of("message", "userId и subjectId обязательны"));
}
if (!userRepository.existsById(userId)) {
return ResponseEntity.badRequest().body(Map.of("message", "Преподаватель не найден"));
}
if (!subjectRepository.existsById(subjectId)) {
return ResponseEntity.badRequest().body(Map.of("message", "Дисциплина не найдена"));
}
TeacherSubjectId id = new TeacherSubjectId(userId, subjectId);
if (teacherSubjectRepository.existsById(id)) {
return ResponseEntity.badRequest().body(Map.of("message", "Привязка уже существует"));
}
TeacherSubject ts = new TeacherSubject(userId, subjectId);
teacherSubjectRepository.save(ts);
return ResponseEntity.ok(Map.of("message", "Привязка создана"));
}
@DeleteMapping
public ResponseEntity<?> delete(@RequestBody Map<String, Long> request) {
Long userId = request.get("userId");
Long subjectId = request.get("subjectId");
if (userId == null || subjectId == null) {
return ResponseEntity.badRequest().body(Map.of("message", "userId и subjectId обязательны"));
}
TeacherSubjectId id = new TeacherSubjectId(userId, subjectId);
if (!teacherSubjectRepository.existsById(id)) {
return ResponseEntity.notFound().build();
}
teacherSubjectRepository.deleteById(id);
return ResponseEntity.ok(Map.of("message", "Привязка удалена"));
}
}

View File

@@ -31,6 +31,13 @@ public class UserController {
.toList();
}
@GetMapping("/teachers")
public List<UserResponse> getTeachers() {
return userRepository.findByRole(Role.TEACHER).stream()
.map(u -> new UserResponse(u.getId(), u.getUsername(), u.getRole().name()))
.toList();
}
@PostMapping
public ResponseEntity<?> createUser(@RequestBody CreateUserRequest request) {
if (request.getUsername() == null || request.getUsername().isBlank()) {

View File

@@ -0,0 +1,32 @@
package com.magistr.app.dto;
public class TeacherSubjectResponse {
private Long userId;
private String username;
private Long subjectId;
private String subjectName;
public TeacherSubjectResponse(Long userId, String username, Long subjectId, String subjectName) {
this.userId = userId;
this.username = username;
this.subjectId = subjectId;
this.subjectName = subjectName;
}
public Long getUserId() {
return userId;
}
public String getUsername() {
return username;
}
public Long getSubjectId() {
return subjectId;
}
public String getSubjectName() {
return subjectName;
}
}

View File

@@ -0,0 +1,39 @@
package com.magistr.app.model;
import jakarta.persistence.*;
@Entity
@Table(name = "subjects")
public class Subject {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false, length = 200)
private String name;
public Subject() {
}
public Subject(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,57 @@
package com.magistr.app.model;
import jakarta.persistence.*;
@Entity
@Table(name = "teacher_subjects")
@IdClass(TeacherSubjectId.class)
public class TeacherSubject {
@Id
@Column(name = "user_id")
private Long userId;
@Id
@Column(name = "subject_id")
private Long subjectId;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id", insertable = false, updatable = false)
private User user;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "subject_id", insertable = false, updatable = false)
private Subject subject;
public TeacherSubject() {
}
public TeacherSubject(Long userId, Long subjectId) {
this.userId = userId;
this.subjectId = subjectId;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Long getSubjectId() {
return subjectId;
}
public void setSubjectId(Long subjectId) {
this.subjectId = subjectId;
}
public User getUser() {
return user;
}
public Subject getSubject() {
return subject;
}
}

View File

@@ -0,0 +1,46 @@
package com.magistr.app.model;
import java.io.Serializable;
import java.util.Objects;
public class TeacherSubjectId implements Serializable {
private Long userId;
private Long subjectId;
public TeacherSubjectId() {
}
public TeacherSubjectId(Long userId, Long subjectId) {
this.userId = userId;
this.subjectId = subjectId;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Long getSubjectId() {
return subjectId;
}
public void setSubjectId(Long subjectId) {
this.subjectId = subjectId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof TeacherSubjectId that)) return false;
return Objects.equals(userId, that.userId) && Objects.equals(subjectId, that.subjectId);
}
@Override
public int hashCode() {
return Objects.hash(userId, subjectId);
}
}

View File

@@ -0,0 +1,10 @@
package com.magistr.app.repository;
import com.magistr.app.model.Subject;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface SubjectRepository extends JpaRepository<Subject, Long> {
Optional<Subject> findByName(String name);
}

View File

@@ -0,0 +1,12 @@
package com.magistr.app.repository;
import com.magistr.app.model.TeacherSubject;
import com.magistr.app.model.TeacherSubjectId;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface TeacherSubjectRepository extends JpaRepository<TeacherSubject, TeacherSubjectId> {
List<TeacherSubject> findByUserId(Long userId);
List<TeacherSubject> findBySubjectId(Long subjectId);
}

View File

@@ -1,11 +1,15 @@
package com.magistr.app.repository;
import com.magistr.app.model.Role;
import com.magistr.app.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Optional;
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
List<User> findByRole(Role role);
}