Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

✨ api versioning #369

Merged
merged 2 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import net.pengcook.recipe.dto.PageRecipeRequest;
import net.pengcook.recipe.dto.RecipeDescriptionResponse;
import net.pengcook.recipe.dto.RecipeHomeWithMineResponse;
import net.pengcook.recipe.dto.RecipeHomeWithMineResponseV1;
import net.pengcook.recipe.dto.RecipeRequest;
import net.pengcook.recipe.dto.RecipeResponse;
import net.pengcook.recipe.dto.RecipeStepResponse;
Expand Down Expand Up @@ -40,11 +41,24 @@ public List<RecipeHomeWithMineResponse> readRecipes(
return recipeService.readRecipes(userInfo, pageRecipeRequest);
}

@GetMapping(produces = "application/vnd.pengcook.v1+json")
public List<RecipeHomeWithMineResponseV1> readRecipesV1(
@LoginUser UserInfo userInfo,
@ModelAttribute @Valid PageRecipeRequest pageRecipeRequest
) {
return recipeService.readRecipesV1(userInfo, pageRecipeRequest);
}

@GetMapping("/likes")
public List<RecipeHomeWithMineResponse> readLikeRecipes(@LoginUser UserInfo userInfo) {
return recipeService.readLikeRecipes(userInfo);
}

@GetMapping(value = "/likes", produces = "application/vnd.pengcook.v1+json")
public List<RecipeHomeWithMineResponseV1> readLikeRecipesV1(@LoginUser UserInfo userInfo) {
return recipeService.readLikeRecipesV1(userInfo);
}

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public RecipeResponse createRecipe(@LoginUser UserInfo userInfo, @RequestBody @Valid RecipeRequest recipeRequest) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,46 @@
package net.pengcook.recipe.dto;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import net.pengcook.authentication.domain.UserInfo;

