-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: 스터디 기본 정보와 상세 정보 작성 API #642
Changes from 20 commits
fc8157d
07c10f7
05422cc
0bbf3f1
dfcd0d1
616f2f5
b10f888
15452f7
16c9aac
22d0afc
846ffa5
6593f4e
a6fb8db
5badce8
a444b60
868f05e
37d650b
fc65781
d944516
d878603
cffe5bb
55eea81
f20ef1a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,28 @@ | ||
package com.gdschongik.gdsc.domain.study.application; | ||
|
||
import static com.gdschongik.gdsc.global.exception.ErrorCode.STUDY_NOT_FOUND; | ||
|
||
import com.gdschongik.gdsc.domain.member.domain.Member; | ||
import com.gdschongik.gdsc.domain.study.dao.StudyAnnouncementRepository; | ||
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.*; | ||
import com.gdschongik.gdsc.domain.study.domain.Study; | ||
import com.gdschongik.gdsc.domain.study.domain.StudyAnnouncement; | ||
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.StudyUpdateRequest; | ||
import com.gdschongik.gdsc.domain.study.dto.response.MentorStudyResponse; | ||
import com.gdschongik.gdsc.domain.study.dto.response.StudyStudentResponse; | ||
import com.gdschongik.gdsc.global.exception.CustomException; | ||
import com.gdschongik.gdsc.global.exception.ErrorCode; | ||
import com.gdschongik.gdsc.global.util.MemberUtil; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Service; | ||
|
@@ -30,6 +38,8 @@ public class MentorStudyService { | |
private final StudyAnnouncementRepository studyAnnouncementRepository; | ||
private final StudyHistoryRepository studyHistoryRepository; | ||
private final StudyValidator studyValidator; | ||
private final StudyDetailRepository studyDetailRepository; | ||
private final StudyDetailValidator studyDetailValidator; | ||
|
||
@Transactional(readOnly = true) | ||
public List<MentorStudyResponse> getStudiesInCharge() { | ||
|
@@ -90,4 +100,49 @@ 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(); | ||
Study study = studyRepository.findById(studyId).orElseThrow(() -> new CustomException(STUDY_NOT_FOUND)); | ||
studyValidator.validateStudyMentor(currentMember, study); | ||
|
||
List<StudyDetail> studyDetails = studyDetailRepository.findAllByStudyId(studyId); | ||
// StudyDetail ID를 추출하여 Set으로 저장 | ||
Set<Long> studyDetailIds = studyDetails.stream().map(StudyDetail::getId).collect(Collectors.toSet()); | ||
|
||
// 요청된 StudySessionCreateRequest의 StudyDetail ID를 추출하여 Set으로 저장 | ||
Set<Long> requestIds = request.studySessions().stream() | ||
.map(StudySessionCreateRequest::studyDetailId) | ||
.collect(Collectors.toSet()); | ||
|
||
studyDetailValidator.validateUpdateStudyDetail(studyDetailIds, requestIds); | ||
|
||
study.update(request.notionLink(), request.introduction()); | ||
studyRepository.save(study); | ||
log.info("[MentorStudyService] 스터디 기본 정보 수정 완료: studyId={}", studyId); | ||
|
||
updateAllStudyDetailSession(studyDetails, request.studySessions()); | ||
} | ||
|
||
private void updateAllStudyDetailSession( | ||
List<StudyDetail> studyDetails, List<StudySessionCreateRequest> studySessions) { | ||
for (StudyDetail studyDetail : studyDetails) { | ||
Long id = studyDetail.getId(); | ||
StudySessionCreateRequest matchingSession = studySessions.stream() | ||
.filter(session -> session.studyDetailId().equals(id)) | ||
.findFirst() | ||
.get(); | ||
|
||
studyDetail.updateSession( | ||
studyDetail.getStudy().getPeriod().getStartDate(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 세션 시작시간이 왜 항상 스터디 시작일이어야 하는 건가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 피그마상에서 세션 시작시간에 대해 요청을 받고 있지 않더라고요 |
||
matchingSession.title(), | ||
matchingSession.description(), | ||
matchingSession.difficulty(), | ||
matchingSession.status()); | ||
} | ||
studyDetailRepository.saveAll(studyDetails); | ||
log.info("[MentorStudyService] 스터디 상세정보 커리큘럼 작성 완료: studyDetailId={}", studyDetails); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
현재 StudySessionCreateRequest matchingSession = studySessions.stream()
.filter(session -> session.studyDetailId().equals(id))
.findFirst()
.orElseThrow(() -> new CustomException(ErrorCode.SESSION_NOT_FOUND, "세션이 존재하지 않습니다: studyDetailId=" + id)); |
||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -182,4 +182,9 @@ public boolean isStudyOngoing() { | |||||
public LocalDate getStartDate() { | ||||||
return period.getStartDate().toLocalDate(); | ||||||
} | ||||||
|
||||||
public void update(String link, String intro) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 위에 필드랑 겹쳐서 오류가 나서 intro로 만들었습니다 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그러면 this로 명시해서 넣으면 되지 않나요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아아 이전에 History쪽에서는 repository를 repo로 하신거 생각하고 이런식으로 처리를 하는건가보다~해서 intro라고 했습니다 다시 보니까 다 this로 바꿔져있군요! |
||||||
notionLink = link; | ||||||
introduction = intro; | ||||||
} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 필드 업데이트에 대한 유효성 검토 필요
public void update(String link, String intro) {
if (link == null || link.isEmpty()) {
throw new IllegalArgumentException("Notion link cannot be null or empty");
}
if (intro == null || intro.isEmpty()) {
throw new IllegalArgumentException("Introduction cannot be null or empty");
}
notionLink = link;
introduction = intro;
} |
||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.gdschongik.gdsc.domain.study.dto.request; | ||
|
||
import com.gdschongik.gdsc.domain.study.domain.Difficulty; | ||
import com.gdschongik.gdsc.domain.study.domain.StudyStatus; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import jakarta.validation.constraints.NotNull; | ||
|
||
public record StudySessionCreateRequest( | ||
@NotNull Long studyDetailId, | ||
@Schema(description = "제목") String title, | ||
@Schema(description = "설명") String description, | ||
@Schema(description = "난이도") Difficulty difficulty, | ||
@Schema(description = "휴강 여부") StudyStatus status) {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.gdschongik.gdsc.domain.study.dto.request; | ||
|
||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import java.util.List; | ||
|
||
public record StudyUpdateRequest( | ||
@Schema(description = "스터디 소개 페이지 링크") String notionLink, | ||
@Schema(description = "스터디 한 줄 소개") String introduction, | ||
List<StudySessionCreateRequest> studySessions) {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
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; | ||
import com.gdschongik.gdsc.domain.member.domain.MemberRole; | ||
import com.gdschongik.gdsc.domain.recruitment.domain.vo.Period; | ||
import com.gdschongik.gdsc.domain.study.domain.Difficulty; | ||
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.StudyUpdateRequest; | ||
import com.gdschongik.gdsc.helper.IntegrationTest; | ||
import java.time.LocalDateTime; | ||
import java.util.*; | ||
import org.junit.jupiter.api.*; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
|
||
public class MentorStudyServiceTest extends IntegrationTest { | ||
|
||
@Autowired | ||
private MentorStudyService mentorStudyService; | ||
|
||
@Nested | ||
class 스터디_정보_작성시 { | ||
|
||
@Test | ||
void 성공한다() { | ||
// given | ||
LocalDateTime now = STUDY_START_DATETIME; | ||
Member mentor = createMentor(); | ||
Study study = createNewStudy( | ||
mentor, | ||
4L, | ||
Period.createPeriod(now.plusDays(5), now.plusDays(10)), | ||
Period.createPeriod(now.minusDays(5), now)); | ||
for (int i = 1; i <= 4; i++) { | ||
Long week = (long) i; | ||
createNewStudyDetail(week, study, now, now.plusDays(7)); | ||
now = now.plusDays(8); | ||
} | ||
logoutAndReloginAs(study.getMentor().getId(), MemberRole.ASSOCIATE); | ||
|
||
List<StudySessionCreateRequest> sessionCreateRequests = 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); | ||
} | ||
|
||
StudyUpdateRequest request = | ||
new StudyUpdateRequest(STUDY_NOTION_LINK, STUDY_INTRODUCTION, sessionCreateRequests); | ||
|
||
// when | ||
mentorStudyService.updateStudy(1L, request); | ||
|
||
// then | ||
Study savedStudy = studyRepository.findById(study.getId()).get(); | ||
assertThat(savedStudy.getNotionLink()).isEqualTo(request.notionLink()); | ||
|
||
List<StudyDetail> studyDetails = studyDetailRepository.findAllByStudyId(1L); | ||
for (int i = 0; i < studyDetails.size(); i++) { | ||
StudyDetail studyDetail = studyDetails.get(i); | ||
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); | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
두 로직을 추출하여 적절히 분리하는게 좋을 것 같습니다.