feat : 리뷰 조회 추가
This commit is contained in:
@@ -96,7 +96,29 @@ public class ReviewInteractor implements CreateReviewUseCase, DeleteReviewUseCas
|
||||
.build())
|
||||
.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) {
|
||||
|
||||
@@ -15,6 +15,11 @@ public interface GetReviewUseCase {
|
||||
* 매장 리뷰 목록 조회
|
||||
*/
|
||||
List<ReviewListResponse> getStoreReviews(Long storeId, Integer page, Integer size);
|
||||
|
||||
/**
|
||||
* 매장 최근 리뷰 목록 조회
|
||||
*/
|
||||
List<ReviewListResponse> getStoreRecentReviews(Long storeId, Integer page, Integer size, Integer days);
|
||||
|
||||
/**
|
||||
* 리뷰 상세 조회
|
||||
|
||||
@@ -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로 리뷰 목록 조회
|
||||
*/
|
||||
|
||||
@@ -52,6 +52,24 @@ public class ReviewController {
|
||||
List<ReviewListResponse> reviews = getReviewUseCase.getStoreReviews(storeId, page, size);
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
@@ -47,7 +48,17 @@ public class ReviewRepositoryAdapter implements ReviewRepository {
|
||||
pageable);
|
||||
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);
|
||||
|
||||
+58
-46
@@ -1,46 +1,58 @@
|
||||
package com.ktds.hi.review.infra.gateway.repository;
|
||||
|
||||
import com.ktds.hi.review.biz.domain.ReviewStatus;
|
||||
import com.ktds.hi.review.infra.gateway.entity.ReviewEntity;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 리뷰 JPA 리포지토리 인터페이스
|
||||
* 리뷰 데이터의 CRUD 작업을 담당
|
||||
*/
|
||||
@Repository
|
||||
public interface ReviewJpaRepository extends JpaRepository<ReviewEntity, Long> {
|
||||
|
||||
/**
|
||||
* 매장 ID와 상태로 리뷰 목록 조회
|
||||
*/
|
||||
Page<ReviewEntity> findByStoreIdAndStatus(Long storeId, ReviewStatus status, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 회원 ID와 상태로 리뷰 목록 조회
|
||||
*/
|
||||
Page<ReviewEntity> findByMemberIdAndStatus(Long memberId, ReviewStatus status, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 리뷰 ID와 회원 ID로 리뷰 조회
|
||||
*/
|
||||
Optional<ReviewEntity> findByIdAndMemberId(Long id, Long memberId);
|
||||
|
||||
|
||||
/**
|
||||
* ✅ 수정: 매장ID + 내용으로 중복 리뷰 체크
|
||||
*/
|
||||
boolean existsByStoreIdAndContent(Long storeId, String content);
|
||||
|
||||
/**
|
||||
* 대안: 외부 닉네임으로만 중복 체크 (더 간단한 방법)
|
||||
*/
|
||||
// boolean existsByStoreIdAndExternalNickname(Long storeId, String externalNickname);
|
||||
}
|
||||
package com.ktds.hi.review.infra.gateway.repository;
|
||||
|
||||
import com.ktds.hi.review.biz.domain.ReviewStatus;
|
||||
import com.ktds.hi.review.infra.gateway.entity.ReviewEntity;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 리뷰 JPA 리포지토리 인터페이스
|
||||
* 리뷰 데이터의 CRUD 작업을 담당
|
||||
*/
|
||||
@Repository
|
||||
public interface ReviewJpaRepository extends JpaRepository<ReviewEntity, Long> {
|
||||
|
||||
/**
|
||||
* 매장 ID와 상태로 리뷰 목록 조회
|
||||
*/
|
||||
Page<ReviewEntity> findByStoreIdAndStatus(Long storeId, ReviewStatus status, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 회원 ID와 상태로 리뷰 목록 조회
|
||||
*/
|
||||
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로 리뷰 조회
|
||||
*/
|
||||
Optional<ReviewEntity> findByIdAndMemberId(Long id, Long memberId);
|
||||
|
||||
|
||||
/**
|
||||
* ✅ 수정: 매장ID + 내용으로 중복 리뷰 체크
|
||||
*/
|
||||
boolean existsByStoreIdAndContent(Long storeId, String content);
|
||||
|
||||
/**
|
||||
* 대안: 외부 닉네임으로만 중복 체크 (더 간단한 방법)
|
||||
*/
|
||||
// boolean existsByStoreIdAndExternalNickname(Long storeId, String externalNickname);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user