diff --git a/src/main/java/com/sumte/guesthouse/controller/GuesthouseController.java b/src/main/java/com/sumte/guesthouse/controller/GuesthouseController.java index 4dd361e..62c3f82 100644 --- a/src/main/java/com/sumte/guesthouse/controller/GuesthouseController.java +++ b/src/main/java/com/sumte/guesthouse/controller/GuesthouseController.java @@ -209,4 +209,12 @@ public ResponseEntity>> searchGuesthouse( } + @GetMapping("/guesthouses/{guesthouseId}/summary") + @Operation( + summary = "게스트하우스 요약 조회", + description = "게스트하우스 ID를 기반으로 게스트하우스 상세정보를 조회합니다.") + public ApiResponse getGuesthouseSummary(@PathVariable Long guesthouseId) { + return ApiResponse.success(guesthouseQueryService.getGuesthouseSummary(guesthouseId)); + } + } \ No newline at end of file diff --git a/src/main/java/com/sumte/guesthouse/converter/GuesthouseConverter.java b/src/main/java/com/sumte/guesthouse/converter/GuesthouseConverter.java index eaccc59..3b96da9 100644 --- a/src/main/java/com/sumte/guesthouse/converter/GuesthouseConverter.java +++ b/src/main/java/com/sumte/guesthouse/converter/GuesthouseConverter.java @@ -56,4 +56,25 @@ public GuesthouseResponseDTO.HomeSummary toHomeSummary( .isAd(guesthouse.getAdvertisement() == AdType.AD) .build(); } + + public GuesthouseResponseDTO.HomeCard toHomeCardResponse( + Guesthouse guesthouse, + Long minPrice, + String earliestCheckin, + Long reviewCount, + Double averageScore, + String imageUrl + ) { + return GuesthouseResponseDTO.HomeCard.builder() + .id(guesthouse.getId()) + .name(guesthouse.getName()) + .addressRegion(guesthouse.getAddressRegion()) + .addressDetail(guesthouse.getAddressDetail()) + .minPrice(minPrice) + .checkin(earliestCheckin) + .reviewCount(reviewCount) + .averageScore(averageScore) + .imageUrl(imageUrl) + .build(); + } } diff --git a/src/main/java/com/sumte/guesthouse/dto/GuesthouseResponseDTO.java b/src/main/java/com/sumte/guesthouse/dto/GuesthouseResponseDTO.java index 1303db6..74d2c29 100644 --- a/src/main/java/com/sumte/guesthouse/dto/GuesthouseResponseDTO.java +++ b/src/main/java/com/sumte/guesthouse/dto/GuesthouseResponseDTO.java @@ -78,4 +78,20 @@ public static class HomeSummary { private boolean isAd; } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class HomeCard { + private Long id; + private String name; + private String addressRegion; + private String addressDetail; + private String imageUrl; + private Long minPrice; + private String checkin; + private Long reviewCount; + private Double averageScore; + } + } diff --git a/src/main/java/com/sumte/guesthouse/repository/GuesthouseRepository.java b/src/main/java/com/sumte/guesthouse/repository/GuesthouseRepository.java index eb0c592..f3aa2ac 100644 --- a/src/main/java/com/sumte/guesthouse/repository/GuesthouseRepository.java +++ b/src/main/java/com/sumte/guesthouse/repository/GuesthouseRepository.java @@ -6,6 +6,7 @@ import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import com.sumte.guesthouse.entity.Guesthouse; @@ -26,4 +27,11 @@ public interface GuesthouseRepository extends JpaRepository { //리뷰는 Page로 했는데 Slice로 수정해도 괜찮을거 같음 (확인 -> 전체 요소수는 필요없으니) Slice findAllOrderedForHome(Pageable pageable); + + //홈카드용 + @Query("SELECT COUNT(r) FROM Review r WHERE r.room.guesthouse.id = :guesthouseId") + Long countByGuesthouseId(@Param("guesthouseId") Long guesthouseId); + + @Query("SELECT AVG(r.score) FROM Review r WHERE r.room.guesthouse.id = :guesthouseId") + Double findAverageScoreByGuesthouseId(@Param("guesthouseId") Long guesthouseId); } diff --git a/src/main/java/com/sumte/guesthouse/service/GuesthouseQueryService.java b/src/main/java/com/sumte/guesthouse/service/GuesthouseQueryService.java index b7c61e1..b481574 100644 --- a/src/main/java/com/sumte/guesthouse/service/GuesthouseQueryService.java +++ b/src/main/java/com/sumte/guesthouse/service/GuesthouseQueryService.java @@ -15,4 +15,6 @@ public interface GuesthouseQueryService { Page getFilteredGuesthouse(GuesthouseSearchRequestDTO dto, Pageable pageable); Slice getGuesthousesForHome(Pageable pageable); + + GuesthouseResponseDTO.HomeCard getGuesthouseSummary(Long guesthouseId); } diff --git a/src/main/java/com/sumte/guesthouse/service/GuesthouseQueryServiceImpl.java b/src/main/java/com/sumte/guesthouse/service/GuesthouseQueryServiceImpl.java index a0aa4ff..cd485a4 100644 --- a/src/main/java/com/sumte/guesthouse/service/GuesthouseQueryServiceImpl.java +++ b/src/main/java/com/sumte/guesthouse/service/GuesthouseQueryServiceImpl.java @@ -13,9 +13,11 @@ import org.springframework.data.domain.Slice; import org.springframework.data.domain.SliceImpl; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import com.sumte.apiPayload.code.error.CommonErrorCode; import com.sumte.apiPayload.exception.SumteException; +import com.sumte.guesthouse.converter.GuesthouseConverter; import com.sumte.guesthouse.dto.GuesthouseDetailDTO; import com.sumte.guesthouse.dto.GuesthousePreviewDTO; import com.sumte.guesthouse.dto.GuesthouseResponseDTO; @@ -34,7 +36,6 @@ import com.sumte.room.entity.Room; import com.sumte.room.repository.RoomRepository; -import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; @Service @@ -48,6 +49,7 @@ public class GuesthouseQueryServiceImpl implements GuesthouseQueryService { private final GuesthouseOptionServicesRepository guesthouseOptionServicesRepository; private final GuesthouseRepositoryCustom guesthouseRepositoryCustom; private final ImageRepository imageRepository; + private final GuesthouseConverter guesthouseConverter; @Override @Transactional @@ -254,4 +256,26 @@ public Page getFilteredGuesthouse(GuesthouseSearchRequestD // 6) PageImpl 으로 감싸서 반환 return new PageImpl<>(dtos, pageable, page.getTotalElements()); } + + @Override + @Transactional(readOnly = true) + public GuesthouseResponseDTO.HomeCard getGuesthouseSummary(Long guesthouseId) { + Guesthouse guesthouse = guesthouseRepository.findById(guesthouseId) + .orElseThrow(() -> new SumteException(CommonErrorCode.NOT_EXIST)); + + Long minPrice = roomRepository.findMinPriceByGuesthouseId(guesthouseId); + String earliestCheckin = roomRepository.findEarliestCheckinByGuesthouseId(guesthouseId); + Long reviewCount = (long)reviewRepository.countByGuesthouseId(guesthouseId); + Double averageScore = reviewRepository.findAverageScoreByGuesthouseId(guesthouseId); + + // 이미지 + List images = imageRepository.findByOwnerTypeAndOwnerIdOrderBySortOrderAsc(OwnerType.GUESTHOUSE, + guesthouseId); + String imageUrl = images.isEmpty() ? null : images.get(0).getUrl(); + + return guesthouseConverter.toHomeCardResponse( + guesthouse, minPrice, earliestCheckin, reviewCount, averageScore, imageUrl + ); + } + } \ No newline at end of file