From 194b0b0a4ad48e051ab3d5fa85f1b6983791a245 Mon Sep 17 00:00:00 2001 From: l-wanderer01 Date: Sun, 18 May 2025 22:10:37 +0900 Subject: [PATCH 1/7] =?UTF-8?q?[feat]=20admin=20=EA=B3=BC=EC=A0=9C=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20api=20=EB=A1=9C=EC=A7=81=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=EA=B3=BC=EC=A0=9C=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20API=EB=AA=85=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AssignmentController.java | 55 ++++++++++++ .../dto/request/AssignmentReq.java | 5 +- .../dto/response/AssignmentDayRes.java | 2 +- .../dto/response/AssignmentDetailRes.java | 4 +- .../dto/response/AssignmentRes.java | 6 +- .../dto/response/AssignmentWeekRes.java | 4 +- .../Assignment/entity/Assignment.java | 52 ++++++++++++ .../Assignment/entity/AssignmentItem.java | 32 +++++++ .../entity/AssignmentStatus.java | 2 +- .../repository/AssignmentItemRepository.java} | 10 +-- .../repository/AssignmentRepository.java | 9 ++ .../Assignment/service/AssignmentService.java | 79 ++++++++++++++++++ .../Deposit/service/DepositService.java | 10 +-- .../backend/pirocheck/User/entity/User.java | 18 ++++ .../controller/AssignmentController.java | 36 -------- .../assignment/entity/Assignment.java | 49 ----------- .../assignment/service/AssignmentService.java | 83 ------------------- .../backend/pirocheck/config/WebConfig.java | 4 +- 18 files changed, 268 insertions(+), 192 deletions(-) create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java rename backend/pirocheck/src/main/java/backend/pirocheck/{assignment => Assignment}/dto/request/AssignmentReq.java (60%) rename backend/pirocheck/src/main/java/backend/pirocheck/{assignment => Assignment}/dto/response/AssignmentDayRes.java (81%) rename backend/pirocheck/src/main/java/backend/pirocheck/{assignment => Assignment}/dto/response/AssignmentDetailRes.java (63%) rename backend/pirocheck/src/main/java/backend/pirocheck/{assignment => Assignment}/dto/response/AssignmentRes.java (66%) rename backend/pirocheck/src/main/java/backend/pirocheck/{assignment => Assignment}/dto/response/AssignmentWeekRes.java (62%) create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentItem.java rename backend/pirocheck/src/main/java/backend/pirocheck/{assignment => Assignment}/entity/AssignmentStatus.java (60%) rename backend/pirocheck/src/main/java/backend/pirocheck/{assignment/repository/AssignmentRepository.java => Assignment/repository/AssignmentItemRepository.java} (50%) create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentRepository.java create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java delete mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/assignment/controller/AssignmentController.java delete mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/assignment/entity/Assignment.java delete mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/assignment/service/AssignmentService.java diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java new file mode 100644 index 0000000..c6663e4 --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java @@ -0,0 +1,55 @@ +package backend.pirocheck.Assignment.controller; + +import backend.pirocheck.Assignment.dto.request.AssignmentReq; +import backend.pirocheck.Assignment.dto.response.AssignmentWeekRes; +import backend.pirocheck.Assignment.service.AssignmentService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api") +@RequiredArgsConstructor +public class AssignmentController { + + private final AssignmentService assignmentService; + + // 과제 결과 확인 API + // 과제 주차별, 요일별 그룹화 JSON + @GetMapping("/assignment/{userId}") + public List getGroupedAssignments(@PathVariable Long userId) { + return assignmentService.search(userId); + } + + // 과제 생성 API + @PostMapping("/admin/assignment/signup") + public String signupAssignment(@RequestBody AssignmentReq assignmentReq) { + return assignmentService.create(assignmentReq); + } + + // 과제 삭제 API + @DeleteMapping("/admin/assignment/delete") + public String deleteAssignment(@RequestBody AssignmentReq assignmentReq) { + return null; + } + + // 과제 수정 API + @PatchMapping("/admin/assignment/update") + public String updateAssignment(@RequestBody AssignmentReq assignmentReq) { + return null; + } + + // 사용자별 과제 제출 여부 생성 API + @PostMapping("/admin/users/{userId}/assignments/{assignmentId}/submission") + public String submissionAssignment(@PathVariable Long userId, @PathVariable Long assignmentId) { + return null; + } + + // 사용자별 과제 제출 여부 수정 API + @PatchMapping("/api/users/{userId}/assignments/{assignmentId}/submission") + public String updateSubmission(@PathVariable Long userId, @PathVariable Long assignmentId) { + return null; + } + +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/request/AssignmentReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentReq.java similarity index 60% rename from backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/request/AssignmentReq.java rename to backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentReq.java index 3d1cfd6..52e05a2 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/request/AssignmentReq.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentReq.java @@ -1,6 +1,5 @@ -package backend.pirocheck.assignment.dto.request; +package backend.pirocheck.Assignment.dto.request; -import backend.pirocheck.assignment.entity.AssignmentStatus; import lombok.AllArgsConstructor; import lombok.Getter; @@ -10,7 +9,7 @@ public class AssignmentReq { private String assignmentName; private Long week; - private Long section; + private String day; private Long orderNumber; } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/response/AssignmentDayRes.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentDayRes.java similarity index 81% rename from backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/response/AssignmentDayRes.java rename to backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentDayRes.java index be325e6..2f46e6a 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/response/AssignmentDayRes.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentDayRes.java @@ -1,4 +1,4 @@ -package backend.pirocheck.assignment.dto.response; +package backend.pirocheck.Assignment.dto.response; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/response/AssignmentDetailRes.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentDetailRes.java similarity index 63% rename from backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/response/AssignmentDetailRes.java rename to backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentDetailRes.java index 5a40dad..9c0f7f3 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/response/AssignmentDetailRes.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentDetailRes.java @@ -1,6 +1,6 @@ -package backend.pirocheck.assignment.dto.response; +package backend.pirocheck.Assignment.dto.response; -import backend.pirocheck.assignment.entity.AssignmentStatus; +import backend.pirocheck.Assignment.entity.AssignmentStatus; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/response/AssignmentRes.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentRes.java similarity index 66% rename from backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/response/AssignmentRes.java rename to backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentRes.java index c924848..ef2ad37 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/response/AssignmentRes.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentRes.java @@ -1,6 +1,6 @@ -package backend.pirocheck.assignment.dto.response; +package backend.pirocheck.Assignment.dto.response; -import backend.pirocheck.assignment.entity.AssignmentStatus; +import backend.pirocheck.Assignment.entity.AssignmentStatus; import lombok.AllArgsConstructor; import lombok.Getter; @@ -11,7 +11,7 @@ public class AssignmentRes { // private Long userId; private String assignmentName; private Long week; - private Long section; + private String day; private Long orderNumber; private AssignmentStatus submitted; diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/response/AssignmentWeekRes.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentWeekRes.java similarity index 62% rename from backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/response/AssignmentWeekRes.java rename to backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentWeekRes.java index 4be2d26..687505c 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/dto/response/AssignmentWeekRes.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentWeekRes.java @@ -1,4 +1,4 @@ -package backend.pirocheck.assignment.dto.response; +package backend.pirocheck.Assignment.dto.response; import lombok.AllArgsConstructor; import lombok.Getter; @@ -9,6 +9,6 @@ @AllArgsConstructor public class AssignmentWeekRes { private Long week; - private String title; // 각 주차 주제 (e.g, Git / HTML / CSS) +// private String title; // 각 주차 주제 (e.g, Git / HTML / CSS) private List days; } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java new file mode 100644 index 0000000..f9f8c8e --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java @@ -0,0 +1,52 @@ +package backend.pirocheck.Assignment.entity; + +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder(access = AccessLevel.PRIVATE) +@NoArgsConstructor +@AllArgsConstructor +public class Assignment { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + // 과제명 + private String assignmentName; + + // 주차 + private Long week; + + // 요일 + private String day; + + // 과제 번호 + private Long orderNumber; + + // AssignmentItem 입장에서 "assignment" 필드의 외래 키를 가진 주인 + // assignment를 참조하는 assignmentitem 컬랙션을 가짐 + @OneToMany(mappedBy = "assignment", cascade = CascadeType.ALL, orphanRemoval = true) + private List assignments = new ArrayList<>(); + + // 연관관계 편의 메서드 (양방향 시 자주 사용) + public void addAssignmentItem(AssignmentItem assignmentItem) { + this.assignments.add(assignmentItem); + assignmentItem.setAssignment(this); + } + + // 관리자가 생성 + public static Assignment create(String assignmentName, Long week, String day, Long orderNumber) { + return Assignment.builder() + .assignmentName(assignmentName) + .week(week) + .day(day) + .orderNumber(orderNumber) + .build(); + } +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentItem.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentItem.java new file mode 100644 index 0000000..bb88fae --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentItem.java @@ -0,0 +1,32 @@ +package backend.pirocheck.Assignment.entity; + +import backend.pirocheck.User.entity.User; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class AssignmentItem { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; // 유저별 과제 정보를 저장하는 ID + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "assignment_id") + private Assignment assignment; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + // 과제 결과 + @Enumerated(EnumType.STRING) + @Column(length = 100) + private AssignmentStatus submitted; // 수강생의 과제 제출여부 +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/entity/AssignmentStatus.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentStatus.java similarity index 60% rename from backend/pirocheck/src/main/java/backend/pirocheck/assignment/entity/AssignmentStatus.java rename to backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentStatus.java index dcc9466..290cfea 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/entity/AssignmentStatus.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentStatus.java @@ -1,4 +1,4 @@ -package backend.pirocheck.assignment.entity; +package backend.pirocheck.Assignment.entity; public enum AssignmentStatus { SUCCESS, INSUFFICIENT, FAILURE; diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/repository/AssignmentRepository.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentItemRepository.java similarity index 50% rename from backend/pirocheck/src/main/java/backend/pirocheck/assignment/repository/AssignmentRepository.java rename to backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentItemRepository.java index c0048f9..9d01975 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/repository/AssignmentRepository.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentItemRepository.java @@ -1,18 +1,18 @@ -package backend.pirocheck.assignment.repository; +package backend.pirocheck.Assignment.repository; import backend.pirocheck.User.entity.User; -import backend.pirocheck.assignment.entity.Assignment; -import backend.pirocheck.assignment.entity.AssignmentStatus; +import backend.pirocheck.Assignment.entity.AssignmentItem; +import backend.pirocheck.Assignment.entity.AssignmentStatus; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.List; @Repository -public interface AssignmentRepository extends JpaRepository { +public interface AssignmentItemRepository extends JpaRepository { // 유저별 과제 목록 조회 - List findByUserId(Long userId); + List findByUserId(Long userId); // 보증금 int countByUserAndSubmitted(User user, AssignmentStatus status); diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentRepository.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentRepository.java new file mode 100644 index 0000000..30fa1a1 --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentRepository.java @@ -0,0 +1,9 @@ +package backend.pirocheck.Assignment.repository; + +import backend.pirocheck.Assignment.entity.Assignment; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface AssignmentRepository extends JpaRepository { +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java new file mode 100644 index 0000000..606588b --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java @@ -0,0 +1,79 @@ +package backend.pirocheck.Assignment.service; + +import backend.pirocheck.Assignment.dto.request.AssignmentReq; +import backend.pirocheck.Assignment.dto.response.AssignmentDayRes; +import backend.pirocheck.Assignment.dto.response.AssignmentDetailRes; +import backend.pirocheck.Assignment.dto.response.AssignmentWeekRes; +import backend.pirocheck.Assignment.entity.Assignment; +import backend.pirocheck.Assignment.entity.AssignmentItem; +import backend.pirocheck.Assignment.repository.AssignmentItemRepository; +import backend.pirocheck.Assignment.repository.AssignmentRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +@Transactional +@RequiredArgsConstructor +public class AssignmentService { + + private final AssignmentItemRepository assignmentItemRepository; + private final AssignmentRepository assignmentRepository; + + public List search(Long userId) { + + List assignments = assignmentItemRepository.findByUserId(userId); + // week 기준으로 그룹화 + Map> weekGroup = assignments.stream() + .collect(Collectors.groupingBy(item -> item.getAssignment().getWeek())); // assignmentItems를 week 별로 그룹핑 + + List assignmentResponses = new ArrayList<>(); + + for (Map.Entry> entry : weekGroup.entrySet()) { + Long week = entry.getKey(); + List assignmentList = entry.getValue(); + + // day를 기준으로 그룹핑 + Map> dayGroup = assignmentList.stream() + .collect(Collectors.groupingBy(item -> item.getAssignment().getDay())); + + List assignmentDayResList = new ArrayList<>(); + + for (Map.Entry> dayEntry : dayGroup.entrySet()) { + String day = dayEntry.getKey(); + List dayAssignmentList = dayEntry.getValue(); + + // 세부 과제명과 과제 결과를 리스트 형태로 + List assignmentDetailResList = dayAssignmentList.stream() + .map(assignmentItem -> new AssignmentDetailRes( + assignmentItem.getAssignment().getAssignmentName(), + assignmentItem.getSubmitted() + )) + .toList(); + assignmentDayResList.add(new AssignmentDayRes(day, assignmentDetailResList)); + } + + assignmentResponses.add(new AssignmentWeekRes(week, assignmentDayResList)); + } + + return assignmentResponses; + } + + public String create(AssignmentReq assignmentReq) { + + Assignment assignment = Assignment.create( + assignmentReq.getAssignmentName(), + assignmentReq.getWeek(), + assignmentReq.getDay(), + assignmentReq.getOrderNumber()); + + assignment = assignmentRepository.save(assignment); + + return assignment.getAssignmentName(); + } +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Deposit/service/DepositService.java b/backend/pirocheck/src/main/java/backend/pirocheck/Deposit/service/DepositService.java index ce3da5f..66eafb1 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Deposit/service/DepositService.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Deposit/service/DepositService.java @@ -6,8 +6,8 @@ import backend.pirocheck.Deposit.repository.DepositRepository; import backend.pirocheck.User.entity.User; import backend.pirocheck.User.repository.UserRepository; -import backend.pirocheck.assignment.entity.AssignmentStatus; -import backend.pirocheck.assignment.repository.AssignmentRepository; +import backend.pirocheck.Assignment.entity.AssignmentStatus; +import backend.pirocheck.Assignment.repository.AssignmentItemRepository; import backend.pirocheck.Attendance.repository.AttendanceRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; @@ -20,7 +20,7 @@ public class DepositService { private final DepositRepository depositRepository; private final UserRepository userRepository; private final AttendanceRepository attendanceRepository; - private final AssignmentRepository assignmentRepository; + private final AssignmentItemRepository assignmentItemRepository; @Transactional public DepositResDto getDeposit(Long userId) { @@ -34,8 +34,8 @@ public DepositResDto getDeposit(Long userId) { int descentAttendance = failAttendanceCount * 10_000; // 과제 실패 - int failAssignmentCount = assignmentRepository.countByUserAndSubmitted(user, AssignmentStatus.FAILURE); - int weakAssignmentCount = assignmentRepository.countByUserAndSubmitted(user, AssignmentStatus.INSUFFICIENT); + int failAssignmentCount = assignmentItemRepository.countByUserAndSubmitted(user, AssignmentStatus.FAILURE); + int weakAssignmentCount = assignmentItemRepository.countByUserAndSubmitted(user, AssignmentStatus.INSUFFICIENT); int descentAssignment = failAssignmentCount * 20_000 + weakAssignmentCount * 10_000; // 방어권 diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/User/entity/User.java b/backend/pirocheck/src/main/java/backend/pirocheck/User/entity/User.java index ad215b0..65b6717 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/User/entity/User.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/User/entity/User.java @@ -1,11 +1,15 @@ package backend.pirocheck.User.entity; +import backend.pirocheck.Assignment.entity.AssignmentItem; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.ArrayList; +import java.util.List; + @Entity @Getter @Table(name="users") @@ -30,6 +34,20 @@ public class User { @Enumerated(EnumType.STRING) private Role role; // MEMBER or ADMIN + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) + private List assignmentItems = new ArrayList<>(); + private Integer generation; + // AssignmentItem 입장에서 "user" 필드의 외래 키를 가진 주인 + // assignment를 참조하는 assignmentitem 컬랙션을 가짐 + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) + private List assignments = new ArrayList<>(); + + // 연관관계 편의 메서드 (양방향 시 자주 사용) + public void addAssignmentItem(AssignmentItem assignmentItem) { + this.assignments.add(assignmentItem); + assignmentItem.setUser(this); + } + } \ No newline at end of file diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/controller/AssignmentController.java b/backend/pirocheck/src/main/java/backend/pirocheck/assignment/controller/AssignmentController.java deleted file mode 100644 index 0c1379f..0000000 --- a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/controller/AssignmentController.java +++ /dev/null @@ -1,36 +0,0 @@ -package backend.pirocheck.assignment.controller; - -import backend.pirocheck.assignment.dto.request.AssignmentReq; -import backend.pirocheck.assignment.dto.response.AssignmentRes; -import backend.pirocheck.assignment.dto.response.AssignmentWeekRes; -import backend.pirocheck.assignment.service.AssignmentService; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -@RestController -@RequestMapping("/api/assignment") -@RequiredArgsConstructor -public class AssignmentController { - - private final AssignmentService assignmentService; - - // 과제 결과 확인 API -// @GetMapping("/{userId}") -// public List getAssignment(@PathVariable("userId") Long userId) { -// // 주차별 과제 제목, 요일별 과제 제목, 과제 상태 반환 -// return assignmentService.search(userId); -// } - // 과제 주차별, 요일별 그룹화 JSON - @GetMapping("/grouped/{userId}") - public List getGroupedAssignments(@PathVariable Long userId) { - return assignmentService.search(userId); - } - - // 과제 생성 API - @PostMapping("/signup") - public String signupAssignment(@RequestBody AssignmentReq assignmentReq) { - return assignmentService.create(assignmentReq); - } -} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/entity/Assignment.java b/backend/pirocheck/src/main/java/backend/pirocheck/assignment/entity/Assignment.java deleted file mode 100644 index 62aa724..0000000 --- a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/entity/Assignment.java +++ /dev/null @@ -1,49 +0,0 @@ -package backend.pirocheck.assignment.entity; - -import backend.pirocheck.User.entity.User; -import jakarta.persistence.*; -import lombok.*; - -@Entity -@Getter -@Builder(access = AccessLevel.PRIVATE) -@NoArgsConstructor -@AllArgsConstructor -public class Assignment { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - // user 정보와 과제 정보를 연결해 저장 - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; // user를 생성했을 때의 해당 user 엔티티 - - // 과제명 - private String assignmentName; - - // 주차 - private Long week; - - // 요일 - private Long section; - - // 과제 번호 - private Long orderNumber; - - // 과제 결과 - @Enumerated(EnumType.STRING) - @Column(length = 100) - private AssignmentStatus submitted; - - // 관리자가 생성 - public static Assignment create(String assignmentName, Long week, Long section, Long orderNumber) { - return Assignment.builder() - .assignmentName(assignmentName) - .week(week) - .section(section) - .orderNumber(orderNumber) - .build(); - } -} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/service/AssignmentService.java b/backend/pirocheck/src/main/java/backend/pirocheck/assignment/service/AssignmentService.java deleted file mode 100644 index d98b74b..0000000 --- a/backend/pirocheck/src/main/java/backend/pirocheck/assignment/service/AssignmentService.java +++ /dev/null @@ -1,83 +0,0 @@ -package backend.pirocheck.assignment.service; - -import backend.pirocheck.assignment.dto.request.AssignmentReq; -import backend.pirocheck.assignment.dto.response.AssignmentDayRes; -import backend.pirocheck.assignment.dto.response.AssignmentDetailRes; -import backend.pirocheck.assignment.dto.response.AssignmentRes; -import backend.pirocheck.assignment.dto.response.AssignmentWeekRes; -import backend.pirocheck.assignment.entity.Assignment; -import backend.pirocheck.assignment.repository.AssignmentRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Service -@Transactional -@RequiredArgsConstructor -public class AssignmentService { - - private final AssignmentRepository assignmentRepository; - - // 그룹화 되지 않은 JSON 형식 -// public List search(Long userId) { -// // 각 유저별 전체 과제 목록 조회 (userId를 어떻게 넘길 것인가?) search의 인자로 넘긴다... -// List assignments = assignmentRepository.findByUserId(userId); -// -// return assignments.stream() -// .map(assignment -> new AssignmentRes(assignment.getAssignmentName(), assignment.getWeek(), assignment.getSection(), assignment.getOrderNumber(), assignment.getSubmitted())) -// .toList(); -// } - public List search(Long userId) { - - List assignments = assignmentRepository.findByUserId(userId); - // week 기준으로 그룹화 - Map> weekGroup = assignments.stream() - .collect(Collectors.groupingBy(Assignment::getWeek)); // assignments를 week 별로 그룹핑 - - List assignmentResponses = new ArrayList<>(); - - for (Map.Entry> entry : weekGroup.entrySet()) { - Long week = entry.getKey(); - List assignmentList = entry.getValue(); - - // day를 기준으로 그룹핑 - Map> dayGroup = assignments.stream() - .collect(Collectors.groupingBy(Assignment::getSection)); - - List assignmentDayResList = new ArrayList<>(); - - for (Map.Entry> dayEntry : dayGroup.entrySet()) { - Long day = dayEntry.getKey(); - List dayAssignmentList = dayEntry.getValue(); - - // 세부 과제명과 과제 결과를 리스트 형태로 - List assignmentDetailResList = dayAssignmentList.stream() - .map(assignment -> new AssignmentDetailRes( - assignment.getAssignmentName(), - assignment.getSubmitted() - )) - .toList(); - } - } - - return assignmentResponses; - } - - public String create(AssignmentReq assignmentReq) { - - Assignment assignment = Assignment.create( - assignmentReq.getAssignmentName(), - assignmentReq.getWeek(), - assignmentReq.getSection(), - assignmentReq.getOrderNumber()); - - assignment = assignmentRepository.save(assignment); - - return assignment.getAssignmentName(); - } -} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java index f729c5c..1dcff3e 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/config/WebConfig.java @@ -12,7 +12,7 @@ public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") // 백엔드 API 요청에만 CORS 허용 .allowedOrigins("http://www.pirocheck.org") // 프론트 배포 URL .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 허용할 HTTP 메서드 - .allowCredentials(true) // 세션 쿠키 주고받기 허용 - .allowedHeaders("*"); + .allowedHeaders("*") + .allowCredentials(true); // 세션 쿠키 주고받기 허용 } } From f2ccf896c31d527b1a839c4ed04084c85fa5083e Mon Sep 17 00:00:00 2001 From: dietken1 Date: Sun, 18 May 2025 23:20:16 +0900 Subject: [PATCH 2/7] =?UTF-8?q?api=20response=20=EB=B0=8F=20swagger?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AdminAttendanceController.java | 107 ++++++++++++++++++ .../dto/response/AttendanceMarkResponse.java | 68 +++++++++++ .../pirocheck/config/SwaggerConfig.java | 24 ++++ 3 files changed, 199 insertions(+) create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/Attendance/controller/AdminAttendanceController.java create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceMarkResponse.java create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/config/SwaggerConfig.java diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/controller/AdminAttendanceController.java b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/controller/AdminAttendanceController.java new file mode 100644 index 0000000..f811f53 --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/controller/AdminAttendanceController.java @@ -0,0 +1,107 @@ +package backend.pirocheck.Attendance.controller; + +import backend.pirocheck.Attendance.dto.response.ApiResponse; +import backend.pirocheck.Attendance.dto.response.AttendanceCodeResponse; +import backend.pirocheck.Attendance.entity.AttendanceCode; +import backend.pirocheck.Attendance.service.AttendanceService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.Optional; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/admin/attendance") +@Tag(name = "관리자 출석관리", description = "관리자용 출석 관리 API") +public class AdminAttendanceController { + + private final AttendanceService attendanceService; + + // 출석체크 시작 + @Operation(summary = "출석 체크 시작", description = "새로운 출석 코드를 생성하고 출석 체크를 시작합니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse( + responseCode = "200", + description = "출석 코드 생성 성공", + content = @Content(schema = @Schema(implementation = AttendanceCodeResponse.class)) + ), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "잘못된 요청") + }) + @PostMapping("/start") + public ApiResponse startAttendance() { + try { + AttendanceCode code = attendanceService.generateCodeAndCreateAttendances(); + return ApiResponse.success(AttendanceCodeResponse.from(code)); + } catch (IllegalStateException e) { + // 하루 최대 출석 체크 횟수를 초과한 경우 + return ApiResponse.error(e.getMessage()); + } catch (Exception e) { + return ApiResponse.error("출석 코드 생성 중 오류가 발생했습니다: " + e.getMessage()); + } + } + + // 현재 활성화된 출석코드 조회 + @Operation(summary = "현재 활성화된 출석 코드 조회", description = "현재 활성화된 출석 코드 정보를 조회합니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse( + responseCode = "200", + description = "조회 성공", + content = @Content(schema = @Schema(implementation = AttendanceCodeResponse.class)) + ), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "활성화된 출석 코드 없음") + }) + @GetMapping("/active-code") + public ApiResponse getActiveCode() { + Optional codeOpt = attendanceService.getActiveAttendanceCode(); + + if (codeOpt.isEmpty()) { + return ApiResponse.error("현재 활성화된 출석코드가 없습니다"); + } + + return ApiResponse.success(AttendanceCodeResponse.from(codeOpt.get())); + } + + // 출석체크 종료 (코드 직접 전달) + @Operation(summary = "특정 출석 코드 만료", description = "특정 출석 코드를 만료 처리합니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "만료 처리 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "잘못된 요청"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "출석 코드를 찾을 수 없음") + }) + @PutMapping("/expire") + public ApiResponse expireAttendance( + @Parameter(description = "만료할 출석 코드", required = true) + @RequestParam String code) { + String result = attendanceService.exprireAttendanceCode(code); + + if (result.equals("출석 코드가 성공적으로 만료되었습니다")) { + return ApiResponse.success(result, null); + } else { + return ApiResponse.error(result); + } + } + + // 출석체크 종료 (가장 최근 활성화된 코드 자동 만료) + @Operation(summary = "최근 활성화된 출석 코드 만료", description = "가장 최근 활성화된 출석 코드를 자동으로 만료 처리합니다.") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "만료 처리 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "활성화된 출석 코드가 없음") + }) + @PutMapping("/expire-latest") + public ApiResponse expireLatestAttendance() { + String result = attendanceService.expireLatestAttendanceCode(); + + if (result.equals("출석 코드가 성공적으로 만료되었습니다")) { + return ApiResponse.success(result, null); + } else { + return ApiResponse.error(result); + } + } +} \ No newline at end of file diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceMarkResponse.java b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceMarkResponse.java new file mode 100644 index 0000000..73ee0d7 --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Attendance/dto/response/AttendanceMarkResponse.java @@ -0,0 +1,68 @@ +package backend.pirocheck.Attendance.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(description = "출석 체크 응답") +public class AttendanceMarkResponse { + @Schema(description = "응답 메시지", example = "출석이 성공적으로 처리되었습니다") + private String message; + + @Schema(description = "상태 코드 (SUCCESS, ALREADY_MARKED, INVALID_CODE, NO_ACTIVE_SESSION, CODE_EXPIRED, ERROR)", example = "SUCCESS") + private String statusCode; + + // 출석 성공 + public static AttendanceMarkResponse success() { + return AttendanceMarkResponse.builder() + .statusCode("SUCCESS") + .message("출석이 성공적으로 처리되었습니다") + .build(); + } + + // 이미 출석 완료 + public static AttendanceMarkResponse alreadyMarked() { + return AttendanceMarkResponse.builder() + .statusCode("ALREADY_MARKED") + .message("이미 출석처리가 완료되었습니다") + .build(); + } + + // 출석체크 진행중 아님 + public static AttendanceMarkResponse noActiveSession() { + return AttendanceMarkResponse.builder() + .statusCode("NO_ACTIVE_SESSION") + .message("출석 코드가 존재하지 않습니다. 현재 출석 체크가 진행중이 아닙니다") + .build(); + } + + // 잘못된 출석 코드 입력 + public static AttendanceMarkResponse invalidCode() { + return AttendanceMarkResponse.builder() + .statusCode("INVALID_CODE") + .message("잘못된 출석 코드입니다. 다시 확인해주세요") + .build(); + } + + // 출석 코드 만료 + public static AttendanceMarkResponse codeExpired() { + return AttendanceMarkResponse.builder() + .statusCode("CODE_EXPIRED") + .message("출석 코드가 만료되었습니다") + .build(); + } + + // 기타 오류 + public static AttendanceMarkResponse error(String message) { + return AttendanceMarkResponse.builder() + .statusCode("ERROR") + .message(message) + .build(); + } +} \ No newline at end of file diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/config/SwaggerConfig.java b/backend/pirocheck/src/main/java/backend/pirocheck/config/SwaggerConfig.java new file mode 100644 index 0000000..aa87446 --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/config/SwaggerConfig.java @@ -0,0 +1,24 @@ +package backend.pirocheck.config; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import io.swagger.v3.oas.models.servers.Server; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SwaggerConfig { + + @Bean + public OpenAPI openAPI() { + return new OpenAPI() + .info(new Info() + .title("PiroCheck API") + .description("피로그래밍 출석체크 시스템 API 문서") + .version("v1.0.0") + .license(new License().name("MIT").url("https://opensource.org/licenses/MIT"))) + .addServersItem(new Server().url("/").description("Default Server URL")); + } +} \ No newline at end of file From fdaf4a28e18c229b4d8162fef76acee5e1287973 Mon Sep 17 00:00:00 2001 From: l-wanderer01 Date: Sun, 18 May 2025 23:34:42 +0900 Subject: [PATCH 3/7] =?UTF-8?q?[feat]=20=EA=B3=BC=EC=A0=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AssignmentController.java | 26 ++++++++++------- ...nmentReq.java => AssignmentCreateReq.java} | 2 +- .../dto/request/AssignmentUpdateReq.java | 14 ++++++++++ .../Assignment/entity/Assignment.java | 8 ++++++ .../repository/AssignmentItemRepository.java | 4 +-- .../repository/AssignmentRepository.java | 2 +- .../Assignment/service/AssignmentService.java | 28 +++++++++++++++---- .../service/ManageStudentsService.java | 15 +++++----- 8 files changed, 71 insertions(+), 28 deletions(-) rename backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/{AssignmentReq.java => AssignmentCreateReq.java} (87%) create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java index c6663e4..879b048 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java @@ -1,6 +1,7 @@ package backend.pirocheck.Assignment.controller; -import backend.pirocheck.Assignment.dto.request.AssignmentReq; +import backend.pirocheck.Assignment.dto.request.AssignmentCreateReq; +import backend.pirocheck.Assignment.dto.request.AssignmentUpdateReq; import backend.pirocheck.Assignment.dto.response.AssignmentWeekRes; import backend.pirocheck.Assignment.service.AssignmentService; import lombok.RequiredArgsConstructor; @@ -24,20 +25,25 @@ public List getGroupedAssignments(@PathVariable Long userId) // 과제 생성 API @PostMapping("/admin/assignment/signup") - public String signupAssignment(@RequestBody AssignmentReq assignmentReq) { - return assignmentService.create(assignmentReq); + public String signupAssignment(@RequestBody AssignmentCreateReq assignmentCreateReq) { + return assignmentService.createAssignment(assignmentCreateReq); } // 과제 삭제 API - @DeleteMapping("/admin/assignment/delete") - public String deleteAssignment(@RequestBody AssignmentReq assignmentReq) { - return null; + @DeleteMapping("/admin/assignment/{assignmentId}") + public String deleteAssignment( + @PathVariable Long assignmentId + ) { + return assignmentService.deleteAssignment(assignmentId); } // 과제 수정 API - @PatchMapping("/admin/assignment/update") - public String updateAssignment(@RequestBody AssignmentReq assignmentReq) { - return null; + @PutMapping("/admin/assignment/{assignmentId}") + public String updateAssignment( + @PathVariable("assignmentId") Long assignmentId, + @RequestBody AssignmentUpdateReq assignmentUpdateReq + ) { + return assignmentService.updateAssignment(assignmentId, assignmentUpdateReq); } // 사용자별 과제 제출 여부 생성 API @@ -47,7 +53,7 @@ public String submissionAssignment(@PathVariable Long userId, @PathVariable Long } // 사용자별 과제 제출 여부 수정 API - @PatchMapping("/api/users/{userId}/assignments/{assignmentId}/submission") + @PutMapping("/api/users/{userId}/assignments/{assignmentId}/submission") public String updateSubmission(@PathVariable Long userId, @PathVariable Long assignmentId) { return null; } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java similarity index 87% rename from backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentReq.java rename to backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java index 52e05a2..123e16e 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentReq.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java @@ -5,7 +5,7 @@ @Getter @AllArgsConstructor -public class AssignmentReq { +public class AssignmentCreateReq { private String assignmentName; private Long week; diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java new file mode 100644 index 0000000..5941f88 --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java @@ -0,0 +1,14 @@ +package backend.pirocheck.Assignment.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class AssignmentUpdateReq { + + private String assignmentName; + private Long week; + private String day; + private Long orderNumber; +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java index f9f8c8e..c51b0d3 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java @@ -49,4 +49,12 @@ public static Assignment create(String assignmentName, Long week, String day, Lo .orderNumber(orderNumber) .build(); } + + // 과제 내용 업데이트 + public void update(String assignmentName, Long week, String day, Long orderNumber) { + this.assignmentName = assignmentName; + this.week = week; + this.day = day; + this.orderNumber = orderNumber; + } } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentItemRepository.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentItemRepository.java index 9d01975..1a39eec 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentItemRepository.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentItemRepository.java @@ -1,15 +1,15 @@ package backend.pirocheck.Assignment.repository; -import backend.pirocheck.User.entity.User; import backend.pirocheck.Assignment.entity.AssignmentItem; import backend.pirocheck.Assignment.entity.AssignmentStatus; +import backend.pirocheck.User.entity.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.List; @Repository -public interface AssignmentItemRepository extends JpaRepository { +public interface AssignmentItemRepository extends JpaRepository { // 유저별 과제 목록 조회 List findByUserId(Long userId); diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentRepository.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentRepository.java index 30fa1a1..408e69c 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentRepository.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/repository/AssignmentRepository.java @@ -5,5 +5,5 @@ import org.springframework.stereotype.Repository; @Repository -public interface AssignmentRepository extends JpaRepository { +public interface AssignmentRepository extends JpaRepository { } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java index 606588b..d49cb12 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java @@ -1,6 +1,7 @@ package backend.pirocheck.Assignment.service; -import backend.pirocheck.Assignment.dto.request.AssignmentReq; +import backend.pirocheck.Assignment.dto.request.AssignmentCreateReq; +import backend.pirocheck.Assignment.dto.request.AssignmentUpdateReq; import backend.pirocheck.Assignment.dto.response.AssignmentDayRes; import backend.pirocheck.Assignment.dto.response.AssignmentDetailRes; import backend.pirocheck.Assignment.dto.response.AssignmentWeekRes; @@ -64,16 +65,31 @@ public List search(Long userId) { return assignmentResponses; } - public String create(AssignmentReq assignmentReq) { + public String createAssignment(AssignmentCreateReq assignmentCreateReq) { Assignment assignment = Assignment.create( - assignmentReq.getAssignmentName(), - assignmentReq.getWeek(), - assignmentReq.getDay(), - assignmentReq.getOrderNumber()); + assignmentCreateReq.getAssignmentName(), + assignmentCreateReq.getWeek(), + assignmentCreateReq.getDay(), + assignmentCreateReq.getOrderNumber()); assignment = assignmentRepository.save(assignment); return assignment.getAssignmentName(); } + + public String deleteAssignment(Long assignmentId) { + assignmentRepository.deleteById(assignmentId); + return "Assignment deleted successfully"; + } + + public String updateAssignment(Long assignmentId, AssignmentUpdateReq req) { + Assignment assignment = assignmentRepository.findById(assignmentId) + .orElseThrow(() -> new IllegalArgumentException("조회된 과제가 없습니다.")); + + assignment.update(req.getAssignmentName(), req.getWeek(), req.getDay(), req.getOrderNumber()); + assignmentRepository.save(assignment); + + return assignment.getAssignmentName(); + } } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java index e28c409..ed60489 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/ManageStudents/service/ManageStudentsService.java @@ -1,5 +1,7 @@ package backend.pirocheck.ManageStudents.service; +import backend.pirocheck.Assignment.entity.AssignmentItem; +import backend.pirocheck.Assignment.repository.AssignmentItemRepository; import backend.pirocheck.Deposit.entity.Deposit; import backend.pirocheck.Deposit.repository.DepositRepository; import backend.pirocheck.ManageStudents.dto.response.ManageStudentDetailResDto; @@ -7,8 +9,6 @@ import backend.pirocheck.User.entity.Role; import backend.pirocheck.User.entity.User; import backend.pirocheck.User.repository.UserRepository; -import backend.pirocheck.assignment.entity.Assignment; -import backend.pirocheck.assignment.repository.AssignmentRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -21,17 +21,16 @@ public class ManageStudentsService { private final UserRepository userRepository; private final DepositRepository depositRepository; - private final AssignmentRepository assignmentRepository; + private final AssignmentItemRepository assignmentItemRepository; // 수강생 조회 public List searchMembers(String name) { List users; - if(name == null || name.isBlank()) { + if (name == null || name.isBlank()) { // 검색어가 없으면 맴버 전체 조회 users = userRepository.findByRole(Role.MEMBER); - } - else { + } else { // 이름 검색 users = userRepository.findByNameContainingAndRole(name, Role.MEMBER); } @@ -54,11 +53,11 @@ public ManageStudentDetailResDto getMemberDetail(Long studentId) { } // Assignment 리스트 조회 - List assignments = assignmentRepository.findByUserId(studentId); + List assignments = assignmentItemRepository.findByUserId(studentId); // 과제 제목만 리스트로 변환 List assignmentTitles = assignments.stream() - .map(Assignment::getAssignmentName) + .map(assignment -> assignment.getAssignment().getAssignmentName()) .toList(); // ManageStudentDetailResDto 조립 From cf79278e06fcd3362c991b31e9df27b934b81ae7 Mon Sep 17 00:00:00 2001 From: l-wanderer01 Date: Mon, 19 May 2025 00:27:27 +0900 Subject: [PATCH 4/7] =?UTF-8?q?[feat]=20swagger=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94=20=EB=82=B4=EC=9A=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AssignmentController.java | 79 +++++++++++++++++-- .../dto/request/AssignmentCreateReq.java | 13 +++ .../dto/request/AssignmentUpdateReq.java | 14 ++++ .../Assignment/entity/Assignment.java | 2 + 4 files changed, 102 insertions(+), 6 deletions(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java index 879b048..c74d85f 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java @@ -4,6 +4,12 @@ import backend.pirocheck.Assignment.dto.request.AssignmentUpdateReq; import backend.pirocheck.Assignment.dto.response.AssignmentWeekRes; import backend.pirocheck.Assignment.service.AssignmentService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -12,49 +18,110 @@ @RestController @RequestMapping("/api") @RequiredArgsConstructor +@Tag(name = "과제관리", description = "과제 관련 API") public class AssignmentController { private final AssignmentService assignmentService; // 과제 결과 확인 API // 과제 주차별, 요일별 그룹화 JSON + @Operation(summary = "학생별 과제 결과 확인", description = "관리자가 채점한 과제의 결과를 학생들이 확인합니다.") + @ApiResponses( + value = { + @ApiResponse(responseCode = "200", description = "사용자별 과제 조회에 성공하였습니다."), + @ApiResponse(responseCode = "400", description = "잘못된 요청입니다.") + } + ) @GetMapping("/assignment/{userId}") - public List getGroupedAssignments(@PathVariable Long userId) { + public List getGroupedAssignments( + @Parameter(description = "사용자 ID", example = "1") + @PathVariable Long userId + ) { return assignmentService.search(userId); } // 과제 생성 API + @Operation(summary = "과제 생성 API", description = "관리자가 과제를 생성합니다.") + @ApiResponses( + value = { + @ApiResponse(responseCode = "200", description = "과제 생성에 성공하였습니다."), + @ApiResponse(responseCode = "400", description = "잘못된 요청입니다.") + } + ) @PostMapping("/admin/assignment/signup") - public String signupAssignment(@RequestBody AssignmentCreateReq assignmentCreateReq) { + public String signupAssignment( + @Valid + @RequestBody AssignmentCreateReq assignmentCreateReq + ) { return assignmentService.createAssignment(assignmentCreateReq); } // 과제 삭제 API + @Operation(summary = "과제 삭제 API", description = "관리자가 과제를 삭제합니다.") + @ApiResponses( + value = { + @ApiResponse(responseCode = "200", description = "과제 삭제에 성공하였습니다."), + @ApiResponse(responseCode = "400", description = "잘못된 요청입니다.") + } + ) @DeleteMapping("/admin/assignment/{assignmentId}") public String deleteAssignment( + @Parameter(description = "과제 ID", example = "1") @PathVariable Long assignmentId ) { return assignmentService.deleteAssignment(assignmentId); } // 과제 수정 API + @Operation(summary = "과제 수정 API", description = "관리자가 과제의 잘못된 부분을 수정합니다.") + @ApiResponses( + value = { + @ApiResponse(responseCode = "200", description = "과제 수정에 성공하였습니다."), + @ApiResponse(responseCode = "400", description = "잘못된 요청입니다.") + } + ) @PutMapping("/admin/assignment/{assignmentId}") public String updateAssignment( + @Parameter(description = "과제 ID", example = "1") @PathVariable("assignmentId") Long assignmentId, @RequestBody AssignmentUpdateReq assignmentUpdateReq ) { return assignmentService.updateAssignment(assignmentId, assignmentUpdateReq); } - // 사용자별 과제 제출 여부 생성 API + // 사용자별 과제 제출 결과 생성 API + @Operation(summary = "관리자 과제 채점 API", description = "관리자가 사용자들의 과제를 채점한 결과 저장합니다.") + @ApiResponses( + value = { + @ApiResponse(responseCode = "200", description = "사용자의 과제 채점 결과 저장에 성공하였습니다."), + @ApiResponse(responseCode = "400", description = "잘못된 요청입니다.") + } + ) @PostMapping("/admin/users/{userId}/assignments/{assignmentId}/submission") - public String submissionAssignment(@PathVariable Long userId, @PathVariable Long assignmentId) { + public String submissionAssignment( + @Parameter(description = "사용자 ID", example = "1") + @PathVariable Long userId, + @Parameter(description = "과제 ID", example = "1") + @PathVariable Long assignmentId + ) { return null; } // 사용자별 과제 제출 여부 수정 API - @PutMapping("/api/users/{userId}/assignments/{assignmentId}/submission") - public String updateSubmission(@PathVariable Long userId, @PathVariable Long assignmentId) { + @Operation(summary = "관리자 과제 채점 내용 수정 API", description = "관리자가 사용자의 과제 결과를 수정하여 저장합니다.") + @ApiResponses( + value = { + @ApiResponse(responseCode = "200", description = "사용자 과제 채점 결과 수정에 성공하였습니다."), + @ApiResponse(responseCode = "400", description = "잘못된 요청입니다.") + } + ) + @PutMapping("/admin/users/{userId}/assignments/{assignmentId}/submission") + public String updateSubmission( + @Parameter(description = "사용자 ID", example = "1") + @PathVariable Long userId, + @Parameter(description = "과제 ID", example = "1") + @PathVariable Long assignmentId + ) { return null; } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java index 123e16e..b12e833 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java @@ -1,5 +1,8 @@ package backend.pirocheck.Assignment.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Getter; @@ -7,9 +10,19 @@ @AllArgsConstructor public class AssignmentCreateReq { + @Schema(description = "과제명", example = "제로초 인강") + @NotNull(message = "과제명은 필수입니다.") private String assignmentName; + + @Schema(description = "주차", example = "1") + @NotBlank(message = "주차를 입력해주세요.") private Long week; + + @Schema(description = "요일", example = "화") + @NotBlank(message = "요일을 입력해주세요.") private String day; + + @Schema(description = "해당 일자 과제 numbering", example = "1") private Long orderNumber; } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java index 5941f88..b4c1c29 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java @@ -1,5 +1,8 @@ package backend.pirocheck.Assignment.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Getter; @@ -7,8 +10,19 @@ @AllArgsConstructor public class AssignmentUpdateReq { + @Schema(description = "과제명", example = "제로초 인강") + @NotNull(message = "과제명은 필수입니다.") private String assignmentName; + + @Schema(description = "주차", example = "1") + @NotBlank(message = "주차를 입력해주세요.") private Long week; + + @Schema(description = "요일", example = "화") + @NotBlank(message = "요일을 입력해주세요.") private String day; + + @Schema(description = "해당 일자 과제 numbering", example = "1") private Long orderNumber; + } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java index c51b0d3..16d64f7 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java @@ -1,5 +1,6 @@ package backend.pirocheck.Assignment.entity; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.persistence.*; import lombok.*; @@ -11,6 +12,7 @@ @Builder(access = AccessLevel.PRIVATE) @NoArgsConstructor @AllArgsConstructor +@Tag(name = "과제 관리", description = "과제 관련 API") public class Assignment { @Id From 102f632366034728187144862837449e5d4923c3 Mon Sep 17 00:00:00 2001 From: l-wanderer01 Date: Mon, 19 May 2025 01:25:30 +0900 Subject: [PATCH 5/7] =?UTF-8?q?[feat]=20=EA=B4=80=EB=A6=AC=EC=9E=90?= =?UTF-8?q?=EA=B0=80=20=EC=82=AC=EC=9A=A9=EC=9E=90=EC=9D=98=20=EA=B3=BC?= =?UTF-8?q?=EC=A0=9C=20=EC=B1=84=EC=A0=90=20=EA=B2=B0=EA=B3=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=ED=95=98=EB=8A=94=20=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AssignmentController.java | 9 ++++-- .../dto/request/AssignmentItemCreateReq.java | 22 +++++++++++++++ .../Assignment/entity/AssignmentItem.java | 22 +++++++++------ .../Assignment/service/AssignmentService.java | 28 ++++++++++++++++++- 4 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentItemCreateReq.java diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java index c74d85f..2759f31 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/controller/AssignmentController.java @@ -1,8 +1,10 @@ package backend.pirocheck.Assignment.controller; import backend.pirocheck.Assignment.dto.request.AssignmentCreateReq; +import backend.pirocheck.Assignment.dto.request.AssignmentItemCreateReq; import backend.pirocheck.Assignment.dto.request.AssignmentUpdateReq; import backend.pirocheck.Assignment.dto.response.AssignmentWeekRes; +import backend.pirocheck.Assignment.entity.AssignmentStatus; import backend.pirocheck.Assignment.service.AssignmentService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -98,13 +100,14 @@ public String updateAssignment( } ) @PostMapping("/admin/users/{userId}/assignments/{assignmentId}/submission") - public String submissionAssignment( + public AssignmentStatus submissionAssignment( @Parameter(description = "사용자 ID", example = "1") @PathVariable Long userId, @Parameter(description = "과제 ID", example = "1") - @PathVariable Long assignmentId + @PathVariable Long assignmentId, + @RequestBody AssignmentItemCreateReq req ) { - return null; + return assignmentService.createAssignmentItem(userId, assignmentId, req); } // 사용자별 과제 제출 여부 수정 API diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentItemCreateReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentItemCreateReq.java new file mode 100644 index 0000000..62fc718 --- /dev/null +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentItemCreateReq.java @@ -0,0 +1,22 @@ +package backend.pirocheck.Assignment.dto.request; + +import backend.pirocheck.Assignment.entity.AssignmentStatus; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Pattern; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class AssignmentItemCreateReq { + + private Long assignmentId; + + private Long userId; + + @Pattern(regexp = "SUCCESS/INSUFFICIENT/FAILURE", message = "status는 SUCCESS, INSUFFICIENT 혹은 FAILURE 여야 합니다.") + @Schema(description = "과제 결과", example = "SUCCESS") + private AssignmentStatus status; +} diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentItem.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentItem.java index bb88fae..74719c7 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentItem.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/AssignmentItem.java @@ -2,14 +2,12 @@ import backend.pirocheck.User.entity.User; import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; +import lombok.*; @Entity @Getter @Setter +@Builder(access = AccessLevel.PRIVATE) @AllArgsConstructor @NoArgsConstructor public class AssignmentItem { @@ -17,16 +15,24 @@ public class AssignmentItem { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 유저별 과제 정보를 저장하는 ID - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "assignment_id") - private Assignment assignment; - @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "assignment_id") + private Assignment assignment; + // 과제 결과 @Enumerated(EnumType.STRING) @Column(length = 100) private AssignmentStatus submitted; // 수강생의 과제 제출여부 + + public static AssignmentItem create(User user, Assignment assignment, AssignmentStatus submitted) { + return AssignmentItem.builder() + .assignment(assignment) + .user(user) + .submitted(submitted) + .build(); + } } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java index d49cb12..b8448c9 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java @@ -1,14 +1,18 @@ package backend.pirocheck.Assignment.service; import backend.pirocheck.Assignment.dto.request.AssignmentCreateReq; +import backend.pirocheck.Assignment.dto.request.AssignmentItemCreateReq; import backend.pirocheck.Assignment.dto.request.AssignmentUpdateReq; import backend.pirocheck.Assignment.dto.response.AssignmentDayRes; import backend.pirocheck.Assignment.dto.response.AssignmentDetailRes; import backend.pirocheck.Assignment.dto.response.AssignmentWeekRes; import backend.pirocheck.Assignment.entity.Assignment; import backend.pirocheck.Assignment.entity.AssignmentItem; +import backend.pirocheck.Assignment.entity.AssignmentStatus; import backend.pirocheck.Assignment.repository.AssignmentItemRepository; import backend.pirocheck.Assignment.repository.AssignmentRepository; +import backend.pirocheck.User.entity.User; +import backend.pirocheck.User.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -25,6 +29,7 @@ public class AssignmentService { private final AssignmentItemRepository assignmentItemRepository; private final AssignmentRepository assignmentRepository; + private final UserRepository userRepository; public List search(Long userId) { @@ -78,11 +83,13 @@ public String createAssignment(AssignmentCreateReq assignmentCreateReq) { return assignment.getAssignmentName(); } + // 과제 삭제 public String deleteAssignment(Long assignmentId) { assignmentRepository.deleteById(assignmentId); - return "Assignment deleted successfully"; + return "과제가 성공적으로 삭제되었습니다."; } + // 과제 수정 public String updateAssignment(Long assignmentId, AssignmentUpdateReq req) { Assignment assignment = assignmentRepository.findById(assignmentId) .orElseThrow(() -> new IllegalArgumentException("조회된 과제가 없습니다.")); @@ -92,4 +99,23 @@ public String updateAssignment(Long assignmentId, AssignmentUpdateReq req) { return assignment.getAssignmentName(); } + + // 과제 채점 결과 저장 + public AssignmentStatus createAssignmentItem(Long assignmentId, Long userId, AssignmentItemCreateReq req) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new IllegalArgumentException("조회된 사용자가 없습니다.")); + + Assignment assignment = assignmentRepository.findById(assignmentId) + .orElseThrow(() -> new IllegalArgumentException("조회된 과제가 없습니다.")); + + AssignmentItem assignmentItem = AssignmentItem.create( + user, + assignment, + req.getStatus() + ); + + assignmentItemRepository.save(assignmentItem); + + return assignmentItem.getSubmitted(); + } } From 0284dc38d275e766d3222c1ac60c26641000255a Mon Sep 17 00:00:00 2001 From: l-wanderer01 Date: Mon, 19 May 2025 01:37:10 +0900 Subject: [PATCH 6/7] =?UTF-8?q?[fix]=20=EA=B3=BC=EC=A0=9C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EA=B3=BC?= =?UTF-8?q?=EC=A0=9C=20=EC=A1=B0=ED=9A=8C=20=EB=A1=9C=EC=A7=81=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=A0=84=EC=B2=B4=20=EC=A3=BC=EC=A0=9C=EB=A5=BC=20?= =?UTF-8?q?=EC=9D=98=EB=AF=B8=ED=95=98=EB=8A=94=20subject=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Assignment/dto/request/AssignmentCreateReq.java | 4 ++++ .../Assignment/dto/request/AssignmentUpdateReq.java | 4 ++++ .../Assignment/dto/response/AssignmentWeekRes.java | 2 +- .../backend/pirocheck/Assignment/entity/Assignment.java | 9 +++++++-- .../pirocheck/Assignment/service/AssignmentService.java | 6 ++++-- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java index b12e833..d4faf7a 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java @@ -10,6 +10,10 @@ @AllArgsConstructor public class AssignmentCreateReq { + @Schema(description = "과제 주제", example = "Git/HTML/CSS") + @NotNull(message = "과제 주제는 필수입니다.") + private String subject; + @Schema(description = "과제명", example = "제로초 인강") @NotNull(message = "과제명은 필수입니다.") private String assignmentName; diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java index b4c1c29..06d1bb5 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java @@ -10,6 +10,10 @@ @AllArgsConstructor public class AssignmentUpdateReq { + @Schema(description = "과제 주제", example = "Git/HTML/CSS") + @NotNull(message = "과제 주제는 필수입니다.") + private String subject; + @Schema(description = "과제명", example = "제로초 인강") @NotNull(message = "과제명은 필수입니다.") private String assignmentName; diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentWeekRes.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentWeekRes.java index 687505c..b0d7721 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentWeekRes.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/response/AssignmentWeekRes.java @@ -9,6 +9,6 @@ @AllArgsConstructor public class AssignmentWeekRes { private Long week; -// private String title; // 각 주차 주제 (e.g, Git / HTML / CSS) + private String subject; // 각 주차 주제 (e.g, Git / HTML / CSS) private List days; } diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java index 16d64f7..410c522 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/entity/Assignment.java @@ -19,6 +19,9 @@ public class Assignment { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + // 전체 주제 + private String subject; + // 과제명 private String assignmentName; @@ -43,8 +46,9 @@ public void addAssignmentItem(AssignmentItem assignmentItem) { } // 관리자가 생성 - public static Assignment create(String assignmentName, Long week, String day, Long orderNumber) { + public static Assignment create(String subject, String assignmentName, Long week, String day, Long orderNumber) { return Assignment.builder() + .subject(subject) .assignmentName(assignmentName) .week(week) .day(day) @@ -53,7 +57,8 @@ public static Assignment create(String assignmentName, Long week, String day, Lo } // 과제 내용 업데이트 - public void update(String assignmentName, Long week, String day, Long orderNumber) { + public void update(String subject, String assignmentName, Long week, String day, Long orderNumber) { + this.subject = subject; this.assignmentName = assignmentName; this.week = week; this.day = day; diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java index b8448c9..38dc73c 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java @@ -42,6 +42,7 @@ public List search(Long userId) { for (Map.Entry> entry : weekGroup.entrySet()) { Long week = entry.getKey(); + String subject = String.valueOf(entry.getKey()); List assignmentList = entry.getValue(); // day를 기준으로 그룹핑 @@ -64,7 +65,7 @@ public List search(Long userId) { assignmentDayResList.add(new AssignmentDayRes(day, assignmentDetailResList)); } - assignmentResponses.add(new AssignmentWeekRes(week, assignmentDayResList)); + assignmentResponses.add(new AssignmentWeekRes(week, subject, assignmentDayResList)); } return assignmentResponses; @@ -73,6 +74,7 @@ public List search(Long userId) { public String createAssignment(AssignmentCreateReq assignmentCreateReq) { Assignment assignment = Assignment.create( + assignmentCreateReq.getSubject(), assignmentCreateReq.getAssignmentName(), assignmentCreateReq.getWeek(), assignmentCreateReq.getDay(), @@ -94,7 +96,7 @@ public String updateAssignment(Long assignmentId, AssignmentUpdateReq req) { Assignment assignment = assignmentRepository.findById(assignmentId) .orElseThrow(() -> new IllegalArgumentException("조회된 과제가 없습니다.")); - assignment.update(req.getAssignmentName(), req.getWeek(), req.getDay(), req.getOrderNumber()); + assignment.update(req.getSubject(), req.getAssignmentName(), req.getWeek(), req.getDay(), req.getOrderNumber()); assignmentRepository.save(assignment); return assignment.getAssignmentName(); From 4f28c1c4cee18eebb254272b409c19a499d74878 Mon Sep 17 00:00:00 2001 From: l-wanderer01 Date: Mon, 19 May 2025 01:51:32 +0900 Subject: [PATCH 7/7] =?UTF-8?q?[fix]=20subject=EA=B0=80=20week=20=EA=B0=92?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=B6=9C=EB=A0=A5=EB=90=98=EB=8D=98=20?= =?UTF-8?q?=EA=B1=B8=20assignment=EC=9D=98=20subject=20=EA=B0=92=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=98=AC=EB=B0=94=EB=A5=B4=EA=B2=8C=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=EB=90=98=EB=8F=84=EB=A1=9D=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Assignment/dto/request/AssignmentCreateReq.java | 3 ++- .../Assignment/dto/request/AssignmentUpdateReq.java | 3 ++- .../pirocheck/Assignment/service/AssignmentService.java | 7 ++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java index d4faf7a..65cbe2f 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentCreateReq.java @@ -3,6 +3,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; import lombok.AllArgsConstructor; import lombok.Getter; @@ -19,7 +20,7 @@ public class AssignmentCreateReq { private String assignmentName; @Schema(description = "주차", example = "1") - @NotBlank(message = "주차를 입력해주세요.") + @Positive private Long week; @Schema(description = "요일", example = "화") diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java index 06d1bb5..5caa73a 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/dto/request/AssignmentUpdateReq.java @@ -3,6 +3,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; import lombok.AllArgsConstructor; import lombok.Getter; @@ -19,7 +20,7 @@ public class AssignmentUpdateReq { private String assignmentName; @Schema(description = "주차", example = "1") - @NotBlank(message = "주차를 입력해주세요.") + @Positive private Long week; @Schema(description = "요일", example = "화") diff --git a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java index 38dc73c..c4c25cd 100644 --- a/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java +++ b/backend/pirocheck/src/main/java/backend/pirocheck/Assignment/service/AssignmentService.java @@ -41,9 +41,10 @@ public List search(Long userId) { List assignmentResponses = new ArrayList<>(); for (Map.Entry> entry : weekGroup.entrySet()) { - Long week = entry.getKey(); - String subject = String.valueOf(entry.getKey()); - List assignmentList = entry.getValue(); + Long week = entry.getKey(); // 주차 정보 + List assignmentList = entry.getValue(); // 주차에 해당하는 days의 list + + String subject = assignmentList.get(0).getAssignment().getSubject(); // day를 기준으로 그룹핑 Map> dayGroup = assignmentList.stream()