diff --git a/src/main/java/zipdabang/server/apiPayload/code/CommonStatus.java b/src/main/java/zipdabang/server/apiPayload/code/CommonStatus.java index f122a8e..a326332 100644 --- a/src/main/java/zipdabang/server/apiPayload/code/CommonStatus.java +++ b/src/main/java/zipdabang/server/apiPayload/code/CommonStatus.java @@ -21,9 +21,6 @@ public enum CommonStatus implements BaseCode { - //recipe response - RECIPE_NOT_FOUND(HttpStatus.OK, 2100, "조회된 목록이 없습니다"), - // market response WATCHED_NOT_FOUND(HttpStatus.OK, 2150, "조회했던 아이템이 없습니다."), @@ -97,33 +94,6 @@ public enum CommonStatus implements BaseCode { // market error - //recipe error - - //BAD_REQUEST - NULL_RECIPE_ERROR(HttpStatus.OK, 4100, "레시피 작성시 누락된 내용이 있습니다."), - //BAD_REQUEST - NO_RECIPE_EXIST(HttpStatus.OK, 4101, "해당 레시피가 존재하지 않습니다."), - //BAD_REQUEST - BLOCKED_USER_RECIPE(HttpStatus.OK, 4102, "차단한 사용자의 레시피입니다."), - //BAD_REQUEST - WRITTEN_BY_TYPE_ERROR(HttpStatus.OK, 4103, "레시피 작성자 타입이 잘못되었습니다. all, influencer, common중 하나로 보내주세요."), - //BAD_REQUEST - ORDER_BY_TYPE_ERROR(HttpStatus.OK, 4104, "조회 방식 타입이 잘못되었습니다. likes, views, latest중 하나로 보내주세요."), - //BAD_REQUEST - NO_RECIPE_CATEGORY_EXIST(HttpStatus.OK, 4105, "해당 id를 가진 레시피 카테고리가 없습니다. 잘못 보내줬어요"), - //BAD_REQUEST - NOT_RECIPE_OWNER(HttpStatus.OK, 4106, "본인이 작성한 레시피가 아닙니다. 변경할 수 없습니다"), - //BAD_REQUEST - NO_COMMENT_EXIST(HttpStatus.OK, 4107, "해당 댓글이 존재하지 않습니다."), - //BAD_REQUEST - NOT_COMMENT_OWNER(HttpStatus.OK, 4108, "본인이 작성한 댓글이 아닙니다. 변경할 수 없습니다"), - //BAD_REQUEST - RECIPE_OWNER(HttpStatus.OK, 4109, "본인의 레시피입니다. 좋아요/스크랩/신고/차단할 수 없습니다"), - //BAD_REQUEST - COMMENT_OWNER(HttpStatus.OK, 4110, "본인의 댓글입니다. 좋아요/스크랩/신고/차단할 수 없습니다"), - //BAD_REQUEST - NO_TEMP_RECIPE_EXIST(HttpStatus.OK, 4111, "해당 임시저장 Id가 존재하지 않습니다."), - //INTERNAL_SERVER_ERROR INTERNAL_ERROR(HttpStatus.OK, 5000, "Internal server Error"), diff --git a/src/main/java/zipdabang/server/apiPayload/code/RecipeStatus.java b/src/main/java/zipdabang/server/apiPayload/code/RecipeStatus.java new file mode 100644 index 0000000..3315116 --- /dev/null +++ b/src/main/java/zipdabang/server/apiPayload/code/RecipeStatus.java @@ -0,0 +1,61 @@ +package zipdabang.server.apiPayload.code; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum RecipeStatus implements BaseCode{ + + RECIPE_NOT_FOUND(HttpStatus.OK, 2100, "조회된 목록이 없습니다"), + + //BAD_REQUEST + NULL_RECIPE_ERROR(HttpStatus.OK, 4100, "레시피 작성시 누락된 내용이 있습니다."), + //BAD_REQUEST + NO_RECIPE_EXIST(HttpStatus.OK, 4101, "해당 레시피가 존재하지 않습니다."), + //BAD_REQUEST + BLOCKED_USER_RECIPE(HttpStatus.OK, 4102, "차단한 사용자의 레시피입니다."), + //BAD_REQUEST + WRITTEN_BY_TYPE_ERROR(HttpStatus.OK, 4103, "레시피 작성자 타입이 잘못되었습니다. all, influencer, common중 하나로 보내주세요."), + //BAD_REQUEST + ORDER_BY_TYPE_ERROR(HttpStatus.OK, 4104, "조회 방식 타입이 잘못되었습니다. likes, views, latest중 하나로 보내주세요."), + //BAD_REQUEST + NO_RECIPE_CATEGORY_EXIST(HttpStatus.OK, 4105, "해당 id를 가진 레시피 카테고리가 없습니다. 잘못 보내줬어요"), + //BAD_REQUEST + NOT_RECIPE_OWNER(HttpStatus.OK, 4106, "본인이 작성한 레시피가 아닙니다. 변경할 수 없습니다"), + //BAD_REQUEST + NO_COMMENT_EXIST(HttpStatus.OK, 4107, "해당 댓글이 존재하지 않습니다."), + //BAD_REQUEST + NOT_COMMENT_OWNER(HttpStatus.OK, 4108, "본인이 작성한 댓글이 아닙니다. 변경할 수 없습니다"), + //BAD_REQUEST + RECIPE_OWNER(HttpStatus.OK, 4109, "본인의 레시피입니다. 좋아요/스크랩/신고/차단할 수 없습니다"), + //BAD_REQUEST + COMMENT_OWNER(HttpStatus.OK, 4110, "본인의 댓글입니다. 좋아요/스크랩/신고/차단할 수 없습니다"), + //BAD_REQUEST + NO_TEMP_RECIPE_EXIST(HttpStatus.OK, 4111, "해당 임시저장 Id가 존재하지 않습니다."); + + private final HttpStatus httpStatus; + private final Integer code; + private final String message; + + @Override + public Reason getReason() { + return Reason.builder() + .message(message) + .code(code) + .isSuccess((code >= 2000 && code < 3000) ? true : false) + .build(); + } + + @Override + public Reason getReasonHttpStatus() { + return Reason.builder() + .message(message) + .code(code) + .isSuccess((code >= 2000 && code < 3000) ? true : false) + .httpStatus(httpStatus) + .build() + ; + } +} diff --git a/src/main/java/zipdabang/server/converter/RecipeConverter.java b/src/main/java/zipdabang/server/converter/RecipeConverter.java index 628e764..e402e8e 100644 --- a/src/main/java/zipdabang/server/converter/RecipeConverter.java +++ b/src/main/java/zipdabang/server/converter/RecipeConverter.java @@ -7,6 +7,7 @@ import org.springframework.web.multipart.MultipartFile; //import zipdabang.server.aws.s3.AmazonS3Manager; import zipdabang.server.apiPayload.code.CommonStatus; +import zipdabang.server.apiPayload.code.RecipeStatus; import zipdabang.server.aws.s3.AmazonS3Manager; import zipdabang.server.apiPayload.exception.handler.RecipeException; import zipdabang.server.domain.Report; @@ -22,6 +23,7 @@ import java.io.IOException; import java.util.List; import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -60,24 +62,28 @@ public class RecipeConverter { private static TimeConverter staticTimeConverter; public static RecipeResponseDto.PerCategoryPreview toPerCategoryPreview(Long categoryId, List recipeList, Member member) { + + AtomicInteger index = new AtomicInteger(1); + return RecipeResponseDto.PerCategoryPreview.builder() .categoryId(categoryId) .totalElements(recipeList.size()) .recipeList(recipeList.stream() - .map(recipe -> toRecipePreviewDto(recipe,member)) + .map(recipe -> toRecipePreviewDto(recipe,member, index.getAndIncrement())) .collect(Collectors.toList())) .build(); } - public static RecipeResponseDto.RecipePreviewDto toRecipePreviewDto(Recipe recipe, Member member) { + public static RecipeResponseDto.RecipePreviewDto toRecipePreviewDto(Recipe recipe, Member member, Integer rank) { return RecipeResponseDto.RecipePreviewDto.builder() .recipeId(recipe.getId()) .recipeName(recipe.getName()) .nickname(recipe.getMember().getNickname()) .likes(recipe.getTotalLike()) - .scraps(recipe.getTotalScrap()) + .comments(recipe.getTotalComments()) .isLiked(staticLikesRepository.findByRecipeAndMember(recipe, member).isPresent()) .isScrapped(staticScrapRepository.findByRecipeAndMember(recipe,member).isPresent()) + .rank(rank) .build(); } @@ -110,6 +116,32 @@ public static RecipeResponseDto.RecipePageListDto toPagingRecipeDtoList(Page bestRecipes, Member member) { + return RecipeResponseDto.WeekBestDtoList.builder() + .recipeList(bestRecipes.stream() + .map(bestRecipe -> toResponseWeekBestDto(bestRecipe.getRecipe(), member, bestRecipe.getRanking())) + .collect(Collectors.toList())) + .totalElements(bestRecipes.size()) + .build(); + } + + private static RecipeResponseDto.RecipeSimpleDtoBest toResponseWeekBestDto(Recipe recipe, Member member, Integer rank) { + return RecipeResponseDto.RecipeSimpleDtoBest.builder() + .rank(rank) + .recipeId(recipe.getId()) + .recipeName(recipe.getName()) + .nickname(recipe.getMember().getNickname()) + .thumbnailUrl(recipe.getThumbnailUrl()) + .createdAt(staticTimeConverter.ConvertTime(recipe.getCreatedAt())) + .updatedAt(staticTimeConverter.ConvertTime(recipe.getUpdatedAt())) + .likes(recipe.getTotalLike()) + .comments(recipe.getTotalComments()) + .scraps(recipe.getTotalScrap()) + .isLiked(staticLikesRepository.findByRecipeAndMember(recipe, member).isPresent()) + .isScrapped(staticScrapRepository.findByRecipeAndMember(recipe,member).isPresent()) + .build(); + } + public static RecipeResponseDto.RecipeListDto toPreviewRecipeDtoList(List recipes, Member member) { return RecipeResponseDto.RecipeListDto.builder() .recipeList(recipes.stream() @@ -159,7 +191,7 @@ public static List toStep(RecipeRequestDto.CreateRecipeDto request, Recipe return request.getSteps().stream() .map(step-> { if (step.getDescription() == null) - throw new RecipeException(CommonStatus.NULL_RECIPE_ERROR); + throw new RecipeException(RecipeStatus.NULL_RECIPE_ERROR); try { return toStepDto(step, recipe, stepImages); } catch (IOException e) { @@ -217,6 +249,7 @@ public static RecipeResponseDto.TempRecipeStatusDto toTempRecipeStatusDto(TempRe public static RecipeResponseDto.RecipeInfoDto toRecipeInfoDto(Recipe recipe, Boolean isOwner, Boolean isLiked, Boolean isScrapped, Member member) { return RecipeResponseDto.RecipeInfoDto.builder() .recipeInfo(toResponseRecipeDto(recipe, isLiked, isScrapped, member)) + .ownerId(recipe.getMember().getMemberId()) .isOwner(isOwner) .steps(toResponseStepDto(recipe)) .ingredients(toResponseIngredientDto(recipe)) @@ -274,7 +307,7 @@ public static RecipeResponseDto.RecipeDto toResponseRecipeDto(Recipe recipe, Boo public static Recipe toRecipe(RecipeRequestDto.CreateRecipeDto request, MultipartFile thumbnail, Member member) throws IOException { Recipe recipe = Recipe.builder() - .isInfluencer(member.isInfluencer()) + .isBarista(member.isBarista()) .name(request.getName()) .intro(request.getIntro()) .recipeTip(request.getRecipeTip()) @@ -286,7 +319,7 @@ public static Recipe toRecipe(RecipeRequestDto.CreateRecipeDto request, Multipar if(thumbnail != null) imageUrl = uploadThumbnail(thumbnail); else - throw new RecipeException(CommonStatus.NULL_RECIPE_ERROR); + throw new RecipeException(RecipeStatus.NULL_RECIPE_ERROR); recipe.setThumbnail(imageUrl); return recipe; @@ -295,7 +328,7 @@ public static Recipe toRecipe(RecipeRequestDto.CreateRecipeDto request, Multipar public static TempRecipe toTempRecipe(RecipeRequestDto.TempRecipeDto request, MultipartFile thumbnail, Member member) throws IOException { TempRecipe tempRecipe = TempRecipe.builder() - .isInfluencer(member.isInfluencer()) + .isBarista(member.isBarista()) .name(request.getName()) .intro(request.getIntro()) .recipeTip(request.getRecipeTip()) @@ -349,7 +382,7 @@ private static Step toStepDto(RecipeRequestDto.StepDto step, Recipe recipe, List if(stepImages != null) imageUrl = uploadStepImage(stepImage); else - throw new RecipeException(CommonStatus.NULL_RECIPE_ERROR); + throw new RecipeException(RecipeStatus.NULL_RECIPE_ERROR); createdStep.setImage(imageUrl); return createdStep; diff --git a/src/main/java/zipdabang/server/domain/member/Member.java b/src/main/java/zipdabang/server/domain/member/Member.java index a68d125..d3af241 100644 --- a/src/main/java/zipdabang/server/domain/member/Member.java +++ b/src/main/java/zipdabang/server/domain/member/Member.java @@ -54,7 +54,7 @@ public class Member extends BaseEntity { private GenderType gender; @Column(columnDefinition = "boolean default false") - private boolean isInfluencer; + private boolean isBarista; @Column(length = 5) private String zipCode; diff --git a/src/main/java/zipdabang/server/domain/recipe/Recipe.java b/src/main/java/zipdabang/server/domain/recipe/Recipe.java index ac64d75..6090fef 100644 --- a/src/main/java/zipdabang/server/domain/recipe/Recipe.java +++ b/src/main/java/zipdabang/server/domain/recipe/Recipe.java @@ -26,7 +26,10 @@ public class Recipe extends BaseEntity { private Long id; @Column(nullable = false) - private Boolean isInfluencer; + private Boolean isBarista; + + @Column(nullable = false) + private Boolean isOfficial; @Column(nullable = false) private String name; @@ -43,8 +46,9 @@ public class Recipe extends BaseEntity { @Column(nullable = false) private String time; - @Column(columnDefinition = "FLOAT DEFAULT 0") - private Float starScore; + @Column(columnDefinition = "BIGINT DEFAULT 0") + private Long totalComments; + @Column(columnDefinition = "BIGINT DEFAULT 0") private Long totalView; @@ -96,6 +100,11 @@ public Recipe setThumbnail(String imageUrl) { return this; } + public Recipe updateComment(Integer i) { + this.totalComments += i; + return this; + } + public Recipe updateLike(Integer i){ this.weekLike += i; this.totalLike += i; diff --git a/src/main/java/zipdabang/server/domain/recipe/TempRecipe.java b/src/main/java/zipdabang/server/domain/recipe/TempRecipe.java index 3296467..14423d0 100644 --- a/src/main/java/zipdabang/server/domain/recipe/TempRecipe.java +++ b/src/main/java/zipdabang/server/domain/recipe/TempRecipe.java @@ -29,7 +29,7 @@ public class TempRecipe extends BaseEntity { private Long id; @Column(nullable = false) - private Boolean isInfluencer; + private Boolean isBarista; private String name; diff --git a/src/main/java/zipdabang/server/repository/recipeRepositories/RecipeRepository.java b/src/main/java/zipdabang/server/repository/recipeRepositories/RecipeRepository.java index d4c3b6b..d457a53 100644 --- a/src/main/java/zipdabang/server/repository/recipeRepositories/RecipeRepository.java +++ b/src/main/java/zipdabang/server/repository/recipeRepositories/RecipeRepository.java @@ -12,25 +12,8 @@ import java.util.Optional; public interface RecipeRepository extends JpaRepository { - List findTop5ByMemberNotInOrderByCreatedAtDesc(List members); - List findTop5ByIsInfluencerTrueAndMemberNotInOrderByCreatedAtDesc(List members); - List findTop5ByIsInfluencerFalseAndMemberNotInOrderByCreatedAtDesc(List members); - - List findTop5ByOrderByCreatedAtDesc(); - - List findTop5ByIsInfluencerTrueOrderByCreatedAtDesc(); - - List findTop5ByIsInfluencerFalseOrderByCreatedAtDesc(); - - Page findByIdIn(List recipeIdList, PageRequest createdAt); - - Page findByIdInAndMemberNotIn(List recipeIdList, List blockedMember, PageRequest createdAt); List findTop5ByIdInAndNameContainingOrderByCreatedAtDesc(List recipeIdList, String keyword); List findTop5ByIdInAndNameContainingAndMemberNotInOrderByCreatedAtDesc(List recipeIdList, String keyword, List blockedMember); - - Page findByIdInAndNameContaining(List recipeIdList, String keyword, PageRequest createdAt); - - Page findByIdInAndNameContainingAndMemberNotIn(List recipeIdList, String keyword, List blockedMember, PageRequest createdAt); } diff --git a/src/main/java/zipdabang/server/repository/recipeRepositories/WeeklyBestRecipeRepository.java b/src/main/java/zipdabang/server/repository/recipeRepositories/WeeklyBestRecipeRepository.java new file mode 100644 index 0000000..f4db000 --- /dev/null +++ b/src/main/java/zipdabang/server/repository/recipeRepositories/WeeklyBestRecipeRepository.java @@ -0,0 +1,7 @@ +package zipdabang.server.repository.recipeRepositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import zipdabang.server.domain.recipe.WeeklyBestRecipe; + +public interface WeeklyBestRecipeRepository extends JpaRepository { +} diff --git a/src/main/java/zipdabang/server/service/RecipeService.java b/src/main/java/zipdabang/server/service/RecipeService.java index 5d5fb9e..faf71d0 100644 --- a/src/main/java/zipdabang/server/service/RecipeService.java +++ b/src/main/java/zipdabang/server/service/RecipeService.java @@ -59,4 +59,10 @@ public interface RecipeService { TempRecipe tempUpdate(Long tempId, RecipeRequestDto.TempRecipeDto request, MultipartFile thumbnail, List stepImages, Member member) throws IOException; List getTop5RecipePerCategory(Long categoryId); + + List getRecipeByOwnerPreview(Long memberId); + + Page getRecipeByOwner(Integer pageIndex, Long memberId); + + List WeekBestRecipe(); } diff --git a/src/main/java/zipdabang/server/service/serviceImpl/RecipeServiceImpl.java b/src/main/java/zipdabang/server/service/serviceImpl/RecipeServiceImpl.java index 5b2efa0..a9c4360 100644 --- a/src/main/java/zipdabang/server/service/serviceImpl/RecipeServiceImpl.java +++ b/src/main/java/zipdabang/server/service/serviceImpl/RecipeServiceImpl.java @@ -1,5 +1,7 @@ package zipdabang.server.service.serviceImpl; +import com.querydsl.core.types.Order; +import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -11,16 +13,22 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import zipdabang.server.apiPayload.code.RecipeStatus; import zipdabang.server.apiPayload.code.CommonStatus; +import zipdabang.server.apiPayload.exception.handler.MemberException; import zipdabang.server.aws.s3.AmazonS3Manager; + import zipdabang.server.apiPayload.exception.handler.RecipeException; + import zipdabang.server.converter.RecipeConverter; import zipdabang.server.domain.Report; import zipdabang.server.domain.member.BlockedMember; import zipdabang.server.domain.member.Member; +import zipdabang.server.domain.member.QFollow; import zipdabang.server.domain.recipe.*; import zipdabang.server.repository.ReportRepository; import zipdabang.server.repository.memberRepositories.BlockedMemberRepository; +import zipdabang.server.repository.memberRepositories.MemberRepository; import zipdabang.server.repository.recipeRepositories.*; import zipdabang.server.service.RecipeService; import zipdabang.server.web.dto.requestDto.RecipeRequestDto; @@ -29,9 +37,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; +import static zipdabang.server.domain.member.QFollow.follow; import static zipdabang.server.domain.recipe.QComment.comment; import static zipdabang.server.domain.recipe.QRecipe.recipe; import static zipdabang.server.domain.recipe.QRecipeCategoryMapping.*; @@ -55,11 +63,13 @@ public class RecipeServiceImpl implements RecipeService { private final ScrapRepository scrapRepository; private final AmazonS3Manager amazonS3Manager; + private final MemberRepository memberRepository; private final BlockedMemberRepository blockedMemberRepository; private final CommentRepository commentRepository; private final ReportRepository reportRepository; private final ReportedCommentRepository reportedCommentRepository; private final ReportedRecipeRepository reportedRecipeRepository; + private final WeeklyBestRecipeRepository weeklyBestRecipeRepository; private final JPAQueryFactory queryFactory; @@ -135,7 +145,7 @@ public TempRecipe tempUpdate(Long tempId, RecipeRequestDto.TempRecipeDto request log.info("service: ", request.toString()); - TempRecipe tempRecipe = tempRecipeRepository.findById(tempId).orElseThrow(() -> new RecipeException(CommonStatus.NO_TEMP_RECIPE_EXIST)); + TempRecipe tempRecipe = tempRecipeRepository.findById(tempId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_TEMP_RECIPE_EXIST)); //recipe String thumbnailUrl = null; @@ -192,11 +202,11 @@ public TempRecipe tempUpdate(Long tempId, RecipeRequestDto.TempRecipeDto request @Override public Recipe getRecipe(Long recipeId, Member member) { - Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(()->new RecipeException(CommonStatus.NO_RECIPE_EXIST)); + Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(()->new RecipeException(RecipeStatus.NO_RECIPE_EXIST)); Optional blockedInfos= blockedMemberRepository.findByOwnerAndBlocked(member, findRecipe.getMember()); if(blockedInfos.isPresent()){ - throw new RecipeException(CommonStatus.BLOCKED_USER_RECIPE); + throw new RecipeException(RecipeStatus.BLOCKED_USER_RECIPE); } else { findRecipe.updateView(); @@ -229,7 +239,7 @@ public Page searchRecipe(Long categoryId, String keyword, Integer pageIn List recipeCategory = recipeCategoryRepository.findAllById(categoryId); if(recipeCategory.isEmpty()) - throw new RecipeException(CommonStatus.RECIPE_NOT_FOUND); + throw new RecipeException(RecipeStatus.RECIPE_NOT_FOUND); QRecipe qRecipe = recipe; QRecipeCategoryMapping qRecipeCategoryMapping = recipeCategoryMapping; @@ -278,14 +288,14 @@ public List getWrittenByRecipePreview(String writtenby, Member member) { } private BooleanExpression checkWrittenBy(String writtenby) { - if (writtenby.equals("influencer")) - return recipe.isInfluencer.eq(true); + if (writtenby.equals("barista")) + return recipe.isBarista.eq(true); else if (writtenby.equals("common")) - return recipe.isInfluencer.eq(false); - else if (writtenby.equals("all")) - return null; + return recipe.isBarista.eq(false); + else if (writtenby.equals("official")) + return recipe.isOfficial.eq(true); else - throw new RecipeException(CommonStatus.WRITTEN_BY_TYPE_ERROR); + throw new RecipeException(RecipeStatus.WRITTEN_BY_TYPE_ERROR); } private BooleanExpression blockedMemberNotInForRecipe(Member member) { @@ -305,10 +315,10 @@ private List getBlockedMember(Member member) { @Override @Transactional(readOnly = false) public Recipe updateLikeOnRecipe(Long recipeId, Member member) { - Recipe recipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(CommonStatus.NO_RECIPE_EXIST)); + Recipe recipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_RECIPE_EXIST)); if(recipe.getMember() == member) - throw new RecipeException(CommonStatus.RECIPE_OWNER); + throw new RecipeException(RecipeStatus.RECIPE_OWNER); Optional likesExist = likesRepository.findByRecipeAndMember(recipe,member); @@ -327,10 +337,10 @@ public Recipe updateLikeOnRecipe(Long recipeId, Member member) { @Override @Transactional(readOnly = false) public Recipe updateScrapOnRecipe(Long recipeId, Member member) { - Recipe recipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(CommonStatus.NO_RECIPE_EXIST)); + Recipe recipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_RECIPE_EXIST)); if(recipe.getMember() == member) - throw new RecipeException(CommonStatus.RECIPE_OWNER); + throw new RecipeException(RecipeStatus.RECIPE_OWNER); Optional scrapExist = scrapRepository.findByRecipeAndMember(recipe,member); if(scrapExist.isEmpty()) { @@ -347,24 +357,40 @@ public Recipe updateScrapOnRecipe(Long recipeId, Member member) { @Override public List getAllRecipeCategories() { - return recipeCategoryRepository.findAll(); + + List categoryList = recipeCategoryRepository.findAll(); + RecipeCategory all = categoryList.remove(0); + categoryList.add(all); + + return categoryList; } @Override public List getTop5RecipePerCategory(Long categoryId) { + QRecipe qRecipe = recipe; QRecipeCategoryMapping qRecipeCategoryMapping = recipeCategoryMapping; - AtomicLong index = new AtomicLong(1); - List recipeList = queryFactory - .selectFrom(recipe) - .join(recipe.categoryMappingList, recipeCategoryMapping).fetchJoin() - .where( - recipeCategoryMapping.category.id.eq(categoryId) - ) - .limit(5) - .orderBy(recipe.totalLike.desc(), recipe.createdAt.desc()) - .fetch(); + List recipeList = new ArrayList<>(); + + if (categoryId == 0){ + recipeList = queryFactory + .selectFrom(recipe) + .limit(5) + .orderBy(recipe.totalLike.desc(), recipe.createdAt.desc()) + .fetch(); + } + else { + recipeList = queryFactory + .selectFrom(recipe) + .join(recipe.categoryMappingList, recipeCategoryMapping).fetchJoin() + .where( + recipeCategoryMapping.category.id.eq(categoryId) + ) + .limit(5) + .orderBy(recipe.totalLike.desc(), recipe.createdAt.desc()) + .fetch(); + } log.info(recipeList.toString()); @@ -374,46 +400,57 @@ public List getTop5RecipePerCategory(Long categoryId) { @Override public Page recipeListByCategory(Long categoryId, Integer pageIndex, Member member, String order) { - List blockedMember = getBlockedMembers(member); + List recipeCategory = recipeCategoryRepository.findAllById(categoryId); - List recipeIdList = new ArrayList<>(); + if(recipeCategory.isEmpty()) + throw new RecipeException(RecipeStatus.RECIPE_NOT_FOUND); - if (categoryId == 0){ - recipeIdList = recipeRepository.findAll().stream() - .map(recipe -> recipe.getId()) - .collect(Collectors.toList()); - } - else{ - List recipeCategory = recipeCategoryRepository.findAllById(categoryId); + QRecipe qRecipe = recipe; + QRecipeCategoryMapping qRecipeCategoryMapping = recipeCategoryMapping; + QFollow qFollow = follow; - if(recipeCategory.isEmpty()) - throw new RecipeException(CommonStatus.RECIPE_NOT_FOUND); + List content = queryFactory + .selectFrom(recipe) + .join(recipe.categoryMappingList, recipeCategoryMapping).fetchJoin() + .where(blockedMemberNotInForRecipe(member), + recipeCategoryMapping.category.id.eq(categoryId) + ) + .orderBy(order(order, member), recipe.createdAt.desc()) + .offset(pageIndex*pageSize) + .limit(pageSize) + .fetch(); - recipeIdList = recipeCategoryMappingRepository.findByCategoryIn(recipeCategory).stream() - .map(categoryMapping -> categoryMapping.getRecipe().getId()) - .collect(Collectors.toList()); - } + JPAQuery count = queryFactory + .select(recipe.count()) + .from(recipe) + .join(recipe.categoryMappingList, recipeCategoryMapping) + .where(blockedMemberNotInForRecipe(member), + recipeCategoryMapping.category.id.eq(categoryId) + ); - String orderBy = null; + return new PageImpl<>(content,PageRequest.of(pageIndex,pageSize), count.fetchOne()); + } + private OrderSpecifier order(String order, Member member) { if(order == null) order = "latest"; if(order.equals("likes")) - orderBy = "totalLike"; - else if(order.equals("views")) - orderBy = "totalView"; + return new OrderSpecifier<>(Order.DESC, recipe.totalLike); + else if(order.equals("follow")) + return new OrderSpecifier(Order.DESC, recipe.member.eq(queryFactory + .select(follow.followee) + .from(follow) + .where( + follow.follower.eq(member) + ) + .orderBy(recipe.createdAt.desc()) + ) + ); else if(order.equals("latest")) - orderBy = "createdAt"; - else - throw new RecipeException(CommonStatus.ORDER_BY_TYPE_ERROR); - - if(blockedMember.isEmpty()) - return recipeRepository.findByIdIn(recipeIdList, - PageRequest.of(pageIndex, pageSize, Sort.by(Sort.Direction.DESC, orderBy))); + return new OrderSpecifier(Order.DESC, recipe.createdAt); else - return recipeRepository.findByIdInAndMemberNotIn(recipeIdList,blockedMember, - PageRequest.of(pageIndex, pageSize, Sort.by(Sort.Direction.DESC, orderBy))); + throw new RecipeException(RecipeStatus.ORDER_BY_TYPE_ERROR); } @Override @@ -445,6 +482,55 @@ public List> searchRecipePreview(String keyword, Member member) { return recipeList; } + @Override + public List WeekBestRecipe() { + List bestRecipes = weeklyBestRecipeRepository.findAll(); + + return bestRecipes; + } + + @Override + public List getRecipeByOwnerPreview(Long memberId) { + Member findMember = memberRepository.findById(memberId).orElseThrow(() -> new MemberException(CommonStatus.MEMBER_NOT_FOUND)); + + QRecipe qRecipe = recipe; + + List recipeList = queryFactory + .selectFrom(recipe) + .where( + recipe.member.eq(findMember) + ) + .limit(5) + .orderBy(recipe.createdAt.desc()) + .fetch(); + + return recipeList; + } + + @Override + public Page getRecipeByOwner(Integer pageIndex, Long memberId) { + + Member findMember = memberRepository.findById(memberId).orElseThrow(() -> new MemberException(CommonStatus.MEMBER_NOT_FOUND)); + + QRecipe qRecipe = recipe; + + List content = queryFactory + .selectFrom(recipe) + .where(recipe.member.eq(findMember)) + .orderBy(recipe.createdAt.desc()) + .offset(pageIndex*pageSize) + .limit(pageSize) + .fetch(); + + + JPAQuery count = queryFactory + .select(recipe.count()) + .from(recipe) + .where(recipe.member.eq(findMember)); + + return PageableExecutionUtils.getPage(content,PageRequest.of(pageIndex,pageSize), ()->count.fetchOne()); + } + private List getBlockedMembers(Member member) { List blockedMember = getBlockedMember(member); @@ -458,7 +544,7 @@ public List getRecipeBannerList() { @Transactional(readOnly = false) @Override public Boolean deleteRecipe(Long recipeId, Member member) { - Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(CommonStatus.NO_RECIPE_EXIST)); + Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_RECIPE_EXIST)); if (findRecipe.getMember().equals(member)) { amazonS3Manager.deleteFile(RecipeConverter.toKeyName(findRecipe.getThumbnailUrl()).substring(1)); @@ -467,7 +553,7 @@ public Boolean deleteRecipe(Long recipeId, Member member) { recipeRepository.deleteById(recipeId); } else - throw new RecipeException(CommonStatus.NOT_RECIPE_OWNER); + throw new RecipeException(RecipeStatus.NOT_RECIPE_OWNER); return recipeRepository.existsById(recipeId) == false; } @@ -475,7 +561,7 @@ public Boolean deleteRecipe(Long recipeId, Member member) { @Transactional(readOnly = false) @Override public Long reportRecipe(Long recipeId, Long reportId, Member member) { - Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(CommonStatus.NO_RECIPE_EXIST)); + Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_RECIPE_EXIST)); Report findReport = reportRepository.findById(reportId).orElseThrow(() -> new RecipeException(CommonStatus.NO_REPORT_EXIST)); if (!findRecipe.getMember().equals(member)) { @@ -485,13 +571,14 @@ public Long reportRecipe(Long recipeId, Long reportId, Member member) { return findRecipe.getId(); } else - throw new RecipeException(CommonStatus.RECIPE_OWNER); + throw new RecipeException(RecipeStatus.RECIPE_OWNER); } @Transactional(readOnly = false) @Override public Comment createComment(String content, Long recipeId, Member member) { - Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(CommonStatus.NO_RECIPE_EXIST)); + Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_RECIPE_EXIST)); + findRecipe.updateComment(1); Comment buildComment = RecipeConverter.toComment(content, findRecipe, member); return commentRepository.save(buildComment); @@ -499,7 +586,7 @@ public Comment createComment(String content, Long recipeId, Member member) { @Override public Page commentList(Integer pageIndex, Long recipeId, Member member) { - recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(CommonStatus.NO_RECIPE_EXIST)); + recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_RECIPE_EXIST)); QComment qComment = comment; @@ -529,14 +616,15 @@ private BooleanExpression blockedMemberNotInForComment(Member member) { @Transactional(readOnly = false) @Override public Boolean deleteComment(Long recipeId, Long commentId, Member member) { - Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(CommonStatus.NO_RECIPE_EXIST)); - Comment findComment = commentRepository.findById(commentId).orElseThrow(() -> new RecipeException(CommonStatus.NO_COMMENT_EXIST)); + Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_RECIPE_EXIST)); + Comment findComment = commentRepository.findById(commentId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_COMMENT_EXIST)); if (findComment.getMember().equals(member) && findComment.getRecipe().equals(findRecipe)) { commentRepository.deleteById(commentId); + findRecipe.updateComment(-1); } else - throw new RecipeException(CommonStatus.NOT_COMMENT_OWNER); + throw new RecipeException(RecipeStatus.NOT_COMMENT_OWNER); return commentRepository.existsById(recipeId) == false; } @@ -544,22 +632,22 @@ public Boolean deleteComment(Long recipeId, Long commentId, Member member) { @Transactional(readOnly = false) @Override public Comment updateComment(RecipeRequestDto.updateCommentDto request, Long recipeId, Long commentId, Member member) { - Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(CommonStatus.NO_RECIPE_EXIST)); - Comment findComment = commentRepository.findById(commentId).orElseThrow(() -> new RecipeException(CommonStatus.NO_COMMENT_EXIST)); + Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_RECIPE_EXIST)); + Comment findComment = commentRepository.findById(commentId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_COMMENT_EXIST)); if (findComment.getMember().equals(member) && findComment.getRecipe().equals(findRecipe)) { return findComment.updateContent(request.getComment()); } else - throw new RecipeException(CommonStatus.NOT_COMMENT_OWNER); + throw new RecipeException(RecipeStatus.NOT_COMMENT_OWNER); } @Transactional(readOnly = false) @Override public Long reportComment(Long recipeId, Long commentId, Long reportId, Member member) { - Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(CommonStatus.NO_RECIPE_EXIST)); - Comment findComment = commentRepository.findById(commentId).orElseThrow(() -> new RecipeException(CommonStatus.NO_COMMENT_EXIST)); + Recipe findRecipe = recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_RECIPE_EXIST)); + Comment findComment = commentRepository.findById(commentId).orElseThrow(() -> new RecipeException(RecipeStatus.NO_COMMENT_EXIST)); Report findReport = reportRepository.findById(reportId).orElseThrow(() -> new RecipeException(CommonStatus.NO_REPORT_EXIST)); if (!findComment.getMember().equals(member) && findComment.getRecipe().equals(findRecipe)) { @@ -569,6 +657,6 @@ public Long reportComment(Long recipeId, Long commentId, Long reportId, Member m return findComment.getId(); } else - throw new RecipeException(CommonStatus.COMMENT_OWNER); + throw new RecipeException(RecipeStatus.COMMENT_OWNER); } } diff --git a/src/main/java/zipdabang/server/validation/validator/ExistRecipeCategoryValidator.java b/src/main/java/zipdabang/server/validation/validator/ExistRecipeCategoryValidator.java index 296f9f9..a707bf7 100644 --- a/src/main/java/zipdabang/server/validation/validator/ExistRecipeCategoryValidator.java +++ b/src/main/java/zipdabang/server/validation/validator/ExistRecipeCategoryValidator.java @@ -3,6 +3,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import zipdabang.server.apiPayload.code.CommonStatus; +import zipdabang.server.apiPayload.code.RecipeStatus; import zipdabang.server.domain.recipe.RecipeCategory; import zipdabang.server.repository.recipeRepositories.RecipeCategoryRepository; import zipdabang.server.validation.annotation.ExistRecipeCategory; @@ -27,7 +28,7 @@ public boolean isValid(Long value, ConstraintValidatorContext context) { Optional findRecipeCategory = recipeCategoryRepository.findById(value); if(findRecipeCategory.isEmpty()){ context.disableDefaultConstraintViolation(); - context.buildConstraintViolationWithTemplate(CommonStatus.NO_RECIPE_CATEGORY_EXIST.toString()).addConstraintViolation(); + context.buildConstraintViolationWithTemplate(RecipeStatus.NO_RECIPE_CATEGORY_EXIST.toString()).addConstraintViolation(); return false; } return true; diff --git a/src/main/java/zipdabang/server/web/controller/RecipeRestController.java b/src/main/java/zipdabang/server/web/controller/RecipeRestController.java index 4ab068a..4071e95 100644 --- a/src/main/java/zipdabang/server/web/controller/RecipeRestController.java +++ b/src/main/java/zipdabang/server/web/controller/RecipeRestController.java @@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import zipdabang.server.apiPayload.code.CommonStatus; +import zipdabang.server.apiPayload.code.RecipeStatus; import zipdabang.server.apiPayload.reponse.ResponseDto; import zipdabang.server.auth.handler.annotation.AuthMember; import zipdabang.server.apiPayload.exception.handler.RecipeException; @@ -22,6 +23,7 @@ import zipdabang.server.domain.member.Member; import zipdabang.server.domain.recipe.*; import zipdabang.server.service.RecipeService; +import zipdabang.server.validation.annotation.CheckPage; import zipdabang.server.validation.annotation.CheckTempMember; import zipdabang.server.validation.annotation.ExistRecipeCategory; import zipdabang.server.web.dto.requestDto.RecipeRequestDto; @@ -188,11 +190,11 @@ public ResponseDto searchRecipePre }) @Parameters({ @Parameter(name = "member", hidden = true), - @Parameter(name = "pageIndex", description = "query string 페이지 번호, 안주면 1으로(최초 페이지) 설정함, 0 이런거 주면 에러 뱉음"), + @Parameter(name = "pageIndex", description = "query string 페이지 번호, 무조건 값 줘야 함, 0 이런거 주면 에러 뱉음"), @Parameter(name = "keyword", description = "query string 검색할 단어") }) @GetMapping(value = "/members/recipes/search/{categoryId}") - public ResponseDto searchRecipe(@ExistRecipeCategory @PathVariable Long categoryId, @RequestParam(name = "keyword") String keyword, @RequestParam(name = "pageIndex", required = false) Integer pageIndex, @AuthMember Member member) { + public ResponseDto searchRecipe(@ExistRecipeCategory @PathVariable Long categoryId, @RequestParam(name = "keyword") String keyword, @RequestParam(name = "pageIndex") Integer pageIndex, @AuthMember Member member) { if (pageIndex == null) pageIndex = 1; @@ -204,7 +206,7 @@ else if (pageIndex < 1) Page recipes = recipeService.searchRecipe(categoryId, keyword, pageIndex, member); if (recipes.getTotalElements() == 0) - throw new RecipeException(CommonStatus.RECIPE_NOT_FOUND); + throw new RecipeException(RecipeStatus.RECIPE_NOT_FOUND); if (pageIndex >= recipes.getTotalPages()) throw new RecipeException(CommonStatus.OVER_PAGE_INDEX_ERROR); @@ -245,7 +247,6 @@ public ResponseDto RecipeCategoryTop5(@Exi @ApiResponse(responseCode = "4008", description = "UNAUTHORIZED, 토큰 없음, 토큰 줘요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @ApiResponse(responseCode = "4052", description = "BAD_REQUEST, 사용자가 없습니다. 이 api에서 이거 생기면 백앤드 개발자 호출", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @ApiResponse(responseCode = "4053", description = "BAD_REQUEST, 넘겨받은 categoryId와 일치하는 카테고리 없음. 1~6 사이로 보내세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), - @ApiResponse(responseCode = "4054", description = "BAD_REQUEST, 페이지 번호 0 이하입니다. 1 이상으로 주세요.", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @ApiResponse(responseCode = "4055", description = "BAD_REQUEST, 페이지 인덱스 범위 초과함", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @ApiResponse(responseCode = "4104", description = "BAD_REQUEST, 조회 방식 타입이 잘못되었습니다. likes, views, lastest중 하나로 보내주세요.", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @ApiResponse(responseCode = "4105", description = "BAD_REQUEST, 해당 id를 가진 레시피 카테고리가 없습니다. 잘못 보내줬어요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @@ -253,16 +254,14 @@ public ResponseDto RecipeCategoryTop5(@Exi }) @Parameters({ @Parameter(name = "member", hidden = true), - @Parameter(name = "pageIndex", description = "query string 페이지 번호, 안주면 1으로(최초 페이지) 설정함, 0 이런거 주면 에러 뱉음"), - @Parameter(name = "order", description = "query string 조회 방식. 인기순: likes, 조회순: views, 최신순: latest로 넘겨주세요, 기본값 latest") + @Parameter(name = "pageIndex", description = "query string 페이지 번호, 무조건 값 줘야 함, 0 이런거 주면 에러 뱉음"), + @Parameter(name = "order", description = "query string 조회 방식. 인기순: likes, 팔로우순: follow, 최신순: latest로 넘겨주세요, 기본값 latest") }) @GetMapping(value = "/members/recipes/categories/{categoryId}") - public ResponseDto recipeListByCategory(@ExistRecipeCategory @PathVariable Long categoryId, @RequestParam(name = "order", required = false) String order, @RequestParam(name = "pageIndex", required = false) Integer pageIndex, @AuthMember Member member) { + public ResponseDto recipeListByCategory(@ExistRecipeCategory @PathVariable Long categoryId, @RequestParam(name = "order", required = false) String order, @CheckPage @RequestParam(name = "pageIndex") Integer pageIndex, @AuthMember Member member) { if (pageIndex == null) pageIndex = 1; - else if (pageIndex < 1) - throw new RecipeException(CommonStatus.UNDER_PAGE_INDEX_ERROR); pageIndex -= 1; @@ -272,7 +271,7 @@ else if (pageIndex < 1) log.info(recipes.toString()); if (recipes.getTotalElements() == 0) - throw new RecipeException(CommonStatus.RECIPE_NOT_FOUND); + throw new RecipeException(RecipeStatus.RECIPE_NOT_FOUND); if (pageIndex >= recipes.getTotalPages()) throw new RecipeException(CommonStatus.OVER_PAGE_INDEX_ERROR); @@ -287,12 +286,12 @@ else if (pageIndex < 1) @ApiResponse(responseCode = "4005", description = "UNAUTHORIZED, 엑세스 토큰 만료, 리프레시 토큰 사용", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @ApiResponse(responseCode = "4008", description = "UNAUTHORIZED, 토큰 없음, 토큰 줘요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @ApiResponse(responseCode = "4052", description = "BAD_REQUEST, 사용자가 없습니다. 이 api에서 이거 생기면 백앤드 개발자 호출", content = @Content(schema = @Schema(implementation = ResponseDto.class))), - @ApiResponse(responseCode = "4103", description = "BAD_REQUEST, 레시피 작성자 타입이 잘못되었습니다. all, influencer, common중 하나로 보내주세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + @ApiResponse(responseCode = "4103", description = "BAD_REQUEST, 레시피 작성자 타입이 잘못되었습니다. official, barista, common중 하나로 보내주세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @ApiResponse(responseCode = "5000", description = "SERVER ERROR, 백앤드 개발자에게 알려주세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), }) @Parameters({ @Parameter(name = "member", hidden = true), - @Parameter(name = "writtenby", description = "query string 누가 쓴 레시피 종류인지. 모든 사람: all, 인플루언서: influencer, 우리들: common으로 넘겨주세요") + @Parameter(name = "writtenby", description = "query string 누가 쓴 레시피 종류인지. 공식: official, 바리스타: barista, 우리들: common으로 넘겨주세요") }) @GetMapping(value = "/members/recipes/types/preview") public ResponseDto recipeListPreviewWrittenBy(@RequestParam(name = "writtenby") String writtenby, @AuthMember Member member) { @@ -301,7 +300,7 @@ public ResponseDto recipeListPreviewWrittenBy(@ log.info(recipes.toString()); if (recipes.size() == 0) - throw new RecipeException(CommonStatus.RECIPE_NOT_FOUND); + throw new RecipeException(RecipeStatus.RECIPE_NOT_FOUND); return ResponseDto.of(RecipeConverter.toPreviewRecipeDtoList(recipes, member)); } @@ -315,22 +314,77 @@ public ResponseDto recipeListPreviewWrittenBy(@ @ApiResponse(responseCode = "4008", description = "UNAUTHORIZED, 토큰 없음, 토큰 줘요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @ApiResponse(responseCode = "4052", description = "BAD_REQUEST, 사용자가 없습니다. 이 api에서 이거 생기면 백앤드 개발자 호출", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @ApiResponse(responseCode = "4053", description = "BAD_REQUEST, 넘겨받은 categoryId와 일치하는 카테고리 없음. 1~6 사이로 보내세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), - @ApiResponse(responseCode = "4054", description = "BAD_REQUEST, 페이지 번호 0 이하입니다. 1 이상으로 주세요.", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @ApiResponse(responseCode = "4055", description = "BAD_REQUEST, 페이지 인덱스 범위 초과함", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @ApiResponse(responseCode = "5000", description = "SERVER ERROR, 백앤드 개발자에게 알려주세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), }) @Parameters({ @Parameter(name = "member", hidden = true), - @Parameter(name = "writtenby", description = "query string 누가 쓴 레시피 종류인지. 모든 사람: all, 인플루언서: influencer, 우리들: common으로 넘겨주세요"), - @Parameter(name = "pageIndex", description = "query string 페이지 번호, 안주면 0으로(최초 페이지) 설정함, -1 이런거 주면 에러 뱉음"), - @Parameter(name = "order", description = "query string 조회 방식. 인기순: likes, 조회순: views, 최신순: latest로 넘겨주세요") + @Parameter(name = "writtenby", description = "query string 누가 쓴 레시피 종류인지. 공식: official, 바리스타: barista, 우리들: common으로 넘겨주세요"), + @Parameter(name = "pageIndex", description = "query string 페이지 번호, 무조건 값 줘야 함, -1 이런거 주면 에러 뱉음"), + @Parameter(name = "order", description = "query string 조회 방식. 인기순: likes, 조회순: name, 최신순: latest로 넘겨주세요") }) @GetMapping(value = "/members/recipes/types") - public ResponseDto recipeListWrittenBy(@RequestParam(name = "writtenby") String writtenby, @RequestParam(name = "order") String order, @RequestParam(name = "pageIndex", required = false) Integer pageIndex, @AuthMember Member member) { + public ResponseDto recipeListWrittenBy(@RequestParam(name = "writtenby") String writtenby, @RequestParam(name = "order") String order, @CheckPage @RequestParam(name = "pageIndex") Integer pageIndex, @AuthMember Member member) { return null; } - @Operation(summary = "🏠figma 홈1, 주간 베스트 레시피 API 🔑", description = "이번 주 베스트 레시피 API입니다.") + @Operation(summary = "특정 유저의 레시피 미리보기 목록 API 🔑 ✔", description = "특정 유저의 레시피 미리기보기 목록") + @ApiResponses({ + @ApiResponse(responseCode = "2000", description = "OK, 목록이 있을 땐 이 응답임"), + @ApiResponse(responseCode = "2100", description = "OK, 목록이 없을 경우, result = null", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + @ApiResponse(responseCode = "4003", description = "UNAUTHORIZED, 토큰 모양이 이상함, 토큰 제대로 주세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + @ApiResponse(responseCode = "4005", description = "UNAUTHORIZED, 엑세스 토큰 만료, 리프레시 토큰 사용", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + @ApiResponse(responseCode = "4008", description = "UNAUTHORIZED, 토큰 없음, 토큰 줘요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + @ApiResponse(responseCode = "4052", description = "BAD_REQUEST, 해당 memberId를 가진 사용자가 없습니다.", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + @ApiResponse(responseCode = "5000", description = "SERVER ERROR, 백앤드 개발자에게 알려주세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + }) + @Parameters({ + @Parameter(name = "member", hidden = true), + }) + @GetMapping(value = "/members/recipes/owner/preview/{memberId}") + public ResponseDto recipeByOwnerPreview(@PathVariable Long memberId, @AuthMember Member member) { + List recipes = recipeService.getRecipeByOwnerPreview(memberId); + + return ResponseDto.of(RecipeConverter.toPreviewRecipeDtoList(recipes, member)); + } + + @Operation(summary = "특정 유저의 레시피 목록 API 🔑 ✔", description = "특정 유저의 레시피 목록") + @ApiResponses({ + @ApiResponse(responseCode = "2000", description = "OK, 목록이 있을 땐 이 응답임"), + @ApiResponse(responseCode = "2100", description = "OK, 목록이 없을 경우, result = null", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + @ApiResponse(responseCode = "4003", description = "UNAUTHORIZED, 토큰 모양이 이상함, 토큰 제대로 주세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + @ApiResponse(responseCode = "4005", description = "UNAUTHORIZED, 엑세스 토큰 만료, 리프레시 토큰 사용", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + @ApiResponse(responseCode = "4008", description = "UNAUTHORIZED, 토큰 없음, 토큰 줘요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + @ApiResponse(responseCode = "4052", description = "BAD_REQUEST, 해당 memberId를 가진 사용자가 없습니다.", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + @ApiResponse(responseCode = "4055", description = "BAD_REQUEST, 페이지 인덱스 범위 초과함", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + @ApiResponse(responseCode = "5000", description = "SERVER ERROR, 백앤드 개발자에게 알려주세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), + }) + @Parameters({ + @Parameter(name = "member", hidden = true), + @Parameter(name = "pageIndex", description = "query string 페이지 번호, 무조건 값 줘야 함, -1 이런거 주면 에러 뱉음"), + }) + @GetMapping(value = "/members/recipes/owner/{memberId}") + public ResponseDto recipeByOwner(@CheckPage @RequestParam(name = "pageIndex") Integer pageIndex, + @PathVariable Long memberId, + @AuthMember Member member) { + if (pageIndex == null) + pageIndex = 1; + + pageIndex -= 1; + + Page recipes = recipeService.getRecipeByOwner(pageIndex, memberId); + + log.info(recipes.toString()); + + if (recipes.getTotalElements() == 0) + throw new RecipeException(RecipeStatus.RECIPE_NOT_FOUND); + if (pageIndex >= recipes.getTotalPages()) + throw new RecipeException(CommonStatus.OVER_PAGE_INDEX_ERROR); + + return ResponseDto.of(RecipeConverter.toPagingRecipeDtoList(recipes, member)); + } + + @Operation(summary = "🏠figma 홈1, 주간 베스트 레시피 API 🔑 ✔", description = "이번 주 베스트 레시피 API입니다.") @ApiResponses({ @ApiResponse(responseCode = "2000", description = "OK, 목록이 있을 땐 이 응답임"), @ApiResponse(responseCode = "2100", description = "OK, 목록이 없을 경우, result = null", content = @Content(schema = @Schema(implementation = ResponseDto.class))), @@ -344,8 +398,10 @@ public ResponseDto recipeListWrittenBy(@Req @Parameter(name = "member", hidden = true), }) @GetMapping(value = "/members/recipes/week-best") - public ResponseDto recipeWeekBest(@AuthMember Member member) { - return null; + public ResponseDto recipeWeekBest(@AuthMember Member member) { + List bestRecipes = recipeService.WeekBestRecipe(); + + return ResponseDto.of(RecipeConverter.toWeekBestDtoList(bestRecipes, member)); } @Operation(summary = "레시피 스크랩/취소 API 🔑 ✔", description = "레시피 스크랩/취소 API입니다.") @@ -443,27 +499,6 @@ public ResponseDto reportRecipe(@PathVariable Long recipeId, @PathVariab return ResponseDto.of(reportedRecipeId+"번 레시피가 신고되었습니다."); } -// @Operation(summary = "레시피 차단 API 🔑 ✔", description = "래시피 차단 API입니다.") -// @ApiResponses({ -// @ApiResponse(responseCommonStatus = "2000", description = "OK, 레시피가 차단 되었습니다."), -// @ApiResponse(responseCommonStatus = "4003", description = "UNAUTHORIZED, 토큰 모양이 이상함, 토큰 제대로 주세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "4005", description = "UNAUTHORIZED, 엑세스 토큰 만료, 리프레시 토큰 사용", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "4008", description = "UNAUTHORIZED, 토큰 없음, 토큰 줘요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "4052", description = "BAD_REQUEST, 사용자가 없습니다. 이 api에서 이거 생기면 백앤드 개발자 호출", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "4101", description = "BAD_REQUEST, 해당 recipeId를 가진 recipe가 없어요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "4109", description = "BAD_REQUEST, 본인의 레시피입니다. 신고/차단할 수 없습니다", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "5000", description = "SERVER ERROR, 백앤드 개발자에게 알려주세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// }) -// @Parameters({ -// @Parameter(name = "member", hidden = true), -// }) -// @GetMapping("/members/recipes/{recipeId}/block") -// public ResponseDto blockRecipe(@PathVariable(name = "recipeId") Long recipeId, @CheckTempMember @AuthMember Member member) { -// Long blockRecipeId = recipeService.blockRecipe(recipeId, member); -// -// return ResponseDto.of(blockRecipeId+"번 레시피가 차단되었습니다."); -// } - @Operation(summary = "댓글 등록 API 🔑 ✔", description = "레시피 (작성)등록 API입니다.") @ApiResponses({ @ApiResponse(responseCode = "2000"), @@ -499,10 +534,10 @@ public ResponseDto createComment(@RequestBody Reci }) @Parameters({ @Parameter(name = "member", hidden = true), - @Parameter(name = "pageIndex", description = "query string 페이지 번호, 안주면 1으로(최초 페이지) 설정함, 0 이런거 주면 에러 뱉음"), + @Parameter(name = "pageIndex", description = "query string 페이지 번호, 무조건 값 줘야 함, 0 이런거 주면 에러 뱉음"), }) @GetMapping(value = "/members/recipes/{recipeId}/comments") - public ResponseDto searchRecipe(@PathVariable Long recipeId, @RequestParam(name = "pageIndex", required = false) Integer pageIndex, @AuthMember Member member) { + public ResponseDto searchRecipe(@PathVariable Long recipeId, @RequestParam(name = "pageIndex") Integer pageIndex, @AuthMember Member member) { if (pageIndex == null) pageIndex = 1; @@ -591,26 +626,4 @@ public ResponseDto reportComment(@PathVariable Long recipeId, @PathVaria return ResponseDto.of(reportedCommentId+"번 댓글이 신고되었습니다."); } - -// @Operation(summary = "댓글 차단 API 🔑 ✔", description = "댓글 차단 API입니다.") -// @ApiResponses({ -// @ApiResponse(responseCommonStatus = "2000", description = "OK, 댓글이 차단 되었습니다."), -// @ApiResponse(responseCommonStatus = "4003", description = "UNAUTHORIZED, 토큰 모양이 이상함, 토큰 제대로 주세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "4005", description = "UNAUTHORIZED, 엑세스 토큰 만료, 리프레시 토큰 사용", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "4008", description = "UNAUTHORIZED, 토큰 없음, 토큰 줘요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "4052", description = "BAD_REQUEST, 사용자가 없습니다. 이 api에서 이거 생기면 백앤드 개발자 호출", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "4101", description = "BAD_REQUEST, 해당 recipeId를 가진 recipe가 없어요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "4107", description = "BAD_REQUEST, 해당 commentId를 가진 댓글이 없어요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "4110", description = "BAD_REQUEST, 본인의 댓글입니다. 신고/차단할 수 없습니다", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// @ApiResponse(responseCommonStatus = "5000", description = "SERVER ERROR, 백앤드 개발자에게 알려주세요", content = @Content(schema = @Schema(implementation = ResponseDto.class))), -// }) -// @Parameters({ -// @Parameter(name = "member", hidden = true), -// }) -// @GetMapping("/members/recipes/{recipeId}/{commentId}/block") -// public ResponseDto blockComment(@PathVariable(name = "recipeId") Long recipeId, @PathVariable(name = "commentId") Long commentId, @CheckTempMember @AuthMember Member member) { -// Long blockCommentId = recipeService.blockComment(recipeId, commentId, member); -// -// return ResponseDto.of(blockCommentId+"번 댓글이 차단되었습니다."); -// } } diff --git a/src/main/java/zipdabang/server/web/dto/responseDto/RecipeResponseDto.java b/src/main/java/zipdabang/server/web/dto/responseDto/RecipeResponseDto.java index a78ef0d..8c62f2d 100644 --- a/src/main/java/zipdabang/server/web/dto/responseDto/RecipeResponseDto.java +++ b/src/main/java/zipdabang/server/web/dto/responseDto/RecipeResponseDto.java @@ -44,9 +44,10 @@ public static class RecipePreviewDto { private String nickname; private String thumbnailUrl; private Long likes; - private Long scraps; + private Long comments; private Boolean isLiked; private Boolean isScrapped; + private Integer rank; } @Builder @@ -68,6 +69,34 @@ public static class RecipeSimpleDto { private Boolean isScrapped; } + @Builder + @Getter + @AllArgsConstructor(access = AccessLevel.PROTECTED) + @NoArgsConstructor(access = AccessLevel.PROTECTED) + public static class RecipeSimpleDtoBest { + private Long recipeId; + private String recipeName; + private String nickname; + private String thumbnailUrl; + private String createdAt; + private String updatedAt; + private Long likes; + private Long comments; + private Long scraps; + private Boolean isLiked; + private Boolean isScrapped; + private Integer rank; + } + + @Builder + @Getter + @AllArgsConstructor(access = AccessLevel.PROTECTED) + @NoArgsConstructor(access = AccessLevel.PROTECTED) + public static class WeekBestDtoList { + private List recipeList; + Integer totalElements; + } + @Builder @Getter @AllArgsConstructor(access = AccessLevel.PROTECTED) @@ -137,6 +166,7 @@ public static class SearchRecipePreviewByCategoryDto { @NoArgsConstructor(access = AccessLevel.PROTECTED) public static class RecipeInfoDto { private RecipeDto recipeInfo; + private Long ownerId; private boolean isOwner; private List steps; private List ingredients;