Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
194b0b0
[feat] admin 과제 생성 api 로직 작성 및 과제 관련 API명 작성
l-wanderer01 May 18, 2025
78fc1a5
Merge remote-tracking branch 'origin/main' into backend_jh
l-wanderer01 May 18, 2025
5895fe3
Merge pull request #110 from pirogramming/main
Imggaggu May 18, 2025
4b909e6
Merge pull request #113 from pirogramming/main
Imggaggu May 18, 2025
fdaf4a2
[feat] 과제 수정 및 삭제 기능 추가
l-wanderer01 May 18, 2025
23fcef0
Merge remote-tracking branch 'origin/main' into backend_jh
l-wanderer01 May 18, 2025
191b49e
[fix]: ManageTask / ManageStudent Header 수정
NamKyeongMin May 18, 2025
371c043
Merge branch 'deploy' of https://github.com/pirogramming/PiroCheck in…
NamKyeongMin May 18, 2025
429ba81
Merge pull request #114 from pirogramming/frontend_km
NamKyeongMin May 18, 2025
cf79278
[feat] swagger 문서화 내용 추가
l-wanderer01 May 18, 2025
b86457c
[add]: 과제 관리 페이지 base
NamKyeongMin May 18, 2025
0ad52c3
[add]: ManageTask + Modal form UI까지
NamKyeongMin May 18, 2025
7bbcc4f
Merge pull request #117 from pirogramming/frontend_km
NamKyeongMin May 18, 2025
102f632
[feat] 관리자가 사용자의 과제 채점 결과 생성하는 기능 추가
l-wanderer01 May 18, 2025
0284dc3
[fix] 과제 생성 및 사용자 과제 조회 로직에서 전체 주제를 의미하는 subject 필드 추가
l-wanderer01 May 18, 2025
4f28c1c
[fix] subject가 week 값으로 출력되던 걸 assignment의 subject 값으로 올바르게 출력되도록 로직 수정
l-wanderer01 May 18, 2025
ec44640
Merge remote-tracking branch 'origin/deploy' into backend_jh
l-wanderer01 May 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
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;
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.*;

import java.util.List;

@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<AssignmentWeekRes> 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(
@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
@Operation(summary = "관리자 과제 채점 API", description = "관리자가 사용자들의 과제를 채점한 결과 저장합니다.")
@ApiResponses(
value = {
@ApiResponse(responseCode = "200", description = "사용자의 과제 채점 결과 저장에 성공하였습니다."),
@ApiResponse(responseCode = "400", description = "잘못된 요청입니다.")
}
)
@PostMapping("/admin/users/{userId}/assignments/{assignmentId}/submission")
public AssignmentStatus submissionAssignment(
@Parameter(description = "사용자 ID", example = "1")
@PathVariable Long userId,
@Parameter(description = "과제 ID", example = "1")
@PathVariable Long assignmentId,
@RequestBody AssignmentItemCreateReq req
) {
return assignmentService.createAssignmentItem(userId, assignmentId, req);
}

// 사용자별 과제 제출 여부 수정 API
@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;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
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 jakarta.validation.constraints.Positive;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class AssignmentCreateReq {

@Schema(description = "과제 주제", example = "Git/HTML/CSS")
@NotNull(message = "과제 주제는 필수입니다.")
private String subject;

@Schema(description = "과제명", example = "제로초 인강")
@NotNull(message = "과제명은 필수입니다.")
private String assignmentName;

@Schema(description = "주차", example = "1")
@Positive
private Long week;

@Schema(description = "요일", example = "화")
@NotBlank(message = "요일을 입력해주세요.")
private String day;

@Schema(description = "해당 일자 과제 numbering", example = "1")
private Long orderNumber;

}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
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 jakarta.validation.constraints.Positive;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class AssignmentUpdateReq {

@Schema(description = "과제 주제", example = "Git/HTML/CSS")
@NotNull(message = "과제 주제는 필수입니다.")
private String subject;

@Schema(description = "과제명", example = "제로초 인강")
@NotNull(message = "과제명은 필수입니다.")
private String assignmentName;

@Schema(description = "주차", example = "1")
@Positive
private Long week;

@Schema(description = "요일", example = "화")
@NotBlank(message = "요일을 입력해주세요.")
private String day;

@Schema(description = "해당 일자 과제 numbering", example = "1")
private Long orderNumber;

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package backend.pirocheck.assignment.dto.response;
package backend.pirocheck.Assignment.dto.response;

import lombok.AllArgsConstructor;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package backend.pirocheck.assignment.dto.response;
package backend.pirocheck.Assignment.dto.response;

import lombok.AllArgsConstructor;
import lombok.Getter;
Expand All @@ -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<AssignmentDayRes> days;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package backend.pirocheck.Assignment.entity;

import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.persistence.*;
import lombok.*;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@Builder(access = AccessLevel.PRIVATE)
@NoArgsConstructor
@AllArgsConstructor
@Tag(name = "과제 관리", description = "과제 관련 API")
public class Assignment {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

// 전체 주제
private String subject;

// 과제명
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<AssignmentItem> assignments = new ArrayList<>();

// 연관관계 편의 메서드 (양방향 시 자주 사용)
public void addAssignmentItem(AssignmentItem assignmentItem) {
this.assignments.add(assignmentItem);
assignmentItem.setAssignment(this);
}

// 관리자가 생성
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)
.orderNumber(orderNumber)
.build();
}

// 과제 내용 업데이트
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;
this.orderNumber = orderNumber;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package backend.pirocheck.Assignment.entity;

import backend.pirocheck.User.entity.User;
import jakarta.persistence.*;
import lombok.*;

@Entity
@Getter
@Setter
@Builder(access = AccessLevel.PRIVATE)
@AllArgsConstructor
@NoArgsConstructor
public class AssignmentItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 유저별 과제 정보를 저장하는 ID

@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();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package backend.pirocheck.assignment.entity;
package backend.pirocheck.Assignment.entity;

public enum AssignmentStatus {
SUCCESS, INSUFFICIENT, FAILURE;
Expand Down
Loading