Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ docker compose -p kitchenpos up -d
- [x] 주문 아이템이 반드시 있어야 한다.
- [x] 주문 아이템의 수량은 0개 이상이어야 한다.
- [x] 주문 아이템의 메뉴는 반드시 있어야 한다.
- [x] 배달, 포장 주문시 수량이 0원 이상이어야 한다.
- [x] 배달, 포장 주문시 수량이 0개 이상이어야 한다.
- [x] 메뉴가 노출된 상태여야 한다.
- [x] 메뉴가격과 주문 아이템 가격이 다르면 안된다.
- [x] 배달 주문시 배달 주소가 반드시 있어야 한다.
Expand Down
19 changes: 18 additions & 1 deletion src/main/java/kitchenpos/global/exception/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ public enum ErrorCode implements ErrorType {
NOT_FOUND_MENU("404", "메뉴를 찾을 수 없습니다."),
NOT_FOUND_MENU_GROUP("404", "메뉴그룹을 찾을 수 없습니다."),
NOT_FOUND_MENU_PRODUCT("404", "메뉴상품을 찾을 수 없습니다."),
NOT_FOUND_ORDER("404", "주문을 찾을 수 없습니다."),
NOT_FOUND_ORDER_MENU("404", "주문메뉴를 찾을 수 없습니다."),
NOT_FOUND_ORDER_TABLE("404", "주문테이블을 찾을 수 없습니다."),
NOT_FOUND_ORDER_ITEM("404", "주문항목을 찾을 수 없습니다."),

PRODUCT_PRICE_NOT_ALLOWED("400", "상품가격은 0원 이상이어야 합니다."),
PRODUCT_NAME_NOT_ALLOWED("400", "상품명은 필수값 입니다."),
Expand All @@ -24,7 +28,20 @@ public enum ErrorCode implements ErrorType {
MENU_PRICE_OVER_TOTAL_PRODUCTS_NOT_ALLOWED("400", "메뉴가격은 구성 상품의 총 금액보다 클 수 없습니다."),

MENU_PRODUCT_NOT_ALLOWED("400", "메뉴 상품은 1개 이상 입력해야 합니다."),
MENU_PRODUCT_QTY_NOT_ALLOWED("400", "메뉴 상품 수량은 0개 이상이어야 합니다.");
MENU_PRODUCT_QTY_NOT_ALLOWED("400", "메뉴 상품 수량은 0개 이상이어야 합니다."),

DELIVERY_ADDRESS_NOT_ALLOWED("400", "배달 주소는 필수값 입니다."),
ORDER_PRICE_MISMATCH_MENU_PRICE("400", "주문가격이 실제 메뉴 가격과 일치하지 않습니다."),
ORDER_HIDE_MENU_NOT_ALLOWED("400", "숨김 메뉴는 주문할 수 없습니다."),
ORDER_LINE_ITEM_QTY_NOT_ALLOWED("400", "주문 수량은 0개 이상이어야 합니다."),
ORDER_TABLE_NAME_NOT_ALLOWED("400", "주문 테이블명은 필수값 입니다."),
ORDER_TABLE_NUMBER_OF_GUESTS_NOT_ALLOWED("400", "주문 테이블 인원수는 0명 이상이어야 합니다."),

ORDER_STATUS_IS_NOT_WAITING("400", "주문대기 상태가 아닙니다."),
ORDER_STATUS_IS_NOT_ACCEPTED("400", "주문수락 상태가 아닙니다."),
ORDER_STATUS_IS_NOT_DELIVERED("400", "배달완료 상태가 아닙니다."),
ORDER_STATUS_IS_NOT_SERVED("400", "주문제공 상태가 아닙니다."),
ORDER_TYPE_IS_NOT_ALLOWED("400", "유효한 주문유형이 아닙니다.");

private final String code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package kitchenpos.menu.domain.service;

import java.math.BigDecimal;
import java.util.List;
import kitchenpos.global.exception.ErrorCode;
import kitchenpos.global.exception.NotFoundException;
import kitchenpos.menu.domain.model.MenuId;
import kitchenpos.menu.domain.model.MenuVo.MenuInfo;
import kitchenpos.menu.domain.repository.MenuRepository;
import kitchenpos.order.common.application.MenuContextProvider;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Transactional(readOnly = true)
@Service
public class DefaultMenuContextService implements MenuContextProvider {

private final MenuRepository menuRepository;

public DefaultMenuContextService(MenuRepository menuRepository) {
this.menuRepository = menuRepository;
}

@Override
public BigDecimal getPrice(MenuId menuId) {
return menuRepository.findByMenuId(menuId)
.map(menu -> menu.getPrice().price())
.orElseThrow(() -> new NotFoundException(ErrorCode.NOT_FOUND_MENU.toString()));
}

@Override
public List<MenuInfo> findMenus(List<MenuId> menuIds) {
return menuRepository.findAllByMenuIdIn(menuIds).stream()
.map(MenuInfo::fromEntity)
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package kitchenpos.order.common.application;

import java.math.BigDecimal;
import java.util.List;
import kitchenpos.menu.domain.model.MenuId;
import kitchenpos.menu.domain.model.MenuVo.MenuInfo;

public interface MenuContextProvider {
BigDecimal getPrice(MenuId menuId);

List<MenuInfo> findMenus(List<MenuId> menuIds);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package kitchenpos.order.common.application.dto;

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import kitchenpos.order.common.domain.entity.OrderLineItem;
import kitchenpos.order.common.domain.entity.OrderType;
import kitchenpos.order.common.domain.model.OrderLineItems;
import kitchenpos.order.common.domain.model.OrderVo;
import kitchenpos.order.eatin.domain.model.OrderTableId;

public record OrderRequest() {

public record Create(
@NotNull(message = "주문유형은 필수입니다.")
OrderType type,
UUID orderTableId,
@NotEmpty(message = "메뉴 구성 상품을 하나 이상 포함해야 합니다.")
List<OrderLineItemCreate> orderLineItems,
String deliveryAddress
) {
public OrderVo.Create toVo() {
return new OrderVo.Create(
type,
OrderTableId.of(orderTableId),
OrderLineItems.of(orderLineItems.stream()
.map(item -> OrderLineItem.fromDto(item, null, type))
.collect(Collectors.toList())),
deliveryAddress
);
}
}

public record OrderLineItemCreate(UUID menuId, BigDecimal price, long quantity) {}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package kitchenpos.order.common.application.dto;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import kitchenpos.order.common.domain.entity.OrderLineItem;
import kitchenpos.order.common.domain.entity.OrderStatus;
import kitchenpos.order.common.domain.entity.OrderType;
import kitchenpos.order.common.domain.model.OrderVo;

public record OrderResponse() {
public record GetOrder(
UUID id,
UUID orderTableId,
List<GetOrderItems> orderItems,
LocalDateTime orderDateTime,
OrderStatus status,
OrderType type

) {
public static GetOrder fromVo(OrderVo.OrderInfo vo) {
return new GetOrder(
vo.getOrderId(),
vo.getOrderTableId(),
vo.orderLineItems().getItems().stream()
.map(GetOrderItems::fromVo)
.toList(),
vo.orderDateTime(),
vo.status(),
vo.type()
);
}
}

public record GetOrderItems(
UUID menuId,
long quantity
) {
public static OrderResponse.GetOrderItems fromVo(OrderLineItem vo) {
return new OrderResponse.GetOrderItems(vo.getOrderId().get(), vo.getQuantity().get());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package kitchenpos.order.common.application.dto;

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import java.util.UUID;
import kitchenpos.order.eatin.domain.model.OrderTableGuests;
import kitchenpos.order.eatin.domain.model.OrderTableId;
import kitchenpos.order.eatin.domain.model.OrderTableName;
import kitchenpos.order.eatin.domain.model.OrderTableVo;

public record OrderTableRequest() {

public record Create(
@NotNull(message = "테이블 이름은 필수입니다.")
String name

) {
public OrderTableVo.Create toVo() {
return new OrderTableVo.Create(
OrderTableName.of(name),
OrderTableGuests.of(0),
false
);
}
}

public record UpdateGuests(
UUID orderTableId,
@Positive(message = "테이블 인원 0보다 커야 합니다.")
int numberOfGuests
) {

public OrderTableVo.Update toVo() {
return new OrderTableVo.Update(OrderTableId.of(orderTableId), OrderTableGuests.of(numberOfGuests));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package kitchenpos.order.common.application.dto;

import java.util.UUID;
import kitchenpos.order.eatin.domain.model.OrderTableVo;

public record OrderTableResponse() {
public record GetOrderTable(
UUID id,
String name,
int numberOfGuests,
boolean occupied
) {
public static GetOrderTable fromVo(OrderTableVo.OrderTableInfo vo) {
return new GetOrderTable(
vo.getOrderTableId(),
vo.getOrderTableName(),
vo.getNumberOfGuests(),
vo.occupied()
);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,94 @@
package kitchenpos.order.common.application.facade;

import kitchenpos.order.delivery.application.DeliveryUsecase;
import kitchenpos.order.eatin.application.EatinUsecase;
import kitchenpos.order.takeout.application.TakeoutUsecase;
import java.util.List;
import java.util.UUID;
import kitchenpos.order.common.application.dto.OrderRequest;
import kitchenpos.order.common.application.dto.OrderResponse;
import kitchenpos.order.common.application.dto.OrderResponse.GetOrder;
import kitchenpos.order.common.application.dto.OrderTableRequest.Create;
import kitchenpos.order.common.application.dto.OrderTableRequest.UpdateGuests;
import kitchenpos.order.common.application.dto.OrderTableResponse;
import kitchenpos.order.common.application.dto.OrderTableResponse.GetOrderTable;
import kitchenpos.order.common.domain.model.OrderId;
import kitchenpos.order.common.domain.service.OrderCommandService;
import kitchenpos.order.common.domain.service.OrderQueryService;
import kitchenpos.order.delivery.domain.service.DeliveryService;
import kitchenpos.order.eatin.domain.model.OrderTableId;
import kitchenpos.order.eatin.domain.service.EatInService;
import org.springframework.stereotype.Component;

@Component
public class OrderFacade {
private final TakeoutUsecase takeoutUsecase;
private final DeliveryUsecase deliveryUsecase;
private final EatinUsecase eatinUsecase;

public OrderFacade(TakeoutUsecase takeoutUsecase, DeliveryUsecase deliveryUsecase,
EatinUsecase eatinUsecase) {
this.takeoutUsecase = takeoutUsecase;
this.deliveryUsecase = deliveryUsecase;
this.eatinUsecase = eatinUsecase;
private final DeliveryService deliveryService;
private final EatInService eatinService;
private final OrderQueryService orderQueryService;

private final OrderCommandService orderCommandService;

public OrderFacade(
DeliveryService deliveryService,
EatInService eatinService,
OrderQueryService orderQueryService,
OrderCommandService orderCommandService
) {
this.deliveryService = deliveryService;
this.eatinService = eatinService;
this.orderQueryService = orderQueryService;
this.orderCommandService = orderCommandService;
}

public GetOrder create(OrderRequest.Create request) {
return GetOrder.fromVo(orderCommandService.create(request.toVo()));
}

public OrderResponse.GetOrder accept(final UUID orderId) {
return GetOrder.fromVo(orderCommandService.accept(OrderId.of(orderId)));
}

public OrderResponse.GetOrder serve(final UUID orderId) {
return GetOrder.fromVo(orderCommandService.serve(OrderId.of(orderId)));
}

public GetOrder startDelivery(final UUID orderId) {
return GetOrder.fromVo(deliveryService.startDelivery(OrderId.of(orderId)));
}

public GetOrder completeDelivery(final UUID orderId) {
return GetOrder.fromVo(deliveryService.completeDelivery(OrderId.of(orderId)));
}


public GetOrder complete(UUID orderId) {
return GetOrder.fromVo(orderCommandService.complete(OrderId.of(orderId)));
}

public List<GetOrder> findAll() {
return orderQueryService.findAll()
.stream()
.map(OrderResponse.GetOrder::fromVo)
.toList();
}

public List<GetOrderTable> findOrderTableAll() {
return eatinService.findAll()
.stream()
.map(OrderTableResponse.GetOrderTable::fromVo)
.toList();
}

public GetOrderTable createOrderTable(Create request) {
return GetOrderTable.fromVo(eatinService.create(request.toVo()));
}

public GetOrderTable sit(UUID orderTableId) {
return GetOrderTable.fromVo(eatinService.sit(OrderTableId.of(orderTableId)));
}

public GetOrderTable clear(UUID orderTableId) {
return GetOrderTable.fromVo(eatinService.clear(OrderTableId.of(orderTableId)));
}

public GetOrderTable changeNumberOfGuests(UpdateGuests request) {
return GetOrderTable.fromVo(eatinService.changeNumberOfGuests(request.toVo()));
}
}
Loading