diff --git a/src/main/java/kitchenpos/menus/application/MenuProductMapper.java b/src/main/java/kitchenpos/menus/application/MenuProductMapper.java new file mode 100644 index 000000000..4c760ea0c --- /dev/null +++ b/src/main/java/kitchenpos/menus/application/MenuProductMapper.java @@ -0,0 +1,62 @@ +package kitchenpos.menus.application; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import kitchenpos.menus.application.dto.MenuProductCreateRequest; +import kitchenpos.menus.application.dto.MenuProductsCreateRequest; +import kitchenpos.menus.domain.tobe.MenuProduct; +import kitchenpos.menus.domain.tobe.MenuProductsValidator; +import kitchenpos.menus.domain.tobe.MenuProducts; +import kitchenpos.menus.domain.tobe.ProductQuantity; +import kitchenpos.products.domain.ProductRepository; +import kitchenpos.products.domain.tobe.Product; +import org.springframework.stereotype.Component; + +@Component +public class MenuProductMapper { + + private final ProductRepository productRepository; + private final MenuProductsValidator menuProductsValidator; + + public MenuProductMapper(ProductRepository productRepository, + MenuProductsValidator menuProductValidator) { + this.productRepository = productRepository; + this.menuProductsValidator = menuProductValidator; + } + + public MenuProducts map(MenuProductsCreateRequest request) { + List productIds = request.menuProducts() + .stream().map(MenuProductCreateRequest::productId) + .toList(); + + List products = productRepository.findAllByIdIn(productIds); + List menuProducts = createMenuProducts(request, products); + menuProductsValidator.validate(menuProducts, products); + return new MenuProducts(menuProducts); + } + + private List createMenuProducts(MenuProductsCreateRequest menuProducts, + List products) { + return menuProducts.menuProducts() + .stream() + .map(menuProduct -> createMenuProduct(products, + menuProduct.productId(), + menuProduct.quantity()) + ) + .toList(); + } + + private MenuProduct createMenuProduct(List products, + UUID productId, + ProductQuantity quantity) { + Product product = findProduct(products, productId); + return new MenuProduct(product, quantity); + } + + private Product findProduct(List products, UUID productId) { + return products.stream() + .filter(product -> product.getId().equals(productId)) + .findFirst().orElseThrow((NoSuchElementException::new)); + } +} diff --git a/src/main/java/kitchenpos/menus/application/MenuProductsService.java b/src/main/java/kitchenpos/menus/application/MenuProductsService.java deleted file mode 100644 index 018f7ee93..000000000 --- a/src/main/java/kitchenpos/menus/application/MenuProductsService.java +++ /dev/null @@ -1,72 +0,0 @@ -package kitchenpos.menus.application; - -import java.math.BigDecimal; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.UUID; -import java.util.stream.Collectors; -import kitchenpos.menus.domain.tobe.MenuPrice; -import kitchenpos.menus.domain.tobe.MenuProduct; -import kitchenpos.menus.domain.tobe.MenuProducts; -import kitchenpos.menus.ui.dto.MenuProductCreateRequests; -import kitchenpos.products.domain.ProductRepository; -import kitchenpos.products.domain.tobe.Product; -import org.springframework.stereotype.Service; - -@Service -public class MenuProductsService { - - private final ProductRepository productRepository; - - public MenuProductsService(ProductRepository productRepository) { - this.productRepository = productRepository; - } - - public MenuProducts create(final MenuProductCreateRequests requests, - MenuPrice price) { - List products = findProducts(requests.getProductIds()); - requests.validateMenuProducts(products); - - List menuProducts = createMenuProducts(requests); - validateMenuPrice(menuProducts, price); - return new MenuProducts(menuProducts); - } - - private List createMenuProducts(MenuProductCreateRequests requests) { - return requests.getMenuProducts() - .stream() - .map(request -> { - Product product = findProduct(request.getProductId()); - return request.to(product); - }) - .collect(Collectors.toList()); - } - - public void validateMenuPrice(List menuProducts, MenuPrice price) { - if (isOverThanProductSumPrice(menuProducts, price)) { - throw new IllegalArgumentException(); - } - } - - public boolean isOverThanProductSumPrice(List menuProducts, MenuPrice price) { - return price.isOver(calculateProductSumPrice(menuProducts)); - } - - private BigDecimal calculateProductSumPrice(List menuProducts) { - BigDecimal sum = BigDecimal.ZERO; - for (MenuProduct menuProduct : menuProducts) { - Product product = findProduct(menuProduct.getProductId()); - sum = sum.add(menuProduct.calculateSum(product)); - } - return sum; - } - - private List findProducts(List productIds) { - return productRepository.findAllByIdIn(productIds); - } - - private Product findProduct(UUID productId) { - return productRepository.findById(productId) - .orElseThrow(NoSuchElementException::new); - } -} diff --git a/src/main/java/kitchenpos/menus/application/MenuService.java b/src/main/java/kitchenpos/menus/application/MenuService.java index abad4364d..af777029d 100644 --- a/src/main/java/kitchenpos/menus/application/MenuService.java +++ b/src/main/java/kitchenpos/menus/application/MenuService.java @@ -4,12 +4,12 @@ import java.util.NoSuchElementException; import java.util.UUID; import kitchenpos.menugroups.domain.MenuGroupRepository; +import kitchenpos.menugroups.domain.tobe.MenuGroup; +import kitchenpos.menus.application.dto.MenuCreateRequest; import kitchenpos.menus.domain.MenuRepository; import kitchenpos.menus.domain.tobe.Menu; import kitchenpos.menus.domain.tobe.MenuPrice; import kitchenpos.menus.domain.tobe.MenuProducts; -import kitchenpos.menugroups.domain.tobe.MenuGroup; -import kitchenpos.menus.ui.dto.MenuCreateRequest; import kitchenpos.products.domain.ProfanityValidator; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -20,33 +20,36 @@ public class MenuService { private final MenuRepository menuRepository; private final MenuGroupRepository menuGroupRepository; private final ProfanityValidator profanityValidator; - private final MenuProductsService menuProductsService; + private final MenuProductMapper menuProductMapper; - public MenuService( - final MenuRepository menuRepository, - final MenuGroupRepository menuGroupRepository, - final ProfanityValidator profanityValidator, - final MenuProductsService menuProductsService - ) { + public MenuService(MenuRepository menuRepository, MenuGroupRepository menuGroupRepository, + ProfanityValidator profanityValidator, MenuProductMapper menuProductMapper) { this.menuRepository = menuRepository; this.menuGroupRepository = menuGroupRepository; this.profanityValidator = profanityValidator; - this.menuProductsService = menuProductsService; + this.menuProductMapper = menuProductMapper; } @Transactional public Menu create(final MenuCreateRequest request) { - request.validateName(profanityValidator); - final MenuGroup menuGroup = findMenuGroup(request.getMenuGroupId()); - final MenuProducts menuProducts = menuProductsService.create(request.getMenuProducts(), - request.getPrice()); - return menuRepository.save(request.to(menuGroup, menuProducts)); + profanityValidator.validate(request.name().getName()); + final MenuGroup menuGroup = findMenuGroup(request.menuGroupId()); + final MenuProducts menuProducts = menuProductMapper.map( + request.menuProductsCreateRequest()); + + final Menu menu = new Menu( + request.name(), + request.price(), + menuGroup, + request.displayed(), + menuProducts); + return menuRepository.save(menu); } + @Transactional public Menu changePrice(final UUID menuId, final MenuPrice request) { final Menu menu = findMenu(menuId); - menuProductsService.validateMenuPrice(menu.getMenuProducts(), request); menu.changePrice(request); return menu; } @@ -54,7 +57,6 @@ public Menu changePrice(final UUID menuId, final MenuPrice request) { @Transactional public Menu display(final UUID menuId) { final Menu menu = findMenu(menuId); - menuProductsService.validateMenuPrice(menu.getMenuProducts(), menu.getMenuPrice()); menu.display(); return menu; } @@ -73,11 +75,11 @@ public List findAll() { private MenuGroup findMenuGroup(UUID menuGroupId) { return menuGroupRepository.findById(menuGroupId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); } private Menu findMenu(UUID menuId) { return menuRepository.findById(menuId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); } } diff --git a/src/main/java/kitchenpos/menus/application/dto/MenuCreateRequest.java b/src/main/java/kitchenpos/menus/application/dto/MenuCreateRequest.java new file mode 100644 index 000000000..82187864c --- /dev/null +++ b/src/main/java/kitchenpos/menus/application/dto/MenuCreateRequest.java @@ -0,0 +1,15 @@ +package kitchenpos.menus.application.dto; + +import jakarta.validation.constraints.NotNull; +import java.util.UUID; +import kitchenpos.menus.domain.tobe.DisplayedMenu; +import kitchenpos.menus.domain.tobe.MenuName; +import kitchenpos.menus.domain.tobe.MenuPrice; + +public record MenuCreateRequest(@NotNull MenuName name, + @NotNull MenuPrice price, + @NotNull UUID menuGroupId, + @NotNull DisplayedMenu displayed, + @NotNull MenuProductsCreateRequest menuProductsCreateRequest) { + +} diff --git a/src/main/java/kitchenpos/menus/application/dto/MenuProductCreateRequest.java b/src/main/java/kitchenpos/menus/application/dto/MenuProductCreateRequest.java new file mode 100644 index 000000000..61621f6d0 --- /dev/null +++ b/src/main/java/kitchenpos/menus/application/dto/MenuProductCreateRequest.java @@ -0,0 +1,10 @@ +package kitchenpos.menus.application.dto; + +import jakarta.validation.constraints.NotNull; +import java.util.UUID; +import kitchenpos.menus.domain.tobe.ProductQuantity; + +public record MenuProductCreateRequest(@NotNull UUID productId, + @NotNull ProductQuantity quantity) { + +} diff --git a/src/main/java/kitchenpos/menus/application/dto/MenuProductsCreateRequest.java b/src/main/java/kitchenpos/menus/application/dto/MenuProductsCreateRequest.java new file mode 100644 index 000000000..4fe086582 --- /dev/null +++ b/src/main/java/kitchenpos/menus/application/dto/MenuProductsCreateRequest.java @@ -0,0 +1,8 @@ +package kitchenpos.menus.application.dto; + +import jakarta.validation.constraints.NotEmpty; +import java.util.List; + +public record MenuProductsCreateRequest(@NotEmpty List menuProducts) { + +} diff --git a/src/main/java/kitchenpos/menus/domain/tobe/Menu.java b/src/main/java/kitchenpos/menus/domain/tobe/Menu.java index 4bcf7b340..cfde31640 100644 --- a/src/main/java/kitchenpos/menus/domain/tobe/Menu.java +++ b/src/main/java/kitchenpos/menus/domain/tobe/Menu.java @@ -3,16 +3,12 @@ import jakarta.persistence.Column; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; -import jakarta.persistence.ForeignKey; import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; -import jakarta.persistence.Transient; import java.math.BigDecimal; -import java.util.List; import java.util.UUID; import kitchenpos.menugroups.domain.tobe.MenuGroup; +import kitchenpos.products.domain.tobe.ProductPrice; @Table(name = "menu") @Entity @@ -40,32 +36,56 @@ protected Menu() { } public Menu(MenuName name, MenuPrice price, MenuGroup menuGroup, DisplayedMenu displayed, - MenuProducts menuProducts) { - this(UUID.randomUUID(), name, price, menuGroup.getId(), displayed, menuProducts); - } - - public Menu(UUID id, MenuName name, MenuPrice price, UUID menuGroupId, - DisplayedMenu displayed, MenuProducts menuProducts) { - this.id = id; + MenuProducts menuProducts) { + validateMenuPrice(price, menuProducts); + this.id = UUID.randomUUID(); this.name = name; this.price = price; - this.menuGroupId = menuGroupId; + this.menuGroupId = menuGroup.getId(); this.displayed = displayed; this.menuProducts = menuProducts; } + private static void validateMenuPrice(MenuPrice price, MenuProducts menuProducts) { + if (price.isOver(menuProducts.calculateSumPrice())) { + throw new IllegalArgumentException(); + } + } + public void changePrice(MenuPrice price) { + if (price.isOver(menuProducts.calculateSumPrice())) { + throw new IllegalArgumentException(); + } this.price = price; } public void display() { + if (isOverThanProductSumPrice()) { + throw new IllegalArgumentException(); + } this.displayed = new DisplayedMenu(true); } + public boolean isOverThanProductSumPrice() { + return price.isOver(menuProducts.calculateSumPrice()); + } + public void hide() { this.displayed = new DisplayedMenu(false); } + public void changeMenuProductPrice(UUID productId, ProductPrice price) { + for (MenuProduct menuProduct : menuProducts) { + if (menuProduct.getProductId().equals(productId)) { + menuProduct.changePrice(price); + } + } + + if (isOverThanProductSumPrice()) { + hide(); + } + } + public boolean isDisplayed() { return this.displayed.isDisplayed(); } @@ -74,15 +94,11 @@ public UUID getId() { return id; } - public MenuPrice getMenuPrice() { - return price; - } - public BigDecimal getPrice() { return price.getPrice(); } - public List getMenuProducts() { - return menuProducts.getMenuProducts(); + public MenuProducts getMenuProducts() { + return menuProducts; } } diff --git a/src/main/java/kitchenpos/menus/domain/tobe/MenuProduct.java b/src/main/java/kitchenpos/menus/domain/tobe/MenuProduct.java index 74d023ed7..977333a69 100644 --- a/src/main/java/kitchenpos/menus/domain/tobe/MenuProduct.java +++ b/src/main/java/kitchenpos/menus/domain/tobe/MenuProduct.java @@ -10,6 +10,7 @@ import java.math.BigDecimal; import java.util.UUID; import kitchenpos.products.domain.tobe.Product; +import kitchenpos.products.domain.tobe.ProductPrice; @Table(name = "menu_product") @Entity @@ -22,27 +23,33 @@ public class MenuProduct { private UUID productId; + private BigDecimal price; + @Embedded - private MenuQuantity quantity; + private ProductQuantity quantity; protected MenuProduct() { } - public MenuProduct(Product product, MenuQuantity quantity) { - this(null, product.getId(), quantity); + public MenuProduct(Product product, int quantity) { + this(product, new ProductQuantity(quantity)); } - public MenuProduct(Long seq, UUID productId, MenuQuantity quantity) { - this.seq = seq; - this.productId = productId; + public MenuProduct(Product product, ProductQuantity quantity) { + this.productId = product.getId(); + this.price = product.getPrice(); this.quantity = quantity; } - public BigDecimal calculateSum(Product product) { - return product.getPrice().multiply(quantity.getQuantity()); + public BigDecimal calculateSum() { + return price.multiply(quantity.getQuantity()); } public UUID getProductId() { return productId; } + + public void changePrice(ProductPrice price) { + this.price = price.getPrice(); + } } diff --git a/src/main/java/kitchenpos/menus/domain/tobe/MenuProducts.java b/src/main/java/kitchenpos/menus/domain/tobe/MenuProducts.java index abc485517..fa1484c55 100644 --- a/src/main/java/kitchenpos/menus/domain/tobe/MenuProducts.java +++ b/src/main/java/kitchenpos/menus/domain/tobe/MenuProducts.java @@ -5,18 +5,20 @@ import jakarta.persistence.ForeignKey; import jakarta.persistence.JoinColumn; import jakarta.persistence.OneToMany; +import java.math.BigDecimal; +import java.util.Iterator; import java.util.List; -import java.util.Objects; +import org.jetbrains.annotations.NotNull; @Embeddable -public class MenuProducts { +public class MenuProducts implements Iterable { @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) @JoinColumn( - name = "menu_id", - nullable = false, - columnDefinition = "binary(16)", - foreignKey = @ForeignKey(name = "fk_menu_product_to_menu") + name = "menu_id", + nullable = false, + columnDefinition = "binary(16)", + foreignKey = @ForeignKey(name = "fk_menu_product_to_menu") ) private List menuProducts; @@ -24,17 +26,24 @@ protected MenuProducts() { } public MenuProducts(List menuProducts) { - validateMenuProducts(menuProducts); + if (menuProducts == null || menuProducts.isEmpty()) { + throw new IllegalArgumentException(); + } + this.menuProducts = menuProducts; } - private void validateMenuProducts(List menuProducts) { - if (Objects.isNull(menuProducts) || menuProducts.isEmpty()) { - throw new IllegalArgumentException(); + public BigDecimal calculateSumPrice() { + BigDecimal sum = BigDecimal.ZERO; + for (MenuProduct menuProduct : menuProducts) { + sum = sum.add(menuProduct.calculateSum()); } + return sum; } - public List getMenuProducts() { - return menuProducts; + @NotNull + @Override + public Iterator iterator() { + return menuProducts.iterator(); } } diff --git a/src/main/java/kitchenpos/menus/domain/tobe/MenuProductsValidator.java b/src/main/java/kitchenpos/menus/domain/tobe/MenuProductsValidator.java new file mode 100644 index 000000000..843120afd --- /dev/null +++ b/src/main/java/kitchenpos/menus/domain/tobe/MenuProductsValidator.java @@ -0,0 +1,23 @@ +package kitchenpos.menus.domain.tobe; + +import java.util.List; +import kitchenpos.products.domain.tobe.Product; +import org.springframework.stereotype.Component; + +@Component +public class MenuProductsValidator { + + public void validate(List menuProducts, List products) { + if (menuProducts == null || products == null) { + throw new IllegalArgumentException(); + } + + if (menuProducts.isEmpty() || products.isEmpty()) { + throw new IllegalArgumentException(); + } + + if (products.size() != menuProducts.size()) { + throw new IllegalArgumentException(); + } + } +} diff --git a/src/main/java/kitchenpos/menus/domain/tobe/MenuQuantity.java b/src/main/java/kitchenpos/menus/domain/tobe/ProductQuantity.java similarity index 83% rename from src/main/java/kitchenpos/menus/domain/tobe/MenuQuantity.java rename to src/main/java/kitchenpos/menus/domain/tobe/ProductQuantity.java index d2d9dd486..50f192e51 100644 --- a/src/main/java/kitchenpos/menus/domain/tobe/MenuQuantity.java +++ b/src/main/java/kitchenpos/menus/domain/tobe/ProductQuantity.java @@ -6,15 +6,15 @@ import java.util.Objects; @Embeddable -public class MenuQuantity { +public class ProductQuantity { @Column(name = "quantity", nullable = false) private long quantity; - protected MenuQuantity() { + protected ProductQuantity() { } - public MenuQuantity(long quantity) { + public ProductQuantity(long quantity) { if (quantity < 0) { throw new IllegalArgumentException(); } @@ -34,7 +34,7 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - MenuQuantity that = (MenuQuantity) o; + ProductQuantity that = (ProductQuantity) o; return quantity == that.quantity; } diff --git a/src/main/java/kitchenpos/menus/ui/MenuRestController.java b/src/main/java/kitchenpos/menus/ui/MenuRestController.java index 944291021..dde9743cf 100644 --- a/src/main/java/kitchenpos/menus/ui/MenuRestController.java +++ b/src/main/java/kitchenpos/menus/ui/MenuRestController.java @@ -1,12 +1,13 @@ package kitchenpos.menus.ui; +import jakarta.validation.Valid; import java.net.URI; import java.util.List; import java.util.UUID; import kitchenpos.menus.application.MenuService; +import kitchenpos.menus.application.dto.MenuCreateRequest; import kitchenpos.menus.domain.tobe.Menu; import kitchenpos.menus.domain.tobe.MenuPrice; -import kitchenpos.menus.ui.dto.MenuCreateRequest; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -27,7 +28,7 @@ public MenuRestController(final MenuService menuService) { } @PostMapping - public ResponseEntity create(@RequestBody final MenuCreateRequest request) { + public ResponseEntity create(@RequestBody @Valid final MenuCreateRequest request) { final Menu response = menuService.create(request); return ResponseEntity.created(URI.create("/api/menus/" + response.getId())) .body(response); diff --git a/src/main/java/kitchenpos/menus/ui/dto/MenuCreateRequest.java b/src/main/java/kitchenpos/menus/ui/dto/MenuCreateRequest.java deleted file mode 100644 index e47f86910..000000000 --- a/src/main/java/kitchenpos/menus/ui/dto/MenuCreateRequest.java +++ /dev/null @@ -1,53 +0,0 @@ -package kitchenpos.menus.ui.dto; - -import java.util.UUID; -import kitchenpos.menus.domain.tobe.DisplayedMenu; -import kitchenpos.menus.domain.tobe.Menu; -import kitchenpos.menus.domain.tobe.MenuName; -import kitchenpos.menus.domain.tobe.MenuPrice; -import kitchenpos.menus.domain.tobe.MenuProducts; -import kitchenpos.menugroups.domain.tobe.MenuGroup; -import kitchenpos.products.domain.ProfanityValidator; - -public class MenuCreateRequest { - - private MenuName name; - - private MenuPrice price; - - private UUID menuGroupId; - - private DisplayedMenu displayed; - - private MenuProductCreateRequests menuProducts; - - public MenuCreateRequest(MenuName name, MenuPrice price, UUID menuGroupId, - DisplayedMenu displayed, - MenuProductCreateRequests menuProducts) { - this.name = name; - this.price = price; - this.menuGroupId = menuGroupId; - this.displayed = displayed; - this.menuProducts = menuProducts; - } - - public void validateName(ProfanityValidator profanityValidator) { - profanityValidator.validate(name.getName()); - } - - public Menu to(MenuGroup menuGroup, MenuProducts menuProducts) { - return new Menu(name, price, menuGroup, displayed, menuProducts); - } - - public UUID getMenuGroupId() { - return menuGroupId; - } - - public MenuProductCreateRequests getMenuProducts() { - return menuProducts; - } - - public MenuPrice getPrice() { - return price; - } -} diff --git a/src/main/java/kitchenpos/menus/ui/dto/MenuProductCreateRequest.java b/src/main/java/kitchenpos/menus/ui/dto/MenuProductCreateRequest.java deleted file mode 100644 index 71f258e24..000000000 --- a/src/main/java/kitchenpos/menus/ui/dto/MenuProductCreateRequest.java +++ /dev/null @@ -1,30 +0,0 @@ -package kitchenpos.menus.ui.dto; - -import java.util.UUID; -import kitchenpos.menus.domain.tobe.MenuProduct; -import kitchenpos.menus.domain.tobe.MenuQuantity; -import kitchenpos.products.domain.tobe.Product; - -public class MenuProductCreateRequest { - - private UUID productId; - - private MenuQuantity quantity; - - public MenuProductCreateRequest(UUID productId, MenuQuantity quantity) { - this.productId = productId; - this.quantity = quantity; - } - - public MenuProduct to(Product product) { - return new MenuProduct(product, quantity); - } - - public UUID getProductId() { - return productId; - } - - public MenuQuantity getQuantity() { - return quantity; - } -} diff --git a/src/main/java/kitchenpos/menus/ui/dto/MenuProductCreateRequests.java b/src/main/java/kitchenpos/menus/ui/dto/MenuProductCreateRequests.java deleted file mode 100644 index 83e511bfa..000000000 --- a/src/main/java/kitchenpos/menus/ui/dto/MenuProductCreateRequests.java +++ /dev/null @@ -1,35 +0,0 @@ -package kitchenpos.menus.ui.dto; - -import java.util.List; -import java.util.Objects; -import java.util.UUID; -import kitchenpos.products.domain.tobe.Product; - -public class MenuProductCreateRequests { - - private List menuProducts; - - public MenuProductCreateRequests(List menuProducts) { - if (Objects.isNull(menuProducts) || menuProducts.isEmpty()) { - throw new IllegalArgumentException(); - } - - this.menuProducts = menuProducts; - } - - public List getProductIds() { - return menuProducts.stream() - .map(MenuProductCreateRequest::getProductId) - .toList(); - } - - public void validateMenuProducts(List products) { - if (products.size() != menuProducts.size()) { - throw new IllegalArgumentException(); - } - } - - public List getMenuProducts() { - return menuProducts; - } -} diff --git a/src/main/java/kitchenpos/orders/common/application/OrderLineItemMapper.java b/src/main/java/kitchenpos/orders/common/application/OrderLineItemMapper.java new file mode 100644 index 000000000..1e34e28dd --- /dev/null +++ b/src/main/java/kitchenpos/orders/common/application/OrderLineItemMapper.java @@ -0,0 +1,64 @@ +package kitchenpos.orders.common.application; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.menus.domain.tobe.Menu; +import kitchenpos.orders.common.application.dto.OrderLineItemRequest; +import kitchenpos.orders.common.application.dto.OrderLineItemsRequest; +import kitchenpos.orders.common.domain.OrderType; +import kitchenpos.orders.common.domain.tobe.MenuQuantity; +import kitchenpos.orders.common.domain.tobe.OrderLineItem; +import kitchenpos.orders.common.domain.tobe.OrderLineItems; +import kitchenpos.orders.common.domain.tobe.OrderLineItemsValidator; +import org.springframework.stereotype.Component; + +@Component +public class OrderLineItemMapper { + + private final MenuRepository menuRepository; + private final OrderLineItemsValidator orderLineItemsValidator; + + public OrderLineItemMapper(MenuRepository menuRepository, + OrderLineItemsValidator orderLineItemsValidator) { + this.menuRepository = menuRepository; + this.orderLineItemsValidator = orderLineItemsValidator; + } + + public OrderLineItems map(OrderType orderType, OrderLineItemsRequest request) { + List menuIds = request.orderLineItems() + .stream().map(OrderLineItemRequest::menuId) + .toList(); + + List menus = menuRepository.findAllByIdIn(menuIds); + List orderLineItems = createOrderLineItems(orderType, request, menus); + orderLineItemsValidator.validate(orderLineItems, menus); + return new OrderLineItems(orderLineItems); + } + + private List createOrderLineItems(OrderType orderType, + OrderLineItemsRequest request, + List menus) { + return request.orderLineItems() + .stream() + .map(orderLineItem -> createOrderLineItem(menus, + orderLineItem.menuId(), + orderType, + orderLineItem.quantity()) + ) + .toList(); + } + + private OrderLineItem createOrderLineItem(List menus, UUID menuId, OrderType orderType, + long quantity) { + Menu menu = findMenu(menus, menuId); + MenuQuantity menuQuantity = new MenuQuantity(orderType, quantity); + return new OrderLineItem(menu, menuQuantity); + } + + private Menu findMenu(List menus, UUID menuId) { + return menus.stream().filter(menu -> menu.getId().equals(menuId)) + .findFirst().orElseThrow((NoSuchElementException::new)); + } +} diff --git a/src/main/java/kitchenpos/orders/common/application/OrderService.java b/src/main/java/kitchenpos/orders/common/application/OrderService.java index 8e2c4ab6f..e9a35f61f 100644 --- a/src/main/java/kitchenpos/orders/common/application/OrderService.java +++ b/src/main/java/kitchenpos/orders/common/application/OrderService.java @@ -15,8 +15,8 @@ import kitchenpos.orders.common.domain.OrderStatus; import kitchenpos.orders.common.domain.OrderType; import kitchenpos.orders.delivery.domain.KitchenridersClient; -import kitchenpos.orders.eatin.domain.OrderTable; -import kitchenpos.orders.eatin.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.tobe.OrderTable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -180,8 +180,7 @@ public Order complete(final UUID orderId) { final OrderTable orderTable = order.getOrderTable(); if (!orderRepository.existsByOrderTableAndStatusNot(orderTable, OrderStatus.COMPLETED)) { - orderTable.setNumberOfGuests(0); - orderTable.setOccupied(false); + orderTable.clear(); } } return order; diff --git a/src/main/java/kitchenpos/orders/common/application/dto/OrderLineItemRequest.java b/src/main/java/kitchenpos/orders/common/application/dto/OrderLineItemRequest.java new file mode 100644 index 000000000..480693155 --- /dev/null +++ b/src/main/java/kitchenpos/orders/common/application/dto/OrderLineItemRequest.java @@ -0,0 +1,9 @@ +package kitchenpos.orders.common.application.dto; + +import jakarta.validation.constraints.NotNull; +import java.util.UUID; + +public record OrderLineItemRequest(@NotNull UUID menuId, + long quantity) { + +} diff --git a/src/main/java/kitchenpos/orders/common/application/dto/OrderLineItemsRequest.java b/src/main/java/kitchenpos/orders/common/application/dto/OrderLineItemsRequest.java new file mode 100644 index 000000000..16f1cce00 --- /dev/null +++ b/src/main/java/kitchenpos/orders/common/application/dto/OrderLineItemsRequest.java @@ -0,0 +1,8 @@ +package kitchenpos.orders.common.application.dto; + +import jakarta.validation.constraints.NotEmpty; +import java.util.List; + +public record OrderLineItemsRequest(@NotEmpty List orderLineItems) { + +} diff --git a/src/main/java/kitchenpos/orders/common/domain/Order.java b/src/main/java/kitchenpos/orders/common/domain/Order.java index 6611a0876..eb91c5650 100644 --- a/src/main/java/kitchenpos/orders/common/domain/Order.java +++ b/src/main/java/kitchenpos/orders/common/domain/Order.java @@ -15,7 +15,7 @@ import java.time.LocalDateTime; import java.util.List; import java.util.UUID; -import kitchenpos.orders.eatin.domain.OrderTable; +import kitchenpos.orders.store.domain.tobe.OrderTable; @Table(name = "orders") @Entity diff --git a/src/main/java/kitchenpos/orders/common/domain/OrderRepository.java b/src/main/java/kitchenpos/orders/common/domain/OrderRepository.java index 7384b9f13..0a0bcfb27 100644 --- a/src/main/java/kitchenpos/orders/common/domain/OrderRepository.java +++ b/src/main/java/kitchenpos/orders/common/domain/OrderRepository.java @@ -3,7 +3,7 @@ import java.util.List; import java.util.Optional; import java.util.UUID; -import kitchenpos.orders.eatin.domain.OrderTable; +import kitchenpos.orders.store.domain.tobe.OrderTable; public interface OrderRepository { diff --git a/src/main/java/kitchenpos/orders/common/domain/tobe/MenuQuantity.java b/src/main/java/kitchenpos/orders/common/domain/tobe/MenuQuantity.java new file mode 100644 index 000000000..714420e36 --- /dev/null +++ b/src/main/java/kitchenpos/orders/common/domain/tobe/MenuQuantity.java @@ -0,0 +1,29 @@ +package kitchenpos.orders.common.domain.tobe; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import kitchenpos.orders.common.domain.OrderType; + +@Embeddable +public class MenuQuantity { + + @Column(name = "quantity", nullable = false) + private long quantity; + + protected MenuQuantity() { + } + + public MenuQuantity(OrderType type, long quantity) { + if (type != OrderType.EAT_IN) { + validateQuantity(quantity); + } + + this.quantity = quantity; + } + + private static void validateQuantity(long quantity) { + if (quantity < 0) { + throw new IllegalArgumentException(); + } + } +} diff --git a/src/main/java/kitchenpos/orders/common/domain/tobe/Order.java b/src/main/java/kitchenpos/orders/common/domain/tobe/Order.java new file mode 100644 index 000000000..a2ed44f94 --- /dev/null +++ b/src/main/java/kitchenpos/orders/common/domain/tobe/Order.java @@ -0,0 +1,81 @@ +package kitchenpos.orders.common.domain.tobe; + +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.Table; +import java.time.LocalDateTime; +import java.util.UUID; +import kitchenpos.orders.common.domain.OrderStatus; +import kitchenpos.orders.common.domain.OrderType; + +@Table(name = "orders") +@Entity +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn +public abstract class Order { + + @Column(name = "id", columnDefinition = "binary(16)") + @Id + private UUID id; + + @Column(name = "type", nullable = false, columnDefinition = "varchar(255)") + @Enumerated(EnumType.STRING) + private OrderType type; + + @Column(name = "status", nullable = false, columnDefinition = "varchar(255)") + @Enumerated(EnumType.STRING) + private OrderStatus status; + + @Column(name = "order_date_time", nullable = false) + private LocalDateTime orderDateTime; + + @Embedded + private OrderLineItems orderLineItems; + + protected Order() { + } + + public Order(OrderType type, OrderLineItems orderLineItems) { + this.id = UUID.randomUUID(); + this.type = type; + this.status = OrderStatus.WAITING; + this.orderDateTime = LocalDateTime.now(); + this.orderLineItems = orderLineItems; + } + + public void accept() { + if (status != OrderStatus.WAITING) { + throw new IllegalStateException(); + } + status = OrderStatus.ACCEPTED; + } + + public void serve() { + if (status != OrderStatus.ACCEPTED) { + throw new IllegalStateException(); + } + status = OrderStatus.SERVED; + } + + public void complete() { + if (status != OrderStatus.SERVED) { + throw new IllegalStateException(); + } + status = OrderStatus.COMPLETED; + } + + public UUID getId() { + return id; + } + + public OrderStatus getStatus() { + return status; + } +} diff --git a/src/main/java/kitchenpos/orders/common/domain/tobe/OrderLineItem.java b/src/main/java/kitchenpos/orders/common/domain/tobe/OrderLineItem.java new file mode 100644 index 000000000..3cf984c3d --- /dev/null +++ b/src/main/java/kitchenpos/orders/common/domain/tobe/OrderLineItem.java @@ -0,0 +1,41 @@ +package kitchenpos.orders.common.domain.tobe; + +import jakarta.persistence.Column; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import java.math.BigDecimal; +import java.util.UUID; +import kitchenpos.menus.domain.tobe.Menu; + +@Table(name = "order_line_item") +@Entity +public class OrderLineItem { + + @Column(name = "seq") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + private Long seq; + + private UUID menuId; + + private BigDecimal price; + + @Embedded + private MenuQuantity quantity; + + protected OrderLineItem() { + } + + public OrderLineItem(Menu menu, MenuQuantity quantity) { + if (!menu.isDisplayed()) { + throw new IllegalStateException(); + } + this.menuId = menu.getId(); + this.price = menu.getPrice(); + this.quantity = quantity; + } +} diff --git a/src/main/java/kitchenpos/orders/common/domain/tobe/OrderLineItems.java b/src/main/java/kitchenpos/orders/common/domain/tobe/OrderLineItems.java new file mode 100644 index 000000000..d06eba05e --- /dev/null +++ b/src/main/java/kitchenpos/orders/common/domain/tobe/OrderLineItems.java @@ -0,0 +1,32 @@ +package kitchenpos.orders.common.domain.tobe; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Embeddable; +import jakarta.persistence.ForeignKey; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; +import java.util.List; + +@Embeddable +public class OrderLineItems { + + @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) + @JoinColumn( + name = "order_id", + nullable = false, + columnDefinition = "binary(16)", + foreignKey = @ForeignKey(name = "fk_order_line_item_to_orders") + ) + private List orderLineItems; + + protected OrderLineItems() { + } + + public OrderLineItems(List orderLineItems) { + if (orderLineItems == null || orderLineItems.isEmpty()) { + throw new IllegalArgumentException(); + } + + this.orderLineItems = orderLineItems; + } +} diff --git a/src/main/java/kitchenpos/orders/common/domain/tobe/OrderLineItemsValidator.java b/src/main/java/kitchenpos/orders/common/domain/tobe/OrderLineItemsValidator.java new file mode 100644 index 000000000..d9d04ea31 --- /dev/null +++ b/src/main/java/kitchenpos/orders/common/domain/tobe/OrderLineItemsValidator.java @@ -0,0 +1,23 @@ +package kitchenpos.orders.common.domain.tobe; + +import java.util.List; +import kitchenpos.menus.domain.tobe.Menu; +import org.springframework.stereotype.Component; + +@Component +public class OrderLineItemsValidator { + + public void validate(List orderLineItems, List menus){ + if (orderLineItems == null || menus == null) { + throw new IllegalArgumentException(); + } + + if (orderLineItems.isEmpty() || menus.isEmpty()) { + throw new IllegalArgumentException(); + } + + if (orderLineItems.size() != menus.size()) { + throw new IllegalArgumentException(); + } + } +} diff --git a/src/main/java/kitchenpos/orders/eatin/application/OrderTableService.java b/src/main/java/kitchenpos/orders/store/application/OrderTableService.java similarity index 50% rename from src/main/java/kitchenpos/orders/eatin/application/OrderTableService.java rename to src/main/java/kitchenpos/orders/store/application/OrderTableService.java index d4aaa0f69..f17971e4d 100644 --- a/src/main/java/kitchenpos/orders/eatin/application/OrderTableService.java +++ b/src/main/java/kitchenpos/orders/store/application/OrderTableService.java @@ -1,13 +1,14 @@ -package kitchenpos.orders.eatin.application; +package kitchenpos.orders.store.application; import java.util.List; import java.util.NoSuchElementException; -import java.util.Objects; import java.util.UUID; -import kitchenpos.orders.common.domain.OrderRepository; import kitchenpos.orders.common.domain.OrderStatus; -import kitchenpos.orders.eatin.domain.OrderTable; -import kitchenpos.orders.eatin.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.StoreOrderRepository; +import kitchenpos.orders.store.domain.tobe.NumberOfGuests; +import kitchenpos.orders.store.domain.tobe.OrderTable; +import kitchenpos.orders.store.domain.tobe.OrderTableName; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -15,33 +16,24 @@ public class OrderTableService { private final OrderTableRepository orderTableRepository; - private final OrderRepository orderRepository; + private final StoreOrderRepository storeOrderRepository; public OrderTableService(final OrderTableRepository orderTableRepository, - final OrderRepository orderRepository) { + final StoreOrderRepository storeOrderRepository) { this.orderTableRepository = orderTableRepository; - this.orderRepository = orderRepository; + this.storeOrderRepository = storeOrderRepository; } @Transactional - public OrderTable create(final OrderTable request) { - final String name = request.getName(); - if (Objects.isNull(name) || name.isEmpty()) { - throw new IllegalArgumentException(); - } - final OrderTable orderTable = new OrderTable(); - orderTable.setId(UUID.randomUUID()); - orderTable.setName(name); - orderTable.setNumberOfGuests(0); - orderTable.setOccupied(false); - return orderTableRepository.save(orderTable); + public OrderTable create(final OrderTableName request) { + return orderTableRepository.save(new OrderTable(request)); } @Transactional public OrderTable sit(final UUID orderTableId) { final OrderTable orderTable = orderTableRepository.findById(orderTableId) .orElseThrow(NoSuchElementException::new); - orderTable.setOccupied(true); + orderTable.sit(); return orderTable; } @@ -49,26 +41,19 @@ public OrderTable sit(final UUID orderTableId) { public OrderTable clear(final UUID orderTableId) { final OrderTable orderTable = orderTableRepository.findById(orderTableId) .orElseThrow(NoSuchElementException::new); - if (orderRepository.existsByOrderTableAndStatusNot(orderTable, OrderStatus.COMPLETED)) { + if (storeOrderRepository.existsByOrderTableAndStatusNot(orderTable, + OrderStatus.COMPLETED)) { throw new IllegalStateException(); } - orderTable.setNumberOfGuests(0); - orderTable.setOccupied(false); + orderTable.clear(); return orderTable; } @Transactional - public OrderTable changeNumberOfGuests(final UUID orderTableId, final OrderTable request) { - final int numberOfGuests = request.getNumberOfGuests(); - if (numberOfGuests < 0) { - throw new IllegalArgumentException(); - } + public OrderTable changeNumberOfGuests(final UUID orderTableId, final NumberOfGuests request) { final OrderTable orderTable = orderTableRepository.findById(orderTableId) .orElseThrow(NoSuchElementException::new); - if (!orderTable.isOccupied()) { - throw new IllegalStateException(); - } - orderTable.setNumberOfGuests(numberOfGuests); + orderTable.changeNumberOfGuests(request); return orderTable; } diff --git a/src/main/java/kitchenpos/orders/store/application/StoreOrderService.java b/src/main/java/kitchenpos/orders/store/application/StoreOrderService.java new file mode 100644 index 000000000..256dd6739 --- /dev/null +++ b/src/main/java/kitchenpos/orders/store/application/StoreOrderService.java @@ -0,0 +1,76 @@ +package kitchenpos.orders.store.application; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import kitchenpos.orders.common.application.OrderLineItemMapper; +import kitchenpos.orders.common.domain.OrderType; +import kitchenpos.orders.common.domain.tobe.OrderLineItems; +import kitchenpos.orders.store.application.dto.StoreOrderCreateRequest; +import kitchenpos.orders.store.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.StoreOrderRepository; +import kitchenpos.orders.store.domain.tobe.OrderTable; +import kitchenpos.orders.store.domain.tobe.StoreOrder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class StoreOrderService { + + private final StoreOrderRepository storeOrderRepository; + private final OrderTableRepository orderTableRepository; + private final OrderLineItemMapper orderLineItemMapper; + + public StoreOrderService(StoreOrderRepository storeOrderRepository, + OrderTableRepository orderTableRepository, OrderLineItemMapper orderLineItemMapper) { + this.storeOrderRepository = storeOrderRepository; + this.orderTableRepository = orderTableRepository; + this.orderLineItemMapper = orderLineItemMapper; + } + + @Transactional + public StoreOrder create(final StoreOrderCreateRequest request) { + final OrderLineItems orderLineItems = orderLineItemMapper.map(OrderType.EAT_IN, + request.orderLineItemRequests()); + final OrderTable orderTable = orderTableRepository.findById(request.orderTableId()) + .orElseThrow(NoSuchElementException::new); + + final StoreOrder storeOrder = new StoreOrder(orderLineItems, orderTable); + return storeOrderRepository.save(storeOrder); + } + + @Transactional + public StoreOrder accept(final UUID orderId) { + final StoreOrder storeOrder = storeOrderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + + storeOrder.accept(); + + return storeOrder; + } + + @Transactional + public StoreOrder serve(final UUID orderId) { + final StoreOrder storeOrder = storeOrderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + + storeOrder.serve(); + + return storeOrder; + } + + @Transactional + public StoreOrder complete(final UUID orderId) { + final StoreOrder storeOrder = storeOrderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + + storeOrder.complete(); + + return storeOrder; + } + + @Transactional(readOnly = true) + public List findAll() { + return storeOrderRepository.findAll(); + } +} diff --git a/src/main/java/kitchenpos/orders/store/application/dto/StoreOrderCreateRequest.java b/src/main/java/kitchenpos/orders/store/application/dto/StoreOrderCreateRequest.java new file mode 100644 index 000000000..b4badfb43 --- /dev/null +++ b/src/main/java/kitchenpos/orders/store/application/dto/StoreOrderCreateRequest.java @@ -0,0 +1,10 @@ +package kitchenpos.orders.store.application.dto; + +import jakarta.validation.constraints.NotNull; +import java.util.UUID; +import kitchenpos.orders.common.application.dto.OrderLineItemsRequest; + +public record StoreOrderCreateRequest(@NotNull OrderLineItemsRequest orderLineItemRequests, + @NotNull UUID orderTableId) { + +} diff --git a/src/main/java/kitchenpos/orders/eatin/domain/OrderTable.java b/src/main/java/kitchenpos/orders/store/domain/OrderTable.java similarity index 96% rename from src/main/java/kitchenpos/orders/eatin/domain/OrderTable.java rename to src/main/java/kitchenpos/orders/store/domain/OrderTable.java index 0b0cf6ec8..8d40d54de 100644 --- a/src/main/java/kitchenpos/orders/eatin/domain/OrderTable.java +++ b/src/main/java/kitchenpos/orders/store/domain/OrderTable.java @@ -1,4 +1,4 @@ -package kitchenpos.orders.eatin.domain; +package kitchenpos.orders.store.domain; import jakarta.persistence.Column; import jakarta.persistence.Entity; diff --git a/src/main/java/kitchenpos/orders/eatin/domain/OrderTableRepository.java b/src/main/java/kitchenpos/orders/store/domain/OrderTableRepository.java similarity index 71% rename from src/main/java/kitchenpos/orders/eatin/domain/OrderTableRepository.java rename to src/main/java/kitchenpos/orders/store/domain/OrderTableRepository.java index 238d3a29f..bd8057ef1 100644 --- a/src/main/java/kitchenpos/orders/eatin/domain/OrderTableRepository.java +++ b/src/main/java/kitchenpos/orders/store/domain/OrderTableRepository.java @@ -1,8 +1,9 @@ -package kitchenpos.orders.eatin.domain; +package kitchenpos.orders.store.domain; import java.util.List; import java.util.Optional; import java.util.UUID; +import kitchenpos.orders.store.domain.tobe.OrderTable; public interface OrderTableRepository { diff --git a/src/main/java/kitchenpos/orders/store/domain/StoreOrderRepository.java b/src/main/java/kitchenpos/orders/store/domain/StoreOrderRepository.java new file mode 100644 index 000000000..abfe2bdd4 --- /dev/null +++ b/src/main/java/kitchenpos/orders/store/domain/StoreOrderRepository.java @@ -0,0 +1,20 @@ +package kitchenpos.orders.store.domain; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import kitchenpos.orders.common.domain.OrderStatus; +import kitchenpos.orders.store.domain.tobe.OrderTable; +import kitchenpos.orders.store.domain.tobe.StoreOrder; + +public interface StoreOrderRepository { + + StoreOrder save(StoreOrder order); + + Optional findById(UUID id); + + List findAll(); + + boolean existsByOrderTableAndStatusNot(OrderTable orderTable, OrderStatus status); +} + diff --git a/src/main/java/kitchenpos/orders/store/domain/tobe/NumberOfGuests.java b/src/main/java/kitchenpos/orders/store/domain/tobe/NumberOfGuests.java new file mode 100644 index 000000000..e42edda92 --- /dev/null +++ b/src/main/java/kitchenpos/orders/store/domain/tobe/NumberOfGuests.java @@ -0,0 +1,43 @@ +package kitchenpos.orders.store.domain.tobe; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import java.util.Objects; + +@Embeddable +public class NumberOfGuests { + + @Column(name = "number_of_guests", nullable = false) + private int numberOfGuests; + + protected NumberOfGuests() { + } + + public NumberOfGuests(int numberOfGuests) { + if (numberOfGuests < 0) { + throw new IllegalArgumentException(); + } + this.numberOfGuests = numberOfGuests; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + NumberOfGuests that = (NumberOfGuests) o; + return numberOfGuests == that.numberOfGuests; + } + + @Override + public int hashCode() { + return Objects.hashCode(numberOfGuests); + } + + public int getNumberOfGuests() { + return numberOfGuests; + } +} diff --git a/src/main/java/kitchenpos/orders/store/domain/tobe/OrderTable.java b/src/main/java/kitchenpos/orders/store/domain/tobe/OrderTable.java new file mode 100644 index 000000000..799a02231 --- /dev/null +++ b/src/main/java/kitchenpos/orders/store/domain/tobe/OrderTable.java @@ -0,0 +1,72 @@ +package kitchenpos.orders.store.domain.tobe; + +import jakarta.persistence.Column; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import java.util.UUID; + +@Table(name = "order_table") +@Entity +public class OrderTable { + + @Column(name = "id", columnDefinition = "binary(16)") + @Id + private UUID id; + + @Embedded + private OrderTableName name; + + @Embedded + private NumberOfGuests numberOfGuests; + + @Column(name = "occupied", nullable = false) + private boolean occupied; + + protected OrderTable() { + } + + public OrderTable(String name) { + this(new OrderTableName(name)); + } + + public OrderTable(OrderTableName name) { + this.id = UUID.randomUUID(); + this.name = name; + this.numberOfGuests = new NumberOfGuests(0); + this.occupied = false; + } + + public void sit() { + this.occupied = true; + } + + public void clear() { + this.numberOfGuests = new NumberOfGuests(0); + this.occupied = false; + } + + public void changeNumberOfGuests(NumberOfGuests numberOfGuests) { + if (!isOccupied()) { + throw new IllegalStateException(); + } + this.numberOfGuests = numberOfGuests; + } + + public boolean isOccupied() { + return occupied; + } + + public boolean hasGuest() { + return numberOfGuests.getNumberOfGuests() > 0; + } + + public UUID getId() { + return id; + } + + public int getNumberOfGuests() { + return numberOfGuests.getNumberOfGuests(); + } +} diff --git a/src/main/java/kitchenpos/orders/store/domain/tobe/OrderTableName.java b/src/main/java/kitchenpos/orders/store/domain/tobe/OrderTableName.java new file mode 100644 index 000000000..524d0bd0b --- /dev/null +++ b/src/main/java/kitchenpos/orders/store/domain/tobe/OrderTableName.java @@ -0,0 +1,40 @@ +package kitchenpos.orders.store.domain.tobe; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import java.util.Objects; + +@Embeddable +public class OrderTableName { + + @Column(name = "name", nullable = false) + private String name; + + protected OrderTableName() { + } + + public OrderTableName(String name) { + if (Objects.isNull(name) || name.isEmpty()) { + throw new IllegalArgumentException(); + } + + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OrderTableName that = (OrderTableName) o; + return Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hashCode(name); + } +} diff --git a/src/main/java/kitchenpos/orders/store/domain/tobe/StoreOrder.java b/src/main/java/kitchenpos/orders/store/domain/tobe/StoreOrder.java new file mode 100644 index 000000000..a6b2b05cd --- /dev/null +++ b/src/main/java/kitchenpos/orders/store/domain/tobe/StoreOrder.java @@ -0,0 +1,46 @@ +package kitchenpos.orders.store.domain.tobe; + +import jakarta.persistence.Entity; +import jakarta.persistence.ForeignKey; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import java.util.List; +import kitchenpos.menus.domain.tobe.Menu; +import kitchenpos.orders.common.domain.OrderType; +import kitchenpos.orders.common.domain.tobe.Order; +import kitchenpos.orders.common.domain.tobe.OrderLineItem; +import kitchenpos.orders.common.domain.tobe.OrderLineItems; + +@Entity +public class StoreOrder extends Order { + + @ManyToOne + @JoinColumn( + name = "order_table_id", + columnDefinition = "binary(16)", + foreignKey = @ForeignKey(name = "fk_orders_to_order_table") + ) + private OrderTable orderTable; + + protected StoreOrder() { + } + + public StoreOrder(OrderLineItems orderLineItems, OrderTable orderTable) { + super(OrderType.EAT_IN, orderLineItems); + + if (!orderTable.isOccupied()) { + throw new IllegalStateException(); + } + this.orderTable = orderTable; + } + + @Override + public void complete() { + super.complete(); + orderTable.clear(); + } + + public OrderTable getOrderTable() { + return orderTable; + } +} diff --git a/src/main/java/kitchenpos/orders/eatin/infra/JpaOrderTableRepository.java b/src/main/java/kitchenpos/orders/store/infra/JpaOrderTableRepository.java similarity index 56% rename from src/main/java/kitchenpos/orders/eatin/infra/JpaOrderTableRepository.java rename to src/main/java/kitchenpos/orders/store/infra/JpaOrderTableRepository.java index aae2b57ea..9836d4205 100644 --- a/src/main/java/kitchenpos/orders/eatin/infra/JpaOrderTableRepository.java +++ b/src/main/java/kitchenpos/orders/store/infra/JpaOrderTableRepository.java @@ -1,8 +1,8 @@ -package kitchenpos.orders.eatin.infra; +package kitchenpos.orders.store.infra; import java.util.UUID; -import kitchenpos.orders.eatin.domain.OrderTable; -import kitchenpos.orders.eatin.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.tobe.OrderTable; import org.springframework.data.jpa.repository.JpaRepository; public interface JpaOrderTableRepository extends OrderTableRepository, diff --git a/src/main/java/kitchenpos/orders/store/infra/JpaStoreOrderRepository.java b/src/main/java/kitchenpos/orders/store/infra/JpaStoreOrderRepository.java new file mode 100644 index 000000000..415788b6d --- /dev/null +++ b/src/main/java/kitchenpos/orders/store/infra/JpaStoreOrderRepository.java @@ -0,0 +1,11 @@ +package kitchenpos.orders.store.infra; + +import java.util.UUID; +import kitchenpos.orders.store.domain.StoreOrderRepository; +import kitchenpos.orders.store.domain.tobe.StoreOrder; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface JpaStoreOrderRepository extends StoreOrderRepository, + JpaRepository { + +} diff --git a/src/main/java/kitchenpos/orders/eatin/ui/OrderTableRestController.java b/src/main/java/kitchenpos/orders/store/ui/OrderTableRestController.java similarity index 84% rename from src/main/java/kitchenpos/orders/eatin/ui/OrderTableRestController.java rename to src/main/java/kitchenpos/orders/store/ui/OrderTableRestController.java index 320291d5a..7ad623a68 100644 --- a/src/main/java/kitchenpos/orders/eatin/ui/OrderTableRestController.java +++ b/src/main/java/kitchenpos/orders/store/ui/OrderTableRestController.java @@ -1,10 +1,12 @@ -package kitchenpos.orders.eatin.ui; +package kitchenpos.orders.store.ui; import java.net.URI; import java.util.List; import java.util.UUID; -import kitchenpos.orders.eatin.application.OrderTableService; -import kitchenpos.orders.eatin.domain.OrderTable; +import kitchenpos.orders.store.application.OrderTableService; +import kitchenpos.orders.store.domain.tobe.NumberOfGuests; +import kitchenpos.orders.store.domain.tobe.OrderTable; +import kitchenpos.orders.store.domain.tobe.OrderTableName; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -25,7 +27,7 @@ public OrderTableRestController(final OrderTableService orderTableService) { } @PostMapping - public ResponseEntity create(@RequestBody final OrderTable request) { + public ResponseEntity create(@RequestBody final OrderTableName request) { final OrderTable response = orderTableService.create(request); return ResponseEntity.created(URI.create("/api/order-tables/" + response.getId())) .body(response); @@ -44,7 +46,7 @@ public ResponseEntity clear(@PathVariable final UUID orderTableId) { @PutMapping("/{orderTableId}/number-of-guests") public ResponseEntity changeNumberOfGuests( @PathVariable final UUID orderTableId, - @RequestBody final OrderTable request + @RequestBody final NumberOfGuests request ) { return ResponseEntity.ok(orderTableService.changeNumberOfGuests(orderTableId, request)); } diff --git a/src/main/java/kitchenpos/orders/store/ui/StoreOrderRestController.java b/src/main/java/kitchenpos/orders/store/ui/StoreOrderRestController.java new file mode 100644 index 000000000..680f3b387 --- /dev/null +++ b/src/main/java/kitchenpos/orders/store/ui/StoreOrderRestController.java @@ -0,0 +1,56 @@ +package kitchenpos.orders.store.ui; + +import jakarta.validation.Valid; +import java.net.URI; +import java.util.List; +import java.util.UUID; +import kitchenpos.orders.store.application.StoreOrderService; +import kitchenpos.orders.store.application.dto.StoreOrderCreateRequest; +import kitchenpos.orders.store.domain.tobe.StoreOrder; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequestMapping("/api/store-orders") +@RestController +public class StoreOrderRestController { + + private final StoreOrderService storeOrderService; + + public StoreOrderRestController(final StoreOrderService storeOrderService) { + this.storeOrderService = storeOrderService; + } + + @PostMapping + public ResponseEntity create( + @RequestBody @Valid final StoreOrderCreateRequest request) { + StoreOrder response = storeOrderService.create(request); + return ResponseEntity.created(URI.create("/api/store-orders/" + response.getId())) + .body(response); + } + + @PutMapping("/{orderId}/accept") + public ResponseEntity accept(@PathVariable final UUID orderId) { + return ResponseEntity.ok(storeOrderService.accept(orderId)); + } + + @PutMapping("/{orderId}/serve") + public ResponseEntity serve(@PathVariable final UUID orderId) { + return ResponseEntity.ok(storeOrderService.serve(orderId)); + } + + @PutMapping("/{orderId}/complete") + public ResponseEntity complete(@PathVariable final UUID orderId) { + return ResponseEntity.ok(storeOrderService.complete(orderId)); + } + + @GetMapping + public ResponseEntity> findAll() { + return ResponseEntity.ok(storeOrderService.findAll()); + } +} diff --git a/src/main/java/kitchenpos/products/application/ProductService.java b/src/main/java/kitchenpos/products/application/ProductService.java index f18ff03af..4aca4c984 100644 --- a/src/main/java/kitchenpos/products/application/ProductService.java +++ b/src/main/java/kitchenpos/products/application/ProductService.java @@ -3,14 +3,13 @@ import java.util.List; import java.util.NoSuchElementException; import java.util.UUID; -import kitchenpos.menus.application.MenuProductsService; import kitchenpos.menus.domain.MenuRepository; import kitchenpos.menus.domain.tobe.Menu; +import kitchenpos.products.application.dto.ProductCreateRequest; import kitchenpos.products.domain.ProductRepository; import kitchenpos.products.domain.ProfanityValidator; import kitchenpos.products.domain.tobe.Product; import kitchenpos.products.domain.tobe.ProductPrice; -import kitchenpos.products.ui.dto.ProductCreateRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -19,19 +18,15 @@ public class ProductService { private final ProductRepository productRepository; private final MenuRepository menuRepository; - - private final MenuProductsService menuProductsService; private final ProfanityValidator profanityValidator; public ProductService( final ProductRepository productRepository, final MenuRepository menuRepository, - final MenuProductsService menuProductsService, final ProfanityValidator profanityValidator ) { this.productRepository = productRepository; this.menuRepository = menuRepository; - this.menuProductsService = menuProductsService; this.profanityValidator = profanityValidator; } @@ -48,12 +43,7 @@ public Product changePrice(final UUID productId, final ProductPrice request) { product.changePrice(request); final List menus = menuRepository.findAllByProductId(productId); - menus.forEach(menu -> { - if (menuProductsService.isOverThanProductSumPrice(menu.getMenuProducts(), - menu.getMenuPrice())) { - menu.hide(); - } - }); + menus.forEach(menu -> menu.changeMenuProductPrice(productId, request)); return product; } diff --git a/src/main/java/kitchenpos/products/ui/dto/ProductCreateRequest.java b/src/main/java/kitchenpos/products/application/dto/ProductCreateRequest.java similarity index 94% rename from src/main/java/kitchenpos/products/ui/dto/ProductCreateRequest.java rename to src/main/java/kitchenpos/products/application/dto/ProductCreateRequest.java index df63c6b42..6a8372bf1 100644 --- a/src/main/java/kitchenpos/products/ui/dto/ProductCreateRequest.java +++ b/src/main/java/kitchenpos/products/application/dto/ProductCreateRequest.java @@ -1,4 +1,4 @@ -package kitchenpos.products.ui.dto; +package kitchenpos.products.application.dto; import java.math.BigDecimal; import kitchenpos.products.domain.ProfanityValidator; diff --git a/src/main/java/kitchenpos/products/domain/tobe/Product.java b/src/main/java/kitchenpos/products/domain/tobe/Product.java index 325149346..e2f72ced6 100644 --- a/src/main/java/kitchenpos/products/domain/tobe/Product.java +++ b/src/main/java/kitchenpos/products/domain/tobe/Product.java @@ -30,6 +30,10 @@ public Product(String name, BigDecimal price) { this(new ProductName(name), new ProductPrice(price)); } + public Product(UUID uuid, String name, BigDecimal price) { + this(uuid, new ProductName(name), new ProductPrice(price)); + } + public Product(ProductName name, ProductPrice price) { this(UUID.randomUUID(), name, price); } diff --git a/src/main/java/kitchenpos/products/ui/ProductRestController.java b/src/main/java/kitchenpos/products/ui/ProductRestController.java index c5bc047e3..9ed3cbe0f 100644 --- a/src/main/java/kitchenpos/products/ui/ProductRestController.java +++ b/src/main/java/kitchenpos/products/ui/ProductRestController.java @@ -4,9 +4,9 @@ import java.util.List; import java.util.UUID; import kitchenpos.products.application.ProductService; +import kitchenpos.products.application.dto.ProductCreateRequest; import kitchenpos.products.domain.tobe.Product; import kitchenpos.products.domain.tobe.ProductPrice; -import kitchenpos.products.ui.dto.ProductCreateRequest; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; diff --git a/src/test/java/kitchenpos/fake/InMemoryOrderRepository.java b/src/test/java/kitchenpos/fake/InMemoryOrderRepository.java index e41d0ffa9..6caee9d66 100644 --- a/src/test/java/kitchenpos/fake/InMemoryOrderRepository.java +++ b/src/test/java/kitchenpos/fake/InMemoryOrderRepository.java @@ -8,7 +8,7 @@ import kitchenpos.orders.common.domain.Order; import kitchenpos.orders.common.domain.OrderRepository; import kitchenpos.orders.common.domain.OrderStatus; -import kitchenpos.orders.eatin.domain.OrderTable; +import kitchenpos.orders.store.domain.tobe.OrderTable; public class InMemoryOrderRepository implements OrderRepository { diff --git a/src/test/java/kitchenpos/fake/InMemoryOrderTableRepository.java b/src/test/java/kitchenpos/fake/InMemoryOrderTableRepository.java index 783fc47e5..058676a20 100644 --- a/src/test/java/kitchenpos/fake/InMemoryOrderTableRepository.java +++ b/src/test/java/kitchenpos/fake/InMemoryOrderTableRepository.java @@ -5,8 +5,8 @@ import java.util.List; import java.util.Optional; import java.util.UUID; -import kitchenpos.orders.eatin.domain.OrderTable; -import kitchenpos.orders.eatin.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.tobe.OrderTable; public class InMemoryOrderTableRepository implements OrderTableRepository { diff --git a/src/test/java/kitchenpos/fake/InMemoryStoreOrderRepository.java b/src/test/java/kitchenpos/fake/InMemoryStoreOrderRepository.java new file mode 100644 index 000000000..016c1f9e2 --- /dev/null +++ b/src/test/java/kitchenpos/fake/InMemoryStoreOrderRepository.java @@ -0,0 +1,47 @@ +package kitchenpos.fake; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import kitchenpos.orders.common.domain.OrderStatus; +import kitchenpos.orders.store.domain.StoreOrderRepository; +import kitchenpos.orders.store.domain.tobe.OrderTable; +import kitchenpos.orders.store.domain.tobe.StoreOrder; + +public class InMemoryStoreOrderRepository implements StoreOrderRepository { + + private final HashMap orders = new HashMap<>(); + + @Override + public StoreOrder save(StoreOrder entity) { + orders.put(entity.getId(), entity); + return entity; + } + + @Override + public Optional findById(UUID id) { + return Optional.ofNullable(orders.get(id)); + } + + @Override + public List findAll() { + return new ArrayList<>(orders.values()); + } + + @Override + public boolean existsByOrderTableAndStatusNot(OrderTable orderTable, OrderStatus status) { + return orders.values().stream() + .anyMatch(order -> isEqualOrderTable(order, orderTable) + && !isStatus(order, status)); + } + + private boolean isEqualOrderTable(StoreOrder order, OrderTable orderTable) { + return order.getOrderTable().getId().equals(orderTable.getId()); + } + + private boolean isStatus(StoreOrder order, OrderStatus status) { + return order.getStatus().equals(status); + } +} diff --git a/src/test/java/kitchenpos/fixture/MenuFixture.java b/src/test/java/kitchenpos/fixture/MenuFixture.java index 131b98588..c543098ab 100644 --- a/src/test/java/kitchenpos/fixture/MenuFixture.java +++ b/src/test/java/kitchenpos/fixture/MenuFixture.java @@ -2,42 +2,42 @@ import java.math.BigDecimal; import java.util.List; +import kitchenpos.menugroups.domain.tobe.MenuGroup; +import kitchenpos.menus.application.dto.MenuCreateRequest; +import kitchenpos.menus.application.dto.MenuProductsCreateRequest; import kitchenpos.menus.domain.tobe.DisplayedMenu; import kitchenpos.menus.domain.tobe.Menu; import kitchenpos.menus.domain.tobe.MenuName; import kitchenpos.menus.domain.tobe.MenuPrice; import kitchenpos.menus.domain.tobe.MenuProduct; import kitchenpos.menus.domain.tobe.MenuProducts; -import kitchenpos.menus.domain.tobe.MenuQuantity; -import kitchenpos.menugroups.domain.tobe.MenuGroup; -import kitchenpos.menus.ui.dto.MenuCreateRequest; -import kitchenpos.menus.ui.dto.MenuProductCreateRequests; +import kitchenpos.menus.domain.tobe.ProductQuantity; import kitchenpos.products.domain.tobe.Product; public class MenuFixture { public static MenuCreateRequest createRequest(Long price, MenuGroup menuGroup, Product product, - Integer quantity) { + Integer quantity) { return createRequest("후라이드1+1", price, menuGroup, true, product, quantity); } public static MenuCreateRequest createRequest(String name, Long price, MenuGroup menuGroup, - Product product, - Integer quantity) { + Product product, + Integer quantity) { return createRequest(name, price, menuGroup, true, product, quantity); } public static MenuCreateRequest createRequest(String name, Long price, MenuGroup menuGroup, - Boolean displayed, Product product, Integer quantity) { + Boolean displayed, Product product, Integer quantity) { MenuName menuName = new MenuName(name); MenuPrice menuPrice = new MenuPrice(BigDecimal.valueOf(price)); DisplayedMenu displayedMenu = new DisplayedMenu(displayed); - MenuProductCreateRequests menuProducts = MenuProductFixture.createRequests(product, - quantity); + MenuProductsCreateRequest menuProducts = MenuProductFixture.createRequests(product, + quantity); if (menuGroup != null) { return new MenuCreateRequest(menuName, menuPrice, menuGroup.getId(), displayedMenu, - menuProducts); + menuProducts); } return new MenuCreateRequest(menuName, menuPrice, null, displayedMenu, menuProducts); @@ -48,11 +48,25 @@ public static MenuPrice changePriceRequest(Long price) { } public static Menu createFriedOnePlusOne(MenuGroup menuGroup, Product product) { + return createFriedOnePlusOne(menuGroup, product, 30_000L); + } + + public static Menu createFriedOnePlusOne(MenuGroup menuGroup, Product product, Long price) { MenuName menuName = new MenuName("후라이드1+1"); - MenuPrice menuPrice = new MenuPrice(BigDecimal.valueOf(30_000L)); + MenuPrice menuPrice = new MenuPrice(BigDecimal.valueOf(price)); + DisplayedMenu displayedMenu = new DisplayedMenu(true); + MenuProducts menuProducts = new MenuProducts( + List.of(new MenuProduct(product, new ProductQuantity(2)))); + + return new Menu(menuName, menuPrice, menuGroup, displayedMenu, menuProducts); + } + + public static Menu SeasonedOnePlusOne(MenuGroup menuGroup, Product product) { + MenuName menuName = new MenuName("양념1+1"); + MenuPrice menuPrice = new MenuPrice(BigDecimal.valueOf(35_000L)); DisplayedMenu displayedMenu = new DisplayedMenu(true); MenuProducts menuProducts = new MenuProducts( - List.of(new MenuProduct(product, new MenuQuantity(2)))); + List.of(new MenuProduct(product, new ProductQuantity(2)))); return new Menu(menuName, menuPrice, menuGroup, displayedMenu, menuProducts); } diff --git a/src/test/java/kitchenpos/fixture/MenuProductFixture.java b/src/test/java/kitchenpos/fixture/MenuProductFixture.java index 8d982ba45..b34548138 100644 --- a/src/test/java/kitchenpos/fixture/MenuProductFixture.java +++ b/src/test/java/kitchenpos/fixture/MenuProductFixture.java @@ -1,24 +1,25 @@ package kitchenpos.fixture; import java.util.List; +import kitchenpos.menus.application.dto.MenuProductCreateRequest; +import kitchenpos.menus.application.dto.MenuProductsCreateRequest; import kitchenpos.menus.domain.tobe.MenuProduct; -import kitchenpos.menus.domain.tobe.MenuQuantity; -import kitchenpos.menus.ui.dto.MenuProductCreateRequest; -import kitchenpos.menus.ui.dto.MenuProductCreateRequests; +import kitchenpos.menus.domain.tobe.ProductQuantity; import kitchenpos.products.domain.tobe.Product; public class MenuProductFixture { - public static MenuProductCreateRequests createRequests(Product product, Integer quantity) { - return new MenuProductCreateRequests( - List.of(new MenuProductCreateRequest(product.getId(), new MenuQuantity(quantity)))); + public static MenuProductsCreateRequest createRequests(Product product, Integer quantity) { + return new MenuProductsCreateRequest( + List.of(new MenuProductCreateRequest(product.getId(), + new ProductQuantity(quantity)))); } public static MenuProduct createFired(long quantity) { - return new MenuProduct(ProductFixture.createFired(), new MenuQuantity(quantity)); + return new MenuProduct(ProductFixture.createFired(), new ProductQuantity(quantity)); } public static MenuProduct createSeasoned(long quantity) { - return new MenuProduct(ProductFixture.createSeasoned(), new MenuQuantity(quantity)); + return new MenuProduct(ProductFixture.createSeasoned(), new ProductQuantity(quantity)); } } diff --git a/src/test/java/kitchenpos/fixture/OrderFixture.java b/src/test/java/kitchenpos/fixture/OrderFixture.java index 50100a8b5..0b14316bd 100644 --- a/src/test/java/kitchenpos/fixture/OrderFixture.java +++ b/src/test/java/kitchenpos/fixture/OrderFixture.java @@ -1,13 +1,11 @@ package kitchenpos.fixture; import java.util.List; -import java.util.UUID; import kitchenpos.menus.domain.tobe.Menu; import kitchenpos.orders.common.domain.Order; import kitchenpos.orders.common.domain.OrderLineItem; -import kitchenpos.orders.common.domain.OrderStatus; import kitchenpos.orders.common.domain.OrderType; -import kitchenpos.orders.eatin.domain.OrderTable; +import kitchenpos.orders.store.domain.tobe.OrderTable; public class OrderFixture { @@ -51,14 +49,4 @@ public static OrderLineItem createOrderLineItem(Menu menu, Integer quantity) { orderLineItem.setPrice(menu.getPrice()); return orderLineItem; } - - public static Order createEatIn(OrderTable orderTable, Menu menu) { - Order order = new Order(); - order.setId(UUID.randomUUID()); - order.setType(OrderType.EAT_IN); - order.setOrderTable(orderTable); - order.setOrderLineItems(List.of(createOrderLineItem(menu, 2))); - order.setStatus(OrderStatus.WAITING); - return order; - } } diff --git a/src/test/java/kitchenpos/fixture/OrderTableFixture.java b/src/test/java/kitchenpos/fixture/OrderTableFixture.java index fe6f24630..fc3238b86 100644 --- a/src/test/java/kitchenpos/fixture/OrderTableFixture.java +++ b/src/test/java/kitchenpos/fixture/OrderTableFixture.java @@ -1,26 +1,10 @@ package kitchenpos.fixture; -import java.util.UUID; -import kitchenpos.orders.eatin.domain.OrderTable; +import kitchenpos.orders.store.domain.tobe.OrderTable; public class OrderTableFixture { - public static OrderTable createRequest(final String name) { - OrderTable orderTable = new OrderTable(); - orderTable.setName(name); - return orderTable; - } - - public static OrderTable changeNumberOfGuestsRequest(final int numberOfGuests) { - OrderTable orderTable = new OrderTable(); - orderTable.setNumberOfGuests(numberOfGuests); - return orderTable; - } - public static OrderTable createNumber1() { - OrderTable orderTable = new OrderTable(); - orderTable.setId(UUID.randomUUID()); - orderTable.setName("1번 테이블"); - return orderTable; + return new OrderTable("1번 테이블"); } } diff --git a/src/test/java/kitchenpos/fixture/ProductFixture.java b/src/test/java/kitchenpos/fixture/ProductFixture.java index 0eff22dab..3533a23a5 100644 --- a/src/test/java/kitchenpos/fixture/ProductFixture.java +++ b/src/test/java/kitchenpos/fixture/ProductFixture.java @@ -1,8 +1,8 @@ package kitchenpos.fixture; import java.math.BigDecimal; +import kitchenpos.products.application.dto.ProductCreateRequest; import kitchenpos.products.domain.tobe.Product; -import kitchenpos.products.ui.dto.ProductCreateRequest; public class ProductFixture { @@ -19,7 +19,11 @@ public static ProductCreateRequest createRequest(final String name, final long p } public static Product createFired() { - return new Product("후라이드", BigDecimal.valueOf(20_000L)); + return createFired(20_000L); + } + + public static Product createFired(Long price) { + return new Product("후라이드", BigDecimal.valueOf(price)); } public static Product createSeasoned() { diff --git a/src/test/java/kitchenpos/fixture/StoreOrderFixture.java b/src/test/java/kitchenpos/fixture/StoreOrderFixture.java new file mode 100644 index 000000000..7a7c9fb51 --- /dev/null +++ b/src/test/java/kitchenpos/fixture/StoreOrderFixture.java @@ -0,0 +1,37 @@ +package kitchenpos.fixture; + +import java.util.Arrays; +import java.util.List; +import kitchenpos.menus.domain.tobe.Menu; +import kitchenpos.orders.common.domain.OrderType; +import kitchenpos.orders.common.domain.tobe.MenuQuantity; +import kitchenpos.orders.common.domain.tobe.OrderLineItem; +import kitchenpos.orders.common.domain.tobe.OrderLineItems; +import kitchenpos.orders.store.domain.tobe.OrderTable; +import kitchenpos.orders.store.domain.tobe.StoreOrder; + +public class StoreOrderFixture { + + public static StoreOrder createStoreOrder() { + OrderTable orderTable = OrderTableFixture.createNumber1(); + orderTable.sit(); + + Menu menu = MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), + ProductFixture.createFired()); + return new StoreOrder(createOrderLineItems(menu), orderTable); + } + + public static StoreOrder createStoreOrder(OrderTable orderTable, Menu... menu) { + return new StoreOrder(createOrderLineItems(menu), orderTable); + } + + public static OrderLineItems createOrderLineItems(Menu... menu) { + List orderLineItems = Arrays.stream(menu) + .map(StoreOrderFixture::createOrderLineItem).toList(); + return new OrderLineItems(orderLineItems); + } + + public static OrderLineItem createOrderLineItem(Menu menu) { + return new OrderLineItem(menu, new MenuQuantity(OrderType.EAT_IN, 1)); + } +} diff --git a/src/test/java/kitchenpos/menugroups/application/MenuGroupServiceTest.java b/src/test/java/kitchenpos/menugroups/application/MenuGroupServiceTest.java index dd6b0de99..1bb18bd7d 100644 --- a/src/test/java/kitchenpos/menugroups/application/MenuGroupServiceTest.java +++ b/src/test/java/kitchenpos/menugroups/application/MenuGroupServiceTest.java @@ -5,7 +5,6 @@ import java.util.List; import kitchenpos.fake.InMemoryMenuGroupRepository; -import kitchenpos.menugroups.application.MenuGroupService; import kitchenpos.menugroups.domain.MenuGroupRepository; import kitchenpos.menugroups.domain.tobe.MenuGroup; import kitchenpos.menugroups.domain.tobe.MenuGroupName; diff --git a/src/test/java/kitchenpos/menugroups/domain/tobe/MenuGroupTest.java b/src/test/java/kitchenpos/menugroups/domain/tobe/MenuGroupTest.java index 09487ddca..98cfb4202 100644 --- a/src/test/java/kitchenpos/menugroups/domain/tobe/MenuGroupTest.java +++ b/src/test/java/kitchenpos/menugroups/domain/tobe/MenuGroupTest.java @@ -3,7 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import kitchenpos.menugroups.domain.tobe.MenuGroup; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; diff --git a/src/test/java/kitchenpos/menus/application/MenuProductsServiceTest.java b/src/test/java/kitchenpos/menus/application/MenuProductsServiceTest.java deleted file mode 100644 index 20143817d..000000000 --- a/src/test/java/kitchenpos/menus/application/MenuProductsServiceTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package kitchenpos.menus.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import java.math.BigDecimal; -import java.util.List; -import kitchenpos.fake.InMemoryProductRepository; -import kitchenpos.fixture.MenuProductFixture; -import kitchenpos.fixture.ProductFixture; -import kitchenpos.menus.domain.tobe.MenuPrice; -import kitchenpos.menus.domain.tobe.MenuProducts; -import kitchenpos.menus.ui.dto.MenuProductCreateRequests; -import kitchenpos.products.domain.ProductRepository; -import kitchenpos.products.domain.tobe.Product; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; -import org.junit.jupiter.api.Test; - -@DisplayName("MenuProductsService") -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -class MenuProductsServiceTest { - - private ProductRepository productRepository = new InMemoryProductRepository(); - - private MenuProductsService menuProductsService; - - @BeforeEach - void setUp() { - menuProductsService = new MenuProductsService(productRepository); - } - - @Test - void 메뉴상품들을_생성한다() { - MenuProductCreateRequests createRequests = MenuProductFixture.createRequests( - createFriedProduct(), 2); - - MenuProducts actual = menuProductsService.create(createRequests, - new MenuPrice(BigDecimal.valueOf(30_000L))); - - assertThat(actual.getMenuProducts()).isNotEmpty(); - } - - @Test - void 메뉴상품들_생성시_메뉴상품들이_null일_경우_예외를_던진다() { - assertThatThrownBy(() -> menuProductsService.create(new MenuProductCreateRequests(null), - new MenuPrice(BigDecimal.valueOf(30_000L)))) - .isInstanceOf(IllegalArgumentException.class); - } - - @Test - void 메뉴상품들_생성시_메뉴상품들이_비어있을_경우_예외를_던진다() { - assertThatThrownBy( - () -> menuProductsService.create(new MenuProductCreateRequests(List.of()), - new MenuPrice(BigDecimal.valueOf(30_000L)))) - .isInstanceOf(IllegalArgumentException.class); - } - - @Test - void 메뉴상품들_생성시_메뉴가격이_메뉴상품들의_가격합보다_클_경우_예외를_던진다() { - MenuProductCreateRequests createRequests = MenuProductFixture.createRequests( - createFriedProduct(), 2); - - assertThatThrownBy(() -> menuProductsService.create(createRequests, - new MenuPrice(BigDecimal.valueOf(50_000L)))) - .isInstanceOf(IllegalArgumentException.class); - } - - @Test - void 메뉴상품들_생성시_메뉴가격이_메뉴상품들의_가격합보다_큰지_여부를_확인한다() { - MenuProductCreateRequests createRequests = MenuProductFixture.createRequests( - createFriedProduct(), 2); - MenuProducts menuProducts = menuProductsService.create(createRequests, - new MenuPrice(BigDecimal.valueOf(40_000L))); - - boolean actual = menuProductsService.isOverThanProductSumPrice( - menuProducts.getMenuProducts(), - new MenuPrice(BigDecimal.valueOf(50_000L))); - - assertThat(actual).isTrue(); - } - - private Product createFriedProduct() { - return productRepository.save(ProductFixture.createFired()); - } -} \ No newline at end of file diff --git a/src/test/java/kitchenpos/menus/application/MenuServiceTest.java b/src/test/java/kitchenpos/menus/application/MenuServiceTest.java index 447600a27..4e1786c34 100644 --- a/src/test/java/kitchenpos/menus/application/MenuServiceTest.java +++ b/src/test/java/kitchenpos/menus/application/MenuServiceTest.java @@ -15,11 +15,12 @@ import kitchenpos.fixture.MenuGroupFixture; import kitchenpos.fixture.ProductFixture; import kitchenpos.menugroups.domain.MenuGroupRepository; +import kitchenpos.menugroups.domain.tobe.MenuGroup; +import kitchenpos.menus.application.dto.MenuCreateRequest; import kitchenpos.menus.domain.MenuRepository; import kitchenpos.menus.domain.tobe.Menu; import kitchenpos.menus.domain.tobe.MenuPrice; -import kitchenpos.menugroups.domain.tobe.MenuGroup; -import kitchenpos.menus.ui.dto.MenuCreateRequest; +import kitchenpos.menus.domain.tobe.MenuProductsValidator; import kitchenpos.products.domain.ProductRepository; import kitchenpos.products.domain.ProfanityValidator; import kitchenpos.products.domain.tobe.Product; @@ -33,25 +34,26 @@ @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) class MenuServiceTest { - private MenuRepository menuRepository = new InMemoryMenuRepository(); - private MenuGroupRepository menuGroupRepository = new InMemoryMenuGroupRepository(); - private ProductRepository productRepository = new InMemoryProductRepository(); - private ProfanityValidator profanityValidator = new FakeProfanityValidator(); + private final MenuRepository menuRepository = new InMemoryMenuRepository(); + private final MenuGroupRepository menuGroupRepository = new InMemoryMenuGroupRepository(); + private final ProductRepository productRepository = new InMemoryProductRepository(); + private final ProfanityValidator profanityValidator = new FakeProfanityValidator(); private MenuService menuService; @BeforeEach void setUp() { - MenuProductsService menuProductService = new MenuProductsService(productRepository); + final MenuProductMapper menuProductMapper = new MenuProductMapper(productRepository, + new MenuProductsValidator()); menuService = new MenuService(menuRepository, menuGroupRepository, profanityValidator, - menuProductService); + menuProductMapper); } @Test void 상품들을_조합하여_메뉴를_생성한다() { MenuCreateRequest createRequest = MenuFixture.createRequest(30_000L, - createChickenMenuGroup(), - createFriedProduct(), 2); + createChickenMenuGroup(), + createFriedProduct(), 2); Menu actual = menuService.create(createRequest); @@ -61,8 +63,8 @@ void setUp() { @Test void 메뉴에_상품이_1개_이상_존재하지_않으면_예외를_던진다() { MenuCreateRequest createRequest = MenuFixture.createRequest(30_000L, - createChickenMenuGroup(), - createFriedProduct(), 0); + createChickenMenuGroup(), + createFriedProduct(), 0); assertThatIllegalArgumentException().isThrownBy(() -> menuService.create(createRequest)); } @@ -71,8 +73,8 @@ void setUp() { @Test void 메뉴이름에_욕설이나_부적절한_언어를_사용하면_예외를_던진다() { MenuCreateRequest createRequest = MenuFixture.createRequest("욕설", 30_000L, - createChickenMenuGroup(), - createFriedProduct(), 2); + createChickenMenuGroup(), + createFriedProduct(), 2); assertThatIllegalArgumentException().isThrownBy(() -> menuService.create(createRequest)); } @@ -80,38 +82,38 @@ void setUp() { @Test void 메뉴는_메뉴그룹에_속하지않으면_예외를_던진다() { MenuCreateRequest createRequest = MenuFixture.createRequest(30_000L, null, - createFriedProduct(), 2); + createFriedProduct(), 2); assertThatThrownBy(() -> menuService.create(createRequest)).isInstanceOf( - NoSuchElementException.class); + NoSuchElementException.class); } @Test void 메뉴가격은_0보다_작으면_예외를_던진다() { assertThatThrownBy(() -> menuService.create( - MenuFixture.createRequest(-20_000L, createChickenMenuGroup(), - createFriedProduct(), 2))).isInstanceOf( - IllegalArgumentException.class); + MenuFixture.createRequest(-20_000L, createChickenMenuGroup(), + createFriedProduct(), 2))).isInstanceOf( + IllegalArgumentException.class); } @Test void 메뉴가격은_상품가격x상품갯수의_총합을_넘으면_예외를_던진다() { MenuCreateRequest createRequest = MenuFixture.createRequest(50_000L, - createChickenMenuGroup(), - createFriedProduct(), 2); + createChickenMenuGroup(), + createFriedProduct(), 2); assertThatThrownBy(() -> menuService.create(createRequest)).isInstanceOf( - IllegalArgumentException.class); + IllegalArgumentException.class); } @Test void 메뉴가격을_수정한다() { Menu saved = menuService.create( - MenuFixture.createRequest(30_000L, createChickenMenuGroup(), createFriedProduct(), - 2)); + MenuFixture.createRequest(30_000L, createChickenMenuGroup(), createFriedProduct(), + 2)); Menu actual = menuService.changePrice(saved.getId(), - new MenuPrice(BigDecimal.valueOf(40_000L))); + new MenuPrice(BigDecimal.valueOf(40_000L))); assertThat(actual.getPrice()).isEqualTo(BigDecimal.valueOf(40_000L)); } @@ -119,30 +121,30 @@ void setUp() { @Test void 메뉴가격_수정시_0보다_작으면_예외를_던진다() { Menu saved = menuService.create( - MenuFixture.createRequest(30_000L, createChickenMenuGroup(), createFriedProduct(), - 2)); + MenuFixture.createRequest(30_000L, createChickenMenuGroup(), createFriedProduct(), + 2)); assertThatThrownBy(() -> menuService.changePrice(saved.getId(), - new MenuPrice(BigDecimal.valueOf(-40_000L)))).isInstanceOf( - IllegalArgumentException.class); + new MenuPrice(BigDecimal.valueOf(-40_000L)))).isInstanceOf( + IllegalArgumentException.class); } @Test void 메뉴가격_수정시_상품가격x상품갯수의_총합을_넘으면_예외를_던진다() { Menu saved = menuService.create( - MenuFixture.createRequest(30_000L, createChickenMenuGroup(), createFriedProduct(), - 2)); + MenuFixture.createRequest(30_000L, createChickenMenuGroup(), createFriedProduct(), + 2)); assertThatThrownBy(() -> menuService.changePrice(saved.getId(), - MenuFixture.changePriceRequest(50_000L))).isInstanceOf( - IllegalArgumentException.class); + MenuFixture.changePriceRequest(50_000L))).isInstanceOf( + IllegalArgumentException.class); } @Test void 메뉴를_손님들에게_노출한다() { Menu saved = menuService.create( - MenuFixture.createRequest(30_000L, createChickenMenuGroup(), createFriedProduct(), - 2)); + MenuFixture.createRequest(30_000L, createChickenMenuGroup(), createFriedProduct(), + 2)); Menu actual = menuService.display(saved.getId()); @@ -152,8 +154,8 @@ void setUp() { @Test void 메뉴를_손님들에게_숨긴다() { Menu saved = menuService.create( - MenuFixture.createRequest(30_000L, createChickenMenuGroup(), createFriedProduct(), - 2)); + MenuFixture.createRequest(30_000L, createChickenMenuGroup(), createFriedProduct(), + 2)); Menu actual = menuService.hide(saved.getId()); @@ -163,11 +165,11 @@ void setUp() { @Test void 모든_메뉴_목록을_볼_수_있다() { menuService.create( - MenuFixture.createRequest("후라이드2마리", 30_000L, createChickenMenuGroup(), - createFriedProduct(), 2)); + MenuFixture.createRequest("후라이드2마리", 30_000L, createChickenMenuGroup(), + createFriedProduct(), 2)); menuService.create( - MenuFixture.createRequest("후라이드1마리", 20_000L, createChickenMenuGroup(), - createFriedProduct(), 1)); + MenuFixture.createRequest("후라이드1마리", 20_000L, createChickenMenuGroup(), + createFriedProduct(), 1)); List actual = menuService.findAll(); diff --git a/src/test/java/kitchenpos/menus/domain/tobe/MenuProductTest.java b/src/test/java/kitchenpos/menus/domain/tobe/MenuProductTest.java index 51b355d51..02f594a2b 100644 --- a/src/test/java/kitchenpos/menus/domain/tobe/MenuProductTest.java +++ b/src/test/java/kitchenpos/menus/domain/tobe/MenuProductTest.java @@ -4,9 +4,6 @@ import java.math.BigDecimal; import kitchenpos.fixture.ProductFixture; -import kitchenpos.menus.domain.tobe.MenuProduct; -import kitchenpos.menus.domain.tobe.MenuQuantity; -import kitchenpos.products.domain.tobe.Product; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; @@ -18,9 +15,8 @@ class MenuProductTest { @Test void 메뉴상품의_가격과_수량을_곱하여_합을_구할_수_있다() { - Product product = ProductFixture.createFired(); - MenuProduct actual = new MenuProduct(ProductFixture.createFired(), new MenuQuantity(2)); + MenuProduct actual = new MenuProduct(ProductFixture.createFired(), new ProductQuantity(2)); - assertThat(actual.calculateSum(product)).isEqualTo(BigDecimal.valueOf(40_000L)); + assertThat(actual.calculateSum()).isEqualTo(BigDecimal.valueOf(40_000L)); } } \ No newline at end of file diff --git a/src/test/java/kitchenpos/menus/domain/tobe/MenuProductValidatorTest.java b/src/test/java/kitchenpos/menus/domain/tobe/MenuProductValidatorTest.java new file mode 100644 index 000000000..01f0fefda --- /dev/null +++ b/src/test/java/kitchenpos/menus/domain/tobe/MenuProductValidatorTest.java @@ -0,0 +1,52 @@ +package kitchenpos.menus.domain.tobe; + +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.List; +import kitchenpos.fixture.ProductFixture; +import kitchenpos.products.domain.tobe.Product; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +@DisplayName("MenuProductValidator") +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class MenuProductValidatorTest { + + private final MenuProductsValidator menuProductValidator = new MenuProductsValidator(); + + @Test + void 메뉴상품들이_null일_경우_검증을_실패한다() { + assertThatThrownBy( + () -> menuProductValidator.validate(null, null)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 메뉴상품들이_비어있을_경우_검증을_실패한다() { + assertThatThrownBy( + () -> menuProductValidator.validate(List.of(), List.of())) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 메뉴상품들에_메뉴가_중복되면_검증을_실패한다() { + Product product = ProductFixture.createFired(20_000L); + MenuProduct menuProduct = new MenuProduct(product, 2); + + assertThatThrownBy( + () -> menuProductValidator.validate(List.of(menuProduct, menuProduct), + List.of(product))) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 메뉴상품들의_검증을_성공한다() { + Product product = ProductFixture.createFired(20_000L); + assertThatNoException().isThrownBy(() -> menuProductValidator.validate( + List.of(new MenuProduct(product, 2)), List.of(product)) + ); + } +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/menus/domain/tobe/MenuProductsTest.java b/src/test/java/kitchenpos/menus/domain/tobe/MenuProductsTest.java index 46728f741..9d6ddb79b 100644 --- a/src/test/java/kitchenpos/menus/domain/tobe/MenuProductsTest.java +++ b/src/test/java/kitchenpos/menus/domain/tobe/MenuProductsTest.java @@ -1,9 +1,11 @@ package kitchenpos.menus.domain.tobe; +import static org.assertj.core.api.Assertions.assertThatNoException; import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.util.List; -import kitchenpos.menus.domain.tobe.MenuProducts; +import kitchenpos.fixture.ProductFixture; +import kitchenpos.products.domain.tobe.Product; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; @@ -26,4 +28,12 @@ class MenuProductsTest { () -> new MenuProducts(List.of())) .isInstanceOf(IllegalArgumentException.class); } + + @Test + void 메뉴상품들을_생성할_수_있다() { + Product product = ProductFixture.createFired(20_000L); + assertThatNoException().isThrownBy(() -> new MenuProducts( + List.of(new MenuProduct(product, 2))) + ); + } } \ No newline at end of file diff --git a/src/test/java/kitchenpos/menus/domain/tobe/MenuTest.java b/src/test/java/kitchenpos/menus/domain/tobe/MenuTest.java index e3601489d..0f1bacaa7 100644 --- a/src/test/java/kitchenpos/menus/domain/tobe/MenuTest.java +++ b/src/test/java/kitchenpos/menus/domain/tobe/MenuTest.java @@ -1,13 +1,15 @@ package kitchenpos.menus.domain.tobe; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.math.BigDecimal; +import java.util.UUID; import kitchenpos.fixture.MenuFixture; import kitchenpos.fixture.MenuGroupFixture; import kitchenpos.fixture.ProductFixture; -import kitchenpos.menus.domain.tobe.Menu; -import kitchenpos.menus.domain.tobe.MenuPrice; +import kitchenpos.products.domain.tobe.Product; +import kitchenpos.products.domain.tobe.ProductPrice; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; @@ -26,6 +28,14 @@ class MenuTest { assertThat(actual.getPrice()).isEqualTo(BigDecimal.valueOf(35_000L)); } + @Test + void 메뉴가격_변경시_상품가격x상품갯수의_총합을_넘으면_예외를_던진다() { + Menu actual = createFriedMenu(); + + assertThatThrownBy(() -> actual.changePrice(new MenuPrice(BigDecimal.valueOf(50_000L)))) + .isInstanceOf(IllegalArgumentException.class); + } + @Test void 메뉴를_노출할_수_있다() { Menu actual = createFriedMenu(); @@ -44,8 +54,26 @@ class MenuTest { assertThat(actual.isDisplayed()).isFalse(); } + @Test + void 메뉴가격이_상품가격x상품갯수의_총합을_넘는지_확인할_수_있다() { + Menu actual = createFriedMenu(); + + assertThat(actual.isOverThanProductSumPrice()).isFalse(); + } + + @Test + void 메뉴상품의_가격_수정_시_상품가격x상품갯수의_총합이_넘으면_메뉴를_숨김처리한다() { + UUID productId = UUID.randomUUID(); + Menu menu = MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), + new Product(productId, "후라이드", BigDecimal.valueOf(20_000L)), 30_000L); + + menu.changeMenuProductPrice(productId, new ProductPrice(BigDecimal.valueOf(10_000L))); + + assertThat(menu.isDisplayed()).isFalse(); + } + private Menu createFriedMenu() { return MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), - ProductFixture.createFired()); + ProductFixture.createFired(20_000L), 30_000L); } } \ No newline at end of file diff --git a/src/test/java/kitchenpos/orders/common/application/OrderServiceTest.java b/src/test/java/kitchenpos/orders/common/application/OrderServiceTest.java index bfcf9c66f..3b7c97cc1 100644 --- a/src/test/java/kitchenpos/orders/common/application/OrderServiceTest.java +++ b/src/test/java/kitchenpos/orders/common/application/OrderServiceTest.java @@ -18,16 +18,16 @@ import kitchenpos.fixture.OrderTableFixture; import kitchenpos.fixture.ProductFixture; import kitchenpos.menugroups.domain.MenuGroupRepository; +import kitchenpos.menugroups.domain.tobe.MenuGroup; import kitchenpos.menus.domain.MenuRepository; import kitchenpos.menus.domain.tobe.Menu; -import kitchenpos.menugroups.domain.tobe.MenuGroup; import kitchenpos.orders.common.domain.Order; import kitchenpos.orders.common.domain.OrderLineItem; import kitchenpos.orders.common.domain.OrderRepository; import kitchenpos.orders.common.domain.OrderStatus; import kitchenpos.orders.delivery.domain.KitchenridersClient; -import kitchenpos.orders.eatin.domain.OrderTable; -import kitchenpos.orders.eatin.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.tobe.OrderTable; import kitchenpos.products.domain.ProductRepository; import kitchenpos.products.domain.tobe.Product; import org.junit.jupiter.api.BeforeEach; @@ -465,7 +465,7 @@ private OrderLineItem createOrderLineItem(Menu menu) { private OrderTable createOccupiedTable() { OrderTable orderTable = createTable(); - orderTable.setOccupied(true); + orderTable.sit(); return orderTable; } diff --git a/src/test/java/kitchenpos/orders/common/domain/tobe/MenuQuantityTest.java b/src/test/java/kitchenpos/orders/common/domain/tobe/MenuQuantityTest.java new file mode 100644 index 000000000..4f8a8fc1d --- /dev/null +++ b/src/test/java/kitchenpos/orders/common/domain/tobe/MenuQuantityTest.java @@ -0,0 +1,22 @@ +package kitchenpos.orders.common.domain.tobe; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import kitchenpos.orders.common.domain.OrderType; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +@DisplayName("MenuQuantity") +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class MenuQuantityTest { + + @ParameterizedTest + @CsvSource(value = {"DELIVERY", "TAKEOUT"}) + void 매장주문이_아닌_주문의_메뉴수량은_음수가_될_수_없다(OrderType orderType) { + assertThatThrownBy(() -> new MenuQuantity(orderType, -2)) + .isInstanceOf(IllegalArgumentException.class); + } +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/orders/common/domain/tobe/OrderLineItemTest.java b/src/test/java/kitchenpos/orders/common/domain/tobe/OrderLineItemTest.java new file mode 100644 index 000000000..119dd6354 --- /dev/null +++ b/src/test/java/kitchenpos/orders/common/domain/tobe/OrderLineItemTest.java @@ -0,0 +1,41 @@ +package kitchenpos.orders.common.domain.tobe; + +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import kitchenpos.fixture.MenuFixture; +import kitchenpos.fixture.MenuGroupFixture; +import kitchenpos.fixture.ProductFixture; +import kitchenpos.menus.domain.tobe.Menu; +import kitchenpos.orders.common.domain.OrderType; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +@DisplayName("OrderLineItem") +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class OrderLineItemTest { + + @Test + void 노출되어있지않은_메뉴로_주문라인아이템을_생성하면_예외를_던진다() { + Menu menu = MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), + ProductFixture.createFired()); + menu.hide(); + + assertThatThrownBy(() -> createOrderLineItem(menu)) + .isInstanceOf(IllegalStateException.class); + } + + @Test + void 주문라인아이템을_생성한다() { + Menu menu = MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), + ProductFixture.createFired()); + + assertThatNoException().isThrownBy(() -> createOrderLineItem(menu)); + } + + private static void createOrderLineItem(Menu menu) { + new OrderLineItem(menu, new MenuQuantity(OrderType.TAKEOUT, 2)); + } +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/orders/common/domain/tobe/OrderLineItemsTest.java b/src/test/java/kitchenpos/orders/common/domain/tobe/OrderLineItemsTest.java new file mode 100644 index 000000000..b12ca8336 --- /dev/null +++ b/src/test/java/kitchenpos/orders/common/domain/tobe/OrderLineItemsTest.java @@ -0,0 +1,43 @@ +package kitchenpos.orders.common.domain.tobe; + +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.List; +import kitchenpos.fixture.MenuFixture; +import kitchenpos.fixture.MenuGroupFixture; +import kitchenpos.fixture.ProductFixture; +import kitchenpos.fixture.StoreOrderFixture; +import kitchenpos.menus.domain.tobe.Menu; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +@DisplayName("OrderLineItems") +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class OrderLineItemsTest { + + @Test + void 주문아이템들이_null일_경우_예외를_던진다() { + assertThatThrownBy( + () -> new OrderLineItems(null)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 주문아이템들이_비어있을_경우_예외를_던진다() { + assertThatThrownBy( + () -> new OrderLineItems(List.of())) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 주문아이템들을_생성할_수_있다() { + Menu menu = MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), + ProductFixture.createFired()); + OrderLineItem orderLineItem = StoreOrderFixture.createOrderLineItem(menu); + + assertThatNoException().isThrownBy(() -> new OrderLineItems(List.of(orderLineItem))); + } +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/orders/common/domain/tobe/OrderLineItemsValidatorTest.java b/src/test/java/kitchenpos/orders/common/domain/tobe/OrderLineItemsValidatorTest.java new file mode 100644 index 000000000..a171b125a --- /dev/null +++ b/src/test/java/kitchenpos/orders/common/domain/tobe/OrderLineItemsValidatorTest.java @@ -0,0 +1,59 @@ +package kitchenpos.orders.common.domain.tobe; + +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.List; +import kitchenpos.fixture.MenuFixture; +import kitchenpos.fixture.MenuGroupFixture; +import kitchenpos.fixture.ProductFixture; +import kitchenpos.fixture.StoreOrderFixture; +import kitchenpos.menus.domain.tobe.Menu; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +@DisplayName("OrderLineItemsValidator") +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class OrderLineItemsValidatorTest { + + private final OrderLineItemsValidator orderLineItemsValidator = new OrderLineItemsValidator(); + + @Test + void 주문아이템들이_null일_경우_검증을_실패한다() { + assertThatThrownBy( + () -> orderLineItemsValidator.validate(null, null)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 주문아이템들이_비어있을_경우_검증을_실패한다() { + assertThatThrownBy( + () -> orderLineItemsValidator.validate(List.of(), List.of())) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 주문아이템들에_메뉴가_중복되면_검증을_실패한다() { + Menu menu = MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), + ProductFixture.createFired()); + OrderLineItem orderLineItem = StoreOrderFixture.createOrderLineItem(menu); + + assertThatThrownBy(() -> orderLineItemsValidator.validate( + List.of(orderLineItem, orderLineItem), + List.of(menu)) + ).isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 주문아이템들의_검증을_성공한다() { + Menu menu = MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), + ProductFixture.createFired()); + OrderLineItem orderLineItem = StoreOrderFixture.createOrderLineItem(menu); + + assertThatNoException().isThrownBy(() -> orderLineItemsValidator.validate( + List.of(orderLineItem), List.of(menu)) + ); + } +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/orders/eatin/application/OrderTableServiceTest.java b/src/test/java/kitchenpos/orders/store/application/OrderTableServiceTest.java similarity index 60% rename from src/test/java/kitchenpos/orders/eatin/application/OrderTableServiceTest.java rename to src/test/java/kitchenpos/orders/store/application/OrderTableServiceTest.java index d59e415a9..454332caf 100644 --- a/src/test/java/kitchenpos/orders/eatin/application/OrderTableServiceTest.java +++ b/src/test/java/kitchenpos/orders/store/application/OrderTableServiceTest.java @@ -1,31 +1,32 @@ -package kitchenpos.orders.eatin.application; +package kitchenpos.orders.store.application; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; +import static org.assertj.core.api.Assertions.assertThatNoException; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; import java.util.List; import kitchenpos.fake.InMemoryMenuGroupRepository; import kitchenpos.fake.InMemoryMenuRepository; -import kitchenpos.fake.InMemoryOrderRepository; import kitchenpos.fake.InMemoryOrderTableRepository; import kitchenpos.fake.InMemoryProductRepository; +import kitchenpos.fake.InMemoryStoreOrderRepository; import kitchenpos.fixture.MenuFixture; import kitchenpos.fixture.MenuGroupFixture; -import kitchenpos.fixture.OrderFixture; -import kitchenpos.fixture.OrderTableFixture; import kitchenpos.fixture.ProductFixture; +import kitchenpos.fixture.StoreOrderFixture; import kitchenpos.menugroups.domain.MenuGroupRepository; +import kitchenpos.menugroups.domain.tobe.MenuGroup; import kitchenpos.menus.domain.MenuRepository; import kitchenpos.menus.domain.tobe.Menu; -import kitchenpos.menugroups.domain.tobe.MenuGroup; -import kitchenpos.orders.common.domain.Order; -import kitchenpos.orders.common.domain.OrderRepository; -import kitchenpos.orders.common.domain.OrderStatus; -import kitchenpos.orders.eatin.domain.OrderTable; -import kitchenpos.orders.eatin.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.StoreOrderRepository; +import kitchenpos.orders.store.domain.tobe.NumberOfGuests; +import kitchenpos.orders.store.domain.tobe.OrderTable; +import kitchenpos.orders.store.domain.tobe.OrderTableName; +import kitchenpos.orders.store.domain.tobe.StoreOrder; import kitchenpos.products.domain.ProductRepository; import kitchenpos.products.domain.tobe.Product; import org.junit.jupiter.api.BeforeEach; @@ -38,7 +39,7 @@ @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) class OrderTableServiceTest { - private OrderRepository orderRepository = new InMemoryOrderRepository(); + private StoreOrderRepository storeOrderRepository = new InMemoryStoreOrderRepository(); private MenuRepository menuRepository = new InMemoryMenuRepository(); @@ -52,32 +53,24 @@ class OrderTableServiceTest { @BeforeEach void setUp() { - orderTableService = new OrderTableService(orderTableRepository, orderRepository); + orderTableService = new OrderTableService(orderTableRepository, storeOrderRepository); } @Test void 테이블을_생성한다() { - OrderTable request = OrderTableFixture.createRequest("1번테이블"); - - OrderTable actual = orderTableService.create(request); - - assertAll(() -> assertThat(actual.getId()).isNotNull(), - () -> assertThat(actual.getNumberOfGuests()).isZero(), - () -> assertThat(actual.isOccupied()).isFalse()); + assertThatNoException().isThrownBy( + () -> orderTableService.create(new OrderTableName("1번테이블"))); } @Test void 테이블이름이_비어있으면_예외를던진다() { - OrderTable createRequest = OrderTableFixture.createRequest(""); - assertThatIllegalArgumentException().isThrownBy( - () -> orderTableService.create(createRequest)); + () -> orderTableService.create(new OrderTableName(""))); } @Test void 먹고가는_손님이_오면_테이블점유를_체크한다() { - OrderTable createRequest = OrderTableFixture.createRequest("1번테이블"); - OrderTable saved = orderTableService.create(createRequest); + OrderTable saved = orderTableService.create(new OrderTableName("1번테이블")); OrderTable actual = orderTableService.sit(saved.getId()); @@ -86,8 +79,7 @@ void setUp() { @Test void 주문이_완료된_테이블을_치울_수_있다() { - OrderTable createRequset = OrderTableFixture.createRequest("1번테이블"); - OrderTable saved = orderTableService.create(createRequset); + OrderTable saved = orderTableService.create(new OrderTableName("1번테이블")); orderTableService.sit(saved.getId()); createCompleteOrder(saved); @@ -99,65 +91,62 @@ void setUp() { @Test void 주문이_완료되지_않은_테이블을_치우면_예외를던진다() { - OrderTable createRequest = OrderTableFixture.createRequest("1번테이블"); - OrderTable saved = orderTableService.create(createRequest); + OrderTable saved = orderTableService.create(new OrderTableName("1번테이블")); orderTableService.sit(saved.getId()); - createOrder(saved); + createStoreOrder(saved); assertThatThrownBy(() -> orderTableService.clear(saved.getId())) .isInstanceOf(IllegalStateException.class); } private void createCompleteOrder(OrderTable orderTable) { - Order order = createOrder(orderTable); - order.setStatus(OrderStatus.COMPLETED); + StoreOrder storeOrder = createStoreOrder(orderTable); + storeOrder.accept(); + storeOrder.serve(); + storeOrder.complete(); } - private Order createOrder(OrderTable orderTable) { + private StoreOrder createStoreOrder(OrderTable orderTable) { MenuGroup chickenMenuGroup = menuGroupRepository.save(MenuGroupFixture.createChicken()); Product friedProduct = productRepository.save(ProductFixture.createFired()); Menu friedMenu = menuRepository.save( MenuFixture.createFriedOnePlusOne(chickenMenuGroup, friedProduct)); - return orderRepository.save(OrderFixture.createEatIn(orderTable, friedMenu)); + return storeOrderRepository.save(StoreOrderFixture.createStoreOrder(orderTable, friedMenu)); } @Test void 점유되어있는_테이블의_손님수를_변경할_수_있다() { - OrderTable createRequest = OrderTableFixture.createRequest("1번테이블"); - OrderTable saved = orderTableService.create(createRequest); + OrderTable saved = orderTableService.create(new OrderTableName("1번테이블")); orderTableService.sit(saved.getId()); - OrderTable changeRequest = OrderTableFixture.changeNumberOfGuestsRequest(4); - OrderTable actual = orderTableService.changeNumberOfGuests(saved.getId(), changeRequest); + OrderTable actual = orderTableService.changeNumberOfGuests(saved.getId(), + new NumberOfGuests(4)); assertThat(actual.getNumberOfGuests()).isEqualTo(4); } @Test void 점유되어있지_않은_테이블의_손님수를_변경하면_예외를던진다() { - OrderTable createRequest = OrderTableFixture.createRequest("1번테이블"); - OrderTable saved = orderTableService.create(createRequest); - OrderTable changeRequest = OrderTableFixture.changeNumberOfGuestsRequest(4); + OrderTable saved = orderTableService.create(new OrderTableName("1번테이블")); assertThatIllegalStateException().isThrownBy( - () -> orderTableService.changeNumberOfGuests(saved.getId(), changeRequest)); + () -> orderTableService.changeNumberOfGuests(saved.getId(), new NumberOfGuests(4))); } @Test void 테이블의_손님수를_마이너스로_변경하면_예외를던진다() { - OrderTable createRequest = OrderTableFixture.createRequest("1번테이블"); - OrderTable saved = orderTableService.create(createRequest); + OrderTable saved = orderTableService.create(new OrderTableName("1번테이블")); orderTableService.sit(saved.getId()); - OrderTable changeRequest = OrderTableFixture.changeNumberOfGuestsRequest(-10); assertThatIllegalArgumentException().isThrownBy( - () -> orderTableService.changeNumberOfGuests(saved.getId(), changeRequest)); + () -> orderTableService.changeNumberOfGuests(saved.getId(), + new NumberOfGuests(-10))); } @Test void 모든_테이블_목록을_볼_수_있다() { - orderTableService.create(OrderTableFixture.createRequest("1번테이블")); - orderTableService.create(OrderTableFixture.createRequest("2번테이블")); + orderTableService.create(new OrderTableName("1번테이블")); + orderTableService.create(new OrderTableName("2번테이블")); List actual = orderTableService.findAll(); diff --git a/src/test/java/kitchenpos/orders/store/application/StoreOrderServiceTest.java b/src/test/java/kitchenpos/orders/store/application/StoreOrderServiceTest.java new file mode 100644 index 000000000..6d636fc8e --- /dev/null +++ b/src/test/java/kitchenpos/orders/store/application/StoreOrderServiceTest.java @@ -0,0 +1,216 @@ +package kitchenpos.orders.store.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +import java.util.Arrays; +import java.util.List; +import java.util.NoSuchElementException; +import kitchenpos.fake.InMemoryMenuGroupRepository; +import kitchenpos.fake.InMemoryMenuRepository; +import kitchenpos.fake.InMemoryOrderTableRepository; +import kitchenpos.fake.InMemoryProductRepository; +import kitchenpos.fake.InMemoryStoreOrderRepository; +import kitchenpos.fixture.MenuFixture; +import kitchenpos.fixture.MenuGroupFixture; +import kitchenpos.fixture.OrderTableFixture; +import kitchenpos.fixture.ProductFixture; +import kitchenpos.menugroups.domain.MenuGroupRepository; +import kitchenpos.menugroups.domain.tobe.MenuGroup; +import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.menus.domain.tobe.Menu; +import kitchenpos.orders.common.application.OrderLineItemMapper; +import kitchenpos.orders.common.application.dto.OrderLineItemRequest; +import kitchenpos.orders.common.application.dto.OrderLineItemsRequest; +import kitchenpos.orders.common.domain.OrderStatus; +import kitchenpos.orders.common.domain.tobe.OrderLineItemsValidator; +import kitchenpos.orders.store.application.dto.StoreOrderCreateRequest; +import kitchenpos.orders.store.domain.OrderTableRepository; +import kitchenpos.orders.store.domain.StoreOrderRepository; +import kitchenpos.orders.store.domain.tobe.NumberOfGuests; +import kitchenpos.orders.store.domain.tobe.OrderTable; +import kitchenpos.orders.store.domain.tobe.StoreOrder; +import kitchenpos.products.domain.ProductRepository; +import kitchenpos.products.domain.tobe.Product; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +@DisplayName("OrderService") +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class StoreOrderServiceTest { + + private StoreOrderRepository storeOrderRepository = new InMemoryStoreOrderRepository(); + + private MenuRepository menuRepository = new InMemoryMenuRepository(); + + private OrderTableRepository orderTableRepository = new InMemoryOrderTableRepository(); + + private MenuGroupRepository menuGroupRepository = new InMemoryMenuGroupRepository(); + + private ProductRepository productRepository = new InMemoryProductRepository(); + + private StoreOrderService storeOrderService; + + @BeforeEach + void setUp() { + final OrderLineItemMapper orderLineItemMapper = new OrderLineItemMapper(menuRepository, + new OrderLineItemsValidator()); + storeOrderService = new StoreOrderService(storeOrderRepository, orderTableRepository, + orderLineItemMapper); + } + + @Test + void 매장주문_생성시_테이블을_빠뜨리면_예외를_던진다() { + MenuGroup menuGroup = createMenuGroup(); + + assertThatThrownBy(() -> storeOrderService.create(new StoreOrderCreateRequest( + createOrderLineItemRequests(createFriedMenu(menuGroup)), null))) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + void 매장주문_생성시_손님이_앉아있지_않은_테이블이면_예외를_던진다() { + MenuGroup menuGroup = createMenuGroup(); + OrderTable orderTable = createOrderTable(); + StoreOrderCreateRequest createRequest = new StoreOrderCreateRequest( + createOrderLineItemRequests(createFriedMenu(menuGroup)), orderTable.getId()); + + assertThatThrownBy(() -> storeOrderService.create(createRequest)) + .isInstanceOf(IllegalStateException.class); + } + + @Test + void 매장주문_하나에_여러_메뉴를_주문할_수_있다() { + StoreOrderCreateRequest createRequest = createStoreOrderCreateRequest(); + + StoreOrder actual = storeOrderService.create(createRequest); + + assertThat(actual.getId()).isNotNull(); + } + + @Test + void 매장주문이_생성되면_주문은_승인을_대기하는_상태가_된다() { + StoreOrderCreateRequest createRequest = createStoreOrderCreateRequest(); + + StoreOrder actual = storeOrderService.create(createRequest); + + assertThat(actual.getStatus()).isEqualTo(OrderStatus.WAITING); + } + + @Test + void 대기상태의_매장주문을_접수한다() { + StoreOrderCreateRequest createRequest = createStoreOrderCreateRequest(); + StoreOrder saved = storeOrderService.create(createRequest); + + storeOrderService.accept(saved.getId()); + + assertThat(saved.getStatus()).isEqualTo(OrderStatus.ACCEPTED); + } + + @Test + void 대기상태가_아닌_매장주문을_접수하면_예외를_던진다() { + StoreOrderCreateRequest createRequest = createStoreOrderCreateRequest(); + StoreOrder saved = storeOrderService.create(createRequest); + + storeOrderService.accept(saved.getId()); + + assertThatThrownBy(() -> storeOrderService.accept(saved.getId())) + .isInstanceOf(IllegalStateException.class); + } + + @Test + void 접수상태의_매장주문을_전달상태로_변경한다() { + StoreOrderCreateRequest createRequest = createStoreOrderCreateRequest(); + StoreOrder saved = storeOrderService.create(createRequest); + storeOrderService.accept(saved.getId()); + + storeOrderService.serve(saved.getId()); + + assertThat(saved.getStatus()).isEqualTo(OrderStatus.SERVED); + } + + @Test + void 접수상태가_아닌_매장주문을_전달상태로_변경하면_예외를_던진다() { + StoreOrderCreateRequest createRequest = createStoreOrderCreateRequest(); + StoreOrder saved = storeOrderService.create(createRequest); + + assertThatThrownBy(() -> storeOrderService.serve(saved.getId())) + .isInstanceOf(IllegalStateException.class); + } + + @Test + void 전달된_매장주문을_완료상태로_변경하면_테이블은_초기값으로_세팅된다() { + MenuGroup menuGroup = createMenuGroup(); + OrderTable orderTable = createOrderTableAndSit(); + StoreOrderCreateRequest createRequest = new StoreOrderCreateRequest( + createOrderLineItemRequests(createFriedMenu(menuGroup)), + orderTable.getId()); + StoreOrder saved = storeOrderService.create(createRequest); + storeOrderService.accept(saved.getId()); + storeOrderService.serve(saved.getId()); + + storeOrderService.complete(saved.getId()); + + assertAll(() -> assertThat(saved.getStatus()).isEqualTo(OrderStatus.COMPLETED), + () -> assertThat(orderTable.isOccupied()).isFalse(), + () -> assertThat(orderTable.getNumberOfGuests()).isZero()); + } + + @Test + void 전달상태가_아닌_포장주문을_완료상태로_변경하면_예외를_던진다() { + StoreOrderCreateRequest createRequest = createStoreOrderCreateRequest(); + StoreOrder saved = storeOrderService.create(createRequest); + + assertThatThrownBy(() -> storeOrderService.complete(saved.getId())) + .isInstanceOf(IllegalStateException.class); + } + + private StoreOrderCreateRequest createStoreOrderCreateRequest() { + MenuGroup menuGroup = createMenuGroup(); + OrderTable orderTable = createOrderTableAndSit(); + return new StoreOrderCreateRequest( + createOrderLineItemRequests( + createFriedMenu(menuGroup), + createSeasonedMenu(menuGroup)), + orderTable.getId()); + } + + private MenuGroup createMenuGroup() { + return menuGroupRepository.save(MenuGroupFixture.createChicken()); + } + + private OrderTable createOrderTable() { + return orderTableRepository.save(OrderTableFixture.createNumber1()); + } + + private OrderTable createOrderTableAndSit() { + OrderTable orderTable = createOrderTable(); + orderTable.sit(); + orderTable.changeNumberOfGuests(new NumberOfGuests(3)); + return orderTable; + } + + private Menu createFriedMenu(MenuGroup menuGroup) { + Product product = productRepository.save(ProductFixture.createFired()); + return menuRepository.save(MenuFixture.createFriedOnePlusOne(menuGroup, product)); + } + + private Menu createSeasonedMenu(MenuGroup menuGroup) { + Product product = productRepository.save(ProductFixture.createSeasoned()); + return menuRepository.save(MenuFixture.SeasonedOnePlusOne(menuGroup, product)); + } + + private OrderLineItemsRequest createOrderLineItemRequests(Menu... menu) { + List orderLineItemRequests = Arrays.stream(menu) + .map(this::createOrderLineItemRequest).toList(); + return new OrderLineItemsRequest(orderLineItemRequests); + } + + private OrderLineItemRequest createOrderLineItemRequest(Menu menu) { + return new OrderLineItemRequest(menu.getId(), 1); + } +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/orders/store/domain/tobe/OrderTableTest.java b/src/test/java/kitchenpos/orders/store/domain/tobe/OrderTableTest.java new file mode 100644 index 000000000..acc7fe21d --- /dev/null +++ b/src/test/java/kitchenpos/orders/store/domain/tobe/OrderTableTest.java @@ -0,0 +1,72 @@ +package kitchenpos.orders.store.domain.tobe; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; + +@DisplayName("OrderTable") +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class OrderTableTest { + + @Test + void 주문테이블을_생성할_수_있다() { + assertThatNoException() + .isThrownBy(() -> new OrderTable("1번테이블")); + } + + @ParameterizedTest + @NullAndEmptySource + void 이름이_비어있거나_없는_주문테이블을_생성하면_예외를_던진다(String name) { + assertThatThrownBy(() -> new OrderTable(name)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 주문테이블에_손님이_앉으면_점유된다() { + OrderTable target = new OrderTable("1번테이블"); + + target.sit(); + + assertThat(target.isOccupied()).isTrue(); + } + + @Test + void 주문테이블을_치우면_손님은0명_비점유상태로_변경된다() { + OrderTable target = new OrderTable("1번테이블"); + target.sit(); + target.changeNumberOfGuests(new NumberOfGuests(5)); + + target.clear(); + + assertAll( + () -> assertThat(target.isOccupied()).isFalse(), + () -> assertThat(target.hasGuest()).isFalse() + ); + } + + @Test + void 점유되지않은_테이블의_손님수를_변경하면_예외를_던진다() { + OrderTable target = new OrderTable("1번테이블"); + + assertThatThrownBy(() -> target.changeNumberOfGuests(new NumberOfGuests(5))) + .isInstanceOf(IllegalStateException.class); + } + + @Test + void 점유된_테이블의_손님수를_변경할_수_있다() { + OrderTable target = new OrderTable("1번테이블"); + target.sit(); + + target.changeNumberOfGuests(new NumberOfGuests(5)); + + assertThat(target.hasGuest()).isTrue(); + } +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/orders/store/domain/tobe/StoreOrderTest.java b/src/test/java/kitchenpos/orders/store/domain/tobe/StoreOrderTest.java new file mode 100644 index 000000000..06a546a4b --- /dev/null +++ b/src/test/java/kitchenpos/orders/store/domain/tobe/StoreOrderTest.java @@ -0,0 +1,126 @@ +package kitchenpos.orders.store.domain.tobe; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import kitchenpos.fixture.MenuFixture; +import kitchenpos.fixture.MenuGroupFixture; +import kitchenpos.fixture.OrderTableFixture; +import kitchenpos.fixture.ProductFixture; +import kitchenpos.fixture.StoreOrderFixture; +import kitchenpos.menus.domain.tobe.Menu; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +@DisplayName("StoreOrder") +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class StoreOrderTest { + + @Test + void 매장주문을_생성_시_테이블이_점유되어있지않으면_예외를_던진다() { + Menu menu = MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), + ProductFixture.createFired()); + + assertThatThrownBy(() -> new StoreOrder( + StoreOrderFixture.createOrderLineItems(menu), + OrderTableFixture.createNumber1())) + .isInstanceOf(IllegalStateException.class); + } + + @Test + void 매장주문을_생성_시_메뉴가_겹치면_예외를_던진다() { + OrderTable orderTable = OrderTableFixture.createNumber1(); + orderTable.sit(); + Menu menu1 = MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), + ProductFixture.createFired()); + Menu menu2 = MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), + ProductFixture.createFired()); + + assertThatThrownBy(() -> new StoreOrder( + StoreOrderFixture.createOrderLineItems(menu1, menu2), + OrderTableFixture.createNumber1())) + .isInstanceOf(IllegalStateException.class); + } + + @Test + void 매장주문을_생성한다() { + OrderTable orderTable = OrderTableFixture.createNumber1(); + orderTable.sit(); + Menu menu = MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), + ProductFixture.createFired()); + + assertThatNoException().isThrownBy( + () -> new StoreOrder( + StoreOrderFixture.createOrderLineItems(menu), + orderTable)); + } + + @Test + void 매장주문을_접수한다() { + StoreOrder storeOrder = StoreOrderFixture.createStoreOrder(); + + assertThatNoException().isThrownBy(storeOrder::accept); + } + + @Test + void 매장주문을_접수시_대기상태가_아니면_예외를_던진다() { + StoreOrder storeOrder = StoreOrderFixture.createStoreOrder(); + storeOrder.accept(); + + assertThatThrownBy(storeOrder::accept) + .isInstanceOf(IllegalStateException.class); + } + + @Test + void 매장주문을_전달한다() { + StoreOrder storeOrder = StoreOrderFixture.createStoreOrder(); + storeOrder.accept(); + + assertThatNoException().isThrownBy(storeOrder::serve); + } + + @Test + void 매장주문을_전달시_접수상태가_아니면_예외를_던진다() { + StoreOrder storeOrder = StoreOrderFixture.createStoreOrder(); + + assertThatThrownBy(storeOrder::serve) + .isInstanceOf(IllegalStateException.class); + } + + @Test + void 매장주문을_완료한다() { + StoreOrder storeOrder = StoreOrderFixture.createStoreOrder(); + storeOrder.accept(); + storeOrder.serve(); + + assertThatNoException().isThrownBy(storeOrder::complete); + } + + @Test + void 매장주문을_완료하면_테이블은_청소된다() { + OrderTable targetTable = OrderTableFixture.createNumber1(); + targetTable.sit(); + Menu menu = MenuFixture.createFriedOnePlusOne(MenuGroupFixture.createChicken(), + ProductFixture.createFired()); + StoreOrder storeOrder = new StoreOrder( + StoreOrderFixture.createOrderLineItems(menu), + targetTable); + storeOrder.accept(); + storeOrder.serve(); + + storeOrder.complete(); + + assertThat(targetTable.isOccupied()).isFalse(); + } + + @Test + void 매장주문을_완료시_전달상태가_아니면_예외를_던진다() { + StoreOrder storeOrder = StoreOrderFixture.createStoreOrder(); + + assertThatThrownBy(storeOrder::serve) + .isInstanceOf(IllegalStateException.class); + } +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/products/application/ProductServiceTest.java b/src/test/java/kitchenpos/products/application/ProductServiceTest.java index 8ff46ec0c..0ad72e78e 100644 --- a/src/test/java/kitchenpos/products/application/ProductServiceTest.java +++ b/src/test/java/kitchenpos/products/application/ProductServiceTest.java @@ -13,16 +13,15 @@ import kitchenpos.fixture.MenuFixture; import kitchenpos.fixture.MenuGroupFixture; import kitchenpos.fixture.ProductFixture; -import kitchenpos.menus.application.MenuProductsService; import kitchenpos.menugroups.domain.MenuGroupRepository; +import kitchenpos.menugroups.domain.tobe.MenuGroup; import kitchenpos.menus.domain.MenuRepository; import kitchenpos.menus.domain.tobe.Menu; -import kitchenpos.menugroups.domain.tobe.MenuGroup; +import kitchenpos.products.application.dto.ProductCreateRequest; import kitchenpos.products.domain.ProductRepository; import kitchenpos.products.domain.ProfanityValidator; import kitchenpos.products.domain.tobe.Product; import kitchenpos.products.domain.tobe.ProductPrice; -import kitchenpos.products.ui.dto.ProductCreateRequest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayNameGeneration; @@ -47,9 +46,7 @@ class ProductServiceTest { @BeforeEach void setUp() { - MenuProductsService menuProductService = new MenuProductsService(productRepository); - productService = new ProductService(productRepository, menuRepository, menuProductService, - profanityValidator); + productService = new ProductService(productRepository, menuRepository, profanityValidator); } @Test