diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java new file mode 100644 index 000000000..a29ef12d1 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderService.java @@ -0,0 +1,110 @@ +package kitchenpos.eatinorders.tobe.application; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderCreateRequest; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderCreateResponse; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderLineItemRequest; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderResponse; +import kitchenpos.eatinorders.tobe.domain.OrderMenu; +import kitchenpos.eatinorders.tobe.domain.TobeMenuClient; +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItems; +import kitchenpos.eatinorders.tobe.domain.TobeOrderRepository; +import kitchenpos.eatinorders.tobe.domain.TobeOrderTableRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +@Service +public class TobeOrderService { + private final TobeOrderRepository orderRepository; + private final TobeMenuClient tobeMenuClient; + private final TobeOrderTableRepository orderTableRepository; + + public TobeOrderService( + final TobeOrderRepository orderRepository, + final TobeMenuClient tobeMenuClient, + final TobeOrderTableRepository orderTableRepository + ) { + this.orderRepository = orderRepository; + this.tobeMenuClient = tobeMenuClient; + this.orderTableRepository = orderTableRepository; + } + + @Transactional + public TobeOrderCreateResponse create(final TobeOrderCreateRequest request) { + TobeOrderLineItems tobeOrderLineItems = getTobeOrderLineItem(request.getOrderLineItems()); + final TobeOrderTable orderTable = orderTableRepository.findById(request.getOrderTableId()) + .orElseThrow(NoSuchElementException::new); + orderTable.validateCreateOrder(); + + TobeOrder order = new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), orderTable.getId(), + tobeOrderLineItems); + TobeOrder savedOrder = orderRepository.save(order); + return TobeOrderCreateResponse.from(savedOrder); + } + + private TobeOrderLineItems getTobeOrderLineItem(final List requests) { + if (Objects.isNull(requests) || requests.isEmpty()) { + throw new IllegalArgumentException(); + } + + List tobeOrderLineItems = requests.stream().map(it -> { + final OrderMenu orderMenu = tobeMenuClient.getOrderMenu(it.getMenuId()); + if (!orderMenu.isDisplayed()) { + throw new IllegalStateException(); + } + if (orderMenu.getMenuPrice().compareTo(it.getPrice()) != 0) { + throw new IllegalArgumentException(); + } + return new TobeOrderLineItem(it.getQuantity(), orderMenu.getId(), orderMenu.getMenuPrice()); + }).collect(Collectors.toList()); + + return new TobeOrderLineItems(tobeOrderLineItems); + } + + @Transactional + public TobeOrderResponse accept(final UUID orderId) { + final TobeOrder order = orderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + order.accept(); + + return TobeOrderResponse.from(order); + } + + @Transactional + public TobeOrderResponse serve(final UUID orderId) { + final TobeOrder order = orderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + + order.served(); + + return TobeOrderResponse.from(order); + } + + @Transactional + public TobeOrderResponse complete(final UUID orderId) { + final TobeOrder order = orderRepository.findById(orderId) + .orElseThrow(NoSuchElementException::new); + order.completed(); + + TobeOrderTable orderTable = orderTableRepository.findById(order.getOrderTableId()).orElseThrow(); + if (!orderRepository.existsByOrderTableAndStatusNot(orderTable, OrderStatus.COMPLETED)) { + orderTable.setNumberOfGuests(0); + orderTable.setOccupied(false); + } + return TobeOrderResponse.from(order); + } + + @Transactional(readOnly = true) + public List findAll() { + return orderRepository.findAll().stream().map(TobeOrderResponse::from).collect(Collectors.toList()); + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java new file mode 100644 index 000000000..cc95a07d7 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/TobeOrderTable.java @@ -0,0 +1,72 @@ +package kitchenpos.eatinorders.tobe.application; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.UUID; + +@Table(name = "order_table") +@Entity +public class TobeOrderTable { + @Column(name = "id", columnDefinition = "binary(16)") + @Id + private UUID id; + + @Column(name = "name", nullable = false) + private String name; + + @Column(name = "number_of_guests", nullable = false) + private int numberOfGuests; + + @Column(name = "occupied", nullable = false) + private boolean occupied; + + protected TobeOrderTable() { + } + + public TobeOrderTable(final UUID id, final String name, final int numberOfGuests, final boolean occupied) { + this.id = id; + this.name = name; + this.numberOfGuests = numberOfGuests; + this.occupied = occupied; + } + + public void validateCreateOrder() { + if (!this.occupied) { + throw new IllegalStateException(); + } + } + + public UUID getId() { + return id; + } + + public void setId(final UUID id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public int getNumberOfGuests() { + return numberOfGuests; + } + + public void setNumberOfGuests(final int numberOfGuests) { + this.numberOfGuests = numberOfGuests; + } + + public boolean isOccupied() { + return occupied; + } + + public void setOccupied(final boolean occupied) { + this.occupied = occupied; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateRequest.java b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateRequest.java new file mode 100644 index 000000000..1b2fb046e --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateRequest.java @@ -0,0 +1,52 @@ +package kitchenpos.eatinorders.tobe.application.dto; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItems; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +public class TobeOrderCreateRequest { + private final UUID id; + private final OrderStatus status; + private final LocalDateTime orderDateTime; + private final List orderLineItems; + private final UUID orderTableId; + + public TobeOrderCreateRequest(final UUID id, final OrderStatus status, final LocalDateTime orderDateTime, + final List orderLineItems, + final UUID orderTableId) { + this.id = id; + this.status = status; + this.orderDateTime = orderDateTime; + this.orderLineItems = orderLineItems; + this.orderTableId = orderTableId; + } + + public TobeOrderLineItems tobeOrderLineItems() { + return new TobeOrderLineItems(orderLineItems.stream() + .map(TobeOrderLineItemRequest::toDomain) + .collect(Collectors.toList())); + } + + public UUID getId() { + return id; + } + + public OrderStatus getStatus() { + return status; + } + + public List getOrderLineItems() { + return orderLineItems; + } + + public UUID getOrderTableId() { + return orderTableId; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateResponse.java b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateResponse.java new file mode 100644 index 000000000..48d6235bd --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderCreateResponse.java @@ -0,0 +1,85 @@ +package kitchenpos.eatinorders.tobe.application.dto; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +public class TobeOrderCreateResponse { + private final UUID id; + private final OrderStatus status; + private final LocalDateTime orderDateTime; + private final List orderLineItems; + private final UUID orderTableId; + + public static class TobeOrderLineItemResponse { + private final UUID menuId; + private final long quantity; + private final BigDecimal price; + + public TobeOrderLineItemResponse(final UUID menuId, final long quantity, final BigDecimal price) { + this.menuId = menuId; + this.quantity = quantity; + this.price = price; + } + + public static TobeOrderCreateResponse.TobeOrderLineItemResponse from(TobeOrderLineItem item) { + return new TobeOrderCreateResponse.TobeOrderLineItemResponse(item.getMenuId(), item.getQuantity(), item.getPrice()); + } + + public UUID getMenuId() { + return menuId; + } + + public long getQuantity() { + return quantity; + } + + public BigDecimal getPrice() { + return price; + } + } + + public TobeOrderCreateResponse(final UUID id, final OrderStatus status, final LocalDateTime orderDateTime, + final List orderLineItems, + final UUID orderTableId) { + this.id = id; + this.status = status; + this.orderDateTime = orderDateTime; + this.orderLineItems = orderLineItems; + this.orderTableId = orderTableId; + } + + public static TobeOrderCreateResponse from(TobeOrder tobeOrder) { + return new TobeOrderCreateResponse(tobeOrder.getId(), tobeOrder.getStatus(), tobeOrder.getOrderDateTime(), + tobeOrder.getOrderLineItemsStream() + .map(TobeOrderLineItemResponse::from) + .collect(Collectors.toList()), tobeOrder.getOrderTableId()); + + } + + public UUID getId() { + return id; + } + + public OrderStatus getStatus() { + return status; + } + + public LocalDateTime getOrderDateTime() { + return orderDateTime; + } + + public List getOrderLineItems() { + return orderLineItems; + } + + public UUID getOrderTableId() { + return orderTableId; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderLineItemRequest.java b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderLineItemRequest.java new file mode 100644 index 000000000..91b5f2156 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderLineItemRequest.java @@ -0,0 +1,40 @@ +package kitchenpos.eatinorders.tobe.application.dto; + +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; + +import java.math.BigDecimal; +import java.util.UUID; + +public class TobeOrderLineItemRequest { + private final Long seq; + private final UUID menuId; + private final long quantity; + private final BigDecimal price; + + public TobeOrderLineItemRequest(final Long seq, final UUID menuId, final long quantity, final BigDecimal price) { + this.seq = seq; + this.menuId = menuId; + this.quantity = quantity; + this.price = price; + } + + public static TobeOrderLineItemRequest from(TobeOrderLineItem item) { + return new TobeOrderLineItemRequest(item.getSeq(), item.getMenuId(), item.getQuantity(), item.getPrice()); + } + + public TobeOrderLineItem toDomain() { + return new TobeOrderLineItem(this.seq, this.quantity, this.menuId, this.price); + } + + public UUID getMenuId() { + return menuId; + } + + public long getQuantity() { + return quantity; + } + + public BigDecimal getPrice() { + return price; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderResponse.java b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderResponse.java new file mode 100644 index 000000000..d610219d0 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/application/dto/TobeOrderResponse.java @@ -0,0 +1,85 @@ +package kitchenpos.eatinorders.tobe.application.dto; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +public class TobeOrderResponse { + private final UUID id; + private final OrderStatus status; + private final LocalDateTime orderDateTime; + private final List orderLineItems; + private final UUID orderTableId; + + public static class TobeOrderLineItemResponse { + private final UUID menuId; + private final long quantity; + private final BigDecimal price; + + public TobeOrderLineItemResponse(final UUID menuId, final long quantity, final BigDecimal price) { + this.menuId = menuId; + this.quantity = quantity; + this.price = price; + } + + public static TobeOrderResponse.TobeOrderLineItemResponse from(TobeOrderLineItem item) { + return new TobeOrderResponse.TobeOrderLineItemResponse(item.getMenuId(), item.getQuantity(), item.getPrice()); + } + + public UUID getMenuId() { + return menuId; + } + + public long getQuantity() { + return quantity; + } + + public BigDecimal getPrice() { + return price; + } + } + + public TobeOrderResponse(final UUID id, final OrderStatus status, final LocalDateTime orderDateTime, + final List orderLineItems, + final UUID orderTableId) { + this.id = id; + this.status = status; + this.orderDateTime = orderDateTime; + this.orderLineItems = orderLineItems; + this.orderTableId = orderTableId; + } + + public static TobeOrderResponse from(TobeOrder tobeOrder) { + return new TobeOrderResponse(tobeOrder.getId(), tobeOrder.getStatus(), tobeOrder.getOrderDateTime(), + tobeOrder.getOrderLineItemsStream() + .map(TobeOrderLineItemResponse::from) + .collect(Collectors.toList()), tobeOrder.getOrderTableId()); + + } + + public UUID getId() { + return id; + } + + public OrderStatus getStatus() { + return status; + } + + public LocalDateTime getOrderDateTime() { + return orderDateTime; + } + + public List getOrderLineItems() { + return orderLineItems; + } + + public UUID getOrderTableId() { + return orderTableId; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/OrderMenu.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/OrderMenu.java new file mode 100644 index 000000000..f5576e51e --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/OrderMenu.java @@ -0,0 +1,29 @@ +package kitchenpos.eatinorders.tobe.domain; + + +import java.math.BigDecimal; +import java.util.UUID; + +public class OrderMenu { + private final UUID id; + private final boolean displayed; + private final BigDecimal menuPrice; + + public OrderMenu(final UUID id, final boolean displayed, final BigDecimal menuPrice) { + this.id = id; + this.displayed = displayed; + this.menuPrice = menuPrice; + } + + public UUID getId() { + return id; + } + + public boolean isDisplayed() { + return displayed; + } + + public BigDecimal getMenuPrice() { + return menuPrice; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeMenuClient.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeMenuClient.java new file mode 100644 index 000000000..d09e9f98b --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeMenuClient.java @@ -0,0 +1,10 @@ +package kitchenpos.eatinorders.tobe.domain; + +import java.util.List; +import java.util.UUID; + +public interface TobeMenuClient { + OrderMenu getOrderMenu(UUID id); + + List findAllByIdIn(List ids); +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java new file mode 100644 index 000000000..590354e51 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrder.java @@ -0,0 +1,88 @@ +package kitchenpos.eatinorders.tobe.domain; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.application.TobeOrderTable; + +import javax.persistence.*; +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; +import java.util.stream.Stream; + +@Table(name = "orders") +@Entity +public class TobeOrder { + @Column(name = "id", columnDefinition = "binary(16)") + @Id + private UUID id; + + @Column(name = "status", nullable = false) + @Enumerated(EnumType.STRING) + private OrderStatus status; + + @Column(name = "order_date_time", nullable = false) + private LocalDateTime orderDateTime; + + private UUID orderTableId; + + private TobeOrderLineItems tobeOrderLineItems; + protected TobeOrder() { + } + + public TobeOrder(final UUID id, final OrderStatus status, final LocalDateTime orderDateTime, final UUID orderTableId, final List orderLineItems) { + this(id, status, orderDateTime, orderTableId, new TobeOrderLineItems(orderLineItems)); + } + + public TobeOrder(final UUID id, final OrderStatus status, final LocalDateTime orderDateTime, final UUID orderTableId, final TobeOrderLineItems orderLineItems) { + this.id = id; + this.status = status; + this.orderDateTime = orderDateTime; + this.orderTableId = orderTableId; + this.tobeOrderLineItems = orderLineItems; + } + + public UUID getId() { + return id; + } + + public OrderStatus getStatus() { + return status; + } + + public LocalDateTime getOrderDateTime() { + return orderDateTime; + } + + public UUID getOrderTableId() { + return orderTableId; + } + + public TobeOrderLineItems getOrderLineItems() { + return tobeOrderLineItems; + } + + public Stream getOrderLineItemsStream() { + return tobeOrderLineItems.getOrderLineItems().stream(); + } + + public void accept() { + if (status != OrderStatus.WAITING) { + throw new IllegalStateException(); + } + this.status = OrderStatus.ACCEPTED; + } + + public void served() { + if (status != OrderStatus.ACCEPTED) { + throw new IllegalStateException(); + } + this.status = OrderStatus.SERVED; + } + + public void completed() { + if (status != OrderStatus.SERVED) { + throw new IllegalStateException(); + } + this.status = OrderStatus.COMPLETED; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItem.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItem.java new file mode 100644 index 000000000..8f3933596 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItem.java @@ -0,0 +1,58 @@ +package kitchenpos.eatinorders.tobe.domain; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import java.math.BigDecimal; +import java.util.UUID; + +@Table(name = "order_line_item") +@Entity +public class TobeOrderLineItem { + @Column(name = "seq") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + private Long seq; + + @Column(name = "quantity", nullable = false) + private long quantity; + + private UUID menuId; + + @Transient + private BigDecimal price; + + protected TobeOrderLineItem() { + } + + public TobeOrderLineItem(final long quantity, final UUID menuId, final BigDecimal price) { + this(null, quantity, menuId, price); + } + + public TobeOrderLineItem(final Long seq, final long quantity, final UUID menuId, final BigDecimal price) { + this.seq = seq; + this.quantity = quantity; + this.menuId = menuId; + this.price = price; + } + + public Long getSeq() { + return seq; + } + + public long getQuantity() { + return quantity; + } + + public UUID getMenuId() { + return menuId; + } + + public BigDecimal getPrice() { + return price; + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItems.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItems.java new file mode 100644 index 000000000..cb1f723b3 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderLineItems.java @@ -0,0 +1,47 @@ +package kitchenpos.eatinorders.tobe.domain; + +import javax.persistence.CascadeType; +import javax.persistence.Embeddable; +import javax.persistence.ForeignKey; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +@Embeddable +public class TobeOrderLineItems { + @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) + @JoinColumn( + name = "order_id", + nullable = false, + columnDefinition = "binary(16)", + foreignKey = @ForeignKey(name = "fk_order_line_item_to_orders") + ) + private List orderLineItems; + + protected TobeOrderLineItems() { + } + + public TobeOrderLineItems(final List orderLineItems) { + if (Objects.isNull(orderLineItems) || orderLineItems.isEmpty()) { + throw new IllegalArgumentException(); + } + this.orderLineItems = orderLineItems; + } + + public List getOrderLineItems() { + return orderLineItems; + } + + public List getMenuIds() { + return orderLineItems.stream().map(TobeOrderLineItem::getMenuId).collect(Collectors.toList()); + } + + public void validation(final int size) { + if (orderLineItems.size() != size) { + throw new IllegalArgumentException(); + } + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderRepository.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderRepository.java new file mode 100644 index 000000000..73c49af4f --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderRepository.java @@ -0,0 +1,18 @@ +package kitchenpos.eatinorders.tobe.domain; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.application.TobeOrderTable; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface TobeOrderRepository { + TobeOrder save(TobeOrder order); + + Optional findById(UUID id); + + List findAll(); + + boolean existsByOrderTableAndStatusNot(TobeOrderTable orderTable, OrderStatus status); +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTableRepository.java b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTableRepository.java new file mode 100644 index 000000000..5ae951a91 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTableRepository.java @@ -0,0 +1,15 @@ +package kitchenpos.eatinorders.tobe.domain; + +import kitchenpos.eatinorders.tobe.application.TobeOrderTable; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface TobeOrderTableRepository { + TobeOrderTable save(TobeOrderTable orderTable); + + Optional findById(UUID id); + + List findAll(); +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/infra/DefaultTobeMenuClient.java b/src/main/java/kitchenpos/eatinorders/tobe/infra/DefaultTobeMenuClient.java new file mode 100644 index 000000000..f9d4bfb3c --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/infra/DefaultTobeMenuClient.java @@ -0,0 +1,37 @@ +package kitchenpos.eatinorders.tobe.infra; + +import kitchenpos.eatinorders.tobe.domain.OrderMenu; +import kitchenpos.eatinorders.tobe.domain.TobeMenuClient; +import kitchenpos.menus.tobe.domain.menu.TobeMenu; +import kitchenpos.menus.tobe.domain.menu.TobeMenuRepository; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import java.util.stream.Collectors; + +@Component +public class DefaultTobeMenuClient implements TobeMenuClient { + private final TobeMenuRepository menuRepository; + + public DefaultTobeMenuClient(final TobeMenuRepository menuRepository) { + this.menuRepository = menuRepository; + } + + + @Override + public OrderMenu getOrderMenu(final UUID id) { + TobeMenu tobeMenu = menuRepository.findById(id) + .orElseThrow(() -> new NoSuchElementException("메뉴를 찾을 수 없습니다.")); + return new OrderMenu(id, tobeMenu.isDisplayed(), tobeMenu.getPriceValue()); + } + + @Override + public List findAllByIdIn(final List ids) { + List tobeMenus = menuRepository.findAllByIdIn(ids); + return tobeMenus.stream() + .map(it -> new OrderMenu(it.getId(), it.isDisplayed(), it.getPriceValue())) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderRepository.java b/src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderRepository.java new file mode 100644 index 000000000..029d48dcf --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderRepository.java @@ -0,0 +1,10 @@ +package kitchenpos.eatinorders.tobe.infra; + +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderRepository; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +public interface JpaTobeOrderRepository extends TobeOrderRepository, JpaRepository { +} diff --git a/src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderTableRepository.java b/src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderTableRepository.java new file mode 100644 index 000000000..f5894e685 --- /dev/null +++ b/src/main/java/kitchenpos/eatinorders/tobe/infra/JpaTobeOrderTableRepository.java @@ -0,0 +1,10 @@ +package kitchenpos.eatinorders.tobe.infra; + +import kitchenpos.eatinorders.tobe.application.TobeOrderTable; +import kitchenpos.eatinorders.tobe.domain.TobeOrderTableRepository; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +public interface JpaTobeOrderTableRepository extends TobeOrderTableRepository, JpaRepository { +} diff --git a/src/main/java/kitchenpos/menus/tobe/domain/menu/TobeMenu.java b/src/main/java/kitchenpos/menus/tobe/domain/menu/TobeMenu.java index 4819b5f11..85cc7fb4f 100644 --- a/src/main/java/kitchenpos/menus/tobe/domain/menu/TobeMenu.java +++ b/src/main/java/kitchenpos/menus/tobe/domain/menu/TobeMenu.java @@ -1,6 +1,7 @@ package kitchenpos.menus.tobe.domain.menu; import javax.persistence.*; +import java.math.BigDecimal; import java.util.List; import java.util.Objects; import java.util.UUID; @@ -88,6 +89,10 @@ public MenuPrice getPrice() { return price; } + public BigDecimal getPriceValue() { + return price.getPrice(); + } + public boolean isDisplayed() { return displayed; } diff --git a/src/test/java/kitchenpos/TobeFixtures.java b/src/test/java/kitchenpos/TobeFixtures.java index c8bcca5e8..b1db8ec4e 100644 --- a/src/test/java/kitchenpos/TobeFixtures.java +++ b/src/test/java/kitchenpos/TobeFixtures.java @@ -1,20 +1,26 @@ package kitchenpos; +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.application.TobeOrderTable; +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderLineItem; import kitchenpos.menus.tobe.application.FakeMenuPurgomalumChecker; import kitchenpos.menus.tobe.domain.menu.MenuName; import kitchenpos.menus.tobe.domain.menu.MenuPrice; import kitchenpos.menus.tobe.domain.menu.TobeMenu; +import kitchenpos.menus.tobe.domain.menu.TobeMenuProduct; +import kitchenpos.menus.tobe.domain.menu.TobeMenuProductQuantity; import kitchenpos.menus.tobe.domain.menugroup.TobeMenuGroup; import kitchenpos.menus.tobe.domain.menugroup.TobeMenuGroupName; -import kitchenpos.menus.tobe.domain.menu.TobeMenuProductQuantity; -import kitchenpos.menus.tobe.domain.menu.TobeMenuProduct; import kitchenpos.products.application.FakePurgomalumChecker; import kitchenpos.products.tobe.domain.ProductName; import kitchenpos.products.tobe.domain.ProductPrice; import kitchenpos.products.tobe.domain.TobeProduct; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.Arrays; +import java.util.List; import java.util.Random; import java.util.UUID; @@ -62,4 +68,38 @@ public static TobeProduct product() { public static TobeProduct product(final String name, final long price) { return new TobeProduct(UUID.randomUUID(), new ProductName(name, new FakePurgomalumChecker()), new ProductPrice(BigDecimal.valueOf(price))); } + +// public static TobeOrder order(final OrderStatus status) { +// final TobeOrder order = new TobeOrder(UUID.randomUUID(), status, LocalDateTime.of(2020, 1, 1, 12, 0), +// +// ); +// order.setId(UUID.randomUUID()); +// order.setType(OrderType.DELIVERY); +// order.setStatus(status); +// order.setOrderDateTime(); +// order.setOrderLineItems(Arrays.asList(orderLineItem())); +// return order; +// } + + public static TobeOrder order(final OrderStatus status) { + return new TobeOrder(UUID.randomUUID(), status, LocalDateTime.of(2020, 1, 1, 12, 0), UUID.randomUUID(), + List.of(orderLineItem())); + } + + public static TobeOrder order(final OrderStatus status, final TobeOrderTable orderTable) { + return new TobeOrder(UUID.randomUUID(), status, LocalDateTime.of(2020, 1, 1, 12, 0), orderTable.getId(), + List.of(orderLineItem())); + } + + public static TobeOrderLineItem orderLineItem() { + return new TobeOrderLineItem(new Random().nextLong(), menu().getId(), BigDecimal.valueOf(16_000)); + } + +// public static TobeOrderLineItem orderTable() { +// return orderTable(false, 0); +// } + + public static TobeOrderTable orderTable(final boolean occupied, final int numberOfGuests) { + return new TobeOrderTable(UUID.randomUUID(), "1번", numberOfGuests, occupied); + } } diff --git a/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeMenuClient.java b/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeMenuClient.java new file mode 100644 index 000000000..d4cc5983f --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeMenuClient.java @@ -0,0 +1,33 @@ +package kitchenpos.eatinorders.tobe.application; + +import kitchenpos.eatinorders.tobe.domain.OrderMenu; +import kitchenpos.eatinorders.tobe.domain.TobeMenuClient; +import kitchenpos.menus.tobe.domain.menu.TobeMenu; +import kitchenpos.menus.tobe.domain.menu.TobeMenuRepository; + +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +public class InMemoryTobeMenuClient implements TobeMenuClient { + private final TobeMenuRepository tobeMenuRepository; + + public InMemoryTobeMenuClient(final TobeMenuRepository tobeMenuRepository) { + this.tobeMenuRepository = tobeMenuRepository; + } + + @Override + public OrderMenu getOrderMenu(final UUID id) { + TobeMenu menu = tobeMenuRepository.findById(id).orElseThrow(); + return new OrderMenu(menu.getId(), menu.isDisplayed(), menu.getPriceValue()); + } + + @Override + public List findAllByIdIn(final List ids) { + List tobeMenus = tobeMenuRepository.findAllByIdIn(ids); + return tobeMenus.stream() + .map(it -> new OrderMenu(it.getId(), it.isDisplayed(), it.getPriceValue())) + .collect(Collectors.toList()); + } + +} diff --git a/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderRepository.java b/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderRepository.java new file mode 100644 index 000000000..0773282ba --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderRepository.java @@ -0,0 +1,39 @@ +package kitchenpos.eatinorders.tobe.application; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderRepository; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +public class InMemoryTobeOrderRepository implements TobeOrderRepository { + private final Map orders = new HashMap<>(); + + @Override + public TobeOrder save(final TobeOrder order) { + orders.put(order.getId(), order); + return order; + } + + @Override + public Optional findById(final UUID id) { + return Optional.ofNullable(orders.get(id)); + } + + @Override + public List findAll() { + return new ArrayList<>(orders.values()); + } + + @Override + public boolean existsByOrderTableAndStatusNot(final TobeOrderTable orderTable, final OrderStatus status) { + return orders.values() + .stream() + .anyMatch(order -> order.getOrderTableId() == orderTable.getId() && order.getStatus() != status); + } +} diff --git a/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderTableRepository.java b/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderTableRepository.java new file mode 100644 index 000000000..470a54d7e --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/tobe/application/InMemoryTobeOrderTableRepository.java @@ -0,0 +1,30 @@ +package kitchenpos.eatinorders.tobe.application; + +import kitchenpos.eatinorders.tobe.domain.TobeOrderTableRepository; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +public class InMemoryTobeOrderTableRepository implements TobeOrderTableRepository { + private final Map orderTables = new HashMap<>(); + + @Override + public TobeOrderTable save(final TobeOrderTable orderTable) { + orderTables.put(orderTable.getId(), orderTable); + return orderTable; + } + + @Override + public Optional findById(final UUID id) { + return Optional.ofNullable(orderTables.get(id)); + } + + @Override + public List findAll() { + return new ArrayList<>(orderTables.values()); + } +} diff --git a/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java b/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java new file mode 100644 index 000000000..05848089e --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/tobe/application/TobeOrderServiceTest.java @@ -0,0 +1,236 @@ +package kitchenpos.eatinorders.tobe.application; + +import kitchenpos.eatinorders.domain.OrderStatus; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderCreateRequest; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderCreateResponse; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderLineItemRequest; +import kitchenpos.eatinorders.tobe.application.dto.TobeOrderResponse; +import kitchenpos.eatinorders.tobe.domain.TobeMenuClient; +import kitchenpos.eatinorders.tobe.domain.TobeOrder; +import kitchenpos.eatinorders.tobe.domain.TobeOrderRepository; +import kitchenpos.eatinorders.tobe.domain.TobeOrderTableRepository; +import kitchenpos.menus.tobe.application.InMemoryTobeMenuRepository; +import kitchenpos.menus.tobe.domain.menu.TobeMenuRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.UUID; + +import static kitchenpos.Fixtures.INVALID_ID; +import static kitchenpos.TobeFixtures.menu; +import static kitchenpos.TobeFixtures.menuProduct; +import static kitchenpos.TobeFixtures.order; +import static kitchenpos.TobeFixtures.orderTable; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class TobeOrderServiceTest { + private TobeOrderRepository orderRepository; + private TobeMenuRepository menuRepository; + private TobeOrderTableRepository orderTableRepository; + private TobeMenuClient tobeMenuClient; + private TobeOrderService orderService; + + @BeforeEach + void setUp() { + orderRepository = new InMemoryTobeOrderRepository(); + menuRepository = new InMemoryTobeMenuRepository(); + orderTableRepository = new InMemoryTobeOrderTableRepository(); + tobeMenuClient = new InMemoryTobeMenuClient(menuRepository); + orderService = new TobeOrderService(orderRepository, tobeMenuClient, orderTableRepository); + } + + @DisplayName("1개 이상의 등록된 메뉴로 매장 주문을 등록할 수 있다.") + @Test + void createEatInOrder() { + final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); + final UUID orderTableId = orderTableRepository.save(orderTable(true, 4)).getId(); + final TobeOrderCreateRequest expected = createOrderRequest(orderTableId, + createOrderLineItemRequest(menuId, 19_000L, 3L)); + final TobeOrderCreateResponse actual = orderService.create(expected); + assertThat(actual).isNotNull(); + assertAll( + () -> assertThat(actual.getId()).isNotNull(), + () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.WAITING), + () -> assertThat(actual.getOrderDateTime()).isNotNull(), + () -> assertThat(actual.getOrderLineItems()).hasSize(1), + () -> assertThat(actual.getOrderTableId()).isEqualTo(expected.getOrderTableId()) + ); + } + + @DisplayName("메뉴가 비어 있으면 등록할 수 없다.") + @NullAndEmptySource + @ParameterizedTest + void create(final List orderLineItems) { + TobeOrderCreateRequest expected = createOrderRequest(orderLineItems); + assertThatThrownBy(() -> orderService.create(expected)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("메뉴가 없으면 등록할 수 없다.") + @Test + void create01() { + TobeOrderCreateRequest expected = createOrderRequest(List.of(createOrderLineItemRequest(INVALID_ID, 19_000L, 3L))); + assertThatThrownBy(() -> orderService.create(expected)) + .isInstanceOf(NoSuchElementException.class); + } + + @DisplayName("매장 주문은 주문 항목의 수량이 0 미만일 수 있다.") + @ValueSource(longs = -1L) + @ParameterizedTest + void createEatInOrder(final long quantity) { + final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); + final UUID orderTableId = orderTableRepository.save(orderTable(true, 4)).getId(); + TobeOrderCreateRequest expected = createOrderRequest(orderTableId, + createOrderLineItemRequest(menuId, 19_000L, quantity)); + assertDoesNotThrow(() -> orderService.create(expected)); + } + + @DisplayName("빈 테이블에는 매장 주문을 등록할 수 없다.") + @Test + void createEmptyTableEatInOrder() { + final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); + final UUID orderTableId = orderTableRepository.save(orderTable(false, 0)).getId(); + final TobeOrderCreateRequest expected = createOrderRequest( + orderTableId, createOrderLineItemRequest(menuId, 19_000L, 3L) + ); + assertThatThrownBy(() -> orderService.create(expected)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("숨겨진 메뉴는 주문할 수 없다.") + @Test + void createNotDisplayedMenuOrder() { + final UUID menuId = menuRepository.save(menu(19_000L, false, menuProduct())).getId(); + final TobeOrderCreateRequest expected = createOrderRequest(createOrderLineItemRequest(menuId, 19_000L, 3L)); + assertThatThrownBy(() -> orderService.create(expected)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("주문한 메뉴의 가격은 실제 메뉴 가격과 일치해야 한다.") + @Test + void createNotMatchedMenuPriceOrder() { + final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct())).getId(); + final TobeOrderCreateRequest expected = createOrderRequest(createOrderLineItemRequest(menuId, 16_000L, 3L)); + assertThatThrownBy(() -> orderService.create(expected)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("주문을 접수한다.") + @Test + void accept() { + final UUID orderId = orderRepository.save(order(OrderStatus.WAITING, orderTable(true, 4))).getId(); + final TobeOrderResponse actual = orderService.accept(orderId); + assertThat(actual.getStatus()).isEqualTo(OrderStatus.ACCEPTED); + } + + @DisplayName("접수 대기 중인 주문만 접수할 수 있다.") + @EnumSource(value = OrderStatus.class, names = "WAITING", mode = EnumSource.Mode.EXCLUDE) + @ParameterizedTest + void accept(final OrderStatus status) { + final UUID orderId = orderRepository.save(order(status, orderTable(true, 4))).getId(); + assertThatThrownBy(() -> orderService.accept(orderId)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("주문을 서빙한다.") + @Test + void serve() { + final UUID orderId = orderRepository.save(order(OrderStatus.ACCEPTED)).getId(); + final TobeOrderResponse actual = orderService.serve(orderId); + assertThat(actual.getStatus()).isEqualTo(OrderStatus.SERVED); + } + + @DisplayName("접수된 주문만 서빙할 수 있다.") + @EnumSource(value = OrderStatus.class, names = "ACCEPTED", mode = EnumSource.Mode.EXCLUDE) + @ParameterizedTest + void serve(final OrderStatus status) { + final UUID orderId = orderRepository.save(order(status)).getId(); + assertThatThrownBy(() -> orderService.serve(orderId)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("매장 주문의 경우 서빙된 주문만 완료할 수 있다.") + @EnumSource(value = OrderStatus.class, names = "SERVED", mode = EnumSource.Mode.EXCLUDE) + @ParameterizedTest + void completeTakeoutAndEatInOrder(final OrderStatus status) { + final UUID orderId = orderRepository.save(order(status)).getId(); + assertThatThrownBy(() -> orderService.complete(orderId)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("주문 테이블의 모든 매장 주문이 완료되면 빈 테이블로 설정한다.") + @Test + void completeEatInOrder() { + final TobeOrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); + final TobeOrder expected = orderRepository.save(order(OrderStatus.SERVED, orderTable)); + final TobeOrderResponse actual = orderService.complete(expected.getId()); + assertAll( + () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.COMPLETED), + () -> assertThat(orderTableRepository.findById(orderTable.getId()).get().isOccupied()).isFalse(), + () -> assertThat(orderTableRepository.findById(orderTable.getId()).get().getNumberOfGuests()).isEqualTo( + 0) + ); + } + + @DisplayName("완료되지 않은 매장 주문이 있는 주문 테이블은 빈 테이블로 설정하지 않는다.") + @Test + void completeNotTable() { + final TobeOrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); + orderRepository.save(order(OrderStatus.ACCEPTED, orderTable)); + final TobeOrder expected = orderRepository.save(order(OrderStatus.SERVED, orderTable)); + final TobeOrderResponse actual = orderService.complete(expected.getId()); + assertAll( + () -> assertThat(actual.getStatus()).isEqualTo(OrderStatus.COMPLETED), + () -> assertThat(orderTableRepository.findById(orderTable.getId()).get().isOccupied()).isTrue(), + () -> assertThat(orderTableRepository.findById(orderTable.getId()).get().getNumberOfGuests()).isEqualTo( + 4) + ); + } + + @DisplayName("주문의 목록을 조회할 수 있다.") + @Test + void findAll() { + final TobeOrderTable orderTable = orderTableRepository.save(orderTable(true, 4)); + orderRepository.save(order(OrderStatus.SERVED, orderTable)); + orderRepository.save(order(OrderStatus.COMPLETED)); + final List actual = orderService.findAll(); + assertThat(actual).hasSize(2); + } + + private TobeOrderCreateRequest createOrderRequest(final TobeOrderLineItemRequest... orderLineItems) { + return createOrderRequest(Arrays.asList(orderLineItems)); + } + + private TobeOrderCreateRequest createOrderRequest(List orderLineItems) { + return new TobeOrderCreateRequest(UUID.randomUUID(), OrderStatus.ACCEPTED, LocalDateTime.now(), + orderLineItems, + UUID.randomUUID()); + } + + + private TobeOrderCreateRequest createOrderRequest(final UUID orderTableId, final TobeOrderLineItemRequest... orderLineItems) { + return new TobeOrderCreateRequest(UUID.randomUUID(), OrderStatus.ACCEPTED, LocalDateTime.now(), + Arrays.asList(orderLineItems), orderTableId); + } + + private static TobeOrderLineItemRequest createOrderLineItemRequest(final UUID menuId, final long price, final long quantity) { + return new TobeOrderLineItemRequest(new Random().nextLong(), menuId, quantity, BigDecimal.valueOf(price)); + } +} diff --git a/src/test/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTest.java b/src/test/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTest.java new file mode 100644 index 000000000..fc353f017 --- /dev/null +++ b/src/test/java/kitchenpos/eatinorders/tobe/domain/TobeOrderTest.java @@ -0,0 +1,94 @@ +package kitchenpos.eatinorders.tobe.domain; + +import kitchenpos.TobeFixtures; +import kitchenpos.eatinorders.domain.OrderStatus; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class TobeOrderTest { + + @DisplayName("주문을 생성한다.") + @Test + void create() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + assertThat(tobeOrder.getId()).isNotNull(); + } + + @DisplayName("주문된 음식은 없을 수 없다.") + @Test + void create01() { + assertThatThrownBy(() -> new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), + UUID.randomUUID(), new TobeOrderLineItems(Collections.emptyList()))) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("주문을 접수한다.") + @Test + void accept01() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + tobeOrder.accept(); + assertThat(tobeOrder.getStatus()).isEqualTo(OrderStatus.ACCEPTED); + } + + @DisplayName("주문을 접수 시 주문이 준비중일 때만 가능하다.") + @Test + void accept02() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.ACCEPTED, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + assertThatThrownBy(() -> tobeOrder.accept()) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("주문을 서빙한다.") + @Test + void served01() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.ACCEPTED, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + tobeOrder.served(); + assertThat(tobeOrder.getStatus()).isEqualTo(OrderStatus.SERVED); + } + + @DisplayName("주문을 서빙 시 주문이 접수일 때만 가능하다.") + @Test + void served02() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + assertThatThrownBy(() -> tobeOrder.served()) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("주문을 종료한다.") + @Test + void completed01() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.SERVED, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + tobeOrder.completed(); + assertThat(tobeOrder.getStatus()).isEqualTo(OrderStatus.COMPLETED); + } + + @DisplayName("주문을 종료 시 주문이 서빙일 때만 가능하다.") + @Test + void completed02() { + TobeOrder tobeOrder = new TobeOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), + UUID.randomUUID(), + new TobeOrderLineItems(List.of(TobeFixtures.orderLineItem()))); + assertThatThrownBy(() -> tobeOrder.completed()) + .isInstanceOf(IllegalStateException.class); + } +}