From 4d999fe4f458699b0eb2be9d987ed83c141600f3 Mon Sep 17 00:00:00 2001 From: saerang Date: Sat, 23 Sep 2023 10:57:03 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat(order):=20step3=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=84=B0=EB=A7=81=20=EC=A4=80=EB=B9=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tobe/application/TobeOrderService.java | 194 ++++++++++++++++++ .../tobe/application/TobeOrderTable.java | 59 ++++++ .../eatinorders/tobe/domain/TobeOrder.java | 41 ++++ .../tobe/domain/TobeOrderRepository.java | 18 ++ .../tobe/domain/TobeOrderTableRepository.java | 15 ++ .../tobe/infra/JpaTobeOrderRepository.java | 10 + .../infra/JpaTobeOrderTableRepository.java | 10 + .../application/TobeOrderServiceTest.java | 7 + .../tobe/domain/TobeOrderTest.java | 7 + 9 files changed, 361 insertions(+) create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderRepository.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTableRepository.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderRepository.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderTableRepository.java create mode 100644 src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java create mode 100644 src/test/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTest.java diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java new file mode 100644 index 000000000..0ce307e84 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java @@ -0,0 +1,194 @@ +package kitchenpos.eatinorders.tobe.application; + +import kitchenpos.deliveryorders.infra.KitchenridersClient; +import kitchenpos.eatinorders.domain.Order; +import kitchenpos.eatinorders.domain.OrderLineItem; +import kitchenpos.eatinorders.domain.OrderRepository; +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.domain.OrderTable; +import kitchenpos.eatinorders.domain.OrderTableRepository; +import kitchenpos.eatinorders.domain.OrderType; +import kitchenpos.menus.domain.Menu; +import kitchenpos.menus.domain.MenuRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +@Service +public class TobeOrderService { + private final OrderRepository orderRepository; + private final MenuRepository menuRepository; + private final OrderTableRepository orderTableRepository; + private final KitchenridersClient kitchenridersClient; + + public TobeOrderService( + final OrderRepository orderRepository, + final MenuRepository menuRepository, + final OrderTableRepository orderTableRepository, + final KitchenridersClient kitchenridersClient + ) { + this.orderRepository = orderRepository; + this.menuRepository = menuRepository; + this.orderTableRepository = orderTableRepository; + this.kitchenridersClient = kitchenridersClient; + } + + @Transactional + public Order create(final Order request) { + final OrderType type = request.getType(); + if (Objects.isNull(type)) { + throw new IllegalArgumentException(); + } + final List orderLineItemRequests = request.getOrderLineItems(); + if (Objects.isNull(orderLineItemRequests) || orderLineItemRequests.isEmpty()) { + throw new IllegalArgumentException(); + } + final List menus = menuRepository.findAllByIdIn( + orderLineItemRequests.stream() + .map(OrderLineItem::getMenuId) + .collect(Collectors.toList()) + ); + if (menus.size() != orderLineItemRequests.size()) { + throw new IllegalArgumentException(); + } + final List orderLineItems = new ArrayList<>(); + for (final OrderLineItem orderLineItemRequest : orderLineItemRequests) { + final long quantity = orderLineItemRequest.getQuantity(); + if (type != OrderType.EAT_IN) { + if (quantity < 0) { + throw new IllegalArgumentException(); + } + } + final Menu menu = menuRepository.findById(orderLineItemRequest.getMenuId()) + .orElseThrow(NoSuchElementException::new); + if (!menu.isDisplayed()) { + throw new IllegalStateException(); + } + if (menu.getPrice().compareTo(orderLineItemRequest.getPrice()) != 0) { + throw new IllegalArgumentException(); + } + final OrderLineItem orderLineItem = new OrderLineItem(); + orderLineItem.setMenu(menu); + orderLineItem.setQuantity(quantity); + orderLineItems.add(orderLineItem); + } + Order order = new Order(); + order.setId(UUID.randomUUID()); + order.setType(type); + order.setStatus(OrderStatus.WAITING); + order.setOrderDateTime(LocalDateTime.now()); + order.setOrderLineItems(orderLineItems); + if (type == OrderType.DELIVERY) { + final String deliveryAddress = request.getDeliveryAddress(); + if (Objects.isNull(deliveryAddress) || deliveryAddress.isEmpty()) { + throw new IllegalArgumentException(); + } + order.setDeliveryAddress(deliveryAddress); + } + if (type == OrderType.EAT_IN) { + final OrderTable orderTable = orderTableRepository.findById(request.getOrderTableId()) + .orElseThrow(NoSuchElementException::new); + if (!orderTable.isOccupied()) { + throw new IllegalStateException(); + } + order.setOrderTable(orderTable); + } + return orderRepository.save(order); + } + + @Transactional + public Order accept(final UUID orderId) { + final Order order = orderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + if (order.getStatus() != OrderStatus.WAITING) { + throw new IllegalStateException(); + } + if (order.getType() == OrderType.DELIVERY) { + BigDecimal sum = BigDecimal.ZERO; + for (final OrderLineItem orderLineItem : order.getOrderLineItems()) { + sum = orderLineItem.getMenu() + .getPrice() + .multiply(BigDecimal.valueOf(orderLineItem.getQuantity())); + } + kitchenridersClient.requestDelivery(orderId, sum, order.getDeliveryAddress()); + } + order.setStatus(OrderStatus.ACCEPTED); + return order; + } + + @Transactional + public Order serve(final UUID orderId) { + final Order order = orderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + if (order.getStatus() != OrderStatus.ACCEPTED) { + throw new IllegalStateException(); + } + order.setStatus(OrderStatus.SERVED); + return order; + } + + @Transactional + public Order startDelivery(final UUID orderId) { + final Order order = orderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + if (order.getType() != OrderType.DELIVERY) { + throw new IllegalStateException(); + } + if (order.getStatus() != OrderStatus.SERVED) { + throw new IllegalStateException(); + } + order.setStatus(OrderStatus.DELIVERING); + return order; + } + + @Transactional + public Order completeDelivery(final UUID orderId) { + final Order order = orderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + if (order.getStatus() != OrderStatus.DELIVERING) { + throw new IllegalStateException(); + } + order.setStatus(OrderStatus.DELIVERED); + return order; + } + + @Transactional + public Order complete(final UUID orderId) { + final Order order = orderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + final OrderType type = order.getType(); + final OrderStatus status = order.getStatus(); + if (type == OrderType.DELIVERY) { + if (status != OrderStatus.DELIVERED) { + throw new IllegalStateException(); + } + } + if (type == OrderType.TAKEOUT || type == OrderType.EAT_IN) { + if (status != OrderStatus.SERVED) { + throw new IllegalStateException(); + } + } + order.setStatus(OrderStatus.COMPLETED); + if (type == OrderType.EAT_IN) { + final OrderTable orderTable = order.getOrderTable(); + if (!orderRepository.existsByOrderTableAndStatusNot(orderTable, OrderStatus.COMPLETED)) { + orderTable.setNumberOfGuests(0); + orderTable.setOccupied(false); + } + } + return order; + } + + @Transactional(readOnly = true) + public List findAll() { + return orderRepository.findAll(); + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java new file mode 100644 index 000000000..facf926c3 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java @@ -0,0 +1,59 @@ +package kitchenpos.eatinorders.tobe.application; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.UUID; + +@Table(name = "order_table") +@Entity +public class TobeOrderTable { + @Column(name = "id", columnDefinition = "binary(16)") + @Id + private UUID id; + + @Column(name = "name", nullable = false) + private String name; + + @Column(name = "number_of_guests", nullable = false) + private int numberOfGuests; + + @Column(name = "occupied", nullable = false) + private boolean occupied; + + public TobeOrderTable() { + } + + public UUID getId() { + return id; + } + + public void setId(final UUID id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public int getNumberOfGuests() { + return numberOfGuests; + } + + public void setNumberOfGuests(final int numberOfGuests) { + this.numberOfGuests = numberOfGuests; + } + + public boolean isOccupied() { + return occupied; + } + + public void setOccupied(final boolean occupied) { + this.occupied = occupied; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java new file mode 100644 index 000000000..b12e0b2c5 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java @@ -0,0 +1,41 @@ +package kitchenpos.eatinorders.tobe.domain; + +import kitchenpos.eatinorders.domain.OrderLineItem; +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.domain.OrderTable; +import kitchenpos.eatinorders.domain.OrderType; + +import javax.persistence.*; +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +@Table(name = "orders") +@Entity +public class TobeOrder { + @Column(name = "id", columnDefinition = "binary(16)") + @Id + private UUID id; + + @Column(name = "status", nullable = false) + @Enumerated(EnumType.STRING) + private OrderStatus status; + + @Column(name = "order_date_time", nullable = false) + private LocalDateTime orderDateTime; + + private UUID orderTableId; + + @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 TobeOrder() { + } + +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderRepository.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderRepository.java new file mode 100644 index 000000000..73c49af4f --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderRepository.java @@ -0,0 +1,18 @@ +package kitchenpos.eatinorders.tobe.domain; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.application.TobeOrderTable; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface TobeOrderRepository { + TobeOrder save(TobeOrder order); + + Optional findById(UUID id); + + List findAll(); + + boolean existsByOrderTableAndStatusNot(TobeOrderTable orderTable, OrderStatus status); +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTableRepository.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTableRepository.java new file mode 100644 index 000000000..5ae951a91 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTableRepository.java @@ -0,0 +1,15 @@ +package kitchenpos.eatinorders.tobe.domain; + +import kitchenpos.eatinorders.tobe.application.TobeOrderTable; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface TobeOrderTableRepository { + TobeOrderTable save(TobeOrderTable orderTable); + + Optional findById(UUID id); + + List findAll(); +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderRepository.java b/src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderRepository.java new file mode 100644 index 000000000..029d48dcf --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderRepository.java @@ -0,0 +1,10 @@ +package kitchenpos.eatinorders.tobe.infra; + +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderRepository; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +public interface JpaTobeOrderRepository extends TobeOrderRepository, JpaRepository { +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderTableRepository.java b/src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderTableRepository.java new file mode 100644 index 000000000..f5894e685 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderTableRepository.java @@ -0,0 +1,10 @@ +package kitchenpos.eatinorders.tobe.infra; + +import kitchenpos.eatinorders.tobe.application.TobeOrderTable; +import kitchenpos.eatinorders.tobe.domain.TobeOrderTableRepository; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +public interface JpaTobeOrderTableRepository extends TobeOrderTableRepository, JpaRepository { +} diff --git a/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java b/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java new file mode 100644 index 000000000..0a860373a --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java @@ -0,0 +1,7 @@ +package kitchenpos.eatinorders.tobe.application; + +import static org.junit.jupiter.api.Assertions.*; + +class TobeOrderServiceTest { + +} diff --git a/src/test/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTest.java b/src/test/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTest.java new file mode 100644 index 000000000..201edb8b6 --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTest.java @@ -0,0 +1,7 @@ +package kitchenpos.eatinorders.tobe.domain; + +import static org.junit.jupiter.api.Assertions.*; + +class TobeOrderTest { + +} From c1feb47d994c7b28bb958ec3191c8a6caf23bb59 Mon Sep 17 00:00:00 2001 From: saerang Date: Sun, 24 Sep 2023 23:18:04 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat(order):=20step3=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=A4=80=EB=B9=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tobe/application/TobeOrderService.java | 186 ++++++-------- .../tobe/application/TobeOrderTable.java | 9 +- .../dto/TobeOrderCreateRequest.java | 45 ++++ .../dto/TobeOrderCreateResponse.java | 86 +++++++ .../dto/TobeOrderLineItemRequest.java | 36 +++ .../application/dto/TobeOrderResponse.java | 86 +++++++ .../eatinorders/tobe/domain/OrderMenu.java | 29 +++ .../tobe/domain/TobeMenuClient.java | 10 + .../eatinorders/tobe/domain/TobeOrder.java | 57 ++++- .../tobe/domain/TobeOrderLineItem.java | 58 +++++ .../tobe/infra/DefaultTobeMenuClient.java | 37 +++ .../menus/tobe/domain/menu/TobeMenu.java | 5 + src/test/java/kitchenpos/TobeFixtures.java | 44 +++- .../application/InMemoryTobeMenuClient.java | 33 +++ .../InMemoryTobeOrderRepository.java | 39 +++ .../InMemoryTobeOrderTableRepository.java | 30 +++ .../application/TobeOrderServiceTest.java | 238 +++++++++++++++++- 17 files changed, 907 insertions(+), 121 deletions(-) create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateRequest.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateResponse.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderLineItemRequest.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderResponse.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/domain/OrderMenu.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/domain/TobeMenuClient.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItem.java create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/infra/DefaultTobeMenuClient.java create mode 100644 src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeMenuClient.java create mode 100644 src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderRepository.java create mode 100644 src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderTableRepository.java diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java index 0ce307e84..df6d8e264 100644 --- a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java @@ -1,19 +1,19 @@ package kitchenpos.eatinorders.tobe.application; -import kitchenpos.deliveryorders.infra.KitchenridersClient; -import kitchenpos.eatinorders.domain.Order; -import kitchenpos.eatinorders.domain.OrderLineItem; -import kitchenpos.eatinorders.domain.OrderRepository; import kitchenpos.eatinorders.domain.OrderStatus; -import kitchenpos.eatinorders.domain.OrderTable; -import kitchenpos.eatinorders.domain.OrderTableRepository; -import kitchenpos.eatinorders.domain.OrderType; -import kitchenpos.menus.domain.Menu; -import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderCreateRequest; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderCreateResponse; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderLineItemRequest; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderResponse; +import kitchenpos.eatinorders.tobe.domain.OrderMenu; +import kitchenpos.eatinorders.tobe.domain.TobeMenuClient; +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; +import kitchenpos.eatinorders.tobe.domain.TobeOrderRepository; +import kitchenpos.eatinorders.tobe.domain.TobeOrderTableRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -24,171 +24,131 @@ @Service public class TobeOrderService { - private final OrderRepository orderRepository; - private final MenuRepository menuRepository; - private final OrderTableRepository orderTableRepository; - private final KitchenridersClient kitchenridersClient; + private final TobeOrderRepository orderRepository; + private final TobeMenuClient tobeMenuClient; + private final TobeOrderTableRepository orderTableRepository; public TobeOrderService( - final OrderRepository orderRepository, - final MenuRepository menuRepository, - final OrderTableRepository orderTableRepository, - final KitchenridersClient kitchenridersClient + final TobeOrderRepository orderRepository, + final TobeMenuClient tobeMenuClient, + final TobeOrderTableRepository orderTableRepository ) { this.orderRepository = orderRepository; - this.menuRepository = menuRepository; + this.tobeMenuClient = tobeMenuClient; this.orderTableRepository = orderTableRepository; - this.kitchenridersClient = kitchenridersClient; } @Transactional - public Order create(final Order request) { - final OrderType type = request.getType(); - if (Objects.isNull(type)) { - throw new IllegalArgumentException(); - } - final List orderLineItemRequests = request.getOrderLineItems(); + public TobeOrderCreateResponse create(final TobeOrderCreateRequest request) { + final List orderLineItemRequests = request.getOrderLineItems(); if (Objects.isNull(orderLineItemRequests) || orderLineItemRequests.isEmpty()) { throw new IllegalArgumentException(); } - final List menus = menuRepository.findAllByIdIn( + final List menus = tobeMenuClient.findAllByIdIn( orderLineItemRequests.stream() - .map(OrderLineItem::getMenuId) + .map(TobeOrderLineItemRequest::getMenuId) .collect(Collectors.toList()) ); if (menus.size() != orderLineItemRequests.size()) { throw new IllegalArgumentException(); } - final List orderLineItems = new ArrayList<>(); - for (final OrderLineItem orderLineItemRequest : orderLineItemRequests) { + final List orderLineItems = new ArrayList<>(); + for (final TobeOrderLineItemRequest orderLineItemRequest : orderLineItemRequests) { final long quantity = orderLineItemRequest.getQuantity(); - if (type != OrderType.EAT_IN) { - if (quantity < 0) { - throw new IllegalArgumentException(); - } - } - final Menu menu = menuRepository.findById(orderLineItemRequest.getMenuId()) - .orElseThrow(NoSuchElementException::new); - if (!menu.isDisplayed()) { + final OrderMenu orderMenu = tobeMenuClient.getOrderMenu(orderLineItemRequest.getMenuId()); + final OrderMenu menu = tobeMenuClient.getOrderMenu(orderLineItemRequest.getMenuId()); + if (!orderMenu.isDisplayed()) { throw new IllegalStateException(); } - if (menu.getPrice().compareTo(orderLineItemRequest.getPrice()) != 0) { + if (orderMenu.getMenuPrice().compareTo(orderLineItemRequest.getPrice()) != 0) { throw new IllegalArgumentException(); } - final OrderLineItem orderLineItem = new OrderLineItem(); - orderLineItem.setMenu(menu); - orderLineItem.setQuantity(quantity); + final TobeOrderLineItem orderLineItem = new TobeOrderLineItem(quantity, menu.getId(), menu.getMenuPrice()); orderLineItems.add(orderLineItem); } - Order order = new Order(); - order.setId(UUID.randomUUID()); - order.setType(type); - order.setStatus(OrderStatus.WAITING); - order.setOrderDateTime(LocalDateTime.now()); - order.setOrderLineItems(orderLineItems); - if (type == OrderType.DELIVERY) { - final String deliveryAddress = request.getDeliveryAddress(); - if (Objects.isNull(deliveryAddress) || deliveryAddress.isEmpty()) { - throw new IllegalArgumentException(); - } - order.setDeliveryAddress(deliveryAddress); - } - if (type == OrderType.EAT_IN) { - final OrderTable orderTable = orderTableRepository.findById(request.getOrderTableId()) - .orElseThrow(NoSuchElementException::new); - if (!orderTable.isOccupied()) { - throw new IllegalStateException(); - } - order.setOrderTable(orderTable); + TobeOrder order = new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), request.getOrderTableId(), orderLineItems); + + final TobeOrderTable orderTable = orderTableRepository.findById(request.getOrderTableId()) + .orElseThrow(NoSuchElementException::new); + if (!orderTable.isOccupied()) { + throw new IllegalStateException(); } - return orderRepository.save(order); + order.setOrderTable(orderTable); + + TobeOrder savedOrder = orderRepository.save(order); + + return TobeOrderCreateResponse.from(savedOrder); } @Transactional - public Order accept(final UUID orderId) { - final Order order = orderRepository.findById(orderId) + public TobeOrderResponse accept(final UUID orderId) { + final TobeOrder order = orderRepository.findById(orderId) .orElseThrow(NoSuchElementException::new); if (order.getStatus() != OrderStatus.WAITING) { throw new IllegalStateException(); } - if (order.getType() == OrderType.DELIVERY) { - BigDecimal sum = BigDecimal.ZERO; - for (final OrderLineItem orderLineItem : order.getOrderLineItems()) { - sum = orderLineItem.getMenu() - .getPrice() - .multiply(BigDecimal.valueOf(orderLineItem.getQuantity())); - } - kitchenridersClient.requestDelivery(orderId, sum, order.getDeliveryAddress()); - } - order.setStatus(OrderStatus.ACCEPTED); - return order; + order.accept(); + + return TobeOrderResponse.from(order); } @Transactional - public Order serve(final UUID orderId) { - final Order order = orderRepository.findById(orderId) + public TobeOrderResponse serve(final UUID orderId) { + final TobeOrder order = orderRepository.findById(orderId) .orElseThrow(NoSuchElementException::new); if (order.getStatus() != OrderStatus.ACCEPTED) { throw new IllegalStateException(); } - order.setStatus(OrderStatus.SERVED); - return order; + order.served(); + + return TobeOrderResponse.from(order); } @Transactional - public Order startDelivery(final UUID orderId) { - final Order order = orderRepository.findById(orderId) + public TobeOrderResponse startDelivery(final UUID orderId) { + final TobeOrder order = orderRepository.findById(orderId) .orElseThrow(NoSuchElementException::new); - if (order.getType() != OrderType.DELIVERY) { - throw new IllegalStateException(); - } if (order.getStatus() != OrderStatus.SERVED) { throw new IllegalStateException(); } - order.setStatus(OrderStatus.DELIVERING); - return order; + order.delivering(); + + return TobeOrderResponse.from(order); } @Transactional - public Order completeDelivery(final UUID orderId) { - final Order order = orderRepository.findById(orderId) + public TobeOrderResponse completeDelivery(final UUID orderId) { + final TobeOrder order = orderRepository.findById(orderId) .orElseThrow(NoSuchElementException::new); if (order.getStatus() != OrderStatus.DELIVERING) { throw new IllegalStateException(); } - order.setStatus(OrderStatus.DELIVERED); - return order; + order.delivered(); + + return TobeOrderResponse.from(order); } @Transactional - public Order complete(final UUID orderId) { - final Order order = orderRepository.findById(orderId) + public TobeOrderResponse complete(final UUID orderId) { + final TobeOrder order = orderRepository.findById(orderId) .orElseThrow(NoSuchElementException::new); - final OrderType type = order.getType(); final OrderStatus status = order.getStatus(); - if (type == OrderType.DELIVERY) { - if (status != OrderStatus.DELIVERED) { - throw new IllegalStateException(); - } - } - if (type == OrderType.TAKEOUT || type == OrderType.EAT_IN) { - if (status != OrderStatus.SERVED) { - throw new IllegalStateException(); - } + + if (status != OrderStatus.SERVED) { + throw new IllegalStateException(); } - order.setStatus(OrderStatus.COMPLETED); - if (type == OrderType.EAT_IN) { - final OrderTable orderTable = order.getOrderTable(); - if (!orderRepository.existsByOrderTableAndStatusNot(orderTable, OrderStatus.COMPLETED)) { - orderTable.setNumberOfGuests(0); - orderTable.setOccupied(false); - } + order.completed(); + TobeOrderTable orderTable = orderTableRepository.findById(order.getOrderTableId()).orElseThrow(); + + if (!orderRepository.existsByOrderTableAndStatusNot(orderTable, OrderStatus.COMPLETED)) { + orderTable.setNumberOfGuests(0); + orderTable.setOccupied(false); } - return order; + return TobeOrderResponse.from(order); } @Transactional(readOnly = true) - public List findAll() { - return orderRepository.findAll(); + public List findAll() { + return orderRepository.findAll().stream().map(TobeOrderResponse::from).collect(Collectors.toList()); } } diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java index facf926c3..7020517c6 100644 --- a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java @@ -22,7 +22,14 @@ public class TobeOrderTable { @Column(name = "occupied", nullable = false) private boolean occupied; - public TobeOrderTable() { + protected TobeOrderTable() { + } + + public TobeOrderTable(final UUID id, final String name, final int numberOfGuests, final boolean occupied) { + this.id = id; + this.name = name; + this.numberOfGuests = numberOfGuests; + this.occupied = occupied; } public UUID getId() { diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateRequest.java b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateRequest.java new file mode 100644 index 000000000..d7291be7f --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateRequest.java @@ -0,0 +1,45 @@ +package kitchenpos.eatinorders.tobe.application.dto; + +import kitchenpos.eatinorders.domain.OrderStatus; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +public class TobeOrderCreateRequest { + private final UUID id; + private final OrderStatus status; + private final LocalDateTime orderDateTime; + private final List orderLineItems; + private final UUID orderTableId; + + public TobeOrderCreateRequest(final UUID id, final OrderStatus status, final LocalDateTime orderDateTime, + final List orderLineItems, + final UUID orderTableId) { + this.id = id; + this.status = status; + this.orderDateTime = orderDateTime; + this.orderLineItems = orderLineItems; + this.orderTableId = orderTableId; + } + + public UUID getId() { + return id; + } + + public OrderStatus getStatus() { + return status; + } + + public LocalDateTime getOrderDateTime() { + return orderDateTime; + } + + public List getOrderLineItems() { + return orderLineItems; + } + + public UUID getOrderTableId() { + return orderTableId; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateResponse.java b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateResponse.java new file mode 100644 index 000000000..29e3d87a2 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateResponse.java @@ -0,0 +1,86 @@ +package kitchenpos.eatinorders.tobe.application.dto; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +public class TobeOrderCreateResponse { + private final UUID id; + private final OrderStatus status; + private final LocalDateTime orderDateTime; + private final List orderLineItems; + private final UUID orderTableId; + + public static class TobeOrderLineItemResponse { + private final UUID menuId; + private final long quantity; + private final BigDecimal price; + + public TobeOrderLineItemResponse(final UUID menuId, final long quantity, final BigDecimal price) { + this.menuId = menuId; + this.quantity = quantity; + this.price = price; + } + + public static TobeOrderCreateResponse.TobeOrderLineItemResponse from(TobeOrderLineItem item) { + return new TobeOrderCreateResponse.TobeOrderLineItemResponse(item.getMenuId(), item.getQuantity(), item.getPrice()); + } + + public UUID getMenuId() { + return menuId; + } + + public long getQuantity() { + return quantity; + } + + public BigDecimal getPrice() { + return price; + } + } + + public TobeOrderCreateResponse(final UUID id, final OrderStatus status, final LocalDateTime orderDateTime, + final List orderLineItems, + final UUID orderTableId) { + this.id = id; + this.status = status; + this.orderDateTime = orderDateTime; + this.orderLineItems = orderLineItems; + this.orderTableId = orderTableId; + } + + public static TobeOrderCreateResponse from(TobeOrder tobeOrder) { + return new TobeOrderCreateResponse(tobeOrder.getId(), tobeOrder.getStatus(), tobeOrder.getOrderDateTime(), + tobeOrder.getOrderLineItems() + .stream() + .map(TobeOrderLineItemResponse::from) + .collect(Collectors.toList()), tobeOrder.getOrderTableId()); + + } + + public UUID getId() { + return id; + } + + public OrderStatus getStatus() { + return status; + } + + public LocalDateTime getOrderDateTime() { + return orderDateTime; + } + + public List getOrderLineItems() { + return orderLineItems; + } + + public UUID getOrderTableId() { + return orderTableId; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderLineItemRequest.java b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderLineItemRequest.java new file mode 100644 index 000000000..cb00f00bc --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderLineItemRequest.java @@ -0,0 +1,36 @@ +package kitchenpos.eatinorders.tobe.application.dto; + +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; + +import java.math.BigDecimal; +import java.util.UUID; + +public class TobeOrderLineItemRequest { + private final long seq; + private final UUID menuId; + private final long quantity; + private final BigDecimal price; + + public TobeOrderLineItemRequest(final long seq, final UUID menuId, final long quantity, final BigDecimal price) { + this.seq = seq; + this.menuId = menuId; + this.quantity = quantity; + this.price = price; + } + + public static TobeOrderLineItemRequest from(TobeOrderLineItem item) { + return new TobeOrderLineItemRequest(item.getSeq(), item.getMenuId(), item.getQuantity(), item.getPrice()); + } + + public UUID getMenuId() { + return menuId; + } + + public long getQuantity() { + return quantity; + } + + public BigDecimal getPrice() { + return price; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderResponse.java b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderResponse.java new file mode 100644 index 000000000..d46308890 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderResponse.java @@ -0,0 +1,86 @@ +package kitchenpos.eatinorders.tobe.application.dto; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +public class TobeOrderResponse { + private final UUID id; + private final OrderStatus status; + private final LocalDateTime orderDateTime; + private final List orderLineItems; + private final UUID orderTableId; + + public static class TobeOrderLineItemResponse { + private final UUID menuId; + private final long quantity; + private final BigDecimal price; + + public TobeOrderLineItemResponse(final UUID menuId, final long quantity, final BigDecimal price) { + this.menuId = menuId; + this.quantity = quantity; + this.price = price; + } + + public static TobeOrderResponse.TobeOrderLineItemResponse from(TobeOrderLineItem item) { + return new TobeOrderResponse.TobeOrderLineItemResponse(item.getMenuId(), item.getQuantity(), item.getPrice()); + } + + public UUID getMenuId() { + return menuId; + } + + public long getQuantity() { + return quantity; + } + + public BigDecimal getPrice() { + return price; + } + } + + public TobeOrderResponse(final UUID id, final OrderStatus status, final LocalDateTime orderDateTime, + final List orderLineItems, + final UUID orderTableId) { + this.id = id; + this.status = status; + this.orderDateTime = orderDateTime; + this.orderLineItems = orderLineItems; + this.orderTableId = orderTableId; + } + + public static TobeOrderResponse from(TobeOrder tobeOrder) { + return new TobeOrderResponse(tobeOrder.getId(), tobeOrder.getStatus(), tobeOrder.getOrderDateTime(), + tobeOrder.getOrderLineItems() + .stream() + .map(TobeOrderLineItemResponse::from) + .collect(Collectors.toList()), tobeOrder.getOrderTableId()); + + } + + public UUID getId() { + return id; + } + + public OrderStatus getStatus() { + return status; + } + + public LocalDateTime getOrderDateTime() { + return orderDateTime; + } + + public List getOrderLineItems() { + return orderLineItems; + } + + public UUID getOrderTableId() { + return orderTableId; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/OrderMenu.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/OrderMenu.java new file mode 100644 index 000000000..f5576e51e --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/OrderMenu.java @@ -0,0 +1,29 @@ +package kitchenpos.eatinorders.tobe.domain; + + +import java.math.BigDecimal; +import java.util.UUID; + +public class OrderMenu { + private final UUID id; + private final boolean displayed; + private final BigDecimal menuPrice; + + public OrderMenu(final UUID id, final boolean displayed, final BigDecimal menuPrice) { + this.id = id; + this.displayed = displayed; + this.menuPrice = menuPrice; + } + + public UUID getId() { + return id; + } + + public boolean isDisplayed() { + return displayed; + } + + public BigDecimal getMenuPrice() { + return menuPrice; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeMenuClient.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeMenuClient.java new file mode 100644 index 000000000..d09e9f98b --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeMenuClient.java @@ -0,0 +1,10 @@ +package kitchenpos.eatinorders.tobe.domain; + +import java.util.List; +import java.util.UUID; + +public interface TobeMenuClient { + OrderMenu getOrderMenu(UUID id); + + List findAllByIdIn(List ids); +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java index b12e0b2c5..e61c5143e 100644 --- a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java @@ -1,9 +1,7 @@ package kitchenpos.eatinorders.tobe.domain; -import kitchenpos.eatinorders.domain.OrderLineItem; import kitchenpos.eatinorders.domain.OrderStatus; -import kitchenpos.eatinorders.domain.OrderTable; -import kitchenpos.eatinorders.domain.OrderType; +import kitchenpos.eatinorders.tobe.application.TobeOrderTable; import javax.persistence.*; import java.time.LocalDateTime; @@ -33,9 +31,60 @@ public class TobeOrder { columnDefinition = "binary(16)", foreignKey = @ForeignKey(name = "fk_order_line_item_to_orders") ) - private List orderLineItems; + private List orderLineItems; protected TobeOrder() { } + public TobeOrder(final UUID id, final OrderStatus status, final LocalDateTime orderDateTime, final UUID orderTableId, final List orderLineItems) { + this.id = id; + this.status = status; + this.orderDateTime = orderDateTime; + this.orderTableId = orderTableId; + this.orderLineItems = orderLineItems; + } + + public void setOrderTable(final TobeOrderTable orderTable) { + this.orderTableId = orderTable.getId(); + } + + public UUID getId() { + return id; + } + + public OrderStatus getStatus() { + return status; + } + + public LocalDateTime getOrderDateTime() { + return orderDateTime; + } + + public UUID getOrderTableId() { + return orderTableId; + } + + public List getOrderLineItems() { + return orderLineItems; + } + + public void accept() { + this.status = OrderStatus.ACCEPTED; + } + + public void served() { + this.status = OrderStatus.SERVED; + } + + public void delivering() { + this.status = OrderStatus.DELIVERING; + } + + public void delivered() { + this.status = OrderStatus.DELIVERED; + } + + public void completed() { + this.status = OrderStatus.COMPLETED; + } } diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItem.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItem.java new file mode 100644 index 000000000..8f3933596 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItem.java @@ -0,0 +1,58 @@ +package kitchenpos.eatinorders.tobe.domain; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import java.math.BigDecimal; +import java.util.UUID; + +@Table(name = "order_line_item") +@Entity +public class TobeOrderLineItem { + @Column(name = "seq") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + private Long seq; + + @Column(name = "quantity", nullable = false) + private long quantity; + + private UUID menuId; + + @Transient + private BigDecimal price; + + protected TobeOrderLineItem() { + } + + public TobeOrderLineItem(final long quantity, final UUID menuId, final BigDecimal price) { + this(null, quantity, menuId, price); + } + + public TobeOrderLineItem(final Long seq, final long quantity, final UUID menuId, final BigDecimal price) { + this.seq = seq; + this.quantity = quantity; + this.menuId = menuId; + this.price = price; + } + + public Long getSeq() { + return seq; + } + + public long getQuantity() { + return quantity; + } + + public UUID getMenuId() { + return menuId; + } + + public BigDecimal getPrice() { + return price; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/infra/DefaultTobeMenuClient.java b/src/main/java/kitchenpos/eatinorders/tobe/infra/DefaultTobeMenuClient.java new file mode 100644 index 000000000..f9d4bfb3c --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/infra/DefaultTobeMenuClient.java @@ -0,0 +1,37 @@ +package kitchenpos.eatinorders.tobe.infra; + +import kitchenpos.eatinorders.tobe.domain.OrderMenu; +import kitchenpos.eatinorders.tobe.domain.TobeMenuClient; +import kitchenpos.menus.tobe.domain.menu.TobeMenu; +import kitchenpos.menus.tobe.domain.menu.TobeMenuRepository; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import java.util.stream.Collectors; + +@Component +public class DefaultTobeMenuClient implements TobeMenuClient { + private final TobeMenuRepository menuRepository; + + public DefaultTobeMenuClient(final TobeMenuRepository menuRepository) { + this.menuRepository = menuRepository; + } + + + @Override + public OrderMenu getOrderMenu(final UUID id) { + TobeMenu tobeMenu = menuRepository.findById(id) + .orElseThrow(() -> new NoSuchElementException("메뉴를 찾을 수 없습니다.")); + return new OrderMenu(id, tobeMenu.isDisplayed(), tobeMenu.getPriceValue()); + } + + @Override + public List findAllByIdIn(final List ids) { + List tobeMenus = menuRepository.findAllByIdIn(ids); + return tobeMenus.stream() + .map(it -> new OrderMenu(it.getId(), it.isDisplayed(), it.getPriceValue())) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/kitchenpos/menus/tobe/domain/menu/TobeMenu.java b/src/main/java/kitchenpos/menus/tobe/domain/menu/TobeMenu.java index 4819b5f11..85cc7fb4f 100644 --- a/src/main/java/kitchenpos/menus/tobe/domain/menu/TobeMenu.java +++ b/src/main/java/kitchenpos/menus/tobe/domain/menu/TobeMenu.java @@ -1,6 +1,7 @@ package kitchenpos.menus.tobe.domain.menu; import javax.persistence.*; +import java.math.BigDecimal; import java.util.List; import java.util.Objects; import java.util.UUID; @@ -88,6 +89,10 @@ public MenuPrice getPrice() { return price; } + public BigDecimal getPriceValue() { + return price.getPrice(); + } + public boolean isDisplayed() { return displayed; } diff --git a/src/test/java/kitchenpos/TobeFixtures.java b/src/test/java/kitchenpos/TobeFixtures.java index c8bcca5e8..b1db8ec4e 100644 --- a/src/test/java/kitchenpos/TobeFixtures.java +++ b/src/test/java/kitchenpos/TobeFixtures.java @@ -1,20 +1,26 @@ package kitchenpos; +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.application.TobeOrderTable; +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; import kitchenpos.menus.tobe.application.FakeMenuPurgomalumChecker; import kitchenpos.menus.tobe.domain.menu.MenuName; import kitchenpos.menus.tobe.domain.menu.MenuPrice; import kitchenpos.menus.tobe.domain.menu.TobeMenu; +import kitchenpos.menus.tobe.domain.menu.TobeMenuProduct; +import kitchenpos.menus.tobe.domain.menu.TobeMenuProductQuantity; import kitchenpos.menus.tobe.domain.menugroup.TobeMenuGroup; import kitchenpos.menus.tobe.domain.menugroup.TobeMenuGroupName; -import kitchenpos.menus.tobe.domain.menu.TobeMenuProductQuantity; -import kitchenpos.menus.tobe.domain.menu.TobeMenuProduct; import kitchenpos.products.application.FakePurgomalumChecker; import kitchenpos.products.tobe.domain.ProductName; import kitchenpos.products.tobe.domain.ProductPrice; import kitchenpos.products.tobe.domain.TobeProduct; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.Arrays; +import java.util.List; import java.util.Random; import java.util.UUID; @@ -62,4 +68,38 @@ public static TobeProduct product() { public static TobeProduct product(final String name, final long price) { return new TobeProduct(UUID.randomUUID(), new ProductName(name, new FakePurgomalumChecker()), new ProductPrice(BigDecimal.valueOf(price))); } + +// public static TobeOrder order(final OrderStatus status) { +// final TobeOrder order = new TobeOrder(UUID.randomUUID(), status, LocalDateTime.of(2020, 1, 1, 12, 0), +// +// ); +// order.setId(UUID.randomUUID()); +// order.setType(OrderType.DELIVERY); +// order.setStatus(status); +// order.setOrderDateTime(); +// order.setOrderLineItems(Arrays.asList(orderLineItem())); +// return order; +// } + + public static TobeOrder order(final OrderStatus status) { + return new TobeOrder(UUID.randomUUID(), status, LocalDateTime.of(2020, 1, 1, 12, 0), UUID.randomUUID(), + List.of(orderLineItem())); + } + + public static TobeOrder order(final OrderStatus status, final TobeOrderTable orderTable) { + return new TobeOrder(UUID.randomUUID(), status, LocalDateTime.of(2020, 1, 1, 12, 0), orderTable.getId(), + List.of(orderLineItem())); + } + + public static TobeOrderLineItem orderLineItem() { + return new TobeOrderLineItem(new Random().nextLong(), menu().getId(), BigDecimal.valueOf(16_000)); + } + +// public static TobeOrderLineItem orderTable() { +// return orderTable(false, 0); +// } + + public static TobeOrderTable orderTable(final boolean occupied, final int numberOfGuests) { + return new TobeOrderTable(UUID.randomUUID(), "1번", numberOfGuests, occupied); + } } diff --git a/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeMenuClient.java b/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeMenuClient.java new file mode 100644 index 000000000..d4cc5983f --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeMenuClient.java @@ -0,0 +1,33 @@ +package kitchenpos.eatinorders.tobe.application; + +import kitchenpos.eatinorders.tobe.domain.OrderMenu; +import kitchenpos.eatinorders.tobe.domain.TobeMenuClient; +import kitchenpos.menus.tobe.domain.menu.TobeMenu; +import kitchenpos.menus.tobe.domain.menu.TobeMenuRepository; + +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +public class InMemoryTobeMenuClient implements TobeMenuClient { + private final TobeMenuRepository tobeMenuRepository; + + public InMemoryTobeMenuClient(final TobeMenuRepository tobeMenuRepository) { + this.tobeMenuRepository = tobeMenuRepository; + } + + @Override + public OrderMenu getOrderMenu(final UUID id) { + TobeMenu menu = tobeMenuRepository.findById(id).orElseThrow(); + return new OrderMenu(menu.getId(), menu.isDisplayed(), menu.getPriceValue()); + } + + @Override + public List findAllByIdIn(final List ids) { + List tobeMenus = tobeMenuRepository.findAllByIdIn(ids); + return tobeMenus.stream() + .map(it -> new OrderMenu(it.getId(), it.isDisplayed(), it.getPriceValue())) + .collect(Collectors.toList()); + } + +} diff --git a/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderRepository.java b/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderRepository.java new file mode 100644 index 000000000..0773282ba --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderRepository.java @@ -0,0 +1,39 @@ +package kitchenpos.eatinorders.tobe.application; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderRepository; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +public class InMemoryTobeOrderRepository implements TobeOrderRepository { + private final Map orders = new HashMap<>(); + + @Override + public TobeOrder save(final TobeOrder order) { + orders.put(order.getId(), order); + return order; + } + + @Override + public Optional findById(final UUID id) { + return Optional.ofNullable(orders.get(id)); + } + + @Override + public List findAll() { + return new ArrayList<>(orders.values()); + } + + @Override + public boolean existsByOrderTableAndStatusNot(final TobeOrderTable orderTable, final OrderStatus status) { + return orders.values() + .stream() + .anyMatch(order -> order.getOrderTableId() == orderTable.getId() && order.getStatus() != status); + } +} diff --git a/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderTableRepository.java b/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderTableRepository.java new file mode 100644 index 000000000..470a54d7e --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderTableRepository.java @@ -0,0 +1,30 @@ +package kitchenpos.eatinorders.tobe.application; + +import kitchenpos.eatinorders.tobe.domain.TobeOrderTableRepository; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +public class InMemoryTobeOrderTableRepository implements TobeOrderTableRepository { + private final Map orderTables = new HashMap<>(); + + @Override + public TobeOrderTable save(final TobeOrderTable orderTable) { + orderTables.put(orderTable.getId(), orderTable); + return orderTable; + } + + @Override + public Optional findById(final UUID id) { + return Optional.ofNullable(orderTables.get(id)); + } + + @Override + public List findAll() { + return new ArrayList<>(orderTables.values()); + } +} diff --git a/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java b/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java index 0a860373a..6ed5e835c 100644 --- a/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java +++ b/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java @@ -1,7 +1,243 @@ package kitchenpos.eatinorders.tobe.application; -import static org.junit.jupiter.api.Assertions.*; +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderCreateRequest; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderCreateResponse; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderLineItemRequest; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderResponse; +import kitchenpos.eatinorders.tobe.domain.TobeMenuClient; +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderRepository; +import kitchenpos.eatinorders.tobe.domain.TobeOrderTableRepository; +import kitchenpos.menus.tobe.application.InMemoryTobeMenuRepository; +import kitchenpos.menus.tobe.domain.menu.TobeMenuRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Random; +import java.util.UUID; + +import static kitchenpos.Fixtures.INVALID_ID; +import static kitchenpos.TobeFixtures.menu; +import static kitchenpos.TobeFixtures.menuProduct; +import static kitchenpos.TobeFixtures.order; +import static kitchenpos.TobeFixtures.orderTable; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; class TobeOrderServiceTest { + private TobeOrderRepository orderRepository; + private TobeMenuRepository menuRepository; + private TobeOrderTableRepository orderTableRepository; + private TobeMenuClient tobeMenuClient; + private TobeOrderService orderService; + + @BeforeEach + void setUp() { + orderRepository = new InMemoryTobeOrderRepository(); + menuRepository = new InMemoryTobeMenuRepository(); + orderTableRepository = new InMemoryTobeOrderTableRepository(); + tobeMenuClient = new InMemoryTobeMenuClient(menuRepository); + orderService = new TobeOrderService(orderRepository, tobeMenuClient, orderTableRepository); + } + + @DisplayName("1개 이상의 등록된 메뉴로 매장 주문을 등록할 수 있다.") + @Test + void createEatInOrder() { + final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); + final UUID orderTableId = orderTableRepository.save(orderTable(true, 4)).getId(); + final TobeOrderCreateRequest expected = createOrderRequest(orderTableId, + createOrderLineItemRequest(menuId, 19_000L, 3L)); + final TobeOrderCreateResponse actual = orderService.create(expected); + assertThat(actual).isNotNull(); + assertAll( + () -> assertThat(actual.getId()).isNotNull(), + () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.WAITING), + () -> assertThat(actual.getOrderDateTime()).isNotNull(), + () -> assertThat(actual.getOrderLineItems()).hasSize(1), + () -> assertThat(actual.getOrderTableId()).isEqualTo(expected.getOrderTableId()) + ); + } + + @DisplayName("메뉴가 없으면 등록할 수 없다.") + @MethodSource("orderLineItems") + @ParameterizedTest + void create(final List orderLineItems) { + TobeOrderCreateRequest expected = createOrderRequest(orderLineItems); + assertThatThrownBy(() -> orderService.create(expected)) + .isInstanceOf(IllegalArgumentException.class); + } + + private static List orderLineItems() { + return Arrays.asList( + null, + Arguments.of(Collections.emptyList()), + Arguments.of(List.of(createOrderLineItemRequest(INVALID_ID, 19_000L, 3L))) + ); + } + + @DisplayName("매장 주문은 주문 항목의 수량이 0 미만일 수 있다.") + @ValueSource(longs = -1L) + @ParameterizedTest + void createEatInOrder(final long quantity) { + final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); + final UUID orderTableId = orderTableRepository.save(orderTable(true, 4)).getId(); + TobeOrderCreateRequest expected = createOrderRequest(orderTableId, + createOrderLineItemRequest(menuId, 19_000L, quantity)); + assertDoesNotThrow(() -> orderService.create(expected)); + } + + @DisplayName("빈 테이블에는 매장 주문을 등록할 수 없다.") + @Test + void createEmptyTableEatInOrder() { + final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); + final UUID orderTableId = orderTableRepository.save(orderTable(false, 0)).getId(); + final TobeOrderCreateRequest expected = createOrderRequest( + orderTableId, createOrderLineItemRequest(menuId, 19_000L, 3L) + ); + assertThatThrownBy(() -> orderService.create(expected)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("숨겨진 메뉴는 주문할 수 없다.") + @Test + void createNotDisplayedMenuOrder() { + final UUID menuId = menuRepository.save(menu(19_000L, false, menuProduct())).getId(); + final TobeOrderCreateRequest expected = createOrderRequest(createOrderLineItemRequest(menuId, 19_000L, 3L)); + assertThatThrownBy(() -> orderService.create(expected)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("주문한 메뉴의 가격은 실제 메뉴 가격과 일치해야 한다.") + @Test + void createNotMatchedMenuPriceOrder() { + final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); + final TobeOrderCreateRequest expected = createOrderRequest(createOrderLineItemRequest(menuId, 16_000L, 3L)); + assertThatThrownBy(() -> orderService.create(expected)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("주문을 접수한다.") + @Test + void accept() { + final UUID orderId = orderRepository.save(order(OrderStatus.WAITING, orderTable(true, 4))).getId(); + final TobeOrderResponse actual = orderService.accept(orderId); + assertThat(actual.getStatus()).isEqualTo(OrderStatus.ACCEPTED); + } + + @DisplayName("접수 대기 중인 주문만 접수할 수 있다.") + @EnumSource(value = OrderStatus.class, names = "WAITING", mode = EnumSource.Mode.EXCLUDE) + @ParameterizedTest + void accept(final OrderStatus status) { + final UUID orderId = orderRepository.save(order(status, orderTable(true, 4))).getId(); + assertThatThrownBy(() -> orderService.accept(orderId)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("주문을 서빙한다.") + @Test + void serve() { + final UUID orderId = orderRepository.save(order(OrderStatus.ACCEPTED)).getId(); + final TobeOrderResponse actual = orderService.serve(orderId); + assertThat(actual.getStatus()).isEqualTo(OrderStatus.SERVED); + } + + @DisplayName("접수된 주문만 서빙할 수 있다.") + @EnumSource(value = OrderStatus.class, names = "ACCEPTED", mode = EnumSource.Mode.EXCLUDE) + @ParameterizedTest + void serve(final OrderStatus status) { + final UUID orderId = orderRepository.save(order(status)).getId(); + assertThatThrownBy(() -> orderService.serve(orderId)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("서빙된 주문만 배달할 수 있다.") + @EnumSource(value = OrderStatus.class, names = "SERVED", mode = EnumSource.Mode.EXCLUDE) + @ParameterizedTest + void startDelivery(final OrderStatus status) { + final UUID orderId = orderRepository.save(order(status)).getId(); + assertThatThrownBy(() -> orderService.startDelivery(orderId)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("매장 주문의 경우 서빙된 주문만 완료할 수 있다.") + @EnumSource(value = OrderStatus.class, names = "SERVED", mode = EnumSource.Mode.EXCLUDE) + @ParameterizedTest + void completeTakeoutAndEatInOrder(final OrderStatus status) { + final UUID orderId = orderRepository.save(order(status)).getId(); + assertThatThrownBy(() -> orderService.complete(orderId)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("주문 테이블의 모든 매장 주문이 완료되면 빈 테이블로 설정한다.") + @Test + void completeEatInOrder() { + final TobeOrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); + final TobeOrder expected = orderRepository.save(order(OrderStatus.SERVED, orderTable)); + final TobeOrderResponse actual = orderService.complete(expected.getId()); + assertAll( + () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.COMPLETED), + () -> assertThat(orderTableRepository.findById(orderTable.getId()).get().isOccupied()).isFalse(), + () -> assertThat(orderTableRepository.findById(orderTable.getId()).get().getNumberOfGuests()).isEqualTo( + 0) + ); + } + + @DisplayName("완료되지 않은 매장 주문이 있는 주문 테이블은 빈 테이블로 설정하지 않는다.") + @Test + void completeNotTable() { + final TobeOrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); + orderRepository.save(order(OrderStatus.ACCEPTED, orderTable)); + final TobeOrder expected = orderRepository.save(order(OrderStatus.SERVED, orderTable)); + final TobeOrderResponse actual = orderService.complete(expected.getId()); + assertAll( + () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.COMPLETED), + () -> assertThat(orderTableRepository.findById(orderTable.getId()).get().isOccupied()).isTrue(), + () -> assertThat(orderTableRepository.findById(orderTable.getId()).get().getNumberOfGuests()).isEqualTo( + 4) + ); + } + + @DisplayName("주문의 목록을 조회할 수 있다.") + @Test + void findAll() { + final TobeOrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); + orderRepository.save(order(OrderStatus.SERVED, orderTable)); + orderRepository.save(order(OrderStatus.COMPLETED)); + final List actual = orderService.findAll(); + assertThat(actual).hasSize(2); + } + + private TobeOrderCreateRequest createOrderRequest(final TobeOrderLineItemRequest... orderLineItems) { + return createOrderRequest(Arrays.asList(orderLineItems)); + } + + private TobeOrderCreateRequest createOrderRequest(List orderLineItems) { + return new TobeOrderCreateRequest(UUID.randomUUID(), OrderStatus.ACCEPTED, LocalDateTime.now(), + orderLineItems, + UUID.randomUUID()); + } + + + private TobeOrderCreateRequest createOrderRequest(final UUID orderTableId, final TobeOrderLineItemRequest... orderLineItems) { + return new TobeOrderCreateRequest(UUID.randomUUID(), OrderStatus.ACCEPTED, LocalDateTime.now(), + Arrays.asList(orderLineItems), orderTableId); + } + private static TobeOrderLineItemRequest createOrderLineItemRequest(final UUID menuId, final long price, final long quantity) { + return new TobeOrderLineItemRequest(new Random().nextLong(), menuId, quantity, BigDecimal.valueOf(price)); + } } From ed749403f448de8edb6ad394ad479a0fe3f59383 Mon Sep 17 00:00:00 2001 From: saerang Date: Mon, 25 Sep 2023 00:06:24 +0900 Subject: [PATCH 3/4] refactor(order): refactor create order --- .../tobe/application/TobeOrderService.java | 88 ++++++------------- .../tobe/application/TobeOrderTable.java | 6 ++ .../dto/TobeOrderCreateRequest.java | 15 +++- .../dto/TobeOrderCreateResponse.java | 3 +- .../dto/TobeOrderLineItemRequest.java | 8 +- .../application/dto/TobeOrderResponse.java | 7 +- .../eatinorders/tobe/domain/TobeOrder.java | 29 +++--- .../tobe/domain/TobeOrderLineItems.java | 47 ++++++++++ .../application/TobeOrderServiceTest.java | 27 +++--- 9 files changed, 124 insertions(+), 106 deletions(-) create mode 100644 src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItems.java diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java index df6d8e264..ff42ce79a 100644 --- a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java @@ -9,13 +9,13 @@ import kitchenpos.eatinorders.tobe.domain.TobeMenuClient; import kitchenpos.eatinorders.tobe.domain.TobeOrder; import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItems; import kitchenpos.eatinorders.tobe.domain.TobeOrderRepository; import kitchenpos.eatinorders.tobe.domain.TobeOrderTableRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; @@ -29,9 +29,9 @@ public class TobeOrderService { private final TobeOrderTableRepository orderTableRepository; public TobeOrderService( - final TobeOrderRepository orderRepository, - final TobeMenuClient tobeMenuClient, - final TobeOrderTableRepository orderTableRepository + final TobeOrderRepository orderRepository, + final TobeMenuClient tobeMenuClient, + final TobeOrderTableRepository orderTableRepository ) { this.orderRepository = orderRepository; this.tobeMenuClient = tobeMenuClient; @@ -40,50 +40,40 @@ public TobeOrderService( @Transactional public TobeOrderCreateResponse create(final TobeOrderCreateRequest request) { - final List orderLineItemRequests = request.getOrderLineItems(); - if (Objects.isNull(orderLineItemRequests) || orderLineItemRequests.isEmpty()) { - throw new IllegalArgumentException(); - } - final List menus = tobeMenuClient.findAllByIdIn( - orderLineItemRequests.stream() - .map(TobeOrderLineItemRequest::getMenuId) - .collect(Collectors.toList()) - ); - if (menus.size() != orderLineItemRequests.size()) { + TobeOrderLineItems tobeOrderLineItems = getTobeOrderLineItem(request.getOrderLineItems()); + final TobeOrderTable orderTable = orderTableRepository.findById(request.getOrderTableId()) + .orElseThrow(NoSuchElementException::new); + orderTable.validateCreateOrder(); + + TobeOrder order = new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), orderTable.getId(), + tobeOrderLineItems); + TobeOrder savedOrder = orderRepository.save(order); + return TobeOrderCreateResponse.from(savedOrder); + } + + private TobeOrderLineItems getTobeOrderLineItem(final List requests) { + if (Objects.isNull(requests) || requests.isEmpty()) { throw new IllegalArgumentException(); } - final List orderLineItems = new ArrayList<>(); - for (final TobeOrderLineItemRequest orderLineItemRequest : orderLineItemRequests) { - final long quantity = orderLineItemRequest.getQuantity(); - final OrderMenu orderMenu = tobeMenuClient.getOrderMenu(orderLineItemRequest.getMenuId()); - final OrderMenu menu = tobeMenuClient.getOrderMenu(orderLineItemRequest.getMenuId()); + + List tobeOrderLineItems = requests.stream().map(it -> { + final OrderMenu orderMenu = tobeMenuClient.getOrderMenu(it.getMenuId()); if (!orderMenu.isDisplayed()) { throw new IllegalStateException(); } - if (orderMenu.getMenuPrice().compareTo(orderLineItemRequest.getPrice()) != 0) { + if (orderMenu.getMenuPrice().compareTo(it.getPrice()) != 0) { throw new IllegalArgumentException(); } - final TobeOrderLineItem orderLineItem = new TobeOrderLineItem(quantity, menu.getId(), menu.getMenuPrice()); - orderLineItems.add(orderLineItem); - } - TobeOrder order = new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), request.getOrderTableId(), orderLineItems); - - final TobeOrderTable orderTable = orderTableRepository.findById(request.getOrderTableId()) - .orElseThrow(NoSuchElementException::new); - if (!orderTable.isOccupied()) { - throw new IllegalStateException(); - } - order.setOrderTable(orderTable); - - TobeOrder savedOrder = orderRepository.save(order); + return new TobeOrderLineItem(it.getQuantity(), orderMenu.getId(), orderMenu.getMenuPrice()); + }).collect(Collectors.toList()); - return TobeOrderCreateResponse.from(savedOrder); + return new TobeOrderLineItems(tobeOrderLineItems); } @Transactional public TobeOrderResponse accept(final UUID orderId) { final TobeOrder order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (order.getStatus() != OrderStatus.WAITING) { throw new IllegalStateException(); } @@ -95,7 +85,7 @@ public TobeOrderResponse accept(final UUID orderId) { @Transactional public TobeOrderResponse serve(final UUID orderId) { final TobeOrder order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (order.getStatus() != OrderStatus.ACCEPTED) { throw new IllegalStateException(); } @@ -104,34 +94,10 @@ public TobeOrderResponse serve(final UUID orderId) { return TobeOrderResponse.from(order); } - @Transactional - public TobeOrderResponse startDelivery(final UUID orderId) { - final TobeOrder order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); - if (order.getStatus() != OrderStatus.SERVED) { - throw new IllegalStateException(); - } - order.delivering(); - - return TobeOrderResponse.from(order); - } - - @Transactional - public TobeOrderResponse completeDelivery(final UUID orderId) { - final TobeOrder order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); - if (order.getStatus() != OrderStatus.DELIVERING) { - throw new IllegalStateException(); - } - order.delivered(); - - return TobeOrderResponse.from(order); - } - @Transactional public TobeOrderResponse complete(final UUID orderId) { final TobeOrder order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); final OrderStatus status = order.getStatus(); if (status != OrderStatus.SERVED) { diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java index 7020517c6..cc95a07d7 100644 --- a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java @@ -32,6 +32,12 @@ public TobeOrderTable(final UUID id, final String name, final int numberOfGuests this.occupied = occupied; } + public void validateCreateOrder() { + if (!this.occupied) { + throw new IllegalStateException(); + } + } + public UUID getId() { return id; } diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateRequest.java b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateRequest.java index d7291be7f..1b2fb046e 100644 --- a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateRequest.java +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateRequest.java @@ -1,10 +1,15 @@ package kitchenpos.eatinorders.tobe.application.dto; import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItems; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.UUID; +import java.util.stream.Collectors; public class TobeOrderCreateRequest { private final UUID id; @@ -23,6 +28,12 @@ public TobeOrderCreateRequest(final UUID id, final OrderStatus status, final Loc this.orderTableId = orderTableId; } + public TobeOrderLineItems tobeOrderLineItems() { + return new TobeOrderLineItems(orderLineItems.stream() + .map(TobeOrderLineItemRequest::toDomain) + .collect(Collectors.toList())); + } + public UUID getId() { return id; } @@ -31,10 +42,6 @@ public OrderStatus getStatus() { return status; } - public LocalDateTime getOrderDateTime() { - return orderDateTime; - } - public List getOrderLineItems() { return orderLineItems; } diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateResponse.java b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateResponse.java index 29e3d87a2..48d6235bd 100644 --- a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateResponse.java +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateResponse.java @@ -57,8 +57,7 @@ public TobeOrderCreateResponse(final UUID id, final OrderStatus status, final Lo public static TobeOrderCreateResponse from(TobeOrder tobeOrder) { return new TobeOrderCreateResponse(tobeOrder.getId(), tobeOrder.getStatus(), tobeOrder.getOrderDateTime(), - tobeOrder.getOrderLineItems() - .stream() + tobeOrder.getOrderLineItemsStream() .map(TobeOrderLineItemResponse::from) .collect(Collectors.toList()), tobeOrder.getOrderTableId()); diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderLineItemRequest.java b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderLineItemRequest.java index cb00f00bc..91b5f2156 100644 --- a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderLineItemRequest.java +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderLineItemRequest.java @@ -6,12 +6,12 @@ import java.util.UUID; public class TobeOrderLineItemRequest { - private final long seq; + private final Long seq; private final UUID menuId; private final long quantity; private final BigDecimal price; - public TobeOrderLineItemRequest(final long seq, final UUID menuId, final long quantity, final BigDecimal price) { + public TobeOrderLineItemRequest(final Long seq, final UUID menuId, final long quantity, final BigDecimal price) { this.seq = seq; this.menuId = menuId; this.quantity = quantity; @@ -22,6 +22,10 @@ public static TobeOrderLineItemRequest from(TobeOrderLineItem item) { return new TobeOrderLineItemRequest(item.getSeq(), item.getMenuId(), item.getQuantity(), item.getPrice()); } + public TobeOrderLineItem toDomain() { + return new TobeOrderLineItem(this.seq, this.quantity, this.menuId, this.price); + } + public UUID getMenuId() { return menuId; } diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderResponse.java b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderResponse.java index d46308890..d610219d0 100644 --- a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderResponse.java +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderResponse.java @@ -57,10 +57,9 @@ public TobeOrderResponse(final UUID id, final OrderStatus status, final LocalDat public static TobeOrderResponse from(TobeOrder tobeOrder) { return new TobeOrderResponse(tobeOrder.getId(), tobeOrder.getStatus(), tobeOrder.getOrderDateTime(), - tobeOrder.getOrderLineItems() - .stream() - .map(TobeOrderLineItemResponse::from) - .collect(Collectors.toList()), tobeOrder.getOrderTableId()); + tobeOrder.getOrderLineItemsStream() + .map(TobeOrderLineItemResponse::from) + .collect(Collectors.toList()), tobeOrder.getOrderTableId()); } diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java index e61c5143e..e9c955c59 100644 --- a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java @@ -7,6 +7,7 @@ import java.time.LocalDateTime; import java.util.List; import java.util.UUID; +import java.util.stream.Stream; @Table(name = "orders") @Entity @@ -24,28 +25,20 @@ public class TobeOrder { private UUID orderTableId; - @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; - + private TobeOrderLineItems tobeOrderLineItems; protected TobeOrder() { } public TobeOrder(final UUID id, final OrderStatus status, final LocalDateTime orderDateTime, final UUID orderTableId, final List orderLineItems) { + this(id, status, orderDateTime, orderTableId, new TobeOrderLineItems(orderLineItems)); + } + + public TobeOrder(final UUID id, final OrderStatus status, final LocalDateTime orderDateTime, final UUID orderTableId, final TobeOrderLineItems orderLineItems) { this.id = id; this.status = status; this.orderDateTime = orderDateTime; this.orderTableId = orderTableId; - this.orderLineItems = orderLineItems; - } - - public void setOrderTable(final TobeOrderTable orderTable) { - this.orderTableId = orderTable.getId(); + this.tobeOrderLineItems = orderLineItems; } public UUID getId() { @@ -64,8 +57,12 @@ public UUID getOrderTableId() { return orderTableId; } - public List getOrderLineItems() { - return orderLineItems; + public TobeOrderLineItems getOrderLineItems() { + return tobeOrderLineItems; + } + + public Stream getOrderLineItemsStream() { + return tobeOrderLineItems.getOrderLineItems().stream(); } public void accept() { diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItems.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItems.java new file mode 100644 index 000000000..cb1f723b3 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItems.java @@ -0,0 +1,47 @@ +package kitchenpos.eatinorders.tobe.domain; + +import javax.persistence.CascadeType; +import javax.persistence.Embeddable; +import javax.persistence.ForeignKey; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +@Embeddable +public class TobeOrderLineItems { + @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 TobeOrderLineItems() { + } + + public TobeOrderLineItems(final List orderLineItems) { + if (Objects.isNull(orderLineItems) || orderLineItems.isEmpty()) { + throw new IllegalArgumentException(); + } + this.orderLineItems = orderLineItems; + } + + public List getOrderLineItems() { + return orderLineItems; + } + + public List getMenuIds() { + return orderLineItems.stream().map(TobeOrderLineItem::getMenuId).collect(Collectors.toList()); + } + + public void validation(final int size) { + if (orderLineItems.size() != size) { + throw new IllegalArgumentException(); + } + } +} diff --git a/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java b/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java index 6ed5e835c..05848089e 100644 --- a/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java +++ b/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java @@ -18,6 +18,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.NullAndEmptySource; import org.junit.jupiter.params.provider.ValueSource; import java.math.BigDecimal; @@ -25,6 +26,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.NoSuchElementException; import java.util.Random; import java.util.UUID; @@ -72,8 +74,8 @@ void createEatInOrder() { ); } - @DisplayName("메뉴가 없으면 등록할 수 없다.") - @MethodSource("orderLineItems") + @DisplayName("메뉴가 비어 있으면 등록할 수 없다.") + @NullAndEmptySource @ParameterizedTest void create(final List orderLineItems) { TobeOrderCreateRequest expected = createOrderRequest(orderLineItems); @@ -81,12 +83,12 @@ void create(final List orderLineItems) { .isInstanceOf(IllegalArgumentException.class); } - private static List orderLineItems() { - return Arrays.asList( - null, - Arguments.of(Collections.emptyList()), - Arguments.of(List.of(createOrderLineItemRequest(INVALID_ID, 19_000L, 3L))) - ); + @DisplayName("메뉴가 없으면 등록할 수 없다.") + @Test + void create01() { + TobeOrderCreateRequest expected = createOrderRequest(List.of(createOrderLineItemRequest(INVALID_ID, 19_000L, 3L))); + assertThatThrownBy(() -> orderService.create(expected)) + .isInstanceOf(NoSuchElementException.class); } @DisplayName("매장 주문은 주문 항목의 수량이 0 미만일 수 있다.") @@ -164,15 +166,6 @@ void serve(final OrderStatus status) { .isInstanceOf(IllegalStateException.class); } - @DisplayName("서빙된 주문만 배달할 수 있다.") - @EnumSource(value = OrderStatus.class, names = "SERVED", mode = EnumSource.Mode.EXCLUDE) - @ParameterizedTest - void startDelivery(final OrderStatus status) { - final UUID orderId = orderRepository.save(order(status)).getId(); - assertThatThrownBy(() -> orderService.startDelivery(orderId)) - .isInstanceOf(IllegalStateException.class); - } - @DisplayName("매장 주문의 경우 서빙된 주문만 완료할 수 있다.") @EnumSource(value = OrderStatus.class, names = "SERVED", mode = EnumSource.Mode.EXCLUDE) @ParameterizedTest From 389634b9ac3247d36a250f8e99cab647a8972d83 Mon Sep 17 00:00:00 2001 From: saerang Date: Mon, 25 Sep 2023 00:19:26 +0900 Subject: [PATCH 4/4] =?UTF-8?q?refactor(order):=20=EC=A3=BC=EB=AC=B8=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tobe/application/TobeOrderService.java | 14 +-- .../eatinorders/tobe/domain/TobeOrder.java | 17 ++-- .../tobe/domain/TobeOrderTest.java | 89 ++++++++++++++++++- 3 files changed, 99 insertions(+), 21 deletions(-) diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java index ff42ce79a..a29ef12d1 100644 --- a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java @@ -74,9 +74,6 @@ private TobeOrderLineItems getTobeOrderLineItem(final List getOrderLineItemsStream() { } public void accept() { + if (status != OrderStatus.WAITING) { + throw new IllegalStateException(); + } this.status = OrderStatus.ACCEPTED; } public void served() { + if (status != OrderStatus.ACCEPTED) { + throw new IllegalStateException(); + } this.status = OrderStatus.SERVED; } - public void delivering() { - this.status = OrderStatus.DELIVERING; - } - - public void delivered() { - this.status = OrderStatus.DELIVERED; - } - public void completed() { + if (status != OrderStatus.SERVED) { + throw new IllegalStateException(); + } this.status = OrderStatus.COMPLETED; } } diff --git a/src/test/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTest.java b/src/test/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTest.java index 201edb8b6..fc353f017 100644 --- a/src/test/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTest.java +++ b/src/test/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTest.java @@ -1,7 +1,94 @@ package kitchenpos.eatinorders.tobe.domain; -import static org.junit.jupiter.api.Assertions.*; +import kitchenpos.TobeFixtures; +import kitchenpos.eatinorders.domain.OrderStatus; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; class TobeOrderTest { + @DisplayName("주문을 생성한다.") + @Test + void create() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + assertThat(tobeOrder.getId()).isNotNull(); + } + + @DisplayName("주문된 음식은 없을 수 없다.") + @Test + void create01() { + assertThatThrownBy(() -> new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), + UUID.randomUUID(), new TobeOrderLineItems(Collections.emptyList()))) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("주문을 접수한다.") + @Test + void accept01() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + tobeOrder.accept(); + assertThat(tobeOrder.getStatus()).isEqualTo(OrderStatus.ACCEPTED); + } + + @DisplayName("주문을 접수 시 주문이 준비중일 때만 가능하다.") + @Test + void accept02() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.ACCEPTED, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + assertThatThrownBy(() -> tobeOrder.accept()) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("주문을 서빙한다.") + @Test + void served01() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.ACCEPTED, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + tobeOrder.served(); + assertThat(tobeOrder.getStatus()).isEqualTo(OrderStatus.SERVED); + } + + @DisplayName("주문을 서빙 시 주문이 접수일 때만 가능하다.") + @Test + void served02() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + assertThatThrownBy(() -> tobeOrder.served()) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("주문을 종료한다.") + @Test + void completed01() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.SERVED, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + tobeOrder.completed(); + assertThat(tobeOrder.getStatus()).isEqualTo(OrderStatus.COMPLETED); + } + + @DisplayName("주문을 종료 시 주문이 서빙일 때만 가능하다.") + @Test + void completed02() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + assertThatThrownBy(() -> tobeOrder.completed()) + .isInstanceOf(IllegalStateException.class); + } }