feat : 리뷰 조회 추가

This commit is contained in:
lsh9672 2025-06-18 13:25:12 +09:00
parent 2eefb269e6
commit 458f532b31
9 changed files with 159 additions and 48 deletions

View File

@ -18,6 +18,7 @@ public interface ExternalReviewPort {
*/
List<String> getRecentReviews(Long storeId, Integer days);
/**
* 리뷰 개수 조회
*/

View File

@ -97,6 +97,28 @@ public class ReviewInteractor implements CreateReviewUseCase, DeleteReviewUseCas
.collect(Collectors.toList());
}
@Override
public List<ReviewListResponse> getStoreRecentReviews(Long storeId, Integer page, Integer size, Integer days) {
Pageable pageable = PageRequest.of(page != null ? page : 0, size == null || size == 0 ? 1000 : size);
LocalDateTime cutoffDate = LocalDateTime.now().minusDays(days);
Page<Review> reviews = reviewRepository.findRecentReviewsByStoreId(storeId, pageable, cutoffDate);
return reviews.stream()
.filter(review -> review.getStatus() == ReviewStatus.ACTIVE)
.map(review -> ReviewListResponse.builder()
.reviewId(review.getId())
.memberNickname(review.getMemberNickname())
.rating(review.getRating())
.content(review.getContent())
.imageUrls(review.getImageUrls())
.likeCount(review.getLikeCount())
.dislikeCount(review.getDislikeCount())
.createdAt(review.getCreatedAt())
.build())
.collect(Collectors.toList());
}
@Override
@Transactional(readOnly = true)
public ReviewDetailResponse getReviewDetail(Long reviewId) {

View File

@ -16,6 +16,11 @@ public interface GetReviewUseCase {
*/
List<ReviewListResponse> getStoreReviews(Long storeId, Integer page, Integer size);
/**
* 매장 최근 리뷰 목록 조회
*/
List<ReviewListResponse> getStoreRecentReviews(Long storeId, Integer page, Integer size, Integer days);
/**
* 리뷰 상세 조회
*/

View File

@ -3,7 +3,9 @@ package com.ktds.hi.review.biz.usecase.out;
import com.ktds.hi.review.biz.domain.Review;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.query.Param;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@ -34,6 +36,11 @@ public interface ReviewRepository {
*/
Page<Review> findReviewsByStoreIdOrderByCreatedAtDesc(Long storeId, Pageable pageable);
/**
* 매장 ID와 일자 데이터로 최근 리뷰 목록 조회
*/
Page<Review> findRecentReviewsByStoreId(Long storeId, Pageable pageable, @Param("cutoffDate") LocalDateTime cutoffDate);
/**
* 회원 ID로 리뷰 목록 조회
*/

View File

@ -53,6 +53,24 @@ public class ReviewController {
return ResponseEntity.ok(reviews);
}
/**
* 최근 매장 리뷰 목록 조회 API
*/
@GetMapping("/stores/recent/{storeId}")
@Operation(summary = "매장 최근 리뷰 목록 조회", description = "특정 매장의 최근 리뷰 목록을 조회합니다.")
public ResponseEntity<List<ReviewListResponse>> getStoreRecentReviews(
@PathVariable Long storeId,
@RequestParam(defaultValue = "0") Integer page,
@RequestParam(defaultValue = "0") Integer size,
@RequestParam Integer days
) {
List<ReviewListResponse> reviews = getReviewUseCase.getStoreRecentReviews(storeId, page, size, days);
return ResponseEntity.ok(reviews);
}
/**
* 리뷰 상세 조회 API
*/

View File

@ -10,6 +10,7 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Optional;
/**
@ -48,6 +49,16 @@ public class ReviewRepositoryAdapter implements ReviewRepository {
return entities.map(this::toDomain);
}
@Override
public Page<Review> findRecentReviewsByStoreId(Long storeId, Pageable pageable,
LocalDateTime cutoffDate) {
Page<ReviewEntity> entities = reviewJpaRepository.findRecentReviewsByStoreId(storeId, ReviewStatus.ACTIVE,
cutoffDate,pageable);
return entities.map(this::toDomain);
}
@Override
public Page<Review> findReviewsByMemberId(Long memberId, Pageable pageable) {
Page<ReviewEntity> entities = reviewJpaRepository.findByMemberIdAndStatus(memberId, ReviewStatus.ACTIVE, pageable);

View File

@ -9,6 +9,7 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.time.LocalDateTime;
import java.util.Optional;
/**
@ -28,6 +29,17 @@ public interface ReviewJpaRepository extends JpaRepository<ReviewEntity, Long> {
*/
Page<ReviewEntity> findByMemberIdAndStatus(Long memberId, ReviewStatus status, Pageable pageable);
@Query("SELECT r FROM ReviewEntity r WHERE r.storeId = :storeId " +
"AND r.status = :status " +
"AND (CAST(:cutoffDate AS TIMESTAMP) IS NULL OR r.createdAt >= :cutoffDate) " +
"ORDER BY r.createdAt DESC")
Page<ReviewEntity> findRecentReviewsByStoreId(
@Param("storeId") Long storeId,
@Param("status") ReviewStatus status,
@Param("cutoffDate") LocalDateTime cutoffDate,
Pageable pageable
);
/**
* 리뷰 ID와 회원 ID로 리뷰 조회
*/

View File

@ -5,4 +5,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'com.azure:azure-messaging-eventhubs:5.15.0'
implementation 'com.azure:azure-storage-blob:12.22.1'
implementation 'com.azure:azure-storage-common:12.21.1'
}

View File

@ -0,0 +1,32 @@
package com.ktds.hi.store.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.azure.storage.blob.BlobServiceClient;
import com.azure.storage.blob.BlobServiceClientBuilder;
import lombok.extern.slf4j.Slf4j;
/**
* Azure Blob Storage 설정
*
* @author 하이오더 개발팀
* @version 1.0.0
*/
@Slf4j
// @Configuration
public class AzureStorageConfig {
@Value("${azure.storage.connection-string}")
private String connectionString;
@Bean
public BlobServiceClient blobServiceClient() {
log.info("Azure Blob Storage 클라이언트 초기화");
return new BlobServiceClientBuilder()
.connectionString(connectionString)
.buildClient();
}
}