Skip to content

Commit

Permalink
[BE] feat: 리뷰 삭제시 상품 정보 업데이트 로직 추가 (#803)
Browse files Browse the repository at this point in the history
* refactor: 상품 상세 조회시 리뷰 데이터 조회 대신 상품 속 reviewCount 사용하도록 개선

* feat: 리뷰 삭제시 상품 정보 갱신 로직 추가
  • Loading branch information
hanueleee authored Oct 19, 2023
1 parent 9e928b3 commit c4bb04f
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,9 @@ private boolean hasNextPage(final List<Product> findProducts) {
public ProductResponse findProductDetail(final Long productId) {
final Product product = productRepository.findById(productId)
.orElseThrow(() -> new ProductNotFoundException(PRODUCT_NOT_FOUND, productId));
final Long reviewCount = reviewRepository.countByProduct(product);
final List<Tag> tags = reviewTagRepository.findTop3TagsByReviewIn(productId, PageRequest.of(TOP, THREE));

return ProductResponse.toResponse(product, reviewCount, tags);
return ProductResponse.toResponse(product, tags);
}

public RankingProductsResponse getTop3Products() {
Expand Down
28 changes: 26 additions & 2 deletions backend/src/main/java/com/funeat/product/domain/Product.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,36 @@ public Product(final String name, final Long price, final String image, final St
this.category = category;
this.reviewCount = reviewCount;
}


public Product(final String name, final Long price, final String image, final String content,
final Double averageRating, final Category category, final Long reviewCount) {
this.name = name;
this.price = price;
this.image = image;
this.content = content;
this.averageRating = averageRating;
this.category = category;
this.reviewCount = reviewCount;
}

public static Product create(final String name, final Long price, final String content, final Category category) {
return new Product(name, price, null, content, category);
}

public void updateAverageRating(final Long rating, final Long count) {
public void updateAverageRatingForInsert(final Long count, final Long rating) {
final double calculatedRating = ((count - 1) * averageRating + rating) / count;
this.averageRating = Math.round(calculatedRating * 10.0) / 10.0;
}

public void updateAverageRatingForDelete(final Long deletedRating) {
if (reviewCount == 1) {
this.averageRating = 0.0;
return;
}
final double calculatedRating = (reviewCount * averageRating - deletedRating) / (reviewCount - 1);
this.averageRating = Math.round(calculatedRating * 10.0) / 10.0;
}

public Double calculateRankingScore(final Long reviewCount) {
final double exponent = -Math.log10(reviewCount + 1);
final double factor = Math.pow(2, exponent);
Expand Down Expand Up @@ -133,4 +153,8 @@ public Long getReviewCount() {
public void addReviewCount() {
reviewCount++;
}

public void minusReviewCount() {
reviewCount--;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ public ProductResponse(final Long id, final String name, final Long price, final
this.tags = tags;
}

public static ProductResponse toResponse(final Product product, final Long reviewCount, final List<Tag> tags) {
public static ProductResponse toResponse(final Product product, final List<Tag> tags) {
List<TagDto> tagDtos = new ArrayList<>();
for (Tag tag : tags) {
tagDtos.add(TagDto.toDto(tag));
}
return new ProductResponse(product.getId(), product.getName(), product.getPrice(), product.getImage(),
product.getContent(), product.getAverageRating(), reviewCount, tagDtos);
product.getContent(), product.getAverageRating(), product.getReviewCount(), tagDtos);
}

public Long getId() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public void create(final Long productId, final Long memberId, final MultipartFil

final Long countByProduct = reviewRepository.countByProduct(findProduct);

findProduct.updateAverageRating(savedReview.getRating(), countByProduct);
findProduct.updateAverageRatingForInsert(countByProduct, savedReview.getRating());
findProduct.addReviewCount();
reviewTagRepository.saveAll(reviewTags);
}
Expand Down Expand Up @@ -247,13 +247,19 @@ public void deleteReview(final Long reviewId, final Long memberId) {

if (review.checkAuthor(member)) {
eventPublisher.publishEvent(new ReviewDeleteEvent(image));
updateProduct(product, review.getRating());
deleteThingsRelatedToReview(review);
updateProductImage(product.getId());
return;
}
throw new NotAuthorOfReviewException(NOT_AUTHOR_OF_REVIEW, memberId);
}

private void updateProduct(final Product product, final Long deletedRating) {
updateProductImage(product.getId());
product.updateAverageRatingForDelete(deletedRating);
product.minusReviewCount();
}

private void deleteThingsRelatedToReview(final Review review) {
deleteReviewTags(review);
deleteReviewFavorites(review);
Expand Down
52 changes: 23 additions & 29 deletions backend/src/test/java/com/funeat/product/domain/ProductTest.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.funeat.product.domain;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.SoftAssertions.assertSoftly;

import org.junit.jupiter.api.DisplayNameGeneration;
Expand All @@ -14,17 +13,17 @@
class ProductTest {

@Nested
class updateAverageRating_성공_테스트 {
class updateAverageRatingForInsert_성공_테스트 {

@Test
void 평균_평점을_업데이트___있다() {
// given
final var product = new Product("testName", 1000L, "testImage", "testContent", null);
final var reviewRating = 4L;
final var reviewCount = 1L;
final var reviewRating = 4L;

// when
product.updateAverageRating(reviewRating, reviewCount);
product.updateAverageRatingForInsert(reviewCount, reviewRating);
final var actual = product.getAverageRating();

// then
Expand All @@ -35,16 +34,16 @@ class updateAverageRating_성공_테스트 {
void 평균_평점을_여러번_업데이트___있다() {
// given
final var product = new Product("testName", 1000L, "testImage", "testContent", null);
final var reviewRating1 = 4L;
final var reviewRating2 = 2L;
final var reviewCount1 = 1L;
final var reviewCount2 = 2L;
final var reviewRating1 = 4L;
final var reviewRating2 = 2L;

// when
product.updateAverageRating(reviewRating1, reviewCount1);
product.updateAverageRatingForInsert(reviewCount1, reviewRating1);
final var actual1 = product.getAverageRating();

product.updateAverageRating(reviewRating2, reviewCount2);
product.updateAverageRatingForInsert(reviewCount2, reviewRating2);
final var actual2 = product.getAverageRating();

// then
Expand All @@ -58,39 +57,34 @@ class updateAverageRating_성공_테스트 {
}

@Nested
class updateAverageRating_실패_테스트 {
class updateAverageRatingForDelete_성공_테스트 {

@Test
void 리뷰_평점에_null_값이_들어오면_예외가_발생한다() {
void 리뷰가_하나인_상품의_리뷰를_삭제하면_평균평점은_0점이_된다() {
// given
final var product = new Product("testName", 1000L, "testImage", "testContent", null);
final var reviewCount = 1L;
final var product = new Product("testName", 1000L, "testImage", "testContent", 4.0, null, 1L);
final var reviewRating = 4L;

// when
assertThatThrownBy(() -> product.updateAverageRating(null, reviewCount))
.isInstanceOf(NullPointerException.class);
}

@Test
void 리뷰_평점이_0점이라면_예외가_발생해야하는데_관련_로직이_없어_통과하고_있다() {
// given
final var product = new Product("testName", 1000L, "testImage", "testContent", null);
final var reviewRating = 0L;
final var reviewCount = 1L;
product.updateAverageRatingForDelete(reviewRating);
final var actual = product.getAverageRating();

// when
product.updateAverageRating(reviewRating, reviewCount);
// then
assertThat(actual).isEqualTo(0.0);
}

@Test
void 리뷰_개수가_0개라면_예외가_발생해야하는데_calculatedRating값이_infinity가_나와_통과하고_있다() {
void 리뷰가_여러개인_상품의_리뷰를_삭제하면_평균평점이_갱신된다() {
// given
final var product = new Product("testName", 1000L, "testImage", "testContent", null);
final var reviewRating = 3L;
final var reviewCount = 0L;
final var product = new Product("testName", 1000L, "testImage", "testContent", 4.0, null, 4L);
final var reviewRating = 5L;

// when
product.updateAverageRating(reviewRating, reviewCount);
product.updateAverageRatingForDelete(reviewRating);
final var actual = product.getAverageRating();

// then
assertThat(actual).isEqualTo(3.7);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -800,28 +800,37 @@ class deleteReview_성공_테스트 {

final var tagIds = 태그_아이디_변환(tag1, tag2);
final var image = 이미지_생성();
final var reviewCreateRequest = 리뷰추요청_재구매O_생성(4L, tagIds);
reviewService.create(productId, authorId, image, reviewCreateRequest);
final var reviewCreateRequest1 = 리뷰추요청_재구매O_생성(2L, tagIds);
final var reviewCreateRequest2 = 리뷰추요청_재구매O_생성(4L, tagIds);

final var review = reviewRepository.findAll().get(0);
final var reviewId = review.getId();
reviewService.create(productId, authorId, image, reviewCreateRequest1);
reviewService.create(productId, authorId, image, reviewCreateRequest2);

final var reviews = reviewRepository.findAll();
final var rating2_review = reviews.stream()
.filter(it -> it.getRating() == 2L)
.findFirst()
.get();

final var favoriteRequest = 리뷰좋아요요청_생성(true);
reviewService.likeReview(reviewId, authorId, favoriteRequest);
reviewService.likeReview(reviewId, memberId, favoriteRequest);
reviewService.likeReview(rating2_review.getId(), authorId, favoriteRequest);
reviewService.likeReview(rating2_review.getId(), memberId, favoriteRequest);

// when
reviewService.deleteReview(reviewId, authorId);
reviewService.deleteReview(rating2_review.getId(), authorId);

// then
final var tags = reviewTagRepository.findAll();
final var favorites = reviewFavoriteRepository.findAll();
final var findReview = reviewRepository.findById(reviewId);
final var tags = reviewTagRepository.findByReview(rating2_review);
final var favorites = reviewFavoriteRepository.findByReview(rating2_review);
final var findReview = reviewRepository.findById(rating2_review.getId());
final var findProduct = productRepository.findById(productId).get();

assertSoftly(soft -> {
soft.assertThat(tags).isEmpty();
soft.assertThat(favorites).isEmpty();
soft.assertThat(findReview).isEmpty();
soft.assertThat(findProduct.getAverageRating()).isEqualTo(4.0);
soft.assertThat(findProduct.getReviewCount()).isEqualTo(1);
});
}
}
Expand Down

0 comments on commit c4bb04f

Please sign in to comment.