diff --git a/src/main/java/org/withtime/be/withtimebe/domain/date/controller/query/DateQueryController.java b/src/main/java/org/withtime/be/withtimebe/domain/date/controller/query/DateQueryController.java index a5e5d4a..b3d4e62 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/date/controller/query/DateQueryController.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/date/controller/query/DateQueryController.java @@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.namul.api.payload.response.DefaultResponse; +import org.springdoc.core.annotations.ParameterObject; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; @@ -33,13 +34,13 @@ public class DateQueryController { @ApiResponse(responseCode = "404", description = "DATE_COURSE404_1 : 해당하는 데이트 코스를 찾을 수 없습니다.") }) @SwaggerPageable - @PostMapping("/search") + @GetMapping public DefaultResponse findDateCourses( @PageableDefault(page = 0, size = 10) Pageable pageable, - @RequestBody DateRequestDTO.DateCourseSearchCond dateCourseSearchCond + @ParameterObject DateRequestDTO.DateCourseSearchCond dateCourseSearchCond, + @AuthenticatedMember Member member ) { - Page dateCourses = dateQueryService.findDateCourses(dateCourseSearchCond, pageable); - DateResponseDTO.DateCourseList response = DateConverter.createDateCourseList(dateCourses); + DateResponseDTO.DateCourseList response = dateQueryService.findDateCourses(dateCourseSearchCond, pageable, member); return DefaultResponse.ok(response); } @@ -53,11 +54,11 @@ public DefaultResponse findDateCourses( @PostMapping("/bookmarks/search") public DefaultResponse findDateCourseBookmark( @PageableDefault(page = 0, size = 10) Pageable pageable, - @RequestBody DateRequestDTO.DateCourseSearchCond dateCourseSearchCond, + @ModelAttribute DateRequestDTO.DateCourseSearchCond dateCourseSearchCond, @AuthenticatedMember Member member ){ Page bookmarkedDateCourses = dateQueryService.findDateCourseBookmarks(dateCourseSearchCond, pageable, member); - DateResponseDTO.DateCourseList response = DateConverter.createDateCourseList(bookmarkedDateCourses); + DateResponseDTO.DateCourseList response = DateConverter.createDateCourseList(bookmarkedDateCourses, null, dateCourseSearchCond); return DefaultResponse.ok(response); } } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/date/converter/DateConverter.java b/src/main/java/org/withtime/be/withtimebe/domain/date/converter/DateConverter.java index a124b8b..c622466 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/date/converter/DateConverter.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/date/converter/DateConverter.java @@ -10,8 +10,9 @@ import org.withtime.be.withtimebe.domain.member.entity.Member; import java.time.LocalDateTime; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Set; public class DateConverter { @@ -37,13 +38,11 @@ public static DateCourse createDateCourse(DateRequestDTO.SaveDateCourse dateCour .build(); } - // 나중에 생성한 정보를 리턴하는 데 사용,,? 근데 애초에 그 뭐야 - // builder()로 만들 때 잘 만들어주면 안되냐 // List -> DateResponseDTO.DateCourseInfo // 단일 추천 코스를 응답으로 구성(시그니처 포함) public static DateResponseDTO.DateCourse createDateCourseInfo(List datePlaces, String signature){ List datePlaceDtos = datePlaces.stream() - .map(DateConverter::createDatePlace) + .map(dp -> DateConverter.createDatePlace(dp, null, null)) .toList(); return DateResponseDTO.DateCourse.builder() @@ -54,7 +53,9 @@ public static DateResponseDTO.DateCourse createDateCourseInfo(List da } // DatePlace -> DateResponseDTO.DatePlace - public static DateResponseDTO.DatePlace createDatePlace(DatePlace datePlace) { + public static DateResponseDTO.DatePlace createDatePlace(DatePlace datePlace, + LocalDateTime startTime, + LocalDateTime endTime) { return DateResponseDTO.DatePlace.builder() .datePlaceId(datePlace.getId()) .name(datePlace.getName()) @@ -67,27 +68,48 @@ public static DateResponseDTO.DatePlace createDatePlace(DatePlace datePlace) { .roadNameAddress(datePlace.getRoadNameAddress()) .lotNumberAddress(datePlace.getLotNumberAddress()) .placeType(datePlace.getPlaceType()) + .startTime(startTime) + .endTime(endTime) .build(); } // DateResponseDTO.DateCourse -> DateResponseDTO.DateCourse - public static DateResponseDTO.DateCourse createDateCourse(DateCourse dateCourse){ - + public static DateResponseDTO.DateCourse createDateCourse(DateCourse dateCourse, + Set bookmarkedIds, + DateRequestDTO.DateCourseSearchCond cond){ + Boolean bookmarked = null; + if (!bookmarkedIds.isEmpty()) bookmarked = bookmarkedIds.contains(dateCourse.getId()); List datePlaces = dateCourse.getDatePlaceDateCourses().stream() - .map(DatePlaceDateCourse::getDatePlace) - .map(DateConverter::createDatePlace) + .map(dc -> DateConverter.createDatePlace(dc.getDatePlace(), dc.getStartTime(), dc.getEndTime())) .toList(); return DateResponseDTO.DateCourse.builder() .name(dateCourse.getName()) .datePlaces(datePlaces) + .isBookmarked(bookmarked) + .dateCourseSearchCondInfo(createSearchCond(cond)) + .build(); + } + + public static DateResponseDTO.DateCourseSearchCondInfo createSearchCond(DateRequestDTO.DateCourseSearchCond cond){ + return DateResponseDTO.DateCourseSearchCondInfo.builder() + .budget(cond.budget()) + .datePlaces(cond.datePlaces()) + .mealTypes(cond.mealTypes()) + .transportation(cond.transportation()) + .dateDurationTime(cond.dateDurationTime()) + .userPreferredKeywords(cond.userPreferredKeywords()) .build(); } // Page -> DateRequestDTO.DateCourseList - public static DateResponseDTO.DateCourseList createDateCourseList(Page dateCourses){ + public static DateResponseDTO.DateCourseList createDateCourseList(Page dateCourses, Set bookmarkedIds, + DateRequestDTO.DateCourseSearchCond cond){ List dateCourseList = dateCourses.stream() - .map(DateConverter::createDateCourse) + .map(dc ->{ + if (bookmarkedIds != null) return createDateCourse(dc, bookmarkedIds, cond); + return createDateCourse(dc, Collections.emptySet(), cond); + }) .toList(); return DateResponseDTO.DateCourseList.builder() @@ -96,6 +118,7 @@ public static DateResponseDTO.DateCourseList createDateCourseList(Page datePlaces, + DateCourseSearchCondInfo dateCourseSearchCondInfo, + Boolean isBookmarked, String signature ){} @@ -40,6 +45,17 @@ public record DateCourseList( Integer totalPages, Integer currentPage, Integer currentSize, - Boolean hasNextPage + Boolean hasNextPage, + Long totalCount + ){} + + @Builder + public record DateCourseSearchCondInfo( + DatePriceRange budget, + List datePlaces, + DateTime dateDurationTime, + List mealTypes, + Transportation transportation, + List userPreferredKeywords ){} } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/date/repository/DateCourseBookmarkRepository.java b/src/main/java/org/withtime/be/withtimebe/domain/date/repository/DateCourseBookmarkRepository.java index 1d60c00..85d223f 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/date/repository/DateCourseBookmarkRepository.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/date/repository/DateCourseBookmarkRepository.java @@ -1,12 +1,22 @@ package org.withtime.be.withtimebe.domain.date.repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.withtime.be.withtimebe.domain.date.entity.DateCourse; import org.withtime.be.withtimebe.domain.date.entity.DateCourseBookmark; import org.withtime.be.withtimebe.domain.member.entity.Member; +import java.util.List; import java.util.Optional; public interface DateCourseBookmarkRepository extends JpaRepository { - Optional findByMemberAndDateCourse(Member member, DateCourse dateCourse); + Optional findByMemberAndDateCourse(Member member, DateCourse dateCourse); + + @Query(""" + select b.dateCourse.id + from DateCourseBookmark b + where b.member.id = :memberId + and b.dateCourse.id in :courseIds + """) + List findBookmarkedCourseIds(Long memberId, List courseIds); } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/date/service/query/DateQueryService.java b/src/main/java/org/withtime/be/withtimebe/domain/date/service/query/DateQueryService.java index 5431154..09ed177 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/date/service/query/DateQueryService.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/date/service/query/DateQueryService.java @@ -3,10 +3,12 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.withtime.be.withtimebe.domain.date.dto.request.DateRequestDTO; +import org.withtime.be.withtimebe.domain.date.dto.response.DateResponseDTO; import org.withtime.be.withtimebe.domain.date.entity.DateCourse; import org.withtime.be.withtimebe.domain.member.entity.Member; public interface DateQueryService { - public Page findDateCourses(DateRequestDTO.DateCourseSearchCond dateCourseSearchCond, Pageable pageable); + public DateResponseDTO.DateCourseList findDateCourses(DateRequestDTO.DateCourseSearchCond dateCourseSearchCond, Pageable pageable, Member member); public Page findDateCourseBookmarks(DateRequestDTO.DateCourseSearchCond dateCourseSearchCond, Pageable pageable, Member member); + public Boolean checkBookmark(Member member, DateCourse dateCourse); } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/date/service/query/DateQueryServiceImpl.java b/src/main/java/org/withtime/be/withtimebe/domain/date/service/query/DateQueryServiceImpl.java index b10f019..f49b919 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/date/service/query/DateQueryServiceImpl.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/date/service/query/DateQueryServiceImpl.java @@ -5,24 +5,44 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.withtime.be.withtimebe.domain.date.converter.DateConverter; import org.withtime.be.withtimebe.domain.date.dto.request.DateRequestDTO; +import org.withtime.be.withtimebe.domain.date.dto.response.DateResponseDTO; import org.withtime.be.withtimebe.domain.date.entity.DateCourse; +import org.withtime.be.withtimebe.domain.date.repository.DateCourseBookmarkRepository; import org.withtime.be.withtimebe.domain.date.repository.DateCourseRepository; import org.withtime.be.withtimebe.domain.log.placecategorylog.annotation.LogPlaceCategory; import org.withtime.be.withtimebe.domain.member.annotation.GetPoint; import org.withtime.be.withtimebe.domain.member.annotation.enums.PointAction; import org.withtime.be.withtimebe.domain.member.entity.Member; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + @Service @Transactional(readOnly = true) @RequiredArgsConstructor public class DateQueryServiceImpl implements DateQueryService { private final DateCourseRepository dateCourseRepository; + private final DateCourseBookmarkRepository dateCourseBookmarkRepository; + + public DateResponseDTO.DateCourseList findDateCourses(DateRequestDTO.DateCourseSearchCond dateCourseSearchCond, Pageable pageable, Member member){ + Page dateCourses = dateCourseRepository.searchDateCourseByApplyPage(dateCourseSearchCond, pageable); + List ids = dateCourses.getContent().stream().map(DateCourse::getId).toList(); + Set bookmarkedIds = + (member != null && !ids.isEmpty()) + ? new HashSet<>(dateCourseBookmarkRepository.findBookmarkedCourseIds(member.getId(), ids)) + : java.util.Collections.emptySet(); + + return DateConverter.createDateCourseList(dateCourses, bookmarkedIds, dateCourseSearchCond); + } + @LogPlaceCategory @GetPoint(action = PointAction.VIEW_DATE_COURSE) - public Page findDateCourses(DateRequestDTO.DateCourseSearchCond dateCourseSearchCond, Pageable pageable){ + public Page findDateCourses(DateRequestDTO.DateCourseSearchCond dateCourseSearchCond, Pageable pageable) { return dateCourseRepository.searchDateCourseByApplyPage(dateCourseSearchCond, pageable); } @@ -31,4 +51,10 @@ public Page findDateCourses(DateRequestDTO.DateCourseSearchCond date public Page findDateCourseBookmarks(DateRequestDTO.DateCourseSearchCond dateCourseSearchCond, Pageable pageable, Member member){ return dateCourseRepository.searchDateCourseBookmarkByMemberAndApplyPage(dateCourseSearchCond, member, pageable); } + + + public Boolean checkBookmark(Member member, DateCourse dateCourse){ + return dateCourseBookmarkRepository.findByMemberAndDateCourse(member, dateCourse).isPresent(); + } + }