Skip to content

Commit

Permalink
Feat: 특정 음식 주문하기 기능의 컨트롤러 구현
Browse files Browse the repository at this point in the history
- Product 테이블과 객체에 stock_quantity 필드 추가
- stock_quantity 샘플 데이터 추가
- 컨트롤러 테스트 구현
  • Loading branch information
Louie-03 committed Apr 25, 2022
1 parent a763171 commit 401b9ad
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 39 deletions.
25 changes: 25 additions & 0 deletions BE/src/main/java/sidedish/com/controller/OrderController.java
@@ -0,0 +1,25 @@
package sidedish.com.controller;

import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
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.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import sidedish.com.service.OrderService;

@RequiredArgsConstructor
@RestController
public class OrderController {

private final OrderService orderService;

@PostMapping("/api/products/{id}/order")
@ResponseStatus(HttpStatus.CREATED)
public Long order(@PathVariable Long id, @RequestBody Map<String, Integer> map) {
int count = map.get("count");
return orderService.save(id, count);
}
}
6 changes: 4 additions & 2 deletions BE/src/main/java/sidedish/com/domain/Product.java
@@ -1,7 +1,6 @@
package sidedish.com.domain;

import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
Expand All @@ -17,20 +16,23 @@ public class Product {
private final String description;
private final long fixedPrice;
private final long originalPrice;
private final long stockQuantity;
private final String mealCategory;
private final String bestCategory;
private final long mileage;

public Product(Long id, DiscountPolicy discountPolicy,
DeliveryPolicy deliveryPolicy, List<Image> images, String productName,
String description, long originalPrice, String mealCategory, String bestCategory) {
String description, long originalPrice, long stockQuantity, String mealCategory,
String bestCategory) {
this.id = id;
this.discountPolicy = discountPolicy;
this.deliveryPolicy = deliveryPolicy;
this.images = images;
this.productName = productName;
this.description = description;
this.originalPrice = originalPrice;
this.stockQuantity = stockQuantity;
this.mealCategory = mealCategory;
this.bestCategory = bestCategory;
this.fixedPrice = calculateFixedPrice();
Expand Down
Expand Up @@ -35,9 +35,7 @@ public Product toDomainFromProductEntity(ProductEntity productEntity,
DeliveryPolicyEntity deliveryPolicyEntity = searchDeliveryPolicyEntity(
deliveryPolicyEntities, productEntity);

Product product = createProduct(productEntity, discountPolicyEntity, deliveryPolicyEntity);

return product;
return createProduct(productEntity, discountPolicyEntity, deliveryPolicyEntity);
}

private DiscountPolicyEntity searchDiscountPolicyEntity(
Expand Down Expand Up @@ -78,6 +76,7 @@ public Product createProduct(ProductEntity productEntity,
productEntity.getProductName(),
productEntity.getDescription(),
productEntity.getOriginalPrice(),
productEntity.getStockQuantity(),
productEntity.getMealCategory(),
productEntity.getBestCategory());
}
Expand Down
Expand Up @@ -11,7 +11,7 @@ public interface ProductsRepository extends CrudRepository<ProductEntity, Long>
@Override
List<ProductEntity> findAll();

@Query("select id, discount_policy_id, delivery_policy_id, product_name, description, original_price, meal_category "
@Query("select id, discount_policy_id, delivery_policy_id, product_name, description, original_price, stock_quantity, meal_category "
+ "from PRODUCT where meal_category = :mealType")
List<ProductEntity> findByMealType(@Param("mealType") String mealType);

Expand Down
Expand Up @@ -20,22 +20,24 @@ public class ProductEntity {
private final String productName;
private final String description;
private final long originalPrice;
private final long stockQuantity;
private final String mealCategory;
private final String bestCategory;


@PersistenceConstructor
public ProductEntity(Long id, Long discountPolicyId,
Long deliveryPolicyId, List<ImageEntity> imageEntities, String productName,
String description, long originalPrice,
String mealCategory, String bestCategory) {
String description, long originalPrice, long stockQuantity, String mealCategory,
String bestCategory) {
this.id = id;
this.discountPolicyId = discountPolicyId;
this.deliveryPolicyId = deliveryPolicyId;
this.imageEntities = imageEntities;
this.productName = productName;
this.description = description;
this.originalPrice = originalPrice;
this.stockQuantity = stockQuantity;
this.mealCategory = mealCategory;
this.bestCategory = bestCategory;
}
Expand Down
13 changes: 13 additions & 0 deletions BE/src/main/java/sidedish/com/service/OrderService.java
@@ -0,0 +1,13 @@
package sidedish.com.service;

import org.springframework.stereotype.Service;

@Service
public class OrderService {



public Long save(Long productId, int count) {
return null;
}
}
26 changes: 13 additions & 13 deletions BE/src/main/resources/db/data.sql
Expand Up @@ -6,20 +6,20 @@ INSERT INTO delivery_policy (delivery_info, delivery_charge, free_delivery_over_
VALUES ('서울 경기 새벽 배송, 전국 택배 배송', 2500, 40000);

INSERT INTO product (discount_policy_id, delivery_policy_id, product_name, description,
original_price, meal_category,
original_price, stock_quantity, meal_category,
best_category)
VALUES (1, 1, '오리주물럭', '감칠맛 나는 매콤한 양념', 15800, 'main', 'meat'),
(2, 1, '잡채', '탱글한 면과 맛깔진 고명이 가득', 12900, 'main', null),
(2, 1, '소갈비찜', '촉촉하게 밴 양념이 일품', 28900, 'main', 'meat'),
(null, 1, '간장 코다리조림', '쫀득한 코다리를 국내산 간장소스로맛있게 조렸어요', 14900, 'main', 'season'),
(2, 1, '한돈 돼지 김치찌개', '김치찌개에는 역시 돼지고기', 9300, 'soup', 'meat'),
(2, 1, '된장찌개', '특별하지 않아서 더 좋은 우리맛', 8800, 'soup', 'easy'),
(2, 1, '미역오이냉국', '여름엔 시원한 냉국이 최고', 7800, 'soup', 'season'),
(null, 1, '동태찌개', '겨울철 보양식으로 안성맞춤', 12000, 'soup', null),
(1, 1, '새콤달콤 오징어무침', '국내산 오징어를 새콤달콤하게', 7500, 'side', 'kids'),
(2, 1, '호두 멸치볶음', '잔명치와 호두가 만나 짭쪼름하지만 고소하게!', 5800, 'side', 'kids'),
(2, 1, '한동 매콤 안심장조림', '촉촉하게 밴 양념이 일품', 6900, 'side', 'easy'),
(2, 1, '야채 어묵볶음', '첨가물 없는 순수어묵과 야채와 만남', 4900, 'side', 'easy');
VALUES (1, 1, '오리주물럭', '감칠맛 나는 매콤한 양념', 15800, 100, 'main', 'meat'),
(2, 1, '잡채', '탱글한 면과 맛깔진 고명이 가득', 12900, 100, 'main', null),
(2, 1, '소갈비찜', '촉촉하게 밴 양념이 일품', 28900, 100, 'main', 'meat'),
(null, 1, '간장 코다리조림', '쫀득한 코다리를 국내산 간장소스로맛있게 조렸어요', 14900, 100, 'main', 'season'),
(2, 1, '한돈 돼지 김치찌개', '김치찌개에는 역시 돼지고기', 9300, 100, 'soup', 'meat'),
(2, 1, '된장찌개', '특별하지 않아서 더 좋은 우리맛', 8800, 100, 'soup', 'easy'),
(2, 1, '미역오이냉국', '여름엔 시원한 냉국이 최고', 7800, 100, 'soup', 'season'),
(null, 1, '동태찌개', '겨울철 보양식으로 안성맞춤', 12000, 100, 'soup', null),
(1, 1, '새콤달콤 오징어무침', '국내산 오징어를 새콤달콤하게', 7500, 100, 'side', 'kids'),
(2, 1, '호두 멸치볶음', '잔명치와 호두가 만나 짭쪼름하지만 고소하게!', 5800, 100, 'side', 'kids'),
(2, 1, '한동 매콤 안심장조림', '촉촉하게 밴 양념이 일품', 6900, 100, 'side', 'easy'),
(2, 1, '야채 어묵볶음', '첨가물 없는 순수어묵과 야채와 만남', 4900, 100, 'side', 'easy');


INSERT INTO product_image (product_id, image_url)
Expand Down
1 change: 1 addition & 0 deletions BE/src/main/resources/db/schema.sql
Expand Up @@ -26,6 +26,7 @@ create table product
product_name varchar(100) not null,
description varchar(1000),
original_price int not null,
stock_quantity int not null,
meal_category varchar(100) not null,
best_category varchar(100),
foreign key (discount_policy_id) references discount_policy (id),
Expand Down
46 changes: 46 additions & 0 deletions BE/src/test/java/sidedish/com/controller/OrderControllerTest.java
@@ -0,0 +1,46 @@
package sidedish.com.controller;

import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Collections;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
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.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import sidedish.com.service.OrderService;

@WebMvcTest(OrderController.class)
@DisplayName("OrderController 클래스")
class OrderControllerTest {

@Autowired
MockMvc mockMvc;

@MockBean
OrderService orderService;

@Test
void 만약_특정_상품_id_주문_요청을_하는_경우_재고가_남아있다면_주문_성공() throws Exception {
given(orderService.save(1L, 3))
.willReturn(1L);

ObjectMapper objectMapper = new ObjectMapper();

ResultActions perform = mockMvc.perform(
post("/api/products/1/order")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(Collections.singletonMap("count", 3))));

perform
.andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
}
}
Expand Up @@ -15,8 +15,8 @@
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import sidedish.com.controller.model.ProductDetailTypeResponse;
import sidedish.com.controller.model.ProductBasicTypeResponse;
import sidedish.com.controller.model.ProductDetailTypeResponse;
import sidedish.com.domain.DeliveryPolicy;
import sidedish.com.domain.DiscountPolicy;
import sidedish.com.domain.Image;
Expand Down Expand Up @@ -82,11 +82,11 @@ private List<ProductBasicTypeResponse> createProductsMealTypeResponse() {
products.add(
new Product(5L, discountPolicy, deliveryPolicy,
List.of(new Image("http://kukukukukukukukuku.com/test.jpg")),
"한돈 돼지 김치찌개", "김치찌개에는 역시 돼지고기", 8370, "soup", "meat"));
"한돈 돼지 김치찌개", "김치찌개에는 역시 돼지고기", 8370, 100, "soup", "meat"));
products.add(
new Product(6L, discountPolicy, deliveryPolicy,
List.of(new Image("http://kukukukukukukukuku.com/test2.jpg")),
"하하하 테스트 음식", "맛있어요", 8370, "main", "soup"));
"하하하 테스트 음식", "맛있어요", 8370, 100, "main", "soup"));

return productsDtoMapper.toProductsBasicTypeResponseFromDomain(products);
}
Expand Down
4 changes: 2 additions & 2 deletions BE/src/test/java/sidedish/com/domain/ProductTest.java
Expand Up @@ -28,7 +28,7 @@ void It_returns_a_Product() {

Product sut = new Product(1L, discountPolicy, deliveryPolicy, List.of(image),
"김치찌개", "맛있어요",
10000, "soup", "meat");
10000, 100, "soup", "meat");

