diff --git a/src/main/java/org/atdev/artrip/domain/exhibit/reponse/ExhibitDetailResponse.java b/src/main/java/org/atdev/artrip/domain/exhibit/reponse/ExhibitDetailResponse.java index bbe12d7..2630938 100644 --- a/src/main/java/org/atdev/artrip/domain/exhibit/reponse/ExhibitDetailResponse.java +++ b/src/main/java/org/atdev/artrip/domain/exhibit/reponse/ExhibitDetailResponse.java @@ -26,4 +26,5 @@ public class ExhibitDetailResponse { private Double hallLatitude; private Double hallLongitude; + private boolean isFavorite; } diff --git a/src/main/java/org/atdev/artrip/domain/exhibit/service/ExhibitService.java b/src/main/java/org/atdev/artrip/domain/exhibit/service/ExhibitService.java index e67c64b..98496d4 100644 --- a/src/main/java/org/atdev/artrip/domain/exhibit/service/ExhibitService.java +++ b/src/main/java/org/atdev/artrip/domain/exhibit/service/ExhibitService.java @@ -4,6 +4,7 @@ import org.atdev.artrip.domain.exhibit.data.Exhibit; import org.atdev.artrip.domain.exhibit.reponse.ExhibitDetailResponse; import org.atdev.artrip.domain.exhibit.repository.ExhibitRepository; +import org.atdev.artrip.domain.favortie.repository.FavoriteExhibitRepository; import org.atdev.artrip.domain.home.converter.HomeConverter; import org.atdev.artrip.global.apipayload.code.status.ExhibitError; import org.atdev.artrip.global.apipayload.exception.GeneralException; @@ -15,14 +16,20 @@ public class ExhibitService { private final ExhibitRepository exhibitRepository; private final HomeConverter homeConverter; + private final FavoriteExhibitRepository favoriteExhibitRepository; - public ExhibitDetailResponse getExhibitDetail(Long exhibitId) { + public ExhibitDetailResponse getExhibitDetail(Long exhibitId, Long userId) { Exhibit exhibit = exhibitRepository.findById(exhibitId) .orElseThrow(() -> new GeneralException(ExhibitError._EXHIBIT_NOT_FOUND)); - return homeConverter.toHomeExhibitResponse(exhibit); + boolean isFavorite = false; + if (userId != null ) { + isFavorite = favoriteExhibitRepository.existsActive(userId, exhibitId); + } + + return homeConverter.toHomeExhibitResponse(exhibit, isFavorite); } diff --git a/src/main/java/org/atdev/artrip/domain/exhibit/web/controller/ExhibitController.java b/src/main/java/org/atdev/artrip/domain/exhibit/web/controller/ExhibitController.java index 6284cf6..9c5b192 100644 --- a/src/main/java/org/atdev/artrip/domain/exhibit/web/controller/ExhibitController.java +++ b/src/main/java/org/atdev/artrip/domain/exhibit/web/controller/ExhibitController.java @@ -14,6 +14,8 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -26,7 +28,9 @@ public class ExhibitController { private final HomeService homeService; private final ExhibitService exhibitService; - + private Long getUserId(UserDetails userDetails) { + return userDetails != null ? Long.parseLong(userDetails.getUsername()) : null; + } @Operation(summary = "장르 조회", description = "키워드 장르 데이터 전체 조회") @ApiErrorResponses( common = {CommonError._BAD_REQUEST, CommonError._UNAUTHORIZED}, @@ -45,9 +49,11 @@ public ResponseEntity>> getGenres(){ ) @GetMapping("/{id}") public ResponseEntity> getExhibit( - @PathVariable Long id){ + @PathVariable Long id, + @AuthenticationPrincipal UserDetails userDetails) { - ExhibitDetailResponse exhibit= exhibitService.getExhibitDetail(id); + Long userId = getUserId(userDetails); + ExhibitDetailResponse exhibit= exhibitService.getExhibitDetail(id, userId); return ResponseEntity.ok(CommonResponse.onSuccess(exhibit)); } @@ -86,9 +92,10 @@ public ResponseEntity>> getDomestic(){ @PostMapping("/filter") public ResponseEntity getDomesticFilter(@RequestBody ExhibitFilterRequest dto, @RequestParam(required = false) Long cursor, - @PageableDefault(size = 20) Pageable pageable){ - - FilterResponse exhibits = homeService.getFilterExhibit(dto, pageable, cursor); + @PageableDefault(size = 20) Pageable pageable, + @AuthenticationPrincipal UserDetails userDetails) { + Long userId = getUserId(userDetails); + FilterResponse exhibits = homeService.getFilterExhibit(dto, pageable, cursor,userId); return ResponseEntity.ok(exhibits); diff --git a/src/main/java/org/atdev/artrip/domain/exhibitHall/repository/ExhibitHallRepository.java b/src/main/java/org/atdev/artrip/domain/exhibitHall/repository/ExhibitHallRepository.java index 064d3a2..e5130a9 100644 --- a/src/main/java/org/atdev/artrip/domain/exhibitHall/repository/ExhibitHallRepository.java +++ b/src/main/java/org/atdev/artrip/domain/exhibitHall/repository/ExhibitHallRepository.java @@ -17,7 +17,7 @@ public interface ExhibitHallRepository extends JpaRepository @Query("SELECT DISTINCT e.country FROM ExhibitHall e WHERE e.country <> '한국'") List findAllOverseasCountries(); - @Query("SELECT DISTINCT e.region FROM ExhibitHall e WHERE e.country = '한국'") + @Query("SELECT DISTINCT e.region FROM ExhibitHall e WHERE e.country IN ('한국', '대한민국')") List findAllDomesticRegions(); diff --git a/src/main/java/org/atdev/artrip/domain/favortie/repository/FavoriteExhibitRepository.java b/src/main/java/org/atdev/artrip/domain/favortie/repository/FavoriteExhibitRepository.java index 658f79c..8c2bf2b 100644 --- a/src/main/java/org/atdev/artrip/domain/favortie/repository/FavoriteExhibitRepository.java +++ b/src/main/java/org/atdev/artrip/domain/favortie/repository/FavoriteExhibitRepository.java @@ -8,6 +8,7 @@ import java.time.LocalDate; import java.util.List; import java.util.Optional; +import java.util.Set; public interface FavoriteExhibitRepository extends JpaRepository { @Query(""" @@ -86,4 +87,11 @@ List findDatesByYearMonth( AND f.exhibit.exhibitId = :exhibitId """) Optional findByUserAndExhibit(@Param("userId") Long userId, @Param("exhibitId") Long exhibitId); + + @Query(""" + SELECT f.exhibit.exhibitId + FROM FavoriteExhibit f + WHERE f.user.userId = :userId AND f.status = true + """) + Set findActiveExhibitIds(@Param("userId") Long userId); } diff --git a/src/main/java/org/atdev/artrip/domain/favortie/service/FavoriteExhibitService.java b/src/main/java/org/atdev/artrip/domain/favortie/service/FavoriteExhibitService.java index 5898207..e4641dc 100644 --- a/src/main/java/org/atdev/artrip/domain/favortie/service/FavoriteExhibitService.java +++ b/src/main/java/org/atdev/artrip/domain/favortie/service/FavoriteExhibitService.java @@ -182,7 +182,7 @@ private FavoriteResponse toFavoriteResponse(FavoriteExhibit favorite) { .title(exhibit.getTitle()) .posterUrl(exhibit.getPosterUrl()) .exhibitStatus(exhibit.getStatus()) - .favoriteStatus(favorite.isStatus()) + .active(favorite.isStatus()) .exhibitPeriod(period) .exhibitHallName(hall != null ? hall.getName() : null ) .country(hall != null ? hall.getCountry() : null) diff --git a/src/main/java/org/atdev/artrip/domain/favortie/web/dto/response/FavoriteResponse.java b/src/main/java/org/atdev/artrip/domain/favortie/web/dto/response/FavoriteResponse.java index a21e2cd..7ed5cd5 100644 --- a/src/main/java/org/atdev/artrip/domain/favortie/web/dto/response/FavoriteResponse.java +++ b/src/main/java/org/atdev/artrip/domain/favortie/web/dto/response/FavoriteResponse.java @@ -15,7 +15,7 @@ public class FavoriteResponse { private String title; private String posterUrl; private Status exhibitStatus; - private boolean favoriteStatus; + private boolean active; private String exhibitPeriod; private String exhibitHallName; private String country; diff --git a/src/main/java/org/atdev/artrip/domain/home/converter/HomeConverter.java b/src/main/java/org/atdev/artrip/domain/home/converter/HomeConverter.java index b0dc1f7..4954cff 100644 --- a/src/main/java/org/atdev/artrip/domain/home/converter/HomeConverter.java +++ b/src/main/java/org/atdev/artrip/domain/home/converter/HomeConverter.java @@ -20,11 +20,11 @@ public class HomeConverter { private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd"); - public FilterResponse toFilterResponse(Slice slice) { + public FilterResponse toFilterResponse(Slice slice, Set favorites) { List postDtos = slice.getContent() .stream() - .map(this::toHomeExhibitListResponse) + .map(exhibit -> toHomeExhibitListResponse(exhibit, favorites.contains(exhibit.getExhibitId()))) .toList(); Long nextCursor = slice.hasNext() @@ -35,7 +35,7 @@ public FilterResponse toFilterResponse(Slice slice) { } - public HomeListResponse toHomeExhibitListResponse(Exhibit exhibit){ + public HomeListResponse toHomeExhibitListResponse(Exhibit exhibit, boolean isFavorite) { String period = exhibit.getStartDate().format(formatter) + " - " + exhibit.getEndDate().format(formatter); @@ -45,10 +45,11 @@ public HomeListResponse toHomeExhibitListResponse(Exhibit exhibit){ .posterUrl(exhibit.getPosterUrl()) .status(exhibit.getStatus()) .exhibitPeriod(period) + .isFavorite(isFavorite) .build(); } - public ExhibitDetailResponse toHomeExhibitResponse(Exhibit exhibit) { + public ExhibitDetailResponse toHomeExhibitResponse(Exhibit exhibit, boolean isFavorite) { var hall = exhibit.getExhibitHall(); String period = exhibit.getStartDate().format(formatter) + " - " + exhibit.getEndDate().format(formatter); @@ -64,13 +65,13 @@ public ExhibitDetailResponse toHomeExhibitResponse(Exhibit exhibit) { .ticketUrl(exhibit.getTicketUrl()) .status(exhibit.getStatus()) .exhibitPeriod(period) - .hallName(hall != null ? hall.getName() : null)// exhibit과 exhibithall이 연결되어있지않아도 체크 가능 .hallAddress(hall != null ? hall.getAddress() : null) .hallOpeningHours(hall != null ? hall.getOpeningHours() : null) .hallPhone(hall != null ? hall.getPhone() : null) .hallLatitude(lat) .hallLongitude(lng) + .isFavorite(isFavorite) .build(); } diff --git a/src/main/java/org/atdev/artrip/domain/home/response/HomeListResponse.java b/src/main/java/org/atdev/artrip/domain/home/response/HomeListResponse.java index 2e038fa..b365c8e 100644 --- a/src/main/java/org/atdev/artrip/domain/home/response/HomeListResponse.java +++ b/src/main/java/org/atdev/artrip/domain/home/response/HomeListResponse.java @@ -25,5 +25,19 @@ public class HomeListResponse { private String countryName; private String regionName; + private boolean isFavorite; + + public HomeListResponse(Long exhibit_id, String title, String posterUrl, Status status, + String exhibitPeriod, String hallName, String countryName, String regionName) { + this.exhibit_id = exhibit_id; + this.title = title; + this.posterUrl = posterUrl; + this.status = status; + this.exhibitPeriod = exhibitPeriod; + this.hallName = hallName; + this.countryName = countryName; + this.regionName = regionName; + this.isFavorite = false; + } } diff --git a/src/main/java/org/atdev/artrip/domain/home/service/HomeService.java b/src/main/java/org/atdev/artrip/domain/home/service/HomeService.java index 9a29c5c..d90c3b9 100644 --- a/src/main/java/org/atdev/artrip/domain/home/service/HomeService.java +++ b/src/main/java/org/atdev/artrip/domain/home/service/HomeService.java @@ -5,6 +5,7 @@ import org.atdev.artrip.domain.exhibit.data.Exhibit; import org.atdev.artrip.domain.exhibit.web.dto.request.ExhibitFilterRequest; import org.atdev.artrip.domain.exhibitHall.repository.ExhibitHallRepository; +import org.atdev.artrip.domain.favortie.repository.FavoriteExhibitRepository; import org.atdev.artrip.domain.home.converter.HomeConverter; import org.atdev.artrip.domain.home.response.FilterResponse; @@ -22,7 +23,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Collections; import java.util.List; +import java.util.Set; @Service @RequiredArgsConstructor @@ -33,8 +36,14 @@ public class HomeService { private final ExhibitHallRepository exhibitHallRepository; private final UserRepository userRepository; private final HomeConverter homeConverter; + private final FavoriteExhibitRepository favoriteExhibitRepository; - + private Set getFavoriteIds(Long userId) { + if (userId == null) { + return Collections.emptySet(); + } + return favoriteExhibitRepository.findActiveExhibitIds(userId); + } // // 큐레이션 전시 // public List getCuratedExhibits() { @@ -44,6 +53,9 @@ public class HomeService { // .toList(); // } + private void setFavorites(List result, Set favoriteIds) { + result.forEach(r -> r.setFavorite(favoriteIds.contains(r.getExhibit_id()))); + } // 장르 전체 조회 public List getAllGenres() { @@ -62,11 +74,11 @@ public List getDomestic(){ //필터 전체 조회 - public FilterResponse getFilterExhibit(ExhibitFilterRequest dto, Pageable pageable, Long cursorId) { + public FilterResponse getFilterExhibit(ExhibitFilterRequest dto, Pageable pageable, Long cursorId, Long userId) { Slice slice = exhibitRepository.findExhibitByFilters(dto, pageable, cursorId); - - return homeConverter.toFilterResponse(slice); + Set favoriteIds = getFavoriteIds(userId); + return homeConverter.toFilterResponse(slice, favoriteIds); } // 사용자 맞춤 전시 랜덤 추천 @@ -89,6 +101,9 @@ public List getRandomPersonalized(Long userId, PersonalizedReq List results = exhibitRepository.findRandomExhibits(filter); + Set favoriteIds = getFavoriteIds(userId); + setFavorites(results, favoriteIds); + adjustLocationFields( results, request.getIsDomestic(), @@ -100,11 +115,14 @@ public List getRandomPersonalized(Long userId, PersonalizedReq } // 이번주 랜덤 전시 추천 - public List getRandomSchedule(ScheduleRandomRequest request){ + public List getRandomSchedule(ScheduleRandomRequest request, Long userId){ RandomExhibitRequest filter = homeConverter.from(request); List results = exhibitRepository.findRandomExhibits(filter); + Set favoriteIds = getFavoriteIds(userId); + setFavorites(results, favoriteIds); + adjustLocationFields( results, request.getIsDomestic(), @@ -116,12 +134,15 @@ public List getRandomSchedule(ScheduleRandomRequest request){ } // 장르별 전시 랜덤 추천 - public List getRandomGenre(GenreRandomRequest request){ + public List getRandomGenre(GenreRandomRequest request, Long userId){ RandomExhibitRequest filter = homeConverter.fromGenre(request); List results = exhibitRepository.findRandomExhibits(filter); + Set favoriteIds = getFavoriteIds(userId); + setFavorites(results, favoriteIds); + adjustLocationFields( results, request.getIsDomestic(), @@ -133,12 +154,15 @@ public List getRandomGenre(GenreRandomRequest request){ } // 오늘날 전시 랜덤 추천 - public List getRandomToday(TodayRandomRequest request){ + public List getRandomToday(TodayRandomRequest request, Long userId){ RandomExhibitRequest filter = homeConverter.fromToday(request); List results = exhibitRepository.findRandomExhibits(filter); + Set favoriteIds = getFavoriteIds(userId); + setFavorites(results, favoriteIds); + adjustLocationFields( results, request.getIsDomestic(), diff --git a/src/main/java/org/atdev/artrip/domain/home/web/controller/HomeController.java b/src/main/java/org/atdev/artrip/domain/home/web/controller/HomeController.java index 109d67b..74a29c7 100644 --- a/src/main/java/org/atdev/artrip/domain/home/web/controller/HomeController.java +++ b/src/main/java/org/atdev/artrip/domain/home/web/controller/HomeController.java @@ -81,9 +81,11 @@ public ResponseEntity>> getRandomPersonali ) @PostMapping("/schedule") public ResponseEntity>> getRandomSchedule( - @Valid @RequestBody ScheduleRandomRequest request){ + @Valid @RequestBody ScheduleRandomRequest request, + @AuthenticationPrincipal UserDetails userDetails){ - List exhibits= homeService.getRandomSchedule(request); + Long userId = Long.parseLong(userDetails.getUsername()); + List exhibits= homeService.getRandomSchedule(request, userId); return ResponseEntity.ok(CommonResponse.onSuccess(exhibits)); } @@ -112,9 +114,11 @@ public ResponseEntity>> getRandomSchedule( ) @PostMapping("/genre/random") public ResponseEntity>> getRandomExhibits( - @Valid @RequestBody GenreRandomRequest request){ + @Valid @RequestBody GenreRandomRequest request, + @AuthenticationPrincipal UserDetails userDetails){ - List exhibits = homeService.getRandomGenre(request); + Long userId = Long.parseLong(userDetails.getUsername()); + List exhibits = homeService.getRandomGenre(request, userId); return ResponseEntity.ok(CommonResponse.onSuccess(exhibits)); } @@ -140,9 +144,11 @@ public ResponseEntity>> getRandomExhibits( ) @PostMapping("recommend/today") public ResponseEntity>> getTodayRecommendations( - @Valid @RequestBody TodayRandomRequest request){ + @Valid @RequestBody TodayRandomRequest request, + @AuthenticationPrincipal UserDetails userDetails){ - List exhibits = homeService.getRandomToday(request); + Long userId = Long.parseLong(userDetails.getUsername()); + List exhibits = homeService.getRandomToday(request, userId); return ResponseEntity.ok(CommonResponse.onSuccess(exhibits)); }