diff --git a/src/main/java/everymeal/server/meal/controller/dto/response/DayMealGetRes.java b/src/main/java/everymeal/server/meal/controller/dto/response/DayMealGetRes.java index 838af45..ccc7115 100644 --- a/src/main/java/everymeal/server/meal/controller/dto/response/DayMealGetRes.java +++ b/src/main/java/everymeal/server/meal/controller/dto/response/DayMealGetRes.java @@ -32,7 +32,7 @@ public static Map> of(List> meal (String) meal.get("menu"), (Double) meal.get("price"), (String) meal.get("category"), - (Long) meal.get("restaurantIdx"), + (Long) meal.get("idx"), (String) meal.get("restaurantName"), (String) meal.get("universityName"), (Integer) meal.get("reviewCount"), diff --git a/src/main/java/everymeal/server/review/controller/ReviewController.java b/src/main/java/everymeal/server/review/controller/ReviewController.java index 957ce80..63d3500 100644 --- a/src/main/java/everymeal/server/review/controller/ReviewController.java +++ b/src/main/java/everymeal/server/review/controller/ReviewController.java @@ -41,13 +41,13 @@ public class ReviewController { private final ReviewService reviewService; @Operation( - summary = "식당 리뷰 작성", + summary = "학식 리뷰 작성", description = """ - 식당 리뷰 작성을 진행합니다.
+ 학식 리뷰 작성을 진행합니다.
로그인이 필요한 기능입니다. """) @ApiResponses({ - @ApiResponse(responseCode = "200", description = "리뷰 등록 성공"), + @ApiResponse(responseCode = "200", description = "학식 리뷰 등록 성공"), }) @Auth(require = true) @PostMapping @@ -189,4 +189,22 @@ public ApplicationResponse getTodayReview( String offeredAt) { return ApplicationResponse.ok(reviewService.getTodayReview(restaurantIdx, offeredAt)); } + + @Auth(require = true) + @Operation(summary = "주변 식당 리뷰 생성", description = """ + 주변 식당 리뷰 생성합니다.
+ """) + @SecurityRequirement(name = "jwt-user-auth") + @ApiResponses({ + @ApiResponse( + responseCode = "200", + description = "리뷰 생성 성공", + content = @Content(schema = @Schema(implementation = Long.class))), + }) + @PostMapping("/store") + public ApplicationResponse createReviewByStore( + @RequestBody ReviewCreateReq request, + @Parameter(hidden = true) @AuthUser AuthenticatedUser user) { + return ApplicationResponse.ok(reviewService.createReviewByStore(request, user.getIdx())); + } } diff --git a/src/main/java/everymeal/server/review/dto/request/ReviewCreateReq.java b/src/main/java/everymeal/server/review/dto/request/ReviewCreateReq.java index 7cd20a2..1a5721b 100644 --- a/src/main/java/everymeal/server/review/dto/request/ReviewCreateReq.java +++ b/src/main/java/everymeal/server/review/dto/request/ReviewCreateReq.java @@ -9,7 +9,7 @@ public record ReviewCreateReq( @Schema(description = "리뷰를 남기고자 하는 식당의 idx를 입력해주세요.", defaultValue = "1") @NotBlank - Long restaurantIdx, + Long idx, @Schema( description = "학식에 대한 리뷰 평가 점수를 정수형 최소 1 ~ 최대 5점까지로 입력해주세요. 사진 리뷰인 경우 0으로 보내주세요.", @@ -21,10 +21,7 @@ public record ReviewCreateReq( defaultValue = "오늘 학식 진짜 미침...안먹으면 땅을 치고 후회함") @Nullable String content, - @Schema( - description = - "학식이 보이는 사진 이미지 주소를 String 리스트 형태로 입력해주세요. 최대 10개의 이미지를 첨부할 수 있습니다.", - defaultValue = "['이미지 주소']") + @Schema(description = "학식이 보이는 사진 이미지 주소를 String 리스트 형태로 입력해주세요. 최대 10개의 이미지를 첨부할 수 있습니다.") @Max(10) List imageList, @Schema( diff --git a/src/main/java/everymeal/server/review/service/ReviewCommServiceImpl.java b/src/main/java/everymeal/server/review/service/ReviewCommServiceImpl.java index fcb3dd0..d4f86c8 100644 --- a/src/main/java/everymeal/server/review/service/ReviewCommServiceImpl.java +++ b/src/main/java/everymeal/server/review/service/ReviewCommServiceImpl.java @@ -62,7 +62,9 @@ public void deleteReviewMark(ReviewMark reviewMark) { public Map getTodayReviewEntityFromMapper( Long restaurantIdx, String offeredAt) { - return reviewMapper.findTodayReview(restaurantIdx, offeredAt); + Map todayReview = reviewMapper.findTodayReview(restaurantIdx, offeredAt); + System.out.println("todayReview = " + todayReview); + return todayReview; } @Transactional diff --git a/src/main/java/everymeal/server/review/service/ReviewService.java b/src/main/java/everymeal/server/review/service/ReviewService.java index d077dc7..dc9eb7d 100644 --- a/src/main/java/everymeal/server/review/service/ReviewService.java +++ b/src/main/java/everymeal/server/review/service/ReviewService.java @@ -18,4 +18,6 @@ public interface ReviewService { Boolean markReview(Long reviewIdx, boolean isLike, Long userIdx); ReviewTodayGetRes getTodayReview(Long restaurantIdx, String offeredAt); + + Long createReviewByStore(ReviewCreateReq request, Long idx); } diff --git a/src/main/java/everymeal/server/review/service/ReviewServiceImpl.java b/src/main/java/everymeal/server/review/service/ReviewServiceImpl.java index 8a5c484..e17093e 100644 --- a/src/main/java/everymeal/server/review/service/ReviewServiceImpl.java +++ b/src/main/java/everymeal/server/review/service/ReviewServiceImpl.java @@ -3,6 +3,7 @@ import static everymeal.server.global.exception.ExceptionList.REVIEW_ALREADY_MARKED; import static everymeal.server.global.exception.ExceptionList.REVIEW_MARK_NOT_FOUND; import static everymeal.server.global.exception.ExceptionList.REVIEW_UNAUTHORIZED; +import static everymeal.server.global.exception.ExceptionList.STORE_NOT_FOUND; import everymeal.server.global.exception.ApplicationException; import everymeal.server.global.util.TimeFormatUtil; @@ -15,6 +16,8 @@ import everymeal.server.review.dto.response.ReviewDto.ReviewTodayGetRes; import everymeal.server.review.entity.Image; import everymeal.server.review.entity.Review; +import everymeal.server.store.entity.Store; +import everymeal.server.store.repository.StoreRepository; import everymeal.server.user.entity.User; import everymeal.server.user.service.UserCommServiceImpl; import java.util.ArrayList; @@ -31,13 +34,13 @@ public class ReviewServiceImpl implements ReviewService { private final RestaurantCommServiceImpl restaurantCommServiceImpl; private final UserCommServiceImpl userCommServiceImpl; private final ReviewCommServiceImpl reviewCommServiceImpl; + private final StoreRepository storeRepository; @Override @Transactional public Long createReview(ReviewCreateReq request, Long userIdx) { // (1) restaurant 객체 조회 - Restaurant restaurant = - restaurantCommServiceImpl.getRestaurantEntity(request.restaurantIdx()); + Restaurant restaurant = restaurantCommServiceImpl.getRestaurantEntity(request.idx()); // (2) 이미지 주소 <> 이미지 객체 치환 List imageList = getImageFromString(request.imageList()); @@ -172,6 +175,38 @@ public ReviewTodayGetRes getTodayReview(Long restaurantIdx, String offeredAt) { reviewCommServiceImpl.getTodayReviewEntityFromMapper(restaurantIdx, offeredAt)); } + @Override + @Transactional + public Long createReviewByStore(ReviewCreateReq request, Long userIdx) { + // (1) restaurant 객체 조회 + Store store = + storeRepository + .findById(request.idx()) + .orElseThrow(() -> new ApplicationException(STORE_NOT_FOUND)); + + // (2) 이미지 주소 <> 이미지 객체 치환 + List imageList = getImageFromString(request.imageList()); + User user = userCommServiceImpl.getUserEntity(userIdx); + + // (3) Entity 생성 ( 사진리뷰인지 분기 처리 ) + Review review = + (request.content() == null && request.grade() == 0) + ? Review.builder().images(imageList).store(store).user(user).build() + : Review.builder() + .content(request.content()) + .images(imageList) + .store(store) + .grade(request.grade()) + .user(user) + .build(); + + // (4) 저장 + Review savedReview = reviewCommServiceImpl.save(review); + + store.addGrade(request.grade()); + return savedReview.getIdx(); + } + /** * ============================================================================================ * PRIVATE FUNCTION diff --git a/src/main/java/everymeal/server/store/entity/Store.java b/src/main/java/everymeal/server/store/entity/Store.java index 7a10b58..5e396ff 100644 --- a/src/main/java/everymeal/server/store/entity/Store.java +++ b/src/main/java/everymeal/server/store/entity/Store.java @@ -94,4 +94,8 @@ public Store( this.university = university; this.isDeleted = Boolean.FALSE; } + + public void addGrade(Integer grade) { + this.gradeStatistics.addGrade(grade); + } } diff --git a/src/main/resources/mybatis/mappers/ReviewMapper.xml b/src/main/resources/mybatis/mappers/ReviewMapper.xml index 80ae350..9d34e27 100644 --- a/src/main/resources/mybatis/mappers/ReviewMapper.xml +++ b/src/main/resources/mybatis/mappers/ReviewMapper.xml @@ -1,7 +1,7 @@ - SELECT r.idx as 'reviewIdx', r.content as 'content' FROM reviews r diff --git a/src/test/java/everymeal/server/review/ReviewData.java b/src/test/java/everymeal/server/review/ReviewData.java index 3242129..35a7c06 100644 --- a/src/test/java/everymeal/server/review/ReviewData.java +++ b/src/test/java/everymeal/server/review/ReviewData.java @@ -8,6 +8,8 @@ import everymeal.server.review.dto.response.ReviewDto.ReviewPaging; import everymeal.server.review.dto.response.ReviewDto.ReviewPagingVOWithCnt; import everymeal.server.review.entity.Review; +import everymeal.server.store.entity.GradeStatistics; +import everymeal.server.store.entity.Store; import everymeal.server.university.entity.University; import everymeal.server.user.entity.User; import java.util.List; @@ -30,6 +32,25 @@ public static User getUserEntity(University university, int i) { return new User("test" + i, "test" + i + "@everymeal.com", "test_IMG_URL", university); } + public static Store getStoreEntity(University university) { + return Store.builder() + .name("name") + .address("address") + .categoryGroup("categoryGroup") + .category("category") + .kakaoId("kakaoId") + .phone("phone") + .distance(3) + .url("url") + .roadAddress("roadAddress") + .x("x") + .y("y") + .gradeStatistics(new GradeStatistics()) + .university(university) + .categoryDetail("한식") + .build(); + } + public static Review getReviewEntity() { return Review.builder() .restaurant(MealData.getRestaurant()) diff --git a/src/test/java/everymeal/server/review/controller/ReviewControllerTest.java b/src/test/java/everymeal/server/review/controller/ReviewControllerTest.java index c7b5121..87f279a 100644 --- a/src/test/java/everymeal/server/review/controller/ReviewControllerTest.java +++ b/src/test/java/everymeal/server/review/controller/ReviewControllerTest.java @@ -177,4 +177,20 @@ void getTodayReview() throws Exception { .andDo(MockMvcResultHandlers.print()) .andExpect(status().isOk()); } + + @DisplayName("주변 식당 리뷰 생성") + @Test + void createReviewAround() throws Exception { + // given + ReviewCreateReq req = new ReviewCreateReq(1L, 5, "오늘 학식 진짜 미침", List.of(), true); + given(userJwtResolver.resolveArgument(any(), any(), any(), any())) + .willReturn(AuthenticatedUser.builder().idx(1L).build()); + // when-then + mockMvc.perform( + post("/api/v1/reviews/store") + .content(objectMapper.writeValueAsString(req)) + .contentType(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()); + } } diff --git a/src/test/java/everymeal/server/review/service/ReviewServiceImplTest.java b/src/test/java/everymeal/server/review/service/ReviewServiceImplTest.java index 358078b..b0d9f69 100644 --- a/src/test/java/everymeal/server/review/service/ReviewServiceImplTest.java +++ b/src/test/java/everymeal/server/review/service/ReviewServiceImplTest.java @@ -5,6 +5,7 @@ import static everymeal.server.meal.MealData.getRestaurantRegisterReq; import static everymeal.server.meal.MealData.getUniversity; import static everymeal.server.review.ReviewData.getReviewEntity; +import static everymeal.server.review.ReviewData.getStoreEntity; import static everymeal.server.review.ReviewData.getUserEntity; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; @@ -22,6 +23,8 @@ import everymeal.server.review.entity.ReviewMark; import everymeal.server.review.repository.ReviewMarkRepository; import everymeal.server.review.repository.ReviewRepository; +import everymeal.server.store.entity.Store; +import everymeal.server.store.repository.StoreRepository; import everymeal.server.university.entity.University; import everymeal.server.university.repository.UniversityRepository; import everymeal.server.user.entity.User; @@ -44,6 +47,7 @@ class ReviewServiceImplTest extends IntegrationTestSupport { @Autowired private RestaurantRepository restaurantRepository; @Autowired private UserRepository userRepository; @Autowired private ReviewMarkRepository reviewMarkRepository; + @Autowired private StoreRepository storeRepository; /** * ============================================================================================ @@ -53,7 +57,7 @@ class ReviewServiceImplTest extends IntegrationTestSupport { private University university; private Meal meal; - + private Store store; private Restaurant restaurant; private User user; private Review review; @@ -66,6 +70,7 @@ void createDummyForTest() { meal = mealRepository.save(getMealEntity(restaurant)); user = userRepository.save(getUserEntity(university)); review = reviewRepository.save(getReviewEntity(restaurant, user)); + store = storeRepository.save(getStoreEntity(university)); } @AfterEach @@ -73,6 +78,7 @@ void tearDown() { reviewMarkRepository.deleteAllInBatch(); reviewRepository.deleteAllInBatch(); mealRepository.deleteAllInBatch(); + storeRepository.deleteAllInBatch(); restaurantRepository.deleteAllInBatch(); userRepository.deleteAllInBatch(); universityRepository.deleteAllInBatch(); @@ -230,4 +236,30 @@ void getTodayReview() { // then assertEquals(result.content(), review.getContent()); } + + @DisplayName("주변 식당 리뷰 생성") + @Test + void getNearRestaurantReview() { + // given + ReviewCreateReq req = + new ReviewCreateReq(store.getIdx(), 5, "오늘 학식 진짜 미침", List.of(), true); + // when + var result = reviewService.createReviewByStore(req, user.getIdx()); + + // then + assertThat(result).isNotNull(); + } + + @DisplayName("없는 식당 리뷰 생성 - 실패") + @Test + void getNearRestaurantReview_failed() { + // given + ReviewCreateReq req = new ReviewCreateReq(0L, 5, "오늘 학식 진짜 미침", List.of(), true); + // when + ApplicationException applicationException = + assertThrows( + ApplicationException.class, + () -> reviewService.createReviewByStore(req, user.getIdx())); + assertEquals(applicationException.getErrorCode(), ExceptionList.STORE_NOT_FOUND.getCODE()); + } }