diff --git a/src/main/java/kitchenpos/common/domain/Price.java b/src/main/java/kitchenpos/common/domain/Price.java new file mode 100644 index 000000000..57e20843e --- /dev/null +++ b/src/main/java/kitchenpos/common/domain/Price.java @@ -0,0 +1,56 @@ +package kitchenpos.common.domain; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.math.BigDecimal; +import java.util.Objects; + +@Embeddable +public class Price { + + @Column(name = "price", nullable = false) + private BigDecimal price; + + protected Price() { + } + + public Price(BigDecimal price) { + validation(price); + this.price = price; + } + + private void validation(BigDecimal price) { + if (Objects.isNull(price)) { + throw new IllegalArgumentException("가격은 필수입니다."); + } + + if (price.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalArgumentException("가격은 0원 이상이여야 합니다."); + } + } + + public BigDecimal getPrice() { + return price; + } + + public Price add(Price addPrice) { + return new Price(this.price.add(addPrice.price)); + } + + public int compareTo(Price totalPrice) { + return price.compareTo(totalPrice.price); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Price price1 = (Price) o; + return Objects.equals(price, price1.price); + } + + @Override + public int hashCode() { + return Objects.hash(price); + } +} diff --git a/src/main/java/kitchenpos/eatinorders/application/OrderService.java b/src/main/java/kitchenpos/eatinorders/application/OrderService.java index 91ad8e025..924dee5a7 100644 --- a/src/main/java/kitchenpos/eatinorders/application/OrderService.java +++ b/src/main/java/kitchenpos/eatinorders/application/OrderService.java @@ -2,7 +2,7 @@ import kitchenpos.deliveryorders.infra.KitchenridersClient; import kitchenpos.eatinorders.domain.*; -import kitchenpos.menus.domain.Menu; +import kitchenpos.menus.tobe.domain.Menu; import kitchenpos.menus.domain.MenuRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -20,10 +20,10 @@ public class OrderService { private final KitchenridersClient kitchenridersClient; public OrderService( - final OrderRepository orderRepository, - final MenuRepository menuRepository, - final OrderTableRepository orderTableRepository, - final KitchenridersClient kitchenridersClient + final OrderRepository orderRepository, + final MenuRepository menuRepository, + final OrderTableRepository orderTableRepository, + final KitchenridersClient kitchenridersClient ) { this.orderRepository = orderRepository; this.menuRepository = menuRepository; @@ -42,9 +42,9 @@ public Order create(final Order request) { throw new IllegalArgumentException(); } final List menus = menuRepository.findAllByIdIn( - orderLineItemRequests.stream() - .map(OrderLineItem::getMenuId) - .collect(Collectors.toList()) + orderLineItemRequests.stream() + .map(OrderLineItem::getMenuId) + .collect(Collectors.toList()) ); if (menus.size() != orderLineItemRequests.size()) { throw new IllegalArgumentException(); @@ -58,7 +58,7 @@ public Order create(final Order request) { } } final Menu menu = menuRepository.findById(orderLineItemRequest.getMenuId()) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (!menu.isDisplayed()) { throw new IllegalStateException(); } @@ -85,7 +85,7 @@ public Order create(final Order request) { } if (type == OrderType.EAT_IN) { final OrderTable orderTable = orderTableRepository.findById(request.getOrderTableId()) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (orderTable.isEmpty()) { throw new IllegalStateException(); } @@ -97,7 +97,7 @@ public Order create(final Order request) { @Transactional public Order accept(final UUID orderId) { final Order order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (order.getStatus() != OrderStatus.WAITING) { throw new IllegalStateException(); } @@ -105,8 +105,8 @@ public Order accept(final UUID orderId) { BigDecimal sum = BigDecimal.ZERO; for (final OrderLineItem orderLineItem : order.getOrderLineItems()) { sum = orderLineItem.getMenu() - .getPrice() - .multiply(BigDecimal.valueOf(orderLineItem.getQuantity())); + .getPrice() + .multiply(BigDecimal.valueOf(orderLineItem.getQuantity())); } kitchenridersClient.requestDelivery(orderId, sum, order.getDeliveryAddress()); } @@ -117,7 +117,7 @@ public Order accept(final UUID orderId) { @Transactional public Order serve(final UUID orderId) { final Order order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (order.getStatus() != OrderStatus.ACCEPTED) { throw new IllegalStateException(); } @@ -128,7 +128,7 @@ public Order serve(final UUID orderId) { @Transactional public Order startDelivery(final UUID orderId) { final Order order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (order.getType() != OrderType.DELIVERY) { throw new IllegalStateException(); } @@ -142,7 +142,7 @@ public Order startDelivery(final UUID orderId) { @Transactional public Order completeDelivery(final UUID orderId) { final Order order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (order.getStatus() != OrderStatus.DELIVERING) { throw new IllegalStateException(); } @@ -153,7 +153,7 @@ public Order completeDelivery(final UUID orderId) { @Transactional public Order complete(final UUID orderId) { final Order order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); final OrderType type = order.getType(); final OrderStatus status = order.getStatus(); if (type == OrderType.DELIVERY) { diff --git a/src/main/java/kitchenpos/eatinorders/application/OrderTableService.java b/src/main/java/kitchenpos/eatinorders/application/OrderTableService.java index 0c76c89e6..68ace8e7f 100644 --- a/src/main/java/kitchenpos/eatinorders/application/OrderTableService.java +++ b/src/main/java/kitchenpos/eatinorders/application/OrderTableService.java @@ -39,7 +39,7 @@ public OrderTable create(final OrderTable request) { @Transactional public OrderTable sit(final UUID orderTableId) { final OrderTable orderTable = orderTableRepository.findById(orderTableId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); orderTable.setEmpty(false); return orderTable; } @@ -47,7 +47,7 @@ public OrderTable sit(final UUID orderTableId) { @Transactional public OrderTable clear(final UUID orderTableId) { final OrderTable orderTable = orderTableRepository.findById(orderTableId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (orderRepository.existsByOrderTableAndStatusNot(orderTable, OrderStatus.COMPLETED)) { throw new IllegalStateException(); } @@ -63,7 +63,7 @@ public OrderTable changeNumberOfGuests(final UUID orderTableId, final OrderTable throw new IllegalArgumentException(); } final OrderTable orderTable = orderTableRepository.findById(orderTableId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (orderTable.isEmpty()) { throw new IllegalStateException(); } diff --git a/src/main/java/kitchenpos/eatinorders/domain/Order.java b/src/main/java/kitchenpos/eatinorders/domain/Order.java index 36ec39a46..717b70348 100644 --- a/src/main/java/kitchenpos/eatinorders/domain/Order.java +++ b/src/main/java/kitchenpos/eatinorders/domain/Order.java @@ -25,10 +25,10 @@ public class Order { @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) @JoinColumn( - name = "order_id", - nullable = false, - columnDefinition = "varbinary(16)", - foreignKey = @ForeignKey(name = "fk_order_line_item_to_orders") + name = "order_id", + nullable = false, + columnDefinition = "varbinary(16)", + foreignKey = @ForeignKey(name = "fk_order_line_item_to_orders") ) private List orderLineItems; @@ -37,9 +37,9 @@ public class Order { @ManyToOne @JoinColumn( - name = "order_table_id", - columnDefinition = "varbinary(16)", - foreignKey = @ForeignKey(name = "fk_orders_to_order_table") + name = "order_table_id", + columnDefinition = "varbinary(16)", + foreignKey = @ForeignKey(name = "fk_orders_to_order_table") ) private OrderTable orderTable; diff --git a/src/main/java/kitchenpos/eatinorders/domain/OrderLineItem.java b/src/main/java/kitchenpos/eatinorders/domain/OrderLineItem.java index 990bfefa7..78493d4b0 100644 --- a/src/main/java/kitchenpos/eatinorders/domain/OrderLineItem.java +++ b/src/main/java/kitchenpos/eatinorders/domain/OrderLineItem.java @@ -1,6 +1,6 @@ package kitchenpos.eatinorders.domain; -import kitchenpos.menus.domain.Menu; +import kitchenpos.menus.tobe.domain.Menu; import javax.persistence.*; import java.math.BigDecimal; @@ -16,9 +16,9 @@ public class OrderLineItem { @ManyToOne(optional = false) @JoinColumn( - name = "menu_id", - columnDefinition = "varbinary(16)", - foreignKey = @ForeignKey(name = "fk_order_line_item_to_menu") + name = "menu_id", + columnDefinition = "varbinary(16)", + foreignKey = @ForeignKey(name = "fk_order_line_item_to_menu") ) private Menu menu; diff --git a/src/main/java/kitchenpos/eatinorders/ui/OrderRestController.java b/src/main/java/kitchenpos/eatinorders/ui/OrderRestController.java index 1c2741f73..e0e3d69d8 100644 --- a/src/main/java/kitchenpos/eatinorders/ui/OrderRestController.java +++ b/src/main/java/kitchenpos/eatinorders/ui/OrderRestController.java @@ -22,7 +22,7 @@ public OrderRestController(final OrderService orderService) { public ResponseEntity create(@RequestBody final Order request) { final Order response = orderService.create(request); return ResponseEntity.created(URI.create("/api/orders/" + response.getId())) - .body(response); + .body(response); } @PutMapping("/{orderId}/accept") diff --git a/src/main/java/kitchenpos/eatinorders/ui/OrderTableRestController.java b/src/main/java/kitchenpos/eatinorders/ui/OrderTableRestController.java index 120c28d1d..eaaa85aec 100644 --- a/src/main/java/kitchenpos/eatinorders/ui/OrderTableRestController.java +++ b/src/main/java/kitchenpos/eatinorders/ui/OrderTableRestController.java @@ -22,7 +22,7 @@ public OrderTableRestController(final OrderTableService orderTableService) { public ResponseEntity create(@RequestBody final OrderTable request) { final OrderTable response = orderTableService.create(request); return ResponseEntity.created(URI.create("/api/order-tables/" + response.getId())) - .body(response); + .body(response); } @PutMapping("/{orderTableId}/sit") @@ -37,8 +37,8 @@ public ResponseEntity clear(@PathVariable final UUID orderTableId) { @PutMapping("/{orderTableId}/number-of-guests") public ResponseEntity changeNumberOfGuests( - @PathVariable final UUID orderTableId, - @RequestBody final OrderTable request + @PathVariable final UUID orderTableId, + @RequestBody final OrderTable request ) { return ResponseEntity.ok(orderTableService.changeNumberOfGuests(orderTableId, request)); } diff --git a/src/main/java/kitchenpos/menus/application/MenuGroupService.java b/src/main/java/kitchenpos/menus/application/MenuGroupService.java index c468893a2..bd5e701e2 100644 --- a/src/main/java/kitchenpos/menus/application/MenuGroupService.java +++ b/src/main/java/kitchenpos/menus/application/MenuGroupService.java @@ -1,12 +1,12 @@ package kitchenpos.menus.application; -import kitchenpos.menus.domain.MenuGroup; import kitchenpos.menus.domain.MenuGroupRepository; +import kitchenpos.menus.tobe.domain.MenuGroup; +import kitchenpos.menus.ui.dto.MenuGroupRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; -import java.util.Objects; import java.util.UUID; @Service @@ -18,14 +18,9 @@ public MenuGroupService(final MenuGroupRepository menuGroupRepository) { } @Transactional - public MenuGroup create(final MenuGroup request) { - final String name = request.getName(); - if (Objects.isNull(name) || name.isEmpty()) { - throw new IllegalArgumentException(); - } - final MenuGroup menuGroup = new MenuGroup(); - menuGroup.setId(UUID.randomUUID()); - menuGroup.setName(name); + public MenuGroup create(final MenuGroupRequest request) { + final MenuGroup menuGroup = new MenuGroup(UUID.randomUUID(), request.getName()); + return menuGroupRepository.save(menuGroup); } diff --git a/src/main/java/kitchenpos/menus/application/MenuService.java b/src/main/java/kitchenpos/menus/application/MenuService.java index 21ce75a57..6cd57250c 100644 --- a/src/main/java/kitchenpos/menus/application/MenuService.java +++ b/src/main/java/kitchenpos/menus/application/MenuService.java @@ -1,14 +1,23 @@ package kitchenpos.menus.application; -import kitchenpos.menus.domain.*; +import kitchenpos.common.domain.Price; +import kitchenpos.menus.domain.MenuGroupRepository; +import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.menus.tobe.domain.Menu; +import kitchenpos.menus.tobe.domain.MenuGroup; +import kitchenpos.menus.tobe.domain.MenuProductDto; +import kitchenpos.menus.tobe.domain.MenuProducts; +import kitchenpos.menus.ui.dto.MenuProductRequests; +import kitchenpos.menus.ui.dto.MenuRequest; import kitchenpos.products.domain.ProductRepository; import kitchenpos.products.infra.PurgomalumClient; import kitchenpos.products.tobe.domain.Product; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.math.BigDecimal; -import java.util.*; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; import java.util.stream.Collectors; @Service @@ -31,77 +40,36 @@ public MenuService( } @Transactional - public Menu create(final Menu request) { - final BigDecimal price = request.getPrice(); - if (Objects.isNull(price) || price.compareTo(BigDecimal.ZERO) < 0) { - throw new IllegalArgumentException(); - } + public Menu create(final MenuRequest request) { + Price price = new Price(request.getPrice()); + final MenuGroup menuGroup = menuGroupRepository.findById(request.getMenuGroupId()) .orElseThrow(NoSuchElementException::new); - final List menuProductRequests = request.getMenuProducts(); - if (Objects.isNull(menuProductRequests) || menuProductRequests.isEmpty()) { - throw new IllegalArgumentException(); - } + MenuProductRequests menuProductRequests = new MenuProductRequests(request.getMenuProducts()); + final List products = productRepository.findAllByIdIn( - menuProductRequests.stream() - .map(MenuProduct::getProductId) + menuProductRequests.getMenuProductRequests() + .stream() + .map(MenuProductDto::getProductId) .collect(Collectors.toList()) ); - if (products.size() != menuProductRequests.size()) { - throw new IllegalArgumentException(); - } - final List menuProducts = new ArrayList<>(); - BigDecimal sum = BigDecimal.ZERO; - for (final MenuProduct menuProductRequest : menuProductRequests) { - final long quantity = menuProductRequest.getQuantity(); - if (quantity < 0) { - throw new IllegalArgumentException(); - } - final Product product = productRepository.findById(menuProductRequest.getProductId()) - .orElseThrow(NoSuchElementException::new); - sum = sum.add( - product.getPrice() - .multiply(BigDecimal.valueOf(quantity)) - ); - final MenuProduct menuProduct = new MenuProduct(); - menuProduct.setProduct(product); - menuProduct.setQuantity(quantity); - menuProducts.add(menuProduct); - } - if (price.compareTo(sum) > 0) { - throw new IllegalArgumentException(); - } - final String name = request.getName(); - if (Objects.isNull(name) || purgomalumClient.containsProfanity(name)) { - throw new IllegalArgumentException(); - } - final Menu menu = new Menu(); - menu.setId(UUID.randomUUID()); - menu.setName(name); - menu.setPrice(price); - menu.setMenuGroup(menuGroup); - menu.setDisplayed(request.isDisplayed()); - menu.setMenuProducts(menuProducts); + MenuProducts menuProducts = new MenuProducts(menuProductRequests.getMenuProductRequests(), products, price); + + final Menu menu = new Menu(purgomalumClient, UUID.randomUUID(), request.getName(), price, menuGroup.getId(), request.isDisplayed(), menuProducts); + return menuRepository.save(menu); } @Transactional - public Menu changePrice(final UUID menuId, final Menu request) { - final BigDecimal price = request.getPrice(); - if (Objects.isNull(price) || price.compareTo(BigDecimal.ZERO) < 0) { - throw new IllegalArgumentException(); - } + public Menu changePrice(final UUID menuId, final MenuRequest request) { + Price price = new Price(request.getPrice()); + final Menu menu = menuRepository.findById(menuId) .orElseThrow(NoSuchElementException::new); - for (final MenuProduct menuProduct : menu.getMenuProducts()) { - final BigDecimal sum = menuProduct.getProduct() - .getPrice() - .multiply(BigDecimal.valueOf(menuProduct.getQuantity())); - if (price.compareTo(sum) > 0) { - throw new IllegalArgumentException(); - } - } - menu.setPrice(price); + + List findProducts = productRepository.findAllByIdIn(menu.getProductIds()); + + menu.changePrice(price, findProducts); return menu; } @@ -109,15 +77,10 @@ public Menu changePrice(final UUID menuId, final Menu request) { public Menu display(final UUID menuId) { final Menu menu = menuRepository.findById(menuId) .orElseThrow(NoSuchElementException::new); - for (final MenuProduct menuProduct : menu.getMenuProducts()) { - final BigDecimal sum = menuProduct.getProduct() - .getPrice() - .multiply(BigDecimal.valueOf(menuProduct.getQuantity())); - if (menu.getPrice().compareTo(sum) > 0) { - throw new IllegalStateException(); - } - } - menu.setDisplayed(true); + + List findProducts = productRepository.findAllByIdIn(menu.getProductIds()); + + menu.show(findProducts); return menu; } @@ -125,7 +88,7 @@ public Menu display(final UUID menuId) { public Menu hide(final UUID menuId) { final Menu menu = menuRepository.findById(menuId) .orElseThrow(NoSuchElementException::new); - menu.setDisplayed(false); + menu.hide(); return menu; } diff --git a/src/main/java/kitchenpos/menus/domain/JpaMenuGroupRepository.java b/src/main/java/kitchenpos/menus/domain/JpaMenuGroupRepository.java index 233488198..7df7e842f 100644 --- a/src/main/java/kitchenpos/menus/domain/JpaMenuGroupRepository.java +++ b/src/main/java/kitchenpos/menus/domain/JpaMenuGroupRepository.java @@ -1,5 +1,6 @@ package kitchenpos.menus.domain; +import kitchenpos.menus.tobe.domain.MenuGroup; import org.springframework.data.jpa.repository.JpaRepository; import java.util.UUID; diff --git a/src/main/java/kitchenpos/menus/domain/JpaMenuRepository.java b/src/main/java/kitchenpos/menus/domain/JpaMenuRepository.java index 423df175a..f3beb2a56 100644 --- a/src/main/java/kitchenpos/menus/domain/JpaMenuRepository.java +++ b/src/main/java/kitchenpos/menus/domain/JpaMenuRepository.java @@ -1,5 +1,6 @@ package kitchenpos.menus.domain; +import kitchenpos.menus.tobe.domain.Menu; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -8,7 +9,7 @@ import java.util.UUID; public interface JpaMenuRepository extends MenuRepository, JpaRepository { - @Query("select m from Menu m, MenuProduct mp where mp.product.id = :productId") + @Query("select m from Menu m, MenuProduct mp where mp.productId = :productId") @Override List findAllByProductId(@Param("productId") UUID productId); } diff --git a/src/main/java/kitchenpos/menus/domain/Menu.java b/src/main/java/kitchenpos/menus/domain/Menu.java deleted file mode 100644 index 5e78ee1a2..000000000 --- a/src/main/java/kitchenpos/menus/domain/Menu.java +++ /dev/null @@ -1,102 +0,0 @@ -package kitchenpos.menus.domain; - -import javax.persistence.*; -import java.math.BigDecimal; -import java.util.List; -import java.util.UUID; - -@Table(name = "menu") -@Entity -public class Menu { - @Column(name = "id", columnDefinition = "varbinary(16)") - @Id - private UUID id; - - @Column(name = "name", nullable = false) - private String name; - - @Column(name = "price", nullable = false) - private BigDecimal price; - - @ManyToOne(optional = false) - @JoinColumn( - name = "menu_group_id", - columnDefinition = "varbinary(16)", - foreignKey = @ForeignKey(name = "fk_menu_to_menu_group") - ) - private MenuGroup menuGroup; - - @Column(name = "displayed", nullable = false) - private boolean displayed; - - @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) - @JoinColumn( - name = "menu_id", - nullable = false, - columnDefinition = "varbinary(16)", - foreignKey = @ForeignKey(name = "fk_menu_product_to_menu") - ) - private List menuProducts; - - @Transient - private UUID menuGroupId; - - public Menu() { - } - - public UUID getId() { - return id; - } - - public void setId(final UUID id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - public BigDecimal getPrice() { - return price; - } - - public void setPrice(final BigDecimal price) { - this.price = price; - } - - public MenuGroup getMenuGroup() { - return menuGroup; - } - - public void setMenuGroup(final MenuGroup menuGroup) { - this.menuGroup = menuGroup; - } - - public boolean isDisplayed() { - return displayed; - } - - public void setDisplayed(final boolean displayed) { - this.displayed = displayed; - } - - public List getMenuProducts() { - return menuProducts; - } - - public void setMenuProducts(final List menuProducts) { - this.menuProducts = menuProducts; - } - - public UUID getMenuGroupId() { - return menuGroupId; - } - - public void setMenuGroupId(final UUID menuGroupId) { - this.menuGroupId = menuGroupId; - } -} diff --git a/src/main/java/kitchenpos/menus/domain/MenuGroup.java b/src/main/java/kitchenpos/menus/domain/MenuGroup.java deleted file mode 100644 index 9509c23ff..000000000 --- a/src/main/java/kitchenpos/menus/domain/MenuGroup.java +++ /dev/null @@ -1,37 +0,0 @@ -package kitchenpos.menus.domain; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; -import java.util.UUID; - -@Table(name = "menu_group") -@Entity -public class MenuGroup { - @Column(name = "id", columnDefinition = "varbinary(16)") - @Id - private UUID id; - - @Column(name = "name", nullable = false) - private String name; - - public MenuGroup() { - } - - public UUID getId() { - return id; - } - - public void setId(final UUID id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } -} diff --git a/src/main/java/kitchenpos/menus/domain/MenuGroupRepository.java b/src/main/java/kitchenpos/menus/domain/MenuGroupRepository.java index b25e6acbc..39d2ed364 100644 --- a/src/main/java/kitchenpos/menus/domain/MenuGroupRepository.java +++ b/src/main/java/kitchenpos/menus/domain/MenuGroupRepository.java @@ -1,5 +1,7 @@ package kitchenpos.menus.domain; +import kitchenpos.menus.tobe.domain.MenuGroup; + import java.util.List; import java.util.Optional; import java.util.UUID; diff --git a/src/main/java/kitchenpos/menus/domain/MenuRepository.java b/src/main/java/kitchenpos/menus/domain/MenuRepository.java index 5fbaab864..ea4437b76 100644 --- a/src/main/java/kitchenpos/menus/domain/MenuRepository.java +++ b/src/main/java/kitchenpos/menus/domain/MenuRepository.java @@ -1,5 +1,7 @@ package kitchenpos.menus.domain; +import kitchenpos.menus.tobe.domain.Menu; + import java.util.List; import java.util.Optional; import java.util.UUID; diff --git a/src/main/java/kitchenpos/menus/tobe/domain/Menu.java b/src/main/java/kitchenpos/menus/tobe/domain/Menu.java new file mode 100644 index 000000000..46741d4d1 --- /dev/null +++ b/src/main/java/kitchenpos/menus/tobe/domain/Menu.java @@ -0,0 +1,103 @@ +package kitchenpos.menus.tobe.domain; + +import kitchenpos.common.domain.Price; +import kitchenpos.products.infra.PurgomalumClient; +import kitchenpos.products.tobe.domain.Product; + +import javax.persistence.*; +import java.math.BigDecimal; +import java.util.List; +import java.util.UUID; + +@Table(name = "menu") +@Entity +public class Menu { + + @Column(name = "id", columnDefinition = "varbinary(16)") + @Id + private UUID id; + + @Embedded + private MenuName name; + + @Embedded + private Price price; + + @Column(name = "menu_group_id", columnDefinition = "varbinary(16)", nullable = false) + private UUID menuGroupId; + + @Column(name = "displayed", nullable = false) + private boolean displayed; + + @Embedded + private MenuProducts menuProducts; + + protected Menu() { + } + + public Menu(PurgomalumClient purgomalumClient, UUID id, String name, Price price, UUID menuGroupId, boolean displayed, MenuProducts menuProducts) { + this.id = id; + this.name = new MenuName(purgomalumClient, name); + this.price = price; + this.menuGroupId = menuGroupId; + this.displayed = displayed; + this.menuProducts = menuProducts; + } + + public Menu(PurgomalumClient purgomalumClient, UUID id, String name, BigDecimal price, UUID menuGroupId, boolean displayed, MenuProducts menuProducts) { + this(purgomalumClient, id, name, new Price(price), menuGroupId, displayed, menuProducts); + } + + public Menu(PurgomalumClient purgomalumClient, String name, BigDecimal price, UUID menuGroupId, boolean displayed, MenuProducts menuProducts) { + this(purgomalumClient, null, name, price, menuGroupId, displayed, menuProducts); + + } + + public UUID getId() { + return id; + } + + public String getName() { + return name.getName(); + } + + public BigDecimal getPrice() { + return price.getPrice(); + } + + public boolean isDisplayed() { + return displayed; + } + + public List getMenuProducts() { + return menuProducts.getMenuProducts(); + } + + public UUID getMenuGroupId() { + return menuGroupId; + } + + public void changePrice(Price price, List findProducts) { + if (menuProducts.isExpensiveMenuPrice(price, findProducts)) { + throw new IllegalArgumentException("메뉴의 가격은 상품가격의 총합보다 작거나 같아야합니다."); + } + + this.price = price; + } + + public void show(List findProducts) { + if (menuProducts.isExpensiveMenuPrice(price, findProducts)) { + throw new IllegalStateException("메뉴의 가격이 상품의 가격보다 비쌀경우 메뉴를 노출할수 없습니다."); + } + + this.displayed = true; + } + + public void hide() { + this.displayed = false; + } + + public List getProductIds() { + return menuProducts.getProductIds(); + } +} diff --git a/src/main/java/kitchenpos/menus/tobe/domain/MenuGroup.java b/src/main/java/kitchenpos/menus/tobe/domain/MenuGroup.java new file mode 100644 index 000000000..b8be88396 --- /dev/null +++ b/src/main/java/kitchenpos/menus/tobe/domain/MenuGroup.java @@ -0,0 +1,37 @@ +package kitchenpos.menus.tobe.domain; + +import javax.persistence.*; +import java.util.UUID; + +@Table(name = "menu_group") +@Entity +public class MenuGroup { + + @Column(name = "id", columnDefinition = "varbinary(16)") + @Id + private UUID id; + + @Embedded + private MenuGroupName name; + + protected MenuGroup() { + } + + public MenuGroup(String name) { + this.name = new MenuGroupName(name); + } + + public MenuGroup(UUID id, String name) { + this.id = id; + this.name = new MenuGroupName(name); + } + + public UUID getId() { + return id; + } + + public String getName() { + return name.getName(); + } + +} diff --git a/src/main/java/kitchenpos/menus/tobe/domain/MenuGroupName.java b/src/main/java/kitchenpos/menus/tobe/domain/MenuGroupName.java new file mode 100644 index 000000000..659c3c4a8 --- /dev/null +++ b/src/main/java/kitchenpos/menus/tobe/domain/MenuGroupName.java @@ -0,0 +1,34 @@ +package kitchenpos.menus.tobe.domain; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.util.Objects; + +@Embeddable +public class MenuGroupName { + + @Column(name = "name", nullable = false) + private String name; + + protected MenuGroupName() { + } + + protected MenuGroupName(String name) { + validation(name); + this.name = name; + } + + private void validation(String name) { + if (Objects.isNull(name)) { + throw new IllegalArgumentException("메뉴그룹이름은 필수입니다."); + } + + if (name.isEmpty()) { + throw new IllegalArgumentException("메뉴 그룹의 이름은 공백이 될수 없습니다."); + } + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/kitchenpos/menus/tobe/domain/MenuName.java b/src/main/java/kitchenpos/menus/tobe/domain/MenuName.java new file mode 100644 index 000000000..57f81b249 --- /dev/null +++ b/src/main/java/kitchenpos/menus/tobe/domain/MenuName.java @@ -0,0 +1,34 @@ +package kitchenpos.menus.tobe.domain; + +import kitchenpos.products.infra.PurgomalumClient; + +import javax.persistence.Embeddable; +import java.util.Objects; + +@Embeddable +public class MenuName { + + private String name; + + protected MenuName() { + } + + protected MenuName(PurgomalumClient purgomalumClient, String name) { + validation(purgomalumClient, name); + this.name = name; + } + + private void validation(PurgomalumClient purgomalumClient, String name) { + if (Objects.isNull(name)) { + throw new IllegalArgumentException("메뉴이름은 필수입니다."); + } + + if (purgomalumClient.containsProfanity(name)) { + throw new IllegalArgumentException("메뉴이름은 비속어를 사용할수 없습니다."); + } + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/kitchenpos/menus/domain/MenuProduct.java b/src/main/java/kitchenpos/menus/tobe/domain/MenuProduct.java similarity index 51% rename from src/main/java/kitchenpos/menus/domain/MenuProduct.java rename to src/main/java/kitchenpos/menus/tobe/domain/MenuProduct.java index 55377a421..3ac3b5c52 100644 --- a/src/main/java/kitchenpos/menus/domain/MenuProduct.java +++ b/src/main/java/kitchenpos/menus/tobe/domain/MenuProduct.java @@ -1,6 +1,4 @@ -package kitchenpos.menus.domain; - -import kitchenpos.products.tobe.domain.Product; +package kitchenpos.menus.tobe.domain; import javax.persistence.*; import java.util.UUID; @@ -8,57 +6,42 @@ @Table(name = "menu_product") @Entity public class MenuProduct { + @Column(name = "seq") @GeneratedValue(strategy = GenerationType.IDENTITY) @Id private Long seq; - @ManyToOne(optional = false) - @JoinColumn( - name = "product_id", - columnDefinition = "varbinary(16)", - foreignKey = @ForeignKey(name = "fk_menu_product_to_product") - ) - private Product product; + @Column(name = "product_id", columnDefinition = "varbinary(16)", nullable = false) + private UUID productId; @Column(name = "quantity", nullable = false) private long quantity; - @Transient - private UUID productId; - public MenuProduct() { } - public Long getSeq() { - return seq; + public MenuProduct(UUID productId, long quantity) { + this.productId = productId; + this.quantity = quantity; } - public void setSeq(final Long seq) { + public MenuProduct(Long seq, UUID productId, long quantity) { this.seq = seq; + this.productId = productId; + this.quantity = quantity; } - public Product getProduct() { - return product; - } - - public void setProduct(final Product product) { - this.product = product; + public Long getSeq() { + return seq; } public long getQuantity() { return quantity; } - public void setQuantity(final long quantity) { - this.quantity = quantity; - } - public UUID getProductId() { return productId; } - public void setProductId(final UUID productId) { - this.productId = productId; - } } diff --git a/src/main/java/kitchenpos/menus/tobe/domain/MenuProductDto.java b/src/main/java/kitchenpos/menus/tobe/domain/MenuProductDto.java new file mode 100644 index 000000000..db565fdac --- /dev/null +++ b/src/main/java/kitchenpos/menus/tobe/domain/MenuProductDto.java @@ -0,0 +1,23 @@ +package kitchenpos.menus.tobe.domain; + +import java.util.UUID; + +public class MenuProductDto { + + private UUID productId; + + private long quantity; + + public MenuProductDto(UUID productId, long quantity) { + this.productId = productId; + this.quantity = quantity; + } + + public UUID getProductId() { + return productId; + } + + public long getQuantity() { + return quantity; + } +} diff --git a/src/main/java/kitchenpos/menus/tobe/domain/MenuProducts.java b/src/main/java/kitchenpos/menus/tobe/domain/MenuProducts.java new file mode 100644 index 000000000..b89866ab4 --- /dev/null +++ b/src/main/java/kitchenpos/menus/tobe/domain/MenuProducts.java @@ -0,0 +1,105 @@ +package kitchenpos.menus.tobe.domain; + +import kitchenpos.common.domain.Price; +import kitchenpos.products.tobe.domain.Product; + +import javax.persistence.Embeddable; +import javax.persistence.ForeignKey; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import javax.persistence.CascadeType; +import java.math.BigDecimal; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import java.util.stream.Collectors; + +@Embeddable +public class MenuProducts { + + @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) + @JoinColumn( + name = "menu_id", + nullable = false, + columnDefinition = "varbinary(16)", + foreignKey = @ForeignKey(name = "fk_menu_product_to_menu") + ) + private List menuProducts; + + protected MenuProducts() { + } + + public MenuProducts(List menuProducts) { + this.menuProducts = menuProducts; + } + + public MenuProducts(List menuProductDtos, List products, Price menuPrice) { + validation(menuProductDtos, products, menuPrice); + + this.menuProducts = menuProductDtos.stream() + .map(menuProductRequest -> new MenuProduct(menuProductRequest.getProductId(), menuProductRequest.getQuantity())) + .collect(Collectors.toList()); + } + + private void validation(List menuProductDtos, List products, Price menuPrice) { + if (products.size() != menuProductDtos.size()) { + throw new IllegalArgumentException("메뉴에 등록하려고 하는 상품이 존재하지 않습니다."); + } + + if (menuPrice.compareTo(getMenuProductsTotalPrice(menuProductDtos, products)) > 0) { + throw new IllegalArgumentException("메뉴의 가격은 상품의 총합보다 작거나 같아야합니다."); + } + } + + private Price getMenuProductsTotalPrice(List menuProductDtos, List products) { + Price totalPrice = menuProductDtos.stream() + .map(menuProductDto -> new Price(getProductTotalPrice(products, menuProductDto)) + ).reduce(new Price(BigDecimal.ZERO), Price::add); + return totalPrice; + } + + private BigDecimal getProductTotalPrice(List products, MenuProductDto menuProductDtos) { + return getProductPrice(products, menuProductDtos) + .multiply(BigDecimal.valueOf(menuProductDtos.getQuantity())); + } + + private BigDecimal getProductPrice(List products, MenuProductDto menuProductDtos) { + return products.stream() + .filter(product -> product.isSameProductId(menuProductDtos.getProductId())) + .findFirst() + .orElseThrow(() -> new NoSuchElementException("상품이 존재하지 않습니다.")) + .getPrice(); + } + + public List getMenuProducts() { + return menuProducts; + } + + public List getProductIds() { + return menuProducts.stream() + .map(menuProduct -> menuProduct.getProductId()) + .collect(Collectors.toList()); + } + + public int size() { + return menuProducts.size(); + } + + public boolean isExpensiveMenuPrice(Price price, List findProducts) { + for (final MenuProduct menuProduct : menuProducts) { + BigDecimal productPrice = getMatchedProduct(findProducts, menuProduct).getPrice(); + final Price sum = new Price(productPrice.multiply(BigDecimal.valueOf(menuProduct.getQuantity()))); + if (price.compareTo(sum) > 0) { + return true; + } + } + return false; + } + + private Product getMatchedProduct(List findProducts, MenuProduct menuProduct) { + return findProducts.stream() + .filter(product -> product.isSameProductId(menuProduct.getProductId())) + .findAny() + .orElseThrow(NoSuchElementException::new); + } +} diff --git a/src/main/java/kitchenpos/menus/ui/MenuGroupRestController.java b/src/main/java/kitchenpos/menus/ui/MenuGroupRestController.java index 1a5d0fd06..7e5d16959 100644 --- a/src/main/java/kitchenpos/menus/ui/MenuGroupRestController.java +++ b/src/main/java/kitchenpos/menus/ui/MenuGroupRestController.java @@ -1,7 +1,8 @@ package kitchenpos.menus.ui; import kitchenpos.menus.application.MenuGroupService; -import kitchenpos.menus.domain.MenuGroup; +import kitchenpos.menus.tobe.domain.MenuGroup; +import kitchenpos.menus.ui.dto.MenuGroupRequest; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -18,10 +19,10 @@ public MenuGroupRestController(final MenuGroupService menuGroupService) { } @PostMapping - public ResponseEntity create(@RequestBody final MenuGroup request) { + public ResponseEntity create(@RequestBody final MenuGroupRequest request) { final MenuGroup response = menuGroupService.create(request); return ResponseEntity.created(URI.create("/api/menu-groups/" + response.getId())) - .body(response); + .body(response); } @GetMapping diff --git a/src/main/java/kitchenpos/menus/ui/MenuRestController.java b/src/main/java/kitchenpos/menus/ui/MenuRestController.java index 3e3a0e23a..b939c067c 100644 --- a/src/main/java/kitchenpos/menus/ui/MenuRestController.java +++ b/src/main/java/kitchenpos/menus/ui/MenuRestController.java @@ -1,7 +1,8 @@ package kitchenpos.menus.ui; import kitchenpos.menus.application.MenuService; -import kitchenpos.menus.domain.Menu; +import kitchenpos.menus.tobe.domain.Menu; +import kitchenpos.menus.ui.dto.MenuRequest; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -19,14 +20,14 @@ public MenuRestController(final MenuService menuService) { } @PostMapping - public ResponseEntity create(@RequestBody final Menu request) { + public ResponseEntity create(@RequestBody final MenuRequest request) { final Menu response = menuService.create(request); return ResponseEntity.created(URI.create("/api/menus/" + response.getId())) - .body(response); + .body(response); } @PutMapping("/{menuId}/price") - public ResponseEntity changePrice(@PathVariable final UUID menuId, @RequestBody final Menu request) { + public ResponseEntity changePrice(@PathVariable final UUID menuId, @RequestBody final MenuRequest request) { return ResponseEntity.ok(menuService.changePrice(menuId, request)); } diff --git a/src/main/java/kitchenpos/menus/ui/dto/MenuGroupRequest.java b/src/main/java/kitchenpos/menus/ui/dto/MenuGroupRequest.java new file mode 100644 index 000000000..278eb4d20 --- /dev/null +++ b/src/main/java/kitchenpos/menus/ui/dto/MenuGroupRequest.java @@ -0,0 +1,13 @@ +package kitchenpos.menus.ui.dto; + +public class MenuGroupRequest { + private String name; + + public MenuGroupRequest(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/kitchenpos/menus/ui/dto/MenuProductRequest.java b/src/main/java/kitchenpos/menus/ui/dto/MenuProductRequest.java new file mode 100644 index 000000000..6f5a88a0f --- /dev/null +++ b/src/main/java/kitchenpos/menus/ui/dto/MenuProductRequest.java @@ -0,0 +1,35 @@ +package kitchenpos.menus.ui.dto; + +import java.util.UUID; + +public class MenuProductRequest { + + private Long seq; + + private UUID productId; + + private long quantity; + + public MenuProductRequest(UUID productId, long quantity) { + this.productId = productId; + this.quantity = quantity; + } + + public MenuProductRequest(Long seq, UUID productId, long quantity) { + this.seq = seq; + this.productId = productId; + this.quantity = quantity; + } + + public Long getSeq() { + return seq; + } + + public UUID getProductId() { + return productId; + } + + public long getQuantity() { + return quantity; + } +} diff --git a/src/main/java/kitchenpos/menus/ui/dto/MenuProductRequests.java b/src/main/java/kitchenpos/menus/ui/dto/MenuProductRequests.java new file mode 100644 index 000000000..9459b7d59 --- /dev/null +++ b/src/main/java/kitchenpos/menus/ui/dto/MenuProductRequests.java @@ -0,0 +1,30 @@ +package kitchenpos.menus.ui.dto; + +import kitchenpos.menus.tobe.domain.MenuProductDto; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class MenuProductRequests { + + List menuProductRequests; + + public MenuProductRequests(List menuProductRequests) { + if (Objects.isNull(menuProductRequests) || menuProductRequests.isEmpty()) { + throw new IllegalArgumentException("메뉴에 등록할 상품은 필수입니다."); + } + + this.menuProductRequests = menuProductRequests; + } + + public List getMenuProductRequests() { + return menuProductRequests.stream() + .map(menuProductRequest -> new MenuProductDto(menuProductRequest.getProductId(), menuProductRequest.getQuantity())) + .collect(Collectors.toList()); + } + + public int size() { + return menuProductRequests.size(); + } +} diff --git a/src/main/java/kitchenpos/menus/ui/dto/MenuRequest.java b/src/main/java/kitchenpos/menus/ui/dto/MenuRequest.java new file mode 100644 index 000000000..154861c6b --- /dev/null +++ b/src/main/java/kitchenpos/menus/ui/dto/MenuRequest.java @@ -0,0 +1,50 @@ +package kitchenpos.menus.ui.dto; + +import java.math.BigDecimal; +import java.util.List; +import java.util.UUID; + +public class MenuRequest { + + private String name; + + private BigDecimal price; + + private UUID menuGroupId; + + private boolean displayed; + + private List menuProducts; + + public MenuRequest(BigDecimal price) { + this.price = price; + } + + public MenuRequest(String name, BigDecimal price, UUID menuGroupId, boolean displayed, List menuProducts) { + this.name = name; + this.price = price; + this.menuGroupId = menuGroupId; + this.displayed = displayed; + this.menuProducts = menuProducts; + } + + public String getName() { + return name; + } + + public BigDecimal getPrice() { + return price; + } + + public UUID getMenuGroupId() { + return menuGroupId; + } + + public boolean isDisplayed() { + return displayed; + } + + public List getMenuProducts() { + return menuProducts; + } +} diff --git a/src/main/java/kitchenpos/products/application/ProductService.java b/src/main/java/kitchenpos/products/application/ProductService.java index 8ac8d570f..e6f390386 100644 --- a/src/main/java/kitchenpos/products/application/ProductService.java +++ b/src/main/java/kitchenpos/products/application/ProductService.java @@ -1,8 +1,8 @@ package kitchenpos.products.application; -import kitchenpos.menus.domain.Menu; -import kitchenpos.menus.domain.MenuProduct; import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.menus.tobe.domain.Menu; +import kitchenpos.menus.tobe.domain.MenuProduct; import kitchenpos.products.domain.ProductRepository; import kitchenpos.products.infra.PurgomalumClient; import kitchenpos.products.tobe.domain.Product; @@ -51,12 +51,12 @@ public ProductResponse changePrice(final UUID productId, final ProductRequest re for (final Menu menu : menus) { BigDecimal sum = BigDecimal.ZERO; for (final MenuProduct menuProduct : menu.getMenuProducts()) { - sum = menuProduct.getProduct() + sum = product .getPrice() .multiply(BigDecimal.valueOf(menuProduct.getQuantity())); } if (menu.getPrice().compareTo(sum) > 0) { - menu.setDisplayed(false); + menu.hide(); } } return new ProductResponse(product); diff --git a/src/main/java/kitchenpos/products/tobe/domain/Product.java b/src/main/java/kitchenpos/products/tobe/domain/Product.java index 956315d30..00cea7356 100644 --- a/src/main/java/kitchenpos/products/tobe/domain/Product.java +++ b/src/main/java/kitchenpos/products/tobe/domain/Product.java @@ -1,5 +1,6 @@ package kitchenpos.products.tobe.domain; +import kitchenpos.common.domain.Price; import kitchenpos.products.infra.PurgomalumClient; import javax.persistence.*; @@ -17,7 +18,7 @@ public class Product { private ProductName name; @Embedded - private ProductPrice price; + private Price price; protected Product() { } @@ -25,7 +26,7 @@ protected Product() { public Product(PurgomalumClient purgomalumClient, String name, BigDecimal price) { this.id = UUID.randomUUID(); this.name = new ProductName(purgomalumClient, name); - this.price = new ProductPrice(price); + this.price = new Price(price); } public UUID getId() { @@ -41,6 +42,10 @@ public BigDecimal getPrice() { } public void changePrice(BigDecimal price) { - this.price = new ProductPrice(price); + this.price = new Price(price); + } + + public boolean isSameProductId(UUID productId) { + return id.equals(productId); } } diff --git a/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java b/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java deleted file mode 100644 index b0b1552fd..000000000 --- a/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java +++ /dev/null @@ -1,36 +0,0 @@ -package kitchenpos.products.tobe.domain; - -import javax.persistence.Column; -import javax.persistence.Embeddable; -import java.math.BigDecimal; -import java.util.Objects; - -@Embeddable -public class ProductPrice { - - @Column(name = "price", nullable = false) - private BigDecimal price; - - protected ProductPrice() { - } - - protected ProductPrice(BigDecimal price) { - validation(price); - - this.price = price; - } - - private void validation(BigDecimal price) { - if (Objects.isNull(price)) { - throw new IllegalArgumentException("상품 가격은 필수 입니다"); - } - - if (price.compareTo(BigDecimal.ZERO) < 0) { - throw new IllegalArgumentException("가격은 음수가 될수 없습니다."); - } - } - - public BigDecimal getPrice() { - return price; - } -} diff --git a/src/test/java/kitchenpos/Fixtures.java b/src/test/java/kitchenpos/Fixtures.java index 38b406808..989f791f2 100644 --- a/src/test/java/kitchenpos/Fixtures.java +++ b/src/test/java/kitchenpos/Fixtures.java @@ -1,9 +1,7 @@ package kitchenpos; import kitchenpos.eatinorders.domain.*; -import kitchenpos.menus.domain.Menu; -import kitchenpos.menus.domain.MenuGroup; -import kitchenpos.menus.domain.MenuProduct; +import kitchenpos.menus.tobe.domain.*; import kitchenpos.products.application.FakePurgomalumClient; import kitchenpos.products.tobe.domain.Product; @@ -25,13 +23,7 @@ public static Menu menu(final long price, final MenuProduct... menuProducts) { } public static Menu menu(final long price, final boolean displayed, final MenuProduct... menuProducts) { - final Menu menu = new Menu(); - menu.setId(UUID.randomUUID()); - menu.setName("후라이드+후라이드"); - menu.setPrice(BigDecimal.valueOf(price)); - menu.setMenuGroup(menuGroup()); - menu.setDisplayed(displayed); - menu.setMenuProducts(Arrays.asList(menuProducts)); + final Menu menu = new Menu(new FakePurgomalumClient(), UUID.randomUUID(), "후라이드+후라이드", BigDecimal.valueOf(price), menuGroup().getId(), displayed, new MenuProducts(Arrays.asList(menuProducts))); return menu; } @@ -40,25 +32,17 @@ public static MenuGroup menuGroup() { } public static MenuGroup menuGroup(final String name) { - final MenuGroup menuGroup = new MenuGroup(); - menuGroup.setId(UUID.randomUUID()); - menuGroup.setName(name); + final MenuGroup menuGroup = new MenuGroup(UUID.randomUUID(), name); return menuGroup; } public static MenuProduct menuProduct() { - final MenuProduct menuProduct = new MenuProduct(); - menuProduct.setSeq(new Random().nextLong()); - menuProduct.setProduct(product()); - menuProduct.setQuantity(2L); + final MenuProduct menuProduct = new MenuProduct(new Random().nextLong(), product().getId(), 2L); return menuProduct; } public static MenuProduct menuProduct(final Product product, final long quantity) { - final MenuProduct menuProduct = new MenuProduct(); - menuProduct.setSeq(new Random().nextLong()); - menuProduct.setProduct(product); - menuProduct.setQuantity(quantity); + final MenuProduct menuProduct = new MenuProduct(new Random().nextLong(), product.getId(), quantity); return menuProduct; } @@ -121,4 +105,12 @@ public static Product product() { public static Product product(final String name, final long price) { return new Product(new FakePurgomalumClient(), name, BigDecimal.valueOf(price)); } + + public static MenuProductDto menuProductDto() { + return menuProductDto(product().getId(), 1L); + } + + public static MenuProductDto menuProductDto(UUID productId, long quantity) { + return new MenuProductDto(productId, quantity); + } } diff --git a/src/test/java/kitchenpos/common/domain/PriceTest.java b/src/test/java/kitchenpos/common/domain/PriceTest.java new file mode 100644 index 000000000..a44e345a0 --- /dev/null +++ b/src/test/java/kitchenpos/common/domain/PriceTest.java @@ -0,0 +1,45 @@ +package kitchenpos.common.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.math.BigDecimal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +class PriceTest { + + @DisplayName("정상적으로 가격을 생성해보자") + @ParameterizedTest + @ValueSource(ints = {0, 1000, 5000, 10000}) + void createPrice(int inputPrice) { + Price price = new Price(BigDecimal.valueOf(inputPrice)); + + assertAll( + () -> assertThat(price).isNotNull(), + () -> assertThat(price.getPrice()).isEqualTo(BigDecimal.valueOf(inputPrice)) + ); + } + + @DisplayName("가격은 null이 될수 없다.") + @ParameterizedTest + @NullSource + void invalidPrice(BigDecimal price) { + assertThatThrownBy( + () -> new Price(price) + ).isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("가격은 음수가 될수 없다.") + @ParameterizedTest + @ValueSource(ints = {-100, -5000, -10000}) + void negativePrice(int price) { + assertThatThrownBy( + () -> new Price(BigDecimal.valueOf(price)) + ).isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/src/test/java/kitchenpos/menus/application/InMemoryMenuGroupRepository.java b/src/test/java/kitchenpos/menus/application/InMemoryMenuGroupRepository.java index 9b50d73bb..0cb98ae18 100644 --- a/src/test/java/kitchenpos/menus/application/InMemoryMenuGroupRepository.java +++ b/src/test/java/kitchenpos/menus/application/InMemoryMenuGroupRepository.java @@ -1,7 +1,7 @@ package kitchenpos.menus.application; -import kitchenpos.menus.domain.MenuGroup; import kitchenpos.menus.domain.MenuGroupRepository; +import kitchenpos.menus.tobe.domain.MenuGroup; import java.util.*; diff --git a/src/test/java/kitchenpos/menus/application/InMemoryMenuRepository.java b/src/test/java/kitchenpos/menus/application/InMemoryMenuRepository.java index 971ded7e3..6fd1d0f28 100644 --- a/src/test/java/kitchenpos/menus/application/InMemoryMenuRepository.java +++ b/src/test/java/kitchenpos/menus/application/InMemoryMenuRepository.java @@ -1,7 +1,7 @@ package kitchenpos.menus.application; -import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.menus.tobe.domain.Menu; import java.util.*; import java.util.stream.Collectors; @@ -28,16 +28,16 @@ public List findAll() { @Override public List findAllByIdIn(final List ids) { return menus.values() - .stream() - .filter(menu -> ids.contains(menu.getId())) - .collect(Collectors.toList()); + .stream() + .filter(menu -> ids.contains(menu.getId())) + .collect(Collectors.toList()); } @Override public List findAllByProductId(final UUID productId) { return menus.values() - .stream() - .filter(menu -> menu.getMenuProducts().stream().anyMatch(menuProduct -> menuProduct.getProduct().getId().equals(productId))) - .collect(Collectors.toList()); + .stream() + .filter(menu -> menu.getMenuProducts().stream().anyMatch(menuProduct -> menuProduct.getProductId().equals(productId))) + .collect(Collectors.toList()); } } diff --git a/src/test/java/kitchenpos/menus/application/MenuGroupServiceTest.java b/src/test/java/kitchenpos/menus/application/MenuGroupServiceTest.java index a5fbc71d1..a8061c305 100644 --- a/src/test/java/kitchenpos/menus/application/MenuGroupServiceTest.java +++ b/src/test/java/kitchenpos/menus/application/MenuGroupServiceTest.java @@ -1,7 +1,8 @@ package kitchenpos.menus.application; -import kitchenpos.menus.domain.MenuGroup; import kitchenpos.menus.domain.MenuGroupRepository; +import kitchenpos.menus.tobe.domain.MenuGroup; +import kitchenpos.menus.ui.dto.MenuGroupRequest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -28,12 +29,12 @@ void setUp() { @DisplayName("메뉴 그룹을 등록할 수 있다.") @Test void create() { - final MenuGroup expected = createMenuGroupRequest("두마리메뉴"); + final MenuGroupRequest expected = createMenuGroupRequest("두마리메뉴"); final MenuGroup actual = menuGroupService.create(expected); assertThat(actual).isNotNull(); assertAll( - () -> assertThat(actual.getId()).isNotNull(), - () -> assertThat(actual.getName()).isEqualTo(expected.getName()) + () -> assertThat(actual.getId()).isNotNull(), + () -> assertThat(actual.getName()).isEqualTo(expected.getName()) ); } @@ -41,9 +42,9 @@ void create() { @NullAndEmptySource @ParameterizedTest void create(final String name) { - final MenuGroup expected = createMenuGroupRequest(name); + final MenuGroupRequest expected = createMenuGroupRequest(name); assertThatThrownBy(() -> menuGroupService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @DisplayName("메뉴 그룹의 목록을 조회할 수 있다.") @@ -54,9 +55,8 @@ void findAll() { assertThat(actual).hasSize(1); } - private MenuGroup createMenuGroupRequest(final String name) { - final MenuGroup menuGroup = new MenuGroup(); - menuGroup.setName(name); + private MenuGroupRequest createMenuGroupRequest(final String name) { + final MenuGroupRequest menuGroup = new MenuGroupRequest(name); return menuGroup; } } diff --git a/src/test/java/kitchenpos/menus/application/MenuServiceTest.java b/src/test/java/kitchenpos/menus/application/MenuServiceTest.java index d8418bf7e..f21dcae0e 100644 --- a/src/test/java/kitchenpos/menus/application/MenuServiceTest.java +++ b/src/test/java/kitchenpos/menus/application/MenuServiceTest.java @@ -1,9 +1,10 @@ package kitchenpos.menus.application; -import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuGroupRepository; -import kitchenpos.menus.domain.MenuProduct; import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.menus.tobe.domain.Menu; +import kitchenpos.menus.ui.dto.MenuProductRequest; +import kitchenpos.menus.ui.dto.MenuRequest; import kitchenpos.products.application.FakePurgomalumClient; import kitchenpos.products.application.InMemoryProductRepository; import kitchenpos.products.tobe.domain.Product; @@ -26,7 +27,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; -class MenuServiceTest { +public class MenuServiceTest { private MenuRepository menuRepository; private MenuGroupRepository menuGroupRepository; private ProductRepository productRepository; @@ -49,46 +50,46 @@ void setUp() { @DisplayName("1개 이상의 등록된 상품으로 메뉴를 등록할 수 있다.") @Test void create() { - final Menu expected = createMenuRequest( - "후라이드+후라이드", 19_000L, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) + final MenuRequest expected = createMenuRequest( + "후라이드+후라이드", 19_000L, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) ); final Menu actual = menuService.create(expected); assertThat(actual).isNotNull(); assertAll( - () -> assertThat(actual.getId()).isNotNull(), - () -> assertThat(actual.getName()).isEqualTo(expected.getName()), - () -> assertThat(actual.getPrice()).isEqualTo(expected.getPrice()), - () -> assertThat(actual.getMenuGroup().getId()).isEqualTo(expected.getMenuGroupId()), - () -> assertThat(actual.isDisplayed()).isEqualTo(expected.isDisplayed()), - () -> assertThat(actual.getMenuProducts()).hasSize(1) + () -> assertThat(actual.getId()).isNotNull(), + () -> assertThat(actual.getName()).isEqualTo(expected.getName()), + () -> assertThat(actual.getPrice()).isEqualTo(expected.getPrice()), + () -> assertThat(actual.getMenuGroupId()).isEqualTo(expected.getMenuGroupId()), + () -> assertThat(actual.isDisplayed()).isEqualTo(expected.isDisplayed()), + () -> assertThat(actual.getMenuProducts()).hasSize(1) ); } @DisplayName("상품이 없으면 등록할 수 없다.") @MethodSource("menuProducts") @ParameterizedTest - void create(final List menuProducts) { - final Menu expected = createMenuRequest("후라이드+후라이드", 19_000L, menuGroupId, true, menuProducts); + void create(final List menuProducts) { + final MenuRequest expected = createMenuRequest("후라이드+후라이드", 19_000L, menuGroupId, true, menuProducts); assertThatThrownBy(() -> menuService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } private static List menuProducts() { return Arrays.asList( - null, - Arguments.of(Collections.emptyList()), - Arguments.of(Arrays.asList(createMenuProductRequest(INVALID_ID, 2L))) + null, + Arguments.of(Collections.emptyList()), + Arguments.of(Arrays.asList(createMenuProductRequest(INVALID_ID, 2L))) ); } @DisplayName("메뉴에 속한 상품의 수량은 0개 이상이어야 한다.") @Test void createNegativeQuantity() { - final Menu expected = createMenuRequest( - "후라이드+후라이드", 19_000L, menuGroupId, true, createMenuProductRequest(product.getId(), -1L) + final MenuRequest expected = createMenuRequest( + "후라이드+후라이드", 19_000L, menuGroupId, true, createMenuProductRequest(product.getId(), -1L) ); assertThatThrownBy(() -> menuService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @DisplayName("메뉴의 가격이 올바르지 않으면 등록할 수 없다.") @@ -96,32 +97,32 @@ void createNegativeQuantity() { @NullSource @ParameterizedTest void create(final BigDecimal price) { - final Menu expected = createMenuRequest( - "후라이드+후라이드", price, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) + final MenuRequest expected = createMenuRequest( + "후라이드+후라이드", price, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) ); assertThatThrownBy(() -> menuService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @DisplayName("메뉴에 속한 상품 금액의 합은 메뉴의 가격보다 크거나 같아야 한다.") @Test void createExpensiveMenu() { - final Menu expected = createMenuRequest( - "후라이드+후라이드", 33_000L, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) + final MenuRequest expected = createMenuRequest( + "후라이드+후라이드", 33_000L, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) ); assertThatThrownBy(() -> menuService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @DisplayName("메뉴는 특정 메뉴 그룹에 속해야 한다.") @NullSource @ParameterizedTest void create(final UUID menuGroupId) { - final Menu expected = createMenuRequest( - "후라이드+후라이드", 19_000L, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) + final MenuRequest expected = createMenuRequest( + "후라이드+후라이드", 19_000L, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) ); assertThatThrownBy(() -> menuService.create(expected)) - .isInstanceOf(NoSuchElementException.class); + .isInstanceOf(NoSuchElementException.class); } @DisplayName("메뉴의 이름이 올바르지 않으면 등록할 수 없다.") @@ -129,18 +130,18 @@ void create(final UUID menuGroupId) { @NullSource @ParameterizedTest void create(final String name) { - final Menu expected = createMenuRequest( - name, 19_000L, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) + final MenuRequest expected = createMenuRequest( + name, 19_000L, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) ); assertThatThrownBy(() -> menuService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @DisplayName("메뉴의 가격을 변경할 수 있다.") @Test void changePrice() { final UUID menuId = menuRepository.save(menu(19_000L, menuProduct(product, 2L))).getId(); - final Menu expected = changePriceRequest(16_000L); + final MenuRequest expected = changePriceRequest(16_000L); final Menu actual = menuService.changePrice(menuId, expected); assertThat(actual.getPrice()).isEqualTo(expected.getPrice()); } @@ -151,18 +152,18 @@ void changePrice() { @ParameterizedTest void changePrice(final BigDecimal price) { final UUID menuId = menuRepository.save(menu(19_000L, menuProduct(product, 2L))).getId(); - final Menu expected = changePriceRequest(price); + final MenuRequest expected = changePriceRequest(price); assertThatThrownBy(() -> menuService.changePrice(menuId, expected)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @DisplayName("메뉴에 속한 상품 금액의 합은 메뉴의 가격보다 크거나 같아야 한다.") @Test void changePriceToExpensive() { final UUID menuId = menuRepository.save(menu(19_000L, menuProduct(product, 2L))).getId(); - final Menu expected = changePriceRequest(33_000L); + final MenuRequest expected = changePriceRequest(33_000L); assertThatThrownBy(() -> menuService.changePrice(menuId, expected)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @DisplayName("메뉴를 노출할 수 있다.") @@ -178,7 +179,7 @@ void display() { void displayExpensiveMenu() { final UUID menuId = menuRepository.save(menu(33_000L, false, menuProduct(product, 2L))).getId(); assertThatThrownBy(() -> menuService.display(menuId)) - .isInstanceOf(IllegalStateException.class); + .isInstanceOf(IllegalStateException.class); } @DisplayName("메뉴를 숨길 수 있다.") @@ -197,66 +198,58 @@ void findAll() { assertThat(actual).hasSize(1); } - private Menu createMenuRequest( - final String name, - final long price, - final UUID menuGroupId, - final boolean displayed, - final MenuProduct... menuProducts + private MenuRequest createMenuRequest( + final String name, + final long price, + final UUID menuGroupId, + final boolean displayed, + final MenuProductRequest... menuProducts ) { return createMenuRequest(name, BigDecimal.valueOf(price), menuGroupId, displayed, menuProducts); } - private Menu createMenuRequest( - final String name, - final BigDecimal price, - final UUID menuGroupId, - final boolean displayed, - final MenuProduct... menuProducts + private MenuRequest createMenuRequest( + final String name, + final BigDecimal price, + final UUID menuGroupId, + final boolean displayed, + final MenuProductRequest... menuProducts ) { return createMenuRequest(name, price, menuGroupId, displayed, Arrays.asList(menuProducts)); } - private Menu createMenuRequest( - final String name, - final long price, - final UUID menuGroupId, - final boolean displayed, - final List menuProducts + private MenuRequest createMenuRequest( + final String name, + final long price, + final UUID menuGroupId, + final boolean displayed, + final List menuProducts ) { return createMenuRequest(name, BigDecimal.valueOf(price), menuGroupId, displayed, menuProducts); } - private Menu createMenuRequest( - final String name, - final BigDecimal price, - final UUID menuGroupId, - final boolean displayed, - final List menuProducts + private MenuRequest createMenuRequest( + final String name, + final BigDecimal price, + final UUID menuGroupId, + final boolean displayed, + final List menuProducts ) { - final Menu menu = new Menu(); - menu.setName(name); - menu.setPrice(price); - menu.setMenuGroupId(menuGroupId); - menu.setDisplayed(displayed); - menu.setMenuProducts(menuProducts); + final MenuRequest menu = new MenuRequest(name, price, menuGroupId, displayed, menuProducts); return menu; } - private static MenuProduct createMenuProductRequest(final UUID productId, final long quantity) { - final MenuProduct menuProduct = new MenuProduct(); - menuProduct.setProductId(productId); - menuProduct.setQuantity(quantity); + public static MenuProductRequest createMenuProductRequest(final UUID productId, final long quantity) { + final MenuProductRequest menuProduct = new MenuProductRequest(productId, quantity); return menuProduct; } - private Menu changePriceRequest(final long price) { + private MenuRequest changePriceRequest(final long price) { return changePriceRequest(BigDecimal.valueOf(price)); } - private Menu changePriceRequest(final BigDecimal price) { - final Menu menu = new Menu(); - menu.setPrice(price); + private MenuRequest changePriceRequest(final BigDecimal price) { + final MenuRequest menu = new MenuRequest(price); return menu; } } diff --git a/src/test/java/kitchenpos/menus/tobe/domain/MenuGroupNameTest.java b/src/test/java/kitchenpos/menus/tobe/domain/MenuGroupNameTest.java new file mode 100644 index 000000000..bdaa60dac --- /dev/null +++ b/src/test/java/kitchenpos/menus/tobe/domain/MenuGroupNameTest.java @@ -0,0 +1,34 @@ +package kitchenpos.menus.tobe.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +class MenuGroupNameTest { + + @DisplayName("정상적으로 메뉴그룹을 생성해보자") + @ParameterizedTest + @ValueSource(strings = {"1인 메뉴", "세트 메뉴"}) + void createProduct(String name) { + MenuGroupName menuGroupName = new MenuGroupName(name); + + assertAll( + () -> assertThat(menuGroupName).isNotNull(), + () -> assertThat(menuGroupName.getName()).isEqualTo(name) + ); + } + + @DisplayName("메뉴그룹 이름에 Null 또는 공백은 불가능하다") + @ParameterizedTest + @NullAndEmptySource + void invalidProductName(String name) { + assertThatThrownBy( + () -> new MenuGroupName(name) + ).isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/src/test/java/kitchenpos/menus/tobe/domain/MenuNameTest.java b/src/test/java/kitchenpos/menus/tobe/domain/MenuNameTest.java new file mode 100644 index 000000000..8b1bd4d04 --- /dev/null +++ b/src/test/java/kitchenpos/menus/tobe/domain/MenuNameTest.java @@ -0,0 +1,49 @@ +package kitchenpos.menus.tobe.domain; + +import kitchenpos.products.application.FakePurgomalumClient; +import kitchenpos.products.infra.PurgomalumClient; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +class MenuNameTest { + + @DisplayName("정상적으로 메뉴를 생성해보자") + @ParameterizedTest + @ValueSource(strings = {"1인 메뉴", "세트메뉴"}) + void createMenuName(String name) { + PurgomalumClient purgomalumClient = new FakePurgomalumClient(); + MenuName menuName = new MenuName(purgomalumClient, name); + + assertAll( + () -> assertThat(menuName).isNotNull(), + () -> assertThat(menuName.getName()).isEqualTo(name) + ); + } + + @DisplayName("메뉴이름에 null은 불가능하다") + @Test + void invalidMenuName() { + PurgomalumClient purgomalumClient = new FakePurgomalumClient(); + + assertThatThrownBy( + () -> new MenuName(purgomalumClient, null) + ).isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("메뉴이름이 비속어가 될수 없다.") + @ParameterizedTest + @ValueSource(strings = {"비속어", "욕설"}) + void slangMenuName(String name) { + PurgomalumClient purgomalumClient = new FakePurgomalumClient(); + + assertThatThrownBy( + () -> new MenuName(purgomalumClient, name) + ).isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/src/test/java/kitchenpos/menus/tobe/domain/MenuProductsTest.java b/src/test/java/kitchenpos/menus/tobe/domain/MenuProductsTest.java new file mode 100644 index 000000000..1251551d8 --- /dev/null +++ b/src/test/java/kitchenpos/menus/tobe/domain/MenuProductsTest.java @@ -0,0 +1,87 @@ +package kitchenpos.menus.tobe.domain; + +import kitchenpos.common.domain.Price; +import kitchenpos.products.tobe.domain.Product; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import static kitchenpos.Fixtures.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +class MenuProductsTest { + + @DisplayName("메뉴상품을 생성해보자") + @Test + void create() { + Product product = product(); + List products = Arrays.asList(product); + List menuProductDtos = Arrays.asList(menuProductDto(product.getId(), 1L)); + MenuProducts menuProducts = new MenuProducts(menuProductDtos, products, new Price(product.getPrice())); + + assertThat(menuProducts).isNotNull(); + assertAll( + () -> assertThat(menuProducts.getMenuProducts()).isNotNull(), + () -> assertThat(menuProducts.getMenuProducts()).hasSize(1), + () -> assertThat(menuProducts.size()).isEqualTo(1) + ); + } + + @DisplayName("등록하려는 메뉴상품과 상품의 갯수가 다르면 생성할수 없다") + @Test + void notEqualProductCount() { + Product product = product(); + List products = Arrays.asList(product); + List menuProductDtos = + Arrays.asList(menuProductDto(UUID.randomUUID(), 1L), menuProductDto(product.getId(), 1L)); + assertThatThrownBy( + () -> new MenuProducts(menuProductDtos, products, new Price(product.getPrice())) + ).isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("메뉴의 가격은 메뉴상품의 총합보다 작거나 같아야한다.") + @ParameterizedTest + @CsvSource(value = {"18000:19000", "1000:5000", "100:110"}, delimiter = ':') + void menuPriceNotExpesiveThanMenuProduct(long productPrice, long menuPrice) { + Product product = product("양념치킨", productPrice); + List products = Arrays.asList(product); + List menuProductDtos = Arrays.asList(menuProductDto(product.getId(), 1L)); + + assertThatThrownBy( + () -> new MenuProducts(menuProductDtos, products, new Price(BigDecimal.valueOf(menuPrice))) + ).isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("메뉴의 가격이 메뉴상품의 가격보다 비싸지 않을경우를 테스트해보자") + @ParameterizedTest + @CsvSource(value = {"18000:19000", "5000:5000", "100:100"}, delimiter = ':') + void isNotExpensivePrice(long menuPrice, long productPrice) { + Product product = product("양념치킨", productPrice); + List products = Arrays.asList(product); + List menuProductDtos = Arrays.asList(menuProductDto(product.getId(), 1L)); + MenuProducts menuProducts = new MenuProducts(menuProductDtos, products, new Price(product.getPrice())); + + assertThat(menuProducts.isExpensiveMenuPrice(new Price(BigDecimal.valueOf(menuPrice)), products)).isFalse(); + } + + @DisplayName("메뉴의 가격이 메뉴상품의 가격보다 비쌀경우를 테스트해보자") + @ParameterizedTest + @CsvSource(value = {"19000:18000", "5000:1000", "110:100"}, delimiter = ':') + void isExpensivePrice(long menuPrice, long productPrice) { + Product product = product("양념치킨", productPrice); + List products = Arrays.asList(product); + List menuProductDtos = Arrays.asList(menuProductDto(product.getId(), 1L)); + MenuProducts menuProducts = new MenuProducts(menuProductDtos, products, new Price(product.getPrice())); + + assertThat(menuProducts.isExpensiveMenuPrice(new Price(BigDecimal.valueOf(menuPrice)), products)).isTrue(); + } + +} diff --git a/src/test/java/kitchenpos/menus/tobe/domain/MenuTest.java b/src/test/java/kitchenpos/menus/tobe/domain/MenuTest.java new file mode 100644 index 000000000..5d546c8ca --- /dev/null +++ b/src/test/java/kitchenpos/menus/tobe/domain/MenuTest.java @@ -0,0 +1,106 @@ +package kitchenpos.menus.tobe.domain; + +import kitchenpos.common.domain.Price; +import kitchenpos.products.application.FakePurgomalumClient; +import kitchenpos.products.tobe.domain.Product; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.UUID; + +import static kitchenpos.Fixtures.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +class MenuTest { + + @DisplayName("메뉴를 생성해보자") + @Test + void create() { + UUID menuId = UUID.randomUUID(); + UUID menuGroupId = menuGroup().getId(); + String menuName = "후라이드+후라이드"; + BigDecimal price = BigDecimal.valueOf(20000L); + + Menu menu = new Menu(new FakePurgomalumClient(), menuId, menuName, price, menuGroupId, true, new MenuProducts(Arrays.asList(menuProduct()))); + + assertThat(menu).isNotNull(); + assertAll( + () -> assertThat(menu.getId()).isEqualTo(menuId), + () -> assertThat(menu.getName()).isEqualTo(menuName), + () -> assertThat(menu.getMenuGroupId()).isEqualTo(menuGroupId), + () -> assertThat(menu.getMenuProducts()).hasSize(1), + () -> assertThat(menu.getPrice()).isEqualTo(price) + ); + } + + @DisplayName("메뉴의 가격을 변경해보자") + @ParameterizedTest + @CsvSource(value = {"18000:19000", "1000:5000", "1000:1000"}, delimiter = ':') + void changePrice(long menuPrice, long productPrice) { + Price price = new Price(BigDecimal.valueOf(menuPrice)); + Product product = product("양념치킨", productPrice); + menuProduct(product, 1L); + Menu menu = new Menu(new FakePurgomalumClient(), UUID.randomUUID(), "핫한치킨", BigDecimal.valueOf(productPrice), menuGroup().getId(), true, new MenuProducts(Arrays.asList(menuProduct(product, 1L)))); + + menu.changePrice(price, Arrays.asList(product)); + + assertThat(menu.getPrice()).isEqualTo(price.getPrice()); + } + + @DisplayName("가격의합이 메뉴가 더 크면 불가능하다") + @ParameterizedTest + @CsvSource(value = {"19000:18000", "5000:1000", "2000:1900"}, delimiter = ':') + void impossibleChangePrice(long menuPrice, long productPrice) { + Price price = new Price(BigDecimal.valueOf(menuPrice)); + Product product = product("양념치킨", productPrice); + menuProduct(product, 1L); + Menu menu = new Menu(new FakePurgomalumClient(), UUID.randomUUID(), "핫한치킨", BigDecimal.valueOf(productPrice), menuGroup().getId(), true, new MenuProducts(Arrays.asList(menuProduct(product, 1L)))); + + assertThatThrownBy( + () -> menu.changePrice(price, Arrays.asList(product)) + ).isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("메뉴를 노출해보자") + @ParameterizedTest + @CsvSource(value = {"18000:19000", "1000:5000", "1000:1000"}, delimiter = ':') + void show(long menuPrice, long productPrice) { + Product product = product("양념치킨", productPrice); + menuProduct(product, 1L); + Menu menu = new Menu(new FakePurgomalumClient(), UUID.randomUUID(), "인기치킨", BigDecimal.valueOf(menuPrice), menuGroup().getId(), true, new MenuProducts(Arrays.asList(menuProduct(product, 1L)))); + + menu.show(Arrays.asList(product)); + + assertThat(menu.isDisplayed()).isTrue(); + } + + @DisplayName("가격의 합이 메뉴가 더 크면 불가능하다") + @ParameterizedTest + @CsvSource(value = {"19000:18000", "6000:5000", "2000:1000"}, delimiter = ':') + void impossibleShow(long menuPrice, long productPrice) { + Product product = product("양념치킨", productPrice); + menuProduct(product, 1L); + Menu menu = new Menu(new FakePurgomalumClient(), UUID.randomUUID(), "인기치킨", BigDecimal.valueOf(menuPrice), menuGroup().getId(), true, new MenuProducts(Arrays.asList(menuProduct(product, 1L)))); + + assertThatThrownBy( + () -> menu.show(Arrays.asList(product)) + ).isInstanceOf(IllegalStateException.class); + + assertThat(menu.isDisplayed()).isTrue(); + } + + @DisplayName("메뉴를 미노출 상태로 변경해보자") + @Test + void hide() { + Menu menu = new Menu(new FakePurgomalumClient(), UUID.randomUUID(), "후라이드+후라이드", BigDecimal.valueOf(20000L), menuGroup().getId(), true, new MenuProducts(Arrays.asList(menuProduct()))); + menu.hide(); + + assertThat(menu.isDisplayed()).isFalse(); + } +} diff --git a/src/test/java/kitchenpos/menus/ui/dto/MenuProductRequestsTest.java b/src/test/java/kitchenpos/menus/ui/dto/MenuProductRequestsTest.java new file mode 100644 index 000000000..d5b483896 --- /dev/null +++ b/src/test/java/kitchenpos/menus/ui/dto/MenuProductRequestsTest.java @@ -0,0 +1,48 @@ +package kitchenpos.menus.ui.dto; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static kitchenpos.Fixtures.product; +import static kitchenpos.menus.application.MenuServiceTest.createMenuProductRequest; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +class MenuProductRequestsTest { + + @DisplayName("메뉴 상품목록을 생성한다.") + @Test + void createMenuProductRequests() { + MenuProductRequests menuProductRequests = new MenuProductRequests(Arrays.asList(createMenuProductRequest(product().getId(), 1L))); + + assertThat(menuProductRequests).isNotNull(); + assertAll( + () -> assertThat(menuProductRequests.getMenuProductRequests()).isNotNull(), + () -> assertThat(menuProductRequests.getMenuProductRequests()).hasSize(1) + ); + } + + @DisplayName("메뉴 상품목록은 null 또는 빈 목록이 될수 없다.") + @MethodSource("menuProducts") + @ParameterizedTest + void create(final List menuProducts) { + assertThatThrownBy( + () -> new MenuProductRequests(menuProducts) + ).isInstanceOf(IllegalArgumentException.class); + } + + private static List menuProducts() { + return Arrays.asList( + null, + Arguments.of(Collections.emptyList()) + ); + } +} diff --git a/src/test/java/kitchenpos/products/application/ProductServiceTest.java b/src/test/java/kitchenpos/products/application/ProductServiceTest.java index 8a8a89cb1..c5185b539 100644 --- a/src/test/java/kitchenpos/products/application/ProductServiceTest.java +++ b/src/test/java/kitchenpos/products/application/ProductServiceTest.java @@ -1,11 +1,11 @@ package kitchenpos.products.application; import kitchenpos.menus.application.InMemoryMenuRepository; -import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuRepository; -import kitchenpos.products.tobe.domain.Product; +import kitchenpos.menus.tobe.domain.Menu; import kitchenpos.products.domain.ProductRepository; import kitchenpos.products.infra.PurgomalumClient; +import kitchenpos.products.tobe.domain.Product; import kitchenpos.products.ui.dto.ProductRequest; import kitchenpos.products.ui.dto.ProductResponse; import org.junit.jupiter.api.BeforeEach; @@ -45,9 +45,9 @@ void create() { final ProductResponse actual = productService.create(expected); assertThat(actual).isNotNull(); assertAll( - () -> assertThat(actual.getId()).isNotNull(), - () -> assertThat(actual.getName()).isEqualTo(expected.getName()), - () -> assertThat(actual.getPrice()).isEqualTo(expected.getPrice()) + () -> assertThat(actual.getId()).isNotNull(), + () -> assertThat(actual.getName()).isEqualTo(expected.getName()), + () -> assertThat(actual.getPrice()).isEqualTo(expected.getPrice()) ); } @@ -58,7 +58,7 @@ void create() { void create(final BigDecimal price) { final ProductRequest expected = createProductRequest("후라이드", price); assertThatThrownBy(() -> productService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @DisplayName("상품의 이름이 올바르지 않으면 등록할 수 없다.") @@ -68,7 +68,7 @@ void create(final BigDecimal price) { void create(final String name) { final ProductRequest expected = createProductRequest(name, 16_000L); assertThatThrownBy(() -> productService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @DisplayName("상품의 가격을 변경할 수 있다.") @@ -88,7 +88,7 @@ void changePrice(final BigDecimal price) { final UUID productId = productRepository.save(product("후라이드", 16_000L)).getId(); final ProductRequest expected = changePriceRequest(price); assertThatThrownBy(() -> productService.changePrice(productId, expected)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @DisplayName("상품의 가격이 변경될 때 메뉴의 가격이 메뉴에 속한 상품 금액의 합보다 크면 메뉴가 숨겨진다.") diff --git a/src/test/java/kitchenpos/products/tobe/domain/ProductPriceTest.java b/src/test/java/kitchenpos/products/tobe/domain/ProductPriceTest.java deleted file mode 100644 index fe6a0ff13..000000000 --- a/src/test/java/kitchenpos/products/tobe/domain/ProductPriceTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package kitchenpos.products.tobe.domain; - -import kitchenpos.products.application.FakePurgomalumClient; -import kitchenpos.products.infra.PurgomalumClient; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import java.math.BigDecimal; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.*; - -class ProductPriceTest { - - @DisplayName("정상적으로 상품의 가격을 생성해보자") - @ParameterizedTest - @ValueSource(ints = {0, 1000, 5000, 10000}) - void createProductPrice(int price) { - ProductPrice productPrice = new ProductPrice(BigDecimal.valueOf(price)); - - assertAll( - () -> assertThat(productPrice).isNotNull(), - () -> assertThat(productPrice.getPrice()).isEqualTo(BigDecimal.valueOf(price)) - ); - } - - @DisplayName("상품가격은 null이 될수 없다.") - @Test - void invalidProductPrice() { - assertThatThrownBy( - () -> new ProductPrice(null) - ).isInstanceOf(IllegalArgumentException.class); - } - - @DisplayName("상품 가격은 음수가 될수 없다.") - @ParameterizedTest - @ValueSource(ints = {-100, -5000, -10000}) - void negativeProductPrice(int price) { - assertThatThrownBy( - () -> new ProductPrice(BigDecimal.valueOf(price)) - ).isInstanceOf(IllegalArgumentException.class); - } -}