Skip to content

Commit

Permalink
[BE] feat: 꿀조합 댓글 작성 기능 구현 (#747)
Browse files Browse the repository at this point in the history
* remove: 북마크 관련 삭제

* feat: 꿀조합 댓글 작성 구현

* refactor: Comments 단방향으로 수정

* feat: 꿀조합 댓글 조회 기능 추가

* refactor: Specification private 기본생성자 추가

* refactor: 적용된 코드 SESSION ID 수정

* refactor: 생성자 정렬 수정

* refactor: 세션 쿠키 이름 SESSION 으로 수정

* refactor: 변수명 상세하게 specification 로 수정

* refactor: repeat 사용과 디버깅 출력 코드 삭제

* remove: 디버깅 출력 코드 삭제

* refactor: subList() 와 for each 사용으로 수정

* test: 꿀조합 댓글 관련 서비스 테스트 추가

* refactor: 응답 변수명 상세하게 수정

* refactor: toResponse 맞춰서 수정

* refactor: 메소드 순서에 맞게 수정

* refactor: 리뷰 반영

* refactor: 테스트 실패 수정
  • Loading branch information
wugawuga authored Oct 16, 2023
1 parent 5d2e717 commit dab066e
Show file tree
Hide file tree
Showing 27 changed files with 844 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ public class AdminProductSpecification {

private static final List<Class<Long>> COUNT_RESULT_TYPES = List.of(Long.class, long.class);

private AdminProductSpecification() {
}

public static Specification<Product> searchBy(final ProductSearchCondition condition) {
return (root, query, criteriaBuilder) -> {
if (!COUNT_RESULT_TYPES.contains(query.getResultType())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

public class AdminReviewSpecification {

private AdminReviewSpecification() {
}

public static Specification<Review> searchBy(final ReviewSearchCondition condition) {
return (root, query, criteriaBuilder) -> {
if (query.getResultType() != Long.class && query.getResultType() != long.class) {
Expand Down
59 changes: 59 additions & 0 deletions backend/src/main/java/com/funeat/comment/domain/Comment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.funeat.comment.domain;

import com.funeat.member.domain.Member;
import com.funeat.recipe.domain.Recipe;
import java.time.LocalDateTime;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity
public class Comment {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String comment;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "recipe_id")
private Recipe recipe;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;

@Column(nullable = false)
private LocalDateTime createdAt = LocalDateTime.now();

protected Comment() {
}

public Comment(final Recipe recipe, final Member member, final String comment) {
this.recipe = recipe;
this.member = member;
this.comment = comment;
}

public Long getId() {
return id;
}

public String getComment() {
return comment;
}

public Member getMember() {
return member;
}

public LocalDateTime getCreatedAt() {
return createdAt;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.funeat.comment.persistence;

import com.funeat.comment.domain.Comment;
import com.funeat.common.repository.BaseRepository;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CommentRepository extends JpaRepository<Comment, Long>, BaseRepository<Comment, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.funeat.comment.specification;

import com.funeat.comment.domain.Comment;
import com.funeat.recipe.domain.Recipe;
import java.util.List;
import java.util.Objects;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Path;
import org.springframework.data.jpa.domain.Specification;

public class CommentSpecification {

private CommentSpecification() {
}

private static final List<Class<Long>> COUNT_RESULT_TYPES = List.of(Long.class, long.class);

public static Specification<Comment> findAllByRecipe(final Recipe recipe, final Long lastCommentId) {
return (root, query, criteriaBuilder) -> {
if (!COUNT_RESULT_TYPES.contains(query.getResultType())) {
root.fetch("member", JoinType.LEFT);
}

criteriaBuilder.desc(root.get("id"));

return Specification
.where(lessThan(lastCommentId))
.and(equalToRecipe(recipe))
.toPredicate(root, query, criteriaBuilder);
};
}

private static Specification<Comment> lessThan(final Long commentId) {
return (root, query, criteriaBuilder) -> {
if (Objects.isNull(commentId)) {
return null;
}

final Path<Long> commentIdPath = root.get("id");

return criteriaBuilder.lessThan(commentIdPath, commentId);
};
}

private static Specification<Comment> equalToRecipe(final Recipe recipe) {
return (root, query, criteriaBuilder) -> {
if (Objects.isNull(recipe)) {
return null;
}

final Path<Recipe> recipePath = root.get("recipe");

return criteriaBuilder.equal(recipePath, recipe);
};
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions backend/src/main/java/com/funeat/product/domain/Product.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.funeat.product.domain;

import com.funeat.member.domain.bookmark.ProductBookmark;
import com.funeat.review.domain.Review;
import java.util.List;
import javax.persistence.Entity;
Expand Down Expand Up @@ -39,9 +38,6 @@ public class Product {
@OneToMany(mappedBy = "product")
private List<ProductRecipe> productRecipes;

@OneToMany(mappedBy = "product")
private List<ProductBookmark> productBookmarks;

private Long reviewCount = 0L;

protected Product() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import static com.funeat.product.exception.ProductErrorCode.PRODUCT_NOT_FOUND;
import static com.funeat.recipe.exception.RecipeErrorCode.RECIPE_NOT_FOUND;

import com.funeat.comment.domain.Comment;
import com.funeat.comment.persistence.CommentRepository;
import com.funeat.comment.specification.CommentSpecification;
import com.funeat.common.ImageUploader;
import com.funeat.common.dto.PageDto;
import com.funeat.member.domain.Member;
Expand All @@ -26,6 +29,10 @@
import com.funeat.recipe.dto.RankingRecipeDto;
import com.funeat.recipe.dto.RankingRecipesResponse;
import com.funeat.recipe.dto.RecipeAuthorDto;
import com.funeat.recipe.dto.RecipeCommentCondition;
import com.funeat.recipe.dto.RecipeCommentCreateRequest;
import com.funeat.recipe.dto.RecipeCommentResponse;
import com.funeat.recipe.dto.RecipeCommentsResponse;
import com.funeat.recipe.dto.RecipeCreateRequest;
import com.funeat.recipe.dto.RecipeDetailResponse;
import com.funeat.recipe.dto.RecipeDto;
Expand All @@ -36,13 +43,16 @@
import com.funeat.recipe.exception.RecipeException.RecipeNotFoundException;
import com.funeat.recipe.persistence.RecipeImageRepository;
import com.funeat.recipe.persistence.RecipeRepository;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
Expand All @@ -53,25 +63,30 @@ public class RecipeService {

private static final int THREE = 3;
private static final int TOP = 0;
private static final int RECIPE_COMMENT_PAGE_SIZE = 10;
private static final int DEFAULT_CURSOR_PAGINATION_SIZE = 11;

private final MemberRepository memberRepository;
private final ProductRepository productRepository;
private final ProductRecipeRepository productRecipeRepository;
private final RecipeRepository recipeRepository;
private final RecipeImageRepository recipeImageRepository;
private final RecipeFavoriteRepository recipeFavoriteRepository;
private final CommentRepository commentRepository;
private final ImageUploader imageUploader;

public RecipeService(final MemberRepository memberRepository, final ProductRepository productRepository,
final ProductRecipeRepository productRecipeRepository, final RecipeRepository recipeRepository,
final RecipeImageRepository recipeImageRepository,
final RecipeFavoriteRepository recipeFavoriteRepository, final ImageUploader imageUploader) {
final RecipeFavoriteRepository recipeFavoriteRepository,
final CommentRepository commentRepository, final ImageUploader imageUploader) {
this.memberRepository = memberRepository;
this.productRepository = productRepository;
this.productRecipeRepository = productRecipeRepository;
this.recipeRepository = recipeRepository;
this.recipeImageRepository = recipeImageRepository;
this.recipeFavoriteRepository = recipeFavoriteRepository;
this.commentRepository = commentRepository;
this.imageUploader = imageUploader;
}

Expand Down Expand Up @@ -166,7 +181,8 @@ public void likeRecipe(final Long memberId, final Long recipeId, final RecipeFav
recipeFavorite.updateFavorite(request.getFavorite());
}

private RecipeFavorite createAndSaveRecipeFavorite(final Member member, final Recipe recipe, final Boolean favorite) {
private RecipeFavorite createAndSaveRecipeFavorite(final Member member, final Recipe recipe,
final Boolean favorite) {
try {
final RecipeFavorite recipeFavorite = RecipeFavorite.create(member, recipe, favorite);
return recipeFavoriteRepository.save(recipeFavorite);
Expand Down Expand Up @@ -201,4 +217,63 @@ public RankingRecipesResponse getTop3Recipes() {
.collect(Collectors.toList());
return RankingRecipesResponse.toResponse(dtos);
}

@Transactional
public Long writeCommentOfRecipe(final Long memberId, final Long recipeId,
final RecipeCommentCreateRequest request) {
final Member findMember = memberRepository.findById(memberId)
.orElseThrow(() -> new MemberNotFoundException(MEMBER_NOT_FOUND, memberId));

final Recipe findRecipe = recipeRepository.findById(recipeId)
.orElseThrow(() -> new RecipeNotFoundException(RECIPE_NOT_FOUND, recipeId));

final Comment comment = new Comment(findRecipe, findMember, request.getComment());

final Comment savedComment = commentRepository.save(comment);
return savedComment.getId();
}

public RecipeCommentsResponse getCommentsOfRecipe(final Long recipeId, final RecipeCommentCondition condition) {
final Recipe findRecipe = recipeRepository.findById(recipeId)
.orElseThrow(() -> new RecipeNotFoundException(RECIPE_NOT_FOUND, recipeId));

final Specification<Comment> specification = CommentSpecification.findAllByRecipe(findRecipe,
condition.getLastId());

final PageRequest pageable = PageRequest.of(0, DEFAULT_CURSOR_PAGINATION_SIZE, Sort.by("id").descending());

final Page<Comment> commentPaginationResult = commentRepository.findAllForPagination(specification, pageable,
condition.getTotalElements());

final List<RecipeCommentResponse> recipeCommentResponses = getRecipeCommentResponses(
commentPaginationResult.getContent());

final Boolean hasNext = hasNextPage(commentPaginationResult);

return RecipeCommentsResponse.toResponse(recipeCommentResponses, hasNext,
commentPaginationResult.getTotalElements());
}

private List<RecipeCommentResponse> getRecipeCommentResponses(final List<Comment> findComments) {
final List<RecipeCommentResponse> recipeCommentResponses = new ArrayList<>();
final int resultSize = getResultSize(findComments);
final List<Comment> comments = findComments.subList(0, resultSize);

for (final Comment comment : comments) {
final RecipeCommentResponse recipeCommentResponse = RecipeCommentResponse.toResponse(comment);
recipeCommentResponses.add(recipeCommentResponse);
}
return recipeCommentResponses;
}

private int getResultSize(final List<Comment> findComments) {
if (findComments.size() < DEFAULT_CURSOR_PAGINATION_SIZE) {
return findComments.size();
}
return RECIPE_COMMENT_PAGE_SIZE;
}

private Boolean hasNextPage(final Page<Comment> findComments) {
return findComments.getContent().size() > RECIPE_COMMENT_PAGE_SIZE;
}
}
Loading

0 comments on commit dab066e

Please sign in to comment.