diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/api/StudentStudyDetailController.java b/src/main/java/com/gdschongik/gdsc/domain/study/api/StudentStudyDetailController.java index c153140b1..ccc11013c 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/api/StudentStudyDetailController.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/api/StudentStudyDetailController.java @@ -2,6 +2,7 @@ import com.gdschongik.gdsc.domain.study.application.StudentStudyDetailService; import com.gdschongik.gdsc.domain.study.dto.response.AssignmentDashboardResponse; +import com.gdschongik.gdsc.domain.study.dto.response.AssignmentHistoryStatusResponse; import com.gdschongik.gdsc.domain.study.dto.response.StudyStudentSessionResponse; import com.gdschongik.gdsc.domain.study.dto.response.StudyTodoResponse; import io.swagger.v3.oas.annotations.Operation; @@ -45,4 +46,12 @@ public ResponseEntity> getStudySessions( List response = studentStudyDetailService.getStudySessions(studyId); return ResponseEntity.ok(response); } + + @Operation(summary = "이번주 제출해야 할 과제 조회", description = "마감 기한이 이번주까지인 과제를 조회합니다.") + @GetMapping("/assignments/upcoming") + public ResponseEntity> getUpcomingAssignments( + @RequestParam(name = "studyId") Long studyId) { + List response = studentStudyDetailService.getUpcomingAssignments(studyId); + return ResponseEntity.ok(response); + } } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyDetailService.java b/src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyDetailService.java index 652b397fc..046a1204d 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyDetailService.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyDetailService.java @@ -10,6 +10,7 @@ import com.gdschongik.gdsc.domain.study.domain.StudyDetail; import com.gdschongik.gdsc.domain.study.domain.StudyHistory; import com.gdschongik.gdsc.domain.study.dto.response.AssignmentDashboardResponse; +import com.gdschongik.gdsc.domain.study.dto.response.AssignmentHistoryStatusResponse; import com.gdschongik.gdsc.domain.study.dto.response.AssignmentSubmittableDto; import com.gdschongik.gdsc.domain.study.dto.response.StudyStudentSessionResponse; import com.gdschongik.gdsc.domain.study.dto.response.StudyTodoResponse; @@ -41,7 +42,7 @@ public AssignmentDashboardResponse getSubmittableAssignments(Long studyId) { .findByStudentAndStudyId(currentMember, studyId) .orElseThrow(() -> new CustomException(ErrorCode.STUDY_HISTORY_NOT_FOUND)); List assignmentHistories = - assignmentHistoryRepository.findAssignmentHistoriesByStudentAndStudy(currentMember, studyId); + assignmentHistoryRepository.findAssignmentHistoriesByStudentAndStudyId(currentMember, studyId); List studyDetails = studyDetailRepository.findAllByStudyIdOrderByWeekAsc(studyId).stream() .filter(studyDetail -> studyDetail.getAssignment().isOpen() && studyDetail.isAssignmentDeadlineRemaining()) @@ -61,7 +62,7 @@ public List getStudyTodoList(Long studyId) { Member member = memberUtil.getCurrentMember(); final List studyDetails = studyDetailRepository.findAllByStudyIdOrderByWeekAsc(studyId); final List assignmentHistories = - assignmentHistoryRepository.findAssignmentHistoriesByStudentAndStudy(member, studyId); + assignmentHistoryRepository.findAssignmentHistoriesByStudentAndStudyId(member, studyId); final List attendances = attendanceRepository.findByMemberAndStudyId(member, studyId); LocalDate now = LocalDate.now(); @@ -86,7 +87,7 @@ public List getStudySessions(Long studyId) { Member member = memberUtil.getCurrentMember(); final List studyDetails = studyDetailRepository.findAllByStudyIdOrderByWeekAsc(studyId); final List assignmentHistories = - assignmentHistoryRepository.findAssignmentHistoriesByStudentAndStudy(member, studyId); + assignmentHistoryRepository.findAssignmentHistoriesByStudentAndStudyId(member, studyId); final List attendances = attendanceRepository.findByMemberAndStudyId(member, studyId); return studyDetails.stream() @@ -111,4 +112,23 @@ private boolean isAttended(List attendances, StudyDetail studyDetail return attendances.stream() .anyMatch(attendance -> attendance.getStudyDetail().getId().equals(studyDetail.getId())); } + + @Transactional(readOnly = true) + public List getUpcomingAssignments(Long studyId) { + Member currentMember = memberUtil.getCurrentMember(); + List studyDetails = studyDetailRepository.findAllByStudyId(studyId).stream() + .filter(studyDetail -> + studyDetail.getAssignment().isOpen() && studyDetail.isAssignmentDeadlineThisWeek()) + .toList(); + List assignmentHistories = + assignmentHistoryRepository.findAssignmentHistoriesByStudentAndStudyId(currentMember, studyId).stream() + .filter(assignmentHistory -> + assignmentHistory.getStudyDetail().isAssignmentDeadlineThisWeek()) + .toList(); + + return studyDetails.stream() + .map(studyDetail -> AssignmentHistoryStatusResponse.of( + studyDetail, getSubmittedAssignment(assignmentHistories, studyDetail))) + .toList(); + } } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyHistoryService.java b/src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyHistoryService.java index 1dea2ee3e..8a1eb7b42 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyHistoryService.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyHistoryService.java @@ -78,7 +78,7 @@ private String getOwnerRepo(String repositoryLink) { public List getAllAssignmentHistories(Long studyId) { Member currentMember = memberUtil.getCurrentMember(); - return assignmentHistoryRepository.findAssignmentHistoriesByStudentAndStudy(currentMember, studyId).stream() + return assignmentHistoryRepository.findAssignmentHistoriesByStudentAndStudyId(currentMember, studyId).stream() .map(AssignmentHistoryResponse::from) .toList(); } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dao/AssignmentHistoryCustomRepository.java b/src/main/java/com/gdschongik/gdsc/domain/study/dao/AssignmentHistoryCustomRepository.java index 5fa5fc2d9..108112e6f 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/dao/AssignmentHistoryCustomRepository.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dao/AssignmentHistoryCustomRepository.java @@ -9,5 +9,5 @@ public interface AssignmentHistoryCustomRepository { boolean existsSubmittedAssignmentByMemberAndStudy(Member member, Study study); - List findAssignmentHistoriesByStudentAndStudy(Member member, Long studyId); + List findAssignmentHistoriesByStudentAndStudyId(Member member, Long studyId); } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dao/AssignmentHistoryCustomRepositoryImpl.java b/src/main/java/com/gdschongik/gdsc/domain/study/dao/AssignmentHistoryCustomRepositoryImpl.java index a37e68723..4c6df554c 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/dao/AssignmentHistoryCustomRepositoryImpl.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dao/AssignmentHistoryCustomRepositoryImpl.java @@ -41,7 +41,7 @@ private BooleanExpression isSubmitted() { } @Override - public List findAssignmentHistoriesByStudentAndStudy(Member currentMember, Long studyId) { + public List findAssignmentHistoriesByStudentAndStudyId(Member currentMember, Long studyId) { return queryFactory .selectFrom(assignmentHistory) .join(assignmentHistory.studyDetail, studyDetail) diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyDetailRepository.java b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyDetailRepository.java index 5c4fc8c69..c3f317f54 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyDetailRepository.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyDetailRepository.java @@ -7,4 +7,6 @@ public interface StudyDetailRepository extends JpaRepository { List findAllByStudyIdOrderByWeekAsc(Long studyId); + + List findAllByStudyId(Long studyId); } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyDetail.java b/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyDetail.java index be1a4a174..41bb4a0b5 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyDetail.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyDetail.java @@ -96,6 +96,10 @@ public boolean isAssignmentDeadlineRemaining() { return assignment.isDeadlineRemaining(); } + public boolean isAssignmentDeadlineThisWeek() { + return assignment.isDeadLineThisWeek(); + } + // 스터디 시작일자 + 현재 주차 * 7 + (스터디 요일 - 스터디 기간 시작 요일) public LocalDate getAttendanceDay() { // 스터디 시작일자 diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/domain/vo/Assignment.java b/src/main/java/com/gdschongik/gdsc/domain/study/domain/vo/Assignment.java index 1d5a5c278..38be69b1f 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/domain/vo/Assignment.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/domain/vo/Assignment.java @@ -10,6 +10,8 @@ import jakarta.persistence.Embeddable; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; +import java.time.DayOfWeek; +import java.time.LocalDate; import java.time.LocalDateTime; import lombok.AccessLevel; import lombok.Builder; @@ -93,4 +95,17 @@ public boolean isDeadlineRemaining() { LocalDateTime now = LocalDateTime.now(); return now.isBefore(deadline); } + + public boolean isDeadLineThisWeek() { + // 현재 날짜와 마감일의 날짜 부분을 비교할 것이므로 LocalDate로 변환 + LocalDate now = LocalDate.now(); + LocalDate startOfWeek = now.with(DayOfWeek.MONDAY); // 이번 주 월요일 + LocalDate endOfWeek = now.with(DayOfWeek.SUNDAY); // 이번 주 일요일 + + // 마감일의 날짜 부분을 가져옴 + LocalDate deadlineDate = deadline.toLocalDate(); + + // 마감일이 이번 주 내에 있는지 확인 + return !deadlineDate.isBefore(startOfWeek) && !deadlineDate.isAfter(endOfWeek); + } } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/AssignmentHistoryStatusResponse.java b/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/AssignmentHistoryStatusResponse.java new file mode 100644 index 000000000..3209dc8cc --- /dev/null +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/AssignmentHistoryStatusResponse.java @@ -0,0 +1,54 @@ +package com.gdschongik.gdsc.domain.study.dto.response; + +import static com.gdschongik.gdsc.domain.study.domain.SubmissionFailureType.NOT_SUBMITTED; + +import com.gdschongik.gdsc.domain.study.domain.*; +import com.gdschongik.gdsc.domain.study.domain.vo.Assignment; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.annotation.Nullable; +import java.time.LocalDateTime; + +public record AssignmentHistoryStatusResponse( + Long studyDetailId, + @Schema(description = "과제 상태") StudyStatus assignmentStatus, + @Schema(description = "주차") Long week, + @Nullable @Schema(description = "과제 제목") String title, + // TODO 추후 처리 예정 + @Nullable @Schema(description = "과제 제출 상태") AssignmentSubmissionStatus assignmentSubmissionStatus, + @Nullable @Schema(description = "과제 명세 링크") String descriptionLink, + @Nullable @Schema(description = "마감 기한") LocalDateTime deadline, + @Nullable @Schema(description = "과제 제출 링크") String submissionLink, + @Nullable @Schema(description = "과제 제출 실패 사유. 제출 여부도 포함되어 있습니다. 미제출 상태라면 기본 과제 정보만 반환합니다.") + SubmissionFailureType submissionFailureType, + @Nullable @Schema(description = "최종 수정 일시") LocalDateTime committedAt) { + + // 과제 제출이 없는 경우, 과제 정보만 사용하여 AssignmentHistoryStatusResponse 생성 + public static AssignmentHistoryStatusResponse of(StudyDetail studyDetail, AssignmentHistory assignmentHistory) { + if (assignmentHistory == null) { + return new AssignmentHistoryStatusResponse( + studyDetail.getId(), + studyDetail.getAssignment().getStatus(), + studyDetail.getWeek(), + studyDetail.getAssignment().getTitle(), + null, + studyDetail.getAssignment().getDescriptionLink(), + studyDetail.getAssignment().getDeadline(), + null, + NOT_SUBMITTED, + null); + } + + Assignment assignment = studyDetail.getAssignment(); + return new AssignmentHistoryStatusResponse( + studyDetail.getId(), + assignment.getStatus(), + studyDetail.getWeek(), + assignment.getTitle(), + assignmentHistory.getSubmissionStatus(), + assignment.getDescriptionLink(), + assignment.getDeadline(), + assignmentHistory.getSubmissionLink(), + assignmentHistory.getSubmissionFailureType(), + assignmentHistory.getCommittedAt()); + } +}