Skip to content

Commit

Permalink
Merge pull request #80 from everymeals/feature/store-get-detail
Browse files Browse the repository at this point in the history
[feature/store-get-detail] 주변 식당 리뷰 조회 기능을 개발
  • Loading branch information
Qbeom0925 authored Jan 26, 2024
2 parents c88cedc + 7f38b1d commit ba26d8e
Show file tree
Hide file tree
Showing 17 changed files with 414 additions and 4 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ dependencies {
implementation 'org.hibernate.orm:hibernate-core:6.2.5.Final'

//QueryDSL
// implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
Expand Down
103 changes: 102 additions & 1 deletion src/main/java/everymeal/server/global/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package everymeal.server.global.config;


import everymeal.server.global.exception.ExceptionList;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
Expand Down Expand Up @@ -28,7 +29,107 @@ public OpenAPI openAPI() {
.description(
"""
EveryMeal API 명세서입니다.<br>
스웨거 한계로 인해 Response에 공통 response의 data에 대한 정의가 되어있습니다. <br>""");
스웨거 한계로 인해 Response에 공통 response의 data에 대한 정의가 되어있습니다. <br>
<details>
<summary> ERROR LIST </summary>
<table>
<thead>
<tr>
<th>ERROR CODE</th>
<th>STATUS</th>
<th>ERROR MESSAGE</th>
</tr>
</thead>
<tbody>
"""
+ getErrorList()
+ """
</tbody>
<table>
</details>
""");
return new OpenAPI().components(new Components()).info(info);
}

// @Bean
// public OperationCustomizer customize(){
// return (Operation operation, HandlerMethod handlerMethod) -> {
// ApiErrorCodeExample apiErrorCodeExample =
// handlerMethod.getMethodAnnotation(ApiErrorCodeExample.class);
// // ApiErrorCodeExample 어노테이션 단 메소드 적용
// if (apiErrorCodeExample != null) {
// generateErrorCodeResponseExample(operation, apiErrorCodeExample.value());
// }
// return operation;
// };
// }
//
// private void generateErrorCodeResponseExample(
// Operation operation, Class<? extends BaseExceptionList> type) {
// ApiResponses responses = operation.getResponses();
// // 해당 이넘에 선언된 에러코드들의 목록을 가져옵니다.
// BaseExceptionList[] errorCodes = type.getEnumConstants();
// // 400, 401, 404 등 에러코드의 상태코드들로 리스트로 모읍니다.
// // 400 같은 상태코드에 여러 에러코드들이 있을 수 있습니다.
// Map<String, List<ExampleHolder>> statusWithExampleHolders =
// Arrays.stream(errorCodes)
// .map(
// baseErrorCode -> {
// try {
// ApplicationException errorReason = baseErrorCode.getErrorReason();
// return ExampleHolder.builder()
// .holder(
// getSwaggerExample(
// baseErrorCode.getExplainError(),
// errorReason))
// .code(errorReason.getErrorCode())
// .name(errorReason.getMessage())
// .build();
// } catch (NoSuchFieldException e) {
// throw new RuntimeException(e);
// }
// })
// .collect(groupingBy(ExampleHolder::getCode));
// // response 객체들을 responses 에 넣습니다.
// addExamplesToResponses(responses, statusWithExampleHolders);
// }
//
// private Example getSwaggerExample(String value, ApplicationException errorReason) {
// //ErrorResponse 는 클라이언트한 실제 응답하는 공통 에러 응답 객체입니다.
// Example example = new Example();
// example.description(value);
// example.setValue(ApplicationErrorResponse.error(errorReason));
// return example;
// }
//
// private void addExamplesToResponses(
// ApiResponses responses, Map<String, List<ExampleHolder>> statusWithExampleHolders) {
// statusWithExampleHolders.forEach(
// (status, v) -> {
// Content content = new Content();
// MediaType mediaType = new MediaType();
// ApiResponse apiResponse = new ApiResponse();
// v.forEach(
// exampleHolder -> {
// mediaType.addExamples(
// exampleHolder.getName(), exampleHolder.getHolder());
// });
// content.addMediaType("application/json", mediaType);
// apiResponse.setContent(content);
// responses.addApiResponse(status, apiResponse);
// });
// }

private String getErrorList() {
StringBuilder errorList = new StringBuilder();
ExceptionList[] exceptionLists = ExceptionList.values();
for (ExceptionList exceptionList : exceptionLists) {
errorList.append("<tr>");
errorList.append("<td>").append(exceptionList.getCODE()).append("</td>");
errorList.append("<td>").append(exceptionList.getHttpStatus()).append("</td>");
errorList.append("<td>").append(exceptionList.getMESSAGE()).append("</td>");
errorList.append("</tr>");
}
return errorList.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ public ApplicationException(ExceptionList exceptionList) {
this.httpStatus = exceptionList.getHttpStatus();
}

public ApplicationException(String code, HttpStatus status, String message) {
super(message);
this.errorCode = code;
this.httpStatus = status;
}

public ApplicationException(String message) {
super(message);
this.errorCode = "INTERNAL_SERVER_ERROR";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package everymeal.server.global.util.swagger;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
public @interface ApiErrorCodeExample {
Class<? extends BaseExceptionList> value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package everymeal.server.global.util.swagger;


import everymeal.server.global.exception.ApplicationException;

public interface BaseExceptionList {

public ApplicationException getErrorReason();

String getExplainError() throws NoSuchFieldException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package everymeal.server.global.util.swagger;


import io.swagger.v3.oas.models.examples.Example;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class ExampleHolder {
private Example holder;
private String name;
private String code;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package everymeal.server.global.util.swagger;


import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.stereotype.Component;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ExplainError {
String value() default "";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package everymeal.server.global.util.swagger;


import everymeal.server.global.exception.ApplicationException;
import java.lang.reflect.Field;
import java.util.Objects;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum UserExceptionList implements BaseExceptionList {
USER_NOTFOUND("USR0001", HttpStatus.NOT_FOUND, "등록된 유저가 아닙니다."),
;

public final String CODE;
public final HttpStatus httpStatus;
public final String MESSAGE;

@Override
public ApplicationException getErrorReason() {
return new ApplicationException(getCODE(), getHttpStatus(), getMESSAGE());
}

@Override
public String getExplainError() throws NoSuchFieldException {
Field field = this.getClass().getField(this.name());
ExplainError annotation = field.getAnnotation(ExplainError.class);
return Objects.nonNull(annotation) ? annotation.value() : this.getMESSAGE();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ public static ReviewTodayGetRes of(Map<String, Object> resultMap) {
(Long) resultMap.get("reviewIdx"), (String) resultMap.get("content"));
}

public record ReviewGetRes(int reviewTotalCnt, List<ReviewPaging> reviewPagingList) {}
public record ReviewGetRes(int reviewTotalCnt, List<ReviewPaging> reviewPagingList) {

public static List<ReviewGetRes> of(List<Map<String, Object>> storeReview) {
return null;
}
}

public record ReviewPaging(
Long reviewIdx,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import everymeal.server.global.util.authresolver.entity.AuthenticatedUser;
import everymeal.server.store.controller.dto.response.LikedStoreGetRes;
import everymeal.server.store.controller.dto.response.StoreGetRes;
import everymeal.server.store.controller.dto.response.StoreGetReviewRes;
import everymeal.server.store.service.StoreService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
Expand Down Expand Up @@ -205,4 +206,29 @@ public ApplicationResponse<StoreGetRes> getStore(
storeService.getStore(
storeIdx, authenticatedUser == null ? null : authenticatedUser.getIdx()));
}

@Auth(require = false)
@GetMapping("/{index}/reviews")
@SecurityRequirement(name = "jwt-user-auth")
@Operation(summary = "식당 리뷰 조회", description = "식당 리뷰를 조회합니다")
public ApplicationResponse<Page<StoreGetReviewRes>> getStoreReview(
@PathVariable(value = "index")
@Schema(title = "식당 키 값", description = "식당 키 값", example = "1")
Long storeIdx,
@Parameter(hidden = true) @AuthUser AuthenticatedUser authenticatedUser,
@RequestParam(value = "offset", defaultValue = "0")
@Schema(title = "페이지 번호", example = "0", description = "페이지 번호는 0부터 시작합니다.")
Integer offset,
@RequestParam(value = "limit", defaultValue = "10")
@Schema(
title = "Data 갯수",
example = "10",
description = "한 페이지에 보여지는 데이터 수 입니다.")
Integer limit) {
return ApplicationResponse.ok(
storeService.getStoreReview(
storeIdx,
authenticatedUser == null ? null : authenticatedUser.getIdx(),
PageRequest.of(offset, limit)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package everymeal.server.store.controller.dto.response;


import everymeal.server.global.util.aws.S3Util;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public record StoreGetReviewRes(
Integer reviewIdx,
String content,
Integer grade,
LocalDateTime createdAt,
String nickName,
String profileImageUrl,
Integer recommendedCount,
List<String> images) {

public static List<StoreGetReviewRes> of(List<Map<String, Object>> storeReview) {
return storeReview.stream()
.map(
review -> {
List<String> images = null;
if (review.get("images") != null) {
images = Arrays.asList(((String) review.get("images")).split(","));
images.replaceAll(S3Util::getImgUrl);
}
return new StoreGetReviewRes(
(Integer) review.get("reviewIdx"),
(String) review.get("content"),
(Integer) review.get("grade"),
(LocalDateTime) review.get("createdAt"),
(String) review.get("nickName"),
(String) review.get("profileImageUrl"),
(Integer) review.get("recommendedCount"),
images);
})
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@ Long getUserLikesStoreCount(
List<Map<String, Object>> getStoresKeyword(Map<String, Object> parameter);

Long getStoresKeywordCnt(Map<String, Object> parameter);

List<Map<String, Object>> getStoreReview(Map<String, Object> parameter);

Long getStoreReviewCnt(Map<String, Object> parameter);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import everymeal.server.store.controller.dto.response.LikedStoreGetRes;
import everymeal.server.store.controller.dto.response.StoreGetRes;
import everymeal.server.store.controller.dto.response.StoreGetReviewRes;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
Expand All @@ -21,4 +22,6 @@ Page<LikedStoreGetRes> getUserLikesStore(

Page<StoreGetRes> getStoresKeyword(
Long campusIdx, String keyword, Long idx, PageRequest pageRequest);

Page<StoreGetReviewRes> getStoreReview(Long storeIdx, Long aLong, PageRequest of);
}
18 changes: 18 additions & 0 deletions src/main/java/everymeal/server/store/service/StoreServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import everymeal.server.review.repository.ImageRepository;
import everymeal.server.store.controller.dto.response.LikedStoreGetRes;
import everymeal.server.store.controller.dto.response.StoreGetRes;
import everymeal.server.store.controller.dto.response.StoreGetReviewRes;
import everymeal.server.store.entity.Store;
import everymeal.server.store.repository.StoreMapper;
import everymeal.server.store.repository.StoreRepository;
Expand Down Expand Up @@ -146,4 +147,21 @@ public Page<StoreGetRes> getStoresKeyword(
List<StoreGetRes> result = StoreGetRes.of(storesKeyword);
return new PageImpl<>(result, pageRequest, storesKeywordCnt);
}

@Override
public Page<StoreGetReviewRes> getStoreReview(
Long storeIdx, Long userIdx, PageRequest pageRequest) {
Map<String, Object> parameter = new HashMap<>();
parameter.put("storeIdx", storeIdx);
parameter.put("userIdx", userIdx);
parameter.put("limit", pageRequest.getPageSize());
parameter.put("offset", pageRequest.getOffset());

List<Map<String, Object>> storeReview = storeMapper.getStoreReview(parameter);
Long storeReviewCnt = storeMapper.getStoreReviewCnt(parameter);

List<StoreGetReviewRes> result = StoreGetReviewRes.of(storeReview);

return new PageImpl<>(result, pageRequest, storeReviewCnt);
}
}
Loading

0 comments on commit ba26d8e

Please sign in to comment.