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

@ -251,7 +251,49 @@ public class AnalyticsService implements AnalyticsUseCase {
throw new RuntimeException("AI 피드백 요약 조회에 실패했습니다.", e); throw new RuntimeException("AI 피드백 요약 조회에 실패했습니다.", e);
} }
} }
@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 @Override
public ReviewAnalysisResponse getReviewAnalysis(Long storeId, int days) { public ReviewAnalysisResponse getReviewAnalysis(Long storeId, int days) {
log.info("리뷰 분석 조회 시작: storeId={}", storeId); log.info("리뷰 분석 조회 시작: storeId={}", storeId);

View File

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

View File

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

View File

@ -64,7 +64,7 @@ public class AnalyticsController {
return ResponseEntity.ok(SuccessResponse.of(response, "AI 피드백 상세 조회 성공")); return ResponseEntity.ok(SuccessResponse.of(response, "AI 피드백 상세 조회 성공"));
} }
/** /**
* 매장 통계 조회 * 매장 통계 조회
*/ */
@ -102,6 +102,24 @@ public class AnalyticsController {
return ResponseEntity.ok(SuccessResponse.of(response, "AI 피드백 요약 조회 성공")); 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 = "긍정적인 리뷰 요약") @Schema(description = "긍정적인 리뷰 요약")
private String positiveSummary; private String positiveSummary;
@Schema(description = "분석된 총 리뷰 수")
private Integer totalReviewsAnalyzed;
@Schema(description = "분석 일시") @Schema(description = "분석 일시")
private LocalDateTime analyzedAt; private LocalDateTime analyzedAt;
} }

View File

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