From ba0a27e9add59930aa1c389c797d327c6e54d60f Mon Sep 17 00:00:00 2001 From: KimGyeong Date: Sun, 14 Feb 2021 23:48:50 +0900 Subject: [PATCH 01/16] =?UTF-8?q?refactor:=20UserRecipeItem=20=EC=96=91=20?= =?UTF-8?q?=EB=B0=8F=20=EB=8B=A8=EC=9C=84=20=ED=95=84=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/userrecipe/domain/QuantityUnit.java | 5 +++++ .../core/userrecipe/domain/UserRecipeItem.java | 16 +++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/QuantityUnit.java diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/QuantityUnit.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/QuantityUnit.java new file mode 100644 index 00000000..78277e27 --- /dev/null +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/QuantityUnit.java @@ -0,0 +1,5 @@ +package com.cocktailpick.core.userrecipe.domain; + +public enum QuantityUnit { + SOJU, BEER, PIECE +} diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipeItem.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipeItem.java index d0c6a606..fe19e731 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipeItem.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipeItem.java @@ -1,12 +1,7 @@ package com.cocktailpick.core.userrecipe.domain; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; +import javax.persistence.*; +import javax.validation.constraints.NotNull; import com.cocktailpick.core.common.domain.BaseTimeEntity; import com.cocktailpick.core.ingredient.domain.Ingredient; @@ -36,6 +31,13 @@ public class UserRecipeItem extends BaseTimeEntity { @JoinColumn(name = "user_cocktail_id") private UserCocktail userCocktail; + @NotNull + private int quantity; + + @Enumerated(EnumType.STRING) + private QuantityUnit quantityUnit; + + @Builder public UserRecipeItem(Ingredient ingredient, UserCocktail userCocktail) { this.ingredient = ingredient; From 6fada74d71775268bd84b0d58b8e163c9762bbac Mon Sep 17 00:00:00 2001 From: KimGyeong Date: Thu, 18 Feb 2021 02:28:43 +0900 Subject: [PATCH 02/16] =?UTF-8?q?feat:=20UserCocktail=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/config/security/SecurityConfig.java | 22 +++--- .../controller/UserCocktailController.java | 25 +++++++ .../UserCocktailControllerTest.java | 72 +++++++++++++++++++ .../docs/UserCocktailDocumentation.java | 27 +++++++ .../domain/UserCocktailRepository.java | 6 ++ .../dto/UserCocktailCreateRequest.java | 48 +++++++++++++ .../service/UserCocktailService.java | 48 +++++++++++++ .../core/userrecipe/domain/UserRecipe.java | 15 ++-- .../userrecipe/domain/UserRecipeItem.java | 20 ++++-- .../userrecipe/dto/UserRecipeItemRequest.java | 38 ++++++++++ 10 files changed, 298 insertions(+), 23 deletions(-) create mode 100644 back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java create mode 100644 back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java create mode 100644 back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java create mode 100644 back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/domain/UserCocktailRepository.java create mode 100644 back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailCreateRequest.java create mode 100644 back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java create mode 100644 back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/dto/UserRecipeItemRequest.java diff --git a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java index 22e007d7..af07df59 100644 --- a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java +++ b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java @@ -118,16 +118,18 @@ protected void configure(HttpSecurity http) throws Exception { .hasRole(ADMIN) .antMatchers(HttpMethod.PUT, "/api/terminologies/**") .hasRole(ADMIN) - .antMatchers(HttpMethod.DELETE, "/api/terminologies/**") - .hasRole(ADMIN) - .antMatchers(HttpMethod.GET, "/api/ingredients/**") - .hasAnyRole(USER, ADMIN) - .antMatchers(HttpMethod.POST, "/api/ingredients") - .hasRole(ADMIN) - .antMatchers(HttpMethod.PUT, "/api/ingredients/**") - .hasRole(ADMIN) - .antMatchers(HttpMethod.DELETE, "/api/ingredients/**") - .hasRole(ADMIN) + .antMatchers(HttpMethod.DELETE, "/api/terminologies/**") + .hasRole(ADMIN) + .antMatchers(HttpMethod.GET, "/api/ingredients/**") + .hasAnyRole(USER, ADMIN) + .antMatchers(HttpMethod.POST, "/api/ingredients") + .hasRole(ADMIN) + .antMatchers(HttpMethod.PUT, "/api/ingredients/**") + .hasRole(ADMIN) + .antMatchers(HttpMethod.DELETE, "/api/ingredients/**") + .hasRole(ADMIN) + .antMatchers(HttpMethod.POST, "/api/user-cocktails/**") + .hasRole(USER) .anyRequest() .permitAll() .and() diff --git a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java new file mode 100644 index 00000000..2793df9b --- /dev/null +++ b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java @@ -0,0 +1,25 @@ +package com.cocktailpick.api.userCocktail.controller; + +import com.cocktailpick.api.security.CurrentUser; +import com.cocktailpick.core.user.domain.User; +import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; +import com.cocktailpick.core.usercocktail.service.UserCocktailService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.net.URI; + +@CrossOrigin("*") +@RequiredArgsConstructor +@RestController +@RequestMapping("/api/user-cocktails") +public class UserCocktailController { + private final UserCocktailService userCocktailService; + + @PostMapping + public ResponseEntity createUserCocktail(@CurrentUser User user, @RequestBody UserCocktailCreateRequest userCocktailCreateRequest) { + Long saveId = userCocktailService.save(user, userCocktailCreateRequest); + return ResponseEntity.created(URI.create("/api/user-cocktails/" + saveId)).build(); + } +} diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java new file mode 100644 index 00000000..ed0858b9 --- /dev/null +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java @@ -0,0 +1,72 @@ +package com.cocktailpick.api.userCocktail.controller.controller; + +import com.cocktailpick.api.common.WithMockCustomUser; +import com.cocktailpick.api.common.documentation.DocumentationWithSecurity; +import com.cocktailpick.api.userCocktail.controller.UserCocktailController; +import com.cocktailpick.api.userCocktail.controller.docs.UserCocktailDocumentation; +import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; +import com.cocktailpick.core.usercocktail.service.UserCocktailService; +import com.cocktailpick.core.userrecipe.dto.UserRecipeItemRequest; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.RestDocumentationContextProvider; +import org.springframework.web.context.WebApplicationContext; + +import java.util.Collections; + +import static org.mockito.BDDMockito.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(controllers = UserCocktailController.class) +class UserCocktailControllerTest extends DocumentationWithSecurity { + @MockBean + private UserCocktailService userCocktailService; + + private UserCocktailCreateRequest userCocktailCreateRequest; + + private UserRecipeItemRequest userRecipeItemRequest; + + private ObjectMapper objectMapper; + + @BeforeEach + public void setUp(WebApplicationContext webApplicationContext, + RestDocumentationContextProvider restDocumentationContextProvider) { + super.setUp(webApplicationContext, restDocumentationContextProvider); + + userRecipeItemRequest = UserRecipeItemRequest.builder() + .ingredientId(1L) + .quantity(123) + .quantityUnit("SOJU").build(); + + userCocktailCreateRequest = UserCocktailCreateRequest.builder() + .name("name") + .description("description") + .userRecipeItemRequests(Collections.singletonList(userRecipeItemRequest)) + .build(); + objectMapper = new ObjectMapper(); + } + + @DisplayName("나만의 레시피를 생성한다.") + @WithMockCustomUser + @Test + void addUserCocktail() throws Exception { + given(userCocktailService.save(any(), any())).willReturn(1L); + + mockMvc.perform(post("/api/user-cocktails") + .content(objectMapper.writeValueAsString(userCocktailCreateRequest)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isCreated()) + .andExpect(header().string("Location", "/api/user-cocktails/1")) + .andDo(print()) + .andDo(UserCocktailDocumentation.createUserCocktail()); + } +} \ No newline at end of file diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java new file mode 100644 index 00000000..87818337 --- /dev/null +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java @@ -0,0 +1,27 @@ +package com.cocktailpick.api.userCocktail.controller.docs; + +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.restdocs.payload.JsonFieldType; + +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; + +public class UserCocktailDocumentation { + public static RestDocumentationResultHandler createUserCocktail() { + return document("UserCocktails/create", + requestFields( + fieldWithPath("name").type(JsonFieldType.STRING).description("칵테일 이름"), + fieldWithPath("description").type(JsonFieldType.STRING).description("칵테일 설명"), + fieldWithPath("userRecipeItemRequests").type(JsonFieldType.ARRAY).description("재료 목록"), + fieldWithPath("userRecipeItemRequests.[].ingredientId").type(JsonFieldType.NUMBER).description("재료 ID"), + fieldWithPath("userRecipeItemRequests.[].quantity").type(JsonFieldType.NUMBER).description("재료 양"), + fieldWithPath("userRecipeItemRequests.[].quantityUnit").type(JsonFieldType.STRING).description("재료 양 단위") + ), + responseHeaders( + headerWithName("Location").description("생성된 칵테일 id") + )); + } +} diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/domain/UserCocktailRepository.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/domain/UserCocktailRepository.java new file mode 100644 index 00000000..77550189 --- /dev/null +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/domain/UserCocktailRepository.java @@ -0,0 +1,6 @@ +package com.cocktailpick.core.usercocktail.domain; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserCocktailRepository extends JpaRepository { +} diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailCreateRequest.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailCreateRequest.java new file mode 100644 index 00000000..37f63855 --- /dev/null +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailCreateRequest.java @@ -0,0 +1,48 @@ +package com.cocktailpick.core.usercocktail.dto; + +import com.cocktailpick.core.ingredient.domain.Ingredient; +import com.cocktailpick.core.usercocktail.domain.UserCocktail; +import com.cocktailpick.core.userrecipe.domain.UserRecipeItem; +import com.cocktailpick.core.userrecipe.dto.UserRecipeItemRequest; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import java.util.ArrayList; +import java.util.List; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +public class UserCocktailCreateRequest { + @NotBlank + private String name; + @NotBlank + private String description; + + private List userRecipeItemRequests; + + @Builder + public UserCocktailCreateRequest(@NotBlank String name, @NotBlank String description, List userRecipeItemRequests) { + this.name = name; + this.description = description; + this.userRecipeItemRequests = userRecipeItemRequests; + } + + public UserCocktail toUserCocktail(Long userId) { + return UserCocktail.builder() + .name(name) + .description(description) + .memberId(userId) + .build(); + } + + public List toUserRecipeItems(List ingredients) { + List userRecipeItems = new ArrayList<>(); + for (int i = 0; i < ingredients.size(); i++) { + userRecipeItems.add(userRecipeItemRequests.get(i).toUserRecipeItem(ingredients.get(i))); + } + return userRecipeItems; + } +} diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java new file mode 100644 index 00000000..ae37ec4e --- /dev/null +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java @@ -0,0 +1,48 @@ +package com.cocktailpick.core.usercocktail.service; + +import com.cocktailpick.core.ingredient.domain.Ingredient; +import com.cocktailpick.core.ingredient.domain.IngredientRepository; +import com.cocktailpick.core.user.domain.User; +import com.cocktailpick.core.usercocktail.domain.UserCocktail; +import com.cocktailpick.core.usercocktail.domain.UserCocktailRepository; +import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; +import com.cocktailpick.core.userrecipe.domain.UserRecipeItem; +import com.cocktailpick.core.userrecipe.dto.UserRecipeItemRequest; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor(access = AccessLevel.PUBLIC) +@Service +public class UserCocktailService { + private final UserCocktailRepository userCocktailRepository; + private final IngredientRepository ingredientRepository; + + @Transactional + public Long save(User user, UserCocktailCreateRequest userCocktailCreateRequest) { + UserCocktail userCocktail = userCocktailCreateRequest.toUserCocktail(user.getId()); + userCocktailRepository.save(userCocktail); + + List ingredientIds = userCocktailCreateRequest.getUserRecipeItemRequests() + .stream() + .map(UserRecipeItemRequest::getIngredientId) + .collect(Collectors.toList()); + + List ingredients = ingredientRepository.findAllById(ingredientIds); + List userRecipeItems = userCocktailCreateRequest.toUserRecipeItems(ingredients); + + setUserCocktail(userCocktail, userRecipeItems); + + return userCocktail.getId(); + } + + private void setUserCocktail(UserCocktail userCocktail, List userRecipeItems) { + for (UserRecipeItem userRecipeItem : userRecipeItems) { + userRecipeItem.setUserCocktail(userCocktail); + } + } +} diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipe.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipe.java index 35be7524..8e1c89b2 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipe.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipe.java @@ -1,15 +1,14 @@ package com.cocktailpick.core.userrecipe.domain; -import java.util.ArrayList; -import java.util.List; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; import javax.persistence.CascadeType; import javax.persistence.Embeddable; import javax.persistence.OneToMany; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; +import java.util.ArrayList; +import java.util.List; @Embeddable @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -21,4 +20,8 @@ public class UserRecipe { public static UserRecipe empty() { return new UserRecipe(); } + + public void addUserRecipeItem(UserRecipeItem userRecipeItem) { + userRecipe.add(userRecipeItem); + } } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipeItem.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipeItem.java index fe19e731..0de2d999 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipeItem.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipeItem.java @@ -1,8 +1,5 @@ package com.cocktailpick.core.userrecipe.domain; -import javax.persistence.*; -import javax.validation.constraints.NotNull; - import com.cocktailpick.core.common.domain.BaseTimeEntity; import com.cocktailpick.core.ingredient.domain.Ingredient; import com.cocktailpick.core.usercocktail.domain.UserCocktail; @@ -11,6 +8,9 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import javax.persistence.*; +import javax.validation.constraints.NotNull; + @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity @@ -18,8 +18,8 @@ public class UserRecipeItem extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_recipe_item_sequence_gen") @SequenceGenerator( - name = "user_recipe_item_sequence_gen", - sequenceName = "user_recipe_item_sequence" + name = "user_recipe_item_sequence_gen", + sequenceName = "user_recipe_item_sequence" ) private Long id; @@ -37,10 +37,16 @@ public class UserRecipeItem extends BaseTimeEntity { @Enumerated(EnumType.STRING) private QuantityUnit quantityUnit; - @Builder - public UserRecipeItem(Ingredient ingredient, UserCocktail userCocktail) { + public UserRecipeItem(Ingredient ingredient, UserCocktail userCocktail, @NotNull int quantity, QuantityUnit quantityUnit) { this.ingredient = ingredient; this.userCocktail = userCocktail; + this.quantity = quantity; + this.quantityUnit = quantityUnit; + } + + public void setUserCocktail(UserCocktail userCocktail) { + this.userCocktail = userCocktail; + userCocktail.getUserRecipe().addUserRecipeItem(this); } } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/dto/UserRecipeItemRequest.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/dto/UserRecipeItemRequest.java new file mode 100644 index 00000000..1097bbcf --- /dev/null +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/dto/UserRecipeItemRequest.java @@ -0,0 +1,38 @@ +package com.cocktailpick.core.userrecipe.dto; + +import com.cocktailpick.core.ingredient.domain.Ingredient; +import com.cocktailpick.core.userrecipe.domain.QuantityUnit; +import com.cocktailpick.core.userrecipe.domain.UserRecipeItem; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +public class UserRecipeItemRequest { + @NotNull + private Long ingredientId; + @NotNull + private int quantity; + @NotBlank + private String quantityUnit; + + @Builder + public UserRecipeItemRequest(@NotNull Long ingredientId, @NotNull int quantity, @NotBlank String quantityUnit) { + this.ingredientId = ingredientId; + this.quantity = quantity; + this.quantityUnit = quantityUnit; + } + + public UserRecipeItem toUserRecipeItem(Ingredient ingredient) { + return UserRecipeItem.builder() + .ingredient(ingredient) + .quantity(quantity) + .quantityUnit(QuantityUnit.valueOf(quantityUnit)) + .build(); + } +} From 59e3f27a1488671de169dd2931a8c42a4eda32ef Mon Sep 17 00:00:00 2001 From: KimGyeong Date: Sun, 21 Feb 2021 17:57:05 +0900 Subject: [PATCH 03/16] =?UTF-8?q?refactor:=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - QuantityUnit 추가 - 나만의 레시피 권한 관리자 추가 - UserRecipeItemRequest 생성자 Validation 어노테이션 제거 --- .../api/config/security/SecurityConfig.java | 24 +++++++++---------- .../core/userrecipe/domain/QuantityUnit.java | 2 +- .../userrecipe/dto/UserRecipeItemRequest.java | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java index af07df59..6f1345d6 100644 --- a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java +++ b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java @@ -118,18 +118,18 @@ protected void configure(HttpSecurity http) throws Exception { .hasRole(ADMIN) .antMatchers(HttpMethod.PUT, "/api/terminologies/**") .hasRole(ADMIN) - .antMatchers(HttpMethod.DELETE, "/api/terminologies/**") - .hasRole(ADMIN) - .antMatchers(HttpMethod.GET, "/api/ingredients/**") - .hasAnyRole(USER, ADMIN) - .antMatchers(HttpMethod.POST, "/api/ingredients") - .hasRole(ADMIN) - .antMatchers(HttpMethod.PUT, "/api/ingredients/**") - .hasRole(ADMIN) - .antMatchers(HttpMethod.DELETE, "/api/ingredients/**") - .hasRole(ADMIN) - .antMatchers(HttpMethod.POST, "/api/user-cocktails/**") - .hasRole(USER) + .antMatchers(HttpMethod.DELETE, "/api/terminologies/**") + .hasRole(ADMIN) + .antMatchers(HttpMethod.GET, "/api/ingredients/**") + .hasAnyRole(USER, ADMIN) + .antMatchers(HttpMethod.POST, "/api/ingredients") + .hasRole(ADMIN) + .antMatchers(HttpMethod.PUT, "/api/ingredients/**") + .hasRole(ADMIN) + .antMatchers(HttpMethod.DELETE, "/api/ingredients/**") + .hasRole(ADMIN) + .antMatchers(HttpMethod.POST, "/api/user-cocktails/**") + .hasAnyRole(USER, ADMIN) .anyRequest() .permitAll() .and() diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/QuantityUnit.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/QuantityUnit.java index 78277e27..a7285163 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/QuantityUnit.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/QuantityUnit.java @@ -1,5 +1,5 @@ package com.cocktailpick.core.userrecipe.domain; public enum QuantityUnit { - SOJU, BEER, PIECE + SOJU, BEER, PAPER, SHOT, PIECE } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/dto/UserRecipeItemRequest.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/dto/UserRecipeItemRequest.java index 1097bbcf..c9918c23 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/dto/UserRecipeItemRequest.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/dto/UserRecipeItemRequest.java @@ -22,7 +22,7 @@ public class UserRecipeItemRequest { private String quantityUnit; @Builder - public UserRecipeItemRequest(@NotNull Long ingredientId, @NotNull int quantity, @NotBlank String quantityUnit) { + public UserRecipeItemRequest(Long ingredientId, int quantity, String quantityUnit) { this.ingredientId = ingredientId; this.quantity = quantity; this.quantityUnit = quantityUnit; From 780c4f534c0c7c46b4c0ba6ce023ee650831c67a Mon Sep 17 00:00:00 2001 From: KimGyeong Date: Tue, 23 Feb 2021 02:07:07 +0900 Subject: [PATCH 04/16] =?UTF-8?q?feat:=20UserCocktail=20=EB=8B=A8=EC=9D=BC?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/config/security/SecurityConfig.java | 21 +++-- .../controller/UserCocktailController.java | 25 ++++-- .../UserCocktailControllerTest.java | 90 +++++++++++++------ .../docs/UserCocktailDocumentation.java | 59 +++++++----- .../core/common/exceptions/ErrorCode.java | 5 +- .../dto/UserCocktailResponse.java | 36 ++++++++ .../dto/UserRecipeItemResponse.java | 27 ++++++ .../service/UserCocktailService.java | 25 ++++-- .../core/userrecipe/domain/UserRecipe.java | 22 +++-- .../userrecipe/domain/UserRecipeItem.java | 20 +++-- .../userrecipe/dto/UserRecipeItemRequest.java | 11 +-- 11 files changed, 260 insertions(+), 81 deletions(-) create mode 100644 back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponse.java create mode 100644 back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserRecipeItemResponse.java diff --git a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java index 6f1345d6..2363a52c 100644 --- a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java +++ b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java @@ -1,11 +1,5 @@ package com.cocktailpick.api.config.security; -import com.cocktailpick.api.security.*; -import com.cocktailpick.api.security.oauth2.CustomOAuth2UserService; -import com.cocktailpick.api.security.oauth2.HttpCookieOAuth2AuthorizationRequestRepository; -import com.cocktailpick.api.security.oauth2.OAuth2AuthenticationFailureHandler; -import com.cocktailpick.api.security.oauth2.OAuth2AuthenticationSuccessHandler; -import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; @@ -21,6 +15,19 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import com.cocktailpick.api.security.CustomUserDetailsService; +import com.cocktailpick.api.security.LoginFilter; +import com.cocktailpick.api.security.LoginSuccessHandler; +import com.cocktailpick.api.security.RestAuthenticationEntryPoint; +import com.cocktailpick.api.security.TokenAuthenticationFilter; +import com.cocktailpick.api.security.TokenProvider; +import com.cocktailpick.api.security.oauth2.CustomOAuth2UserService; +import com.cocktailpick.api.security.oauth2.HttpCookieOAuth2AuthorizationRequestRepository; +import com.cocktailpick.api.security.oauth2.OAuth2AuthenticationFailureHandler; +import com.cocktailpick.api.security.oauth2.OAuth2AuthenticationSuccessHandler; + +import lombok.RequiredArgsConstructor; + @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) @@ -130,6 +137,8 @@ protected void configure(HttpSecurity http) throws Exception { .hasRole(ADMIN) .antMatchers(HttpMethod.POST, "/api/user-cocktails/**") .hasAnyRole(USER, ADMIN) + .antMatchers(HttpMethod.GET, "/api/user-cocktails/**") + .hasAnyRole(USER, ADMIN) .anyRequest() .permitAll() .and() diff --git a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java index 2793df9b..5b24df2b 100644 --- a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java +++ b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java @@ -1,14 +1,23 @@ package com.cocktailpick.api.userCocktail.controller; +import java.net.URI; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +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.RestController; + import com.cocktailpick.api.security.CurrentUser; import com.cocktailpick.core.user.domain.User; import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; +import com.cocktailpick.core.usercocktail.dto.UserCocktailResponse; import com.cocktailpick.core.usercocktail.service.UserCocktailService; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import java.net.URI; +import lombok.RequiredArgsConstructor; @CrossOrigin("*") @RequiredArgsConstructor @@ -18,8 +27,14 @@ public class UserCocktailController { private final UserCocktailService userCocktailService; @PostMapping - public ResponseEntity createUserCocktail(@CurrentUser User user, @RequestBody UserCocktailCreateRequest userCocktailCreateRequest) { + public ResponseEntity createUserCocktail(@CurrentUser User user, + @RequestBody UserCocktailCreateRequest userCocktailCreateRequest) { Long saveId = userCocktailService.save(user, userCocktailCreateRequest); return ResponseEntity.created(URI.create("/api/user-cocktails/" + saveId)).build(); } + + @GetMapping("/{id}") + public ResponseEntity findUserCocktail(@PathVariable Long id) { + return ResponseEntity.ok(userCocktailService.findUserCocktail(id)); + } } diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java index ed0858b9..d63eff7e 100644 --- a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java @@ -1,13 +1,14 @@ package com.cocktailpick.api.userCocktail.controller.controller; -import com.cocktailpick.api.common.WithMockCustomUser; -import com.cocktailpick.api.common.documentation.DocumentationWithSecurity; -import com.cocktailpick.api.userCocktail.controller.UserCocktailController; -import com.cocktailpick.api.userCocktail.controller.docs.UserCocktailDocumentation; -import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; -import com.cocktailpick.core.usercocktail.service.UserCocktailService; -import com.cocktailpick.core.userrecipe.dto.UserRecipeItemRequest; -import com.fasterxml.jackson.databind.ObjectMapper; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.any; +import static org.mockito.BDDMockito.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.util.Collections; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -15,16 +16,19 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.restdocs.RestDocumentationContextProvider; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; import org.springframework.web.context.WebApplicationContext; -import java.util.Collections; - -import static org.mockito.BDDMockito.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.cocktailpick.api.common.WithMockCustomUser; +import com.cocktailpick.api.common.documentation.DocumentationWithSecurity; +import com.cocktailpick.api.userCocktail.controller.UserCocktailController; +import com.cocktailpick.api.userCocktail.controller.docs.UserCocktailDocumentation; +import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; +import com.cocktailpick.core.usercocktail.dto.UserCocktailResponse; +import com.cocktailpick.core.usercocktail.dto.UserRecipeItemResponse; +import com.cocktailpick.core.usercocktail.service.UserCocktailService; +import com.cocktailpick.core.userrecipe.dto.UserRecipeItemRequest; +import com.fasterxml.jackson.databind.ObjectMapper; @WebMvcTest(controllers = UserCocktailController.class) class UserCocktailControllerTest extends DocumentationWithSecurity { @@ -35,6 +39,10 @@ class UserCocktailControllerTest extends DocumentationWithSecurity { private UserRecipeItemRequest userRecipeItemRequest; + private UserCocktailResponse userCocktailResponse; + + private UserRecipeItemResponse userRecipeItemResponse; + private ObjectMapper objectMapper; @BeforeEach @@ -43,15 +51,28 @@ public void setUp(WebApplicationContext webApplicationContext, super.setUp(webApplicationContext, restDocumentationContextProvider); userRecipeItemRequest = UserRecipeItemRequest.builder() - .ingredientId(1L) - .quantity(123) + .ingredientId(1L) + .quantity(123.0) .quantityUnit("SOJU").build(); userCocktailCreateRequest = UserCocktailCreateRequest.builder() - .name("name") - .description("description") - .userRecipeItemRequests(Collections.singletonList(userRecipeItemRequest)) - .build(); + .name("name") + .description("description") + .userRecipeItemRequests(Collections.singletonList(userRecipeItemRequest)) + .build(); + + userRecipeItemResponse = UserRecipeItemResponse.builder() + .ingredientId(1L) + .ingredientName("test ingredient") + .ingredientAbv(1.0) + .ingredientColor("#000000") + .quantity(1.5) + .quantityUnit("PAPER") + .build(); + + userCocktailResponse = new UserCocktailResponse("test", "test Description", + Collections.singletonList(userRecipeItemResponse)); + objectMapper = new ObjectMapper(); } @@ -62,11 +83,24 @@ void addUserCocktail() throws Exception { given(userCocktailService.save(any(), any())).willReturn(1L); mockMvc.perform(post("/api/user-cocktails") - .content(objectMapper.writeValueAsString(userCocktailCreateRequest)) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isCreated()) - .andExpect(header().string("Location", "/api/user-cocktails/1")) - .andDo(print()) - .andDo(UserCocktailDocumentation.createUserCocktail()); + .content(objectMapper.writeValueAsString(userCocktailCreateRequest)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isCreated()) + .andExpect(header().string("Location", "/api/user-cocktails/1")) + .andDo(print()) + .andDo(UserCocktailDocumentation.createUserCocktail()); + } + + @DisplayName("나만의 레시피를 단일 조회한다.") + @WithMockCustomUser + @Test + void findUserCocktailById() throws Exception { + given(userCocktailService.findUserCocktail(anyLong())).willReturn(userCocktailResponse); + + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/user-cocktails/{id}", 1L) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(print()) + .andDo(UserCocktailDocumentation.findUserCocktailById()); } } \ No newline at end of file diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java index 87818337..f90a3113 100644 --- a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java @@ -1,27 +1,46 @@ package com.cocktailpick.api.userCocktail.controller.docs; +import static org.springframework.restdocs.headers.HeaderDocumentation.*; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; + import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; import org.springframework.restdocs.payload.JsonFieldType; -import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; -import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; - public class UserCocktailDocumentation { - public static RestDocumentationResultHandler createUserCocktail() { - return document("UserCocktails/create", - requestFields( - fieldWithPath("name").type(JsonFieldType.STRING).description("칵테일 이름"), - fieldWithPath("description").type(JsonFieldType.STRING).description("칵테일 설명"), - fieldWithPath("userRecipeItemRequests").type(JsonFieldType.ARRAY).description("재료 목록"), - fieldWithPath("userRecipeItemRequests.[].ingredientId").type(JsonFieldType.NUMBER).description("재료 ID"), - fieldWithPath("userRecipeItemRequests.[].quantity").type(JsonFieldType.NUMBER).description("재료 양"), - fieldWithPath("userRecipeItemRequests.[].quantityUnit").type(JsonFieldType.STRING).description("재료 양 단위") - ), - responseHeaders( - headerWithName("Location").description("생성된 칵테일 id") - )); - } + public static RestDocumentationResultHandler createUserCocktail() { + return document("UserCocktails/create", + requestFields( + fieldWithPath("name").type(JsonFieldType.STRING).description("칵테일 이름"), + fieldWithPath("description").type(JsonFieldType.STRING).description("칵테일 설명"), + fieldWithPath("userRecipeItemRequests").type(JsonFieldType.ARRAY).description("재료 목록"), + fieldWithPath("userRecipeItemRequests.[].ingredientId").type(JsonFieldType.NUMBER).description("재료 ID"), + fieldWithPath("userRecipeItemRequests.[].quantity").type(JsonFieldType.NUMBER).description("재료 양"), + fieldWithPath("userRecipeItemRequests.[].quantityUnit").type(JsonFieldType.STRING) + .description("재료 양 단위") + ), + responseHeaders( + headerWithName("Location").description("생성된 칵테일 id") + )); + } + + public static RestDocumentationResultHandler findUserCocktailById() { + return document("UserCocktails/find", + responseFields( + fieldWithPath("name").type(JsonFieldType.STRING).description("나만의 레시피 이름"), + fieldWithPath("description").type(JsonFieldType.STRING).description("나만의 레시피 설명"), + fieldWithPath("userRecipeItemResponses").type(JsonFieldType.ARRAY).description("재료 목록"), + fieldWithPath("userRecipeItemResponses.[].ingredientId").type(JsonFieldType.NUMBER) + .description("재료 ID"), + fieldWithPath("userRecipeItemResponses.[].ingredientName").type(JsonFieldType.STRING) + .description("재료 이름"), + fieldWithPath("userRecipeItemResponses.[].ingredientColor").type(JsonFieldType.STRING) + .description("재료 색"), + fieldWithPath("userRecipeItemResponses.[].ingredientAbv").type(JsonFieldType.NUMBER) + .description("재료 도수"), + fieldWithPath("userRecipeItemResponses.[].quantity").type(JsonFieldType.NUMBER).description("재료 양"), + fieldWithPath("userRecipeItemResponses.[].quantityUnit").type(JsonFieldType.STRING) + .description("재료 양 단위") + )); + } } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/common/exceptions/ErrorCode.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/common/exceptions/ErrorCode.java index 53737466..fa635401 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/common/exceptions/ErrorCode.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/common/exceptions/ErrorCode.java @@ -27,9 +27,10 @@ public enum ErrorCode { UNAUTHORIZED_REDIRECT_URI(400, "AU_003", "인증되지 않은 REDIRECT_URI입니다."), BAD_LOGIN(400, "AU_004", "잘못된 아이디 또는 패스워드입니다."), - INGREDIENT_NOT_FOUND(400, "IN_001", "재료를 찾을 수 없습니다."); + INGREDIENT_NOT_FOUND(400, "IN_001", "재료를 찾을 수 없습니다."), + USERCOCKTAIL_NOT_FOUND(400, "UC_001", "나만의 레시피를 찾을 수 없습니다."); - private final String code; + private final String code; private final String message; private final int status; diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponse.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponse.java new file mode 100644 index 00000000..f309d4dd --- /dev/null +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponse.java @@ -0,0 +1,36 @@ +package com.cocktailpick.core.usercocktail.dto; + +import java.util.List; +import java.util.stream.Collectors; + +import com.cocktailpick.core.usercocktail.domain.UserCocktail; +import com.cocktailpick.core.userrecipe.domain.UserRecipeItem; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class UserCocktailResponse { + private String name; + private String description; + private List userRecipeItemResponses; + + public static UserCocktailResponse of(UserCocktail userCocktail) { + List userRecipeItems = userCocktail.getUserRecipe().getUserRecipe(); + List userRecipeItemResponses = userRecipeItems.stream() + .map(userRecipeItem -> UserRecipeItemResponse.builder() + .ingredientId(userRecipeItem.getIngredient().getId()) + .ingredientAbv(userRecipeItem.getIngredient().getAbv()) + .ingredientColor(userRecipeItem.getIngredient().getColor()) + .ingredientName(userRecipeItem.getIngredient().getName()) + .quantity(userRecipeItem.getQuantity()) + .quantityUnit(userRecipeItem.getQuantityUnit().name()) + .build()) + .collect(Collectors.toList()); + + return new UserCocktailResponse(userCocktail.getName(), userCocktail.getDescription(), userRecipeItemResponses); + } +} diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserRecipeItemResponse.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserRecipeItemResponse.java new file mode 100644 index 00000000..6657af46 --- /dev/null +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserRecipeItemResponse.java @@ -0,0 +1,27 @@ +package com.cocktailpick.core.usercocktail.dto; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@Getter +public class UserRecipeItemResponse { + private Long ingredientId; + private String ingredientName; + private String ingredientColor; + private Double ingredientAbv; + private Double quantity; + private String quantityUnit; + + @Builder + public UserRecipeItemResponse(Long ingredientId, String ingredientName, String ingredientColor, + Double ingredientAbv, Double quantity, String quantityUnit) { + this.ingredientId = ingredientId; + this.ingredientName = ingredientName; + this.ingredientColor = ingredientColor; + this.ingredientAbv = ingredientAbv; + this.quantity = quantity; + this.quantityUnit = quantityUnit; + } +} diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java index ae37ec4e..7c9cb9d0 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java @@ -1,20 +1,25 @@ package com.cocktailpick.core.usercocktail.service; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.cocktailpick.core.common.exceptions.EntityNotFoundException; +import com.cocktailpick.core.common.exceptions.ErrorCode; import com.cocktailpick.core.ingredient.domain.Ingredient; import com.cocktailpick.core.ingredient.domain.IngredientRepository; import com.cocktailpick.core.user.domain.User; import com.cocktailpick.core.usercocktail.domain.UserCocktail; import com.cocktailpick.core.usercocktail.domain.UserCocktailRepository; import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; +import com.cocktailpick.core.usercocktail.dto.UserCocktailResponse; import com.cocktailpick.core.userrecipe.domain.UserRecipeItem; import com.cocktailpick.core.userrecipe.dto.UserRecipeItemRequest; + import lombok.AccessLevel; import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.stream.Collectors; @RequiredArgsConstructor(access = AccessLevel.PUBLIC) @Service @@ -45,4 +50,14 @@ private void setUserCocktail(UserCocktail userCocktail, List use userRecipeItem.setUserCocktail(userCocktail); } } + + public UserCocktailResponse findUserCocktail(Long id) { + UserCocktail userCocktail = findUserCocktailById(id); + return UserCocktailResponse.of(userCocktail); + } + + private UserCocktail findUserCocktailById(Long id) { + return userCocktailRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException(ErrorCode.USERCOCKTAIL_NOT_FOUND)); + } } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipe.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipe.java index 8e1c89b2..e9bcf3f1 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipe.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipe.java @@ -1,16 +1,22 @@ package com.cocktailpick.core.userrecipe.domain; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; import javax.persistence.CascadeType; import javax.persistence.Embeddable; import javax.persistence.OneToMany; -import java.util.ArrayList; -import java.util.List; + +import com.cocktailpick.core.ingredient.domain.Ingredient; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; @Embeddable +@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor(access = AccessLevel.PUBLIC) public class UserRecipe { @@ -24,4 +30,10 @@ public static UserRecipe empty() { public void addUserRecipeItem(UserRecipeItem userRecipeItem) { userRecipe.add(userRecipeItem); } + + public List getIngredients() { + return userRecipe.stream() + .map(UserRecipeItem::getIngredient) + .collect(Collectors.toList()); + } } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipeItem.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipeItem.java index 0de2d999..9986591f 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipeItem.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipeItem.java @@ -1,16 +1,25 @@ package com.cocktailpick.core.userrecipe.domain; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.SequenceGenerator; +import javax.validation.constraints.NotNull; + import com.cocktailpick.core.common.domain.BaseTimeEntity; import com.cocktailpick.core.ingredient.domain.Ingredient; import com.cocktailpick.core.usercocktail.domain.UserCocktail; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.persistence.*; -import javax.validation.constraints.NotNull; - @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity @@ -32,13 +41,14 @@ public class UserRecipeItem extends BaseTimeEntity { private UserCocktail userCocktail; @NotNull - private int quantity; + private Double quantity; @Enumerated(EnumType.STRING) private QuantityUnit quantityUnit; @Builder - public UserRecipeItem(Ingredient ingredient, UserCocktail userCocktail, @NotNull int quantity, QuantityUnit quantityUnit) { + public UserRecipeItem(Ingredient ingredient, UserCocktail userCocktail, @NotNull Double quantity, + QuantityUnit quantityUnit) { this.ingredient = ingredient; this.userCocktail = userCocktail; this.quantity = quantity; diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/dto/UserRecipeItemRequest.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/dto/UserRecipeItemRequest.java index c9918c23..2ef66a03 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/dto/UserRecipeItemRequest.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/dto/UserRecipeItemRequest.java @@ -1,28 +1,29 @@ package com.cocktailpick.core.userrecipe.dto; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + import com.cocktailpick.core.ingredient.domain.Ingredient; import com.cocktailpick.core.userrecipe.domain.QuantityUnit; import com.cocktailpick.core.userrecipe.domain.UserRecipeItem; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - @NoArgsConstructor(access = AccessLevel.PRIVATE) @Getter public class UserRecipeItemRequest { @NotNull private Long ingredientId; @NotNull - private int quantity; + private Double quantity; @NotBlank private String quantityUnit; @Builder - public UserRecipeItemRequest(Long ingredientId, int quantity, String quantityUnit) { + public UserRecipeItemRequest(Long ingredientId, Double quantity, String quantityUnit) { this.ingredientId = ingredientId; this.quantity = quantity; this.quantityUnit = quantityUnit; From 1d37c4c3bdcd79cbd339c2ba93ea174982bb9490 Mon Sep 17 00:00:00 2001 From: KimGyeong Date: Tue, 23 Feb 2021 02:29:15 +0900 Subject: [PATCH 05/16] =?UTF-8?q?feat:=20UserCocktail=20=EC=A0=84=EC=B2=B4?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/UserCocktailController.java | 6 ++++ .../UserCocktailControllerTest.java | 21 ++++++++++++-- .../docs/UserCocktailDocumentation.java | 29 +++++++++++++++++++ .../dto/UserCocktailResponses.java | 14 +++++++++ .../service/UserCocktailService.java | 11 +++++++ 5 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponses.java diff --git a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java index 5b24df2b..5561ffc0 100644 --- a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java +++ b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java @@ -15,6 +15,7 @@ import com.cocktailpick.core.user.domain.User; import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; import com.cocktailpick.core.usercocktail.dto.UserCocktailResponse; +import com.cocktailpick.core.usercocktail.dto.UserCocktailResponses; import com.cocktailpick.core.usercocktail.service.UserCocktailService; import lombok.RequiredArgsConstructor; @@ -37,4 +38,9 @@ public ResponseEntity createUserCocktail(@CurrentUser User user, public ResponseEntity findUserCocktail(@PathVariable Long id) { return ResponseEntity.ok(userCocktailService.findUserCocktail(id)); } + + @GetMapping + public ResponseEntity findUserCocktails() { + return ResponseEntity.ok(userCocktailService.findUserCocktails()); + } } diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java index d63eff7e..8b110d8d 100644 --- a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java @@ -25,6 +25,7 @@ import com.cocktailpick.api.userCocktail.controller.docs.UserCocktailDocumentation; import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; import com.cocktailpick.core.usercocktail.dto.UserCocktailResponse; +import com.cocktailpick.core.usercocktail.dto.UserCocktailResponses; import com.cocktailpick.core.usercocktail.dto.UserRecipeItemResponse; import com.cocktailpick.core.usercocktail.service.UserCocktailService; import com.cocktailpick.core.userrecipe.dto.UserRecipeItemRequest; @@ -47,13 +48,13 @@ class UserCocktailControllerTest extends DocumentationWithSecurity { @BeforeEach public void setUp(WebApplicationContext webApplicationContext, - RestDocumentationContextProvider restDocumentationContextProvider) { + RestDocumentationContextProvider restDocumentationContextProvider) { super.setUp(webApplicationContext, restDocumentationContextProvider); userRecipeItemRequest = UserRecipeItemRequest.builder() .ingredientId(1L) .quantity(123.0) - .quantityUnit("SOJU").build(); + .quantityUnit("SOJU").build(); userCocktailCreateRequest = UserCocktailCreateRequest.builder() .name("name") @@ -103,4 +104,20 @@ void findUserCocktailById() throws Exception { .andDo(print()) .andDo(UserCocktailDocumentation.findUserCocktailById()); } + + @DisplayName("나만의 레시피를 전체 조회한다.") + @WithMockCustomUser + @Test + void findUserCocktails() throws Exception { + UserCocktailResponses userCocktailResponses = new UserCocktailResponses( + Collections.singletonList(userCocktailResponse)); + + given(userCocktailService.findUserCocktails()).willReturn(userCocktailResponses); + + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/user-cocktails") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(print()) + .andDo(UserCocktailDocumentation.findUserCocktails()); + } } \ No newline at end of file diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java index f90a3113..f41f69ac 100644 --- a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java @@ -43,4 +43,33 @@ public static RestDocumentationResultHandler findUserCocktailById() { .description("재료 양 단위") )); } + + public static RestDocumentationResultHandler findUserCocktails() { + return document("UserCocktails/findAll", + responseFields( + fieldWithPath("userCocktailResponses").type(JsonFieldType.ARRAY).description("나만의 레시피 목록"), + fieldWithPath("userCocktailResponses.[].name").type(JsonFieldType.STRING).description("나만의 레시피 이름"), + fieldWithPath("userCocktailResponses.[].description").type(JsonFieldType.STRING) + .description("나만의 레시피 설명"), + fieldWithPath("userCocktailResponses.[].userRecipeItemResponses").type(JsonFieldType.ARRAY) + .description("재료 목록"), + fieldWithPath("userCocktailResponses.[].userRecipeItemResponses.[].ingredientId").type( + JsonFieldType.NUMBER) + .description("재료 ID"), + fieldWithPath("userCocktailResponses.[].userRecipeItemResponses.[].ingredientName").type( + JsonFieldType.STRING) + .description("재료 이름"), + fieldWithPath("userCocktailResponses.[].userRecipeItemResponses.[].ingredientColor").type( + JsonFieldType.STRING) + .description("재료 색"), + fieldWithPath("userCocktailResponses.[].userRecipeItemResponses.[].ingredientAbv").type( + JsonFieldType.NUMBER) + .description("재료 도수"), + fieldWithPath("userCocktailResponses.[].userRecipeItemResponses.[].quantity").type(JsonFieldType.NUMBER) + .description("재료 양"), + fieldWithPath("userCocktailResponses.[].userRecipeItemResponses.[].quantityUnit").type( + JsonFieldType.STRING) + .description("재료 양 단위") + )); + } } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponses.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponses.java new file mode 100644 index 00000000..5d416546 --- /dev/null +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponses.java @@ -0,0 +1,14 @@ +package com.cocktailpick.core.usercocktail.dto; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class UserCocktailResponses { + private List userCocktailResponses; +} diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java index 7c9cb9d0..b43eb63a 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java @@ -1,5 +1,7 @@ package com.cocktailpick.core.usercocktail.service; +import static java.util.stream.Collectors.*; + import java.util.List; import java.util.stream.Collectors; @@ -15,6 +17,7 @@ import com.cocktailpick.core.usercocktail.domain.UserCocktailRepository; import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; import com.cocktailpick.core.usercocktail.dto.UserCocktailResponse; +import com.cocktailpick.core.usercocktail.dto.UserCocktailResponses; import com.cocktailpick.core.userrecipe.domain.UserRecipeItem; import com.cocktailpick.core.userrecipe.dto.UserRecipeItemRequest; @@ -60,4 +63,12 @@ private UserCocktail findUserCocktailById(Long id) { return userCocktailRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException(ErrorCode.USERCOCKTAIL_NOT_FOUND)); } + + public UserCocktailResponses findUserCocktails() { + List userCocktails = userCocktailRepository.findAll(); + + return userCocktails.stream() + .map(UserCocktailResponse::of) + .collect(collectingAndThen(toList(), UserCocktailResponses::new)); + } } From 97b2039147db5d86f2bb6664dbb99a187b39bc45 Mon Sep 17 00:00:00 2001 From: KimGyeong Date: Tue, 23 Feb 2021 23:56:02 +0900 Subject: [PATCH 06/16] =?UTF-8?q?refactor:=20=ED=94=BC=EB=93=9C=EB=B0=B1?= =?UTF-8?q?=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - UserCocktailResponse id 필드 추가 - DTO 빈 생성자 접근 제어자 변경 - Transactional 어노테이션 추가 --- .../controller/UserCocktailControllerTest.java | 2 +- .../controller/docs/UserCocktailDocumentation.java | 1 + .../usercocktail/dto/UserCocktailCreateRequest.java | 13 ++++++++----- .../core/usercocktail/dto/UserCocktailResponse.java | 7 +++++-- .../usercocktail/dto/UserCocktailResponses.java | 3 ++- .../usercocktail/service/UserCocktailService.java | 2 ++ 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java index 8b110d8d..1d4cb3c9 100644 --- a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java @@ -71,7 +71,7 @@ public void setUp(WebApplicationContext webApplicationContext, .quantityUnit("PAPER") .build(); - userCocktailResponse = new UserCocktailResponse("test", "test Description", + userCocktailResponse = new UserCocktailResponse(1L, "test", "test Description", Collections.singletonList(userRecipeItemResponse)); objectMapper = new ObjectMapper(); diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java index f41f69ac..4b7d4912 100644 --- a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java @@ -48,6 +48,7 @@ public static RestDocumentationResultHandler findUserCocktails() { return document("UserCocktails/findAll", responseFields( fieldWithPath("userCocktailResponses").type(JsonFieldType.ARRAY).description("나만의 레시피 목록"), + fieldWithPath("userCocktailResponses.[].id").type(JsonFieldType.NUMBER).description("나만의 레시피 아이디"), fieldWithPath("userCocktailResponses.[].name").type(JsonFieldType.STRING).description("나만의 레시피 이름"), fieldWithPath("userCocktailResponses.[].description").type(JsonFieldType.STRING) .description("나만의 레시피 설명"), diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailCreateRequest.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailCreateRequest.java index 37f63855..311a4e1a 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailCreateRequest.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailCreateRequest.java @@ -1,18 +1,20 @@ package com.cocktailpick.core.usercocktail.dto; +import java.util.ArrayList; +import java.util.List; + +import javax.validation.constraints.NotBlank; + import com.cocktailpick.core.ingredient.domain.Ingredient; import com.cocktailpick.core.usercocktail.domain.UserCocktail; import com.cocktailpick.core.userrecipe.domain.UserRecipeItem; import com.cocktailpick.core.userrecipe.dto.UserRecipeItemRequest; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; -import java.util.ArrayList; -import java.util.List; - @NoArgsConstructor(access = AccessLevel.PRIVATE) @Getter public class UserCocktailCreateRequest { @@ -41,7 +43,8 @@ public UserCocktail toUserCocktail(Long userId) { public List toUserRecipeItems(List ingredients) { List userRecipeItems = new ArrayList<>(); for (int i = 0; i < ingredients.size(); i++) { - userRecipeItems.add(userRecipeItemRequests.get(i).toUserRecipeItem(ingredients.get(i))); + UserRecipeItem userRecipeItem = userRecipeItemRequests.get(i).toUserRecipeItem(ingredients.get(i)); + userRecipeItems.add(userRecipeItem); } return userRecipeItems; } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponse.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponse.java index f309d4dd..a8ab75b6 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponse.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponse.java @@ -6,14 +6,16 @@ import com.cocktailpick.core.usercocktail.domain.UserCocktail; import com.cocktailpick.core.userrecipe.domain.UserRecipeItem; +import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor @Getter public class UserCocktailResponse { + private Long id; private String name; private String description; private List userRecipeItemResponses; @@ -31,6 +33,7 @@ public static UserCocktailResponse of(UserCocktail userCocktail) { .build()) .collect(Collectors.toList()); - return new UserCocktailResponse(userCocktail.getName(), userCocktail.getDescription(), userRecipeItemResponses); + return new UserCocktailResponse(userCocktail.getId(), userCocktail.getName(), userCocktail.getDescription(), + userRecipeItemResponses); } } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponses.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponses.java index 5d416546..abeeae2b 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponses.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailResponses.java @@ -2,11 +2,12 @@ import java.util.List; +import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor @Getter public class UserCocktailResponses { diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java index b43eb63a..6b21910c 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java @@ -54,6 +54,7 @@ private void setUserCocktail(UserCocktail userCocktail, List use } } + @Transactional(readOnly = true) public UserCocktailResponse findUserCocktail(Long id) { UserCocktail userCocktail = findUserCocktailById(id); return UserCocktailResponse.of(userCocktail); @@ -64,6 +65,7 @@ private UserCocktail findUserCocktailById(Long id) { .orElseThrow(() -> new EntityNotFoundException(ErrorCode.USERCOCKTAIL_NOT_FOUND)); } + @Transactional(readOnly = true) public UserCocktailResponses findUserCocktails() { List userCocktails = userCocktailRepository.findAll(); From a002ca89b444f8e5308e888c13481f8fe75a7c7c Mon Sep 17 00:00:00 2001 From: KimGyeong Date: Wed, 24 Feb 2021 01:37:36 +0900 Subject: [PATCH 07/16] =?UTF-8?q?feat:=20=EB=82=98=EB=A7=8C=EC=9D=98=20?= =?UTF-8?q?=EB=A0=88=EC=8B=9C=ED=94=BC=20=EC=88=98=EC=A0=95=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/config/security/SecurityConfig.java | 2 + .../controller/UserCocktailController.java | 14 +++++-- .../UserCocktailControllerTest.java | 26 +++++++++++-- .../docs/UserCocktailDocumentation.java | 21 ++++++++++- .../core/common/exceptions/ErrorCode.java | 3 +- .../cocktailpick/core/user/domain/User.java | 5 +++ .../usercocktail/domain/UserCocktail.java | 22 ++++++++++- ...eRequest.java => UserCocktailRequest.java} | 5 ++- .../service/UserCocktailService.java | 37 +++++++++++++++---- .../core/userrecipe/domain/UserRecipe.java | 4 ++ 10 files changed, 117 insertions(+), 22 deletions(-) rename back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/{UserCocktailCreateRequest.java => UserCocktailRequest.java} (89%) diff --git a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java index 2363a52c..8c60cf27 100644 --- a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java +++ b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/config/security/SecurityConfig.java @@ -139,6 +139,8 @@ protected void configure(HttpSecurity http) throws Exception { .hasAnyRole(USER, ADMIN) .antMatchers(HttpMethod.GET, "/api/user-cocktails/**") .hasAnyRole(USER, ADMIN) + .antMatchers(HttpMethod.PUT, "/api/user-cocktails/**") + .hasAnyRole(USER, ADMIN) .anyRequest() .permitAll() .and() diff --git a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java index 5561ffc0..87ab6c27 100644 --- a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java +++ b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java @@ -7,13 +7,14 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.cocktailpick.api.security.CurrentUser; import com.cocktailpick.core.user.domain.User; -import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; +import com.cocktailpick.core.usercocktail.dto.UserCocktailRequest; import com.cocktailpick.core.usercocktail.dto.UserCocktailResponse; import com.cocktailpick.core.usercocktail.dto.UserCocktailResponses; import com.cocktailpick.core.usercocktail.service.UserCocktailService; @@ -29,8 +30,8 @@ public class UserCocktailController { @PostMapping public ResponseEntity createUserCocktail(@CurrentUser User user, - @RequestBody UserCocktailCreateRequest userCocktailCreateRequest) { - Long saveId = userCocktailService.save(user, userCocktailCreateRequest); + @RequestBody UserCocktailRequest userCocktailRequest) { + Long saveId = userCocktailService.save(user, userCocktailRequest); return ResponseEntity.created(URI.create("/api/user-cocktails/" + saveId)).build(); } @@ -43,4 +44,11 @@ public ResponseEntity findUserCocktail(@PathVariable Long public ResponseEntity findUserCocktails() { return ResponseEntity.ok(userCocktailService.findUserCocktails()); } + + @PutMapping("/{id}") + public ResponseEntity updateUserCocktail(@CurrentUser User user, @PathVariable Long id, + @RequestBody UserCocktailRequest updateUserCocktailRequest) { + userCocktailService.updateUserCocktail(user, id, updateUserCocktailRequest); + return ResponseEntity.ok().build(); + } } diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java index 1d4cb3c9..d2df57fe 100644 --- a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java @@ -23,7 +23,7 @@ import com.cocktailpick.api.common.documentation.DocumentationWithSecurity; import com.cocktailpick.api.userCocktail.controller.UserCocktailController; import com.cocktailpick.api.userCocktail.controller.docs.UserCocktailDocumentation; -import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; +import com.cocktailpick.core.usercocktail.dto.UserCocktailRequest; import com.cocktailpick.core.usercocktail.dto.UserCocktailResponse; import com.cocktailpick.core.usercocktail.dto.UserCocktailResponses; import com.cocktailpick.core.usercocktail.dto.UserRecipeItemResponse; @@ -36,7 +36,7 @@ class UserCocktailControllerTest extends DocumentationWithSecurity { @MockBean private UserCocktailService userCocktailService; - private UserCocktailCreateRequest userCocktailCreateRequest; + private UserCocktailRequest userCocktailRequest; private UserRecipeItemRequest userRecipeItemRequest; @@ -56,7 +56,7 @@ public void setUp(WebApplicationContext webApplicationContext, .quantity(123.0) .quantityUnit("SOJU").build(); - userCocktailCreateRequest = UserCocktailCreateRequest.builder() + userCocktailRequest = UserCocktailRequest.builder() .name("name") .description("description") .userRecipeItemRequests(Collections.singletonList(userRecipeItemRequest)) @@ -84,7 +84,7 @@ void addUserCocktail() throws Exception { given(userCocktailService.save(any(), any())).willReturn(1L); mockMvc.perform(post("/api/user-cocktails") - .content(objectMapper.writeValueAsString(userCocktailCreateRequest)) + .content(objectMapper.writeValueAsString(userCocktailRequest)) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isCreated()) .andExpect(header().string("Location", "/api/user-cocktails/1")) @@ -120,4 +120,22 @@ void findUserCocktails() throws Exception { .andDo(print()) .andDo(UserCocktailDocumentation.findUserCocktails()); } + + @DisplayName("나만의 레시피를 수정한다.") + @WithMockCustomUser + @Test + void updateUserCocktail() throws Exception { + UserCocktailRequest userCocktailupdateRequest = UserCocktailRequest.builder() + .name("updateUserCocktail") + .description("해피해킹 없이는 살 수 없는 몸이 돼었어") + .userRecipeItemRequests(Collections.singletonList(userRecipeItemRequest)) + .build(); + + mockMvc.perform(RestDocumentationRequestBuilders.put("/api/user-cocktails/{id}", 1L) + .content(objectMapper.writeValueAsString(userCocktailupdateRequest)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(print()) + .andDo(UserCocktailDocumentation.updateUserCocktails()); + } } \ No newline at end of file diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java index 4b7d4912..45b1806e 100644 --- a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java @@ -11,8 +11,8 @@ public class UserCocktailDocumentation { public static RestDocumentationResultHandler createUserCocktail() { return document("UserCocktails/create", requestFields( - fieldWithPath("name").type(JsonFieldType.STRING).description("칵테일 이름"), - fieldWithPath("description").type(JsonFieldType.STRING).description("칵테일 설명"), + fieldWithPath("name").type(JsonFieldType.STRING).description("나만의 레시피 이름"), + fieldWithPath("description").type(JsonFieldType.STRING).description("나만의 레시피 설명"), fieldWithPath("userRecipeItemRequests").type(JsonFieldType.ARRAY).description("재료 목록"), fieldWithPath("userRecipeItemRequests.[].ingredientId").type(JsonFieldType.NUMBER).description("재료 ID"), fieldWithPath("userRecipeItemRequests.[].quantity").type(JsonFieldType.NUMBER).description("재료 양"), @@ -27,6 +27,7 @@ public static RestDocumentationResultHandler createUserCocktail() { public static RestDocumentationResultHandler findUserCocktailById() { return document("UserCocktails/find", responseFields( + fieldWithPath("id").type(JsonFieldType.NUMBER).description("나만의 레시피 아이디"), fieldWithPath("name").type(JsonFieldType.STRING).description("나만의 레시피 이름"), fieldWithPath("description").type(JsonFieldType.STRING).description("나만의 레시피 설명"), fieldWithPath("userRecipeItemResponses").type(JsonFieldType.ARRAY).description("재료 목록"), @@ -73,4 +74,20 @@ public static RestDocumentationResultHandler findUserCocktails() { .description("재료 양 단위") )); } + + public static RestDocumentationResultHandler updateUserCocktails() { + return document("UserCocktails/update", + requestFields( + fieldWithPath("name").type(JsonFieldType.STRING).description("업데이트될 나만의 레시피 이름"), + fieldWithPath("description").type(JsonFieldType.STRING).description("업데이트 될 나만의 레시피 설명"), + fieldWithPath("userRecipeItemRequests").type(JsonFieldType.ARRAY).description("업데이트 될 재료 목록"), + fieldWithPath("userRecipeItemRequests.[].ingredientId").type(JsonFieldType.NUMBER) + .description("업데이트 될 재료 ID"), + fieldWithPath("userRecipeItemRequests.[].quantity").type(JsonFieldType.NUMBER) + .description("업데이트 될 재료 양"), + fieldWithPath("userRecipeItemRequests.[].quantityUnit").type(JsonFieldType.STRING) + .description("업데이트 될 재료 양 단위") + ) + ); + } } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/common/exceptions/ErrorCode.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/common/exceptions/ErrorCode.java index fa635401..b29cf727 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/common/exceptions/ErrorCode.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/common/exceptions/ErrorCode.java @@ -28,7 +28,8 @@ public enum ErrorCode { BAD_LOGIN(400, "AU_004", "잘못된 아이디 또는 패스워드입니다."), INGREDIENT_NOT_FOUND(400, "IN_001", "재료를 찾을 수 없습니다."), - USERCOCKTAIL_NOT_FOUND(400, "UC_001", "나만의 레시피를 찾을 수 없습니다."); + USERCOCKTAIL_NOT_FOUND(400, "UC_001", "나만의 레시피를 찾을 수 없습니다."), + USERCOCKTAIL_UNAUTHORIZED(403, "UC_002", "나만의 레시피를 수정할 수 있는 권한이 없습니다."); private final String code; private final String message; diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/user/domain/User.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/user/domain/User.java index 8dc2f3b6..a0c8a16e 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/user/domain/User.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/user/domain/User.java @@ -18,6 +18,7 @@ import com.cocktailpick.core.common.domain.BaseTimeEntity; import com.cocktailpick.core.favorite.domain.Favorite; import com.cocktailpick.core.favorite.domain.Favorites; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -88,6 +89,10 @@ public boolean isDuplicated(Favorite favorite) { return favorites.isDuplicated(favorite); } + public boolean isNotPossibleToUpdateUserCocktail(Long userId) { + return !this.id.equals(userId) || this.role != Role.ROLE_ADMIN; + } + public List findFavoriteCocktailIds() { return favorites.findFavoriteCocktailIds(); } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/domain/UserCocktail.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/domain/UserCocktail.java index 98562380..9ba7bf31 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/domain/UserCocktail.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/domain/UserCocktail.java @@ -1,5 +1,7 @@ package com.cocktailpick.core.usercocktail.domain; +import java.util.List; + import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -11,6 +13,8 @@ import com.cocktailpick.core.common.domain.BaseTimeEntity; import com.cocktailpick.core.userrecipe.domain.UserRecipe; +import com.cocktailpick.core.userrecipe.domain.UserRecipeItem; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -44,7 +48,21 @@ public class UserCocktail extends BaseTimeEntity { public UserCocktail(Long id, String name, String description, Long memberId) { this.id = id; this.name = name; - this. description = description; - this. memberId = memberId; + this.description = description; + this.memberId = memberId; + } + + public void update(UserCocktail updateUserCocktail, List userRecipeItems) { + this.name = updateUserCocktail.name; + this.description = updateUserCocktail.description; + + updateUserRecipe(userRecipeItems); + } + + private void updateUserRecipe(List userRecipeItems) { + this.userRecipe.clear(); + for (UserRecipeItem userRecipeItem : userRecipeItems) { + userRecipeItem.setUserCocktail(this); + } } } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailCreateRequest.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailRequest.java similarity index 89% rename from back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailCreateRequest.java rename to back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailRequest.java index 311a4e1a..02dce2e9 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailCreateRequest.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/dto/UserCocktailRequest.java @@ -17,7 +17,7 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) @Getter -public class UserCocktailCreateRequest { +public class UserCocktailRequest { @NotBlank private String name; @NotBlank @@ -26,7 +26,8 @@ public class UserCocktailCreateRequest { private List userRecipeItemRequests; @Builder - public UserCocktailCreateRequest(@NotBlank String name, @NotBlank String description, List userRecipeItemRequests) { + public UserCocktailRequest(@NotBlank String name, @NotBlank String description, + List userRecipeItemRequests) { this.name = name; this.description = description; this.userRecipeItemRequests = userRecipeItemRequests; diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java index 6b21910c..50dcbe48 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java @@ -8,6 +8,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.cocktailpick.core.common.exceptions.AuthException; import com.cocktailpick.core.common.exceptions.EntityNotFoundException; import com.cocktailpick.core.common.exceptions.ErrorCode; import com.cocktailpick.core.ingredient.domain.Ingredient; @@ -15,7 +16,7 @@ import com.cocktailpick.core.user.domain.User; import com.cocktailpick.core.usercocktail.domain.UserCocktail; import com.cocktailpick.core.usercocktail.domain.UserCocktailRepository; -import com.cocktailpick.core.usercocktail.dto.UserCocktailCreateRequest; +import com.cocktailpick.core.usercocktail.dto.UserCocktailRequest; import com.cocktailpick.core.usercocktail.dto.UserCocktailResponse; import com.cocktailpick.core.usercocktail.dto.UserCocktailResponses; import com.cocktailpick.core.userrecipe.domain.UserRecipeItem; @@ -31,17 +32,17 @@ public class UserCocktailService { private final IngredientRepository ingredientRepository; @Transactional - public Long save(User user, UserCocktailCreateRequest userCocktailCreateRequest) { - UserCocktail userCocktail = userCocktailCreateRequest.toUserCocktail(user.getId()); + public Long save(User user, UserCocktailRequest userCocktailRequest) { + UserCocktail userCocktail = userCocktailRequest.toUserCocktail(user.getId()); userCocktailRepository.save(userCocktail); - List ingredientIds = userCocktailCreateRequest.getUserRecipeItemRequests() - .stream() - .map(UserRecipeItemRequest::getIngredientId) - .collect(Collectors.toList()); + List ingredientIds = userCocktailRequest.getUserRecipeItemRequests() + .stream() + .map(UserRecipeItemRequest::getIngredientId) + .collect(Collectors.toList()); List ingredients = ingredientRepository.findAllById(ingredientIds); - List userRecipeItems = userCocktailCreateRequest.toUserRecipeItems(ingredients); + List userRecipeItems = userCocktailRequest.toUserRecipeItems(ingredients); setUserCocktail(userCocktail, userRecipeItems); @@ -73,4 +74,24 @@ public UserCocktailResponses findUserCocktails() { .map(UserCocktailResponse::of) .collect(collectingAndThen(toList(), UserCocktailResponses::new)); } + + @Transactional + public void updateUserCocktail(User user, Long id, UserCocktailRequest updateUserCocktailRequest) { + UserCocktail userCocktail = findUserCocktailById(id); + + if (user.isNotPossibleToUpdateUserCocktail(userCocktail.getMemberId())) { + throw new AuthException(ErrorCode.USERCOCKTAIL_UNAUTHORIZED); + } + + UserCocktail updateUserCocktail = updateUserCocktailRequest.toUserCocktail(user.getId()); + List ingredientIds = updateUserCocktailRequest.getUserRecipeItemRequests() + .stream() + .map(UserRecipeItemRequest::getIngredientId) + .collect(Collectors.toList()); + + List ingredients = ingredientRepository.findAllById(ingredientIds); + List userRecipeItems = updateUserCocktailRequest.toUserRecipeItems(ingredients); + + userCocktail.update(updateUserCocktail, userRecipeItems); + } } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipe.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipe.java index e9bcf3f1..570e76b2 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipe.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/userrecipe/domain/UserRecipe.java @@ -36,4 +36,8 @@ public List getIngredients() { .map(UserRecipeItem::getIngredient) .collect(Collectors.toList()); } + + public void clear() { + this.userRecipe = new ArrayList<>(); + } } From eb364c179bb16255a64e4cd83d16f7a80eea1f55 Mon Sep 17 00:00:00 2001 From: KimGyeong Date: Wed, 24 Feb 2021 01:53:19 +0900 Subject: [PATCH 08/16] =?UTF-8?q?feat:=20=EB=82=98=EB=A7=8C=EC=9D=98=20?= =?UTF-8?q?=EB=A0=88=EC=8B=9C=ED=94=BC=20=EC=82=AD=EC=A0=9C=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/UserCocktailController.java | 7 +++++++ .../controller/UserCocktailControllerTest.java | 14 ++++++++++++++ .../controller/docs/UserCocktailDocumentation.java | 8 ++++++++ .../com/cocktailpick/core/user/domain/User.java | 2 +- .../usercocktail/service/UserCocktailService.java | 13 ++++++++++++- 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java index 87ab6c27..923e611d 100644 --- a/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java +++ b/back/cocktailpick-api/src/main/java/com/cocktailpick/api/userCocktail/controller/UserCocktailController.java @@ -4,6 +4,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -51,4 +52,10 @@ public ResponseEntity updateUserCocktail(@CurrentUser User user, @PathVari userCocktailService.updateUserCocktail(user, id, updateUserCocktailRequest); return ResponseEntity.ok().build(); } + + @DeleteMapping("/{id}") + public ResponseEntity deleteUserCocktail(@CurrentUser User user, @PathVariable Long id) { + userCocktailService.deleteUserCocktail(user, id); + return ResponseEntity.noContent().build(); + } } diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java index d2df57fe..3d3556f9 100644 --- a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java @@ -138,4 +138,18 @@ void updateUserCocktail() throws Exception { .andDo(print()) .andDo(UserCocktailDocumentation.updateUserCocktails()); } + + @DisplayName("나만의 레시피를 삭제한다.") + @WithMockCustomUser + @Test + void deleteUserCocktail() throws Exception { + doNothing().when(userCocktailService).deleteUserCocktail(any(), anyLong()); + + mockMvc.perform(RestDocumentationRequestBuilders.delete("/api/user-cocktails/{id}", 1L) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()) + .andDo(print()) + .andDo(UserCocktailDocumentation.deleteUserCocktail()); + + } } \ No newline at end of file diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java index 45b1806e..ecb6c7af 100644 --- a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java @@ -3,6 +3,7 @@ import static org.springframework.restdocs.headers.HeaderDocumentation.*; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*; import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.*; import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; import org.springframework.restdocs.payload.JsonFieldType; @@ -90,4 +91,11 @@ public static RestDocumentationResultHandler updateUserCocktails() { ) ); } + + public static RestDocumentationResultHandler deleteUserCocktail() { + return document("UserCocktails/delete", + pathParameters( + parameterWithName("id").description("수정할 칵테일 ID") + )); + } } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/user/domain/User.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/user/domain/User.java index a0c8a16e..9485c9be 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/user/domain/User.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/user/domain/User.java @@ -89,7 +89,7 @@ public boolean isDuplicated(Favorite favorite) { return favorites.isDuplicated(favorite); } - public boolean isNotPossibleToUpdateUserCocktail(Long userId) { + public boolean isNotPossibleToAccessUserCocktail(Long userId) { return !this.id.equals(userId) || this.role != Role.ROLE_ADMIN; } diff --git a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java index 50dcbe48..18ce564a 100644 --- a/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java +++ b/back/cocktailpick-core/src/main/java/com/cocktailpick/core/usercocktail/service/UserCocktailService.java @@ -79,7 +79,7 @@ public UserCocktailResponses findUserCocktails() { public void updateUserCocktail(User user, Long id, UserCocktailRequest updateUserCocktailRequest) { UserCocktail userCocktail = findUserCocktailById(id); - if (user.isNotPossibleToUpdateUserCocktail(userCocktail.getMemberId())) { + if (user.isNotPossibleToAccessUserCocktail(userCocktail.getMemberId())) { throw new AuthException(ErrorCode.USERCOCKTAIL_UNAUTHORIZED); } @@ -94,4 +94,15 @@ public void updateUserCocktail(User user, Long id, UserCocktailRequest updateUse userCocktail.update(updateUserCocktail, userRecipeItems); } + + @Transactional + public void deleteUserCocktail(User user, Long id) { + UserCocktail userCocktail = findUserCocktailById(id); + + if (user.isNotPossibleToAccessUserCocktail(userCocktail.getMemberId())) { + throw new AuthException(ErrorCode.USERCOCKTAIL_UNAUTHORIZED); + } + + userCocktailRepository.deleteById(id); + } } From 8ad6abfe895ef81235c2d1a5f6d3a73ecd10cd90 Mon Sep 17 00:00:00 2001 From: KimGyeong Date: Wed, 24 Feb 2021 01:54:19 +0900 Subject: [PATCH 09/16] =?UTF-8?q?refactor:=20UserCocktailDocumentation=20?= =?UTF-8?q?=EB=8B=A8=EC=9D=BC=20=EC=A1=B0=ED=9A=8C,=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20PathParameter=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/docs/UserCocktailDocumentation.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java index ecb6c7af..e40efe8f 100644 --- a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/docs/UserCocktailDocumentation.java @@ -27,6 +27,9 @@ public static RestDocumentationResultHandler createUserCocktail() { public static RestDocumentationResultHandler findUserCocktailById() { return document("UserCocktails/find", + pathParameters( + parameterWithName("id").description("수정할 칵테일 ID") + ), responseFields( fieldWithPath("id").type(JsonFieldType.NUMBER).description("나만의 레시피 아이디"), fieldWithPath("name").type(JsonFieldType.STRING).description("나만의 레시피 이름"), @@ -78,6 +81,9 @@ public static RestDocumentationResultHandler findUserCocktails() { public static RestDocumentationResultHandler updateUserCocktails() { return document("UserCocktails/update", + pathParameters( + parameterWithName("id").description("수정할 칵테일 ID") + ), requestFields( fieldWithPath("name").type(JsonFieldType.STRING).description("업데이트될 나만의 레시피 이름"), fieldWithPath("description").type(JsonFieldType.STRING).description("업데이트 될 나만의 레시피 설명"), From 96332850427fc59c72a3b8c2fbf605adc1360a5e Mon Sep 17 00:00:00 2001 From: toneyparky Date: Wed, 24 Feb 2021 09:38:03 +0900 Subject: [PATCH 10/16] =?UTF-8?q?style:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EA=B3=B5=EB=B0=B1=20=EC=A0=9C=EA=B1=B0,=20?= =?UTF-8?q?=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/controller/UserCocktailControllerTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java index 3d3556f9..a089430a 100644 --- a/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java +++ b/back/cocktailpick-api/src/test/java/com/cocktailpick/api/userCocktail/controller/controller/UserCocktailControllerTest.java @@ -125,14 +125,14 @@ void findUserCocktails() throws Exception { @WithMockCustomUser @Test void updateUserCocktail() throws Exception { - UserCocktailRequest userCocktailupdateRequest = UserCocktailRequest.builder() + UserCocktailRequest userCocktailUpdateRequest = UserCocktailRequest.builder() .name("updateUserCocktail") .description("해피해킹 없이는 살 수 없는 몸이 돼었어") .userRecipeItemRequests(Collections.singletonList(userRecipeItemRequest)) .build(); mockMvc.perform(RestDocumentationRequestBuilders.put("/api/user-cocktails/{id}", 1L) - .content(objectMapper.writeValueAsString(userCocktailupdateRequest)) + .content(objectMapper.writeValueAsString(userCocktailUpdateRequest)) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andDo(print()) @@ -150,6 +150,5 @@ void deleteUserCocktail() throws Exception { .andExpect(status().isNoContent()) .andDo(print()) .andDo(UserCocktailDocumentation.deleteUserCocktail()); - } } \ No newline at end of file From 0935b22ee85142eda0bd5edb3579980cdc98e91d Mon Sep 17 00:00:00 2001 From: toneyparky Date: Mon, 22 Feb 2021 10:45:41 +0900 Subject: [PATCH 11/16] =?UTF-8?q?feat:=20Amount=20=EC=84=A0=ED=83=9D?= =?UTF-8?q?=EC=8B=9C=20=EC=A0=84=EC=97=AD=20=EA=B0=9D=EC=B2=B4=EA=B3=BC=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/component/userCocktail/Amount.js | 68 +++++++++++++++++++++- front/src/component/userCocktail/Glass.js | 11 ++-- 2 files changed, 72 insertions(+), 7 deletions(-) diff --git a/front/src/component/userCocktail/Amount.js b/front/src/component/userCocktail/Amount.js index fdf3bb30..bc21e04a 100644 --- a/front/src/component/userCocktail/Amount.js +++ b/front/src/component/userCocktail/Amount.js @@ -1,21 +1,87 @@ -import React from "react"; +import React, { useState } from "react"; import { useHistory } from "react-router-dom"; import { useRecoilState } from "recoil"; import { userCocktailState } from "../../recoil"; +import div from "infinite-react-carousel"; +import GlassItem from "./GlassItem"; const Amount = ({ setStage }) => { const history = useHistory(); const [userCocktail, setUserCocktail] = useRecoilState(userCocktailState); + const [selected, setSelected] = useState({ id: 0, name: "기본값" }); const onNext = (e) => { e.preventDefault(); + const lastRecipe = + userCocktail.userRecipeItemRequests[ + userCocktail.userRecipeItemRequests.length - 1 + ]; + setUserCocktail({ + ...userCocktail, + userRecipeItemRequests: [ + ...userCocktail.userRecipeItemRequests.slice(0, -1), + { + ingredientId: lastRecipe.ingredientId, + ingredientName: lastRecipe.ingredientName, + glassId: lastRecipe.id, + glassName: lastRecipe.name, + amountId: selected.id, + amountName: selected.name, + }, + ], + }); history.push("/my-cocktail/recipe"); setStage("recipe"); }; + const units = + // api로 받아오든 내부에 있는 값을 가져오든 해야한다. + // 값도 바뀌어야 한다. 잔의 종류에 따라 멘트가 다르게 나와야 한다. Piece일 경우에는 개로 표현한다던가. + [ + { id: 1, name: "반 잔" }, + { id: 2, name: "반의 반 잔" }, + { id: 3, name: "한 잔" }, + { id: 4, name: "두 잔" }, + { id: 5, name: "세 잔" }, + { id: 6, name: "네 잔" }, + ]; + + const onSelect = (e) => { + const selectedId = e.target.dataset.id; + const found = units.find((it) => it.id === parseInt(selectedId)); + setSelected(found); + }; + return (
amount 화면입니다.
+
+
{selected.name}
+ +
+
+ {"재료: " + + userCocktail.userRecipeItemRequests[ + userCocktail.userRecipeItemRequests.length - 1 + ].ingredientName} +
+
+ {"잔 종류: " + + userCocktail.userRecipeItemRequests[ + userCocktail.userRecipeItemRequests.length - 1 + ].glassName} +
+
+ {/*Slider로 수정*/} + {units && + units.map((it) => ( +
+
+ {it.name} +
+
+ ))} +
diff --git a/front/src/component/userCocktail/Glass.js b/front/src/component/userCocktail/Glass.js index aa757480..c3720f2c 100644 --- a/front/src/component/userCocktail/Glass.js +++ b/front/src/component/userCocktail/Glass.js @@ -36,12 +36,11 @@ const Glass = ({ setStage }) => { // api로 받아오든 내부에 있는 값을 가져오든 해야한다. // 값도 바뀌어야 한다. 백에서 원하는 SOJU BEER PAPER SHOT PIECE를 가지고 이미지 링크와 한글 이름이 필요하다. [ - { id: 1, name: "반 잔" }, - { id: 2, name: "반의 반 잔" }, - { id: 3, name: "한 잔" }, - { id: 4, name: "두 잔" }, - { id: 5, name: "세 잔" }, - { id: 6, name: "네 잔" }, + { id: 1, name: "SOJU" }, + { id: 2, name: "BEER" }, + { id: 3, name: "PAPER" }, + { id: 4, name: "SHOT" }, + { id: 5, name: "PIECE" }, ]; const onSelect = (e) => { From 4e739d7d0be6c2709dd9e04af469d20b62076c1c Mon Sep 17 00:00:00 2001 From: toneyparky Date: Mon, 22 Feb 2021 12:32:51 +0900 Subject: [PATCH 12/16] =?UTF-8?q?fix:=20=ED=94=84=EB=A1=9C=ED=8D=BC?= =?UTF-8?q?=ED=8B=B0=20=EA=B0=92=20=EC=9E=98=EB=AA=BB=20=EB=84=A3=EC=96=B4?= =?UTF-8?q?=EC=A4=80=20=EA=B2=83=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/component/userCocktail/Recipe.js | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/front/src/component/userCocktail/Recipe.js b/front/src/component/userCocktail/Recipe.js index da5fe94f..13cb316a 100644 --- a/front/src/component/userCocktail/Recipe.js +++ b/front/src/component/userCocktail/Recipe.js @@ -19,9 +19,33 @@ const Recipe = ({ setStage }) => { setStage("ingredients"); }; + const removeRecipe = (e) => { + if (!window.confirm("정말 레시피를 제거하시겠습니까?")) { + return; + } + const selectedIndex = parseInt(e.target.dataset.id); + const recipeRequests = [...userCocktail.userRecipeItemRequests]; + recipeRequests.splice(selectedIndex, 1); + + setUserCocktail({ + ...userCocktail, + userRecipeItemRequests: recipeRequests, + }); + }; + + const recipe = userCocktail.userRecipeItemRequests.map((it, index) => ( +
+ {it.ingredientName} {it.glassName} {it.amountName} + +
+ )); + return ( <>
recipe 화면입니다.
+ {recipe} - diff --git a/front/src/component/userCocktail/UserCocktail.js b/front/src/component/userCocktail/UserCocktail.js index 0d4e5a95..e8db59cb 100644 --- a/front/src/component/userCocktail/UserCocktail.js +++ b/front/src/component/userCocktail/UserCocktail.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import StepProgressBar from "./StepProgressBar"; import "react-step-progress-bar/styles.css"; import "../../css/userCocktail/userCocktail.css"; @@ -8,6 +8,8 @@ import Ingredient from "./Ingredient"; import Glass from "./Glass"; import Amount from "./Amount"; import Recipe from "./Recipe"; +import List from "./UserCocktailItems"; +import UserCocktailItems from "./UserCocktailItems"; const UserCocktail = () => { const INITIAL_STAGE = ""; @@ -16,7 +18,7 @@ const UserCocktail = () => { const renderContents = () => { switch (stage) { case INITIAL_STAGE: - return
처음 화면이니까
; + return ; case "name": return ; case "ingredients": diff --git a/front/src/component/userCocktail/UserCocktailItems.js b/front/src/component/userCocktail/UserCocktailItems.js new file mode 100644 index 00000000..1a8ce05f --- /dev/null +++ b/front/src/component/userCocktail/UserCocktailItems.js @@ -0,0 +1,26 @@ +import React from "react"; +import { useRecoilState } from "recoil"; +import { userCocktailState } from "../../recoil"; +import { useHistory } from "react-router-dom"; + +const UserCocktailItems = ({ setStage }) => { + // todo 사실은 api를 쏴서 보여줘야 한다. + const [userCocktail, setUserCocktail] = useRecoilState(userCocktailState); + const history = useHistory(); + + const onCreate = (e) => { + e.preventDefault(); + history.push("/my-cocktail/name"); + setStage("name"); + }; + + return ( + <> +
{userCocktail.name}
+
{userCocktail.description}
+ + + ); +}; + +export default UserCocktailItems; From 832923cf1083148cd2502c7a02449dcfa961368c Mon Sep 17 00:00:00 2001 From: toneyparky Date: Mon, 22 Feb 2021 17:18:39 +0900 Subject: [PATCH 15/16] =?UTF-8?q?fix:=20Amount=20=EB=8B=A8=EC=9C=84=20?= =?UTF-8?q?=EB=B3=B4=EC=97=AC=EC=A3=BC=EB=8A=94=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=EC=97=90=20key=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/component/userCocktail/Amount.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/front/src/component/userCocktail/Amount.js b/front/src/component/userCocktail/Amount.js index 9de8ac03..e697f775 100644 --- a/front/src/component/userCocktail/Amount.js +++ b/front/src/component/userCocktail/Amount.js @@ -74,8 +74,12 @@ const Amount = ({ setStage }) => {
{/*Slider로 수정*/} {units && - units.map((it) => ( -
+ units.map((it, index) => ( +
{it.name}
From a541df5b42f5dee3a069bd27266bfa30bed3b45b Mon Sep 17 00:00:00 2001 From: toneyparky Date: Wed, 24 Feb 2021 10:28:56 +0900 Subject: [PATCH 16/16] =?UTF-8?q?refactor:=20=EB=B0=B1=EA=B3=BC=20?= =?UTF-8?q?=ED=94=84=EB=A1=A0=ED=8A=B8=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=EC=9D=84=20=EB=A7=9E=EC=B6=94=EA=B8=B0=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 프론트의 amount => quantity, glass => quantity unit --- front/src/component/userCocktail/GlassItem.js | 13 --------- .../src/component/userCocktail/Ingredient.js | 4 +-- .../userCocktail/{Amount.js => Quantity.js} | 23 ++++++++------- .../{Glass.js => QuantityUnit.js} | 28 +++++++++---------- .../userCocktail/QuantityUnitItem.js | 13 +++++++++ front/src/component/userCocktail/Recipe.js | 2 +- .../component/userCocktail/UserCocktail.js | 19 ++++++------- front/src/constants/index.js | 6 ++-- 8 files changed, 54 insertions(+), 54 deletions(-) delete mode 100644 front/src/component/userCocktail/GlassItem.js rename front/src/component/userCocktail/{Amount.js => Quantity.js} (83%) rename front/src/component/userCocktail/{Glass.js => QuantityUnit.js} (75%) create mode 100644 front/src/component/userCocktail/QuantityUnitItem.js diff --git a/front/src/component/userCocktail/GlassItem.js b/front/src/component/userCocktail/GlassItem.js deleted file mode 100644 index 5348c47b..00000000 --- a/front/src/component/userCocktail/GlassItem.js +++ /dev/null @@ -1,13 +0,0 @@ -import React from "react"; - -const GlassItem = ({ glass, onSelect }) => { - return ( -
-
- {glass.name} -
-
- ); -}; - -export default GlassItem; diff --git a/front/src/component/userCocktail/Ingredient.js b/front/src/component/userCocktail/Ingredient.js index a50e7719..d23f4aa9 100644 --- a/front/src/component/userCocktail/Ingredient.js +++ b/front/src/component/userCocktail/Ingredient.js @@ -23,8 +23,8 @@ const Ingredient = ({ setStage }) => { { ingredientId: selected.id, ingredientName: selected.name }, ], }); - history.push("/my-cocktail/glass"); - setStage("glass"); + history.push("/my-cocktail/quantity-unit"); + setStage("quantity-unit"); }; const ingredients = () => { diff --git a/front/src/component/userCocktail/Amount.js b/front/src/component/userCocktail/Quantity.js similarity index 83% rename from front/src/component/userCocktail/Amount.js rename to front/src/component/userCocktail/Quantity.js index e697f775..b799d345 100644 --- a/front/src/component/userCocktail/Amount.js +++ b/front/src/component/userCocktail/Quantity.js @@ -3,9 +3,8 @@ import { useHistory } from "react-router-dom"; import { useRecoilState } from "recoil"; import { userCocktailState } from "../../recoil"; import div from "infinite-react-carousel"; -import GlassItem from "./GlassItem"; -const Amount = ({ setStage }) => { +const Quantity = ({ setStage }) => { const history = useHistory(); const [userCocktail, setUserCocktail] = useRecoilState(userCocktailState); const [selected, setSelected] = useState({ id: 0, name: "기본값" }); @@ -23,10 +22,10 @@ const Amount = ({ setStage }) => { { ingredientId: lastRecipe.ingredientId, ingredientName: lastRecipe.ingredientName, - glassId: lastRecipe.id, - glassName: lastRecipe.glassName, - amountId: selected.id, - amountName: selected.name, + quantityUnitId: lastRecipe.quantityUnitId, + quantityUnitName: lastRecipe.quantityUnitName, + quantityId: selected.id, + quantityName: selected.name, }, ], }); @@ -54,7 +53,7 @@ const Amount = ({ setStage }) => { return (
-
amount 화면입니다.
+
quantity 화면입니다.
{selected.name}
@@ -69,18 +68,18 @@ const Amount = ({ setStage }) => { {"잔 종류: " + userCocktail.userRecipeItemRequests[ userCocktail.userRecipeItemRequests.length - 1 - ].glassName} + ].quantityUnitName}
{/*Slider로 수정*/} {units && units.map((it, index) => (
-
+
{it.name}
@@ -93,4 +92,4 @@ const Amount = ({ setStage }) => { ); }; -export default Amount; +export default Quantity; diff --git a/front/src/component/userCocktail/Glass.js b/front/src/component/userCocktail/QuantityUnit.js similarity index 75% rename from front/src/component/userCocktail/Glass.js rename to front/src/component/userCocktail/QuantityUnit.js index c3720f2c..7a4da7f9 100644 --- a/front/src/component/userCocktail/Glass.js +++ b/front/src/component/userCocktail/QuantityUnit.js @@ -3,9 +3,9 @@ import { useHistory } from "react-router-dom"; import { useRecoilState } from "recoil"; import div from "infinite-react-carousel"; import { userCocktailState } from "../../recoil"; -import GlassItem from "./GlassItem"; +import QuantityUnitItem from "./QuantityUnitItem"; -const Glass = ({ setStage }) => { +const QuantityUnit = ({ setStage }) => { const history = useHistory(); const [userCocktail, setUserCocktail] = useRecoilState(userCocktailState); const [selected, setSelected] = useState({ id: 0, name: "기본값" }); @@ -23,16 +23,16 @@ const Glass = ({ setStage }) => { { ingredientId: lastRecipe.ingredientId, ingredientName: lastRecipe.ingredientName, - glassId: selected.id, - glassName: selected.name, + quantityUnitId: selected.id, + quantityUnitName: selected.name, }, ], }); - history.push("/my-cocktail/amount"); - setStage("amount"); + history.push("/my-cocktail/quantity"); + setStage("quantity"); }; - const glasses = + const quantityUnits = // api로 받아오든 내부에 있는 값을 가져오든 해야한다. // 값도 바뀌어야 한다. 백에서 원하는 SOJU BEER PAPER SHOT PIECE를 가지고 이미지 링크와 한글 이름이 필요하다. [ @@ -45,13 +45,13 @@ const Glass = ({ setStage }) => { const onSelect = (e) => { const selectedId = e.target.dataset.id; - const found = glasses.find((it) => it.id === parseInt(selectedId)); + const found = quantityUnits.find((it) => it.id === parseInt(selectedId)); setSelected(found); }; return ( -
-
glass 화면입니다.
+
+
quantity unit 화면입니다.
{selected.name}
@@ -64,9 +64,9 @@ const Glass = ({ setStage }) => {
{/*Slider로 수정*/} - {glasses && - glasses.map((it) => ( - + {quantityUnits && + quantityUnits.map((it) => ( + ))}
diff --git a/front/src/component/userCocktail/UserCocktail.js b/front/src/component/userCocktail/UserCocktail.js index e8db59cb..3961994a 100644 --- a/front/src/component/userCocktail/UserCocktail.js +++ b/front/src/component/userCocktail/UserCocktail.js @@ -1,14 +1,13 @@ -import React, { useEffect, useState } from "react"; +import React, { useState } from "react"; import StepProgressBar from "./StepProgressBar"; import "react-step-progress-bar/styles.css"; import "../../css/userCocktail/userCocktail.css"; import Question from "./Question"; import Name from "./Name"; import Ingredient from "./Ingredient"; -import Glass from "./Glass"; -import Amount from "./Amount"; +import Quantity from "./Quantity"; import Recipe from "./Recipe"; -import List from "./UserCocktailItems"; +import QuantityUnit from "./QuantityUnit"; import UserCocktailItems from "./UserCocktailItems"; const UserCocktail = () => { @@ -23,10 +22,10 @@ const UserCocktail = () => { return ; case "ingredients": return ; - case "glass": - return ; - case "amount": - return ; + case "quantity-unit": + return ; + case "quantity": + return ; case "recipe": return ; } @@ -40,9 +39,9 @@ const UserCocktail = () => { return 0; case "ingredients": return 25; - case "glass": + case "quantity-unit": return 50; - case "amount": + case "quantity": return 75; case "recipe": return 100; diff --git a/front/src/constants/index.js b/front/src/constants/index.js index bdec2819..18349a8a 100644 --- a/front/src/constants/index.js +++ b/front/src/constants/index.js @@ -39,8 +39,10 @@ export const USER_COCKTAIL_PROTOTYPE = { // { // ingredientId: "", // ingredientName: "", - // quantityUnit: "", - // quantity: "", + // quantityUnitId: "", + // quantityUnitName: "", + // quantityId: "", + // quantityName: "", // }, ], description: "",