assertThat(sut.getDiscountPolicy().getPolicyName()).isEqualTo("이벤트특가");
assertThat(sut.getFixedPrice()).isEqualTo(8000);
Expand All @@ -48,7 +48,7 @@ void It_returns_a_Product() {

Product sut = new Product(1L, discountPolicy, deliveryPolicy, List.of(image),
"김치찌개", "맛있어요",
10000, "soup", "meat");
10000, 100, "soup", "meat");

assertThat(sut.getDiscountPolicy().getPolicyName()).isEqualTo("런칭특가");
assertThat(sut.getFixedPrice()).isEqualTo(9000);
Expand Down
26 changes: 13 additions & 13 deletions BE/src/test/resources/testdb/data.sql
Expand Up @@ -6,20 +6,20 @@ INSERT INTO delivery_policy (delivery_info, delivery_charge, free_delivery_over_
VALUES ('서울 경기 새벽 배송, 전국 택배 배송', 2500, 40000);

INSERT INTO product (discount_policy_id, delivery_policy_id, product_name, description,
original_price, meal_category,
original_price, stock_quantity, meal_category,
best_category)
VALUES (1, 1, '오리주물럭', '감칠맛 나는 매콤한 양념', 15800, 'main', 'meat'),
(2, 1, '잡채', '탱글한 면과 맛깔진 고명이 가득', 12900, 'main', null),
(2, 1, '소갈비찜', '촉촉하게 밴 양념이 일품', 28900, 'main', 'meat'),
(null, 1, '간장 코다리조림', '쫀득한 코다리를 국내산 간장소스로맛있게 조렸어요', 14900, 'main', 'season'),
(2, 1, '한돈 돼지 김치찌개', '김치찌개에는 역시 돼지고기', 9300, 'soup', 'meat'),
(2, 1, '된장찌개', '특별하지 않아서 더 좋은 우리맛', 8800, 'soup', 'easy'),
(2, 1, '미역오이냉국', '여름엔 시원한 냉국이 최고', 7800, 'soup', 'season'),
(null, 1, '동태찌개', '겨울철 보양식으로 안성맞춤', 12000, 'soup', null),
(1, 1, '새콤달콤 오징어무침', '국내산 오징어를 새콤달콤하게', 7500, 'side', 'kids'),
(2, 1, '호두 멸치볶음', '잔명치와 호두가 만나 짭쪼름하지만 고소하게!', 5800, 'side', 'kids'),
(2, 1, '한동 매콤 안심장조림', '촉촉하게 밴 양념이 일품', 6900, 'side', 'easy'),
(2, 1, '야채 어묵볶음', '첨가물 없는 순수어묵과 야채와 만남', 4900, 'side', 'easy');
VALUES (1, 1, '오리주물럭', '감칠맛 나는 매콤한 양념', 15800, 100, 'main', 'meat'),
(2, 1, '잡채', '탱글한 면과 맛깔진 고명이 가득', 12900, 100, 'main', null),
(2, 1, '소갈비찜', '촉촉하게 밴 양념이 일품', 28900, 100, 'main', 'meat'),
(null, 1, '간장 코다리조림', '쫀득한 코다리를 국내산 간장소스로맛있게 조렸어요', 14900, 100, 'main', 'season'),
(2, 1, '한돈 돼지 김치찌개', '김치찌개에는 역시 돼지고기', 9300, 100, 'soup', 'meat'),
(2, 1, '된장찌개', '특별하지 않아서 더 좋은 우리맛', 8800, 100, 'soup', 'easy'),
(2, 1, '미역오이냉국', '여름엔 시원한 냉국이 최고', 7800, 100, 'soup', 'season'),
(null, 1, '동태찌개', '겨울철 보양식으로 안성맞춤', 12000, 100, 'soup', null),
(1, 1, '새콤달콤 오징어무침', '국내산 오징어를 새콤달콤하게', 7500, 100, 'side', 'kids'),
(2, 1, '호두 멸치볶음', '잔명치와 호두가 만나 짭쪼름하지만 고소하게!', 5800, 100, 'side', 'kids'),
(2, 1, '한동 매콤 안심장조림', '촉촉하게 밴 양념이 일품', 6900, 100, 'side', 'easy'),
(2, 1, '야채 어묵볶음', '첨가물 없는 순수어묵과 야채와 만남', 4900, 100, 'side', 'easy');


INSERT INTO product_image (product_id, image_url)
Expand Down
1 change: 1 addition & 0 deletions BE/src/test/resources/testdb/schema.sql
Expand Up @@ -26,6 +26,7 @@ create table product
product_name varchar(100) not null,
description varchar(1000),
original_price int not null,
stock_quantity int not null,
meal_category varchar(100) not null,
best_category varchar(100),
foreign key (discount_policy_id) references discount_policy (id),
Expand Down

0 comments on commit 401b9ad

Please sign in to comment.