Skip to content

Commit

Permalink
v2.0.0 (#45)
Browse files Browse the repository at this point in the history
v2.0.0
  • Loading branch information
Go-Jaecheol authored Apr 20, 2024
2 parents 6f2db64 + d3665bd commit caf43c2
Show file tree
Hide file tree
Showing 25 changed files with 755 additions and 285 deletions.
9 changes: 7 additions & 2 deletions src/main/java/com/funeat/auth/util/AuthArgumentResolver.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.funeat.auth.util;

import com.funeat.auth.dto.LoginInfo;
import java.util.Objects;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import java.util.Objects;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
Expand All @@ -14,6 +14,8 @@
@Component
public class AuthArgumentResolver implements HandlerMethodArgumentResolver {

private static final LoginInfo GUEST = new LoginInfo(-1L);

@Override
public boolean supportsParameter(final MethodParameter parameter) {
return parameter.hasParameterAnnotation(AuthenticationPrincipal.class);
Expand All @@ -24,8 +26,11 @@ public Object resolveArgument(final MethodParameter parameter, final ModelAndVie
final NativeWebRequest webRequest, final WebDataBinderFactory binderFactory) {
final HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
final HttpSession session = Objects.requireNonNull(request).getSession(false);
final String id = String.valueOf(session.getAttribute("member"));
if (Objects.isNull(session)) {
return GUEST;
}

final String id = String.valueOf(session.getAttribute("member"));
return new LoginInfo(Long.valueOf(id));
}
}
37 changes: 29 additions & 8 deletions src/main/java/com/funeat/product/application/ProductService.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.funeat.product.application;

import static com.funeat.member.exception.MemberErrorCode.MEMBER_NOT_FOUND;
import static com.funeat.product.exception.CategoryErrorCode.CATEGORY_NOT_FOUND;
import static com.funeat.product.exception.ProductErrorCode.PRODUCT_NOT_FOUND;

import com.funeat.common.dto.PageDto;
import com.funeat.member.domain.Member;
import com.funeat.member.exception.MemberException.MemberNotFoundException;
import com.funeat.member.persistence.MemberRepository;
import com.funeat.member.persistence.RecipeFavoriteRepository;
import com.funeat.product.domain.Category;
import com.funeat.product.domain.Product;
import com.funeat.product.dto.ProductInCategoryDto;
Expand Down Expand Up @@ -51,6 +56,7 @@ public class ProductService {
private static final int RANKING_SIZE = 3;
private static final int DEFAULT_PAGE_SIZE = 10;
private static final int DEFAULT_CURSOR_PAGINATION_SIZE = 11;
private static final long GUEST_ID = -1L;

private final CategoryRepository categoryRepository;
private final ProductRepository productRepository;
Expand All @@ -59,19 +65,24 @@ public class ProductService {
private final ProductRecipeRepository productRecipeRepository;
private final RecipeImageRepository recipeImageRepository;
private final RecipeRepository recipeRepository;
private final MemberRepository memberRepository;
private final RecipeFavoriteRepository recipeFavoriteRepository;

public ProductService(final CategoryRepository categoryRepository, final ProductRepository productRepository,
final ReviewTagRepository reviewTagRepository, final ReviewRepository reviewRepository,
final ProductRecipeRepository productRecipeRepository,
final RecipeImageRepository recipeImageRepository,
final RecipeRepository recipeRepository) {
final RecipeRepository recipeRepository, final MemberRepository memberRepository,
final RecipeFavoriteRepository recipeFavoriteRepository) {
this.categoryRepository = categoryRepository;
this.productRepository = productRepository;
this.reviewTagRepository = reviewTagRepository;
this.reviewRepository = reviewRepository;
this.productRecipeRepository = productRecipeRepository;
this.recipeImageRepository = recipeImageRepository;
this.recipeRepository = recipeRepository;
this.memberRepository = memberRepository;
this.recipeFavoriteRepository = recipeFavoriteRepository;
}

public ProductsInCategoryResponse getAllProductsInCategory(final Long categoryId, final Long lastProductId,
Expand Down Expand Up @@ -174,20 +185,30 @@ private List<ProductReviewCountDto> findAllWithReviewCountByNameContaining(final
return productRepository.findAllWithReviewCountByNameContaining(query, lastProductId, size);
}

public SortingRecipesResponse getProductRecipes(final Long productId, final Pageable pageable) {
public SortingRecipesResponse getProductRecipes(final Long memberId, final Long productId, final Pageable pageable) {
final Product product = productRepository.findById(productId)
.orElseThrow(() -> new ProductNotFoundException(PRODUCT_NOT_FOUND, productId));

final Page<Recipe> recipes = recipeRepository.findRecipesByProduct(product, pageable);

final PageDto pageDto = PageDto.toDto(recipes);
final List<RecipeDto> recipeDtos = recipes.stream()
.map(recipe -> {
final List<RecipeImage> images = recipeImageRepository.findByRecipe(recipe);
final List<Product> products = productRecipeRepository.findProductByRecipe(recipe);
return RecipeDto.toDto(recipe, images, products);
})
.collect(Collectors.toList());
.map(recipe -> createRecipeDto(memberId, recipe))
.toList();
return SortingRecipesResponse.toResponse(pageDto, recipeDtos);
}

private RecipeDto createRecipeDto(final Long memberId, final Recipe recipe) {
final List<RecipeImage> images = recipeImageRepository.findByRecipe(recipe);
final List<Product> products = productRecipeRepository.findProductByRecipe(recipe);

if (memberId == GUEST_ID) {
return RecipeDto.toDto(recipe, images, products, false);
}

final Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new MemberNotFoundException(MEMBER_NOT_FOUND, memberId));
final Boolean favorite = recipeFavoriteRepository.existsByMemberAndRecipeAndFavoriteTrue(member, recipe);
return RecipeDto.toDto(recipe, images, products, favorite);
}
}
32 changes: 32 additions & 0 deletions src/main/java/com/funeat/product/dto/CategoryDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.funeat.product.dto;

import com.funeat.product.domain.Category;

public class CategoryDto {

private final Long id;
private final String name;
private final String image;

private CategoryDto(final Long id, final String name, final String image) {
this.id = id;
this.name = name;
this.image = image;
}

public static CategoryDto toDto(final Category category) {
return new CategoryDto(category.getId(), category.getName(), category.getImage());
}

public Long getId() {
return id;
}

public String getName() {
return name;
}

public String getImage() {
return image;
}
}
17 changes: 13 additions & 4 deletions src/main/java/com/funeat/product/dto/ProductResponse.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.funeat.product.dto;

import com.funeat.product.domain.Category;
import com.funeat.product.domain.CategoryType;
import com.funeat.product.domain.Product;
import com.funeat.tag.domain.Tag;
import com.funeat.tag.dto.TagDto;
Expand All @@ -15,27 +17,30 @@ public class ProductResponse {
private final String content;
private final Double averageRating;
private final Long reviewCount;
private final CategoryDto category;
private final List<TagDto> tags;

public ProductResponse(final Long id, final String name, final Long price, final String image, final String content,
final Double averageRating, final Long reviewCount, final List<TagDto> tags) {
final Double averageRating, final Long reviewCount, final CategoryDto category, final List<TagDto> tags) {
this.id = id;
this.name = name;
this.price = price;
this.image = image;
this.content = content;
this.averageRating = averageRating;
this.reviewCount = reviewCount;
this.category = category;
this.tags = tags;
}

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

public Long getId() {
Expand Down Expand Up @@ -66,6 +71,10 @@ public Long getReviewCount() {
return reviewCount;
}

public CategoryDto getCategory() {
return category;
}

public List<TagDto> getTags() {
return tags;
}
Expand Down
13 changes: 10 additions & 3 deletions src/main/java/com/funeat/product/dto/RankingProductDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@ public class RankingProductDto {

private final Long id;
private final String name;
private final Long price;
private final String image;
private final String categoryType;

public RankingProductDto(final Long id, final String name, final String image, final String categoryType) {
public RankingProductDto(final Long id, final String name, final Long price,
final String image, final String categoryType) {
this.id = id;
this.name = name;
this.price = price;
this.image = image;
this.categoryType = categoryType;
}

public static RankingProductDto toDto(final Product product) {
return new RankingProductDto(product.getId(), product.getName(), product.getImage(),
product.getCategory().getType().getName());
return new RankingProductDto(product.getId(), product.getName(), product.getPrice(),
product.getImage(), product.getCategory().getType().getName());
}

public Long getId() {
Expand All @@ -29,6 +32,10 @@ public String getName() {
return name;
}

public Long getPrice() {
return price;
}

public String getImage() {
return image;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.funeat.product.presentation;

import com.funeat.auth.dto.LoginInfo;
import com.funeat.auth.util.AuthenticationPrincipal;
import com.funeat.product.application.ProductService;
import com.funeat.product.dto.ProductResponse;
import com.funeat.product.dto.ProductSortCondition;
Expand All @@ -8,7 +10,6 @@
import com.funeat.product.dto.SearchProductResultsResponse;
import com.funeat.product.dto.SearchProductsResponse;
import com.funeat.recipe.dto.SortingRecipesResponse;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -64,9 +65,10 @@ public ResponseEntity<SearchProductResultsResponse> getSearchResults(@RequestPar
}

@GetMapping("/products/{productId}/recipes")
public ResponseEntity<SortingRecipesResponse> getProductRecipes(@PathVariable final Long productId,
public ResponseEntity<SortingRecipesResponse> getProductRecipes(@AuthenticationPrincipal final LoginInfo loginInfo,
@PathVariable final Long productId,
@PageableDefault final Pageable pageable) {
final SortingRecipesResponse response = productService.getProductRecipes(productId, pageable);
final SortingRecipesResponse response = productService.getProductRecipes(loginInfo.getId(), productId, pageable);
return ResponseEntity.ok(response);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.funeat.product.presentation;

import com.funeat.auth.dto.LoginInfo;
import com.funeat.auth.util.AuthenticationPrincipal;
import com.funeat.product.dto.ProductResponse;
import com.funeat.product.dto.ProductsInCategoryResponse;
import com.funeat.product.dto.RankingProductsResponse;
Expand Down Expand Up @@ -71,6 +73,7 @@ ResponseEntity<SearchProductResultsResponse> getSearchResults(@RequestParam fina
description = "해당 상품 꿀조합 목록 조회 성공."
)
@GetMapping
ResponseEntity<SortingRecipesResponse> getProductRecipes(@PathVariable final Long productId,
ResponseEntity<SortingRecipesResponse> getProductRecipes(@AuthenticationPrincipal final LoginInfo loginInfo,
@PathVariable final Long productId,
@PageableDefault final Pageable pageable);
}
51 changes: 36 additions & 15 deletions src/main/java/com/funeat/recipe/application/RecipeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@
public class RecipeService {

private static final long RANKING_MINIMUM_FAVORITE_COUNT = 1L;
private static final int RANKING_SIZE = 3;
private static final int RANKING_SIZE = 4;
private static final int DEFAULT_PAGE_SIZE = 10;
private static final int RECIPE_COMMENT_PAGE_SIZE = 10;
private static final int DEFAULT_CURSOR_PAGINATION_SIZE = 11;
private static final long GUEST_ID = -1L;

private final MemberRepository memberRepository;
private final ProductRepository productRepository;
Expand Down Expand Up @@ -155,21 +156,31 @@ public MemberRecipesResponse findRecipeByMember(final Long memberId, final Pagea
return MemberRecipesResponse.toResponse(page, dtos);
}

public SortingRecipesResponse getSortingRecipes(final Pageable pageable) {
public SortingRecipesResponse getSortingRecipes(final Long memberId, final Pageable pageable) {
final Page<Recipe> pages = recipeRepository.findAll(pageable);

final PageDto page = PageDto.toDto(pages);
final List<RecipeDto> recipes = pages.getContent().stream()
.map(recipe -> {
final List<RecipeImage> images = recipeImageRepository.findByRecipe(recipe);
final List<Product> products = productRecipeRepository.findProductByRecipe(recipe);
return RecipeDto.toDto(recipe, images, products);
})
.collect(Collectors.toList());
.map(recipe -> createRecipeDto(memberId, recipe))
.toList();

return SortingRecipesResponse.toResponse(page, recipes);
}

private RecipeDto createRecipeDto(final Long memberId, final Recipe recipe) {
final List<RecipeImage> images = recipeImageRepository.findByRecipe(recipe);
final List<Product> products = productRecipeRepository.findProductByRecipe(recipe);

if (memberId == GUEST_ID) {
return RecipeDto.toDto(recipe, images, products, false);
}

final Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new MemberNotFoundException(MEMBER_NOT_FOUND, memberId));
final Boolean favorite = recipeFavoriteRepository.existsByMemberAndRecipeAndFavoriteTrue(member, recipe);
return RecipeDto.toDto(recipe, images, products, favorite);
}

@Transactional
public void likeRecipe(final Long memberId, final Long recipeId, final RecipeFavoriteRequest request) {
final Member member = memberRepository.findById(memberId)
Expand Down Expand Up @@ -217,21 +228,31 @@ private List<Recipe> findAllByProductNameContaining(final String query, final Lo
return recipeRepository.findAllByProductNameContaining(query, lastRecipeId, size);
}

public RankingRecipesResponse getTop3Recipes() {
public RankingRecipesResponse getTop4Recipes(final Long memberId) {
final List<Recipe> recipes = recipeRepository.findRecipesByFavoriteCountGreaterThanEqual(RANKING_MINIMUM_FAVORITE_COUNT);

final List<RankingRecipeDto> dtos = recipes.stream()
.sorted(Comparator.comparing(Recipe::calculateRankingScore).reversed())
.limit(RANKING_SIZE)
.map(recipe -> {
final List<RecipeImage> findRecipeImages = recipeImageRepository.findByRecipe(recipe);
final RecipeAuthorDto author = RecipeAuthorDto.toDto(recipe.getMember());
return RankingRecipeDto.toDto(recipe, findRecipeImages, author);
})
.collect(Collectors.toList());
.map(recipe -> createRankingRecipeDto(memberId, recipe))
.toList();
return RankingRecipesResponse.toResponse(dtos);
}

private RankingRecipeDto createRankingRecipeDto(final Long memberId, final Recipe recipe) {
final List<RecipeImage> findRecipeImages = recipeImageRepository.findByRecipe(recipe);
final RecipeAuthorDto author = RecipeAuthorDto.toDto(recipe.getMember());

if (memberId == GUEST_ID) {
return RankingRecipeDto.toDto(recipe, findRecipeImages, author, false);
}

final Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new MemberNotFoundException(MEMBER_NOT_FOUND, memberId));
final boolean favorite = recipeFavoriteRepository.existsByMemberAndRecipeAndFavoriteTrue(member, recipe);
return RankingRecipeDto.toDto(recipe, findRecipeImages, author, favorite);
}

@Transactional
public Long writeCommentOfRecipe(final Long memberId, final Long recipeId,
final RecipeCommentCreateRequest request) {
Expand Down
Loading

0 comments on commit caf43c2

Please sign in to comment.