public record RecipeHomeWithMineResponse(
long recipeId,
String title,
AuthorResponse author,
LocalTime cookingTime,
String thumbnail,
int difficulty,
int likeCount,
int commentCount,
String description,
LocalDateTime createdAt,
List<CategoryResponse> category,
List<IngredientResponse> ingredient,
boolean mine
) {

public RecipeHomeWithMineResponse(
UserInfo userInfo,
RecipeHomeResponse firstResponse
RecipeDataResponse firstResponse,
List<CategoryResponse> category,
List<IngredientResponse> ingredient

) {
this(
firstResponse.recipeId(),
firstResponse.title(),
new AuthorResponse(firstResponse.authorId(), firstResponse.authorName(), firstResponse.authorImage()),
firstResponse.cookingTime(),
firstResponse.thumbnail(),
firstResponse.difficulty(),
firstResponse.likeCount(),
firstResponse.commentCount(),
firstResponse.description(),
firstResponse.createdAt(),
category,
ingredient,
userInfo.isSameUser(firstResponse.authorId())
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package net.pengcook.recipe.dto;

import java.time.LocalDateTime;
import net.pengcook.authentication.domain.UserInfo;

public record RecipeHomeWithMineResponseV1(
long recipeId,
String title,
AuthorResponse author,
String thumbnail,
int likeCount,
int commentCount,
LocalDateTime createdAt,
boolean mine
) {

public RecipeHomeWithMineResponseV1(
UserInfo userInfo,
RecipeHomeResponse firstResponse
) {
this(
firstResponse.recipeId(),
firstResponse.title(),
new AuthorResponse(firstResponse.authorId(), firstResponse.authorName(), firstResponse.authorImage()),
firstResponse.thumbnail(),
firstResponse.likeCount(),
firstResponse.commentCount(),
firstResponse.createdAt(),
userInfo.isSameUser(firstResponse.authorId())
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,35 @@ List<Long> findRecipeIdsByCategoryAndKeyword(
@Param("userId") @Nullable Long userId
);

@Query("""
SELECT new net.pengcook.recipe.dto.RecipeDataResponse(
r.id,
r.title,
r.author.id,
r.author.username,
r.author.image,
r.cookingTime,
r.thumbnail,
r.difficulty,
r.likeCount,
r.commentCount,
r.description,
r.createdAt,
c.id,
c.name,
i.id,
i.name,
ir.requirement
)
FROM Recipe r
JOIN FETCH CategoryRecipe cr ON cr.recipe = r
JOIN FETCH Category c ON cr.category = c
JOIN FETCH IngredientRecipe ir ON ir.recipe = r
JOIN FETCH Ingredient i ON ir.ingredient = i
WHERE r.id IN :recipeIds
""")
List<RecipeDataResponse> findRecipeData(List<Long> recipeIds);

@Query("""
SELECT new net.pengcook.recipe.dto.RecipeHomeResponse(
r.id,
Expand All @@ -44,7 +73,7 @@ List<Long> findRecipeIdsByCategoryAndKeyword(
FROM Recipe r
WHERE r.id IN :recipeIds
""")
List<RecipeHomeResponse> findRecipeData(List<Long> recipeIds);
List<RecipeHomeResponse> findRecipeDataV1(List<Long> recipeIds);

@Query("""
SELECT new net.pengcook.recipe.dto.RecipeDataResponse(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.pengcook.recipe.service;

import java.time.LocalTime;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
Expand All @@ -22,6 +23,7 @@
import net.pengcook.recipe.dto.RecipeDescriptionResponse;
import net.pengcook.recipe.dto.RecipeHomeResponse;
import net.pengcook.recipe.dto.RecipeHomeWithMineResponse;
import net.pengcook.recipe.dto.RecipeHomeWithMineResponseV1;
import net.pengcook.recipe.dto.RecipeRequest;
import net.pengcook.recipe.dto.RecipeResponse;
import net.pengcook.recipe.exception.UnauthorizedException;
Expand Down Expand Up @@ -58,22 +60,44 @@ public List<RecipeHomeWithMineResponse> readRecipes(UserInfo userInfo, PageRecip
pageRecipeRequest.userId()
);

List<RecipeHomeResponse> recipeHomeResponses = recipeRepository.findRecipeData(recipeIds);
List<RecipeDataResponse> recipeDataResponses = recipeRepository.findRecipeData(recipeIds);
return convertToMainRecipeResponses(userInfo, recipeDataResponses);
}

@Transactional(readOnly = true)
public List<RecipeHomeWithMineResponseV1> readRecipesV1(UserInfo userInfo, PageRecipeRequest pageRecipeRequest) {
Pageable pageable = pageRecipeRequest.getPageable();
List<Long> recipeIds = recipeRepository.findRecipeIdsByCategoryAndKeyword(
pageable,
pageRecipeRequest.category(),
pageRecipeRequest.keyword(),
pageRecipeRequest.userId()
);

List<RecipeHomeResponse> recipeHomeResponses = recipeRepository.findRecipeDataV1(recipeIds);

return recipeHomeResponses.stream()
.map(recipeHomeResponse -> new RecipeHomeWithMineResponse(userInfo, recipeHomeResponse))
.sorted(Comparator.comparing(RecipeHomeWithMineResponse::recipeId).reversed())
.map(recipeHomeResponse -> new RecipeHomeWithMineResponseV1(userInfo, recipeHomeResponse))
.sorted(Comparator.comparing(RecipeHomeWithMineResponseV1::recipeId).reversed())
.toList();
}

@Transactional(readOnly = true)
public List<RecipeHomeWithMineResponse> readLikeRecipes(UserInfo userInfo) {
List<Long> likeRecipeIds = likeRepository.findRecipeIdsByUserId(userInfo.getId());
List<RecipeHomeResponse> recipeHomeResponses = recipeRepository.findRecipeData(likeRecipeIds);
List<RecipeDataResponse> recipeDataResponses = recipeRepository.findRecipeData(likeRecipeIds);

return convertToMainRecipeResponses(userInfo, recipeDataResponses);
}

@Transactional(readOnly = true)
public List<RecipeHomeWithMineResponseV1> readLikeRecipesV1(UserInfo userInfo) {
List<Long> likeRecipeIds = likeRepository.findRecipeIdsByUserId(userInfo.getId());
List<RecipeHomeResponse> recipeHomeResponses = recipeRepository.findRecipeDataV1(likeRecipeIds);

return recipeHomeResponses.stream()
.map(recipeHomeResponse -> new RecipeHomeWithMineResponse(userInfo, recipeHomeResponse))
.sorted(Comparator.comparing(RecipeHomeWithMineResponse::recipeId).reversed())
.map(recipeHomeResponse -> new RecipeHomeWithMineResponseV1(userInfo, recipeHomeResponse))
.sorted(Comparator.comparing(RecipeHomeWithMineResponseV1::recipeId).reversed())
.toList();
}

Expand Down Expand Up @@ -125,6 +149,31 @@ public void deleteRecipe(UserInfo userInfo, long recipeId) {
});
}

private List<RecipeHomeWithMineResponse> convertToMainRecipeResponses(
UserInfo userInfo,
List<RecipeDataResponse> recipeDataResponses
) {
Collection<List<RecipeDataResponse>> groupedRecipeData = recipeDataResponses.stream()
.collect(Collectors.groupingBy(RecipeDataResponse::recipeId))
.values();

return groupedRecipeData.stream()
.map(data -> getMainRecipeResponse(userInfo, data))
.sorted(Comparator.comparing(RecipeHomeWithMineResponse::recipeId).reversed())
.collect(Collectors.toList());
}

private RecipeHomeWithMineResponse getMainRecipeResponse(UserInfo userInfo, List<RecipeDataResponse> groupedResponses) {
RecipeDataResponse firstResponse = groupedResponses.getFirst();

return new RecipeHomeWithMineResponse(
userInfo,
firstResponse,
getCategoryResponses(groupedResponses),
getIngredientResponses(groupedResponses)
);
}

private List<IngredientResponse> getIngredientResponses(List<RecipeDataResponse> groupedResponses) {
return groupedResponses.stream()
.map(r -> new IngredientResponse(r.ingredientId(), r.ingredientName(), r.ingredientRequirement()))
Expand Down
Loading
Loading