From a2e3a40e47d48b9f1c7b375715242eee7b71c836 Mon Sep 17 00:00:00 2001 From: Everdu Date: Fri, 11 Oct 2024 00:10:42 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EC=8A=A4=ED=84=B0=EB=94=94=20?= =?UTF-8?q?=EC=88=98=EB=A3=8C=20=EB=82=B4=EC=97=AD=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?API=20(#798)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: StudyAchievementRepository 생성 * feat: 스터디 수료 내역 조회 로직 작성 * feat: 스터디 수료내역 조회 컨트롤러 추가 * refactor: 우수 스터디원 조회 로직 개선 * chore: import 코드 기존 방식으로 변경 * chore: 메서드 이름 개선 * refactor: DTO에서 achievement null 처리 * chore: import Collector * refactor: 우수 스터디원이 없으면 null 반환 * refactor: 우수 스터디원 선정 내역 기본값을 리스트로 설정 * chore: 우수 스터디원 필드 스웨거 설명 수정 --- .../api/StudentStudyHistoryController.java | 8 ++++ .../StudentStudyHistoryService.java | 27 ++++++++++++++ .../study/dao/StudyAchievementRepository.java | 7 +++- .../StudentMyCompleteStudyResponse.java | 37 +++++++++++++++++++ 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudentMyCompleteStudyResponse.java diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/api/StudentStudyHistoryController.java b/src/main/java/com/gdschongik/gdsc/domain/study/api/StudentStudyHistoryController.java index 8764e5a95..1cf0bbb7a 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/api/StudentStudyHistoryController.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/api/StudentStudyHistoryController.java @@ -3,6 +3,7 @@ import com.gdschongik.gdsc.domain.study.application.StudentStudyHistoryService; import com.gdschongik.gdsc.domain.study.dto.request.RepositoryUpdateRequest; import com.gdschongik.gdsc.domain.study.dto.response.AssignmentHistoryResponse; +import com.gdschongik.gdsc.domain.study.dto.response.StudentMyCompleteStudyResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -42,4 +43,11 @@ public ResponseEntity submitAssignment(@RequestParam(name = "studyDetailId studentStudyHistoryService.submitAssignment(studyDetailId); return ResponseEntity.ok().build(); } + + @Operation(summary = "내 스터디 수료 내역 조회", description = "내가 수료한 스터디를 조회합니다.") + @GetMapping("/me/complete") + public ResponseEntity> getMyCompletedStudy() { + List response = studentStudyHistoryService.getMyCompletedStudies(); + return ResponseEntity.ok(response); + } } 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 d631f3779..db39a9ac5 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 @@ -1,28 +1,35 @@ package com.gdschongik.gdsc.domain.study.application; import static com.gdschongik.gdsc.global.exception.ErrorCode.*; +import static java.util.stream.Collectors.*; import com.gdschongik.gdsc.domain.member.domain.Member; import com.gdschongik.gdsc.domain.study.dao.AssignmentHistoryRepository; +import com.gdschongik.gdsc.domain.study.dao.StudyAchievementRepository; import com.gdschongik.gdsc.domain.study.dao.StudyDetailRepository; import com.gdschongik.gdsc.domain.study.dao.StudyHistoryRepository; import com.gdschongik.gdsc.domain.study.dao.StudyRepository; +import com.gdschongik.gdsc.domain.study.domain.AchievementType; import com.gdschongik.gdsc.domain.study.domain.AssignmentHistory; import com.gdschongik.gdsc.domain.study.domain.AssignmentHistoryGrader; import com.gdschongik.gdsc.domain.study.domain.AssignmentSubmissionFetcher; import com.gdschongik.gdsc.domain.study.domain.Study; +import com.gdschongik.gdsc.domain.study.domain.StudyAchievement; import com.gdschongik.gdsc.domain.study.domain.StudyAssignmentHistoryValidator; import com.gdschongik.gdsc.domain.study.domain.StudyDetail; import com.gdschongik.gdsc.domain.study.domain.StudyHistory; import com.gdschongik.gdsc.domain.study.domain.StudyHistoryValidator; import com.gdschongik.gdsc.domain.study.dto.request.RepositoryUpdateRequest; import com.gdschongik.gdsc.domain.study.dto.response.AssignmentHistoryResponse; +import com.gdschongik.gdsc.domain.study.dto.response.StudentMyCompleteStudyResponse; import com.gdschongik.gdsc.global.exception.CustomException; import com.gdschongik.gdsc.global.util.MemberUtil; import com.gdschongik.gdsc.infra.github.client.GithubClient; import java.io.IOException; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Optional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -44,6 +51,7 @@ public class StudentStudyHistoryService { private final StudyAssignmentHistoryValidator studyAssignmentHistoryValidator; private final AssignmentHistoryGrader assignmentHistoryGrader; private final StudyRepository studyRepository; + private final StudyAchievementRepository studyAchievementRepository; @Transactional public void updateRepository(Long studyId, RepositoryUpdateRequest request) throws IOException { @@ -107,6 +115,25 @@ public void submitAssignment(Long studyDetailId) { assignmentHistory.getSubmissionFailureType()); } + @Transactional(readOnly = true) + public List getMyCompletedStudies() { + Member currentMember = memberUtil.getCurrentMember(); + List studyHistories = studyHistoryRepository.findAllByStudent(currentMember); + List studyAchievements = studyAchievementRepository.findAllByStudent(currentMember); + + Map> achievementsByStudy = studyAchievements.stream() + .collect(groupingBy( + StudyAchievement::getStudy, mapping(StudyAchievement::getAchievementType, toList()))); + + return studyHistories.stream() + .map(history -> { + List achievementTypes = + achievementsByStudy.getOrDefault(history.getStudy(), new ArrayList<>()); + return StudentMyCompleteStudyResponse.of(history, achievementTypes); + }) + .toList(); + } + private AssignmentHistory findOrCreate(Member currentMember, StudyDetail studyDetail) { return assignmentHistoryRepository .findByMemberAndStudyDetail(currentMember, studyDetail) diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyAchievementRepository.java b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyAchievementRepository.java index 361e1a35d..9951c1ecf 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyAchievementRepository.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyAchievementRepository.java @@ -1,7 +1,12 @@ package com.gdschongik.gdsc.domain.study.dao; +import com.gdschongik.gdsc.domain.member.domain.Member; import com.gdschongik.gdsc.domain.study.domain.StudyAchievement; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; public interface StudyAchievementRepository - extends JpaRepository, StudyAchievementCustomRepository {} + extends JpaRepository, StudyAchievementCustomRepository { + + List findAllByStudent(Member student); +} diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudentMyCompleteStudyResponse.java b/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudentMyCompleteStudyResponse.java new file mode 100644 index 000000000..a7fa46d9a --- /dev/null +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudentMyCompleteStudyResponse.java @@ -0,0 +1,37 @@ +package com.gdschongik.gdsc.domain.study.dto.response; + +import com.gdschongik.gdsc.domain.common.model.SemesterType; +import com.gdschongik.gdsc.domain.study.domain.AchievementType; +import com.gdschongik.gdsc.domain.study.domain.StudyHistory; +import com.gdschongik.gdsc.domain.study.domain.StudyHistoryStatus; +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; + +public record StudentMyCompleteStudyResponse( + Long studyId, + @Schema(description = "학년도") Integer academicYear, + @Schema(description = "학기") SemesterType semesterType, + @Schema(description = "이름") String title, + @Schema(description = "종류") String studyType, + @Schema(description = "상세설명 노션 링크") String notionLink, + @Schema(description = "한 줄 소개") String introduction, + @Schema(description = "멘토 이름") String mentorName, + @Schema(description = "총 주차수") Long totalWeek, + @Schema(description = "수료 여부") StudyHistoryStatus studyHistoryStatus, + @Schema(description = "우수 스터디원 선정 내역") List achievements) { + + public static StudentMyCompleteStudyResponse of(StudyHistory studyHistory, List achievements) { + return new StudentMyCompleteStudyResponse( + studyHistory.getStudy().getId(), + studyHistory.getStudy().getAcademicYear(), + studyHistory.getStudy().getSemesterType(), + studyHistory.getStudy().getTitle(), + studyHistory.getStudy().getStudyType().getValue(), + studyHistory.getStudy().getNotionLink(), + studyHistory.getStudy().getIntroduction(), + studyHistory.getStudy().getMentor().getName(), + studyHistory.getStudy().getTotalWeek(), + studyHistory.getStudyHistoryStatus(), + achievements); + } +} From f12092ac654a86408e1463cd24bb5191ba099d83 Mon Sep 17 00:00:00 2001 From: Cho Sangwook <82208159+Sangwook02@users.noreply.github.com> Date: Fri, 11 Oct 2024 13:16:27 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EC=9A=B0=EC=88=98=20=EC=8A=A4?= =?UTF-8?q?=ED=84=B0=EB=94=94=EC=9B=90=20=EC=A7=80=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?=EC=B2=A0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84=20(#800)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 우수 스터디원 지정 및 철회 API 구현 * feat: 우수 스터디원 지정 및 철회 로직 추가 * test: 우수 스터디원 지정 및 철회 테스트 추가 * feat: 수강신청 여부 검증 로직 추가 * test: 수강신청 여부 검증 로직 테스트 추가 * refactor: 레포지토리 메서드명 변경 * refactor: getById 메서드를 findById로 대체 * refactor: NPE 방지 코드 추가 * refactor: 타입 캐스팅으로 변경 --- .../api/MentorStudyAchievementController.java | 40 +++++++++ .../MentorStudyAchievementService.java | 74 +++++++++++++++++ .../dao/StudyAchievementCustomRepository.java | 4 + .../StudyAchievementCustomRepositoryImpl.java | 13 +++ .../dao/StudyHistoryCustomRepository.java | 8 ++ .../dao/StudyHistoryCustomRepositoryImpl.java | 27 ++++++ .../study/dao/StudyHistoryRepository.java | 2 +- .../study/domain/StudyHistoryValidator.java | 6 ++ .../request/OutstandingStudentRequest.java | 6 ++ .../gdsc/global/exception/ErrorCode.java | 1 + .../MentorStudyAchievementServiceTest.java | 82 +++++++++++++++++++ .../domain/StudyHistoryValidatorTest.java | 17 ++++ .../gdsc/helper/IntegrationTest.java | 21 +++++ 13 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyAchievementController.java create mode 100644 src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyAchievementService.java create mode 100644 src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyHistoryCustomRepository.java create mode 100644 src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyHistoryCustomRepositoryImpl.java create mode 100644 src/main/java/com/gdschongik/gdsc/domain/study/dto/request/OutstandingStudentRequest.java create mode 100644 src/test/java/com/gdschongik/gdsc/domain/study/application/MentorStudyAchievementServiceTest.java diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyAchievementController.java b/src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyAchievementController.java new file mode 100644 index 000000000..6b1f26455 --- /dev/null +++ b/src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyAchievementController.java @@ -0,0 +1,40 @@ +package com.gdschongik.gdsc.domain.study.api; + +import com.gdschongik.gdsc.domain.study.application.MentorStudyAchievementService; +import com.gdschongik.gdsc.domain.study.dto.request.OutstandingStudentRequest; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "Mentor StudyAchievement", description = "멘토 스터디 우수 스터디원 관리 API입니다.") +@RestController +@RequestMapping("/mentor/study-achievements") +@RequiredArgsConstructor +public class MentorStudyAchievementController { + + private final MentorStudyAchievementService mentorStudyAchievementService; + + @Operation(summary = "우수 스터디원 지정", description = "우수 스터디원으로 지정합니다.") + @PostMapping + public ResponseEntity designateOutstandingStudent( + @RequestParam(name = "studyId") Long studyId, @Valid @RequestBody OutstandingStudentRequest request) { + mentorStudyAchievementService.designateOutstandingStudent(studyId, request); + return ResponseEntity.ok().build(); + } + + @Operation(summary = "우수 스터디원 철회", description = "우수 스터디원 지정을 철회합니다.") + @DeleteMapping + public ResponseEntity withdrawOutstandingStudent( + @RequestParam(name = "studyId") Long studyId, @Valid @RequestBody OutstandingStudentRequest request) { + mentorStudyAchievementService.withdrawOutstandingStudent(studyId, request); + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyAchievementService.java b/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyAchievementService.java new file mode 100644 index 000000000..c639129a5 --- /dev/null +++ b/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyAchievementService.java @@ -0,0 +1,74 @@ +package com.gdschongik.gdsc.domain.study.application; + +import static com.gdschongik.gdsc.global.exception.ErrorCode.*; + +import com.gdschongik.gdsc.domain.member.dao.MemberRepository; +import com.gdschongik.gdsc.domain.member.domain.Member; +import com.gdschongik.gdsc.domain.study.dao.StudyAchievementRepository; +import com.gdschongik.gdsc.domain.study.dao.StudyHistoryRepository; +import com.gdschongik.gdsc.domain.study.dao.StudyRepository; +import com.gdschongik.gdsc.domain.study.domain.Study; +import com.gdschongik.gdsc.domain.study.domain.StudyAchievement; +import com.gdschongik.gdsc.domain.study.domain.StudyHistoryValidator; +import com.gdschongik.gdsc.domain.study.domain.StudyValidator; +import com.gdschongik.gdsc.domain.study.dto.request.OutstandingStudentRequest; +import com.gdschongik.gdsc.global.exception.CustomException; +import com.gdschongik.gdsc.global.util.MemberUtil; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Service +@RequiredArgsConstructor +public class MentorStudyAchievementService { + + private final MemberUtil memberUtil; + private final StudyValidator studyValidator; + private final StudyHistoryValidator studyHistoryValidator; + private final StudyRepository studyRepository; + private final StudyHistoryRepository studyHistoryRepository; + private final StudyAchievementRepository studyAchievementRepository; + private final MemberRepository memberRepository; + + @Transactional + public void designateOutstandingStudent(Long studyId, OutstandingStudentRequest request) { + Member currentMember = memberUtil.getCurrentMember(); + Study study = studyRepository.findById(studyId).orElseThrow(() -> new CustomException(STUDY_NOT_FOUND)); + Long countByStudyIdAndStudentIds = + studyHistoryRepository.countByStudyIdAndStudentIds(studyId, request.studentIds()); + + studyValidator.validateStudyMentor(currentMember, study); + studyHistoryValidator.validateAppliedToStudy( + countByStudyIdAndStudentIds, request.studentIds().size()); + + List outstandingStudents = memberRepository.findAllById(request.studentIds()); + List studyAchievements = outstandingStudents.stream() + .map(member -> StudyAchievement.create(member, study, request.achievementType())) + .toList(); + studyAchievementRepository.saveAll(studyAchievements); + + log.info( + "[MentorStudyAchievementService] 우수 스터디원 지정: studyId={}, studentIds={}", studyId, request.studentIds()); + } + + @Transactional + public void withdrawOutstandingStudent(Long studyId, OutstandingStudentRequest request) { + Member currentMember = memberUtil.getCurrentMember(); + Study study = studyRepository.findById(studyId).orElseThrow(() -> new CustomException(STUDY_NOT_FOUND)); + long countByStudyIdAndStudentIds = + studyHistoryRepository.countByStudyIdAndStudentIds(studyId, request.studentIds()); + + studyValidator.validateStudyMentor(currentMember, study); + studyHistoryValidator.validateAppliedToStudy( + countByStudyIdAndStudentIds, request.studentIds().size()); + + studyAchievementRepository.deleteByStudyAndAchievementTypeAndMemberIds( + studyId, request.achievementType(), request.studentIds()); + + log.info( + "[MentorStudyAchievementService] 우수 스터디원 철회: studyId={}, studentIds={}", studyId, request.studentIds()); + } +} diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyAchievementCustomRepository.java b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyAchievementCustomRepository.java index 2b14404f6..a6ad466ec 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyAchievementCustomRepository.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyAchievementCustomRepository.java @@ -1,8 +1,12 @@ package com.gdschongik.gdsc.domain.study.dao; +import com.gdschongik.gdsc.domain.study.domain.AchievementType; import com.gdschongik.gdsc.domain.study.domain.StudyAchievement; import java.util.List; public interface StudyAchievementCustomRepository { List findByStudyIdAndMemberIds(Long studyId, List memberIds); + + void deleteByStudyAndAchievementTypeAndMemberIds( + Long studyId, AchievementType achievementType, List memberIds); } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyAchievementCustomRepositoryImpl.java b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyAchievementCustomRepositoryImpl.java index 8eb3a9f46..0f8945573 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyAchievementCustomRepositoryImpl.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyAchievementCustomRepositoryImpl.java @@ -2,6 +2,7 @@ import static com.gdschongik.gdsc.domain.study.domain.QStudyAchievement.*; +import com.gdschongik.gdsc.domain.study.domain.AchievementType; import com.gdschongik.gdsc.domain.study.domain.StudyAchievement; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -21,6 +22,18 @@ public List findByStudyIdAndMemberIds(Long studyId, List .fetch(); } + @Override + public void deleteByStudyAndAchievementTypeAndMemberIds( + Long studyId, AchievementType achievementType, List memberIds) { + queryFactory + .delete(studyAchievement) + .where( + eqStudyId(studyId), + studyAchievement.achievementType.eq(achievementType), + studyAchievement.student.id.in(memberIds)) + .execute(); + } + private BooleanExpression eqStudyId(Long studyId) { return studyId != null ? studyAchievement.study.id.eq(studyId) : null; } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyHistoryCustomRepository.java b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyHistoryCustomRepository.java new file mode 100644 index 000000000..f64f7be6a --- /dev/null +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyHistoryCustomRepository.java @@ -0,0 +1,8 @@ +package com.gdschongik.gdsc.domain.study.dao; + +import java.util.List; + +public interface StudyHistoryCustomRepository { + + long countByStudyIdAndStudentIds(Long studyId, List studentIds); +} diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyHistoryCustomRepositoryImpl.java b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyHistoryCustomRepositoryImpl.java new file mode 100644 index 000000000..32232e65c --- /dev/null +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyHistoryCustomRepositoryImpl.java @@ -0,0 +1,27 @@ +package com.gdschongik.gdsc.domain.study.dao; + +import static com.gdschongik.gdsc.domain.study.domain.QStudyHistory.*; + +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; +import java.util.List; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class StudyHistoryCustomRepositoryImpl implements StudyHistoryCustomRepository { + + private final JPAQueryFactory queryFactory; + + @Override + public long countByStudyIdAndStudentIds(Long studyId, List studentIds) { + return (long) queryFactory + .select(studyHistory.count()) + .from(studyHistory) + .where(eqStudyId(studyId), studyHistory.student.id.in(studentIds)) + .fetchOne(); + } + + private BooleanExpression eqStudyId(Long studyId) { + return studyHistory.study.id.eq(studyId); + } +} diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyHistoryRepository.java b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyHistoryRepository.java index 02b61fceb..6e2dbb2cf 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyHistoryRepository.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dao/StudyHistoryRepository.java @@ -9,7 +9,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; -public interface StudyHistoryRepository extends JpaRepository { +public interface StudyHistoryRepository extends JpaRepository, StudyHistoryCustomRepository { List findAllByStudent(Member member); diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyHistoryValidator.java b/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyHistoryValidator.java index 2376df7b4..6a21b0f44 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyHistoryValidator.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyHistoryValidator.java @@ -51,4 +51,10 @@ public void validateUpdateRepository( throw new CustomException(STUDY_HISTORY_REPOSITORY_NOT_UPDATABLE_OWNER_MISMATCH); } } + + public void validateAppliedToStudy(long countStudyHistory, int studentCount) { + if (countStudyHistory != studentCount) { + throw new CustomException(STUDY_HISTORY_NOT_APPLIED_STUDENT_EXISTS); + } + } } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/OutstandingStudentRequest.java b/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/OutstandingStudentRequest.java new file mode 100644 index 000000000..771d09eef --- /dev/null +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/OutstandingStudentRequest.java @@ -0,0 +1,6 @@ +package com.gdschongik.gdsc.domain.study.dto.request; + +import com.gdschongik.gdsc.domain.study.domain.AchievementType; +import java.util.List; + +public record OutstandingStudentRequest(List studentIds, AchievementType achievementType) {} diff --git a/src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java b/src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java index 76ac38309..e0f5ac309 100644 --- a/src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java +++ b/src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java @@ -124,6 +124,7 @@ public enum ErrorCode { STUDY_HISTORY_REPOSITORY_NOT_UPDATABLE_ASSIGNMENT_ALREADY_SUBMITTED( HttpStatus.CONFLICT, "이미 제출한 과제가 있으므로 레포지토리를 수정할 수 없습니다."), STUDY_HISTORY_REPOSITORY_NOT_UPDATABLE_OWNER_MISMATCH(HttpStatus.CONFLICT, "레포지토리 소유자가 현재 멤버와 다릅니다."), + STUDY_HISTORY_NOT_APPLIED_STUDENT_EXISTS(HttpStatus.CONFLICT, "해당 스터디에 신청하지 않은 멤버가 있습니다."), // StudyAnnouncement STUDY_ANNOUNCEMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 스터디 공지입니다."), diff --git a/src/test/java/com/gdschongik/gdsc/domain/study/application/MentorStudyAchievementServiceTest.java b/src/test/java/com/gdschongik/gdsc/domain/study/application/MentorStudyAchievementServiceTest.java new file mode 100644 index 000000000..6fea5b242 --- /dev/null +++ b/src/test/java/com/gdschongik/gdsc/domain/study/application/MentorStudyAchievementServiceTest.java @@ -0,0 +1,82 @@ +package com.gdschongik.gdsc.domain.study.application; + +import static com.gdschongik.gdsc.domain.study.domain.AchievementType.*; +import static org.assertj.core.api.Assertions.*; + +import com.gdschongik.gdsc.domain.member.domain.Member; +import com.gdschongik.gdsc.domain.recruitment.domain.vo.Period; +import com.gdschongik.gdsc.domain.study.domain.Study; +import com.gdschongik.gdsc.domain.study.domain.StudyAchievement; +import com.gdschongik.gdsc.domain.study.dto.request.OutstandingStudentRequest; +import com.gdschongik.gdsc.helper.IntegrationTest; +import java.time.LocalDateTime; +import java.util.List; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +public class MentorStudyAchievementServiceTest extends IntegrationTest { + + @Autowired + private MentorStudyAchievementService mentorStudyAchievementService; + + @Nested + class 우수_스터디원_지정시 { + + @Test + void 성공한다() { + // given + LocalDateTime now = LocalDateTime.now(); + Member mentor = createMentor(); + Study study = createStudy( + mentor, + Period.createPeriod(now.plusDays(5), now.plusDays(10)), + Period.createPeriod(now.minusDays(5), now)); + + Member student = createRegularMember(); + createStudyHistory(student, study); + + logoutAndReloginAs(mentor.getId(), mentor.getRole()); + OutstandingStudentRequest request = + new OutstandingStudentRequest(List.of(student.getId()), FIRST_ROUND_OUTSTANDING_STUDENT); + + // when + mentorStudyAchievementService.designateOutstandingStudent(study.getId(), request); + + // then + List studyAchievements = + studyAchievementRepository.findByStudyIdAndMemberIds(study.getId(), request.studentIds()); + assertThat(studyAchievements).hasSize(request.studentIds().size()); + } + } + + @Nested + class 우수_스터디원_철회시 { + + @Test + void 성공한다() { + // given + Member student = createRegularMember(); + LocalDateTime now = LocalDateTime.now(); + Member mentor = createMentor(); + Study study = createStudy( + mentor, + Period.createPeriod(now.plusDays(5), now.plusDays(10)), + Period.createPeriod(now.minusDays(5), now)); + createStudyHistory(student, study); + createStudyAchievement(student, study, FIRST_ROUND_OUTSTANDING_STUDENT); + + logoutAndReloginAs(mentor.getId(), mentor.getRole()); + OutstandingStudentRequest request = + new OutstandingStudentRequest(List.of(student.getId()), FIRST_ROUND_OUTSTANDING_STUDENT); + + // when + mentorStudyAchievementService.withdrawOutstandingStudent(study.getId(), request); + + // then + List studyAchievements = + studyAchievementRepository.findByStudyIdAndMemberIds(study.getId(), request.studentIds()); + assertThat(studyAchievements).isEmpty(); + } + } +} diff --git a/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyHistoryValidatorTest.java b/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyHistoryValidatorTest.java index 5e6dcb2f1..7ddc02778 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyHistoryValidatorTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyHistoryValidatorTest.java @@ -124,4 +124,21 @@ class 레포지토리_입력시 { .hasMessage(STUDY_HISTORY_REPOSITORY_NOT_UPDATABLE_OWNER_MISMATCH.getMessage()); } } + + @Nested + class 스터디_수강신청_여부_확인시 { + + @Test + void 해당_스터디를_신청하지_않은_멤버가_있다면_실패한다() { + // given + Long countStudyHistory = 1L; + int requestStudentCount = 2; + + // when & then + assertThatThrownBy( + () -> studyHistoryValidator.validateAppliedToStudy(countStudyHistory, requestStudentCount)) + .isInstanceOf(CustomException.class) + .hasMessage(STUDY_HISTORY_NOT_APPLIED_STUDENT_EXISTS.getMessage()); + } + } } diff --git a/src/test/java/com/gdschongik/gdsc/helper/IntegrationTest.java b/src/test/java/com/gdschongik/gdsc/helper/IntegrationTest.java index dbd8c601b..c2c7deed9 100644 --- a/src/test/java/com/gdschongik/gdsc/helper/IntegrationTest.java +++ b/src/test/java/com/gdschongik/gdsc/helper/IntegrationTest.java @@ -30,10 +30,15 @@ import com.gdschongik.gdsc.domain.recruitment.domain.RecruitmentRound; import com.gdschongik.gdsc.domain.recruitment.domain.RoundType; import com.gdschongik.gdsc.domain.recruitment.domain.vo.Period; +import com.gdschongik.gdsc.domain.study.dao.StudyAchievementRepository; import com.gdschongik.gdsc.domain.study.dao.StudyDetailRepository; +import com.gdschongik.gdsc.domain.study.dao.StudyHistoryRepository; import com.gdschongik.gdsc.domain.study.dao.StudyRepository; +import com.gdschongik.gdsc.domain.study.domain.AchievementType; import com.gdschongik.gdsc.domain.study.domain.Study; +import com.gdschongik.gdsc.domain.study.domain.StudyAchievement; import com.gdschongik.gdsc.domain.study.domain.StudyDetail; +import com.gdschongik.gdsc.domain.study.domain.StudyHistory; import com.gdschongik.gdsc.global.security.PrincipalDetails; import com.gdschongik.gdsc.infra.feign.payment.client.PaymentClient; import com.gdschongik.gdsc.infra.github.client.GithubClient; @@ -81,6 +86,12 @@ public abstract class IntegrationTest { @Autowired protected StudyDetailRepository studyDetailRepository; + @Autowired + protected StudyHistoryRepository studyHistoryRepository; + + @Autowired + protected StudyAchievementRepository studyAchievementRepository; + @MockBean protected OnboardingRecruitmentService onboardingRecruitmentService; @@ -262,6 +273,16 @@ protected StudyDetail createNewStudyDetail(Long week, Study study, LocalDateTime return studyDetailRepository.save(studyDetail); } + protected StudyHistory createStudyHistory(Member member, Study study) { + StudyHistory studyHistory = StudyHistory.create(member, study); + return studyHistoryRepository.save(studyHistory); + } + + protected StudyAchievement createStudyAchievement(Member member, Study study, AchievementType achievementType) { + StudyAchievement studyAchievement = StudyAchievement.create(member, study, achievementType); + return studyAchievementRepository.save(studyAchievement); + } + protected StudyDetail publishAssignment(StudyDetail studyDetail) { studyDetail.publishAssignment(ASSIGNMENT_TITLE, studyDetail.getPeriod().getEndDate(), DESCRIPTION_LINK); return studyDetailRepository.save(studyDetail); From 382ac9a426831281dbb06fe9b678497d0e1a6837 Mon Sep 17 00:00:00 2001 From: Jaehyun Ahn <91878695+uwoobeat@users.noreply.github.com> Date: Sat, 12 Oct 2024 16:36:38 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20Period=EB=A5=BC=20=EC=99=B8?= =?UTF-8?q?=EB=B6=80=EC=97=90=EC=84=9C=20=EC=83=9D=EC=84=B1=EB=90=9C=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=EB=A1=9C=20=EB=B0=9B=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#793)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: RequiredArgs 생성자로 변경 * refactor: 생성된 Period를 인자로 받도록 수정 * refactor: START_TO_END_PERIOD 상수를 사용하도록 변경 * refactor: STUDY_ONGOING_PERIOD 적용 * feat: 2차 모집기간 상수 추가 * style: spotless 적용 --- .../application/AdminRecruitmentService.java | 5 +- .../recruitment/domain/RecruitmentRound.java | 4 +- .../domain/recruitment/domain/RoundType.java | 4 +- .../member/domain/MemberValidatorTest.java | 8 +-- .../membership/domain/MembershipTest.java | 2 +- .../domain/MembershipValidatorTest.java | 3 +- .../AdminRecruitmentServiceTest.java | 5 +- .../domain/RecruitmentRoundValidatorTest.java | 54 +++++++++---------- .../domain/AssignmentHistoryGraderTest.java | 3 +- .../study/domain/AssignmentHistoryTest.java | 3 +- .../StudyAssignmentHistoryValidatorTest.java | 3 +- .../gdsc/domain/study/domain/StudyTest.java | 3 +- .../common/constant/RecruitmentConstant.java | 4 ++ .../global/common/constant/StudyConstant.java | 2 + .../gdschongik/gdsc/helper/FixtureHelper.java | 3 +- .../gdsc/helper/IntegrationTest.java | 5 +- 16 files changed, 60 insertions(+), 51 deletions(-) diff --git a/src/main/java/com/gdschongik/gdsc/domain/recruitment/application/AdminRecruitmentService.java b/src/main/java/com/gdschongik/gdsc/domain/recruitment/application/AdminRecruitmentService.java index 23bab5cd0..7eca3189f 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/recruitment/application/AdminRecruitmentService.java +++ b/src/main/java/com/gdschongik/gdsc/domain/recruitment/application/AdminRecruitmentService.java @@ -81,7 +81,10 @@ public void createRecruitmentRound(RecruitmentRoundCreateRequest request) { recruitmentRoundsInThisSemester); RecruitmentRound recruitmentRound = RecruitmentRound.create( - request.name(), request.startDate(), request.endDate(), recruitment, request.roundType()); + request.name(), + Period.createPeriod(request.startDate(), request.endDate()), + recruitment, + request.roundType()); recruitmentRoundRepository.save(recruitmentRound); log.info("[AdminRecruitmentService] 모집회차 생성: recruitmentRoundId={}", recruitmentRound.getId()); diff --git a/src/main/java/com/gdschongik/gdsc/domain/recruitment/domain/RecruitmentRound.java b/src/main/java/com/gdschongik/gdsc/domain/recruitment/domain/RecruitmentRound.java index 94e6e1cd7..59857f237 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/recruitment/domain/RecruitmentRound.java +++ b/src/main/java/com/gdschongik/gdsc/domain/recruitment/domain/RecruitmentRound.java @@ -59,9 +59,7 @@ private RecruitmentRound( this.roundType = roundType; } - public static RecruitmentRound create( - String name, LocalDateTime startDate, LocalDateTime endDate, Recruitment recruitment, RoundType roundType) { - Period period = Period.createPeriod(startDate, endDate); + public static RecruitmentRound create(String name, Period period, Recruitment recruitment, RoundType roundType) { return RecruitmentRound.builder() .name(name) .period(period) diff --git a/src/main/java/com/gdschongik/gdsc/domain/recruitment/domain/RoundType.java b/src/main/java/com/gdschongik/gdsc/domain/recruitment/domain/RoundType.java index f1d377d10..02655e2ed 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/recruitment/domain/RoundType.java +++ b/src/main/java/com/gdschongik/gdsc/domain/recruitment/domain/RoundType.java @@ -1,10 +1,10 @@ package com.gdschongik.gdsc.domain.recruitment.domain; -import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.RequiredArgsConstructor; @Getter -@AllArgsConstructor +@RequiredArgsConstructor public enum RoundType { FIRST("1차"), SECOND("2차"); diff --git a/src/test/java/com/gdschongik/gdsc/domain/member/domain/MemberValidatorTest.java b/src/test/java/com/gdschongik/gdsc/domain/member/domain/MemberValidatorTest.java index 7861dff96..82a70e15a 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/member/domain/MemberValidatorTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/member/domain/MemberValidatorTest.java @@ -24,12 +24,12 @@ class 준회원으로_일괄_강등시 { @Test void 해당_학기에_이미_시작된_모집기간이_있다면_실패한다() { // given - Recruitment recruitment = Recruitment.createRecruitment( - ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, Period.createPeriod(START_DATE, END_DATE)); + Recruitment recruitment = + Recruitment.createRecruitment(ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, START_TO_END_PERIOD); + LocalDateTime now = LocalDateTime.now(); RecruitmentRound recruitmentRound = RecruitmentRound.create( RECRUITMENT_ROUND_NAME, - LocalDateTime.now().minusDays(1), - LocalDateTime.now().plusDays(1), + Period.createPeriod(now.minusDays(1), now.plusDays(1)), recruitment, ROUND_TYPE); List recruitmentRounds = List.of(recruitmentRound); diff --git a/src/test/java/com/gdschongik/gdsc/domain/membership/domain/MembershipTest.java b/src/test/java/com/gdschongik/gdsc/domain/membership/domain/MembershipTest.java index d92981419..72d015e43 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/membership/domain/MembershipTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/membership/domain/MembershipTest.java @@ -36,7 +36,7 @@ class 멤버십_가입신청시 { FEE_NAME, Period.createPeriod(SEMESTER_START_DATE, SEMESTER_END_DATE)); RecruitmentRound recruitmentRound = - RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_DATE, END_DATE, recruitment, ROUND_TYPE); + RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_TO_END_PERIOD, recruitment, ROUND_TYPE); // when Membership membership = Membership.createMembership(member, recruitmentRound); diff --git a/src/test/java/com/gdschongik/gdsc/domain/membership/domain/MembershipValidatorTest.java b/src/test/java/com/gdschongik/gdsc/domain/membership/domain/MembershipValidatorTest.java index 11181fa80..cb99e27ec 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/membership/domain/MembershipValidatorTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/membership/domain/MembershipValidatorTest.java @@ -43,7 +43,8 @@ private RecruitmentRound createRecruitmentRound( LocalDateTime endDate) { Recruitment recruitment = Recruitment.createRecruitment( academicYear, semesterType, fee, FEE_NAME, Period.createPeriod(SEMESTER_START_DATE, SEMESTER_END_DATE)); - return RecruitmentRound.create(RECRUITMENT_ROUND_NAME, startDate, endDate, recruitment, ROUND_TYPE); + return RecruitmentRound.create( + RECRUITMENT_ROUND_NAME, Period.createPeriod(startDate, endDate), recruitment, ROUND_TYPE); } @Nested diff --git a/src/test/java/com/gdschongik/gdsc/domain/recruitment/application/AdminRecruitmentServiceTest.java b/src/test/java/com/gdschongik/gdsc/domain/recruitment/application/AdminRecruitmentServiceTest.java index f70ac4b68..805828841 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/recruitment/application/AdminRecruitmentServiceTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/recruitment/application/AdminRecruitmentServiceTest.java @@ -75,7 +75,10 @@ class 모집회차_수정시 { recruitmentRepository.save(recruitment); RecruitmentRound recruitmentRound = RecruitmentRound.create( - RECRUITMENT_ROUND_NAME, now.plusDays(1), now.plusDays(2), recruitment, ROUND_TYPE); + RECRUITMENT_ROUND_NAME, + Period.createPeriod(now.plusDays(1), now.plusDays(2)), + recruitment, + ROUND_TYPE); recruitmentRoundRepository.save(recruitmentRound); RecruitmentRoundUpdateRequest request = new RecruitmentRoundUpdateRequest( diff --git a/src/test/java/com/gdschongik/gdsc/domain/recruitment/domain/RecruitmentRoundValidatorTest.java b/src/test/java/com/gdschongik/gdsc/domain/recruitment/domain/RecruitmentRoundValidatorTest.java index 0f9c27cd0..20b250d15 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/recruitment/domain/RecruitmentRoundValidatorTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/recruitment/domain/RecruitmentRoundValidatorTest.java @@ -58,8 +58,8 @@ class 모집회차_생성시 { @Test void 모집_시작일과_종료일이_학기_시작일로부터_2주_이내에_있지_않다면_실패한다() { // given - Recruitment recruitment = Recruitment.createRecruitment( - ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, Period.createPeriod(START_DATE, END_DATE)); + Recruitment recruitment = + Recruitment.createRecruitment(ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, START_TO_END_PERIOD); // when & then assertThatThrownBy(() -> recruitmentRoundValidator.validateRecruitmentRoundCreate( @@ -71,11 +71,11 @@ class 모집회차_생성시 { @Test void 학년도_학기_차수가_모두_중복되면_실패한다() { // given - Recruitment recruitment = Recruitment.createRecruitment( - ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, Period.createPeriod(START_DATE, END_DATE)); + Recruitment recruitment = + Recruitment.createRecruitment(ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, START_TO_END_PERIOD); RecruitmentRound recruitmentRound = - RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_DATE, END_DATE, recruitment, ROUND_TYPE); + RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_TO_END_PERIOD, recruitment, ROUND_TYPE); // when & then assertThatThrownBy(() -> recruitmentRoundValidator.validateRecruitmentRoundCreate( @@ -91,8 +91,8 @@ class 모집회차_생성시 { @Test void RoundType_1차가_없을때_2차를_생성하려_하면_실패한다() { // given - Recruitment recruitment = Recruitment.createRecruitment( - ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, Period.createPeriod(START_DATE, END_DATE)); + Recruitment recruitment = + Recruitment.createRecruitment(ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, START_TO_END_PERIOD); // when & then assertThatThrownBy(() -> recruitmentRoundValidator.validateRecruitmentRoundCreate( @@ -104,11 +104,11 @@ class 모집회차_생성시 { @Test void 기간이_중복되는_모집회차가_있다면_실패한다() { // given - Recruitment recruitment = Recruitment.createRecruitment( - ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, Period.createPeriod(START_DATE, END_DATE)); + Recruitment recruitment = + Recruitment.createRecruitment(ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, START_TO_END_PERIOD); RecruitmentRound recruitmentRound = - RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_DATE, END_DATE, recruitment, ROUND_TYPE); + RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_TO_END_PERIOD, recruitment, ROUND_TYPE); // when & then assertThatThrownBy(() -> recruitmentRoundValidator.validateRecruitmentRoundCreate( @@ -124,15 +124,15 @@ class 모집회차_수정시 { @Test void 기간이_중복되는_모집회차가_있다면_실패한다() { // given - Recruitment recruitment = Recruitment.createRecruitment( - ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, Period.createPeriod(START_DATE, END_DATE)); + Recruitment recruitment = + Recruitment.createRecruitment(ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, START_TO_END_PERIOD); RecruitmentRound firstRound = - RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_DATE, END_DATE, recruitment, ROUND_TYPE); + RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_TO_END_PERIOD, recruitment, ROUND_TYPE); ReflectionTestUtils.setField(firstRound, "id", 1L); RecruitmentRound secondRound = RecruitmentRound.create( - RECRUITMENT_ROUND_NAME, ROUND_TWO_START_DATE, ROUND_TWO_END_DATE, recruitment, RoundType.SECOND); + RECRUITMENT_ROUND_NAME, ROUND_TWO_START_TO_END_PERIOD, recruitment, RoundType.SECOND); ReflectionTestUtils.setField(secondRound, "id", 2L); // when & then @@ -145,15 +145,15 @@ class 모집회차_수정시 { @Test void 차수가_중복되는_모집회차가_있다면_실패한다() { // given - Recruitment recruitment = Recruitment.createRecruitment( - ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, Period.createPeriod(START_DATE, END_DATE)); + Recruitment recruitment = + Recruitment.createRecruitment(ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, START_TO_END_PERIOD); RecruitmentRound firstRound = - RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_DATE, END_DATE, recruitment, ROUND_TYPE); + RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_TO_END_PERIOD, recruitment, ROUND_TYPE); ReflectionTestUtils.setField(firstRound, "id", 1L); RecruitmentRound secondRound = RecruitmentRound.create( - RECRUITMENT_ROUND_NAME, ROUND_TWO_START_DATE, ROUND_TWO_END_DATE, recruitment, RoundType.SECOND); + RECRUITMENT_ROUND_NAME, ROUND_TWO_START_TO_END_PERIOD, recruitment, RoundType.SECOND); ReflectionTestUtils.setField(secondRound, "id", 2L); // when & then @@ -166,11 +166,11 @@ class 모집회차_수정시 { @Test void 모집_시작일과_종료일이_학기_시작일로부터_2주_이내에_있지_않다면_실패한다() { // given - Recruitment recruitment = Recruitment.createRecruitment( - ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, Period.createPeriod(START_DATE, END_DATE)); + Recruitment recruitment = + Recruitment.createRecruitment(ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, START_TO_END_PERIOD); RecruitmentRound firstRound = - RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_DATE, END_DATE, recruitment, ROUND_TYPE); + RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_TO_END_PERIOD, recruitment, ROUND_TYPE); ReflectionTestUtils.setField(firstRound, "id", 1L); // when & then @@ -183,11 +183,11 @@ class 모집회차_수정시 { @Test void RoundType_1차를_2차로_수정하려_하면_실패한다() { // given - Recruitment recruitment = Recruitment.createRecruitment( - ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, Period.createPeriod(START_DATE, END_DATE)); + Recruitment recruitment = + Recruitment.createRecruitment(ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, START_TO_END_PERIOD); RecruitmentRound firstRound = - RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_DATE, END_DATE, recruitment, ROUND_TYPE); + RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_TO_END_PERIOD, recruitment, ROUND_TYPE); ReflectionTestUtils.setField(firstRound, "id", 1L); // when & then @@ -200,11 +200,11 @@ class 모집회차_수정시 { @Test void 모집_시작일이_지났다면_수정_실패한다() { // given - Recruitment recruitment = Recruitment.createRecruitment( - ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, Period.createPeriod(START_DATE, END_DATE)); + Recruitment recruitment = + Recruitment.createRecruitment(ACADEMIC_YEAR, SEMESTER_TYPE, FEE, FEE_NAME, START_TO_END_PERIOD); RecruitmentRound recruitmentRound = - RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_DATE, END_DATE, recruitment, ROUND_TYPE); + RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_TO_END_PERIOD, recruitment, ROUND_TYPE); long recruitmentRoundId = 1L; ReflectionTestUtils.setField(recruitmentRound, "id", recruitmentRoundId); diff --git a/src/test/java/com/gdschongik/gdsc/domain/study/domain/AssignmentHistoryGraderTest.java b/src/test/java/com/gdschongik/gdsc/domain/study/domain/AssignmentHistoryGraderTest.java index 671488c27..2f004cc66 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/study/domain/AssignmentHistoryGraderTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/study/domain/AssignmentHistoryGraderTest.java @@ -28,10 +28,9 @@ private AssignmentHistory createAssignmentHistory() { } private Study createStudyWithMentor(Long mentorId) { - Period period = Period.createPeriod(STUDY_START_DATETIME, STUDY_END_DATETIME); Period applicationPeriod = Period.createPeriod(STUDY_START_DATETIME.minusDays(7), STUDY_START_DATETIME.minusDays(1)); - return fixtureHelper.createStudyWithMentor(mentorId, period, applicationPeriod); + return fixtureHelper.createStudyWithMentor(mentorId, STUDY_ONGOING_PERIOD, applicationPeriod); } @Nested diff --git a/src/test/java/com/gdschongik/gdsc/domain/study/domain/AssignmentHistoryTest.java b/src/test/java/com/gdschongik/gdsc/domain/study/domain/AssignmentHistoryTest.java index 3c45e14d1..689852f10 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/study/domain/AssignmentHistoryTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/study/domain/AssignmentHistoryTest.java @@ -20,10 +20,9 @@ private Member createMember(Long id) { } private Study createStudyWithMentor(Long mentorId) { - Period period = Period.createPeriod(STUDY_START_DATETIME, STUDY_END_DATETIME); Period applicationPeriod = Period.createPeriod(STUDY_START_DATETIME.minusDays(7), STUDY_START_DATETIME.minusDays(1)); - return fixtureHelper.createStudyWithMentor(mentorId, period, applicationPeriod); + return fixtureHelper.createStudyWithMentor(mentorId, STUDY_ONGOING_PERIOD, applicationPeriod); } private StudyDetail createStudyDetailWithAssignment(Study study) { diff --git a/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyAssignmentHistoryValidatorTest.java b/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyAssignmentHistoryValidatorTest.java index 5af2b9699..c2fae7e91 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyAssignmentHistoryValidatorTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyAssignmentHistoryValidatorTest.java @@ -23,10 +23,9 @@ private Member createMember(Long id) { } private Study createStudyWithMentor(Long mentorId) { - Period period = Period.createPeriod(STUDY_START_DATETIME, STUDY_END_DATETIME); Period applicationPeriod = Period.createPeriod(STUDY_START_DATETIME.minusDays(7), STUDY_START_DATETIME.minusDays(1)); - return fixtureHelper.createStudyWithMentor(mentorId, period, applicationPeriod); + return fixtureHelper.createStudyWithMentor(mentorId, STUDY_ONGOING_PERIOD, applicationPeriod); } private StudyDetail createStudyDetailWithAssignment(Study study) { diff --git a/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyTest.java b/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyTest.java index d98bccf2d..0d04fa356 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyTest.java @@ -37,7 +37,6 @@ class 스터디_개설시 { void 게스트인_회원을_멘토로_지정하면_실패한다() { // given Member guestMember = Member.createGuestMember(OAUTH_ID); - Period period = Period.createPeriod(START_DATE, END_DATE); Period applicationPeriod = Period.createPeriod(START_DATE.minusDays(10), START_DATE.minusDays(5)); // when & then @@ -46,7 +45,7 @@ class 스터디_개설시 { SEMESTER_TYPE, STUDY_TITLE, guestMember, - period, + START_TO_END_PERIOD, applicationPeriod, TOTAL_WEEK, ONLINE_STUDY, diff --git a/src/test/java/com/gdschongik/gdsc/global/common/constant/RecruitmentConstant.java b/src/test/java/com/gdschongik/gdsc/global/common/constant/RecruitmentConstant.java index beae5f5cb..c14ab7563 100644 --- a/src/test/java/com/gdschongik/gdsc/global/common/constant/RecruitmentConstant.java +++ b/src/test/java/com/gdschongik/gdsc/global/common/constant/RecruitmentConstant.java @@ -2,6 +2,7 @@ import com.gdschongik.gdsc.domain.common.vo.Money; import com.gdschongik.gdsc.domain.recruitment.domain.RoundType; +import com.gdschongik.gdsc.domain.recruitment.domain.vo.Period; import java.math.BigDecimal; import java.time.LocalDateTime; @@ -12,6 +13,7 @@ public class RecruitmentConstant { public static final LocalDateTime BETWEEN_START_AND_END_DATE = LocalDateTime.of(2024, 3, 3, 0, 0); public static final LocalDateTime WRONG_END_DATE = LocalDateTime.of(2024, 3, 2, 0, 0); public static final LocalDateTime END_DATE = LocalDateTime.of(2024, 3, 5, 0, 0); + public static final Period START_TO_END_PERIOD = Period.createPeriod(START_DATE, END_DATE); public static final Money FEE = Money.from(20000L); public static final BigDecimal FEE_AMOUNT = BigDecimal.valueOf(20000); @@ -22,6 +24,8 @@ public class RecruitmentConstant { public static final String ROUND_TWO_RECRUITMENT_NAME = "2024학년도 1학기 2차 모집"; public static final LocalDateTime ROUND_TWO_START_DATE = LocalDateTime.of(2024, 3, 8, 0, 0); public static final LocalDateTime ROUND_TWO_END_DATE = LocalDateTime.of(2024, 3, 10, 0, 0); + public static final Period ROUND_TWO_START_TO_END_PERIOD = + Period.createPeriod(ROUND_TWO_START_DATE, ROUND_TWO_END_DATE); private RecruitmentConstant() {} } diff --git a/src/test/java/com/gdschongik/gdsc/global/common/constant/StudyConstant.java b/src/test/java/com/gdschongik/gdsc/global/common/constant/StudyConstant.java index d39cf6334..bdc0afaea 100644 --- a/src/test/java/com/gdschongik/gdsc/global/common/constant/StudyConstant.java +++ b/src/test/java/com/gdschongik/gdsc/global/common/constant/StudyConstant.java @@ -1,5 +1,6 @@ package com.gdschongik.gdsc.global.common.constant; +import com.gdschongik.gdsc.domain.recruitment.domain.vo.Period; import com.gdschongik.gdsc.domain.study.domain.StudyType; import java.time.DayOfWeek; import java.time.LocalDateTime; @@ -26,6 +27,7 @@ private StudyConstant() {} // Study (2024-09-01 ~ 2024-10-27) public static final LocalDateTime STUDY_START_DATETIME = LocalDateTime.of(2024, 9, 1, 0, 0); public static final LocalDateTime STUDY_END_DATETIME = STUDY_START_DATETIME.plusWeeks(8); + public static final Period STUDY_ONGOING_PERIOD = Period.createPeriod(STUDY_START_DATETIME, STUDY_END_DATETIME); public static final String STUDY_NOTION_LINK = "notionLink"; public static final String STUDY_INTRODUCTION = "introduction"; diff --git a/src/test/java/com/gdschongik/gdsc/helper/FixtureHelper.java b/src/test/java/com/gdschongik/gdsc/helper/FixtureHelper.java index ea1343667..f24a39dcb 100644 --- a/src/test/java/com/gdschongik/gdsc/helper/FixtureHelper.java +++ b/src/test/java/com/gdschongik/gdsc/helper/FixtureHelper.java @@ -69,7 +69,8 @@ public RecruitmentRound createRecruitmentRound( Recruitment recruitment = Recruitment.createRecruitment( academicYear, semesterType, fee, FEE_NAME, Period.createPeriod(SEMESTER_START_DATE, SEMESTER_END_DATE)); - return RecruitmentRound.create(RECRUITMENT_ROUND_NAME, startDate, endDate, recruitment, RoundType.FIRST); + return RecruitmentRound.create( + RECRUITMENT_ROUND_NAME, Period.createPeriod(startDate, endDate), recruitment, RoundType.FIRST); } public Membership createMembership(Member member, RecruitmentRound recruitmentRound) { diff --git a/src/test/java/com/gdschongik/gdsc/helper/IntegrationTest.java b/src/test/java/com/gdschongik/gdsc/helper/IntegrationTest.java index c2c7deed9..7ef757ac1 100644 --- a/src/test/java/com/gdschongik/gdsc/helper/IntegrationTest.java +++ b/src/test/java/com/gdschongik/gdsc/helper/IntegrationTest.java @@ -190,7 +190,7 @@ protected RecruitmentRound createRecruitmentRound() { Recruitment recruitment = createRecruitment(ACADEMIC_YEAR, SEMESTER_TYPE, FEE); RecruitmentRound recruitmentRound = - RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_DATE, END_DATE, recruitment, ROUND_TYPE); + RecruitmentRound.create(RECRUITMENT_ROUND_NAME, START_TO_END_PERIOD, recruitment, ROUND_TYPE); return recruitmentRoundRepository.save(recruitmentRound); } @@ -205,7 +205,8 @@ protected RecruitmentRound createRecruitmentRound( Money fee) { Recruitment recruitment = createRecruitment(academicYear, semesterType, fee); - RecruitmentRound recruitmentRound = RecruitmentRound.create(name, startDate, endDate, recruitment, roundType); + RecruitmentRound recruitmentRound = + RecruitmentRound.create(name, Period.createPeriod(startDate, endDate), recruitment, roundType); return recruitmentRoundRepository.save(recruitmentRound); }