diff --git a/README.md b/README.md index 93670e572..5b167b855 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ docker compose -p kitchenpos up -d | 한글명 | 영문명 | 설명 | | --- | --- | --- | +| 매장 주문 | eat in order | 매장에서 안에서의 주문 | | 방문한 손님 수 | number of guests | 식기가 필요한 사람 수. 필수 사항은 아니며 주문은 0명으로 등록할 수 있다. | | 빈 테이블 | empty table | 주문을 등록할 수 없는 주문 테이블 | | 서빙 | served | 조리가 완료되어 음식이 나갈 수 있는 단계 | @@ -134,18 +135,19 @@ docker compose -p kitchenpos up -d ### 배달 주문 -| 한글명 | 영문명 | 설명 | -| --- | --- | --- | -| 배달 | delivering | 배달원이 매장을 방문하여 배달 음식의 픽업을 완료하고 배달을 시작하는 단계 | -| 배달 대행사 | delivery agency | 준비한 음식을 고객에게 직접 배달하는 서비스 | -| 배달 완료 | delivered | 배달원이 주문한 음식을 고객에게 배달 완료한 단계 | -| 서빙 | served | 조리가 완료되어 음식이 나갈 수 있는 단계 | -| 완료 | completed | 배달 및 결제 완료 단계 | -| 접수 | accepted | 주문을 받고 음식을 조리하는 단계 | -| 접수 대기 | waiting | 주문이 생성되어 매장으로 전달된 단계 | -| 주문 | order | 집이나 직장 등 고객이 선택한 주소로 음식을 배달한다. | -| 주문 상태 | order status | 주문이 생성되면 매장에서 주문을 접수하고 고객이 음식을 받기까지의 단계를 표시한다. | -| 주문 항목 | order line item | 주문에 속하는 수량이 있는 메뉴 | +| 한글명 | 영문명 | 설명 | +|--------|----------------|------------------------------------------------| +| 배달 주문 | delivery order | 배달을 위한 주문 | +| 배달 | delivering | 배달원이 매장을 방문하여 배달 음식의 픽업을 완료하고 배달을 시작하는 단계 | +| 배달 대행사 | delivery agency | 준비한 음식을 고객에게 직접 배달하는 서비스 | +| 배달 완료 | delivered | 배달원이 주문한 음식을 고객에게 배달 완료한 단계 | +| 서빙 | served | 조리가 완료되어 음식이 나갈 수 있는 단계 | +| 완료 | completed | 배달이 완료된 후 주문을 마무리 하는 단계 | +| 접수 | accepted | 주문을 받고 음식을 조리하는 단계 | +| 접수 대기 | waiting | 주문이 생성되어 매장으로 전달된 단계 | +| 주문 | order | 집이나 직장 등 고객이 선택한 주소로 음식을 배달한다. | +| 주문 상태 | order status | 주문이 생성되면 매장에서 주문을 접수하고 고객이 음식을 받기까지의 단계를 표시한다. | +| 주문 항목 | order line item | 주문에 속하는 수량이 있는 메뉴 | ### 포장 주문 @@ -181,27 +183,42 @@ docker compose -p kitchenpos up -d ### 매장 주문 - `OrderTable`은 식별자와 이름, `NumberOfGuests`를 가진다. -- `OrderTable`의 추가 `Order`는 `OrderTable`에 계속 쌓이며 모든 `Order`가 완료되면 `EmptyTable`이 된다. +- `OrderTable`의 추가 `Order`는 `OrderTable`에 계속 쌓이며 모든 `EatInOrder`가 완료되면 `EmptyTable`이 된다. - `EmptyTable`인 경우 `NumberOfGuests`는 0이며 변경할 수 없다. -- `Order`는 식별자와 `OrderStatus`, 주문 시간, `OrderLineItems`를 가진다. -- 메뉴가 노출되고 있으며 판매되는 메뉴 가격과 일치하면 `Order`가 생성된다. -- `Order`는 접수 대기 ➜ 접수 ➜ 서빙 ➜ 계산 완료 순서로 진행된다. +- `EatInOrder`는 식별자와 `OrderStatus`, 주문 시간, `OrderLineItems`를 가진다. +- `Menu`가 `Display Menu`되고 있으며 판매되는 메뉴 가격과 일치하면 `EatInOrder`가 생성된다. +- `EatInOrder`는 접수 대기 ➜ 접수 ➜ 서빙 ➜ 계산 완료 순서로 진행된다. +- `EatInOrder`가 생성되면 `OrderStatus`는 `Waiting` 상태이다. +- `Accepted` 가 되려면 전 주문은 `Waiting` 상태여야 한다. +- `Served` 가 되려면 전 주문은 `Accepted` 상태여야 한다. +- `Completed` 가 되려면 전 주문은 `Served` 상태여야 한다. - `OrderLineItem`는 가격과 수량을 가진다. -- `OrderLineItem`의 수량은 기존 `Order`를 취소하거나 변경해도 수정되지 않기 때문에 0보다 적을 수 있다. +- `OrderLineItem`의 수량은 기존 `EatInOrder`를 취소하거나 변경해도 수정되지 않기 때문에 0보다 적을 수 있다. +- `` ### 배달 주문 -- `Order`는 식별자와 `OrderStatus`, 주문 시간, 배달 주소, `OrderLineItems`를 가진다. -- 메뉴가 노출되고 있으며 판매되는 메뉴 가격과 일치하면 `Order`가 생성된다. -- `Order`는 접수 대기 ➜ 접수 ➜ 서빙 ➜ 배달 ➜ 배달 완료 ➜ 계산 완료 순서로 진행된다. -- `Order`가 접수되면 `DeliveryAgency`가 호출된다. +- `Delivery Order`는 식별자와 `OrderStatus`, 주문 시간, 배달 주소, `OrderLineItems`를 가진다. +- 메뉴가 노출되고 있으며 판매되는 메뉴 가격과 일치하면 `Delivery Order`가 생성된다. +- `Delivery Order`는 접수 대기 ➜ 접수 ➜ 서빙 ➜ 배달 ➜ 배달 완료 ➜ 계산 완료 순서로 진행된다. +- `Delivery Order`가 생성되면 `OrderStatus`는 `Waiting` 상태이다. +- `Delivery Order`가 접수되면 `DeliveryAgency`가 호출된다. +- `Accepted` 가 되려면 전 주문은 `Waiting` 상태여야 한다. +- `Served` 가 되려면 전 주문은 `Accepted` 상태여야 한다. +- `Delivering` 가 되려면 전 주문은 `Served` 상태여야 한다. +- `Delivered` 가 되려면 전 주문은 `Delivering` 상태여야 한다. +- `Completed` 가 되려면 전 주문은 `Delivered` 상태여야 한다. - `OrderLineItem`는 가격과 수량을 가진다. - `OrderLineItem`의 수량은 1보다 커야 한다. ### 포장 주문 -- `Order`는 식별자와 `OrderStatus`, 주문 시간, `OrderLineItems`를 가진다. -- 메뉴가 노출되고 있으며 판매되는 메뉴 가격과 일치하면 `Order`가 생성된다. -- `Order`는 접수 대기 ➜ 접수 ➜ 서빙 ➜ 계산 완료 순서로 진행된다. +- `Take Out Order`는 식별자와 `OrderStatus`, 주문 시간, `OrderLineItems`를 가진다. +- 메뉴가 노출되고 있으며 판매되는 메뉴 가격과 일치하면 `Take Out Order`가 생성된다. +- `Take Out Order`는 접수 대기 ➜ 접수 ➜ 서빙 ➜ 계산 완료 순서로 진행된다. +- `Take Out Order`가 생성되면 `OrderStatus`는 `Waiting` 상태이다. +- `Accepted` 가 되려면 전 주문은 `Waiting` 상태여야 한다. +- `Served` 가 되려면 전 주문은 `Accepted` 상태여야 한다. +- `Completed` 가 되려면 전 주문은 `Served` 상태여야 한다. - `OrderLineItem`는 가격과 수량을 가진다. - `OrderLineItem`의 수량은 1보다 커야 한다. diff --git a/src/main/java/kitchenpos/deliveryorders/application/DeliveryOrderService.java b/src/main/java/kitchenpos/deliveryorders/application/DeliveryOrderService.java new file mode 100644 index 000000000..340e5b016 --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/application/DeliveryOrderService.java @@ -0,0 +1,107 @@ +package kitchenpos.deliveryorders.application; + +import kitchenpos.deliveryorders.domain.DeliveryOrder; +import kitchenpos.deliveryorders.domain.DeliveryOrderAddress; +import kitchenpos.deliveryorders.domain.DeliveryOrderLineItem; +import kitchenpos.deliveryorders.domain.DeliveryOrderLineItemPrice; +import kitchenpos.deliveryorders.domain.DeliveryOrderLineItemQuantity; +import kitchenpos.deliveryorders.domain.DeliveryOrderLineItems; +import kitchenpos.deliveryorders.domain.DeliveryOrderRepository; +import kitchenpos.deliveryorders.domain.KitchenridersClient; +import kitchenpos.deliveryorders.domain.MenuClient; +import kitchenpos.deliveryorders.shared.dto.DeliveryOrderLineItemDto; +import kitchenpos.deliveryorders.shared.dto.DeliveryOrderDto; +import kitchenpos.deliveryorders.shared.dto.request.DeliveryOrderCreateRequest; +import kitchenpos.shared.util.ConvertUtil; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +@Service +public class DeliveryOrderService { + private DeliveryOrderRepository deliveryOrderRepository; + private MenuClient menuClient; + private KitchenridersClient kitchenridersClient; + + public DeliveryOrderService(DeliveryOrderRepository deliveryOrderRepository, MenuClient menuClient, KitchenridersClient kitchenridersClient) { + this.deliveryOrderRepository = deliveryOrderRepository; + this.menuClient = menuClient; + this.kitchenridersClient = kitchenridersClient; + } + + @Transactional + public DeliveryOrderDto create(final DeliveryOrderCreateRequest request) { + final List orderLineItemRequests = request.getOrderLineItems(); + + if (Objects.isNull(orderLineItemRequests) || orderLineItemRequests.isEmpty()) { + throw new IllegalArgumentException(); + } + + List deliveryOrderLineItems = request.getOrderLineItems().stream() + .map(deliveryOrderLineItemDto -> DeliveryOrderLineItem.of( + deliveryOrderLineItemDto.getMenuId(), + new DeliveryOrderLineItemQuantity(deliveryOrderLineItemDto.getQuantity()), + new DeliveryOrderLineItemPrice(deliveryOrderLineItemDto.getPrice()), + menuClient + )) + .collect(Collectors.toList()); + + DeliveryOrder deliveryOrder = DeliveryOrder.of( + new DeliveryOrderLineItems(deliveryOrderLineItems), + new DeliveryOrderAddress(request.getDeliveryAddress()), + menuClient + ); + + return ConvertUtil.convert(deliveryOrderRepository.save(deliveryOrder), DeliveryOrderDto.class); + } + + @Transactional + public DeliveryOrderDto accept(final UUID orderId) { + DeliveryOrder deliveryOrder = deliveryOrderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + deliveryOrder.accept(kitchenridersClient); + return ConvertUtil.convert(deliveryOrder, DeliveryOrderDto.class); + } + + @Transactional + public DeliveryOrderDto serve(final UUID orderId) { + DeliveryOrder deliveryOrder = deliveryOrderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + deliveryOrder.serve(); + return ConvertUtil.convert(deliveryOrder, DeliveryOrderDto.class); + } + + @Transactional + public DeliveryOrderDto startDelivery(final UUID orderId) { + DeliveryOrder deliveryOrder = deliveryOrderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + deliveryOrder.startDelivery(); + return ConvertUtil.convert(deliveryOrder, DeliveryOrderDto.class); + } + + @Transactional + public DeliveryOrderDto completeDelivery(final UUID orderId) { + DeliveryOrder deliveryOrder = deliveryOrderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + deliveryOrder.completeDelivery(); + return ConvertUtil.convert(deliveryOrder, DeliveryOrderDto.class); + } + + @Transactional + public DeliveryOrderDto complete(final UUID orderId) { + DeliveryOrder deliveryOrder = deliveryOrderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + deliveryOrder.complete(); + return ConvertUtil.convert(deliveryOrder, DeliveryOrderDto.class); + } + + @Transactional(readOnly = true) + public List findAll() { + return ConvertUtil.convertList(deliveryOrderRepository.findAll(), DeliveryOrderDto.class); + } +} diff --git a/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrder.java b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrder.java new file mode 100644 index 000000000..c9f04ffc6 --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrder.java @@ -0,0 +1,120 @@ +package kitchenpos.deliveryorders.domain; + +import kitchenpos.eatinorders.domain.OrderStatus; + +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +@Table(name = "delivery_orders") +@Entity +public class DeliveryOrder { + @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; + + @Embedded + private DeliveryOrderLineItems orderLineItems; + + @Embedded + private DeliveryOrderAddress deliveryAddress; + + protected DeliveryOrder() { + } + + public DeliveryOrder(UUID id, OrderStatus status, LocalDateTime orderDateTime, DeliveryOrderLineItems orderLineItems, DeliveryOrderAddress deliveryAddress) { + this.id = id; + this.status = status; + this.orderDateTime = orderDateTime; + this.orderLineItems = orderLineItems; + this.deliveryAddress = deliveryAddress; + } + + public static DeliveryOrder of(DeliveryOrderLineItems orderLineItems, DeliveryOrderAddress orderAddress, MenuClient menuClient) { + validateDeliveryOrder(orderLineItems, menuClient); + return new DeliveryOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), orderLineItems, orderAddress); + } + + private static void validateDeliveryOrder(DeliveryOrderLineItems orderLineItems, MenuClient menuClient) { + int menusSize = menuClient.countAllByIdIn( + orderLineItems.getOrderLineItems().stream() + .map(DeliveryOrderLineItem::getMenuId) + .collect(Collectors.toList()) + ); + if (menusSize != orderLineItems.getOrderLineItems().size()) { + throw new IllegalArgumentException(); + } + } + + public UUID getId() { + return id; + } + + public OrderStatus getStatus() { + return status; + } + + public LocalDateTime getOrderDateTime() { + return orderDateTime; + } + + public List getOrderLineItems() { + return orderLineItems.getOrderLineItems(); + } + + public String getDeliveryAddress() { + return deliveryAddress.getDeliveryOrderAddress(); + } + + public void accept(KitchenridersClient kitchenridersClient) { + if (status != OrderStatus.WAITING) { + throw new IllegalStateException(); + } + + kitchenridersClient.requestDelivery(id, orderLineItems.getTotalDeliveryOrderLineItemsPrice(), getDeliveryAddress()); + status = OrderStatus.ACCEPTED; + } + + public void serve() { + if (status != OrderStatus.ACCEPTED) { + throw new IllegalStateException(); + } + this.status = OrderStatus.SERVED; + } + + public void startDelivery() { + if (status != OrderStatus.SERVED) { + throw new IllegalStateException(); + } + status = OrderStatus.DELIVERING; + } + + public void completeDelivery() { + if (status != OrderStatus.DELIVERING) { + throw new IllegalStateException(); + } + status = OrderStatus.DELIVERED; + } + + public void complete() { + if (status != OrderStatus.DELIVERED) { + throw new IllegalStateException(); + } + status = OrderStatus.COMPLETED; + } +} diff --git a/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderAddress.java b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderAddress.java new file mode 100644 index 000000000..27c26097f --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderAddress.java @@ -0,0 +1,42 @@ +package kitchenpos.deliveryorders.domain; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.util.Objects; + +@Embeddable +public class DeliveryOrderAddress { + @Column(name = "address", nullable = false) + private String deliveryOrderAddress; + + protected DeliveryOrderAddress() { + } + + public DeliveryOrderAddress(String deliveryOrderAddress) { + validateDeliveryOrderAddress(deliveryOrderAddress); + this.deliveryOrderAddress = deliveryOrderAddress; + } + + private void validateDeliveryOrderAddress(String deliveryOrderAddress) { + if (Objects.isNull(deliveryOrderAddress) || deliveryOrderAddress.isEmpty()) { + throw new IllegalArgumentException(); + } + } + + public String getDeliveryOrderAddress() { + return deliveryOrderAddress; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DeliveryOrderAddress that = (DeliveryOrderAddress) o; + return Objects.equals(deliveryOrderAddress, that.deliveryOrderAddress); + } + + @Override + public int hashCode() { + return Objects.hash(deliveryOrderAddress); + } +} diff --git a/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItem.java b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItem.java new file mode 100644 index 000000000..809fca691 --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItem.java @@ -0,0 +1,84 @@ +package kitchenpos.deliveryorders.domain; + +import kitchenpos.menus.tobe.domain.menu.Menu; + +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import java.math.BigDecimal; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.UUID; + +@Table(name = "delivery_order_line_item") +@Entity +public class DeliveryOrderLineItem { + @Column(name = "seq") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + private Long seq; + + private UUID menuId; + + @Embedded + private DeliveryOrderLineItemQuantity quantity; + + @Embedded + private DeliveryOrderLineItemPrice price; + + protected DeliveryOrderLineItem() { + } + + public DeliveryOrderLineItem(UUID menuId, DeliveryOrderLineItemQuantity quantity, DeliveryOrderLineItemPrice price) { + this.menuId = menuId; + this.quantity = quantity; + this.price = price; + } + + public static DeliveryOrderLineItem of(UUID menuId, DeliveryOrderLineItemQuantity quantity, DeliveryOrderLineItemPrice price, MenuClient menuClient) { + validateDeliveryOrderLineItem(menuId, price, menuClient); + return new DeliveryOrderLineItem(menuId, quantity, price); + } + + private static void validateDeliveryOrderLineItem(UUID menuId, DeliveryOrderLineItemPrice price, MenuClient menuClient) { + Menu menu = menuClient.findById(menuId) + .orElseThrow(() -> new NoSuchElementException("메뉴가 존재하지 않습니다. menuId: " + menuId)); + + if (!menu.isDisplayed()) { + throw new IllegalStateException(); + } + + if (menu.getPrice().compareTo(price.getDeliveryOrderLineItemPrice()) != 0) { + throw new IllegalArgumentException(); + } + } + + public UUID getMenuId() { + return menuId; + } + + public long getQuantity() { + return quantity.getQuantity(); + } + + public BigDecimal getPrice() { + return price.getDeliveryOrderLineItemPrice(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DeliveryOrderLineItem that = (DeliveryOrderLineItem) o; + return Objects.equals(seq, that.seq); + } + + @Override + public int hashCode() { + return Objects.hash(seq); + } +} diff --git a/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItemPrice.java b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItemPrice.java new file mode 100644 index 000000000..df97858b4 --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItemPrice.java @@ -0,0 +1,36 @@ +package kitchenpos.deliveryorders.domain; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.math.BigDecimal; +import java.util.Objects; + +@Embeddable +public class DeliveryOrderLineItemPrice { + @Column(name = "price", nullable = false) + private BigDecimal deliveryOrderLineItemPrice; + + protected DeliveryOrderLineItemPrice() { + } + + public DeliveryOrderLineItemPrice(BigDecimal deliveryOrderLineItemPrice) { + this.deliveryOrderLineItemPrice = deliveryOrderLineItemPrice; + } + + public BigDecimal getDeliveryOrderLineItemPrice() { + return deliveryOrderLineItemPrice; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DeliveryOrderLineItemPrice that = (DeliveryOrderLineItemPrice) o; + return Objects.equals(deliveryOrderLineItemPrice, that.deliveryOrderLineItemPrice); + } + + @Override + public int hashCode() { + return Objects.hash(deliveryOrderLineItemPrice); + } +} diff --git a/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItemQuantity.java b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItemQuantity.java new file mode 100644 index 000000000..58c0f4943 --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItemQuantity.java @@ -0,0 +1,28 @@ +package kitchenpos.deliveryorders.domain; + +import javax.persistence.Column; +import javax.persistence.Embeddable; + +@Embeddable +public class DeliveryOrderLineItemQuantity { + @Column + private long quantity; + + protected DeliveryOrderLineItemQuantity() { + } + + public DeliveryOrderLineItemQuantity(long quantity) { + validateDeliveryOrderLineItemQuantity(quantity); + this.quantity = quantity; + } + + private void validateDeliveryOrderLineItemQuantity(long quantity) { + if (quantity < 0) { + throw new IllegalArgumentException("배달 주문의 주문 항목 개수는 0이상이어야 합니다."); + } + } + + public long getQuantity() { + return quantity; + } +} diff --git a/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItems.java b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItems.java new file mode 100644 index 000000000..a5e3d432e --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItems.java @@ -0,0 +1,44 @@ +package kitchenpos.deliveryorders.domain; + +import javax.persistence.CascadeType; +import javax.persistence.Embeddable; +import javax.persistence.ForeignKey; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import java.math.BigDecimal; +import java.util.List; + +@Embeddable +public class DeliveryOrderLineItems { + @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 DeliveryOrderLineItems() { + } + + public DeliveryOrderLineItems(List orderLineItems) { + validateDeliveryOrderLineItems(orderLineItems); + this.orderLineItems = orderLineItems; + } + + private void validateDeliveryOrderLineItems(List orderLineItems) { + if (orderLineItems.isEmpty()) { + throw new IllegalArgumentException(); + } + } + + public List getOrderLineItems() { + return orderLineItems; + } + + public BigDecimal getTotalDeliveryOrderLineItemsPrice() { + return orderLineItems.stream().map(DeliveryOrderLineItem::getPrice) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } +} diff --git a/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderRepository.java b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderRepository.java new file mode 100644 index 000000000..876cbf848 --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/domain/DeliveryOrderRepository.java @@ -0,0 +1,11 @@ +package kitchenpos.deliveryorders.domain; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface DeliveryOrderRepository { + DeliveryOrder save(DeliveryOrder deliveryOrder); + Optional findById(final UUID id); + List findAll(); +} diff --git a/src/main/java/kitchenpos/deliveryorders/infra/KitchenridersClient.java b/src/main/java/kitchenpos/deliveryorders/domain/KitchenridersClient.java similarity index 80% rename from src/main/java/kitchenpos/deliveryorders/infra/KitchenridersClient.java rename to src/main/java/kitchenpos/deliveryorders/domain/KitchenridersClient.java index 0c8278791..bcbeba0e7 100644 --- a/src/main/java/kitchenpos/deliveryorders/infra/KitchenridersClient.java +++ b/src/main/java/kitchenpos/deliveryorders/domain/KitchenridersClient.java @@ -1,4 +1,4 @@ -package kitchenpos.deliveryorders.infra; +package kitchenpos.deliveryorders.domain; import java.math.BigDecimal; import java.util.UUID; diff --git a/src/main/java/kitchenpos/deliveryorders/domain/MenuClient.java b/src/main/java/kitchenpos/deliveryorders/domain/MenuClient.java new file mode 100644 index 000000000..bfffab741 --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/domain/MenuClient.java @@ -0,0 +1,13 @@ +package kitchenpos.deliveryorders.domain; + +import kitchenpos.menus.tobe.domain.menu.Menu; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface MenuClient { + + Optional findById(UUID id); + int countAllByIdIn(List ids); +} diff --git a/src/main/java/kitchenpos/deliveryorders/infra/DefaultKitchenridersClient.java b/src/main/java/kitchenpos/deliveryorders/infra/DefaultKitchenridersClient.java index 31d6d8cee..d6eb810cc 100644 --- a/src/main/java/kitchenpos/deliveryorders/infra/DefaultKitchenridersClient.java +++ b/src/main/java/kitchenpos/deliveryorders/infra/DefaultKitchenridersClient.java @@ -1,5 +1,6 @@ package kitchenpos.deliveryorders.infra; +import kitchenpos.deliveryorders.domain.KitchenridersClient; import org.springframework.stereotype.Component; import java.math.BigDecimal; diff --git a/src/main/java/kitchenpos/deliveryorders/infra/JpaDeliveryOrderRepository.java b/src/main/java/kitchenpos/deliveryorders/infra/JpaDeliveryOrderRepository.java new file mode 100644 index 000000000..0fd585b94 --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/infra/JpaDeliveryOrderRepository.java @@ -0,0 +1,10 @@ +package kitchenpos.deliveryorders.infra; + +import kitchenpos.deliveryorders.domain.DeliveryOrder; +import kitchenpos.deliveryorders.domain.DeliveryOrderRepository; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +public interface JpaDeliveryOrderRepository extends DeliveryOrderRepository, JpaRepository { +} diff --git a/src/main/java/kitchenpos/deliveryorders/infra/MenuClientImpl.java b/src/main/java/kitchenpos/deliveryorders/infra/MenuClientImpl.java new file mode 100644 index 000000000..a61fc46a5 --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/infra/MenuClientImpl.java @@ -0,0 +1,29 @@ +package kitchenpos.deliveryorders.infra; + +import kitchenpos.deliveryorders.domain.MenuClient; +import kitchenpos.menus.tobe.domain.menu.Menu; +import kitchenpos.menus.tobe.domain.menu.MenuRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Service +public class MenuClientImpl implements MenuClient { + private final MenuRepository menuRepository; + + public MenuClientImpl(MenuRepository menuRepository) { + this.menuRepository = menuRepository; + } + + @Override + public Optional findById(UUID id) { + return menuRepository.findById(id); + } + + @Override + public int countAllByIdIn(List ids) { + return menuRepository.findAllByIdIn(ids).size(); + } +} diff --git a/src/main/java/kitchenpos/deliveryorders/shared/dto/DeliveryOrderDto.java b/src/main/java/kitchenpos/deliveryorders/shared/dto/DeliveryOrderDto.java new file mode 100644 index 000000000..0f35724d6 --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/shared/dto/DeliveryOrderDto.java @@ -0,0 +1,43 @@ +package kitchenpos.deliveryorders.shared.dto; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.domain.OrderType; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +public class DeliveryOrderDto { + private UUID id; + private OrderType type; + private OrderStatus status; + + private LocalDateTime orderDateTime; + private String deliveryAddress; + + private List orderLineItems; + + public List getOrderLineItems() { + return orderLineItems; + } + + public String getDeliveryAddress() { + return deliveryAddress; + } + + public UUID getId() { + return id; + } + + public OrderType getType() { + return type; + } + + public OrderStatus getStatus() { + return status; + } + + public LocalDateTime getOrderDateTime() { + return orderDateTime; + } +} diff --git a/src/main/java/kitchenpos/deliveryorders/shared/dto/DeliveryOrderLineItemDto.java b/src/main/java/kitchenpos/deliveryorders/shared/dto/DeliveryOrderLineItemDto.java new file mode 100644 index 000000000..82772952e --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/shared/dto/DeliveryOrderLineItemDto.java @@ -0,0 +1,31 @@ +package kitchenpos.deliveryorders.shared.dto; + +import java.math.BigDecimal; +import java.util.UUID; + +public class DeliveryOrderLineItemDto { + private UUID menuId; + private long quantity; + private BigDecimal price; + + protected DeliveryOrderLineItemDto() { + } + + public DeliveryOrderLineItemDto(UUID menuId, long quantity, BigDecimal price) { + this.menuId = menuId; + this.quantity = quantity; + this.price = price; + } + + public UUID getMenuId() { + return menuId; + } + + public long getQuantity() { + return quantity; + } + + public BigDecimal getPrice() { + return price; + } +} diff --git a/src/main/java/kitchenpos/deliveryorders/shared/dto/request/DeliveryOrderCreateRequest.java b/src/main/java/kitchenpos/deliveryorders/shared/dto/request/DeliveryOrderCreateRequest.java new file mode 100644 index 000000000..47121e862 --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/shared/dto/request/DeliveryOrderCreateRequest.java @@ -0,0 +1,24 @@ +package kitchenpos.deliveryorders.shared.dto.request; + +import kitchenpos.deliveryorders.shared.dto.DeliveryOrderLineItemDto; + +import java.util.List; + +public class DeliveryOrderCreateRequest { + private List orderLineItems; + + private String deliveryAddress; + + public DeliveryOrderCreateRequest(List orderLineItems, String deliveryAddress) { + this.orderLineItems = orderLineItems; + this.deliveryAddress = deliveryAddress; + } + + public List getOrderLineItems() { + return orderLineItems; + } + + public String getDeliveryAddress() { + return deliveryAddress; + } +} diff --git a/src/main/java/kitchenpos/deliveryorders/ui/DeliveryOrderRestController.java b/src/main/java/kitchenpos/deliveryorders/ui/DeliveryOrderRestController.java new file mode 100644 index 000000000..9174fcbbe --- /dev/null +++ b/src/main/java/kitchenpos/deliveryorders/ui/DeliveryOrderRestController.java @@ -0,0 +1,14 @@ +package kitchenpos.deliveryorders.ui; + +import kitchenpos.deliveryorders.application.DeliveryOrderService; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class DeliveryOrderRestController { + + private final DeliveryOrderService deliveryOrderService; + + public DeliveryOrderRestController(DeliveryOrderService deliveryOrderService) { + this.deliveryOrderService = deliveryOrderService; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/application/EatInOrderService.java b/src/main/java/kitchenpos/eatinorders/application/EatInOrderService.java new file mode 100644 index 000000000..846cdabfc --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/application/EatInOrderService.java @@ -0,0 +1,105 @@ +package kitchenpos.eatinorders.application; + +import kitchenpos.eatinorders.tobe.domain.order.EatInMenuClient; +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.shared.dto.EatInOrderDto; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderLineItems; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderRepository; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTableRepository; +import kitchenpos.eatinorders.shared.dto.EatInOrderLineItemDto; +import kitchenpos.eatinorders.shared.dto.request.EatInOrderCreateRequest; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrder; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderLineItem; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderLineItemPrice; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderLineItemQuantity; +import kitchenpos.menus.tobe.domain.menu.MenuRepository; +import kitchenpos.shared.util.ConvertUtil; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +@Service +public class EatInOrderService { + private final EatInOrderRepository eatInOrderRepository; + private final MenuRepository menuRepository; + private final OrderTableRepository orderTableRepository; + private final EatInMenuClient eatInMenuClient; + + public EatInOrderService(EatInOrderRepository eatInOrderRepository, MenuRepository menuRepository, OrderTableRepository orderTableRepository, EatInMenuClient eatInMenuClient) { + this.eatInOrderRepository = eatInOrderRepository; + this.menuRepository = menuRepository; + this.orderTableRepository = orderTableRepository; + this.eatInMenuClient = eatInMenuClient; + } + + @Transactional + public EatInOrderDto create(final EatInOrderCreateRequest request) { + List orderLineItemRequests = request.getOrderLineItems(); + if (Objects.isNull(orderLineItemRequests) || orderLineItemRequests.isEmpty()) { + throw new IllegalArgumentException(); + } + + List orderLineItems = request.getOrderLineItems().stream() + .map(eatInOrderLineItemDto -> EatInOrderLineItem.of( + eatInOrderLineItemDto.getMenuId(), + new EatInOrderLineItemQuantity(eatInOrderLineItemDto.getQuantity()), + new EatInOrderLineItemPrice(eatInOrderLineItemDto.getPrice()), + eatInMenuClient + )) + .collect(Collectors.toList()); + + OrderTable orderTable = orderTableRepository.findById(request.getOrderTableId()) + .orElseThrow(NoSuchElementException::new); + + EatInOrder eatInOrder = EatInOrder.of( + new EatInOrderLineItems(orderLineItems), + orderTable, + eatInMenuClient + ); + + return ConvertUtil.convert(eatInOrderRepository.save(eatInOrder), EatInOrderDto.class); + } + + @Transactional + public EatInOrderDto accept(UUID orderId) { + EatInOrder eatInOrder = eatInOrderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + eatInOrder.accept(); + return ConvertUtil.convert(eatInOrder, EatInOrderDto.class); + } + + @Transactional + public EatInOrderDto serve(UUID orderId) { + EatInOrder eatInOrder = eatInOrderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + eatInOrder.serve(); + return ConvertUtil.convert(eatInOrder, EatInOrderDto.class); + } + + @Transactional + public EatInOrderDto complete(UUID orderId) { + EatInOrder eatInOrder = eatInOrderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + eatInOrder.complete(); + + OrderTable orderTable = orderTableRepository.findById(eatInOrder.getOrderTable().getId()) + .orElseThrow(NoSuchElementException::new); + if (!eatInOrderRepository.existsByOrderTableAndStatusNot(orderTable, OrderStatus.COMPLETED)) { + orderTable.clear(); + } + return ConvertUtil.convert(eatInOrder, EatInOrderDto.class); + } + + + @Transactional + public List findAll() { + return ConvertUtil.convertList(eatInOrderRepository.findAll(), EatInOrderDto.class); + } + +} diff --git a/src/main/java/kitchenpos/eatinorders/application/OrderService.java b/src/main/java/kitchenpos/eatinorders/application/OrderService.java index 0b16edb94..49b911692 100644 --- a/src/main/java/kitchenpos/eatinorders/application/OrderService.java +++ b/src/main/java/kitchenpos/eatinorders/application/OrderService.java @@ -1,7 +1,9 @@ package kitchenpos.eatinorders.application; -import kitchenpos.deliveryorders.infra.KitchenridersClient; +import kitchenpos.deliveryorders.domain.KitchenridersClient; import kitchenpos.eatinorders.domain.*; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTableRepository; import kitchenpos.menus.tobe.domain.menu.Menu; import kitchenpos.menus.tobe.domain.menu.MenuRepository; import org.springframework.stereotype.Service; @@ -170,8 +172,7 @@ public Order complete(final UUID orderId) { if (type == OrderType.EAT_IN) { 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/eatinorders/application/OrderTableService.java b/src/main/java/kitchenpos/eatinorders/application/OrderTableService.java index 1df7e345f..f727483db 100644 --- a/src/main/java/kitchenpos/eatinorders/application/OrderTableService.java +++ b/src/main/java/kitchenpos/eatinorders/application/OrderTableService.java @@ -2,8 +2,13 @@ import kitchenpos.eatinorders.domain.OrderRepository; import kitchenpos.eatinorders.domain.OrderStatus; -import kitchenpos.eatinorders.domain.OrderTable; -import kitchenpos.eatinorders.domain.OrderTableRepository; +import kitchenpos.eatinorders.shared.dto.request.EatInOrderTableChangeNumberOfGuestsRequest; +import kitchenpos.eatinorders.shared.dto.request.OrderTableCreateRequest; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderRepository; +import kitchenpos.eatinorders.tobe.domain.ordertable.NumberOfGuests; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTableName; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTableRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -15,24 +20,20 @@ @Service public class OrderTableService { private final OrderTableRepository orderTableRepository; - private final OrderRepository orderRepository; + private final EatInOrderRepository eatInOrderRepository; - public OrderTableService(final OrderTableRepository orderTableRepository, final OrderRepository orderRepository) { + public OrderTableService(OrderTableRepository orderTableRepository, EatInOrderRepository eatInOrderRepository) { this.orderTableRepository = orderTableRepository; - this.orderRepository = orderRepository; + this.eatInOrderRepository = eatInOrderRepository; } @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); + public OrderTable create(final OrderTableCreateRequest request) { + final OrderTable orderTable = OrderTable.of( + new OrderTableName(request.getName()), + new NumberOfGuests(0), + false + ); return orderTableRepository.save(orderTable); } @@ -40,7 +41,7 @@ public OrderTable create(final OrderTable request) { public OrderTable sit(final UUID orderTableId) { final OrderTable orderTable = orderTableRepository.findById(orderTableId) .orElseThrow(NoSuchElementException::new); - orderTable.setOccupied(true); + orderTable.sit(); return orderTable; } @@ -48,26 +49,18 @@ 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 (eatInOrderRepository.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 EatInOrderTableChangeNumberOfGuestsRequest request) { final OrderTable orderTable = orderTableRepository.findById(orderTableId) .orElseThrow(NoSuchElementException::new); - if (!orderTable.isOccupied()) { - throw new IllegalStateException(); - } - orderTable.setNumberOfGuests(numberOfGuests); + orderTable.changeNumberOfGuests(request.getNumberOfGuests()); return orderTable; } diff --git a/src/main/java/kitchenpos/eatinorders/domain/Order.java b/src/main/java/kitchenpos/eatinorders/domain/Order.java index c6e630c90..10116c100 100644 --- a/src/main/java/kitchenpos/eatinorders/domain/Order.java +++ b/src/main/java/kitchenpos/eatinorders/domain/Order.java @@ -1,5 +1,7 @@ package kitchenpos.eatinorders.domain; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; + import javax.persistence.*; import java.time.LocalDateTime; import java.util.List; diff --git a/src/main/java/kitchenpos/eatinorders/domain/OrderRepository.java b/src/main/java/kitchenpos/eatinorders/domain/OrderRepository.java index f98d45c15..e299e592b 100644 --- a/src/main/java/kitchenpos/eatinorders/domain/OrderRepository.java +++ b/src/main/java/kitchenpos/eatinorders/domain/OrderRepository.java @@ -1,5 +1,7 @@ package kitchenpos.eatinorders.domain; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; + import java.util.List; import java.util.Optional; import java.util.UUID; diff --git a/src/main/java/kitchenpos/eatinorders/domain/OrderTable.java b/src/main/java/kitchenpos/eatinorders/domain/OrderTable.java deleted file mode 100644 index 9e1dc5519..000000000 --- a/src/main/java/kitchenpos/eatinorders/domain/OrderTable.java +++ /dev/null @@ -1,59 +0,0 @@ -package kitchenpos.eatinorders.domain; - -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 OrderTable { - @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 OrderTable() { - } - - 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/infra/EatInMenuClientImpl.java b/src/main/java/kitchenpos/eatinorders/infra/EatInMenuClientImpl.java new file mode 100644 index 000000000..9e5a7e7d1 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/infra/EatInMenuClientImpl.java @@ -0,0 +1,30 @@ +package kitchenpos.eatinorders.infra; + +import kitchenpos.eatinorders.tobe.domain.order.EatInMenuClient; +import kitchenpos.menus.tobe.domain.menu.Menu; +import kitchenpos.menus.tobe.domain.menu.MenuRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Service +public class EatInMenuClientImpl implements EatInMenuClient { + + private final MenuRepository menuRepository; + + public EatInMenuClientImpl(MenuRepository menuRepository) { + this.menuRepository = menuRepository; + } + + @Override + public Optional findById(UUID id) { + return menuRepository.findById(id); + } + + @Override + public List findAllByIdIn(List ids) { + return menuRepository.findAllByIdIn(ids); + } +} diff --git a/src/main/java/kitchenpos/eatinorders/infra/JpaEatInOrderRepositoryImpl.java b/src/main/java/kitchenpos/eatinorders/infra/JpaEatInOrderRepositoryImpl.java new file mode 100644 index 000000000..fdde6f81b --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/infra/JpaEatInOrderRepositoryImpl.java @@ -0,0 +1,11 @@ +package kitchenpos.eatinorders.infra; + +import kitchenpos.eatinorders.tobe.domain.order.EatInOrder; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderRepository; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +public interface JpaEatInOrderRepositoryImpl extends EatInOrderRepository, JpaRepository { + +} diff --git a/src/main/java/kitchenpos/eatinorders/domain/JpaOrderTableRepository.java b/src/main/java/kitchenpos/eatinorders/infra/JpaOrderTableRepository.java similarity index 52% rename from src/main/java/kitchenpos/eatinorders/domain/JpaOrderTableRepository.java rename to src/main/java/kitchenpos/eatinorders/infra/JpaOrderTableRepository.java index 84c0d3c6f..f549aa270 100644 --- a/src/main/java/kitchenpos/eatinorders/domain/JpaOrderTableRepository.java +++ b/src/main/java/kitchenpos/eatinorders/infra/JpaOrderTableRepository.java @@ -1,5 +1,7 @@ -package kitchenpos.eatinorders.domain; +package kitchenpos.eatinorders.infra; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTableRepository; import org.springframework.data.jpa.repository.JpaRepository; import java.util.UUID; diff --git a/src/main/java/kitchenpos/eatinorders/shared/dto/EatInOrderDto.java b/src/main/java/kitchenpos/eatinorders/shared/dto/EatInOrderDto.java new file mode 100644 index 000000000..69df7fb6b --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/shared/dto/EatInOrderDto.java @@ -0,0 +1,43 @@ +package kitchenpos.eatinorders.shared.dto; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.domain.OrderType; +import kitchenpos.eatinorders.shared.dto.EatInOrderLineItemDto; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +public class EatInOrderDto { + private UUID id; + private OrderType type; + private OrderStatus status; + private LocalDateTime orderDateTime; + private List orderLineItems; + + private OrderTableDto orderTable; + + public OrderTableDto getOrderTable() { + return orderTable; + } + + public UUID getId() { + return id; + } + + public OrderType getType() { + return type; + } + + public OrderStatus getStatus() { + return status; + } + + public LocalDateTime getOrderDateTime() { + return orderDateTime; + } + + public List getOrderLineItems() { + return orderLineItems; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/shared/dto/EatInOrderLineItemDto.java b/src/main/java/kitchenpos/eatinorders/shared/dto/EatInOrderLineItemDto.java new file mode 100644 index 000000000..a482f8fc3 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/shared/dto/EatInOrderLineItemDto.java @@ -0,0 +1,31 @@ +package kitchenpos.eatinorders.shared.dto; + +import java.math.BigDecimal; +import java.util.UUID; + +public class EatInOrderLineItemDto { + private UUID menuId; + private long quantity; + private BigDecimal price; + + protected EatInOrderLineItemDto() { + } + + public EatInOrderLineItemDto(UUID menuId, long quantity, BigDecimal price) { + this.menuId = menuId; + this.quantity = quantity; + this.price = price; + } + + public UUID getMenuId() { + return menuId; + } + + public long getQuantity() { + return quantity; + } + + public BigDecimal getPrice() { + return price; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/shared/dto/OrderTableDto.java b/src/main/java/kitchenpos/eatinorders/shared/dto/OrderTableDto.java new file mode 100644 index 000000000..bbf31cf1b --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/shared/dto/OrderTableDto.java @@ -0,0 +1,28 @@ +package kitchenpos.eatinorders.shared.dto; + +import java.util.UUID; + +public class OrderTableDto { + private UUID id; + private String name; + private int numberOfGuests; + private boolean occupied; + protected OrderTableDto() { + } + + public UUID getId() { + return id; + } + + public String getName() { + return name; + } + + public int getNumberOfGuests() { + return numberOfGuests; + } + + public boolean isOccupied() { + return occupied; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/shared/dto/request/EatInOrderCreateRequest.java b/src/main/java/kitchenpos/eatinorders/shared/dto/request/EatInOrderCreateRequest.java new file mode 100644 index 000000000..9bbc27a9e --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/shared/dto/request/EatInOrderCreateRequest.java @@ -0,0 +1,24 @@ +package kitchenpos.eatinorders.shared.dto.request; + +import kitchenpos.eatinorders.shared.dto.EatInOrderLineItemDto; + +import java.util.List; +import java.util.UUID; + +public class EatInOrderCreateRequest { + private List orderLineItems; + private UUID orderTableId; + + public EatInOrderCreateRequest(List orderLineItems, UUID orderTableId) { + this.orderLineItems = orderLineItems; + this.orderTableId = orderTableId; + } + + public List getOrderLineItems() { + return orderLineItems; + } + + public UUID getOrderTableId() { + return orderTableId; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/shared/dto/request/EatInOrderTableChangeNumberOfGuestsRequest.java b/src/main/java/kitchenpos/eatinorders/shared/dto/request/EatInOrderTableChangeNumberOfGuestsRequest.java new file mode 100644 index 000000000..5e00a0c70 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/shared/dto/request/EatInOrderTableChangeNumberOfGuestsRequest.java @@ -0,0 +1,13 @@ +package kitchenpos.eatinorders.shared.dto.request; + +public class EatInOrderTableChangeNumberOfGuestsRequest { + private int numberOfGuests; + + public int getNumberOfGuests() { + return numberOfGuests; + } + + public EatInOrderTableChangeNumberOfGuestsRequest(int numberOfGuests) { + this.numberOfGuests = numberOfGuests; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/shared/dto/request/OrderTableCreateRequest.java b/src/main/java/kitchenpos/eatinorders/shared/dto/request/OrderTableCreateRequest.java new file mode 100644 index 000000000..b72716039 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/shared/dto/request/OrderTableCreateRequest.java @@ -0,0 +1,13 @@ +package kitchenpos.eatinorders.shared.dto.request; + +public class OrderTableCreateRequest { + private String name; + + public OrderTableCreateRequest(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInMenuClient.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInMenuClient.java new file mode 100644 index 000000000..b09af2818 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInMenuClient.java @@ -0,0 +1,12 @@ +package kitchenpos.eatinorders.tobe.domain.order; + +import kitchenpos.menus.tobe.domain.menu.Menu; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface EatInMenuClient { + Optional findById(UUID id); + List findAllByIdIn(List ids); +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrder.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrder.java new file mode 100644 index 000000000..2974e88d0 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrder.java @@ -0,0 +1,131 @@ +package kitchenpos.eatinorders.tobe.domain.order; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; +import kitchenpos.eatinorders.domain.OrderType; +import kitchenpos.menus.tobe.domain.menu.Menu; + +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.ForeignKey; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +@Table(name = "eat_in_orders") +@Entity +public class EatInOrder { + @Column(name = "id", columnDefinition = "binary(16)") + @Id + private UUID id; + + @Column(name = "type", nullable = false) + @Enumerated(EnumType.STRING) + private OrderType type; + + @Column(name = "status", nullable = false) + @Enumerated(EnumType.STRING) + private OrderStatus status; + + @Column(name = "order_date_time", nullable = false) + private LocalDateTime orderDateTime; + + @Embedded + private EatInOrderLineItems orderLineItems; + + @ManyToOne + @JoinColumn( + name = "order_table_id", + columnDefinition = "binary(16)", + foreignKey = @ForeignKey(name = "fk_orders_to_order_table") + ) + private OrderTable orderTable; + + protected EatInOrder() { + } + + public EatInOrder(UUID id, OrderType type, OrderStatus status, LocalDateTime orderDateTime, EatInOrderLineItems orderLineItems, OrderTable orderTable) { + this.id = id; + this.type = type; + this.status = status; + this.orderDateTime = orderDateTime; + this.orderLineItems = orderLineItems; + this.orderTable = orderTable; + } + + public static EatInOrder of(EatInOrderLineItems orderLineItems, OrderTable orderTable, EatInMenuClient eatInMenuClient) { + validateEatInOrder(orderLineItems, eatInMenuClient); + validateOrderTable(orderTable); + return new EatInOrder(UUID.randomUUID(), OrderType.EAT_IN, OrderStatus.WAITING, LocalDateTime.now(), orderLineItems, orderTable); + } + + private static void validateOrderTable(OrderTable orderTable) { + if (!orderTable.isOccupied()) { + throw new IllegalStateException(); + } + } + + private static void validateEatInOrder(EatInOrderLineItems orderLineItems, EatInMenuClient eatInMenuClient) { + List menus = eatInMenuClient.findAllByIdIn( + orderLineItems.getOrderLineItems().stream() + .map(EatInOrderLineItem::getMenuId) + .collect(Collectors.toList()) + ); + if (menus.size() != orderLineItems.getOrderLineItems().size()) { + throw new IllegalArgumentException(); + } + } + + public void accept() { + if (status != OrderStatus.WAITING) { + throw new IllegalStateException(); + } + this.status = OrderStatus.ACCEPTED; + } + + public void serve() { + if (status != OrderStatus.ACCEPTED) { + throw new IllegalStateException(); + } + this.status = OrderStatus.SERVED; + } + + public void complete() { + if (status != OrderStatus.SERVED) { + throw new IllegalStateException(); + } + this.status = OrderStatus.COMPLETED; + } + + public UUID getId() { + return id; + } + + public OrderType getType() { + return type; + } + + public OrderStatus getStatus() { + return status; + } + + public LocalDateTime getOrderDateTime() { + return orderDateTime; + } + + public List getOrderLineItems() { + return orderLineItems.getOrderLineItems(); + } + + public OrderTable getOrderTable() { + return orderTable; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderLineItem.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderLineItem.java new file mode 100644 index 000000000..d60f69abb --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderLineItem.java @@ -0,0 +1,88 @@ +package kitchenpos.eatinorders.tobe.domain.order; + +import kitchenpos.menus.tobe.domain.menu.Menu; + +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import java.math.BigDecimal; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.UUID; + +@Table(name = "eat_in_order_line_item") +@Entity +public class EatInOrderLineItem { + @Column(name = "seq") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + private Long seq; + + private UUID menuId; + + @Embedded + private EatInOrderLineItemQuantity quantity; + + @Embedded + private EatInOrderLineItemPrice price; + + protected EatInOrderLineItem() { + } + + public EatInOrderLineItem(UUID menuId, EatInOrderLineItemQuantity quantity, EatInOrderLineItemPrice price) { + this.menuId = menuId; + this.quantity = quantity; + this.price = price; + } + + public static EatInOrderLineItem of(UUID menuId, EatInOrderLineItemQuantity quantity, EatInOrderLineItemPrice price, EatInMenuClient eatInMenuClient) { + validateEatInOrderLineItem(menuId, price, eatInMenuClient); + return new EatInOrderLineItem(menuId, quantity, price); + } + + private static void validateEatInOrderLineItem(UUID menuId, EatInOrderLineItemPrice price, EatInMenuClient eatInMenuClient) { + Menu menu = eatInMenuClient.findById(menuId) + .orElseThrow(() -> new NoSuchElementException("메뉴가 존재하지 않습니다. menuId: " + menuId)); + + if (!menu.isDisplayed()) { + throw new IllegalStateException(); + } + + if (menu.getPrice().compareTo(price.getEatInOrderLineItemPrice()) != 0) { + throw new IllegalArgumentException(); + } + } + + public Long getSeq() { + return seq; + } + + public UUID getMenuId() { + return menuId; + } + + public long getQuantity() { + return quantity.getQuantity(); + } + + public BigDecimal getPrice() { + return price.getEatInOrderLineItemPrice(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + EatInOrderLineItem that = (EatInOrderLineItem) o; + return Objects.equals(seq, that.seq); + } + + @Override + public int hashCode() { + return Objects.hash(seq); + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderLineItemPrice.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderLineItemPrice.java new file mode 100644 index 000000000..9d5601dfe --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderLineItemPrice.java @@ -0,0 +1,36 @@ +package kitchenpos.eatinorders.tobe.domain.order; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.math.BigDecimal; +import java.util.Objects; + +@Embeddable +public class EatInOrderLineItemPrice { + @Column(name = "price", nullable = false) + private BigDecimal eatInOrderLineItemPrice; + + protected EatInOrderLineItemPrice() { + } + + public EatInOrderLineItemPrice(BigDecimal eatInOrderLineItemPrice) { + this.eatInOrderLineItemPrice = eatInOrderLineItemPrice; + } + + public BigDecimal getEatInOrderLineItemPrice() { + return eatInOrderLineItemPrice; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + EatInOrderLineItemPrice that = (EatInOrderLineItemPrice) o; + return Objects.equals(eatInOrderLineItemPrice, that.eatInOrderLineItemPrice); + } + + @Override + public int hashCode() { + return Objects.hash(eatInOrderLineItemPrice); + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderLineItemQuantity.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderLineItemQuantity.java new file mode 100644 index 000000000..2d1af56f0 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderLineItemQuantity.java @@ -0,0 +1,35 @@ +package kitchenpos.eatinorders.tobe.domain.order; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.util.Objects; + +@Embeddable +public class EatInOrderLineItemQuantity { + @Column(name = "quantity") + private long quantity; + + protected EatInOrderLineItemQuantity() { + } + + public EatInOrderLineItemQuantity(long quantity) { + this.quantity = quantity; + } + + public long getQuantity() { + return quantity; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + EatInOrderLineItemQuantity that = (EatInOrderLineItemQuantity) o; + return quantity == that.quantity; + } + + @Override + public int hashCode() { + return Objects.hash(quantity); + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderLineItems.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderLineItems.java new file mode 100644 index 000000000..5009c435c --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderLineItems.java @@ -0,0 +1,31 @@ +package kitchenpos.eatinorders.tobe.domain.order; + +import javax.persistence.CascadeType; +import javax.persistence.Embeddable; +import javax.persistence.ForeignKey; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import java.util.List; + +@Embeddable +public class EatInOrderLineItems { + @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 EatInOrderLineItems() { + } + + public EatInOrderLineItems(List orderLineItems) { + this.orderLineItems = orderLineItems; + } + + public List getOrderLineItems() { + return orderLineItems; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderRepository.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderRepository.java new file mode 100644 index 000000000..fd5200dd2 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/order/EatInOrderRepository.java @@ -0,0 +1,18 @@ +package kitchenpos.eatinorders.tobe.domain.order; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface EatInOrderRepository { + EatInOrder save(EatInOrder order); + + Optional findById(UUID id); + + List findAll(); + + boolean existsByOrderTableAndStatusNot(OrderTable orderTable, OrderStatus status); +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/ordertable/NumberOfGuests.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/ordertable/NumberOfGuests.java new file mode 100644 index 000000000..b09ba93be --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/ordertable/NumberOfGuests.java @@ -0,0 +1,42 @@ +package kitchenpos.eatinorders.tobe.domain.ordertable; + +import javax.persistence.Column; +import javax.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) { + validateNumberOfGuests(numberOfGuests); + this.numberOfGuests = numberOfGuests; + } + + private void validateNumberOfGuests(int numberOfGuests) { + if (numberOfGuests < 0) { + throw new IllegalArgumentException(); + } + } + + public int getNumberOfGuests() { + return 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.hash(numberOfGuests); + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/ordertable/OrderTable.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/ordertable/OrderTable.java new file mode 100644 index 000000000..0ad3d5ce8 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/ordertable/OrderTable.java @@ -0,0 +1,71 @@ +package kitchenpos.eatinorders.tobe.domain.ordertable; + +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.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(UUID id, OrderTableName name, NumberOfGuests numberOfGuests, boolean occupied) { + this.id = id; + this.name = name; + this.numberOfGuests = numberOfGuests; + this.occupied = occupied; + } + + public static OrderTable of(OrderTableName name, NumberOfGuests numberOfGuests, boolean occupied) { + return new OrderTable(UUID.randomUUID(), name, numberOfGuests, occupied); + } + + public UUID getId() { + return id; + } + + public String getName() { + return name.getName(); + } + + public int getNumberOfGuests() { + return numberOfGuests.getNumberOfGuests(); + } + + public boolean isOccupied() { + return occupied; + } + + public void clear() { + numberOfGuests = new NumberOfGuests(0); + occupied = false; + } + + public void sit() { + occupied = true; + } + + public void changeNumberOfGuests(int numberOfGuests) { + if (!isOccupied()) { + throw new IllegalStateException(); + } + this.numberOfGuests = new NumberOfGuests(numberOfGuests); + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/ordertable/OrderTableName.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/ordertable/OrderTableName.java new file mode 100644 index 000000000..7e23254e5 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/ordertable/OrderTableName.java @@ -0,0 +1,42 @@ +package kitchenpos.eatinorders.tobe.domain.ordertable; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.util.Objects; + +@Embeddable +public class OrderTableName { + @Column(name = "name", nullable = false) + private String name; + + protected OrderTableName() { + } + + public OrderTableName(String name) { + validateOrderTableName(name); + this.name = name; + } + + private void validateOrderTableName(String name) { + if (Objects.isNull(name) || name.isEmpty()) { + throw new IllegalArgumentException(); + } + } + + public String getName() { + return 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.hash(name); + } +} diff --git a/src/main/java/kitchenpos/eatinorders/domain/OrderTableRepository.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/ordertable/OrderTableRepository.java similarity index 81% rename from src/main/java/kitchenpos/eatinorders/domain/OrderTableRepository.java rename to src/main/java/kitchenpos/eatinorders/tobe/domain/ordertable/OrderTableRepository.java index 1e9047d43..a1f0c3625 100644 --- a/src/main/java/kitchenpos/eatinorders/domain/OrderTableRepository.java +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/ordertable/OrderTableRepository.java @@ -1,4 +1,4 @@ -package kitchenpos.eatinorders.domain; +package kitchenpos.eatinorders.tobe.domain.ordertable; import java.util.List; import java.util.Optional; diff --git a/src/main/java/kitchenpos/eatinorders/ui/OrderTableRestController.java b/src/main/java/kitchenpos/eatinorders/ui/OrderTableRestController.java index 120c28d1d..a3983dbf8 100644 --- a/src/main/java/kitchenpos/eatinorders/ui/OrderTableRestController.java +++ b/src/main/java/kitchenpos/eatinorders/ui/OrderTableRestController.java @@ -1,7 +1,9 @@ package kitchenpos.eatinorders.ui; import kitchenpos.eatinorders.application.OrderTableService; -import kitchenpos.eatinorders.domain.OrderTable; +import kitchenpos.eatinorders.shared.dto.request.EatInOrderTableChangeNumberOfGuestsRequest; +import kitchenpos.eatinorders.shared.dto.request.OrderTableCreateRequest; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -19,7 +21,7 @@ public OrderTableRestController(final OrderTableService orderTableService) { } @PostMapping - public ResponseEntity create(@RequestBody final OrderTable request) { + public ResponseEntity create(@RequestBody final OrderTableCreateRequest request) { final OrderTable response = orderTableService.create(request); return ResponseEntity.created(URI.create("/api/order-tables/" + response.getId())) .body(response); @@ -38,7 +40,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 EatInOrderTableChangeNumberOfGuestsRequest request ) { return ResponseEntity.ok(orderTableService.changeNumberOfGuests(orderTableId, request)); } diff --git a/src/main/java/kitchenpos/menus/shared/dto/request/MenuCreateRequest.java b/src/main/java/kitchenpos/menus/shared/dto/request/MenuCreateRequest.java index 87e1b217c..1e5e3ceaf 100644 --- a/src/main/java/kitchenpos/menus/shared/dto/request/MenuCreateRequest.java +++ b/src/main/java/kitchenpos/menus/shared/dto/request/MenuCreateRequest.java @@ -1,6 +1,8 @@ package kitchenpos.menus.shared.dto.request; import kitchenpos.menus.shared.dto.MenuProductDto; +import kitchenpos.menus.tobe.domain.menu.Menu; +import kitchenpos.menus.tobe.domain.menu.MenuName; import java.math.BigDecimal; import java.util.List; @@ -41,4 +43,9 @@ public MenuCreateRequest(String name, BigDecimal price, UUID menuGroupId, List { - private static final ObjectMapper objectMapper = new ObjectMapper(); + private static final ObjectMapper objectMapper; - public ConvertUtil() { + static { + objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false); objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false); objectMapper.registerModule(new JavaTimeModule()); diff --git a/src/main/java/kitchenpos/takeoutorders/domain/TakeOutOrderService.java b/src/main/java/kitchenpos/takeoutorders/domain/TakeOutOrderService.java new file mode 100644 index 000000000..1e5a68318 --- /dev/null +++ b/src/main/java/kitchenpos/takeoutorders/domain/TakeOutOrderService.java @@ -0,0 +1,194 @@ +package kitchenpos.takeoutorders.domain; + +import kitchenpos.deliveryorders.domain.KitchenridersClient; +import kitchenpos.eatinorders.domain.Order; +import kitchenpos.eatinorders.domain.OrderLineItem; +import kitchenpos.eatinorders.domain.OrderRepository; +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTableRepository; +import kitchenpos.eatinorders.domain.OrderType; +import kitchenpos.menus.tobe.domain.menu.Menu; +import kitchenpos.menus.tobe.domain.menu.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 TakeOutOrderService { + + private final OrderRepository orderRepository; + private final MenuRepository menuRepository; + private final OrderTableRepository orderTableRepository; + private final KitchenridersClient kitchenridersClient; + + public TakeOutOrderService( + 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.clear(); + } + } + return order; + } + + @Transactional(readOnly = true) + public List findAll() { + return orderRepository.findAll(); + } +} diff --git a/src/main/java/kitchenpos/takeoutorders/empty.txt b/src/main/java/kitchenpos/takeoutorders/empty.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/test/java/kitchenpos/Fixtures.java b/src/test/java/kitchenpos/Fixtures.java index 3aa74b979..22c22dc0d 100644 --- a/src/test/java/kitchenpos/Fixtures.java +++ b/src/test/java/kitchenpos/Fixtures.java @@ -1,13 +1,26 @@ package kitchenpos; import kitchenpos.common.domain.PurgomalumClient; +import kitchenpos.deliveryorders.domain.DeliveryOrderLineItem; +import kitchenpos.deliveryorders.domain.DeliveryOrderLineItemPrice; +import kitchenpos.deliveryorders.domain.DeliveryOrderLineItemQuantity; +import kitchenpos.deliveryorders.domain.MenuClient; import kitchenpos.eatinorders.domain.*; +import kitchenpos.eatinorders.tobe.domain.order.EatInMenuClient; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrder; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderLineItem; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderLineItemPrice; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderLineItemQuantity; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderLineItems; +import kitchenpos.eatinorders.tobe.domain.ordertable.NumberOfGuests; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTableName; import kitchenpos.menus.tobe.domain.menu.Menu; import kitchenpos.menus.tobe.domain.menu.MenuName; import kitchenpos.menus.tobe.domain.menu.MenuPrice; +import kitchenpos.menus.tobe.domain.menu.MenuProductPrice; import kitchenpos.menus.tobe.domain.menu.MenuProductQuantity; import kitchenpos.menus.tobe.domain.menu.MenuProducts; -import kitchenpos.menus.tobe.domain.menu.ProductClient; import kitchenpos.menus.tobe.domain.menugroup.MenuGroup; import kitchenpos.menus.tobe.domain.menu.MenuProduct; import kitchenpos.menus.tobe.domain.menugroup.MenuGroupName; @@ -35,6 +48,9 @@ public static Menu menu() { public static Menu menu(final long price, final MenuProduct... menuProducts) { return menu(price, false, menuProducts); } + public static Menu displayedMenu(final long price, final MenuProduct... menuProducts) { + return menu(price, true, menuProducts); + } public static Menu menu(final long price, final boolean displayed, final MenuProduct... menuProducts) { final Menu menu = Menu.of(new MenuName("후라이드+후라이드", purgomalumClient), new MenuPrice(BigDecimal.valueOf(price)), menuGroup(), displayed, new MenuProducts(Arrays.asList(menuProducts))); @@ -57,7 +73,7 @@ public static MenuProduct menuProduct() { } public static MenuProduct menuProduct(final Product product, final long quantity) { - final MenuProduct menuProduct = new MenuProduct(product.getId(), new MenuProductQuantity(quantity), product.getPrice()); + final MenuProduct menuProduct = new MenuProduct(product.getId(), new MenuProductQuantity(quantity), new MenuProductPrice(product.getPrice())); return menuProduct; } @@ -93,6 +109,10 @@ public static Order order(final OrderStatus status, final OrderTable orderTable) return order; } + public static EatInOrder eatInOrder(final OrderStatus status, final OrderTable orderTable, final Menu menu) { + return new EatInOrder(UUID.randomUUID(), OrderType.EAT_IN, status, LocalDateTime.now(), new EatInOrderLineItems(Arrays.asList(new EatInOrderLineItem(menu.getId(), new EatInOrderLineItemQuantity(1L), new EatInOrderLineItemPrice(BigDecimal.TEN)))), orderTable); + } + public static OrderLineItem orderLineItem() { final OrderLineItem orderLineItem = new OrderLineItem(); orderLineItem.setSeq(new Random().nextLong()); @@ -100,17 +120,24 @@ public static OrderLineItem orderLineItem() { return orderLineItem; } + public static DeliveryOrderLineItem deliveryOrderLineItem(Menu menu, MenuClient menuClient) { + return DeliveryOrderLineItem.of(menu.getId(), new DeliveryOrderLineItemQuantity(2L), new DeliveryOrderLineItemPrice(menu.getPrice()), menuClient); + } + + public static EatInOrderLineItem eatInOrderLineItem(Menu menu, EatInMenuClient menuClient) { + return EatInOrderLineItem.of(menu.getId(), new EatInOrderLineItemQuantity(2L), new EatInOrderLineItemPrice(menu.getPrice()), menuClient); + } + public static OrderTable orderTable() { return orderTable(false, 0); } + public static OrderTable occupiedOrderTable() { + return orderTable(true, 0); + } + public static OrderTable orderTable(final boolean occupied, final int numberOfGuests) { - final OrderTable orderTable = new OrderTable(); - orderTable.setId(UUID.randomUUID()); - orderTable.setName("1번"); - orderTable.setNumberOfGuests(numberOfGuests); - orderTable.setOccupied(occupied); - return orderTable; + return new OrderTable(UUID.randomUUID(), new OrderTableName("1번"), new NumberOfGuests(numberOfGuests), occupied); } public static Product product() { diff --git a/src/test/java/kitchenpos/deliveryorders/application/DeliveryOrderServiceTest.java b/src/test/java/kitchenpos/deliveryorders/application/DeliveryOrderServiceTest.java new file mode 100644 index 000000000..e57c1810e --- /dev/null +++ b/src/test/java/kitchenpos/deliveryorders/application/DeliveryOrderServiceTest.java @@ -0,0 +1,183 @@ +package kitchenpos.deliveryorders.application; + +import kitchenpos.deliveryorders.domain.DeliveryOrder; +import kitchenpos.deliveryorders.domain.DeliveryOrderAddress; +import kitchenpos.deliveryorders.domain.DeliveryOrderLineItems; +import kitchenpos.deliveryorders.domain.DeliveryOrderRepository; +import kitchenpos.deliveryorders.domain.KitchenridersClient; +import kitchenpos.deliveryorders.domain.MenuClient; +import kitchenpos.deliveryorders.shared.dto.DeliveryOrderDto; +import kitchenpos.deliveryorders.shared.dto.DeliveryOrderLineItemDto; +import kitchenpos.deliveryorders.shared.dto.request.DeliveryOrderCreateRequest; +import kitchenpos.eatinorders.application.FakeKitchenridersClient; +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.domain.OrderType; +import kitchenpos.menus.application.InMemoryMenuRepository; +import kitchenpos.menus.tobe.domain.menu.Menu; +import kitchenpos.menus.tobe.domain.menu.MenuRepository; +import kitchenpos.products.application.InMemoryProductRepository; +import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.tobe.domain.ProductRepository; +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.NullAndEmptySource; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +import static kitchenpos.Fixtures.deliveryOrderLineItem; +import static kitchenpos.Fixtures.displayedMenu; +import static kitchenpos.Fixtures.menu; +import static kitchenpos.Fixtures.menuProduct; +import static kitchenpos.Fixtures.product; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class DeliveryOrderServiceTest { + private DeliveryOrderRepository deliveryOrderRepository; + private MenuClient menuClient; + + private MenuRepository menuRepository; + private ProductRepository productRepository; + + private DeliveryOrderService deliveryOrderService; + private KitchenridersClient kitchenridersClient; + + Menu displayedMenu; + Menu hidedMenu; + Product product; + + + @BeforeEach + void setUp() { + deliveryOrderRepository = new InMemoryDeliveryOrderRepository(); + menuRepository = new InMemoryMenuRepository(); + productRepository = new InMemoryProductRepository(); + kitchenridersClient = new FakeKitchenridersClient(); + product = productRepository.save(product()); + menuClient = new InMemoryMenuClient(menuRepository); + deliveryOrderService = new DeliveryOrderService(deliveryOrderRepository, menuClient, kitchenridersClient); + displayedMenu = menuRepository.save(displayedMenu(1L, menuProduct(product, 1L))); + hidedMenu = menuRepository.save(menu(1L, menuProduct(product, 1L))); + } + + @DisplayName("배달 주문을 성공한다.") + @Test + void success_create_delivery_order() { + //given + DeliveryOrderCreateRequest request = createDeliveryOrderRequest(List.of(createDisplayedDeliveryOrderLineItemDto(displayedMenu.getPrice())), "서울"); + + //when + DeliveryOrderDto result = deliveryOrderService.create(request); + + //then + assertThat(result.getStatus()).isEqualTo(OrderStatus.WAITING); + assertThat(result.getOrderDateTime()).isNotNull(); + assertThat(result.getDeliveryAddress()).isEqualTo(request.getDeliveryAddress()); + } + + @DisplayName("배달 주문을 성공하려면 메뉴가 노출상태여야 한다.") + @Test + void menu_of_delivery_order_should_be_isDisplayed() { + //given + DeliveryOrderCreateRequest request = createDeliveryOrderRequest(List.of(createHidedDeliveryOrderLineItemDto(displayedMenu.getPrice())), "서울"); + + //when + assertThatThrownBy(() -> deliveryOrderService.create(request)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("배달 주문은 주소가 필수값이다.") + @ParameterizedTest + @NullAndEmptySource + void delivery_order_should_contain_delivery_address(String deliveryAddress) { + //given + DeliveryOrderCreateRequest request = createDeliveryOrderRequest(List.of(createDisplayedDeliveryOrderLineItemDto(displayedMenu.getPrice())), deliveryAddress); + + //when + assertThatThrownBy(() -> deliveryOrderService.create(request)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("배달 주문 메뉴 가격은 주문항목 가격과 같아야 한다.") + @Test + void menu_price_of_delivery_order_and_order_line_item_price_should_be_same() { + //given + DeliveryOrderCreateRequest request = createDeliveryOrderRequest(List.of(createDisplayedDeliveryOrderLineItemDto(BigDecimal.TEN)), "서울"); + + //when + assertThatThrownBy(() -> deliveryOrderService.create(request)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("접수 대기 중인 주문만 접수할 수 있다.") + @Test + void only_waiting_order_can_be_accept() { + + DeliveryOrder deliveryOrder = new DeliveryOrder(UUID.randomUUID(), OrderStatus.DELIVERING, LocalDateTime.now(), new DeliveryOrderLineItems(List.of(deliveryOrderLineItem(displayedMenu, menuClient))), new DeliveryOrderAddress("서울")); + deliveryOrderRepository.save(deliveryOrder); + + assertThatThrownBy(() -> deliveryOrderService.accept(deliveryOrder.getId())) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("접수중인 주문만 서빙할 수 있다.") + @Test + void only_accepted_order_can_be_serve() { + + DeliveryOrder deliveryOrder = new DeliveryOrder(UUID.randomUUID(), OrderStatus.DELIVERING, LocalDateTime.now(), new DeliveryOrderLineItems(List.of(deliveryOrderLineItem(displayedMenu, menuClient))), new DeliveryOrderAddress("서울")); + deliveryOrderRepository.save(deliveryOrder); + + assertThatThrownBy(() -> deliveryOrderService.serve(deliveryOrder.getId())) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("서빙중인 주문만 배달할 수 있다.") + @Test + void only_served_order_can_be_delivery_start() { + + DeliveryOrder deliveryOrder = new DeliveryOrder(UUID.randomUUID(), OrderStatus.DELIVERING, LocalDateTime.now(), new DeliveryOrderLineItems(List.of(deliveryOrderLineItem(displayedMenu, menuClient))), new DeliveryOrderAddress("서울")); + deliveryOrderRepository.save(deliveryOrder); + + assertThatThrownBy(() -> deliveryOrderService.startDelivery(deliveryOrder.getId())) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("배달한 주문만 배달 완료할 수 있다.") + @Test + void only_delivery_started_order_can_be_complete_delivery() { + + DeliveryOrder deliveryOrder = new DeliveryOrder(UUID.randomUUID(), OrderStatus.SERVED, LocalDateTime.now(), new DeliveryOrderLineItems(List.of(deliveryOrderLineItem(displayedMenu, menuClient))), new DeliveryOrderAddress("서울")); + deliveryOrderRepository.save(deliveryOrder); + + assertThatThrownBy(() -> deliveryOrderService.completeDelivery(deliveryOrder.getId())) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("배달한 주문만 완료할 수 있다.") + @Test + void only_delivery_completed_order_can_be_complete() { + + DeliveryOrder deliveryOrder = new DeliveryOrder(UUID.randomUUID(), OrderStatus.SERVED, LocalDateTime.now(), new DeliveryOrderLineItems(List.of(deliveryOrderLineItem(displayedMenu, menuClient))), new DeliveryOrderAddress("서울")); + deliveryOrderRepository.save(deliveryOrder); + + assertThatThrownBy(() -> deliveryOrderService.complete(deliveryOrder.getId())) + .isInstanceOf(IllegalStateException.class); + } + + private DeliveryOrderCreateRequest createDeliveryOrderRequest(List deliveryOrderLineItemDtos, String deliveryAddress) { + return new DeliveryOrderCreateRequest(deliveryOrderLineItemDtos, deliveryAddress); + } + + private DeliveryOrderLineItemDto createDisplayedDeliveryOrderLineItemDto(BigDecimal price) { + return new DeliveryOrderLineItemDto(displayedMenu.getId(), 2, price); + } + + private DeliveryOrderLineItemDto createHidedDeliveryOrderLineItemDto(BigDecimal price) { + return new DeliveryOrderLineItemDto(hidedMenu.getId(), 2, price); + } +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/deliveryorders/application/InMemoryDeliveryOrderRepository.java b/src/test/java/kitchenpos/deliveryorders/application/InMemoryDeliveryOrderRepository.java new file mode 100644 index 000000000..f265d8b2c --- /dev/null +++ b/src/test/java/kitchenpos/deliveryorders/application/InMemoryDeliveryOrderRepository.java @@ -0,0 +1,31 @@ +package kitchenpos.deliveryorders.application; + +import kitchenpos.deliveryorders.domain.DeliveryOrder; +import kitchenpos.deliveryorders.domain.DeliveryOrderRepository; + +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 InMemoryDeliveryOrderRepository implements DeliveryOrderRepository { + private final Map orders = new HashMap<>(); + + @Override + public DeliveryOrder save(final DeliveryOrder deliveryOrder) { + orders.put(deliveryOrder.getId(), deliveryOrder); + return deliveryOrder; + } + + @Override + public Optional findById(final UUID id) { + return Optional.ofNullable(orders.get(id)); + } + + @Override + public List findAll() { + return new ArrayList<>(orders.values()); + } +} diff --git a/src/test/java/kitchenpos/deliveryorders/application/InMemoryMenuClient.java b/src/test/java/kitchenpos/deliveryorders/application/InMemoryMenuClient.java new file mode 100644 index 000000000..d77e2fa46 --- /dev/null +++ b/src/test/java/kitchenpos/deliveryorders/application/InMemoryMenuClient.java @@ -0,0 +1,28 @@ +package kitchenpos.deliveryorders.application; + +import kitchenpos.deliveryorders.domain.MenuClient; +import kitchenpos.menus.tobe.domain.menu.Menu; +import kitchenpos.menus.tobe.domain.menu.MenuRepository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public class InMemoryMenuClient implements MenuClient { + + private final MenuRepository menuRepository; + + public InMemoryMenuClient(MenuRepository menuRepository) { + this.menuRepository = menuRepository; + } + + @Override + public Optional findById(UUID id) { + return menuRepository.findById(id); + } + + @Override + public int countAllByIdIn(List ids) { + return menuRepository.findAllByIdIn(ids).size(); + } +} diff --git a/src/test/java/kitchenpos/deliveryorders/domain/DeliveryOrderAddressTest.java b/src/test/java/kitchenpos/deliveryorders/domain/DeliveryOrderAddressTest.java new file mode 100644 index 000000000..8783b5aeb --- /dev/null +++ b/src/test/java/kitchenpos/deliveryorders/domain/DeliveryOrderAddressTest.java @@ -0,0 +1,18 @@ +package kitchenpos.deliveryorders.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class DeliveryOrderAddressTest { + + @DisplayName("배달 주문의 주소는 필수값이다.") + @ParameterizedTest + @NullAndEmptySource + void delivery_address_of_delivery_order_should_be_exist(String deliveryAddress) { + assertThatThrownBy(() -> new DeliveryOrderAddress(deliveryAddress)) + .isInstanceOf(IllegalArgumentException.class); + } +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItemQuantityTest.java b/src/test/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItemQuantityTest.java new file mode 100644 index 000000000..9026c5ab9 --- /dev/null +++ b/src/test/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItemQuantityTest.java @@ -0,0 +1,16 @@ +package kitchenpos.deliveryorders.domain; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class DeliveryOrderLineItemQuantityTest { + + @DisplayName("배달 주문의 주문항목 수량은 0 이상이야 합니다.") + @Test + void deliveryOrderLineItemQuantity_should_be_greater_than_zero() { + Assertions.assertThatThrownBy(() -> new DeliveryOrderLineItemQuantity(-1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("배달 주문의 주문 항목 개수는 0이상이어야 합니다."); + } +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItemTest.java b/src/test/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItemTest.java new file mode 100644 index 000000000..e123abb26 --- /dev/null +++ b/src/test/java/kitchenpos/deliveryorders/domain/DeliveryOrderLineItemTest.java @@ -0,0 +1,68 @@ +package kitchenpos.deliveryorders.domain; + +import kitchenpos.deliveryorders.application.InMemoryMenuClient; +import kitchenpos.menus.application.InMemoryMenuRepository; +import kitchenpos.menus.tobe.domain.menu.Menu; +import kitchenpos.menus.tobe.domain.menu.MenuRepository; +import kitchenpos.products.application.InMemoryProductRepository; +import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.tobe.domain.ProductRepository; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.util.NoSuchElementException; +import java.util.UUID; + +import static kitchenpos.Fixtures.displayedMenu; +import static kitchenpos.Fixtures.menu; +import static kitchenpos.Fixtures.menuProduct; +import static kitchenpos.Fixtures.product; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +class DeliveryOrderLineItemTest { + + private MenuRepository menuRepository; + private MenuClient menuClient; + private ProductRepository productRepository; + + Product product; + Menu displayedMenu; + Menu hidedMenu; + @BeforeEach + void setUp() { + menuRepository = new InMemoryMenuRepository(); + menuClient = new InMemoryMenuClient(menuRepository); + productRepository = new InMemoryProductRepository(); + product = productRepository.save(product()); + displayedMenu = menuRepository.save(displayedMenu(1L, menuProduct(product, 1L))); + hidedMenu = menuRepository.save(menu(1L, menuProduct(product, 1L))); + } + + @DisplayName("주문 항목의 메뉴는 필수로 존재하는 메뉴여야 한다.") + @Test + void menu_of_order_line_items_must_be_exist() { + + assertThatThrownBy(() -> DeliveryOrderLineItem.of(UUID.randomUUID(), new DeliveryOrderLineItemQuantity(1L), new DeliveryOrderLineItemPrice(BigDecimal.TEN), menuClient)) + .isInstanceOf(NoSuchElementException.class) + .hasMessageContaining("메뉴가 존재하지 않습니다."); + } + + @DisplayName("주문 항목의 메뉴는 노출 상태여야 한다.") + @Test + void menu_of_order_line_items_must_be_is_displayed() { + assertThatThrownBy(() -> DeliveryOrderLineItem.of(hidedMenu.getId(), new DeliveryOrderLineItemQuantity(1L), new DeliveryOrderLineItemPrice(BigDecimal.TEN), menuClient)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("주문 항목의 메뉴의 가격은 메뉴 가격과 같아야 한다.") + @Test + void menu_price_and_price_of_order_line_items_must_be_same() { + assertThatThrownBy(() -> DeliveryOrderLineItem.of(displayedMenu.getId(), new DeliveryOrderLineItemQuantity(1L), new DeliveryOrderLineItemPrice(BigDecimal.TEN), menuClient)) + .isInstanceOf(IllegalArgumentException.class); + } + +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/deliveryorders/domain/DeliveryOrderTest.java b/src/test/java/kitchenpos/deliveryorders/domain/DeliveryOrderTest.java new file mode 100644 index 000000000..5307c6366 --- /dev/null +++ b/src/test/java/kitchenpos/deliveryorders/domain/DeliveryOrderTest.java @@ -0,0 +1,9 @@ +package kitchenpos.deliveryorders.domain; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class DeliveryOrderTest { + +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/eatinorders/application/EatInOrderServiceTest.java b/src/test/java/kitchenpos/eatinorders/application/EatInOrderServiceTest.java new file mode 100644 index 000000000..cd6c3e6c5 --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/application/EatInOrderServiceTest.java @@ -0,0 +1,158 @@ +package kitchenpos.eatinorders.application; + +import kitchenpos.deliveryorders.domain.KitchenridersClient; +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.domain.OrderType; +import kitchenpos.eatinorders.shared.dto.EatInOrderLineItemDto; +import kitchenpos.eatinorders.shared.dto.request.EatInOrderCreateRequest; +import kitchenpos.eatinorders.shared.dto.EatInOrderDto; +import kitchenpos.eatinorders.tobe.domain.order.EatInMenuClient; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrder; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderLineItem; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderLineItems; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderRepository; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTableRepository; +import kitchenpos.menus.application.InMemoryMenuRepository; +import kitchenpos.menus.tobe.domain.menu.Menu; +import kitchenpos.menus.tobe.domain.menu.MenuRepository; +import kitchenpos.products.application.InMemoryProductRepository; +import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.tobe.domain.ProductRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import static kitchenpos.Fixtures.displayedMenu; +import static kitchenpos.Fixtures.eatInOrderLineItem; +import static kitchenpos.Fixtures.menu; +import static kitchenpos.Fixtures.menuProduct; +import static kitchenpos.Fixtures.occupiedOrderTable; +import static kitchenpos.Fixtures.product; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class DeliveryOrderServiceTest { + private EatInOrderRepository eatInOrderRepository; + private EatInMenuClient menuClient; + + private MenuRepository menuRepository; + private ProductRepository productRepository; + + private EatInOrderService eatInOrderService; + private KitchenridersClient kitchenridersClient; + private OrderTableRepository orderTableRepository; + + Menu displayedMenu; + Menu hidedMenu; + Product product; + OrderTable orderTable; + + + @BeforeEach + void setUp() { + eatInOrderRepository = new InMemoryEatInOrderRepository(); + menuRepository = new InMemoryMenuRepository(); + productRepository = new InMemoryProductRepository(); + orderTableRepository = new InMemoryOrderTableRepository(); + kitchenridersClient = new FakeKitchenridersClient(); + product = productRepository.save(product()); + orderTable = orderTableRepository.save(occupiedOrderTable()); + menuClient = new InMemoryEatInMenuClient(menuRepository); + eatInOrderService = new EatInOrderService(eatInOrderRepository, menuRepository, orderTableRepository, menuClient); + displayedMenu = menuRepository.save(displayedMenu(1L, menuProduct(product, 1L))); + hidedMenu = menuRepository.save(menu(1L, menuProduct(product, 1L))); + } + + @DisplayName("매장 주문을 성공한다.") + @Test + void success_create_eat_in_order() { + //given + EatInOrderCreateRequest request = createEatInOrderRequest(List.of(createDisplayedEatInOrderLineItemDto(displayedMenu.getPrice())), orderTable.getId()); + + //when + EatInOrderDto result = eatInOrderService.create(request); + + //then + assertThat(result.getStatus()).isEqualTo(OrderStatus.WAITING); + assertThat(result.getType()).isEqualTo(OrderType.EAT_IN); + assertThat(result.getOrderDateTime()).isNotNull(); + assertThat(result.getOrderTable()).isNotNull(); + } + + @DisplayName("매장 주문을 성공하려면 메뉴가 노출상태여야 한다.") + @Test + void menu_of_eat_in_order_should_be_isDisplayed() { + //given + EatInOrderCreateRequest request = createEatInOrderRequest(List.of(createHidedEatInOrderLineItemDto(displayedMenu.getPrice())), orderTable.getId()); + + //when + assertThatThrownBy(() -> eatInOrderService.create(request)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("매장 주문 메뉴 가격은 주문항목 가격과 같아야 한다.") + @Test + void menu_price_of_eat_in_order_and_order_line_item_price_should_be_same() { + //given + EatInOrderCreateRequest request = createEatInOrderRequest(List.of(createDisplayedEatInOrderLineItemDto(BigDecimal.TEN)), orderTable.getId()); + + //when + assertThatThrownBy(() -> eatInOrderService.create(request)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("접수 대기 중인 주문만 접수할 수 있다.") + @Test + void only_waiting_order_can_be_accept() { + + EatInOrder eatInOrder = new EatInOrder(UUID.randomUUID(), OrderType.EAT_IN, OrderStatus.COMPLETED, LocalDateTime.now(), new EatInOrderLineItems(Arrays.asList(eatInOrderLineItem(displayedMenu, menuClient))), orderTable); + + eatInOrderRepository.save(eatInOrder); + + assertThatThrownBy(() -> eatInOrderService.accept(eatInOrder.getId())) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("접수중인 주문만 서빙할 수 있다.") + @Test + void only_accepted_order_can_be_serve() { + + EatInOrder eatInOrder = new EatInOrder(UUID.randomUUID(), OrderType.EAT_IN, OrderStatus.COMPLETED, LocalDateTime.now(), new EatInOrderLineItems(Arrays.asList(eatInOrderLineItem(displayedMenu, menuClient))), orderTable); + + eatInOrderRepository.save(eatInOrder); + + assertThatThrownBy(() -> eatInOrderService.serve(eatInOrder.getId())) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("배달한 주문만 배달 완료할 수 있다.") + @Test + void only_delivery_completed_order_can_be_complete() { + + EatInOrder eatInOrder = new EatInOrder(UUID.randomUUID(), OrderType.EAT_IN, OrderStatus.COMPLETED, LocalDateTime.now(), new EatInOrderLineItems(Arrays.asList(eatInOrderLineItem(displayedMenu, menuClient))), orderTable); + + eatInOrderRepository.save(eatInOrder); + + assertThatThrownBy(() -> eatInOrderService.complete(eatInOrder.getId())) + .isInstanceOf(IllegalStateException.class); + } + + private EatInOrderCreateRequest createEatInOrderRequest(List eatInOrderLineItemDtos, UUID orderTableId) { + return new EatInOrderCreateRequest(eatInOrderLineItemDtos, orderTableId); + } + + private EatInOrderLineItemDto createDisplayedEatInOrderLineItemDto(BigDecimal price) { + return new EatInOrderLineItemDto(displayedMenu.getId(), 2, price); + } + + private EatInOrderLineItemDto createHidedEatInOrderLineItemDto(BigDecimal price) { + return new EatInOrderLineItemDto(hidedMenu.getId(), 2, price); + } +} \ No newline at end of file diff --git a/src/test/java/kitchenpos/eatinorders/application/FakeKitchenridersClient.java b/src/test/java/kitchenpos/eatinorders/application/FakeKitchenridersClient.java index 301e1377b..ea2acd856 100644 --- a/src/test/java/kitchenpos/eatinorders/application/FakeKitchenridersClient.java +++ b/src/test/java/kitchenpos/eatinorders/application/FakeKitchenridersClient.java @@ -1,6 +1,6 @@ package kitchenpos.eatinorders.application; -import kitchenpos.deliveryorders.infra.KitchenridersClient; +import kitchenpos.deliveryorders.domain.KitchenridersClient; import java.math.BigDecimal; import java.util.UUID; diff --git a/src/test/java/kitchenpos/eatinorders/application/InMemoryEatInMenuClient.java b/src/test/java/kitchenpos/eatinorders/application/InMemoryEatInMenuClient.java new file mode 100644 index 000000000..8c749df25 --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/application/InMemoryEatInMenuClient.java @@ -0,0 +1,27 @@ +package kitchenpos.eatinorders.application; + +import kitchenpos.eatinorders.tobe.domain.order.EatInMenuClient; +import kitchenpos.menus.tobe.domain.menu.Menu; +import kitchenpos.menus.tobe.domain.menu.MenuRepository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public class InMemoryEatInMenuClient implements EatInMenuClient { + private final MenuRepository menuRepository; + + public InMemoryEatInMenuClient(MenuRepository menuRepository) { + this.menuRepository = menuRepository; + } + + @Override + public Optional findById(UUID id) { + return menuRepository.findById(id); + } + + @Override + public List findAllByIdIn(List ids) { + return menuRepository.findAllByIdIn(ids); + } +} diff --git a/src/test/java/kitchenpos/eatinorders/application/InMemoryEatInOrderRepository.java b/src/test/java/kitchenpos/eatinorders/application/InMemoryEatInOrderRepository.java new file mode 100644 index 000000000..572c7bf71 --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/application/InMemoryEatInOrderRepository.java @@ -0,0 +1,40 @@ +package kitchenpos.eatinorders.application; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrder; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderRepository; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; + +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 InMemoryEatInOrderRepository implements EatInOrderRepository { + private final Map orders = new HashMap<>(); + + @Override + public EatInOrder save(final EatInOrder 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 OrderTable orderTable, final OrderStatus status) { + return orders.values() + .stream() + .anyMatch(order -> order.getOrderTable().equals(orderTable) && order.getStatus() != status); + } +} diff --git a/src/test/java/kitchenpos/eatinorders/application/InMemoryOrderRepository.java b/src/test/java/kitchenpos/eatinorders/application/InMemoryOrderRepository.java index 38d22969c..a1daacf26 100644 --- a/src/test/java/kitchenpos/eatinorders/application/InMemoryOrderRepository.java +++ b/src/test/java/kitchenpos/eatinorders/application/InMemoryOrderRepository.java @@ -3,7 +3,7 @@ import kitchenpos.eatinorders.domain.Order; import kitchenpos.eatinorders.domain.OrderRepository; import kitchenpos.eatinorders.domain.OrderStatus; -import kitchenpos.eatinorders.domain.OrderTable; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; import java.util.*; diff --git a/src/test/java/kitchenpos/eatinorders/application/InMemoryOrderTableRepository.java b/src/test/java/kitchenpos/eatinorders/application/InMemoryOrderTableRepository.java index 1aa4febce..b4626ea91 100644 --- a/src/test/java/kitchenpos/eatinorders/application/InMemoryOrderTableRepository.java +++ b/src/test/java/kitchenpos/eatinorders/application/InMemoryOrderTableRepository.java @@ -1,7 +1,7 @@ package kitchenpos.eatinorders.application; -import kitchenpos.eatinorders.domain.OrderTable; -import kitchenpos.eatinorders.domain.OrderTableRepository; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTableRepository; import java.util.*; diff --git a/src/test/java/kitchenpos/eatinorders/application/OrderServiceTest.java b/src/test/java/kitchenpos/eatinorders/application/OrderServiceTest.java index 61ee2ab29..4618817bf 100644 --- a/src/test/java/kitchenpos/eatinorders/application/OrderServiceTest.java +++ b/src/test/java/kitchenpos/eatinorders/application/OrderServiceTest.java @@ -1,377 +1,379 @@ -package kitchenpos.eatinorders.application; - -import kitchenpos.eatinorders.domain.*; -import kitchenpos.menus.application.InMemoryMenuRepository; -import kitchenpos.menus.tobe.domain.menu.MenuRepository; -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.*; - -import java.math.BigDecimal; -import java.util.*; - -import static kitchenpos.Fixtures.*; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; - -class OrderServiceTest { - private OrderRepository orderRepository; - private MenuRepository menuRepository; - private OrderTableRepository orderTableRepository; - private FakeKitchenridersClient kitchenridersClient; - private OrderService orderService; - - @BeforeEach - void setUp() { - orderRepository = new InMemoryOrderRepository(); - menuRepository = new InMemoryMenuRepository(); - orderTableRepository = new InMemoryOrderTableRepository(); - kitchenridersClient = new FakeKitchenridersClient(); - orderService = new OrderService(orderRepository, menuRepository, orderTableRepository, kitchenridersClient); - } - - @DisplayName("1개 이상의 등록된 메뉴로 배달 주문을 등록할 수 있다.") - @Test - void createDeliveryOrder() { - final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); - final Order expected = createOrderRequest( - OrderType.DELIVERY, "서울시 송파구 위례성대로 2", createOrderLineItemRequest(menuId, 19_000L, 3L) - ); - final Order actual = orderService.create(expected); - assertThat(actual).isNotNull(); - assertAll( - () -> assertThat(actual.getId()).isNotNull(), - () -> assertThat(actual.getType()).isEqualTo(expected.getType()), - () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.WAITING), - () -> assertThat(actual.getOrderDateTime()).isNotNull(), - () -> assertThat(actual.getOrderLineItems()).hasSize(1), - () -> assertThat(actual.getDeliveryAddress()).isEqualTo(expected.getDeliveryAddress()) - ); - } - - @DisplayName("1개 이상의 등록된 메뉴로 포장 주문을 등록할 수 있다.") - @Test - void createTakeoutOrder() { - final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); - final Order expected = createOrderRequest(OrderType.TAKEOUT, createOrderLineItemRequest(menuId, 19_000L, 3L)); - final Order actual = orderService.create(expected); - assertThat(actual).isNotNull(); - assertAll( - () -> assertThat(actual.getId()).isNotNull(), - () -> assertThat(actual.getType()).isEqualTo(expected.getType()), - () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.WAITING), - () -> assertThat(actual.getOrderDateTime()).isNotNull(), - () -> assertThat(actual.getOrderLineItems()).hasSize(1) - ); - } - - @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 Order expected = createOrderRequest(OrderType.EAT_IN, orderTableId, createOrderLineItemRequest(menuId, 19_000L, 3L)); - final Order actual = orderService.create(expected); - assertThat(actual).isNotNull(); - assertAll( - () -> assertThat(actual.getId()).isNotNull(), - () -> assertThat(actual.getType()).isEqualTo(expected.getType()), - () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.WAITING), - () -> assertThat(actual.getOrderDateTime()).isNotNull(), - () -> assertThat(actual.getOrderLineItems()).hasSize(1), - () -> assertThat(actual.getOrderTable().getId()).isEqualTo(expected.getOrderTableId()) - ); - } - - @DisplayName("주문 유형이 올바르지 않으면 등록할 수 없다.") - @NullSource - @ParameterizedTest - void create(final OrderType type) { - final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); - final Order expected = createOrderRequest(type, createOrderLineItemRequest(menuId, 19_000L, 3L)); - assertThatThrownBy(() -> orderService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); - } - - @DisplayName("메뉴가 없으면 등록할 수 없다.") - @MethodSource("orderLineItems") - @ParameterizedTest - void create(final List orderLineItems) { - final Order expected = createOrderRequest(OrderType.TAKEOUT, orderLineItems); - assertThatThrownBy(() -> orderService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); - } - - private static List orderLineItems() { - return Arrays.asList( - null, - Arguments.of(Collections.emptyList()), - Arguments.of(Arrays.asList(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(); - final Order expected = createOrderRequest( - OrderType.EAT_IN, orderTableId, createOrderLineItemRequest(menuId, 19_000L, quantity) - ); - assertDoesNotThrow(() -> orderService.create(expected)); - } - - @DisplayName("매장 주문을 제외한 주문의 경우 주문 항목의 수량은 0 이상이어야 한다.") - @ValueSource(longs = -1L) - @ParameterizedTest - void createWithoutEatInOrder(final long quantity) { - final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); - final Order expected = createOrderRequest( - OrderType.TAKEOUT, createOrderLineItemRequest(menuId, 19_000L, quantity) - ); - assertThatThrownBy(() -> orderService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); - } - - @DisplayName("배달 주소가 올바르지 않으면 배달 주문을 등록할 수 없다.") - @NullAndEmptySource - @ParameterizedTest - void create(final String deliveryAddress) { - final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); - final Order expected = createOrderRequest( - OrderType.DELIVERY, deliveryAddress, createOrderLineItemRequest(menuId, 19_000L, 3L) - ); - assertThatThrownBy(() -> orderService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); - } - - @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 Order expected = createOrderRequest( - OrderType.EAT_IN, 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 Order expected = createOrderRequest(OrderType.TAKEOUT, 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 Order expected = createOrderRequest(OrderType.TAKEOUT, 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 Order 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 acceptDeliveryOrder() { - final UUID orderId = orderRepository.save(order(OrderStatus.WAITING, "서울시 송파구 위례성대로 2")).getId(); - final Order actual = orderService.accept(orderId); - assertAll( - () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.ACCEPTED), - () -> assertThat(kitchenridersClient.getOrderId()).isEqualTo(orderId), - () -> assertThat(kitchenridersClient.getDeliveryAddress()).isEqualTo("서울시 송파구 위례성대로 2") - ); - } - - @DisplayName("주문을 서빙한다.") - @Test - void serve() { - final UUID orderId = orderRepository.save(order(OrderStatus.ACCEPTED)).getId(); - final Order 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("주문을 배달한다.") - @Test - void startDelivery() { - final UUID orderId = orderRepository.save(order(OrderStatus.SERVED, "서울시 송파구 위례성대로 2")).getId(); - final Order actual = orderService.startDelivery(orderId); - assertThat(actual.getStatus()).isEqualTo(OrderStatus.DELIVERING); - } - - @DisplayName("배달 주문만 배달할 수 있다.") - @Test - void startDeliveryWithoutDeliveryOrder() { - final UUID orderId = orderRepository.save(order(OrderStatus.SERVED)).getId(); - assertThatThrownBy(() -> orderService.startDelivery(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, "서울시 송파구 위례성대로 2")).getId(); - assertThatThrownBy(() -> orderService.startDelivery(orderId)) - .isInstanceOf(IllegalStateException.class); - } - - @DisplayName("주문을 배달 완료한다.") - @Test - void completeDelivery() { - final UUID orderId = orderRepository.save(order(OrderStatus.DELIVERING, "서울시 송파구 위례성대로 2")).getId(); - final Order actual = orderService.completeDelivery(orderId); - assertThat(actual.getStatus()).isEqualTo(OrderStatus.DELIVERED); - } - - @DisplayName("배달 중인 주문만 배달 완료할 수 있다.") - @EnumSource(value = OrderStatus.class, names = "DELIVERING", mode = EnumSource.Mode.EXCLUDE) - @ParameterizedTest - void completeDelivery(final OrderStatus status) { - final UUID orderId = orderRepository.save(order(status, "서울시 송파구 위례성대로 2")).getId(); - assertThatThrownBy(() -> orderService.completeDelivery(orderId)) - .isInstanceOf(IllegalStateException.class); - } - - @DisplayName("주문을 완료한다.") - @Test - void complete() { - final Order expected = orderRepository.save(order(OrderStatus.DELIVERED, "서울시 송파구 위례성대로 2")); - final Order actual = orderService.complete(expected.getId()); - assertThat(actual.getStatus()).isEqualTo(OrderStatus.COMPLETED); - } - - @DisplayName("배달 주문의 경우 배달 완료된 주문만 완료할 수 있다.") - @EnumSource(value = OrderStatus.class, names = "DELIVERED", mode = EnumSource.Mode.EXCLUDE) - @ParameterizedTest - void completeDeliveryOrder(final OrderStatus status) { - final UUID orderId = orderRepository.save(order(status, "서울시 송파구 위례성대로 2")).getId(); - assertThatThrownBy(() -> orderService.complete(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 OrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); - final Order expected = orderRepository.save(order(OrderStatus.SERVED, orderTable)); - final Order 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 OrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); - orderRepository.save(order(OrderStatus.ACCEPTED, orderTable)); - final Order expected = orderRepository.save(order(OrderStatus.SERVED, orderTable)); - final Order 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 OrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); - orderRepository.save(order(OrderStatus.SERVED, orderTable)); - orderRepository.save(order(OrderStatus.DELIVERED, "서울시 송파구 위례성대로 2")); - final List actual = orderService.findAll(); - assertThat(actual).hasSize(2); - } - - private Order createOrderRequest( - final OrderType type, - final String deliveryAddress, - final OrderLineItem... orderLineItems - ) { - final Order order = new Order(); - order.setType(type); - order.setDeliveryAddress(deliveryAddress); - order.setOrderLineItems(Arrays.asList(orderLineItems)); - return order; - } - - private Order createOrderRequest(final OrderType orderType, final OrderLineItem... orderLineItems) { - return createOrderRequest(orderType, Arrays.asList(orderLineItems)); - } - - private Order createOrderRequest(final OrderType orderType, final List orderLineItems) { - final Order order = new Order(); - order.setType(orderType); - order.setOrderLineItems(orderLineItems); - return order; - } - - private Order createOrderRequest( - final OrderType type, - final UUID orderTableId, - final OrderLineItem... orderLineItems - ) { - final Order order = new Order(); - order.setType(type); - order.setOrderTableId(orderTableId); - order.setOrderLineItems(Arrays.asList(orderLineItems)); - return order; - } - - private static OrderLineItem createOrderLineItemRequest(final UUID menuId, final long price, final long quantity) { - final OrderLineItem orderLineItem = new OrderLineItem(); - orderLineItem.setSeq(new Random().nextLong()); - orderLineItem.setMenuId(menuId); - orderLineItem.setPrice(BigDecimal.valueOf(price)); - orderLineItem.setQuantity(quantity); - return orderLineItem; - } -} +//package kitchenpos.eatinorders.application; +// +//import kitchenpos.eatinorders.domain.*; +//import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; +//import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTableRepository; +//import kitchenpos.menus.application.InMemoryMenuRepository; +//import kitchenpos.menus.tobe.domain.menu.MenuRepository; +//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.*; +// +//import java.math.BigDecimal; +//import java.util.*; +// +//import static kitchenpos.Fixtures.*; +//import static org.assertj.core.api.Assertions.assertThat; +//import static org.assertj.core.api.Assertions.assertThatThrownBy; +//import static org.junit.jupiter.api.Assertions.assertAll; +//import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +// +//class OrderServiceTest { +// private OrderRepository orderRepository; +// private MenuRepository menuRepository; +// private OrderTableRepository orderTableRepository; +// private FakeKitchenridersClient kitchenridersClient; +// private OrderService orderService; +// +// @BeforeEach +// void setUp() { +// orderRepository = new InMemoryOrderRepository(); +// menuRepository = new InMemoryMenuRepository(); +// orderTableRepository = new InMemoryOrderTableRepository(); +// kitchenridersClient = new FakeKitchenridersClient(); +// orderService = new OrderService(orderRepository, menuRepository, orderTableRepository, kitchenridersClient); +// } +// +// @DisplayName("1개 이상의 등록된 메뉴로 배달 주문을 등록할 수 있다.") +// @Test +// void createDeliveryOrder() { +// final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); +// final Order expected = createOrderRequest( +// OrderType.DELIVERY, "서울시 송파구 위례성대로 2", createOrderLineItemRequest(menuId, 19_000L, 3L) +// ); +// final Order actual = orderService.create(expected); +// assertThat(actual).isNotNull(); +// assertAll( +// () -> assertThat(actual.getId()).isNotNull(), +// () -> assertThat(actual.getType()).isEqualTo(expected.getType()), +// () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.WAITING), +// () -> assertThat(actual.getOrderDateTime()).isNotNull(), +// () -> assertThat(actual.getOrderLineItems()).hasSize(1), +// () -> assertThat(actual.getDeliveryAddress()).isEqualTo(expected.getDeliveryAddress()) +// ); +// } +// +// @DisplayName("1개 이상의 등록된 메뉴로 포장 주문을 등록할 수 있다.") +// @Test +// void createTakeoutOrder() { +// final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); +// final Order expected = createOrderRequest(OrderType.TAKEOUT, createOrderLineItemRequest(menuId, 19_000L, 3L)); +// final Order actual = orderService.create(expected); +// assertThat(actual).isNotNull(); +// assertAll( +// () -> assertThat(actual.getId()).isNotNull(), +// () -> assertThat(actual.getType()).isEqualTo(expected.getType()), +// () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.WAITING), +// () -> assertThat(actual.getOrderDateTime()).isNotNull(), +// () -> assertThat(actual.getOrderLineItems()).hasSize(1) +// ); +// } +// +// @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 Order expected = createOrderRequest(OrderType.EAT_IN, orderTableId, createOrderLineItemRequest(menuId, 19_000L, 3L)); +// final Order actual = orderService.create(expected); +// assertThat(actual).isNotNull(); +// assertAll( +// () -> assertThat(actual.getId()).isNotNull(), +// () -> assertThat(actual.getType()).isEqualTo(expected.getType()), +// () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.WAITING), +// () -> assertThat(actual.getOrderDateTime()).isNotNull(), +// () -> assertThat(actual.getOrderLineItems()).hasSize(1), +// () -> assertThat(actual.getOrderTable().getId()).isEqualTo(expected.getOrderTableId()) +// ); +// } +// +// @DisplayName("주문 유형이 올바르지 않으면 등록할 수 없다.") +// @NullSource +// @ParameterizedTest +// void create(final OrderType type) { +// final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); +// final Order expected = createOrderRequest(type, createOrderLineItemRequest(menuId, 19_000L, 3L)); +// assertThatThrownBy(() -> orderService.create(expected)) +// .isInstanceOf(IllegalArgumentException.class); +// } +// +// @DisplayName("메뉴가 없으면 등록할 수 없다.") +// @MethodSource("orderLineItems") +// @ParameterizedTest +// void create(final List orderLineItems) { +// final Order expected = createOrderRequest(OrderType.TAKEOUT, orderLineItems); +// assertThatThrownBy(() -> orderService.create(expected)) +// .isInstanceOf(IllegalArgumentException.class); +// } +// +// private static List orderLineItems() { +// return Arrays.asList( +// null, +// Arguments.of(Collections.emptyList()), +// Arguments.of(Arrays.asList(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(); +// final Order expected = createOrderRequest( +// OrderType.EAT_IN, orderTableId, createOrderLineItemRequest(menuId, 19_000L, quantity) +// ); +// assertDoesNotThrow(() -> orderService.create(expected)); +// } +// +// @DisplayName("매장 주문을 제외한 주문의 경우 주문 항목의 수량은 0 이상이어야 한다.") +// @ValueSource(longs = -1L) +// @ParameterizedTest +// void createWithoutEatInOrder(final long quantity) { +// final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); +// final Order expected = createOrderRequest( +// OrderType.TAKEOUT, createOrderLineItemRequest(menuId, 19_000L, quantity) +// ); +// assertThatThrownBy(() -> orderService.create(expected)) +// .isInstanceOf(IllegalArgumentException.class); +// } +// +// @DisplayName("배달 주소가 올바르지 않으면 배달 주문을 등록할 수 없다.") +// @NullAndEmptySource +// @ParameterizedTest +// void create(final String deliveryAddress) { +// final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); +// final Order expected = createOrderRequest( +// OrderType.DELIVERY, deliveryAddress, createOrderLineItemRequest(menuId, 19_000L, 3L) +// ); +// assertThatThrownBy(() -> orderService.create(expected)) +// .isInstanceOf(IllegalArgumentException.class); +// } +// +// @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 Order expected = createOrderRequest( +// OrderType.EAT_IN, 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 Order expected = createOrderRequest(OrderType.TAKEOUT, 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 Order expected = createOrderRequest(OrderType.TAKEOUT, 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 Order 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 acceptDeliveryOrder() { +// final UUID orderId = orderRepository.save(order(OrderStatus.WAITING, "서울시 송파구 위례성대로 2")).getId(); +// final Order actual = orderService.accept(orderId); +// assertAll( +// () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.ACCEPTED), +// () -> assertThat(kitchenridersClient.getOrderId()).isEqualTo(orderId), +// () -> assertThat(kitchenridersClient.getDeliveryAddress()).isEqualTo("서울시 송파구 위례성대로 2") +// ); +// } +// +// @DisplayName("주문을 서빙한다.") +// @Test +// void serve() { +// final UUID orderId = orderRepository.save(order(OrderStatus.ACCEPTED)).getId(); +// final Order 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("주문을 배달한다.") +// @Test +// void startDelivery() { +// final UUID orderId = orderRepository.save(order(OrderStatus.SERVED, "서울시 송파구 위례성대로 2")).getId(); +// final Order actual = orderService.startDelivery(orderId); +// assertThat(actual.getStatus()).isEqualTo(OrderStatus.DELIVERING); +// } +// +// @DisplayName("배달 주문만 배달할 수 있다.") +// @Test +// void startDeliveryWithoutDeliveryOrder() { +// final UUID orderId = orderRepository.save(order(OrderStatus.SERVED)).getId(); +// assertThatThrownBy(() -> orderService.startDelivery(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, "서울시 송파구 위례성대로 2")).getId(); +// assertThatThrownBy(() -> orderService.startDelivery(orderId)) +// .isInstanceOf(IllegalStateException.class); +// } +// +// @DisplayName("주문을 배달 완료한다.") +// @Test +// void completeDelivery() { +// final UUID orderId = orderRepository.save(order(OrderStatus.DELIVERING, "서울시 송파구 위례성대로 2")).getId(); +// final Order actual = orderService.completeDelivery(orderId); +// assertThat(actual.getStatus()).isEqualTo(OrderStatus.DELIVERED); +// } +// +// @DisplayName("배달 중인 주문만 배달 완료할 수 있다.") +// @EnumSource(value = OrderStatus.class, names = "DELIVERING", mode = EnumSource.Mode.EXCLUDE) +// @ParameterizedTest +// void completeDelivery(final OrderStatus status) { +// final UUID orderId = orderRepository.save(order(status, "서울시 송파구 위례성대로 2")).getId(); +// assertThatThrownBy(() -> orderService.completeDelivery(orderId)) +// .isInstanceOf(IllegalStateException.class); +// } +// +// @DisplayName("주문을 완료한다.") +// @Test +// void complete() { +// final Order expected = orderRepository.save(order(OrderStatus.DELIVERED, "서울시 송파구 위례성대로 2")); +// final Order actual = orderService.complete(expected.getId()); +// assertThat(actual.getStatus()).isEqualTo(OrderStatus.COMPLETED); +// } +// +// @DisplayName("배달 주문의 경우 배달 완료된 주문만 완료할 수 있다.") +// @EnumSource(value = OrderStatus.class, names = "DELIVERED", mode = EnumSource.Mode.EXCLUDE) +// @ParameterizedTest +// void completeDeliveryOrder(final OrderStatus status) { +// final UUID orderId = orderRepository.save(order(status, "서울시 송파구 위례성대로 2")).getId(); +// assertThatThrownBy(() -> orderService.complete(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 OrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); +// final Order expected = orderRepository.save(order(OrderStatus.SERVED, orderTable)); +// final Order 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 OrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); +// orderRepository.save(order(OrderStatus.ACCEPTED, orderTable)); +// final Order expected = orderRepository.save(order(OrderStatus.SERVED, orderTable)); +// final Order 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 OrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); +// orderRepository.save(order(OrderStatus.SERVED, orderTable)); +// orderRepository.save(order(OrderStatus.DELIVERED, "서울시 송파구 위례성대로 2")); +// final List actual = orderService.findAll(); +// assertThat(actual).hasSize(2); +// } +// +// private Order createOrderRequest( +// final OrderType type, +// final String deliveryAddress, +// final OrderLineItem... orderLineItems +// ) { +// final Order order = new Order(); +// order.setType(type); +// order.setDeliveryAddress(deliveryAddress); +// order.setOrderLineItems(Arrays.asList(orderLineItems)); +// return order; +// } +// +// private Order createOrderRequest(final OrderType orderType, final OrderLineItem... orderLineItems) { +// return createOrderRequest(orderType, Arrays.asList(orderLineItems)); +// } +// +// private Order createOrderRequest(final OrderType orderType, final List orderLineItems) { +// final Order order = new Order(); +// order.setType(orderType); +// order.setOrderLineItems(orderLineItems); +// return order; +// } +// +// private Order createOrderRequest( +// final OrderType type, +// final UUID orderTableId, +// final OrderLineItem... orderLineItems +// ) { +// final Order order = new Order(); +// order.setType(type); +// order.setOrderTableId(orderTableId); +// order.setOrderLineItems(Arrays.asList(orderLineItems)); +// return order; +// } +// +// private static OrderLineItem createOrderLineItemRequest(final UUID menuId, final long price, final long quantity) { +// final OrderLineItem orderLineItem = new OrderLineItem(); +// orderLineItem.setSeq(new Random().nextLong()); +// orderLineItem.setMenuId(menuId); +// orderLineItem.setPrice(BigDecimal.valueOf(price)); +// orderLineItem.setQuantity(quantity); +// return orderLineItem; +// } +//} diff --git a/src/test/java/kitchenpos/eatinorders/application/OrderTableServiceTest.java b/src/test/java/kitchenpos/eatinorders/application/OrderTableServiceTest.java index 01551a8d4..91fad8907 100644 --- a/src/test/java/kitchenpos/eatinorders/application/OrderTableServiceTest.java +++ b/src/test/java/kitchenpos/eatinorders/application/OrderTableServiceTest.java @@ -1,9 +1,25 @@ package kitchenpos.eatinorders.application; +import kitchenpos.deliveryorders.application.InMemoryMenuClient; +import kitchenpos.deliveryorders.domain.MenuClient; import kitchenpos.eatinorders.domain.OrderRepository; import kitchenpos.eatinorders.domain.OrderStatus; -import kitchenpos.eatinorders.domain.OrderTable; -import kitchenpos.eatinorders.domain.OrderTableRepository; +import kitchenpos.eatinorders.shared.dto.request.EatInOrderTableChangeNumberOfGuestsRequest; +import kitchenpos.eatinorders.shared.dto.request.OrderTableCreateRequest; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrder; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderLineItem; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderLineItems; +import kitchenpos.eatinorders.tobe.domain.order.EatInOrderRepository; +import kitchenpos.eatinorders.tobe.domain.ordertable.NumberOfGuests; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTable; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTableName; +import kitchenpos.eatinorders.tobe.domain.ordertable.OrderTableRepository; +import kitchenpos.menus.application.InMemoryMenuRepository; +import kitchenpos.menus.tobe.domain.menu.Menu; +import kitchenpos.menus.tobe.domain.menu.MenuRepository; +import kitchenpos.products.application.InMemoryProductRepository; +import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.tobe.domain.ProductRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -11,31 +27,49 @@ import org.junit.jupiter.params.provider.NullAndEmptySource; import org.junit.jupiter.params.provider.ValueSource; +import java.util.Arrays; import java.util.List; import java.util.UUID; +import static kitchenpos.Fixtures.displayedMenu; +import static kitchenpos.Fixtures.eatInOrder; +import static kitchenpos.Fixtures.menuProduct; import static kitchenpos.Fixtures.order; +import static kitchenpos.Fixtures.orderLineItem; import static kitchenpos.Fixtures.orderTable; +import static kitchenpos.Fixtures.product; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; class OrderTableServiceTest { private OrderTableRepository orderTableRepository; - private OrderRepository orderRepository; + + private EatInOrderRepository eatInOrderRepository; private OrderTableService orderTableService; + private MenuRepository menuRepository; + private MenuClient menuClient; + private ProductRepository productRepository; + Product product; + Menu displayedMenu; @BeforeEach void setUp() { orderTableRepository = new InMemoryOrderTableRepository(); - orderRepository = new InMemoryOrderRepository(); - orderTableService = new OrderTableService(orderTableRepository, orderRepository); + eatInOrderRepository = new InMemoryEatInOrderRepository(); + + productRepository = new InMemoryProductRepository(); + orderTableService = new OrderTableService(orderTableRepository, eatInOrderRepository); + product = productRepository.save(product()); + menuRepository = new InMemoryMenuRepository(); + menuClient = new InMemoryMenuClient(menuRepository); + displayedMenu = menuRepository.save(displayedMenu(1L, menuProduct(product, 1L))); } @DisplayName("주문 테이블을 등록할 수 있다.") @Test void create() { - final OrderTable expected = createOrderTableRequest("1번"); + final OrderTableCreateRequest expected = createOrderTableRequest("1번"); final OrderTable actual = orderTableService.create(expected); assertThat(actual).isNotNull(); assertAll( @@ -50,7 +84,7 @@ void create() { @NullAndEmptySource @ParameterizedTest void create(final String name) { - final OrderTable expected = createOrderTableRequest(name); + final OrderTableCreateRequest expected = createOrderTableRequest(name); assertThatThrownBy(() -> orderTableService.create(expected)) .isInstanceOf(IllegalArgumentException.class); } @@ -79,7 +113,7 @@ void clear() { void clearWithUncompletedOrders() { final OrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); final UUID orderTableId = orderTable.getId(); - orderRepository.save(order(OrderStatus.ACCEPTED, orderTable)); + eatInOrderRepository.save(eatInOrder(OrderStatus.ACCEPTED, orderTable, displayedMenu)); assertThatThrownBy(() -> orderTableService.clear(orderTableId)) .isInstanceOf(IllegalStateException.class); } @@ -88,7 +122,7 @@ void clearWithUncompletedOrders() { @Test void changeNumberOfGuests() { final UUID orderTableId = orderTableRepository.save(orderTable(true, 0)).getId(); - final OrderTable expected = changeNumberOfGuestsRequest(4); + final EatInOrderTableChangeNumberOfGuestsRequest expected = changeNumberOfGuestsRequest(4); final OrderTable actual = orderTableService.changeNumberOfGuests(orderTableId, expected); assertThat(actual.getNumberOfGuests()).isEqualTo(4); } @@ -98,7 +132,7 @@ void changeNumberOfGuests() { @ParameterizedTest void changeNumberOfGuests(final int numberOfGuests) { final UUID orderTableId = orderTableRepository.save(orderTable(true, 0)).getId(); - final OrderTable expected = changeNumberOfGuestsRequest(numberOfGuests); + final EatInOrderTableChangeNumberOfGuestsRequest expected = changeNumberOfGuestsRequest(numberOfGuests); assertThatThrownBy(() -> orderTableService.changeNumberOfGuests(orderTableId, expected)) .isInstanceOf(IllegalArgumentException.class); } @@ -107,7 +141,7 @@ void changeNumberOfGuests(final int numberOfGuests) { @Test void changeNumberOfGuestsInEmptyTable() { final UUID orderTableId = orderTableRepository.save(orderTable(false, 0)).getId(); - final OrderTable expected = changeNumberOfGuestsRequest(4); + final EatInOrderTableChangeNumberOfGuestsRequest expected = changeNumberOfGuestsRequest(4); assertThatThrownBy(() -> orderTableService.changeNumberOfGuests(orderTableId, expected)) .isInstanceOf(IllegalStateException.class); } @@ -120,15 +154,11 @@ void findAll() { assertThat(actual).hasSize(1); } - private OrderTable createOrderTableRequest(final String name) { - final OrderTable orderTable = new OrderTable(); - orderTable.setName(name); - return orderTable; + private OrderTableCreateRequest createOrderTableRequest(final String name) { + return new OrderTableCreateRequest(name); } - private OrderTable changeNumberOfGuestsRequest(final int numberOfGuests) { - final OrderTable orderTable = new OrderTable(); - orderTable.setNumberOfGuests(numberOfGuests); - return orderTable; + private EatInOrderTableChangeNumberOfGuestsRequest changeNumberOfGuestsRequest(final int numberOfGuests) { + return new EatInOrderTableChangeNumberOfGuestsRequest(numberOfGuests); } }