Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature/store-post-review] 식당 리뷰 생성 API #84

Merged
merged 11 commits into from
Jan 28, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static Map<String, List<DayMealGetRes>> of(List<Map<String, Object>> 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"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ public class ReviewController {
private final ReviewService reviewService;

@Operation(
summary = "식당 리뷰 작성",
summary = "학식 리뷰 작성",
description = """
식당 리뷰 작성을 진행합니다. <br>
학식 리뷰 작성을 진행합니다. <br>
로그인이 필요한 기능입니다.
""")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "리뷰 등록 성공"),
@ApiResponse(responseCode = "200", description = "학식 리뷰 등록 성공"),
Comment on lines -44 to +50
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dldmsql
식당 -> 학식으로 변경했습니다!!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

엇!! 감사합니다

})
@Auth(require = true)
@PostMapping
Expand Down Expand Up @@ -189,4 +189,22 @@ public ApplicationResponse<ReviewTodayGetRes> getTodayReview(
String offeredAt) {
return ApplicationResponse.ok(reviewService.getTodayReview(restaurantIdx, offeredAt));
}

@Auth(require = true)
@Operation(summary = "주변 식당 리뷰 생성", description = """
주변 식당 리뷰 생성합니다. <br>
""")
@SecurityRequirement(name = "jwt-user-auth")
@ApiResponses({
@ApiResponse(
responseCode = "200",
description = "리뷰 생성 성공",
content = @Content(schema = @Schema(implementation = Long.class))),
})
@PostMapping("/store")
public ApplicationResponse<Long> createReviewByStore(
@RequestBody ReviewCreateReq request,
@Parameter(hidden = true) @AuthUser AuthenticatedUser user) {
return ApplicationResponse.ok(reviewService.createReviewByStore(request, user.getIdx()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

public record ReviewCreateReq(
@Schema(description = "리뷰를 남기고자 하는 식당의 idx를 입력해주세요.", defaultValue = "1") @NotBlank
Long restaurantIdx,
Long idx,
@Schema(
description =
"학식에 대한 리뷰 평가 점수를 정수형 최소 1 ~ 최대 5점까지로 입력해주세요. 사진 리뷰인 경우 0으로 보내주세요.",
Expand All @@ -21,10 +21,7 @@ public record ReviewCreateReq(
defaultValue = "오늘 학식 진짜 미침...안먹으면 땅을 치고 후회함")
@Nullable
String content,
@Schema(
description =
"학식이 보이는 사진 이미지 주소를 String 리스트 형태로 입력해주세요. 최대 10개의 이미지를 첨부할 수 있습니다.",
defaultValue = "['이미지 주소']")
@Schema(description = "학식이 보이는 사진 이미지 주소를 String 리스트 형태로 입력해주세요. 최대 10개의 이미지를 첨부할 수 있습니다.")
@Max(10)
List<String> imageList,
@Schema(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ public void deleteReviewMark(ReviewMark reviewMark) {

public Map<String, Object> getTodayReviewEntityFromMapper(
Long restaurantIdx, String offeredAt) {
return reviewMapper.findTodayReview(restaurantIdx, offeredAt);
Map<String, Object> todayReview = reviewMapper.findTodayReview(restaurantIdx, offeredAt);
System.out.println("todayReview = " + todayReview);
return todayReview;
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 StoreRepository를 통하는 진입점을 별도의 서비스로 만들어서 하는 건 어떨까요?
StoreCommServiceImpl 클래스에서만 repository 접근이 가능하도록!!
일종의 파사드 패턴?처럼 작성하면 확장성에도 좋을 거 같아요.


@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<Image> imageList = getImageFromString(request.imageList());
Expand Down Expand Up @@ -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<Image> 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();
Comment on lines +181 to +207
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dldmsql 은비님이 만들어주신 로직... 너무 잘 사용했습니다.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ㅎ.ㅎ 도움이 되었다니 다행이에요

}

/**
* ============================================================================================
* PRIVATE FUNCTION
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/everymeal/server/store/entity/Store.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,8 @@ public Store(
this.university = university;
this.isDeleted = Boolean.FALSE;
}

public void addGrade(Integer grade) {
this.gradeStatistics.addGrade(grade);
}
}
2 changes: 1 addition & 1 deletion src/main/resources/mybatis/mappers/ReviewMapper.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="everymeal.server.review.repository.ReviewMapper">
<select id="findTodayReview">
<select id="findTodayReview" resultType="java.util.Map">
SELECT r.idx as 'reviewIdx',
r.content as 'content'
FROM reviews r
Expand Down
21 changes: 21 additions & 0 deletions src/test/java/everymeal/server/review/ReviewData.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;
Expand All @@ -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;
Expand All @@ -44,6 +47,7 @@ class ReviewServiceImplTest extends IntegrationTestSupport {
@Autowired private RestaurantRepository restaurantRepository;
@Autowired private UserRepository userRepository;
@Autowired private ReviewMarkRepository reviewMarkRepository;
@Autowired private StoreRepository storeRepository;

/**
* ============================================================================================
Expand All @@ -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;
Expand All @@ -66,13 +70,15 @@ void createDummyForTest() {
meal = mealRepository.save(getMealEntity(restaurant));
user = userRepository.save(getUserEntity(university));
review = reviewRepository.save(getReviewEntity(restaurant, user));
store = storeRepository.save(getStoreEntity(university));
}

@AfterEach
void tearDown() {
reviewMarkRepository.deleteAllInBatch();
reviewRepository.deleteAllInBatch();
mealRepository.deleteAllInBatch();
storeRepository.deleteAllInBatch();
restaurantRepository.deleteAllInBatch();
userRepository.deleteAllInBatch();
universityRepository.deleteAllInBatch();
Comment on lines 76 to 84
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dldmsql 이 부분 삭제 순서가 엄청 중요하더라구요...!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ㅎㅎ.. 맞아요 관계가 많다보니 ㅠ

Expand Down Expand Up @@ -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());
}
}
Loading