feat: динамические формы обучения + вкладка группы в админке

This commit is contained in:
Zuev
2026-02-15 03:15:43 +03:00
parent 08ed6ebe36
commit 6774cd673c
12 changed files with 782 additions and 85 deletions

View File

@@ -0,0 +1,67 @@
package com.magistr.app.controller;
import com.magistr.app.model.EducationForm;
import com.magistr.app.model.StudentGroup;
import com.magistr.app.repository.EducationFormRepository;
import com.magistr.app.repository.GroupRepository;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/education-forms")
public class EducationFormController {
private final EducationFormRepository educationFormRepository;
private final GroupRepository groupRepository;
public EducationFormController(EducationFormRepository educationFormRepository,
GroupRepository groupRepository) {
this.educationFormRepository = educationFormRepository;
this.groupRepository = groupRepository;
}
@GetMapping
public List<Map<String, Object>> getAll() {
return educationFormRepository.findAll().stream()
.map(ef -> Map.<String, Object>of("id", ef.getId(), "name", ef.getName()))
.toList();
}
@PostMapping
public ResponseEntity<?> create(@RequestBody Map<String, String> body) {
String name = body.get("name");
if (name == null || name.isBlank()) {
return ResponseEntity.badRequest().body(Map.of("message", "Название обязательно"));
}
name = name.trim();
if (educationFormRepository.findByName(name).isPresent()) {
return ResponseEntity.badRequest().body(Map.of("message", "Такая форма обучения уже существует"));
}
EducationForm ef = new EducationForm();
ef.setName(name);
educationFormRepository.save(ef);
return ResponseEntity.ok(Map.of("id", ef.getId(), "name", ef.getName()));
}
@DeleteMapping("/{id}")
public ResponseEntity<?> delete(@PathVariable Long id) {
if (!educationFormRepository.existsById(id)) {
return ResponseEntity.notFound().build();
}
// Check if any groups use this education form
List<StudentGroup> linked = groupRepository.findByEducationFormId(id);
if (!linked.isEmpty()) {
return ResponseEntity.badRequest().body(Map.of(
"message", "Невозможно удалить: есть привязанные группы (" + linked.size() + ")"));
}
educationFormRepository.deleteById(id);
return ResponseEntity.ok(Map.of("message", "Форма обучения удалена"));
}
}

View File

@@ -0,0 +1,77 @@
package com.magistr.app.controller;
import com.magistr.app.dto.CreateGroupRequest;
import com.magistr.app.dto.GroupResponse;
import com.magistr.app.model.EducationForm;
import com.magistr.app.model.StudentGroup;
import com.magistr.app.repository.EducationFormRepository;
import com.magistr.app.repository.GroupRepository;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@RestController
@RequestMapping("/api/groups")
public class GroupController {
private final GroupRepository groupRepository;
private final EducationFormRepository educationFormRepository;
public GroupController(GroupRepository groupRepository,
EducationFormRepository educationFormRepository) {
this.groupRepository = groupRepository;
this.educationFormRepository = educationFormRepository;
}
@GetMapping
public List<GroupResponse> getAllGroups() {
return groupRepository.findAll().stream()
.map(g -> new GroupResponse(
g.getId(),
g.getName(),
g.getEducationForm().getId(),
g.getEducationForm().getName()))
.toList();
}
@PostMapping
public ResponseEntity<?> createGroup(@RequestBody CreateGroupRequest request) {
if (request.getName() == null || request.getName().isBlank()) {
return ResponseEntity.badRequest().body(Map.of("message", "Название группы обязательно"));
}
if (groupRepository.findByName(request.getName().trim()).isPresent()) {
return ResponseEntity.badRequest().body(Map.of("message", "Группа с таким названием уже существует"));
}
if (request.getEducationFormId() == null) {
return ResponseEntity.badRequest().body(Map.of("message", "Форма обучения обязательна"));
}
Optional<EducationForm> efOpt = educationFormRepository.findById(request.getEducationFormId());
if (efOpt.isEmpty()) {
return ResponseEntity.badRequest().body(Map.of("message", "Форма обучения не найдена"));
}
StudentGroup group = new StudentGroup();
group.setName(request.getName().trim());
group.setEducationForm(efOpt.get());
groupRepository.save(group);
return ResponseEntity.ok(new GroupResponse(
group.getId(),
group.getName(),
group.getEducationForm().getId(),
group.getEducationForm().getName()));
}
@DeleteMapping("/{id}")
public ResponseEntity<?> deleteGroup(@PathVariable Long id) {
if (!groupRepository.existsById(id)) {
return ResponseEntity.notFound().build();
}
groupRepository.deleteById(id);
return ResponseEntity.ok(Map.of("message", "Группа удалена"));
}
}

View File

@@ -0,0 +1,23 @@
package com.magistr.app.dto;
public class CreateGroupRequest {
private String name;
private Long educationFormId;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getEducationFormId() {
return educationFormId;
}
public void setEducationFormId(Long educationFormId) {
this.educationFormId = educationFormId;
}
}

View File

@@ -0,0 +1,32 @@
package com.magistr.app.dto;
public class GroupResponse {
private Long id;
private String name;
private Long educationFormId;
private String educationFormName;
public GroupResponse(Long id, String name, Long educationFormId, String educationFormName) {
this.id = id;
this.name = name;
this.educationFormId = educationFormId;
this.educationFormName = educationFormName;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public Long getEducationFormId() {
return educationFormId;
}
public String getEducationFormName() {
return educationFormName;
}
}

View File

@@ -0,0 +1,34 @@
package com.magistr.app.model;
import jakarta.persistence.*;
@Entity
@Table(name = "education_forms")
public class EducationForm {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false, length = 100)
private String name;
public EducationForm() {
}
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,46 @@
package com.magistr.app.model;
import jakarta.persistence.*;
@Entity
@Table(name = "student_groups")
public class StudentGroup {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false, length = 100)
private String name;
@ManyToOne(optional = false)
@JoinColumn(name = "education_form_id", nullable = false)
private EducationForm educationForm;
public StudentGroup() {
}
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;
}
public EducationForm getEducationForm() {
return educationForm;
}
public void setEducationForm(EducationForm educationForm) {
this.educationForm = educationForm;
}
}

View File

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

View File

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