diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/application/FoodTruckService.java b/src/main/java/konkuk/chacall/domain/foodtruck/application/FoodTruckService.java index 22285d1..0ae4e26 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/application/FoodTruckService.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/application/FoodTruckService.java @@ -92,4 +92,10 @@ public List searchFoodTruckMenus(Long foodTruckId, String return foodTruckMenuService.searchFoodTruckMenus(foodTruckId, keyword, member); } + + public List getTopRatedFoodTrucks(Long memberId) { + memberValidator.validateAndGetMember(memberId); + + return foodTruckInfoService.getTopRatedFoodTrucks(); + } } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java b/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java index 60f6d79..6c208d8 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/application/info/FoodTruckInfoService.java @@ -11,6 +11,7 @@ import konkuk.chacall.domain.foodtruck.presentation.dto.request.UpdateFoodTruckInfoRequest; import konkuk.chacall.domain.foodtruck.presentation.dto.response.FoodTruckDetailResponse; import konkuk.chacall.domain.foodtruck.presentation.dto.response.FoodTruckResponse; +import konkuk.chacall.domain.foodtruck.presentation.dto.response.FoodTruckTopRateResponse; import konkuk.chacall.domain.member.domain.repository.SavedFoodTruckRepository; import konkuk.chacall.domain.region.domain.model.Region; import konkuk.chacall.domain.region.domain.repository.RegionRepository; @@ -19,6 +20,7 @@ import konkuk.chacall.global.common.exception.EntityNotFoundException; import konkuk.chacall.global.common.exception.code.ErrorCode; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; @@ -37,6 +39,8 @@ public class FoodTruckInfoService { private final AvailableDateRepository availableDateRepository; private final RegionRepository regionRepository; + private static final int TOP_RATED_FOOD_TRUCK_LIMIT = 7; + public CursorPagingResponse getFoodTrucks(Long memberId, FoodTruckSearchRequest request) { Slice foodTruckSlice = foodTruckRepository.getFoodTrucks(request); @@ -154,4 +158,10 @@ public FoodTruckDetailResponse getFoodTruckDetails(User member, Long foodTruckId return FoodTruckDetailResponse.from(foodTruck, foodTruckServiceAreas, availableDates, isSaved); } + + public List getTopRatedFoodTrucks() { + return foodTruckRepository.findTopRatedFoodTrucks(PageRequest.of(0, TOP_RATED_FOOD_TRUCK_LIMIT)).stream() + .map(FoodTruckTopRateResponse::from) + .toList(); + } } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckRepository.java b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckRepository.java index a197eb7..ac5be51 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckRepository.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/domain/repository/FoodTruckRepository.java @@ -53,4 +53,13 @@ boolean existsByFoodTruckIdAndOwnerIdAndFoodTruckStatus( @EntityGraph(attributePaths = {"owner"}) List findAll(); + + @Query(""" + select f + from FoodTruck f + where f.foodTruckStatus = 'APPROVED' + and f.foodTruckViewedStatus = 'ON' + order by f.ratingInfo.averageRating desc, f.ratingInfo.ratingCount desc + """) + List findTopRatedFoodTrucks(Pageable pageable); } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java b/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java index c84df2e..2f35a70 100644 --- a/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java +++ b/src/main/java/konkuk/chacall/domain/foodtruck/presentation/FoodTruckController.java @@ -158,4 +158,16 @@ public BaseResponse> searchFoodTruckMenus( ) { return BaseResponse.ok(foodTruckService.searchFoodTruckMenus(foodTruckId, keyword, memberId)); } + + @Operation( + summary = "[홈화면용] 평점 높은 푸드트럭 조회", + description = "평점이 높은 푸드트럭을 조회합니다." + ) + @ExceptionDescription(SwaggerResponseDescription.GET_TOP_RATED_FOOD_TRUCKS) + @GetMapping("/top-rated") + public BaseResponse> getTopRatedFoodTrucks( + @Parameter(hidden = true) @UserId final Long memberId + ) { + return BaseResponse.ok(foodTruckService.getTopRatedFoodTrucks(memberId)); + } } diff --git a/src/main/java/konkuk/chacall/domain/foodtruck/presentation/dto/response/FoodTruckTopRateResponse.java b/src/main/java/konkuk/chacall/domain/foodtruck/presentation/dto/response/FoodTruckTopRateResponse.java new file mode 100644 index 0000000..6b2db54 --- /dev/null +++ b/src/main/java/konkuk/chacall/domain/foodtruck/presentation/dto/response/FoodTruckTopRateResponse.java @@ -0,0 +1,24 @@ +package konkuk.chacall.domain.foodtruck.presentation.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import konkuk.chacall.domain.foodtruck.domain.model.FoodTruck; + +public record FoodTruckTopRateResponse( + @Schema(description = "푸드트럭 식별자", example = "1") + Long foodTruckId, + @Schema(description = "푸드트럭 이름", example = "푸드트럭") + String name, + @Schema(description = "푸드트럭 대표 사진 URL", example = "http://image.png") + String photoUrl, + @Schema(description = "푸드트럭 평균 평점", example = "4.5") + Double averageRating +) { + public static FoodTruckTopRateResponse from(FoodTruck foodTruck) { + return new FoodTruckTopRateResponse( + foodTruck.getFoodTruckId(), + foodTruck.getFoodTruckInfo().getName(), + foodTruck.getFoodTruckInfo().getFoodTruckPhotoList().getMainPhotoUrl(), + foodTruck.getRatingInfo().getAverageRating() + ); + } +} diff --git a/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java b/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java index 437f441..28ef84a 100644 --- a/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java +++ b/src/main/java/konkuk/chacall/global/common/swagger/SwaggerResponseDescription.java @@ -264,6 +264,10 @@ public enum SwaggerResponseDescription { USER_FORBIDDEN, FOOD_TRUCK_STATUS_MISMATCH ))), + GET_TOP_RATED_FOOD_TRUCKS(new LinkedHashSet<>(Set.of( + USER_NOT_FOUND, + USER_FORBIDDEN + ))), // Default DEFAULT(new LinkedHashSet<>())