From b8df9581d70bbb8176c421c79f126b61942a9e7e Mon Sep 17 00:00:00 2001 From: Jaehyun Ahn <91878695+uwoobeat@users.noreply.github.com> Date: Mon, 26 Aug 2024 12:48:45 +0900 Subject: [PATCH 01/10] =?UTF-8?q?hotfix:=20=EC=86=8C=EC=85=9C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EB=A6=AC=EB=8B=A4=EC=9D=B4=EB=A0=89?= =?UTF-8?q?=ED=8A=B8=20URI=EA=B0=80=20=EC=9E=91=EB=8F=99=ED=95=98=EC=A7=80?= =?UTF-8?q?=20=EC=95=8A=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20(#690)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * hotfix: 이메일 정규식에 언더스코어를 허용하도록 수정 (#205) * fix: 언더스코어 허용하도록 변경 * refactor: 테스트 접근제어자 제거 * hotfix: Basic Auth 환경변수 속성 이름 수정 (#260) * fix: 환경변수 속성 이름 오타 수정 * refactor: Basic Auth 환경변수 이름 재수정 * hotfix: 학과 쿼리 메서드 수정 (#282) * hotfix: spotless 적용 (#283) style: spotless 적용 * fix: 추가 파라미터에서 리다이렉트 URI로 수정 --------- Co-authored-by: Cho Sangwook <82208159+Sangwook02@users.noreply.github.com> Co-authored-by: 이한비 <99820610+AlmondBreez3@users.noreply.github.com> --- .../CustomOAuth2AuthorizationRequestResolver.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/gdschongik/gdsc/global/security/CustomOAuth2AuthorizationRequestResolver.java b/src/main/java/com/gdschongik/gdsc/global/security/CustomOAuth2AuthorizationRequestResolver.java index 1d3ae33e3..affbcf493 100644 --- a/src/main/java/com/gdschongik/gdsc/global/security/CustomOAuth2AuthorizationRequestResolver.java +++ b/src/main/java/com/gdschongik/gdsc/global/security/CustomOAuth2AuthorizationRequestResolver.java @@ -3,12 +3,11 @@ import static com.gdschongik.gdsc.global.common.constant.SecurityConstant.*; import jakarta.servlet.http.HttpServletRequest; -import java.util.HashMap; -import java.util.Map; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizationRequestResolver; import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; +import org.springframework.web.util.UriComponentsBuilder; public class CustomOAuth2AuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver { @@ -35,15 +34,17 @@ private OAuth2AuthorizationRequest customizeAuthorizationRequest( HttpServletRequest request, OAuth2AuthorizationRequest authorizationRequest) { String referer = request.getHeader("Referer"); + if (referer == null || referer.isEmpty()) { return authorizationRequest; } - Map additionalParameters = new HashMap<>(); - additionalParameters.put(OAUTH_TARGET_URL_PARAM_NAME, referer); + String redirectUri = UriComponentsBuilder.fromHttpUrl(authorizationRequest.getRedirectUri()) + .queryParam(OAUTH_TARGET_URL_PARAM_NAME, referer) + .toUriString(); return OAuth2AuthorizationRequest.from(authorizationRequest) - .additionalParameters(additionalParameters) + .redirectUri(redirectUri) .build(); } } From a221b8366287c7cc4c14b3fb13642f19532226b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=AC=EA=B8=B0?= <84620016+seulgi99@users.noreply.github.com> Date: Mon, 26 Aug 2024 15:31:40 +0900 Subject: [PATCH 02/10] =?UTF-8?q?feat:=20=EC=8A=A4=ED=84=B0=EB=94=94=20?= =?UTF-8?q?=EC=A3=BC=EC=B0=A8=EB=B3=84=20=EC=B6=9C=EA=B2=B0=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=A1=B0=ED=9A=8C=20(#688)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 스터디 주차별 출결번호 조회 * refactor: 리퀘스트 파라미터 변수명 수정 * refactor: 스터디 출석일자 지났는지 판단 로직 추가 * refactor: 출석일 지남 여부 판단 메소드명 변경 --- .../api/MentorStudyDetailController.java | 11 ++++++++++- .../application/MentorStudyDetailService.java | 13 +++++++++++++ .../gdsc/domain/study/domain/StudyDetail.java | 5 +++++ .../StudyMentorAttendanceResponse.java | 19 +++++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyMentorAttendanceResponse.java diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyDetailController.java b/src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyDetailController.java index bc74e9a7b..9a961a4e7 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyDetailController.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyDetailController.java @@ -3,6 +3,7 @@ import com.gdschongik.gdsc.domain.study.application.MentorStudyDetailService; import com.gdschongik.gdsc.domain.study.dto.request.AssignmentCreateUpdateRequest; import com.gdschongik.gdsc.domain.study.dto.response.AssignmentResponse; +import com.gdschongik.gdsc.domain.study.dto.response.StudyMentorAttendanceResponse; import com.gdschongik.gdsc.domain.study.dto.response.StudySessionResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -67,8 +68,16 @@ public ResponseEntity cancelStudyAssignment(@PathVariable Long studyDetail // TODO 스터디 세션 워딩을 커리큘럼으로 변경해야함 @Operation(summary = "스터디 주차별 커리큘럼 목록 조회", description = "멘토가 자신의 스터디 커리큘럼 목록을 조회합니다") @GetMapping("/sessions") - public ResponseEntity> getStudySessions(@RequestParam(name = "study") Long studyId) { + public ResponseEntity> getStudySessions(@RequestParam(name = "studyId") Long studyId) { List response = mentorStudyDetailService.getSessions(studyId); return ResponseEntity.ok(response); } + + @Operation(summary = "스터디 주차별 출결번호 조회", description = "멘토가 자신의 스터디 출결번호 목록을 조회합니다. 지난 출석은 목록에서 제외합니다.") + @GetMapping("/attendances") + public ResponseEntity> getAttendanceNumbers( + @RequestParam(name = "studyId") Long studyId) { + List response = mentorStudyDetailService.getAttendanceNumbers(studyId); + return ResponseEntity.ok(response); + } } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyDetailService.java b/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyDetailService.java index b6bb9dbb5..629608cb3 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyDetailService.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyDetailService.java @@ -8,9 +8,11 @@ import com.gdschongik.gdsc.domain.study.domain.StudyDetailValidator; import com.gdschongik.gdsc.domain.study.dto.request.AssignmentCreateUpdateRequest; import com.gdschongik.gdsc.domain.study.dto.response.AssignmentResponse; +import com.gdschongik.gdsc.domain.study.dto.response.StudyMentorAttendanceResponse; import com.gdschongik.gdsc.domain.study.dto.response.StudySessionResponse; import com.gdschongik.gdsc.global.exception.CustomException; import com.gdschongik.gdsc.global.util.MemberUtil; +import java.time.LocalDate; import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -90,4 +92,15 @@ public List getSessions(Long studyId) { List studyDetails = studyDetailRepository.findAllByStudyIdOrderByWeekAsc(studyId); return studyDetails.stream().map(StudySessionResponse::from).toList(); } + + @Transactional(readOnly = true) + public List getAttendanceNumbers(Long studyId) { + List studyDetails = studyDetailRepository.findAllByStudyIdOrderByWeekAsc(studyId); + + // 출석일이 오늘 or 오늘이후인 StudyDetail + return studyDetails.stream() + .filter(studyDetail -> studyDetail.isAttendanceDayNotPassed(LocalDate.now())) + .map(StudyMentorAttendanceResponse::from) + .toList(); + } } 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 41bb4a0b5..c2b0c4cc5 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 @@ -123,6 +123,11 @@ public LocalDate getAttendanceDay() { return startDate.plusDays(daysToAdd); } + // 출석일이 오늘 or 오늘이후인지 확인 + public boolean isAttendanceDayNotPassed(LocalDate now) { + return !getAttendanceDay().isBefore(now); + } + public void updateSession( LocalTime startAt, String title, String description, Difficulty difficulty, StudyStatus status) { session = Session.generateSession(startAt, title, description, difficulty, status); diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyMentorAttendanceResponse.java b/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyMentorAttendanceResponse.java new file mode 100644 index 000000000..c33665016 --- /dev/null +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyMentorAttendanceResponse.java @@ -0,0 +1,19 @@ +package com.gdschongik.gdsc.domain.study.dto.response; + +import com.gdschongik.gdsc.domain.study.domain.StudyDetail; +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDateTime; + +public record StudyMentorAttendanceResponse( + Long studyDetailId, + @Schema(description = "주차수") Long week, + @Schema(description = "마감시각") LocalDateTime deadLine, + @Schema(description = "출석번호") String attendanceNumber) { + public static StudyMentorAttendanceResponse from(StudyDetail studyDetail) { + return new StudyMentorAttendanceResponse( + studyDetail.getId(), + studyDetail.getWeek(), + studyDetail.getAttendanceDay().atTime(23, 59, 59), + studyDetail.getAttendanceNumber()); + } +} From 758943f98d19ecf5516d4c07ac2c1fe362b13957 Mon Sep 17 00:00:00 2001 From: Cho Sangwook <82208159+Sangwook02@users.noreply.github.com> Date: Tue, 27 Aug 2024 19:25:57 +0900 Subject: [PATCH 03/10] =?UTF-8?q?feat:=20=EC=96=B4=EB=93=9C=EB=AF=BC?= =?UTF-8?q?=EC=97=90=EA=B2=8C=20=EB=A9=98=ED=86=A0=20API=20=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=20=EA=B6=8C=ED=95=9C=20=EB=B6=80=EC=97=AC=20(#692)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: 어드민에게 멘토 api 접근 권한 부여 --- .../com/gdschongik/gdsc/global/config/WebSecurityConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/gdschongik/gdsc/global/config/WebSecurityConfig.java b/src/main/java/com/gdschongik/gdsc/global/config/WebSecurityConfig.java index 3dab1279d..b30d71cd4 100644 --- a/src/main/java/com/gdschongik/gdsc/global/config/WebSecurityConfig.java +++ b/src/main/java/com/gdschongik/gdsc/global/config/WebSecurityConfig.java @@ -123,7 +123,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers("/admin/**") .hasRole("ADMIN") .requestMatchers("/mentor/**") - .hasRole("MENTOR") + .hasAnyRole("MENTOR", "ADMIN") .anyRequest() .authenticated()); From b58263439d7b1bc7f5ced6319b8ce45ff0e9fff5 Mon Sep 17 00:00:00 2001 From: Cho Sangwook <82208159+Sangwook02@users.noreply.github.com> Date: Tue, 27 Aug 2024 22:53:22 +0900 Subject: [PATCH 04/10] =?UTF-8?q?refactor:=20=EC=8A=A4=ED=84=B0=EB=94=94?= =?UTF-8?q?=20=EA=B0=9C=EA=B0=95=EC=9D=BC=20=EC=A0=84=EC=97=90=EB=8F=84=20?= =?UTF-8?q?=EB=82=B4=20=EC=88=98=EA=B0=95=EC=A4=91=EC=9D=B8=20=EC=8A=A4?= =?UTF-8?q?=ED=84=B0=EB=94=94=20=EC=A1=B0=ED=9A=8C=20API=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EC=84=A0=EB=B3=84=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95=20(#694)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refactor: 스터디 개강일 전에도 내 수강중인 스터디 조회 api에서 선별할 수 있도록 수정 --- .../gdsc/domain/study/application/StudentStudyService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyService.java b/src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyService.java index ba5a997e8..da90b4240 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyService.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/application/StudentStudyService.java @@ -17,6 +17,7 @@ import com.gdschongik.gdsc.global.exception.CustomException; import com.gdschongik.gdsc.global.util.MemberUtil; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; import lombok.RequiredArgsConstructor; @@ -106,7 +107,8 @@ public void attend(Long studyDetailId, StudyAttendCreateRequest request) { public StudentMyCurrentStudyResponse getMyCurrentStudy() { Member currentMember = memberUtil.getCurrentMember(); StudyHistory studyHistory = studyHistoryRepository.findAllByStudent(currentMember).stream() - .filter(s -> s.getStudy().isStudyOngoing()) + .filter(s -> s.getStudy().getApplicationPeriod().getStartDate().isBefore(LocalDateTime.now()) + && s.getStudy().getPeriod().getEndDate().isAfter(LocalDateTime.now())) .findFirst() .orElse(null); return StudentMyCurrentStudyResponse.from(studyHistory); From 517bf5e40d0b71aca566fd7626f60d087d83a0ed Mon Sep 17 00:00:00 2001 From: Jaehyun Ahn <91878695+uwoobeat@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:23:13 +0900 Subject: [PATCH 05/10] =?UTF-8?q?fix:=20=EB=AC=B4=EB=A3=8C=20=EC=A3=BC?= =?UTF-8?q?=EB=AC=B8=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20=EC=BF=A0=ED=8F=B0?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=20=EB=A1=9C=EC=A7=81=EC=9D=B4=20=EB=88=84?= =?UTF-8?q?=EB=9D=BD=EB=90=9C=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0=20?= =?UTF-8?q?(#698)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 무료 주문 시 쿠폰 사용 로직 추가 * test: 주문 통합 테스트에 쿠폰 사용 여부 검증 테스트 추가 --- .../order/application/OrderService.java | 1 + .../order/application/OrderServiceTest.java | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/main/java/com/gdschongik/gdsc/domain/order/application/OrderService.java b/src/main/java/com/gdschongik/gdsc/domain/order/application/OrderService.java index cfbf6dd72..1c1586bfd 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/order/application/OrderService.java +++ b/src/main/java/com/gdschongik/gdsc/domain/order/application/OrderService.java @@ -164,6 +164,7 @@ public void createFreeOrder(OrderCreateRequest request) { orderValidator.validateFreeOrderCreate(membership, issuedCoupon, currentMember); Order order = Order.createFree(request.orderNanoId(), membership, issuedCoupon.orElse(null), moneyInfo); + issuedCoupon.ifPresent(IssuedCoupon::use); orderRepository.save(order); diff --git a/src/test/java/com/gdschongik/gdsc/domain/order/application/OrderServiceTest.java b/src/test/java/com/gdschongik/gdsc/domain/order/application/OrderServiceTest.java index 5fc713ee8..1da174baf 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/order/application/OrderServiceTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/order/application/OrderServiceTest.java @@ -212,6 +212,41 @@ class 주문_완료할때 { Member regularMember = memberRepository.findById(member.getId()).orElseThrow(); assertThat(regularMember.isRegular()).isTrue(); } + + @Test + void 쿠폰_존재한다면_사용처리한다() { + // given + Member member = createMember(); + logoutAndReloginAs(1L, MemberRole.ASSOCIATE); + RecruitmentRound recruitmentRound = createRecruitmentRound( + RECRUITMENT_ROUND_NAME, + LocalDateTime.now().minusDays(1), + LocalDateTime.now().plusDays(1), + ACADEMIC_YEAR, + SEMESTER_TYPE, + ROUND_TYPE, + MONEY_20000_WON); + + Membership membership = createMembership(member, recruitmentRound); + IssuedCoupon issuedCoupon = createAndIssue(MONEY_5000_WON, member); + + orderService.createPendingOrder(new OrderCreateRequest( + ORDER_NANO_ID, + membership.getId(), + issuedCoupon.getId(), + BigDecimal.valueOf(20000), + BigDecimal.valueOf(5000), + BigDecimal.valueOf(15000))); + + // when + var request = new OrderCompleteRequest(ORDER_PAYMENT_KEY, ORDER_NANO_ID, 15000L); + orderService.completeOrder(request); + + // then + IssuedCoupon usedCoupon = + issuedCouponRepository.findById(issuedCoupon.getId()).orElseThrow(); + assertThat(usedCoupon.hasUsed()).isTrue(); + } } @Nested @@ -560,5 +595,39 @@ class 무료주문_생성할때 { Member regularMember = memberRepository.findById(member.getId()).orElseThrow(); assertThat(regularMember.isRegular()).isTrue(); } + + @Test + void 쿠폰_존재한다면_사용처리한다() { + // given + Member member = createMember(); + logoutAndReloginAs(1L, MemberRole.ASSOCIATE); + RecruitmentRound recruitmentRound = createRecruitmentRound( + RECRUITMENT_ROUND_NAME, + LocalDateTime.now().minusDays(1), + LocalDateTime.now().plusDays(1), + ACADEMIC_YEAR, + SEMESTER_TYPE, + ROUND_TYPE, + MONEY_20000_WON); + + Membership membership = createMembership(member, recruitmentRound); + IssuedCoupon issuedCoupon = createAndIssue(MONEY_20000_WON, member); + + var request = new OrderCreateRequest( + ORDER_NANO_ID, + membership.getId(), + issuedCoupon.getId(), + BigDecimal.valueOf(20000), + BigDecimal.valueOf(20000), + BigDecimal.ZERO); + + // when + orderService.createFreeOrder(request); + + // then + IssuedCoupon usedCoupon = + issuedCouponRepository.findById(issuedCoupon.getId()).orElseThrow(); + assertThat(usedCoupon.hasUsed()).isTrue(); + } } } From 2be7f40b066e129998f80cbd32dc3502e2cb6e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=ED=95=9C=EB=B9=84?= <99820610+AlmondBreez3@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:39:03 +0900 Subject: [PATCH 06/10] =?UTF-8?q?refactor:=20=EC=84=B8=EC=85=98=EC=9D=84?= =?UTF-8?q?=20=EC=BB=A4=EB=A6=AC=ED=81=98=EB=9F=BC=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#696)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 세션을 커리큘럼으로 변경 * refactor: 주석 삭제 * feat: 스터디 상태 세션에서 오프라인으로 변경 --- .../api/MentorStudyDetailController.java | 10 +++---- .../api/StudentStudyDetailController.java | 9 +++--- .../application/MentorStudyDetailService.java | 6 ++-- .../study/application/MentorStudyService.java | 29 +++++++++---------- .../StudentStudyDetailService.java | 12 +++----- .../gdsc/domain/study/domain/Study.java | 4 +-- .../gdsc/domain/study/domain/StudyDetail.java | 29 +++++++++++-------- .../study/domain/StudyDetailValidator.java | 4 +-- .../gdsc/domain/study/domain/StudyType.java | 4 +-- .../vo/{Session.java => Curriculum.java} | 14 ++++----- ...java => StudyCurriculumCreateRequest.java} | 2 +- .../study/dto/request/StudyUpdateRequest.java | 2 +- ...onse.java => StudyCurriculumResponse.java} | 16 +++++----- ...va => StudyStudentCurriculumResponse.java} | 16 +++++----- .../gdsc/global/exception/ErrorCode.java | 2 +- .../application/MentorStudyServiceTest.java | 17 +++++------ .../domain/StudyDetailValidatorTest.java | 2 +- .../global/common/constant/StudyConstant.java | 6 ++-- 18 files changed, 91 insertions(+), 93 deletions(-) rename src/main/java/com/gdschongik/gdsc/domain/study/domain/vo/{Session.java => Curriculum.java} (78%) rename src/main/java/com/gdschongik/gdsc/domain/study/dto/request/{StudySessionCreateRequest.java => StudyCurriculumCreateRequest.java} (92%) rename src/main/java/com/gdschongik/gdsc/domain/study/dto/response/{StudySessionResponse.java => StudyCurriculumResponse.java} (53%) rename src/main/java/com/gdschongik/gdsc/domain/study/dto/response/{StudyStudentSessionResponse.java => StudyStudentCurriculumResponse.java} (81%) diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyDetailController.java b/src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyDetailController.java index 9a961a4e7..a2c5dfafd 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyDetailController.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/api/MentorStudyDetailController.java @@ -3,8 +3,8 @@ import com.gdschongik.gdsc.domain.study.application.MentorStudyDetailService; import com.gdschongik.gdsc.domain.study.dto.request.AssignmentCreateUpdateRequest; import com.gdschongik.gdsc.domain.study.dto.response.AssignmentResponse; +import com.gdschongik.gdsc.domain.study.dto.response.StudyCurriculumResponse; import com.gdschongik.gdsc.domain.study.dto.response.StudyMentorAttendanceResponse; -import com.gdschongik.gdsc.domain.study.dto.response.StudySessionResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; @@ -65,11 +65,11 @@ public ResponseEntity cancelStudyAssignment(@PathVariable Long studyDetail return ResponseEntity.noContent().build(); } - // TODO 스터디 세션 워딩을 커리큘럼으로 변경해야함 @Operation(summary = "스터디 주차별 커리큘럼 목록 조회", description = "멘토가 자신의 스터디 커리큘럼 목록을 조회합니다") - @GetMapping("/sessions") - public ResponseEntity> getStudySessions(@RequestParam(name = "studyId") Long studyId) { - List response = mentorStudyDetailService.getSessions(studyId); + @GetMapping("/curriculums") + public ResponseEntity> getStudyCurriculums( + @RequestParam(name = "studyId") Long studyId) { + List response = mentorStudyDetailService.getCurriculums(studyId); return ResponseEntity.ok(response); } 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 ccc11013c..579ba7717 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 @@ -3,7 +3,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.StudyStudentCurriculumResponse; import com.gdschongik.gdsc.domain.study.dto.response.StudyTodoResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -38,12 +38,11 @@ public ResponseEntity> getStudyTodoList(@RequestParam(na return ResponseEntity.ok(response); } - // TODO 스터디 세션 워딩을 커리큘럼으로 변경해야함 @Operation(summary = "스터디 커리큘럼 조회", description = "해당 스터디의 커리큘럼들을 조회합니다.") - @GetMapping("/sessions") - public ResponseEntity> getStudySessions( + @GetMapping("/curriculums") + public ResponseEntity> getStudyCurriculums( @RequestParam(name = "studyId") Long studyId) { - List response = studentStudyDetailService.getStudySessions(studyId); + List response = studentStudyDetailService.getStudyCurriculums(studyId); return ResponseEntity.ok(response); } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyDetailService.java b/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyDetailService.java index 629608cb3..bb34eb745 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyDetailService.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyDetailService.java @@ -8,8 +8,8 @@ import com.gdschongik.gdsc.domain.study.domain.StudyDetailValidator; import com.gdschongik.gdsc.domain.study.dto.request.AssignmentCreateUpdateRequest; import com.gdschongik.gdsc.domain.study.dto.response.AssignmentResponse; +import com.gdschongik.gdsc.domain.study.dto.response.StudyCurriculumResponse; import com.gdschongik.gdsc.domain.study.dto.response.StudyMentorAttendanceResponse; -import com.gdschongik.gdsc.domain.study.dto.response.StudySessionResponse; import com.gdschongik.gdsc.global.exception.CustomException; import com.gdschongik.gdsc.global.util.MemberUtil; import java.time.LocalDate; @@ -88,9 +88,9 @@ public void updateStudyAssignment(Long studyDetailId, AssignmentCreateUpdateRequ } @Transactional(readOnly = true) - public List getSessions(Long studyId) { + public List getCurriculums(Long studyId) { List studyDetails = studyDetailRepository.findAllByStudyIdOrderByWeekAsc(studyId); - return studyDetails.stream().map(StudySessionResponse::from).toList(); + return studyDetails.stream().map(StudyCurriculumResponse::from).toList(); } @Transactional(readOnly = true) diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyService.java b/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyService.java index e4204e2b4..31bcd0aaf 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyService.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/application/MentorStudyService.java @@ -13,7 +13,7 @@ import com.gdschongik.gdsc.domain.study.domain.StudyHistory; import com.gdschongik.gdsc.domain.study.domain.StudyValidator; import com.gdschongik.gdsc.domain.study.dto.request.StudyAnnouncementCreateUpdateRequest; -import com.gdschongik.gdsc.domain.study.dto.request.StudySessionCreateRequest; +import com.gdschongik.gdsc.domain.study.dto.request.StudyCurriculumCreateRequest; import com.gdschongik.gdsc.domain.study.dto.request.StudyUpdateRequest; import com.gdschongik.gdsc.domain.study.dto.response.MentorStudyResponse; import com.gdschongik.gdsc.domain.study.dto.response.StudyStudentResponse; @@ -101,7 +101,6 @@ public void deleteStudyAnnouncement(Long studyAnnouncementId) { log.info("[MentorStudyService] 스터디 공지 삭제 완료: studyAnnouncementId={}", studyAnnouncement.getId()); } - // TODO session -> curriculum 변경 @Transactional public void updateStudy(Long studyId, StudyUpdateRequest request) { Member currentMember = memberUtil.getCurrentMember(); @@ -112,9 +111,9 @@ public void updateStudy(Long studyId, StudyUpdateRequest request) { // StudyDetail ID를 추출하여 Set으로 저장 Set studyDetailIds = studyDetails.stream().map(StudyDetail::getId).collect(Collectors.toSet()); - // 요청된 StudySessionCreateRequest의 StudyDetail ID를 추출하여 Set으로 저장 - Set requestIds = request.studySessions().stream() - .map(StudySessionCreateRequest::studyDetailId) + // 요청된 StudyCurriculumCreateRequest의 StudyDetail ID를 추출하여 Set으로 저장 + Set requestIds = request.studyCurriculums().stream() + .map(StudyCurriculumCreateRequest::studyDetailId) .collect(Collectors.toSet()); studyDetailValidator.validateUpdateStudyDetail(studyDetailIds, requestIds); @@ -123,24 +122,24 @@ public void updateStudy(Long studyId, StudyUpdateRequest request) { studyRepository.save(study); log.info("[MentorStudyService] 스터디 기본 정보 수정 완료: studyId={}", studyId); - updateAllStudyDetailSession(studyDetails, request.studySessions()); + updateAllStudyDetailCurriculum(studyDetails, request.studyCurriculums()); } - private void updateAllStudyDetailSession( - List studyDetails, List studySessions) { + private void updateAllStudyDetailCurriculum( + List studyDetails, List studyCurriculums) { for (StudyDetail studyDetail : studyDetails) { Long id = studyDetail.getId(); - StudySessionCreateRequest matchingSession = studySessions.stream() - .filter(session -> session.studyDetailId().equals(id)) + StudyCurriculumCreateRequest matchingCurriculum = studyCurriculums.stream() + .filter(curriculum -> curriculum.studyDetailId().equals(id)) .findFirst() .get(); - studyDetail.updateSession( + studyDetail.updateCurriculum( studyDetail.getStudy().getStartTime(), - matchingSession.title(), - matchingSession.description(), - matchingSession.difficulty(), - matchingSession.status()); + matchingCurriculum.title(), + matchingCurriculum.description(), + matchingCurriculum.difficulty(), + matchingCurriculum.status()); } studyDetailRepository.saveAll(studyDetails); log.info("[MentorStudyService] 스터디 상세정보 커리큘럼 작성 완료: studyDetailId={}", studyDetails); 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 046a1204d..65050b595 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 @@ -9,11 +9,7 @@ import com.gdschongik.gdsc.domain.study.domain.Attendance; 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; +import com.gdschongik.gdsc.domain.study.dto.response.*; import com.gdschongik.gdsc.global.exception.CustomException; import com.gdschongik.gdsc.global.exception.ErrorCode; import com.gdschongik.gdsc.global.util.MemberUtil; @@ -69,7 +65,7 @@ public List getStudyTodoList(Long studyId) { List response = new ArrayList<>(); // 출석체크 정보 (개설 상태이고, 오늘이 출석체크날짜인 것) studyDetails.stream() - .filter(studyDetail -> studyDetail.getSession().isOpen() + .filter(studyDetail -> studyDetail.getCurriculum().isOpen() && studyDetail.getAttendanceDay().equals(now)) .forEach(studyDetail -> response.add(StudyTodoResponse.createAttendanceType( studyDetail, now, isAttended(attendances, studyDetail)))); @@ -83,7 +79,7 @@ public List getStudyTodoList(Long studyId) { return response; } - public List getStudySessions(Long studyId) { + public List getStudyCurriculums(Long studyId) { Member member = memberUtil.getCurrentMember(); final List studyDetails = studyDetailRepository.findAllByStudyIdOrderByWeekAsc(studyId); final List assignmentHistories = @@ -91,7 +87,7 @@ public List getStudySessions(Long studyId) { final List attendances = attendanceRepository.findByMemberAndStudyId(member, studyId); return studyDetails.stream() - .map(studyDetail -> StudyStudentSessionResponse.of( + .map(studyDetail -> StudyStudentCurriculumResponse.of( studyDetail, getSubmittedAssignment(assignmentHistories, studyDetail), isAttended(attendances, studyDetail), diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/domain/Study.java b/src/main/java/com/gdschongik/gdsc/domain/study/domain/Study.java index 6fe8152b3..0e3cf1185 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/domain/Study.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/domain/Study.java @@ -114,7 +114,7 @@ public static Study createStudy( DayOfWeek dayOfWeek, LocalTime startTime, LocalTime endTime) { - validateApplicationStartDateBeforeSessionStartDate(applicationPeriod.getStartDate(), period.getStartDate()); + validateApplicationStartDateBeforeCurriculumStartDate(applicationPeriod.getStartDate(), period.getStartDate()); validateMentorRole(mentor); validateStudyTime(studyType, startTime, endTime); return Study.builder() @@ -134,7 +134,7 @@ public static Study createStudy( // 검증 로직 - private static void validateApplicationStartDateBeforeSessionStartDate( + private static void validateApplicationStartDateBeforeCurriculumStartDate( LocalDateTime applicationStartDate, LocalDateTime startDate) { if (!applicationStartDate.isBefore(startDate)) { throw new CustomException(STUDY_APPLICATION_START_DATE_INVALID); 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 c2b0c4cc5..c33a59d08 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 @@ -5,7 +5,7 @@ import com.gdschongik.gdsc.domain.common.model.BaseEntity; import com.gdschongik.gdsc.domain.recruitment.domain.vo.Period; import com.gdschongik.gdsc.domain.study.domain.vo.Assignment; -import com.gdschongik.gdsc.domain.study.domain.vo.Session; +import com.gdschongik.gdsc.domain.study.domain.vo.Curriculum; import com.gdschongik.gdsc.global.exception.CustomException; import jakarta.persistence.*; import java.time.DayOfWeek; @@ -41,12 +41,12 @@ public class StudyDetail extends BaseEntity { private Period period; @Embedded - @AttributeOverride(name = "title", column = @Column(name = "session_title")) - @AttributeOverride(name = "difficulty", column = @Column(name = "session_difficulty")) - @AttributeOverride(name = "startAt", column = @Column(name = "session_start_at")) - @AttributeOverride(name = "description", column = @Column(name = "session_description")) - @AttributeOverride(name = "status", column = @Column(name = "session_status")) - private Session session; + @AttributeOverride(name = "title", column = @Column(name = "curriculum_title")) + @AttributeOverride(name = "difficulty", column = @Column(name = "curriculum_difficulty")) + @AttributeOverride(name = "startAt", column = @Column(name = "curriculum_start_at")) + @AttributeOverride(name = "description", column = @Column(name = "curriculum_description")) + @AttributeOverride(name = "status", column = @Column(name = "curriculum_status")) + private Curriculum curriculum; @Embedded @AttributeOverride(name = "title", column = @Column(name = "assignment_title")) @@ -57,12 +57,17 @@ public class StudyDetail extends BaseEntity { @Builder(access = AccessLevel.PRIVATE) private StudyDetail( - Study study, Long week, String attendanceNumber, Period period, Session session, Assignment assignment) { + Study study, + Long week, + String attendanceNumber, + Period period, + Curriculum curriculum, + Assignment assignment) { this.study = study; this.week = week; this.attendanceNumber = attendanceNumber; this.period = period; - this.session = session; + this.curriculum = curriculum; this.assignment = assignment; } @@ -73,7 +78,7 @@ public static StudyDetail createStudyDetail(Study study, Long week, String atten .period(period) .attendanceNumber(attendanceNumber) .period(period) - .session(Session.createEmptySession()) + .curriculum(Curriculum.createEmptyCurriculum()) .assignment(Assignment.createEmptyAssignment()) .build(); } @@ -128,9 +133,9 @@ public boolean isAttendanceDayNotPassed(LocalDate now) { return !getAttendanceDay().isBefore(now); } - public void updateSession( + public void updateCurriculum( LocalTime startAt, String title, String description, Difficulty difficulty, StudyStatus status) { - session = Session.generateSession(startAt, title, description, difficulty, status); + curriculum = Curriculum.generateCurriculum(startAt, title, description, difficulty, status); } public void validateAssignmentSubmittable(LocalDateTime now) { diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyDetailValidator.java b/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyDetailValidator.java index 161a1383f..91341292d 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyDetailValidator.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyDetailValidator.java @@ -57,9 +57,9 @@ private void validateUpdateDeadline( } public void validateUpdateStudyDetail(Set studyDetails, Set requests) { - // StudyDetail 목록과 요청된 StudySessionCreateRequest 목록의 크기를 먼저 비교 + // StudyDetail 목록과 요청된 StudyCurriculumCreateRequest 목록의 크기를 먼저 비교 if (studyDetails.size() != requests.size()) { - throw new CustomException(STUDY_DETAIL_SESSION_SIZE_MISMATCH); + throw new CustomException(STUDY_DETAIL_CURRICULUM_SIZE_MISMATCH); } // 두 ID 집합이 동일한지 비교하여 ID 불일치 시 예외를 던짐 diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyType.java b/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyType.java index 52cd23877..093c0f7cb 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyType.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/domain/StudyType.java @@ -7,8 +7,8 @@ @AllArgsConstructor public enum StudyType { ASSIGNMENT("과제 스터디"), - ONLINE("온라인 세션"), - OFFLINE("오프라인 세션"); + ONLINE("온라인 커리큘럼"), + OFFLINE("오프라인 커리큘럼"); private final String value; } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/domain/vo/Session.java b/src/main/java/com/gdschongik/gdsc/domain/study/domain/vo/Curriculum.java similarity index 78% rename from src/main/java/com/gdschongik/gdsc/domain/study/domain/vo/Session.java rename to src/main/java/com/gdschongik/gdsc/domain/study/domain/vo/Curriculum.java index 07a2282c0..7f299e45c 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/domain/vo/Session.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/domain/vo/Curriculum.java @@ -17,7 +17,7 @@ @Embeddable @EqualsAndHashCode @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Session { +public class Curriculum { private LocalTime startAt; @@ -28,12 +28,12 @@ public class Session { @Enumerated(EnumType.STRING) private Difficulty difficulty; - @Comment("세션 상태") + @Comment("커리큘럼 상태") @Enumerated(EnumType.STRING) private StudyStatus status; @Builder(access = AccessLevel.PRIVATE) - private Session(LocalTime startAt, String title, String description, Difficulty difficulty, StudyStatus status) { + private Curriculum(LocalTime startAt, String title, String description, Difficulty difficulty, StudyStatus status) { this.startAt = startAt; this.title = title; this.description = description; @@ -41,13 +41,13 @@ private Session(LocalTime startAt, String title, String description, Difficulty this.status = status; } - public static Session createEmptySession() { - return Session.builder().status(StudyStatus.NONE).build(); + public static Curriculum createEmptyCurriculum() { + return Curriculum.builder().status(StudyStatus.NONE).build(); } - public static Session generateSession( + public static Curriculum generateCurriculum( LocalTime startAt, String title, String description, Difficulty difficulty, StudyStatus status) { - return Session.builder() + return Curriculum.builder() .startAt(startAt) .title(title) .description(description) diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudySessionCreateRequest.java b/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudyCurriculumCreateRequest.java similarity index 92% rename from src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudySessionCreateRequest.java rename to src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudyCurriculumCreateRequest.java index fd511dcd0..be075a91a 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudySessionCreateRequest.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudyCurriculumCreateRequest.java @@ -5,7 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; -public record StudySessionCreateRequest( +public record StudyCurriculumCreateRequest( @NotNull Long studyDetailId, @Schema(description = "제목") String title, @Schema(description = "설명") String description, diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudyUpdateRequest.java b/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudyUpdateRequest.java index 326c05831..6b106f026 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudyUpdateRequest.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudyUpdateRequest.java @@ -6,4 +6,4 @@ public record StudyUpdateRequest( @Schema(description = "스터디 소개 페이지 링크") String notionLink, @Schema(description = "스터디 한 줄 소개") String introduction, - List studySessions) {} + List studyCurriculums) {} diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudySessionResponse.java b/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyCurriculumResponse.java similarity index 53% rename from src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudySessionResponse.java rename to src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyCurriculumResponse.java index 874b6cfb5..6771a2017 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudySessionResponse.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyCurriculumResponse.java @@ -3,19 +3,19 @@ import com.gdschongik.gdsc.domain.recruitment.domain.vo.Period; import com.gdschongik.gdsc.domain.study.domain.Difficulty; import com.gdschongik.gdsc.domain.study.domain.StudyDetail; -import com.gdschongik.gdsc.domain.study.domain.vo.Session; +import com.gdschongik.gdsc.domain.study.domain.vo.Curriculum; -public record StudySessionResponse( +public record StudyCurriculumResponse( Long studyDetailId, Period period, Long week, String title, String description, Difficulty difficulty) { - public static StudySessionResponse from(StudyDetail studyDetail) { - Session session = studyDetail.getSession(); - return new StudySessionResponse( + public static StudyCurriculumResponse from(StudyDetail studyDetail) { + Curriculum curriculum = studyDetail.getCurriculum(); + return new StudyCurriculumResponse( studyDetail.getId(), studyDetail.getPeriod(), studyDetail.getWeek(), - session.getTitle(), - session.getDescription(), - session.getDifficulty()); + curriculum.getTitle(), + curriculum.getDescription(), + curriculum.getDifficulty()); } } diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyStudentSessionResponse.java b/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyStudentCurriculumResponse.java similarity index 81% rename from src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyStudentSessionResponse.java rename to src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyStudentCurriculumResponse.java index b903bd230..d2c1aaa4a 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyStudentSessionResponse.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dto/response/StudyStudentCurriculumResponse.java @@ -11,13 +11,13 @@ import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; -public record StudyStudentSessionResponse( +public record StudyStudentCurriculumResponse( Long studyDetailId, @Schema(description = "기간") Period period, @Schema(description = "주차수") Long week, @Schema(description = "제목") String title, @Schema(description = "설명") String description, - @Schema(description = "세션 상태") StudyStatus sessionStatus, + @Schema(description = "커리큘럼 상태") StudyStatus curriculumStatus, @Schema(description = "난이도") Difficulty difficulty, @Schema(description = "출석 상태") AttendanceStatusResponse attendanceStatus, @Schema(description = "과제 개설 상태") StudyStatus assignmentStatus, @@ -25,16 +25,16 @@ public record StudyStudentSessionResponse( @Schema(description = "과제 실패 타입") SubmissionFailureType submissionFailureType, @Schema(description = "과제 제출 링크") String submissionLink) { - public static StudyStudentSessionResponse of( + public static StudyStudentCurriculumResponse of( StudyDetail studyDetail, AssignmentHistory assignmentHistory, boolean isAttended, LocalDateTime now) { - return new StudyStudentSessionResponse( + return new StudyStudentCurriculumResponse( studyDetail.getId(), studyDetail.getPeriod(), studyDetail.getWeek(), - studyDetail.getSession().getTitle(), - studyDetail.getSession().getDescription(), - studyDetail.getSession().getStatus(), - studyDetail.getSession().getDifficulty(), + studyDetail.getCurriculum().getTitle(), + studyDetail.getCurriculum().getDescription(), + studyDetail.getCurriculum().getStatus(), + studyDetail.getCurriculum().getDifficulty(), AttendanceStatusResponse.of(studyDetail, now.toLocalDate(), isAttended), studyDetail.getAssignment().getStatus(), AssignmentSubmissionStatusResponse.from(assignmentHistory), 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 2220ddc33..bec818fe9 100644 --- a/src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java +++ b/src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java @@ -115,7 +115,7 @@ public enum ErrorCode { STUDY_DETAIL_ASSIGNMENT_INVALID_DEADLINE(HttpStatus.CONFLICT, "마감기한이 지난 과제의 마감기한을 수정할 수 없습니다"), STUDY_DETAIL_ASSIGNMENT_INVALID_UPDATE_DEADLINE(HttpStatus.CONFLICT, "수정하려고 하는 과제의 마감기한은 기존의 마감기한보다 빠르면 안됩니다."), STUDY_DETAIL_ID_INVALID(HttpStatus.CONFLICT, "수정하려는 스터디 상세정보가 서버에 존재하지 않거나 유효하지 않습니다."), - STUDY_DETAIL_SESSION_SIZE_MISMATCH(HttpStatus.BAD_REQUEST, "스터디 커리큘럼의 총 개수가 일치하지 않습니다."), + STUDY_DETAIL_CURRICULUM_SIZE_MISMATCH(HttpStatus.BAD_REQUEST, "스터디 커리큘럼의 총 개수가 일치하지 않습니다."), // StudyHistory STUDY_HISTORY_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 스터디 수강 기록입니다."), STUDY_HISTORY_DUPLICATE(HttpStatus.CONFLICT, "이미 해당 스터디를 신청했습니다."), diff --git a/src/test/java/com/gdschongik/gdsc/domain/study/application/MentorStudyServiceTest.java b/src/test/java/com/gdschongik/gdsc/domain/study/application/MentorStudyServiceTest.java index 7b4707f6d..6e188a09a 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/study/application/MentorStudyServiceTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/study/application/MentorStudyServiceTest.java @@ -1,7 +1,6 @@ package com.gdschongik.gdsc.domain.study.application; import static com.gdschongik.gdsc.global.common.constant.StudyConstant.*; -import static com.gdschongik.gdsc.global.common.constant.StudyConstant.SESSION_DESCRIPTION; import static org.assertj.core.api.Assertions.assertThat; import com.gdschongik.gdsc.domain.member.domain.Member; @@ -11,7 +10,7 @@ import com.gdschongik.gdsc.domain.study.domain.Study; import com.gdschongik.gdsc.domain.study.domain.StudyDetail; import com.gdschongik.gdsc.domain.study.domain.StudyStatus; -import com.gdschongik.gdsc.domain.study.dto.request.StudySessionCreateRequest; +import com.gdschongik.gdsc.domain.study.dto.request.StudyCurriculumCreateRequest; import com.gdschongik.gdsc.domain.study.dto.request.StudyUpdateRequest; import com.gdschongik.gdsc.helper.IntegrationTest; import java.time.LocalDateTime; @@ -44,16 +43,16 @@ class 스터디_정보_작성시 { } logoutAndReloginAs(study.getMentor().getId(), MemberRole.ASSOCIATE); - List sessionCreateRequests = new ArrayList<>(); + List curriculumCreateRequests = new ArrayList<>(); for (int i = 1; i <= study.getTotalWeek(); i++) { Long id = (long) i; - StudySessionCreateRequest sessionCreateRequest = new StudySessionCreateRequest( - id, SESSION_TITLE + i, SESSION_DESCRIPTION + i, Difficulty.HIGH, StudyStatus.OPEN); - sessionCreateRequests.add(sessionCreateRequest); + StudyCurriculumCreateRequest curriculumCreateRequest = new StudyCurriculumCreateRequest( + id, CURRICULUM_TITLE + i, CURRICULUM_DESCRIPTION + i, Difficulty.HIGH, StudyStatus.OPEN); + curriculumCreateRequests.add(curriculumCreateRequest); } StudyUpdateRequest request = - new StudyUpdateRequest(STUDY_NOTION_LINK, STUDY_INTRODUCTION, sessionCreateRequests); + new StudyUpdateRequest(STUDY_NOTION_LINK, STUDY_INTRODUCTION, curriculumCreateRequests); // when mentorStudyService.updateStudy(1L, request); @@ -68,8 +67,8 @@ class 스터디_정보_작성시 { Long expectedId = studyDetail.getId(); assertThat(studyDetail.getId()).isEqualTo(expectedId); - assertThat(studyDetail.getSession().getTitle()).isEqualTo(SESSION_TITLE + expectedId); - assertThat(studyDetail.getSession().getDescription()).isEqualTo(SESSION_DESCRIPTION + expectedId); + assertThat(studyDetail.getCurriculum().getTitle()).isEqualTo(CURRICULUM_TITLE + expectedId); + assertThat(studyDetail.getCurriculum().getDescription()).isEqualTo(CURRICULUM_DESCRIPTION + expectedId); } } } diff --git a/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyDetailValidatorTest.java b/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyDetailValidatorTest.java index e0e8789f6..2b7e3285f 100644 --- a/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyDetailValidatorTest.java +++ b/src/test/java/com/gdschongik/gdsc/domain/study/domain/StudyDetailValidatorTest.java @@ -174,7 +174,7 @@ class 스터디_상세정보_작성시 { // when & then assertThatThrownBy(() -> studyDetailValidator.validateUpdateStudyDetail(studyDetailIds, requestIds)) .isInstanceOf(CustomException.class) - .hasMessage(STUDY_DETAIL_SESSION_SIZE_MISMATCH.getMessage()); + .hasMessage(STUDY_DETAIL_CURRICULUM_SIZE_MISMATCH.getMessage()); } @Test 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 19714d487..05f8852db 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 @@ -34,9 +34,9 @@ private StudyConstant() {} public static final LocalDateTime STUDY_DETAIL_END_DATETIME = STUDY_DETAIL_START_DATETIME.plusWeeks(1); public static final LocalDateTime STUDY_ASSIGNMENT_DEADLINE_DATETIME = STUDY_DETAIL_END_DATETIME; - // Session - public static final String SESSION_TITLE = "sessionTitle"; - public static final String SESSION_DESCRIPTION = "sessionDescription"; + // Curriculum + public static final String CURRICULUM_TITLE = "curriculumTitle"; + public static final String CURRICULUM_DESCRIPTION = "curriculumDescription"; // AssignmentHistory public static final String SUBMISSION_LINK = "https://github.com/ownername/reponame/blob/main/week1/WIL.md"; From 12519a9f0a7d5c3767b1f9a0d1b809a37cf03bdc Mon Sep 17 00:00:00 2001 From: Cho Sangwook <82208159+Sangwook02@users.noreply.github.com> Date: Wed, 28 Aug 2024 01:26:01 +0900 Subject: [PATCH 07/10] =?UTF-8?q?feat:=20=EC=8A=A4=ED=84=B0=EB=94=94=20?= =?UTF-8?q?=EC=8B=9C=EC=9E=91=20=EC=8B=9C=EA=B0=84=20=EB=B0=8F=20=EC=A2=85?= =?UTF-8?q?=EB=A3=8C=20=EC=8B=9C=EA=B0=84=EC=9D=98=20NotNull=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EC=A0=9C=EA=B1=B0=20(#700)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: 스터디 시작 시간 및 종료 시간의 not null 검증 제거 --- .../gdsc/domain/study/dto/request/StudyCreateRequest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudyCreateRequest.java b/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudyCreateRequest.java index a6e859f48..01ec60833 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudyCreateRequest.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/dto/request/StudyCreateRequest.java @@ -27,6 +27,6 @@ public record StudyCreateRequest( @Future @NotNull(message = "스터디 시작일은 null이 될 수 없습니다.") @Schema(description = "스터디 시작일", pattern = DATE) LocalDate startDate, @NotNull(message = "스터디 요일은 null이 될 수 없습니다.") @Schema(description = "스터디 요일") DayOfWeek dayOfWeek, - @NotNull @Schema(description = "스터디 시작 시간") LocalTime studyStartTime, - @NotNull @Schema(description = "스터디 종료 시간") LocalTime studyEndTime, + @Schema(description = "스터디 시작 시간") LocalTime studyStartTime, + @Schema(description = "스터디 종료 시간") LocalTime studyEndTime, @NotNull(message = "스터디 타입은 null이 될 수 없습니다.") @Schema(description = "스터디 타입") StudyType studyType) {} From 8b779f8a3e0b7669ddef778c8e8adbbb6f49a541 Mon Sep 17 00:00:00 2001 From: Cho Sangwook <82208159+Sangwook02@users.noreply.github.com> Date: Wed, 28 Aug 2024 21:50:49 +0900 Subject: [PATCH 08/10] =?UTF-8?q?hotfix:=20=EB=94=94=EC=8A=A4=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20ID=20=EB=B0=B0=EC=B9=98=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20(#706)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * hotfix: 이메일 정규식에 언더스코어를 허용하도록 수정 (#205) * fix: 언더스코어 허용하도록 변경 * refactor: 테스트 접근제어자 제거 * hotfix: Basic Auth 환경변수 속성 이름 수정 (#260) * fix: 환경변수 속성 이름 오타 수정 * refactor: Basic Auth 환경변수 이름 재수정 * hotfix: 학과 쿼리 메서드 수정 (#282) * hotfix: spotless 적용 (#283) style: spotless 적용 * hotfix: 소셜 로그인 리다이렉트 URI가 작동하지 않는 문제 수정 (#689) fix: 추가 파라미터에서 리다이렉트 URI로 수정 * fix: 디스코드 id 배치 예외 처리 * fix: 로그 수정 --------- Co-authored-by: Jaehyun Ahn <91878695+uwoobeat@users.noreply.github.com> Co-authored-by: 이한비 <99820610+AlmondBreez3@users.noreply.github.com> --- .../discord/application/CommonDiscordService.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/gdschongik/gdsc/domain/discord/application/CommonDiscordService.java b/src/main/java/com/gdschongik/gdsc/domain/discord/application/CommonDiscordService.java index da1e1e62c..4175930d0 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/discord/application/CommonDiscordService.java +++ b/src/main/java/com/gdschongik/gdsc/domain/discord/application/CommonDiscordService.java @@ -10,9 +10,11 @@ import com.gdschongik.gdsc.global.util.DiscordUtil; 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 CommonDiscordService { @@ -40,8 +42,12 @@ public void batchDiscordId(String currentDiscordUsername, RequirementStatus disc discordSatisfiedMembers.forEach(member -> { String discordUsername = member.getDiscordUsername(); - String discordId = discordUtil.getMemberIdByUsername(discordUsername); - member.updateDiscordId(discordId); + try { + String discordId = discordUtil.getMemberIdByUsername(discordUsername); + member.updateDiscordId(discordId); + } catch (CustomException e) { + log.info("[CommonDiscordService] 디스코드 id 배치 실패: 사유 = {} memberId = {}", e.getMessage(), member.getId()); + } }); } } From 9723ee08deca1aecf9376feabd94373663c847a4 Mon Sep 17 00:00:00 2001 From: Jaehyun Ahn <91878695+uwoobeat@users.noreply.github.com> Date: Thu, 29 Aug 2024 12:19:24 +0900 Subject: [PATCH 09/10] =?UTF-8?q?chore:=20Sentry=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=88=ED=84=B0=EB=A7=81=20=EC=A0=81=EC=9A=A9=20(#7?= =?UTF-8?q?07)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: sentry 플러그인 추가 * chore: Sentry 프로파일 추가 * chore: 도커 이미지 태그를 환경변수로 받아서 매핑 * chore: 도커 이미지 태그를 센트리 포맷에 맞춰서 바인딩 * style: spotless 적용 * chore: 로그백 센트리 디펜던시 추가 * chore: 사용자 정보 로깅 추가 * feat: 메서드 이름 변경 및 출력문 제거 --- build.gradle | 4 ++ docker-compose.yml | 1 + .../gdsc/global/config/PropertyConfig.java | 4 +- .../gdsc/global/config/SentryConfig.java | 38 +++++++++++++++++++ .../gdsc/global/property/DockerProperty.java | 12 ++++++ src/main/resources/application-sentry.yml | 17 +++++++++ src/main/resources/application.yml | 1 + 7 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/gdschongik/gdsc/global/config/SentryConfig.java create mode 100644 src/main/java/com/gdschongik/gdsc/global/property/DockerProperty.java create mode 100644 src/main/resources/application-sentry.yml diff --git a/build.gradle b/build.gradle index c09ffb85b..a96886c68 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,7 @@ plugins { id 'io.spring.dependency-management' version '1.1.4' id 'org.asciidoctor.jvm.convert' version '3.3.2' id 'com.diffplug.spotless' version '6.23.3' + id "io.sentry.jvm.gradle" version "4.11.0" } group = 'com.gdschongik' @@ -95,6 +96,9 @@ dependencies { // Github implementation 'org.kohsuke:github-api:1.323' + + // Sentry + implementation 'io.sentry:sentry-logback:7.14.0' } tasks.named('test') { diff --git a/docker-compose.yml b/docker-compose.yml index 9e0cac286..5357ae6e2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,7 @@ services: - .env environment: - TZ=Asia/Seoul + - DOCKER_IMAGE_TAG=${IMAGE_FULL_URL} redis: image: "redis:alpine" container_name: redis diff --git a/src/main/java/com/gdschongik/gdsc/global/config/PropertyConfig.java b/src/main/java/com/gdschongik/gdsc/global/config/PropertyConfig.java index e27273d6b..64778c36d 100644 --- a/src/main/java/com/gdschongik/gdsc/global/config/PropertyConfig.java +++ b/src/main/java/com/gdschongik/gdsc/global/config/PropertyConfig.java @@ -2,6 +2,7 @@ import com.gdschongik.gdsc.global.property.BasicAuthProperty; import com.gdschongik.gdsc.global.property.DiscordProperty; +import com.gdschongik.gdsc.global.property.DockerProperty; import com.gdschongik.gdsc.global.property.EmailProperty; import com.gdschongik.gdsc.global.property.GithubProperty; import com.gdschongik.gdsc.global.property.JwtProperty; @@ -17,7 +18,8 @@ DiscordProperty.class, EmailProperty.class, PaymentProperty.class, - GithubProperty.class + GithubProperty.class, + DockerProperty.class }) @Configuration public class PropertyConfig {} diff --git a/src/main/java/com/gdschongik/gdsc/global/config/SentryConfig.java b/src/main/java/com/gdschongik/gdsc/global/config/SentryConfig.java new file mode 100644 index 000000000..7860fe1d7 --- /dev/null +++ b/src/main/java/com/gdschongik/gdsc/global/config/SentryConfig.java @@ -0,0 +1,38 @@ +package com.gdschongik.gdsc.global.config; + +import com.gdschongik.gdsc.global.property.DockerProperty; +import io.sentry.Sentry; +import io.sentry.SentryOptions; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@RequiredArgsConstructor +public class SentryConfig { + + private final DockerProperty dockerProperty; + + @Bean + Sentry.OptionsConfiguration customOptionsConfiguration() { + return options -> { + options.setRelease(convertTagToRelease(dockerProperty.getTag())); + }; + } + + // gdscrepo/gdsc-server:v1.0.0 -> gdsc-server@1.0.0 + // gdscrepo/gdsc-server:ffffff -> gdsc-server@ffffff + private String convertTagToRelease(String tag) { + if (tag.isBlank()) { + return "gdsc-server"; + } + + String imageWithVersion = tag.split("/")[1]; // gdsc-server:v1.0.0 + String[] split = imageWithVersion.split(":"); // [gdsc-server, v1.0.0] + String version = split[1]; // v1.0.0 or ffffff (commit hash) + if (version.startsWith("v")) { + version = version.substring(1); // 1.0.0 + } + return split[0] + "@" + version; // gdsc-server@1.0.0 + } +} diff --git a/src/main/java/com/gdschongik/gdsc/global/property/DockerProperty.java b/src/main/java/com/gdschongik/gdsc/global/property/DockerProperty.java new file mode 100644 index 000000000..d0ddbdf82 --- /dev/null +++ b/src/main/java/com/gdschongik/gdsc/global/property/DockerProperty.java @@ -0,0 +1,12 @@ +package com.gdschongik.gdsc.global.property; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Getter +@RequiredArgsConstructor +@ConfigurationProperties(prefix = "docker") +public class DockerProperty { + private final String tag; +} diff --git a/src/main/resources/application-sentry.yml b/src/main/resources/application-sentry.yml new file mode 100644 index 000000000..c25bb6390 --- /dev/null +++ b/src/main/resources/application-sentry.yml @@ -0,0 +1,17 @@ +spring: + config: + activate: + on-profile: "sentry" + +sentry: + dsn: ${SENTRY_DSN:} + traces-sample-rate: 1.0 + exception-resolver-order: -2147483647 + environment: ${spring.profiles.active:local} + send-default-pii: true + logging: + minimum-event-level: info + minimum-breadcrumb-level: debug + +docker: + tag: ${DOCKER_IMAGE_TAG:} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1c4604ac1..445b022e4 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -13,6 +13,7 @@ spring: - email - payment - github + - sentry logging: level: From 0eb992ee9ae2a9ef985eedaeac37c373ae32cca6 Mon Sep 17 00:00:00 2001 From: Cho Sangwook <82208159+Sangwook02@users.noreply.github.com> Date: Thu, 29 Aug 2024 12:27:00 +0900 Subject: [PATCH 10/10] =?UTF-8?q?feat:=20=EB=A9=98=ED=86=A0=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EB=B6=80=EC=97=AC=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#712)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 멘토 권한 부여 로직 추가 * test: 스터디 개설시 멘토 권한 부여 테스트 추가 --- .../study/application/AdminStudyService.java | 5 +- .../application/AdminStudyServiceTest.java | 48 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/gdschongik/gdsc/domain/study/application/AdminStudyServiceTest.java diff --git a/src/main/java/com/gdschongik/gdsc/domain/study/application/AdminStudyService.java b/src/main/java/com/gdschongik/gdsc/domain/study/application/AdminStudyService.java index 91143fa72..577011ca8 100644 --- a/src/main/java/com/gdschongik/gdsc/domain/study/application/AdminStudyService.java +++ b/src/main/java/com/gdschongik/gdsc/domain/study/application/AdminStudyService.java @@ -30,8 +30,9 @@ public class AdminStudyService { @Transactional public void createStudyAndStudyDetail(StudyCreateRequest request) { - // TODO: 멘토 권한 부여 - final Member mentor = getMemberById(request.mentorId()); + Member mentor = getMemberById(request.mentorId()); + mentor.assignToMentor(); + memberRepository.save(mentor); Study study = studyDomainFactory.createNewStudy(request, mentor); final Study savedStudy = studyRepository.save(study); diff --git a/src/test/java/com/gdschongik/gdsc/domain/study/application/AdminStudyServiceTest.java b/src/test/java/com/gdschongik/gdsc/domain/study/application/AdminStudyServiceTest.java new file mode 100644 index 000000000..c70a6b6ee --- /dev/null +++ b/src/test/java/com/gdschongik/gdsc/domain/study/application/AdminStudyServiceTest.java @@ -0,0 +1,48 @@ +package com.gdschongik.gdsc.domain.study.application; + +import static com.gdschongik.gdsc.global.common.constant.RecruitmentConstant.*; +import static com.gdschongik.gdsc.global.common.constant.StudyConstant.*; +import static org.assertj.core.api.Assertions.*; + +import com.gdschongik.gdsc.domain.member.domain.Member; +import com.gdschongik.gdsc.domain.study.dto.request.StudyCreateRequest; +import com.gdschongik.gdsc.helper.IntegrationTest; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +public class AdminStudyServiceTest extends IntegrationTest { + + @Autowired + private AdminStudyService adminStudyService; + + @Nested + class 스터디_개설시 { + + @Test + void 멘토로_지정된_멤버의_MemberStudyRole은_MENTOR이다() { + // given + Member regularMember = createRegularMember(); + StudyCreateRequest request = new StudyCreateRequest( + regularMember.getId(), + ACADEMIC_YEAR, + SEMESTER_TYPE, + STUDY_TITLE, + STUDY_START_DATETIME.minusDays(10).toLocalDate(), + STUDY_START_DATETIME.minusDays(5).toLocalDate(), + TOTAL_WEEK, + STUDY_START_DATETIME.toLocalDate(), + DAY_OF_WEEK, + STUDY_START_TIME, + STUDY_END_TIME, + ONLINE_STUDY); + + // when + adminStudyService.createStudyAndStudyDetail(request); + + // then + Member mentor = memberRepository.findById(regularMember.getId()).get(); + assertThat(mentor.isMentor()).isTrue(); + } + } +}