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

✨ implement recipe and recipe steps creation #143

Merged
merged 16 commits into from
Aug 3, 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 @@ -2,15 +2,24 @@

import java.util.List;
import lombok.RequiredArgsConstructor;
import net.pengcook.authentication.domain.UserInfo;
import net.pengcook.authentication.resolver.LoginUser;
import net.pengcook.category.dto.RecipeOfCategoryRequest;
import net.pengcook.recipe.dto.MainRecipeResponse;
import net.pengcook.recipe.dto.RecipeRequest;
import net.pengcook.recipe.dto.RecipeResponse;
import net.pengcook.recipe.dto.RecipeStepRequest;
import net.pengcook.recipe.dto.RecipeStepResponse;
import net.pengcook.recipe.service.RecipeService;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
Expand All @@ -25,13 +34,35 @@ public List<MainRecipeResponse> readRecipes(@RequestParam int pageNumber, @Reque
return recipeService.readRecipes(pageNumber, pageSize);
}

@GetMapping("/{id}/steps")
public List<RecipeStepResponse> readRecipeSteps(@PathVariable long id) {
return recipeService.readRecipeSteps(id);
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public RecipeResponse createRecipe(@LoginUser UserInfo userInfo, @RequestBody RecipeRequest recipeRequest) {
return recipeService.createRecipe(userInfo, recipeRequest);
}

@GetMapping("/{recipeId}/steps")
public List<RecipeStepResponse> readRecipeSteps(@PathVariable long recipeId) {
return recipeService.readRecipeSteps(recipeId);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{recipeId}로 통일하는 것도 괜찮을 것 같습니다!


@GetMapping("/{recipeId}/steps/{sequence}")
public RecipeStepResponse readRecipeStep(@PathVariable long recipeId, @PathVariable long sequence) {
return recipeService.readRecipeStep(recipeId, sequence);
}

@PostMapping("/{recipeId}/steps")
@ResponseStatus(HttpStatus.CREATED)
public RecipeStepResponse createRecipeStep(
@PathVariable long recipeId,
@RequestBody RecipeStepRequest recipeStepRequest
) {
return recipeService.createRecipeStep(recipeId, recipeStepRequest);
}

@GetMapping("/search")
public List<MainRecipeResponse> readRecipesOfCategory(@ModelAttribute RecipeOfCategoryRequest request) {
return recipeService.readRecipesOfCategory(request);
public List<MainRecipeResponse> readRecipesOfCategory(
@ModelAttribute RecipeOfCategoryRequest recipeOfCategoryRequest
) {
return recipeService.readRecipesOfCategory(recipeOfCategoryRequest);
}
}
11 changes: 11 additions & 0 deletions backend/src/main/java/net/pengcook/recipe/domain/Recipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,15 @@ public class Recipe {

@Column(nullable = true)
private String description;

public Recipe(
String title,
User author,
LocalTime cookingTime,
String thumbnail,
int difficulty,
String description
) {
this(0L, title, author, cookingTime, thumbnail, difficulty, 0, description);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import java.time.LocalTime;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
Expand All @@ -31,6 +32,12 @@ public class RecipeStep {

private int sequence;

private LocalTime cookingTime;

public RecipeStep(Recipe recipe, String image, String description, int sequence, LocalTime cookingTime) {
this(0L, recipe, image, description, sequence, cookingTime);
}

public long recipeId() {
return recipe.getId();
}
Expand Down
16 changes: 16 additions & 0 deletions backend/src/main/java/net/pengcook/recipe/dto/RecipeRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package net.pengcook.recipe.dto;

import jakarta.validation.constraints.NotBlank;
import java.util.List;
import net.pengcook.ingredient.dto.IngredientCreateRequest;

public record RecipeRequest(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NotNull 이나 @notblank 등으로 예외처리 해줘도 좋을것 같아요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@notblank 설정 추가했습니다. 아직 다른 예외처리는 되어있지 않아서 해당 부분은 이슈 분리해서 처리할 예정입니다. 😁

@NotBlank String title,
@NotBlank String cookingTime,
@NotBlank String thumbnail,
@NotBlank int difficulty,
@NotBlank String description,
@NotBlank List<String> categories,
@NotBlank List<IngredientCreateRequest> ingredients
) {
}
10 changes: 10 additions & 0 deletions backend/src/main/java/net/pengcook/recipe/dto/RecipeResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package net.pengcook.recipe.dto;

import net.pengcook.recipe.domain.Recipe;

public record RecipeResponse(long recipeId) {

public RecipeResponse(Recipe savedRecipe) {
this(savedRecipe.getId());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package net.pengcook.recipe.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Positive;

public record RecipeStepRequest(
String image,
@NotBlank String description,
@Positive int sequence,
@NotBlank String cookingTime
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package net.pengcook.recipe.exception;

import org.springframework.http.HttpStatus;

public class NotFoundException extends RecipeException {

public NotFoundException(String message) {
super(HttpStatus.NOT_FOUND, message);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package net.pengcook.recipe.repository;

import java.util.List;
import java.util.Optional;
import net.pengcook.recipe.domain.RecipeStep;
import org.springframework.data.jpa.repository.JpaRepository;

public interface RecipeStepRepository extends JpaRepository<RecipeStep, Long> {

List<RecipeStep> findAllByRecipeIdOrderBySequence(long id);
List<RecipeStep> findAllByRecipeIdOrderBySequence(long recipeId);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

매개변수 명을 id또는 recipeId로 맞춰도 좋을 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당부분 일괄 수정했습니다!

Optional<RecipeStep> findByRecipeIdAndSequence(long recipeId, long sequence);
}
Original file line number Diff line number Diff line change
@@ -1,32 +1,51 @@
package net.pengcook.recipe.service;

import java.time.LocalTime;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import net.pengcook.authentication.domain.UserInfo;
import net.pengcook.category.dto.RecipeOfCategoryRequest;
import net.pengcook.category.repository.CategoryRecipeRepository;
import net.pengcook.category.service.CategoryService;
import net.pengcook.image.service.S3ClientService;
import net.pengcook.ingredient.service.IngredientService;
import net.pengcook.recipe.domain.Recipe;
import net.pengcook.recipe.domain.RecipeStep;
import net.pengcook.recipe.dto.AuthorResponse;
import net.pengcook.recipe.dto.CategoryResponse;
import net.pengcook.recipe.dto.IngredientResponse;
import net.pengcook.recipe.dto.MainRecipeResponse;
import net.pengcook.recipe.dto.RecipeDataResponse;
import net.pengcook.recipe.dto.RecipeRequest;
import net.pengcook.recipe.dto.RecipeResponse;
import net.pengcook.recipe.dto.RecipeStepRequest;
import net.pengcook.recipe.dto.RecipeStepResponse;
import net.pengcook.recipe.exception.NotFoundException;
import net.pengcook.recipe.repository.RecipeRepository;
import net.pengcook.recipe.repository.RecipeStepRepository;
import net.pengcook.user.domain.User;
import net.pengcook.user.repository.UserRepository;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
@RequiredArgsConstructor
public class RecipeService {

private final RecipeRepository recipeRepository;
private final RecipeStepRepository recipeStepRepository;
private final CategoryRecipeRepository categoryRecipeRepository;
private final UserRepository userRepository;

private final CategoryService categoryService;
private final IngredientService ingredientService;
private final S3ClientService s3ClientService;

public List<MainRecipeResponse> readRecipes(int pageNumber, int pageSize) {
Pageable pageable = PageRequest.of(pageNumber, pageSize);
Expand All @@ -36,11 +55,53 @@ public List<MainRecipeResponse> readRecipes(int pageNumber, int pageSize) {
return convertToMainRecipeResponses(recipeDataResponses);
}

public List<RecipeStepResponse> readRecipeSteps(long id) {
List<RecipeStep> recipeSteps = recipeStepRepository.findAllByRecipeIdOrderBySequence(id);
public RecipeResponse createRecipe(UserInfo userInfo, RecipeRequest recipeRequest) {
User author = userRepository.findById(userInfo.getId()).orElseThrow();
String thumbnailUrl = s3ClientService.getImageUrl(recipeRequest.thumbnail()).url();
Recipe recipe = new Recipe(
recipeRequest.title(),
author,
LocalTime.parse(recipeRequest.cookingTime()),
thumbnailUrl,
recipeRequest.difficulty(),
recipeRequest.description()
);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

개행 컨벤션에 맞춰도 괜찮을 것 같아요!

Recipe savedRecipe = recipeRepository.save(recipe);
categoryService.saveCategories(savedRecipe, recipeRequest.categories());
ingredientService.register(recipeRequest.ingredients(), savedRecipe);

return new RecipeResponse(savedRecipe);
}

public List<RecipeStepResponse> readRecipeSteps(long recipeId) {
List<RecipeStep> recipeSteps = recipeStepRepository.findAllByRecipeIdOrderBySequence(recipeId);
return convertToRecipeStepResponses(recipeSteps);
}

public RecipeStepResponse readRecipeStep(long recipeId, long sequence) {
RecipeStep recipeStep = recipeStepRepository.findByRecipeIdAndSequence(recipeId, sequence)
.orElseThrow(() -> new NotFoundException("해당되는 레시피 스텝 정보가 없습니다."));

return new RecipeStepResponse(recipeStep);
}

public RecipeStepResponse createRecipeStep(long recipeId, RecipeStepRequest recipeStepRequest) {
Recipe recipe = recipeRepository.findById(recipeId)
.orElseThrow(() -> new NotFoundException("해당되는 레시피가 없습니다."));
String imageUrl = s3ClientService.getImageUrl(recipeStepRequest.image()).url();
RecipeStep recipeStep = new RecipeStep(
recipe,
imageUrl,
recipeStepRequest.description(),
recipeStepRequest.sequence(),
LocalTime.parse(recipeStepRequest.cookingTime())
);

RecipeStep savedRecipeStep = recipeStepRepository.save(recipeStep);
return new RecipeStepResponse(savedRecipeStep);
}

public List<MainRecipeResponse> readRecipesOfCategory(RecipeOfCategoryRequest request) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

recipeOfCategoryRequest로 매개변수 명을 통일해도 괜찮을 것 같습니다!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아무래도 여러명이 작업하다보니 같은 기능이라도 네이밍이 다른 곳들이 꽤 있는 것 같습니다. 오프라인 리뷰때 같이 보면서 수정하면 좋을 것 같아요!

String categoryName = request.category();
Pageable pageable = PageRequest.of(request.pageNumber(), request.pageSize());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import org.springframework.test.context.jdbc.Sql;

@DataJpaTest
@Import({CategoryService.class, RecipeService.class})
@Import(CategoryService.class)
@Sql(scripts = "/data/category.sql")
class CategoryServiceTest {

Expand Down
Loading
Loading