feat : 고객용 긍정 ai 피드백 정보를 위한 api 추가

This commit is contained in:
lsh9672 2025-06-18 18:17:34 +09:00
parent 227f23922c
commit 6614cf2c4f
6 changed files with 81 additions and 7 deletions

View File

@ -252,6 +252,48 @@ public class AnalyticsService implements AnalyticsUseCase {
}
}
@Override
// @Cacheable(value = "customerPositiveFeedback", key = "#storeId")
public CustomerPositiveReviewResponse getPositiveIFeedbackSummary(Long storeId) {
try {
// 1. 캐시에서 먼저 확인 (타입 안전성 보장)
String cacheKey = "customerPositiveFeedback:store:" + storeId;
var cachedResult = cachePort.getAnalyticsCache(cacheKey);
if (cachedResult.isPresent()) {
Object cached = cachedResult.get();
if (cached instanceof CustomerPositiveReviewResponse) {
log.info("캐시에서 AI 긍정 피드백 반환: storeId={}", storeId);
return (CustomerPositiveReviewResponse) cached;
}
log.debug("AI 긍정 피드백 캐시 데이터 타입 불일치, DB에서 조회: storeId={}", storeId);
}
// 1. 기존 AI 피드백 조회
var aiFeedback = analyticsPort.findPositiveAIFeedbackByStoreId(storeId);
if (aiFeedback.isEmpty()) {
// 2. AI 피드백이 없으면 새로 생성
throw new RuntimeException("AI 긍정 피드백 요약 조회 실패");
}
// 3. 응답 생성
var response = CustomerPositiveReviewResponse.builder()
.storeId(aiFeedback.get().getStoreId())
.positiveSummary(aiFeedback.get().getPositiveSummary())
.analyzedAt(aiFeedback.get().getCreatedAt())
.build();
return response;
} catch (Exception e) {
log.error("AI 피드백 조회 중 오류 발생: storeId={}", storeId, e);
throw new RuntimeException("AI 피드백 조회에 실패했습니다.", e);
}
}
@Override
public ReviewAnalysisResponse getReviewAnalysis(Long storeId, int days) {
log.info("리뷰 분석 조회 시작: storeId={}", storeId);

View File

@ -31,6 +31,12 @@ public interface AnalyticsUseCase {
*/
AiFeedbackSummaryResponse getAIFeedbackSummary(Long storeId);
/**
* AI 긍정 피드백 요약 조회(고객용)
*/
CustomerPositiveReviewResponse getPositiveIFeedbackSummary(Long storeId);
/**
* 리뷰 분석 조회
*/

View File

@ -26,6 +26,12 @@ public interface AnalyticsPort {
*/
Optional<AiFeedback> findAIFeedbackByStoreId(Long storeId);
/**
* 매장 ID로 AI 긍정 피드백 조회(고객용)
*/
Optional<AiFeedback> findPositiveAIFeedbackByStoreId(Long storeId);
/**
* AI 피드백 ID로 조회 (추가된 메서드)
*/

View File

@ -103,6 +103,24 @@ public class AnalyticsController {
return ResponseEntity.ok(SuccessResponse.of(response, "AI 피드백 요약 조회 성공"));
}
/**
* AI 긍정 피드백 요약 조회(고객용)
*/
@Operation(summary = "AI 긍정 피드백 요약 조회", description = "매장의 AI 긍정 피드백 요약 정보를 조회합니다.")
@GetMapping("/stores/{storeId}/customer/summary")
public ResponseEntity<SuccessResponse<CustomerPositiveReviewResponse>> getCustomerAIFeedbackSummary(
@Parameter(description = "매장 ID", required = true)
@PathVariable @NotNull Long storeId) {
log.info("AI 피드백 요약 조회 요청: storeId={}", storeId);
CustomerPositiveReviewResponse response = analyticsUseCase.getPositiveIFeedbackSummary(storeId);
return ResponseEntity.ok(SuccessResponse.of(response, "AI 피드백 요약 조회 성공"));
}
/**
* 리뷰 분석 조회
*/

View File

@ -25,10 +25,6 @@ public class CustomerPositiveReviewResponse {
@Schema(description = "긍정적인 리뷰 요약")
private String positiveSummary;
@Schema(description = "분석된 총 리뷰 수")
private Integer totalReviewsAnalyzed;
@Schema(description = "분석 일시")
private LocalDateTime analyzedAt;
}

View File

@ -49,6 +49,12 @@ public class AnalyticsRepositoryAdapter implements AnalyticsPort {
.map(this::toAiFeedbackDomain);
}
@Override
public Optional<AiFeedback> findPositiveAIFeedbackByStoreId(Long storeId) {
return aiFeedbackJpaRepository.findLatestByStoreId(storeId)
.map(this::toAiFeedbackDomain);
}
@Override
public AiFeedback saveAIFeedback(AiFeedback feedback) {
AiFeedbackEntity entity = toAiFeedbackEntity(feedback);