-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: 랜덤 출석번호 생성기를 컴포넌트로 등록 * feat: 스터디 개설 v2 API 구현 * test: 스터디 개설 v2 테스트 추가 * feat: 스터디회차 페치조인해서 조회하는 메서드 추가 * fix: 지연로딩 문제로 인한 페치조인 조회하는 메서드 테스트에 적용 * fix: 누락된 where절 추가
- Loading branch information
Showing
8 changed files
with
265 additions
and
0 deletions.
There are no files selected for viewing
29 changes: 29 additions & 0 deletions
29
src/main/java/com/gdschongik/gdsc/domain/studyv2/api/AdminStudyControllerV2.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.gdschongik.gdsc.domain.studyv2.api; | ||
|
||
import com.gdschongik.gdsc.domain.studyv2.application.AdminStudyServiceV2; | ||
import com.gdschongik.gdsc.domain.studyv2.dto.request.StudyCreateRequest; | ||
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.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@Tag(name = "Admin Study V2", description = "스터디 V2 어드민 API입니다.") | ||
@RestController | ||
@RequestMapping("/admin/studies/v2") | ||
@RequiredArgsConstructor | ||
public class AdminStudyControllerV2 { | ||
|
||
private final AdminStudyServiceV2 adminStudyServiceV2; | ||
|
||
@Operation(summary = "스터디 개설", description = "스터디를 개설합니다. 빈 스터디회차를 함께 생성합니다.") | ||
@PostMapping | ||
public ResponseEntity<Void> createStudy(@Valid @RequestBody StudyCreateRequest request) { | ||
adminStudyServiceV2.createStudy(request); | ||
return ResponseEntity.ok().build(); | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
src/main/java/com/gdschongik/gdsc/domain/studyv2/application/AdminStudyServiceV2.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package com.gdschongik.gdsc.domain.studyv2.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.studyv2.dao.StudyV2Repository; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.AttendanceNumberGenerator; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.StudyFactory; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.StudyV2; | ||
import com.gdschongik.gdsc.domain.studyv2.dto.request.StudyCreateRequest; | ||
import com.gdschongik.gdsc.global.exception.CustomException; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Slf4j | ||
@Service | ||
@RequiredArgsConstructor | ||
public class AdminStudyServiceV2 { | ||
|
||
private final StudyV2Repository studyV2Repository; | ||
private final MemberRepository memberRepository; | ||
private final StudyFactory studyFactory; | ||
private final AttendanceNumberGenerator attendanceNumberGenerator; | ||
|
||
@Transactional | ||
public void createStudy(StudyCreateRequest request) { | ||
Member mentor = | ||
memberRepository.findById(request.mentorId()).orElseThrow(() -> new CustomException(MEMBER_NOT_FOUND)); | ||
|
||
mentor.assignToMentor(); | ||
|
||
StudyV2 study = studyFactory.create( | ||
request.type(), | ||
request.title(), | ||
request.description(), | ||
request.descriptionNotionLink(), | ||
request.semester(), | ||
request.totalRound(), | ||
request.dayOfWeek(), | ||
request.startTime(), | ||
request.endTime(), | ||
request.applicationPeriod(), | ||
request.discordChannelId(), | ||
request.discordRoleId(), | ||
mentor, | ||
attendanceNumberGenerator); | ||
|
||
memberRepository.save(mentor); | ||
studyV2Repository.save(study); | ||
|
||
log.info("[AdminStudyService] 스터디 생성 완료: studyId = {}", study.getId()); | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/StudyV2CustomRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.gdschongik.gdsc.domain.studyv2.dao; | ||
|
||
import com.gdschongik.gdsc.domain.studyv2.domain.StudyV2; | ||
import java.util.Optional; | ||
|
||
public interface StudyV2CustomRepository { | ||
Optional<StudyV2> findFetchById(Long id); | ||
} |
6 changes: 6 additions & 0 deletions
6
src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/StudyV2Repository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.gdschongik.gdsc.domain.studyv2.dao; | ||
|
||
import com.gdschongik.gdsc.domain.studyv2.domain.StudyV2; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface StudyV2Repository extends JpaRepository<StudyV2, Long>, StudyV2CustomRepository {} |
24 changes: 24 additions & 0 deletions
24
src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/StudyV2RepositoryImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.gdschongik.gdsc.domain.studyv2.dao; | ||
|
||
import static com.gdschongik.gdsc.domain.studyv2.domain.QStudyV2.*; | ||
|
||
import com.gdschongik.gdsc.domain.studyv2.domain.StudyV2; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
import java.util.Optional; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@RequiredArgsConstructor | ||
public class StudyV2RepositoryImpl implements StudyV2CustomRepository { | ||
|
||
private final JPAQueryFactory queryFactory; | ||
|
||
@Override | ||
public Optional<StudyV2> findFetchById(Long id) { | ||
return Optional.ofNullable(queryFactory | ||
.selectFrom(studyV2) | ||
.join(studyV2.studySessions) | ||
.fetchJoin() | ||
.where(studyV2.id.eq(id)) | ||
.fetchOne()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
src/main/java/com/gdschongik/gdsc/domain/studyv2/dto/request/StudyCreateRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.gdschongik.gdsc.domain.studyv2.dto.request; | ||
|
||
import com.gdschongik.gdsc.domain.common.vo.Period; | ||
import com.gdschongik.gdsc.domain.common.vo.Semester; | ||
import com.gdschongik.gdsc.domain.study.domain.StudyType; | ||
import jakarta.validation.constraints.NotNull; | ||
import jakarta.validation.constraints.Positive; | ||
import java.time.DayOfWeek; | ||
import java.time.LocalTime; | ||
|
||
public record StudyCreateRequest( | ||
@NotNull @Positive Long mentorId, | ||
@NotNull StudyType type, | ||
@NotNull String title, | ||
String description, | ||
String descriptionNotionLink, | ||
@NotNull Semester semester, | ||
@NotNull @Positive Integer totalRound, | ||
DayOfWeek dayOfWeek, | ||
LocalTime startTime, | ||
LocalTime endTime, | ||
@NotNull Period applicationPeriod, | ||
String discordChannelId, | ||
String discordRoleId) {} |
116 changes: 116 additions & 0 deletions
116
src/test/java/com/gdschongik/gdsc/domain/studyv2/application/AdminStudyServiceV2Test.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package com.gdschongik.gdsc.domain.studyv2.application; | ||
|
||
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.domain.StudyType; | ||
import com.gdschongik.gdsc.domain.studyv2.dao.StudyV2Repository; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.StudySessionV2; | ||
import com.gdschongik.gdsc.domain.studyv2.domain.StudyV2; | ||
import com.gdschongik.gdsc.domain.studyv2.dto.request.StudyCreateRequest; | ||
import com.gdschongik.gdsc.helper.IntegrationTest; | ||
import java.util.Optional; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
|
||
class AdminStudyServiceV2Test extends IntegrationTest { | ||
|
||
@Autowired | ||
AdminStudyServiceV2 adminStudyService; | ||
|
||
@Autowired | ||
StudyV2Repository studyV2Repository; | ||
|
||
@Nested | ||
class 스터디_생성할때 { | ||
|
||
@Test | ||
void 스터디와_스터디회차가_모두_저장된다() { | ||
// given | ||
createRegularMember(); | ||
int totalRound = 8; | ||
var request = new StudyCreateRequest( | ||
1L, | ||
StudyType.OFFLINE, | ||
STUDY_TITLE, | ||
STUDY_DESCRIPTION, | ||
STUDY_DESCRIPTION_NOTION_LINK, | ||
STUDY_SEMESTER, | ||
totalRound, | ||
DAY_OF_WEEK, | ||
STUDY_START_TIME, | ||
STUDY_END_TIME, | ||
STUDY_APPLICATION_PERIOD, | ||
STUDY_DISCORD_CHANNEL_ID, | ||
STUDY_DISCORD_ROLE_ID); | ||
|
||
// when | ||
adminStudyService.createStudy(request); | ||
|
||
// then | ||
Optional<StudyV2> optionalStudy = studyV2Repository.findFetchById(1L); | ||
assertThat(optionalStudy).isPresent(); | ||
|
||
StudyV2 study = optionalStudy.get(); | ||
assertThat(study.getStudySessions()).hasSize(totalRound); | ||
} | ||
|
||
@Test | ||
void 스터디회차에_출석번호가_생성되어_저장된다() { | ||
// given | ||
createRegularMember(); | ||
var request = new StudyCreateRequest( | ||
1L, | ||
StudyType.OFFLINE, | ||
STUDY_TITLE, | ||
STUDY_DESCRIPTION, | ||
STUDY_DESCRIPTION_NOTION_LINK, | ||
STUDY_SEMESTER, | ||
TOTAL_ROUND, | ||
DAY_OF_WEEK, | ||
STUDY_START_TIME, | ||
STUDY_END_TIME, | ||
STUDY_APPLICATION_PERIOD, | ||
STUDY_DISCORD_CHANNEL_ID, | ||
STUDY_DISCORD_ROLE_ID); | ||
|
||
// when | ||
adminStudyService.createStudy(request); | ||
|
||
// then | ||
StudyV2 study = studyV2Repository.findFetchById(1L).orElseThrow(); | ||
assertThat(study.getStudySessions()) | ||
.extracting(StudySessionV2::getLessonAttendanceNumber) | ||
.doesNotContainNull(); | ||
} | ||
|
||
@Test | ||
void 멘토가_멘토_역할로_변경된다() { | ||
// given | ||
createRegularMember(); | ||
var request = new StudyCreateRequest( | ||
1L, | ||
StudyType.OFFLINE, | ||
STUDY_TITLE, | ||
STUDY_DESCRIPTION, | ||
STUDY_DESCRIPTION_NOTION_LINK, | ||
STUDY_SEMESTER, | ||
TOTAL_ROUND, | ||
DAY_OF_WEEK, | ||
STUDY_START_TIME, | ||
STUDY_END_TIME, | ||
STUDY_APPLICATION_PERIOD, | ||
STUDY_DISCORD_CHANNEL_ID, | ||
STUDY_DISCORD_ROLE_ID); | ||
|
||
// when | ||
adminStudyService.createStudy(request); | ||
|
||
// then | ||
Member mentor = memberRepository.findById(1L).orElseThrow(); | ||
assertThat(mentor.isMentor()).isTrue(); | ||
} | ||
} | ||
} |