From ee8b4f9ce218a355dc0a12c675d35e869c56ea47 Mon Sep 17 00:00:00 2001 From: msk226 Date: Mon, 19 May 2025 11:23:36 +0900 Subject: [PATCH 1/7] =?UTF-8?q?[SPOT-284][FEAT]=20=EC=8A=A4=ED=84=B0?= =?UTF-8?q?=EB=94=94=20=EC=97=94=ED=8B=B0=ED=8B=B0=EC=97=90=20=EC=A2=85?= =?UTF-8?q?=EB=A3=8C=EC=8B=9C=EA=B0=84=20=EC=BB=AC=EB=9F=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/spot/domain/study/Study.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/spot/domain/study/Study.java b/src/main/java/com/example/spot/domain/study/Study.java index 1cc85020..31ea9a03 100644 --- a/src/main/java/com/example/spot/domain/study/Study.java +++ b/src/main/java/com/example/spot/domain/study/Study.java @@ -1,12 +1,10 @@ package com.example.spot.domain.study; import com.example.spot.domain.Notification; -import com.example.spot.domain.Quiz; import com.example.spot.domain.common.BaseEntity; import com.example.spot.domain.enums.Gender; import com.example.spot.domain.enums.Status; import com.example.spot.domain.enums.StudyState; -import com.example.spot.domain.enums.ThemeType; import com.example.spot.domain.mapping.MemberStudy; import com.example.spot.domain.mapping.PreferredStudy; import com.example.spot.domain.mapping.RegionStudy; @@ -20,12 +18,11 @@ import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import lombok.*; -import org.hibernate.annotations.DynamicInsert; -import org.hibernate.annotations.DynamicUpdate; @Entity @Getter @@ -88,6 +85,8 @@ public class Study extends BaseEntity { @Column(nullable = false) private Long maxPeople; + private LocalDateTime finishedAt; + @Builder.Default @OneToMany(mappedBy = "study", cascade = CascadeType.ALL) private List schedules = new ArrayList<>(); @@ -207,6 +206,7 @@ public void terminateStudy(String performance) { this.studyState = StudyState.COMPLETED; this.status = Status.OFF; this.performance = performance; + this.finishedAt = LocalDateTime.now(); } public void updateStudyInfo( From e1b30f79537548aaff11bb2fa600b900f236dd89 Mon Sep 17 00:00:00 2001 From: msk226 Date: Mon, 19 May 2025 11:24:30 +0900 Subject: [PATCH 2/7] =?UTF-8?q?[SPOT-284][FEAT]=20=EC=8A=A4=ED=84=B0?= =?UTF-8?q?=EB=94=94=20=ED=9E=88=EC=8A=A4=ED=86=A0=EB=A6=AC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=20=EC=8B=9C=EA=B7=B8=EB=8B=88=EC=B2=98=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spot/service/study/StudyQueryService.java | 5 ++-- .../spot/web/controller/SearchController.java | 19 +++++++++++++ .../dto/search/StudyHistoryResponseDTO.java | 28 +++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/example/spot/web/dto/search/StudyHistoryResponseDTO.java diff --git a/src/main/java/com/example/spot/service/study/StudyQueryService.java b/src/main/java/com/example/spot/service/study/StudyQueryService.java index 50790fb3..82158f4f 100644 --- a/src/main/java/com/example/spot/service/study/StudyQueryService.java +++ b/src/main/java/com/example/spot/service/study/StudyQueryService.java @@ -7,10 +7,8 @@ import com.example.spot.web.dto.search.SearchResponseDTO.HotKeywordDTO; import com.example.spot.web.dto.search.SearchResponseDTO.MyPageDTO; import com.example.spot.web.dto.search.SearchResponseDTO.StudyPreviewDTO; +import com.example.spot.web.dto.search.StudyHistoryResponseDTO; import com.example.spot.web.dto.study.response.StudyInfoResponseDTO; -import com.example.spot.web.dto.study.response.StudyMemberResponseDTO; -import com.example.spot.web.dto.study.response.StudyPostResponseDTO; -import com.example.spot.web.dto.study.response.StudyScheduleResponseDTO; import org.springframework.data.domain.Pageable; public interface StudyQueryService { @@ -71,4 +69,5 @@ StudyPreviewDTO findRecruitingStudiesByConditions( // 내가 모집중인 스터디 조회 StudyPreviewDTO findMyRecruitingStudies(Pageable pageable, Long memberId); + StudyHistoryResponseDTO getFinishedStudies(Pageable pageable, Long currentUserId); } diff --git a/src/main/java/com/example/spot/web/controller/SearchController.java b/src/main/java/com/example/spot/web/controller/SearchController.java index 3fff0b94..69162be3 100644 --- a/src/main/java/com/example/spot/web/controller/SearchController.java +++ b/src/main/java/com/example/spot/web/controller/SearchController.java @@ -12,6 +12,7 @@ import com.example.spot.web.dto.search.SearchResponseDTO.HotKeywordDTO; import com.example.spot.web.dto.search.SearchResponseDTO.MyPageDTO; import com.example.spot.web.dto.search.SearchResponseDTO.StudyPreviewDTO; +import com.example.spot.web.dto.search.StudyHistoryResponseDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.security.SecurityRequirement; @@ -425,6 +426,24 @@ public ApiResponse getAppliedStudies( return ApiResponse.onSuccess(SuccessStatus._STUDY_FOUND, studies); } + /* ----------------------------- 신청한 스터디 목록 조회 ------------------------------------- */ + @Tag(name = "마이 페이지") + @Operation(summary = "[마이 페이지] 사용자님의 노력들 조회", description = """ + + ## [마이페이지] + 호스트가 종료한 스터디, 그리고 스터디원(호스트포함) 본인이 탈퇴한 스터디의 정보와 스터디 한줄 평가를 조회합니다. + """) + @GetMapping("/search/studies/finished-studies") + public ApiResponse getFinishedStudies( + @RequestParam @Min(0) Integer page, + @RequestParam @Min(1) Integer size + ) { + StudyHistoryResponseDTO responseDTO = studyQueryService.getFinishedStudies(PageRequest.of(page, size), + SecurityUtils.getCurrentUserId()); + return ApiResponse.onSuccess(SuccessStatus._STUDY_FOUND, responseDTO); + } + + } diff --git a/src/main/java/com/example/spot/web/dto/search/StudyHistoryResponseDTO.java b/src/main/java/com/example/spot/web/dto/search/StudyHistoryResponseDTO.java new file mode 100644 index 00000000..29aa47f1 --- /dev/null +++ b/src/main/java/com/example/spot/web/dto/search/StudyHistoryResponseDTO.java @@ -0,0 +1,28 @@ +package com.example.spot.web.dto.search; + +import com.example.spot.domain.study.Study; +import java.time.LocalDateTime; +import org.springframework.data.domain.Page; + +public record StudyHistoryResponseDTO ( + Page studyHistories +) { + public static StudyHistoryResponseDTO of(Page studies) { + return new StudyHistoryResponseDTO(studies.map(study -> new StudyHistoryDTO( + study.getId(), + study.getTitle(), + study.getPerformance(), + study.getCreatedAt(), + study.getFinishedAt() + ))); + } + + private record StudyHistoryDTO ( + Long studyId, + String title, + String performance, + LocalDateTime createdAt, + LocalDateTime finishedAt + ) { + } +} From 24d8f232f44b848f865e94fab1c0b587c642423a Mon Sep 17 00:00:00 2001 From: msk226 Date: Mon, 19 May 2025 11:24:36 +0900 Subject: [PATCH 3/7] =?UTF-8?q?[SPOT-284][FEAT]=20=EC=8A=A4=ED=84=B0?= =?UTF-8?q?=EB=94=94=20=ED=9E=88=EC=8A=A4=ED=86=A0=EB=A6=AC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=20=EB=82=B4=EB=B6=80=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../querydsl/StudyRepositoryCustom.java | 3 ++ .../impl/StudyRepositoryCustomImpl.java | 31 +++++++++++++++++++ .../service/study/StudyQueryServiceImpl.java | 9 ++++++ 3 files changed, 43 insertions(+) diff --git a/src/main/java/com/example/spot/repository/querydsl/StudyRepositoryCustom.java b/src/main/java/com/example/spot/repository/querydsl/StudyRepositoryCustom.java index e822a9ce..64096e81 100644 --- a/src/main/java/com/example/spot/repository/querydsl/StudyRepositoryCustom.java +++ b/src/main/java/com/example/spot/repository/querydsl/StudyRepositoryCustom.java @@ -1,5 +1,6 @@ package com.example.spot.repository.querydsl; +import com.example.spot.domain.Member; import com.example.spot.domain.enums.Status; import com.example.spot.domain.enums.StudySortBy; import com.example.spot.domain.mapping.MemberStudy; @@ -9,6 +10,7 @@ import java.util.List; import java.util.Map; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; public interface StudyRepositoryCustom { @@ -36,6 +38,7 @@ List findStudyByConditionsAndRegionStudiesAndNotInIds(Map List findByMemberStudiesAndStatus(List memberStudy, Pageable pageable, Status status); List findRecruitingStudiesByMemberStudy(List memberStudy, Pageable pageable); + Page findFinishedStudies(Member member, Status status, Pageable pageable); long countStudyByConditionsAndThemeTypesAndNotInIds( Map search, List themeTypes, StudySortBy sortBy, List studyIds); diff --git a/src/main/java/com/example/spot/repository/querydsl/impl/StudyRepositoryCustomImpl.java b/src/main/java/com/example/spot/repository/querydsl/impl/StudyRepositoryCustomImpl.java index f30e8720..eb88e027 100644 --- a/src/main/java/com/example/spot/repository/querydsl/impl/StudyRepositoryCustomImpl.java +++ b/src/main/java/com/example/spot/repository/querydsl/impl/StudyRepositoryCustomImpl.java @@ -1,6 +1,8 @@ package com.example.spot.repository.querydsl.impl; +import com.example.spot.domain.Member; import com.example.spot.domain.Region; +import com.example.spot.domain.enums.ApplicationStatus; import com.example.spot.domain.enums.Gender; import com.example.spot.domain.enums.Status; import com.example.spot.domain.enums.StudySortBy; @@ -21,8 +23,11 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import static com.example.spot.domain.mapping.QMemberStudy.memberStudy; import static com.example.spot.domain.study.QStudy.study; @RequiredArgsConstructor @Slf4j @@ -278,7 +283,33 @@ public List findRecruitingStudiesByMemberStudy(List memberSt .fetch(); } + @Override + public Page findFinishedStudies(Member member, Status status, Pageable pageable) { + List content = queryFactory + .selectFrom(study) + .join(study.memberStudies, memberStudy) + .where( + memberStudy.member.id.eq(member.getId()), + memberStudy.status.eq(ApplicationStatus.APPROVED), + study.status.eq(Status.OFF) + ) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + Long count = queryFactory + .select(study.count()) + .from(study) + .join(study.memberStudies, memberStudy) + .where( + memberStudy.member.id.eq(member.getId()), + memberStudy.status.eq(ApplicationStatus.APPROVED), + study.status.eq(Status.OFF) + ) + .fetchOne(); + + return new PageImpl<>(content, pageable, count != null ? count : 0); + } @Override public long countStudyByConditionsAndThemeTypesAndNotInIds(Map search, diff --git a/src/main/java/com/example/spot/service/study/StudyQueryServiceImpl.java b/src/main/java/com/example/spot/service/study/StudyQueryServiceImpl.java index 2c498cfb..7dce5dd6 100644 --- a/src/main/java/com/example/spot/service/study/StudyQueryServiceImpl.java +++ b/src/main/java/com/example/spot/service/study/StudyQueryServiceImpl.java @@ -38,6 +38,7 @@ import com.example.spot.web.dto.search.SearchResponseDTO.MyPageDTO; import com.example.spot.web.dto.search.SearchResponseDTO.SearchStudyDTO; import com.example.spot.web.dto.search.SearchResponseDTO.StudyPreviewDTO; +import com.example.spot.web.dto.search.StudyHistoryResponseDTO; import com.example.spot.web.dto.study.response.StudyInfoResponseDTO; import java.util.ArrayList; import java.util.Collections; @@ -833,6 +834,14 @@ public StudyPreviewDTO findMyRecruitingStudies(Pageable pageable, Long memberId) return getDTOs(studies, pageable, totalElements, memberId); } + @Override + public StudyHistoryResponseDTO getFinishedStudies(Pageable pageable, Long currentUserId) { + Member member = memberRepository.findById(currentUserId) + .orElseThrow(() -> new MemberHandler(ErrorStatus._MEMBER_NOT_FOUND)); + Page finishedStudies = studyRepository.findFinishedStudies(member, Status.OFF, pageable); + return StudyHistoryResponseDTO.of(finishedStudies); + } + /** * 특정 회원이 참가하고 있는 스터디를 조회합니다. * From 5bce40c546a59f62a9f7bde86d1a3d4a3c61a94e Mon Sep 17 00:00:00 2001 From: msk226 Date: Mon, 19 May 2025 12:26:05 +0900 Subject: [PATCH 4/7] =?UTF-8?q?[SPOT-284][FEAT]=20=EC=8A=A4=ED=84=B0?= =?UTF-8?q?=EB=94=94=20=ED=9E=88=EC=8A=A4=ED=86=A0=EB=A6=AC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=A1=B0=EA=B1=B4=20StudyState=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spot/repository/querydsl/StudyRepositoryCustom.java | 3 ++- .../repository/querydsl/impl/StudyRepositoryCustomImpl.java | 6 +++--- .../example/spot/service/study/StudyQueryServiceImpl.java | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/example/spot/repository/querydsl/StudyRepositoryCustom.java b/src/main/java/com/example/spot/repository/querydsl/StudyRepositoryCustom.java index 64096e81..f17673a8 100644 --- a/src/main/java/com/example/spot/repository/querydsl/StudyRepositoryCustom.java +++ b/src/main/java/com/example/spot/repository/querydsl/StudyRepositoryCustom.java @@ -3,6 +3,7 @@ import com.example.spot.domain.Member; import com.example.spot.domain.enums.Status; import com.example.spot.domain.enums.StudySortBy; +import com.example.spot.domain.enums.StudyState; import com.example.spot.domain.mapping.MemberStudy; import com.example.spot.domain.mapping.RegionStudy; import com.example.spot.domain.mapping.StudyTheme; @@ -38,7 +39,7 @@ List findStudyByConditionsAndRegionStudiesAndNotInIds(Map List findByMemberStudiesAndStatus(List memberStudy, Pageable pageable, Status status); List findRecruitingStudiesByMemberStudy(List memberStudy, Pageable pageable); - Page findFinishedStudies(Member member, Status status, Pageable pageable); + Page findFinishedStudies(Member member, Pageable pageable); long countStudyByConditionsAndThemeTypesAndNotInIds( Map search, List themeTypes, StudySortBy sortBy, List studyIds); diff --git a/src/main/java/com/example/spot/repository/querydsl/impl/StudyRepositoryCustomImpl.java b/src/main/java/com/example/spot/repository/querydsl/impl/StudyRepositoryCustomImpl.java index eb88e027..5fee7c7d 100644 --- a/src/main/java/com/example/spot/repository/querydsl/impl/StudyRepositoryCustomImpl.java +++ b/src/main/java/com/example/spot/repository/querydsl/impl/StudyRepositoryCustomImpl.java @@ -284,14 +284,14 @@ public List findRecruitingStudiesByMemberStudy(List memberSt } @Override - public Page findFinishedStudies(Member member, Status status, Pageable pageable) { + public Page findFinishedStudies(Member member, Pageable pageable) { List content = queryFactory .selectFrom(study) .join(study.memberStudies, memberStudy) .where( memberStudy.member.id.eq(member.getId()), memberStudy.status.eq(ApplicationStatus.APPROVED), - study.status.eq(Status.OFF) + study.studyState.eq(StudyState.COMPLETED) ) .offset(pageable.getOffset()) .limit(pageable.getPageSize()) @@ -304,7 +304,7 @@ public Page findFinishedStudies(Member member, Status status, Pageable pa .where( memberStudy.member.id.eq(member.getId()), memberStudy.status.eq(ApplicationStatus.APPROVED), - study.status.eq(Status.OFF) + study.studyState.eq(StudyState.COMPLETED) ) .fetchOne(); diff --git a/src/main/java/com/example/spot/service/study/StudyQueryServiceImpl.java b/src/main/java/com/example/spot/service/study/StudyQueryServiceImpl.java index 7dce5dd6..e27bb9ff 100644 --- a/src/main/java/com/example/spot/service/study/StudyQueryServiceImpl.java +++ b/src/main/java/com/example/spot/service/study/StudyQueryServiceImpl.java @@ -12,6 +12,7 @@ import com.example.spot.domain.enums.Status; import com.example.spot.domain.enums.StudyLikeStatus; import com.example.spot.domain.enums.StudySortBy; +import com.example.spot.domain.enums.StudyState; import com.example.spot.domain.enums.ThemeType; import com.example.spot.domain.mapping.MemberStudy; import com.example.spot.domain.mapping.MemberTheme; @@ -838,7 +839,7 @@ public StudyPreviewDTO findMyRecruitingStudies(Pageable pageable, Long memberId) public StudyHistoryResponseDTO getFinishedStudies(Pageable pageable, Long currentUserId) { Member member = memberRepository.findById(currentUserId) .orElseThrow(() -> new MemberHandler(ErrorStatus._MEMBER_NOT_FOUND)); - Page finishedStudies = studyRepository.findFinishedStudies(member, Status.OFF, pageable); + Page finishedStudies = studyRepository.findFinishedStudies(member, pageable); return StudyHistoryResponseDTO.of(finishedStudies); } From 75a1e431bbce1217dc2e41eaca368d3a4b2ed14b Mon Sep 17 00:00:00 2001 From: msk226 Date: Mon, 19 May 2025 13:02:44 +0900 Subject: [PATCH 5/7] =?UTF-8?q?[SPOT-284][FEAT]=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EC=BF=BC=EB=A6=AC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../querydsl/StudyRepositoryCustom.java | 2 +- .../impl/StudyRepositoryCustomImpl.java | 28 ------------------- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/src/main/java/com/example/spot/repository/querydsl/StudyRepositoryCustom.java b/src/main/java/com/example/spot/repository/querydsl/StudyRepositoryCustom.java index f17673a8..13bb2171 100644 --- a/src/main/java/com/example/spot/repository/querydsl/StudyRepositoryCustom.java +++ b/src/main/java/com/example/spot/repository/querydsl/StudyRepositoryCustom.java @@ -39,7 +39,7 @@ List findStudyByConditionsAndRegionStudiesAndNotInIds(Map List findByMemberStudiesAndStatus(List memberStudy, Pageable pageable, Status status); List findRecruitingStudiesByMemberStudy(List memberStudy, Pageable pageable); - Page findFinishedStudies(Member member, Pageable pageable); + long countStudyByConditionsAndThemeTypesAndNotInIds( Map search, List themeTypes, StudySortBy sortBy, List studyIds); diff --git a/src/main/java/com/example/spot/repository/querydsl/impl/StudyRepositoryCustomImpl.java b/src/main/java/com/example/spot/repository/querydsl/impl/StudyRepositoryCustomImpl.java index 5fee7c7d..472a63bf 100644 --- a/src/main/java/com/example/spot/repository/querydsl/impl/StudyRepositoryCustomImpl.java +++ b/src/main/java/com/example/spot/repository/querydsl/impl/StudyRepositoryCustomImpl.java @@ -283,34 +283,6 @@ public List findRecruitingStudiesByMemberStudy(List memberSt .fetch(); } - @Override - public Page findFinishedStudies(Member member, Pageable pageable) { - List content = queryFactory - .selectFrom(study) - .join(study.memberStudies, memberStudy) - .where( - memberStudy.member.id.eq(member.getId()), - memberStudy.status.eq(ApplicationStatus.APPROVED), - study.studyState.eq(StudyState.COMPLETED) - ) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .fetch(); - - Long count = queryFactory - .select(study.count()) - .from(study) - .join(study.memberStudies, memberStudy) - .where( - memberStudy.member.id.eq(member.getId()), - memberStudy.status.eq(ApplicationStatus.APPROVED), - study.studyState.eq(StudyState.COMPLETED) - ) - .fetchOne(); - - return new PageImpl<>(content, pageable, count != null ? count : 0); - } - @Override public long countStudyByConditionsAndThemeTypesAndNotInIds(Map search, List themeTypes, StudySortBy sortBy, List studyIds) { From 189acbcdacec2775528064b1c8446e773e1bc74b Mon Sep 17 00:00:00 2001 From: msk226 Date: Mon, 19 May 2025 13:03:12 +0900 Subject: [PATCH 6/7] =?UTF-8?q?[SPOT-284][FEAT]=20=EC=8A=A4=ED=84=B0?= =?UTF-8?q?=EB=94=94=20=ED=9E=88=EC=8A=A4=ED=86=A0=EB=A6=AC=20=20MemberStu?= =?UTF-8?q?dy=20=ED=86=B5=ED=95=B4=20=EC=A1=B0=ED=9A=8C=20=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spot/domain/mapping/MemberStudy.java | 15 +++++++-- .../repository/MemberStudyRepository.java | 31 +++++++++++++++++++ .../MemberStudyCommandServiceImpl.java | 10 ++++-- .../study/StudyCommandServiceImpl.java | 2 ++ .../service/study/StudyQueryServiceImpl.java | 2 +- .../dto/search/StudyHistoryResponseDTO.java | 15 ++++----- 6 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/example/spot/domain/mapping/MemberStudy.java b/src/main/java/com/example/spot/domain/mapping/MemberStudy.java index 5358a246..6a32941d 100644 --- a/src/main/java/com/example/spot/domain/mapping/MemberStudy.java +++ b/src/main/java/com/example/spot/domain/mapping/MemberStudy.java @@ -3,12 +3,15 @@ import com.example.spot.domain.Member; import com.example.spot.domain.common.BaseEntity; import com.example.spot.domain.enums.ApplicationStatus; +import com.example.spot.domain.enums.Status; import com.example.spot.domain.study.Study; import jakarta.persistence.*; +import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.Setter; +import org.hibernate.annotations.ColumnDefault; @Getter @Entity @@ -38,6 +41,12 @@ public class MemberStudy extends BaseEntity { @Setter private String reason; + @Column(nullable = false) + @Enumerated(EnumType.STRING) + private Status activeStatus; + + private LocalDateTime finishedAt; + //== 회원 ==// @Setter @ManyToOne(fetch = FetchType.LAZY) @@ -63,6 +72,8 @@ public MemberStudy(Boolean isOwned, String introduction, Member member, Study st this.study = study; this.status = status; } - - + public void disable() { + this.activeStatus = Status.OFF; + this.finishedAt = LocalDateTime.now(); + } } diff --git a/src/main/java/com/example/spot/repository/MemberStudyRepository.java b/src/main/java/com/example/spot/repository/MemberStudyRepository.java index 4a424ab4..ebed450b 100644 --- a/src/main/java/com/example/spot/repository/MemberStudyRepository.java +++ b/src/main/java/com/example/spot/repository/MemberStudyRepository.java @@ -4,8 +4,11 @@ import com.example.spot.domain.enums.ApplicationStatus; import com.example.spot.domain.enums.Status; import com.example.spot.domain.mapping.MemberStudy; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; @@ -28,6 +31,34 @@ public interface MemberStudyRepository extends JpaRepository Optional findByMemberIdAndStudyId(Long memberId, Long studyId); + @Query( + value = """ + SELECT ms.* + FROM member_study ms + JOIN study s ON ms.study_id = s.id + WHERE ms.member_id = :memberId + AND ms.status = 'APPROVED' + AND ( + s.study_state = 'COMPLETED' + OR ms.active_status = 'OFF' + ) + """, + countQuery = """ + SELECT COUNT(*) + FROM member_study ms + JOIN study s ON ms.study_id = s.id + WHERE ms.member_id = :memberId + AND ms.status = 'APPROVED' + AND ( + s.study_state = 'COMPLETED' + OR ms.active_status = 'OFF' + ) + """, + nativeQuery = true + ) + Page findAllByMemberIdAndConditions(@Param("memberId") Long memberId, Pageable pageable); + + long countByStatusAndStudyId(ApplicationStatus status, Long studyId); long countByMemberIdAndStatusAndStudy_Status(Long memberId, ApplicationStatus applicationStatus, Status status); long countByMemberIdAndIsOwnedAndStudy_Status(Long memberId, Boolean isOwned, Status status); diff --git a/src/main/java/com/example/spot/service/memberstudy/MemberStudyCommandServiceImpl.java b/src/main/java/com/example/spot/service/memberstudy/MemberStudyCommandServiceImpl.java index c70ee0d6..e76f17c8 100644 --- a/src/main/java/com/example/spot/service/memberstudy/MemberStudyCommandServiceImpl.java +++ b/src/main/java/com/example/spot/service/memberstudy/MemberStudyCommandServiceImpl.java @@ -96,7 +96,8 @@ public StudyWithdrawalResponseDTO.WithdrawalDTO withdrawFromStudy(Long studyId) throw new StudyHandler(ErrorStatus._STUDY_OWNER_CANNOT_WITHDRAW); } - memberStudyRepository.delete(memberStudy); + memberStudy.disable(); + memberStudyRepository.save(memberStudy); return StudyWithdrawalResponseDTO.WithdrawalDTO.toDTO(member, study); } @@ -117,7 +118,11 @@ public WithdrawalDTO withdrawHostFromStudy(Long studyId, StudyHostWithdrawReques MemberStudy newHostStudy = memberStudyRepository.findByMemberIdAndStudyIdAndStatus(requestDTO.getNewHostId(), studyId, ApplicationStatus.APPROVED) .orElseThrow(() -> new StudyHandler(ErrorStatus._STUDY_MEMBER_NOT_EXIST)); - memberStudyRepository.delete(memberStudy); + + // memberStudyRepository.delete(memberStudy); + + memberStudy.disable(); + memberStudy.setIsOwned(false); newHostStudy.setIsOwned(true); newHostStudy.setReason(requestDTO.getReason()); @@ -154,6 +159,7 @@ public StudyTerminationResponseDTO.TerminationDTO terminateStudy(Long studyId, S throw new StudyHandler(ErrorStatus._STUDY_ALREADY_TERMINATED); } + memberStudy.disable(); study.terminateStudy(performance); studyRepository.save(study); diff --git a/src/main/java/com/example/spot/service/study/StudyCommandServiceImpl.java b/src/main/java/com/example/spot/service/study/StudyCommandServiceImpl.java index be280725..97f0a917 100644 --- a/src/main/java/com/example/spot/service/study/StudyCommandServiceImpl.java +++ b/src/main/java/com/example/spot/service/study/StudyCommandServiceImpl.java @@ -100,6 +100,7 @@ public StudyJoinResponseDTO.JoinDTO applyToStudy(Long studyId, StudyJoinRequestD .member(member) .study(study) .status(ApplicationStatus.APPLIED) + .activeStatus(Status.ON) .build(); member.addMemberStudy(memberStudy); @@ -239,6 +240,7 @@ private void createMemberStudy(Member member, Study study) { .member(member) .study(study) .status(ApplicationStatus.APPROVED) + .activeStatus(Status.ON) .build(); member.addMemberStudy(memberStudy); diff --git a/src/main/java/com/example/spot/service/study/StudyQueryServiceImpl.java b/src/main/java/com/example/spot/service/study/StudyQueryServiceImpl.java index e27bb9ff..078723b9 100644 --- a/src/main/java/com/example/spot/service/study/StudyQueryServiceImpl.java +++ b/src/main/java/com/example/spot/service/study/StudyQueryServiceImpl.java @@ -839,7 +839,7 @@ public StudyPreviewDTO findMyRecruitingStudies(Pageable pageable, Long memberId) public StudyHistoryResponseDTO getFinishedStudies(Pageable pageable, Long currentUserId) { Member member = memberRepository.findById(currentUserId) .orElseThrow(() -> new MemberHandler(ErrorStatus._MEMBER_NOT_FOUND)); - Page finishedStudies = studyRepository.findFinishedStudies(member, pageable); + Page finishedStudies = memberStudyRepository.findAllByMemberIdAndConditions(currentUserId, pageable); return StudyHistoryResponseDTO.of(finishedStudies); } diff --git a/src/main/java/com/example/spot/web/dto/search/StudyHistoryResponseDTO.java b/src/main/java/com/example/spot/web/dto/search/StudyHistoryResponseDTO.java index 29aa47f1..9c174754 100644 --- a/src/main/java/com/example/spot/web/dto/search/StudyHistoryResponseDTO.java +++ b/src/main/java/com/example/spot/web/dto/search/StudyHistoryResponseDTO.java @@ -1,5 +1,6 @@ package com.example.spot.web.dto.search; +import com.example.spot.domain.mapping.MemberStudy; import com.example.spot.domain.study.Study; import java.time.LocalDateTime; import org.springframework.data.domain.Page; @@ -7,13 +8,13 @@ public record StudyHistoryResponseDTO ( Page studyHistories ) { - public static StudyHistoryResponseDTO of(Page studies) { - return new StudyHistoryResponseDTO(studies.map(study -> new StudyHistoryDTO( - study.getId(), - study.getTitle(), - study.getPerformance(), - study.getCreatedAt(), - study.getFinishedAt() + public static StudyHistoryResponseDTO of(Page studies) { + return new StudyHistoryResponseDTO(studies.map(memberStudy -> new StudyHistoryDTO( + memberStudy.getStudy().getId(), + memberStudy.getStudy().getTitle(), + memberStudy.getStudy().getPerformance(), + memberStudy.getCreatedAt(), + memberStudy.getFinishedAt() ))); } From a7d05032ef7607a91865fa7a406dd1e0092254e9 Mon Sep 17 00:00:00 2001 From: msk226 Date: Mon, 19 May 2025 13:08:40 +0900 Subject: [PATCH 7/7] =?UTF-8?q?[SPOT-284][FEAT]=20=EC=8A=A4=ED=84=B0?= =?UTF-8?q?=EB=94=94=20=ED=9E=88=EC=8A=A4=ED=86=A0=EB=A6=AC=20=EC=B5=9C?= =?UTF-8?q?=EC=8B=A0=EC=88=9C=EC=9C=BC=EB=A1=9C=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/spot/repository/MemberStudyRepository.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/example/spot/repository/MemberStudyRepository.java b/src/main/java/com/example/spot/repository/MemberStudyRepository.java index ebed450b..76315045 100644 --- a/src/main/java/com/example/spot/repository/MemberStudyRepository.java +++ b/src/main/java/com/example/spot/repository/MemberStudyRepository.java @@ -42,6 +42,7 @@ public interface MemberStudyRepository extends JpaRepository s.study_state = 'COMPLETED' OR ms.active_status = 'OFF' ) + ORDER BY ms.created_at DESC """, countQuery = """ SELECT COUNT(*)