diff --git a/README.md b/README.md index 4a91e3f71..1ea6c3aa7 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ docker compose -p kitchenpos up -d - 메뉴 그룹을 등록할 수 있다. - 메뉴 그룹의 이름이 올바르지 않으면 등록할 수 없다. - 메뉴 그룹의 이름은 비워 둘 수 없다. + - 메뉴 그룹의 이름에는 비속어가 포함될 수 없다. - 메뉴 그룹의 목록을 조회할 수 있다. ### 메뉴 diff --git a/src/main/java/kitchenpos/common/annotation/Validator.java b/src/main/java/kitchenpos/common/annotation/Validator.java new file mode 100644 index 000000000..eb4d9c48f --- /dev/null +++ b/src/main/java/kitchenpos/common/annotation/Validator.java @@ -0,0 +1,17 @@ +package kitchenpos.common.annotation; + +import org.springframework.core.annotation.AliasFor; +import org.springframework.stereotype.Component; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Component +public @interface Validator { + + @AliasFor(annotation = Component.class) + String value() default ""; + +} diff --git a/src/main/java/kitchenpos/common/domain/AggregateRoot.java b/src/main/java/kitchenpos/common/domain/AggregateRoot.java new file mode 100644 index 000000000..08b5ab9d1 --- /dev/null +++ b/src/main/java/kitchenpos/common/domain/AggregateRoot.java @@ -0,0 +1,33 @@ +package kitchenpos.common.domain; + +import org.springframework.data.domain.AfterDomainEventPublication; +import org.springframework.data.domain.DomainEvents; + +import javax.persistence.Transient; +import java.util.ArrayList; +import java.util.List; + +public interface AggregateRoot { + + @Transient + ThreadLocal> threadLocal = ThreadLocal.withInitial(ArrayList::new); + + default Object register(Object event) { + if (event == null) { + return event; + } + threadLocal.get().add(event); + return event; + } + + @AfterDomainEventPublication + default void clear() { + threadLocal.get().clear(); + } + + @DomainEvents + default List domainEvents() { + return new ArrayList<>(threadLocal.get()); + } + +} diff --git a/src/main/java/kitchenpos/common/exception/KitchenPosExceptionType.java b/src/main/java/kitchenpos/common/exception/KitchenPosExceptionType.java index 3df94f8f6..f0383026d 100644 --- a/src/main/java/kitchenpos/common/exception/KitchenPosExceptionType.java +++ b/src/main/java/kitchenpos/common/exception/KitchenPosExceptionType.java @@ -2,10 +2,10 @@ public enum KitchenPosExceptionType implements KitchenPosThrowable { - BAD_REQUEST( "잘못된 요청입니다."), - METHOD_NOT_ALLOWED( "허용되지 않은 기능입니다."), - NOT_FOUND( "찾을 수 없습니다."), - INTERNAL_SERVER_ERROR( "서버 내부 에러입니다."), + BAD_REQUEST("잘못된 요청입니다."), + METHOD_NOT_ALLOWED("허용되지 않은 기능입니다."), + NOT_FOUND("찾을 수 없습니다."), + INTERNAL_SERVER_ERROR("서버 내부 에러입니다."), ; private final String message; diff --git a/src/main/java/kitchenpos/common/infra/DefaultPurgomalum.java b/src/main/java/kitchenpos/common/infra/DefaultPurgomalum.java index beeefce78..9274b46a9 100644 --- a/src/main/java/kitchenpos/common/infra/DefaultPurgomalum.java +++ b/src/main/java/kitchenpos/common/infra/DefaultPurgomalum.java @@ -19,9 +19,9 @@ public DefaultPurgomalum(final RestTemplateBuilder restTemplateBuilder) { @Override public boolean containsProfanity(final String text) { final URI url = UriComponentsBuilder.fromUriString("https://www.purgomalum.com/service/containsprofanity") - .queryParam("text", text) - .build() - .toUri(); + .queryParam("text", text) + .build() + .toUri(); return Boolean.parseBoolean(restTemplate.getForObject(url, String.class)); } } diff --git a/src/main/java/kitchenpos/common/util/CollectionUtils.java b/src/main/java/kitchenpos/common/util/CollectionUtils.java new file mode 100644 index 000000000..caf0f38a0 --- /dev/null +++ b/src/main/java/kitchenpos/common/util/CollectionUtils.java @@ -0,0 +1,19 @@ +package kitchenpos.common.util; + +import kitchenpos.common.exception.KitchenPosException; +import org.springframework.lang.Nullable; + +import java.util.Collection; + +public class CollectionUtils { + + private CollectionUtils() { + } + + public static void requireNonEmpty(@Nullable Collection collection, KitchenPosException exception) { + if (collection == null || collection.isEmpty()) { + throw exception; + } + } + +} diff --git a/src/main/java/kitchenpos/common/ComparisonUtils.java b/src/main/java/kitchenpos/common/util/ComparisonUtils.java similarity index 95% rename from src/main/java/kitchenpos/common/ComparisonUtils.java rename to src/main/java/kitchenpos/common/util/ComparisonUtils.java index 3993f4750..d00589a97 100644 --- a/src/main/java/kitchenpos/common/ComparisonUtils.java +++ b/src/main/java/kitchenpos/common/util/ComparisonUtils.java @@ -1,4 +1,4 @@ -package kitchenpos.common; +package kitchenpos.common.util; import java.math.BigDecimal; diff --git a/src/main/java/kitchenpos/common/values/Name.java b/src/main/java/kitchenpos/common/values/Name.java index 307f5bd49..e750a4f84 100644 --- a/src/main/java/kitchenpos/common/values/Name.java +++ b/src/main/java/kitchenpos/common/values/Name.java @@ -28,7 +28,7 @@ private static void validate(String value, Purgomalum purgomalum) { String message = String.format("이름이 %s 이므로", value); throw new KitchenPosException(message, KitchenPosExceptionType.BAD_REQUEST); } - if(purgomalum.containsProfanity(value)) { + if (purgomalum.containsProfanity(value)) { String message = String.format("이름=%s 에 비속어가 포함되어 있으므로", value); throw new KitchenPosException(message, KitchenPosExceptionType.BAD_REQUEST); } diff --git a/src/main/java/kitchenpos/common/values/Price.java b/src/main/java/kitchenpos/common/values/Price.java index bcf4e0deb..46be911cf 100644 --- a/src/main/java/kitchenpos/common/values/Price.java +++ b/src/main/java/kitchenpos/common/values/Price.java @@ -2,19 +2,20 @@ import kitchenpos.common.exception.KitchenPosException; import kitchenpos.common.exception.KitchenPosExceptionType; +import kitchenpos.common.util.ComparisonUtils; import javax.persistence.Column; import javax.persistence.Embeddable; import java.math.BigDecimal; -import java.util.Map; import java.util.Objects; -import static java.math.BigDecimal.ZERO; -import static kitchenpos.common.ComparisonUtils.lessThan; +import static kitchenpos.common.util.ComparisonUtils.lessThan; @Embeddable public class Price { + public static final Price ZERO = new Price(BigDecimal.ZERO); + @Column(name = "price", nullable = false) private BigDecimal value; @@ -25,13 +26,14 @@ protected Price() { public Price(final Long value) { this(BigDecimal.valueOf(value)); } + public Price(final BigDecimal value) { validate(value); this.value = value; } private static void validate(BigDecimal value) { - if (value == null || lessThan(value, ZERO)) { + if (value == null || lessThan(value, BigDecimal.ZERO)) { String message = String.format("가격이 %s 이므로", value); throw new KitchenPosException(message, KitchenPosExceptionType.BAD_REQUEST); } @@ -42,7 +44,7 @@ public BigDecimal getValue() { } public boolean equalValue(BigDecimal value) { - return this.value.equals(value); + return ComparisonUtils.isEqual(this.value, value); } @Override @@ -58,11 +60,23 @@ public int hashCode() { return Objects.hash(value); } - public BigDecimal multiply(BigDecimal bigDecimal) { - return value.multiply(bigDecimal); + public Price add(Price price) { + BigDecimal result = value.add(price.value); + return new Price(result); + } + + public Price multiply(long number) { + return multiply(BigDecimal.valueOf(number)); } - public BigDecimal multiply(long bigDecimal) { - return value.multiply(BigDecimal.valueOf(bigDecimal)); + + public Price multiply(BigDecimal number) { + BigDecimal result = value.multiply(number); + return new Price(result); + } + + + public boolean isGreaterThan(Price price) { + return ComparisonUtils.greaterThan(value, price.value); } } diff --git a/src/main/java/kitchenpos/common/values/Quantity.java b/src/main/java/kitchenpos/common/values/Quantity.java new file mode 100644 index 000000000..1cc3e218e --- /dev/null +++ b/src/main/java/kitchenpos/common/values/Quantity.java @@ -0,0 +1,47 @@ +package kitchenpos.common.values; + +import kitchenpos.common.exception.KitchenPosException; +import kitchenpos.common.exception.KitchenPosExceptionType; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.util.Objects; + +@Embeddable +public class Quantity { + + @Column(name = "quantity", nullable = false) + private Long value; + + protected Quantity() { + } + + public Quantity(final Long value) { + if (value < 0) { + String message = String.format("수량이 %s 이므로", value); + throw new KitchenPosException(message, KitchenPosExceptionType.BAD_REQUEST); + } + this.value = value; + } + + public Long getValue() { + return value; + } + + public boolean equalValue(Long value) { + return this.value.equals(value); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Quantity quantity = (Quantity) o; + return Objects.equals(value, quantity.value); + } + + @Override + public int hashCode() { + return Objects.hash(value); + } +} diff --git a/src/main/java/kitchenpos/eatinorders/application/OrderService.java b/src/main/java/kitchenpos/eatinorders/application/OrderService.java index c20f52c7f..99270e101 100644 --- a/src/main/java/kitchenpos/eatinorders/application/OrderService.java +++ b/src/main/java/kitchenpos/eatinorders/application/OrderService.java @@ -20,10 +20,10 @@ public class OrderService { private final KitchenridersClient kitchenridersClient; public OrderService( - final OrderRepository orderRepository, - final MenuRepository menuRepository, - final OrderTableRepository orderTableRepository, - final KitchenridersClient kitchenridersClient + final OrderRepository orderRepository, + final MenuRepository menuRepository, + final OrderTableRepository orderTableRepository, + final KitchenridersClient kitchenridersClient ) { this.orderRepository = orderRepository; this.menuRepository = menuRepository; @@ -42,9 +42,9 @@ public Order create(final Order request) { throw new IllegalArgumentException(); } final List menus = menuRepository.findAllByIdIn( - orderLineItemRequests.stream() - .map(OrderLineItem::getMenuId) - .collect(Collectors.toList()) + orderLineItemRequests.stream() + .map(OrderLineItem::getMenuId) + .collect(Collectors.toList()) ); if (menus.size() != orderLineItemRequests.size()) { throw new IllegalArgumentException(); @@ -58,11 +58,11 @@ public Order create(final Order request) { } } final Menu menu = menuRepository.findById(orderLineItemRequest.getMenuId()) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (!menu.isDisplayed()) { throw new IllegalStateException(); } - if (menu.getPrice().compareTo(orderLineItemRequest.getPrice()) != 0) { + if (!menu.getPrice().equalValue(orderLineItemRequest.getPrice())) { throw new IllegalArgumentException(); } final OrderLineItem orderLineItem = new OrderLineItem(); @@ -85,7 +85,7 @@ public Order create(final Order request) { } if (type == OrderType.EAT_IN) { final OrderTable orderTable = orderTableRepository.findById(request.getOrderTableId()) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (!orderTable.isOccupied()) { throw new IllegalStateException(); } @@ -97,7 +97,7 @@ public Order create(final Order request) { @Transactional public Order accept(final UUID orderId) { final Order order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (order.getStatus() != OrderStatus.WAITING) { throw new IllegalStateException(); } @@ -105,8 +105,8 @@ public Order accept(final UUID orderId) { BigDecimal sum = BigDecimal.ZERO; for (final OrderLineItem orderLineItem : order.getOrderLineItems()) { sum = orderLineItem.getMenu() - .getPrice() - .multiply(BigDecimal.valueOf(orderLineItem.getQuantity())); + .getPrice() + .multiply(BigDecimal.valueOf(orderLineItem.getQuantity())).getValue(); } kitchenridersClient.requestDelivery(orderId, sum, order.getDeliveryAddress()); } @@ -117,7 +117,7 @@ public Order accept(final UUID orderId) { @Transactional public Order serve(final UUID orderId) { final Order order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (order.getStatus() != OrderStatus.ACCEPTED) { throw new IllegalStateException(); } @@ -128,7 +128,7 @@ public Order serve(final UUID orderId) { @Transactional public Order startDelivery(final UUID orderId) { final Order order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (order.getType() != OrderType.DELIVERY) { throw new IllegalStateException(); } @@ -142,7 +142,7 @@ public Order startDelivery(final UUID orderId) { @Transactional public Order completeDelivery(final UUID orderId) { final Order order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (order.getStatus() != OrderStatus.DELIVERING) { throw new IllegalStateException(); } @@ -153,7 +153,7 @@ public Order completeDelivery(final UUID orderId) { @Transactional public Order complete(final UUID orderId) { final Order order = orderRepository.findById(orderId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); final OrderType type = order.getType(); final OrderStatus status = order.getStatus(); if (type == OrderType.DELIVERY) { diff --git a/src/main/java/kitchenpos/eatinorders/application/OrderTableService.java b/src/main/java/kitchenpos/eatinorders/application/OrderTableService.java index 1df7e345f..7b4744c50 100644 --- a/src/main/java/kitchenpos/eatinorders/application/OrderTableService.java +++ b/src/main/java/kitchenpos/eatinorders/application/OrderTableService.java @@ -39,7 +39,7 @@ public OrderTable create(final OrderTable request) { @Transactional public OrderTable sit(final UUID orderTableId) { final OrderTable orderTable = orderTableRepository.findById(orderTableId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); orderTable.setOccupied(true); return orderTable; } @@ -47,7 +47,7 @@ public OrderTable sit(final UUID orderTableId) { @Transactional public OrderTable clear(final UUID orderTableId) { final OrderTable orderTable = orderTableRepository.findById(orderTableId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (orderRepository.existsByOrderTableAndStatusNot(orderTable, OrderStatus.COMPLETED)) { throw new IllegalStateException(); } @@ -63,7 +63,7 @@ public OrderTable changeNumberOfGuests(final UUID orderTableId, final OrderTable throw new IllegalArgumentException(); } final OrderTable orderTable = orderTableRepository.findById(orderTableId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NoSuchElementException::new); if (!orderTable.isOccupied()) { throw new IllegalStateException(); } diff --git a/src/main/java/kitchenpos/eatinorders/domain/Order.java b/src/main/java/kitchenpos/eatinorders/domain/Order.java index c6e630c90..71b58c135 100644 --- a/src/main/java/kitchenpos/eatinorders/domain/Order.java +++ b/src/main/java/kitchenpos/eatinorders/domain/Order.java @@ -25,10 +25,10 @@ public class Order { @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) @JoinColumn( - name = "order_id", - nullable = false, - columnDefinition = "binary(16)", - foreignKey = @ForeignKey(name = "fk_order_line_item_to_orders") + name = "order_id", + nullable = false, + columnDefinition = "binary(16)", + foreignKey = @ForeignKey(name = "fk_order_line_item_to_orders") ) private List orderLineItems; @@ -37,9 +37,9 @@ public class Order { @ManyToOne @JoinColumn( - name = "order_table_id", - columnDefinition = "binary(16)", - foreignKey = @ForeignKey(name = "fk_orders_to_order_table") + name = "order_table_id", + columnDefinition = "binary(16)", + foreignKey = @ForeignKey(name = "fk_orders_to_order_table") ) private OrderTable orderTable; diff --git a/src/main/java/kitchenpos/eatinorders/domain/OrderLineItem.java b/src/main/java/kitchenpos/eatinorders/domain/OrderLineItem.java index e1e037caf..426edadf7 100644 --- a/src/main/java/kitchenpos/eatinorders/domain/OrderLineItem.java +++ b/src/main/java/kitchenpos/eatinorders/domain/OrderLineItem.java @@ -16,9 +16,9 @@ public class OrderLineItem { @ManyToOne(optional = false) @JoinColumn( - name = "menu_id", - columnDefinition = "binary(16)", - foreignKey = @ForeignKey(name = "fk_order_line_item_to_menu") + name = "menu_id", + columnDefinition = "binary(16)", + foreignKey = @ForeignKey(name = "fk_order_line_item_to_menu") ) private Menu menu; diff --git a/src/main/java/kitchenpos/eatinorders/ui/OrderRestController.java b/src/main/java/kitchenpos/eatinorders/ui/OrderRestController.java index 1c2741f73..e0e3d69d8 100644 --- a/src/main/java/kitchenpos/eatinorders/ui/OrderRestController.java +++ b/src/main/java/kitchenpos/eatinorders/ui/OrderRestController.java @@ -22,7 +22,7 @@ public OrderRestController(final OrderService orderService) { public ResponseEntity create(@RequestBody final Order request) { final Order response = orderService.create(request); return ResponseEntity.created(URI.create("/api/orders/" + response.getId())) - .body(response); + .body(response); } @PutMapping("/{orderId}/accept") diff --git a/src/main/java/kitchenpos/eatinorders/ui/OrderTableRestController.java b/src/main/java/kitchenpos/eatinorders/ui/OrderTableRestController.java index 120c28d1d..eaaa85aec 100644 --- a/src/main/java/kitchenpos/eatinorders/ui/OrderTableRestController.java +++ b/src/main/java/kitchenpos/eatinorders/ui/OrderTableRestController.java @@ -22,7 +22,7 @@ public OrderTableRestController(final OrderTableService orderTableService) { public ResponseEntity create(@RequestBody final OrderTable request) { final OrderTable response = orderTableService.create(request); return ResponseEntity.created(URI.create("/api/order-tables/" + response.getId())) - .body(response); + .body(response); } @PutMapping("/{orderTableId}/sit") @@ -37,8 +37,8 @@ public ResponseEntity clear(@PathVariable final UUID orderTableId) { @PutMapping("/{orderTableId}/number-of-guests") public ResponseEntity changeNumberOfGuests( - @PathVariable final UUID orderTableId, - @RequestBody final OrderTable request + @PathVariable final UUID orderTableId, + @RequestBody final OrderTable request ) { return ResponseEntity.ok(orderTableService.changeNumberOfGuests(orderTableId, request)); } diff --git a/src/main/java/kitchenpos/menus/application/MenuGroupService.java b/src/main/java/kitchenpos/menus/application/MenuGroupService.java index c468893a2..d661798e7 100644 --- a/src/main/java/kitchenpos/menus/application/MenuGroupService.java +++ b/src/main/java/kitchenpos/menus/application/MenuGroupService.java @@ -1,36 +1,41 @@ package kitchenpos.menus.application; +import kitchenpos.common.domain.Purgomalum; +import kitchenpos.common.values.Name; import kitchenpos.menus.domain.MenuGroup; import kitchenpos.menus.domain.MenuGroupRepository; +import kitchenpos.menus.dto.CreateMenuGroupRequest; +import kitchenpos.menus.dto.MenuGroupDto; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; -import java.util.Objects; -import java.util.UUID; +import java.util.stream.Collectors; @Service public class MenuGroupService { private final MenuGroupRepository menuGroupRepository; + private final Purgomalum purgomalum; - public MenuGroupService(final MenuGroupRepository menuGroupRepository) { + public MenuGroupService(MenuGroupRepository menuGroupRepository, + Purgomalum purgomalum) { this.menuGroupRepository = menuGroupRepository; + this.purgomalum = purgomalum; } @Transactional - public MenuGroup create(final MenuGroup request) { - final String name = request.getName(); - if (Objects.isNull(name) || name.isEmpty()) { - throw new IllegalArgumentException(); - } - final MenuGroup menuGroup = new MenuGroup(); - menuGroup.setId(UUID.randomUUID()); - menuGroup.setName(name); - return menuGroupRepository.save(menuGroup); + public MenuGroupDto create(final CreateMenuGroupRequest request) { + Name name = new Name(request.getName(), purgomalum); + final MenuGroup menuGroup = new MenuGroup(name); + MenuGroup savedResult = menuGroupRepository.save(menuGroup); + return MenuGroupDto.from(savedResult); } @Transactional(readOnly = true) - public List findAll() { - return menuGroupRepository.findAll(); + public List findAll() { + return menuGroupRepository.findAll() + .stream() + .map(MenuGroupDto::from) + .collect(Collectors.toList()); } } diff --git a/src/main/java/kitchenpos/menus/application/MenuProductService.java b/src/main/java/kitchenpos/menus/application/MenuProductService.java new file mode 100644 index 000000000..6cd81064d --- /dev/null +++ b/src/main/java/kitchenpos/menus/application/MenuProductService.java @@ -0,0 +1,42 @@ +package kitchenpos.menus.application; + +import kitchenpos.common.exception.KitchenPosException; +import kitchenpos.common.values.Quantity; +import kitchenpos.menus.domain.MenuProduct; +import kitchenpos.menus.dto.CreateMenuProductRequest; +import kitchenpos.products.application.ProductValidator; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +import static kitchenpos.common.exception.KitchenPosExceptionType.BAD_REQUEST; + +@Service +public class MenuProductService { + + private final ProductValidator productValidator; + + public MenuProductService(final ProductValidator productValidator) { + this.productValidator = productValidator; + } + + public List create(final List request) { + if (Objects.isNull(request) || request.isEmpty()) { + throw new KitchenPosException("메뉴 구성 상품이 없으므로", BAD_REQUEST); + } + + List productIds = request.stream() + .map(CreateMenuProductRequest::getProductId) + .collect(Collectors.toList()); + + productValidator.isExistProducts(productIds); + + return request.stream() + .map(e -> new MenuProduct(e.getProductId(), new Quantity(e.getQuantity()))) + .collect(Collectors.toList()); + } + +} diff --git a/src/main/java/kitchenpos/menus/application/MenuService.java b/src/main/java/kitchenpos/menus/application/MenuService.java index 889da873a..d127cd0d3 100644 --- a/src/main/java/kitchenpos/menus/application/MenuService.java +++ b/src/main/java/kitchenpos/menus/application/MenuService.java @@ -1,142 +1,106 @@ package kitchenpos.menus.application; import kitchenpos.common.domain.Purgomalum; +import kitchenpos.common.exception.KitchenPosException; +import kitchenpos.common.util.CollectionUtils; +import kitchenpos.common.values.Name; +import kitchenpos.common.values.Price; import kitchenpos.menus.domain.*; -import kitchenpos.products.domain.Product; -import kitchenpos.products.domain.ProductRepository; +import kitchenpos.menus.dto.ChangePriceMenuRequest; +import kitchenpos.menus.dto.CreateMenuProductRequest; +import kitchenpos.menus.dto.CreateMenuRequest; +import kitchenpos.menus.dto.MenuDto; +import kitchenpos.products.application.ProductValidator; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.math.BigDecimal; -import java.util.*; +import java.util.List; +import java.util.UUID; import java.util.stream.Collectors; +import static kitchenpos.common.exception.KitchenPosExceptionType.BAD_REQUEST; +import static kitchenpos.common.exception.KitchenPosExceptionType.NOT_FOUND; + @Service public class MenuService { + private final MenuValidator menuValidator; + private final ProductValidator productValidator; + private final MenuProductService menuProductService; private final MenuRepository menuRepository; private final MenuGroupRepository menuGroupRepository; - private final ProductRepository productRepository; private final Purgomalum purgomalum; public MenuService( - final MenuRepository menuRepository, - final MenuGroupRepository menuGroupRepository, - final ProductRepository productRepository, - final Purgomalum purgomalum + final MenuValidator menuValidator, + final ProductValidator productValidator, + final MenuProductService menuProductService, + final MenuRepository menuRepository, + final MenuGroupRepository menuGroupRepository, + final Purgomalum purgomalum ) { + this.menuValidator = menuValidator; + this.productValidator = productValidator; + this.menuProductService = menuProductService; this.menuRepository = menuRepository; this.menuGroupRepository = menuGroupRepository; - this.productRepository = productRepository; this.purgomalum = purgomalum; } @Transactional - public Menu create(final Menu request) { - final BigDecimal price = request.getPrice(); - if (Objects.isNull(price) || price.compareTo(BigDecimal.ZERO) < 0) { - throw new IllegalArgumentException(); - } + public MenuDto create(final CreateMenuRequest request) { + List menuProductRequests = request.getMenuProducts(); + CollectionUtils.requireNonEmpty(menuProductRequests, new KitchenPosException("메뉴 구성 상품이 없으므로", BAD_REQUEST)); final MenuGroup menuGroup = menuGroupRepository.findById(request.getMenuGroupId()) - .orElseThrow(NoSuchElementException::new); - final List menuProductRequests = request.getMenuProducts(); - if (Objects.isNull(menuProductRequests) || menuProductRequests.isEmpty()) { - throw new IllegalArgumentException(); - } - final List products = productRepository.findAllByIdIn( - menuProductRequests.stream() - .map(MenuProduct::getProductId) - .collect(Collectors.toList()) + .orElseThrow(() -> new KitchenPosException("요청하신 ID에 해당하는 메뉴 그룹을", NOT_FOUND)); + + final Price price = new Price(request.getPrice()); + + productValidator.isExistProducts( + menuProductRequests.stream() + .map(CreateMenuProductRequest::getProductId) + .collect(Collectors.toList()) ); - if (products.size() != menuProductRequests.size()) { - throw new IllegalArgumentException(); - } - final List menuProducts = new ArrayList<>(); - BigDecimal sum = BigDecimal.ZERO; - for (final MenuProduct menuProductRequest : menuProductRequests) { - final long quantity = menuProductRequest.getQuantity(); - if (quantity < 0) { - throw new IllegalArgumentException(); - } - final Product product = productRepository.findById(menuProductRequest.getProductId()) - .orElseThrow(NoSuchElementException::new); - sum = sum.add( - product.getPrice() - .multiply(BigDecimal.valueOf(quantity)) - ); - final MenuProduct menuProduct = new MenuProduct(); - menuProduct.setProduct(product); - menuProduct.setQuantity(quantity); - menuProducts.add(menuProduct); - } - if (price.compareTo(sum) > 0) { - throw new IllegalArgumentException(); - } - final String name = request.getName(); - if (Objects.isNull(name) || purgomalum.containsProfanity(name)) { - throw new IllegalArgumentException(); - } - final Menu menu = new Menu(); - menu.setId(UUID.randomUUID()); - menu.setName(name); - menu.setPrice(price); - menu.setMenuGroup(menuGroup); - menu.setDisplayed(request.isDisplayed()); - menu.setMenuProducts(menuProducts); - return menuRepository.save(menu); + + final List menuProducts = menuProductService.create(menuProductRequests); + menuValidator.validatePrice(price, menuProducts); + final Name name = new Name(request.getName(), purgomalum); + final Menu menu = new Menu(name, price, menuGroup.getId(), menuProducts, request.isDisplayed()); + Menu result = menuRepository.save(menu); + return MenuDto.from(result); } @Transactional - public Menu changePrice(final UUID menuId, final Menu request) { - final BigDecimal price = request.getPrice(); - if (Objects.isNull(price) || price.compareTo(BigDecimal.ZERO) < 0) { - throw new IllegalArgumentException(); - } + public MenuDto changePrice(final UUID menuId, final ChangePriceMenuRequest request) { final Menu menu = menuRepository.findById(menuId) - .orElseThrow(NoSuchElementException::new); - BigDecimal sum = BigDecimal.ZERO; - for (final MenuProduct menuProduct : menu.getMenuProducts()) { - sum = sum.add( - menuProduct.getProduct() - .getPrice() - .multiply(BigDecimal.valueOf(menuProduct.getQuantity())) - ); - } - if (price.compareTo(sum) > 0) { - throw new IllegalArgumentException(); - } - menu.setPrice(price); - return menu; + .orElseThrow(() -> new KitchenPosException("요청하신 ID에 해당하는 메뉴를", NOT_FOUND)); + + Price price = new Price(request.getPrice()); + menuValidator.validatePrice(price, menu.getMenuProducts()); + menu.changePrice(price); + return MenuDto.from(menu); } @Transactional - public Menu display(final UUID menuId) { + public MenuDto display(final UUID menuId) { final Menu menu = menuRepository.findById(menuId) - .orElseThrow(NoSuchElementException::new); - BigDecimal sum = BigDecimal.ZERO; - for (final MenuProduct menuProduct : menu.getMenuProducts()) { - sum = sum.add( - menuProduct.getProduct() - .getPrice() - .multiply(BigDecimal.valueOf(menuProduct.getQuantity())) - ); - } - if (menu.getPrice().compareTo(sum) > 0) { - throw new IllegalStateException(); - } - menu.setDisplayed(true); - return menu; + .orElseThrow(() -> new KitchenPosException("요청하신 ID에 해당하는 메뉴를", NOT_FOUND)); + menuValidator.validatePrice(menu.getPrice(), menu.getMenuProducts()); + menu.display(); + return MenuDto.from(menu); } @Transactional - public Menu hide(final UUID menuId) { + public MenuDto hide(final UUID menuId) { final Menu menu = menuRepository.findById(menuId) - .orElseThrow(NoSuchElementException::new); - menu.setDisplayed(false); - return menu; + .orElseThrow(() -> new KitchenPosException("요청하신 ID에 해당하는 메뉴를", NOT_FOUND)); + menu.hide(); + return MenuDto.from(menu); } @Transactional(readOnly = true) - public List findAll() { - return menuRepository.findAll(); + public List findAll() { + return menuRepository.findAll().stream() + .map(MenuDto::from) + .collect(Collectors.toList()); } } diff --git a/src/main/java/kitchenpos/menus/application/MenuValidator.java b/src/main/java/kitchenpos/menus/application/MenuValidator.java new file mode 100644 index 000000000..87c29d372 --- /dev/null +++ b/src/main/java/kitchenpos/menus/application/MenuValidator.java @@ -0,0 +1,45 @@ +package kitchenpos.menus.application; + +import kitchenpos.common.annotation.Validator; +import kitchenpos.common.exception.KitchenPosException; +import kitchenpos.common.values.Price; +import kitchenpos.menus.domain.MenuProduct; +import kitchenpos.products.domain.Product; +import kitchenpos.products.domain.ProductRepository; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; + +import static kitchenpos.common.exception.KitchenPosExceptionType.BAD_REQUEST; + +@Validator +public class MenuValidator { + + private final ProductRepository productRepository; + + public MenuValidator(ProductRepository productRepository) { + this.productRepository = productRepository; + } + + public boolean isMenuPriceGreaterThanSumOfMenuProducts(Price price, List menuProducts) { + List products = productRepository.findAllByIdIn(menuProducts.stream() + .map(MenuProduct::getProductId) + .collect(Collectors.toList())); + Map productMap = products.stream() + .collect(Collectors.toMap(Product::getId, product -> product)); + final Price sum = menuProducts.stream() + .map(e -> productMap.get(e.getProductId()).getPrice().multiply(e.getQuantity().getValue())) + .reduce(Price.ZERO, Price::add); + + return price.isGreaterThan(sum); + } + + public void validatePrice(Price price, List menuProducts) { + if (isMenuPriceGreaterThanSumOfMenuProducts(price, menuProducts)) { + throw new KitchenPosException("메뉴 가격이 구성 상품 가격보다 작으므로", BAD_REQUEST); + } + } + +} diff --git a/src/main/java/kitchenpos/menus/application/ProductPriceChangeListener.java b/src/main/java/kitchenpos/menus/application/ProductPriceChangeListener.java index 76d9a3844..935bf038d 100644 --- a/src/main/java/kitchenpos/menus/application/ProductPriceChangeListener.java +++ b/src/main/java/kitchenpos/menus/application/ProductPriceChangeListener.java @@ -2,39 +2,32 @@ import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuRepository; -import kitchenpos.products.event.ProductPriceChangeEvent; +import kitchenpos.products.domain.ProductPriceChangeEvent; import org.springframework.stereotype.Component; import org.springframework.transaction.event.TransactionPhase; import org.springframework.transaction.event.TransactionalEventListener; -import java.math.BigDecimal; import java.util.List; -import static kitchenpos.common.ComparisonUtils.greaterThan; - @Component public class ProductPriceChangeListener { + private final MenuValidator menuValidator; private final MenuRepository menuRepository; - public ProductPriceChangeListener(MenuRepository menuRepository) { + public ProductPriceChangeListener(MenuValidator menuValidator, MenuRepository menuRepository) { + this.menuValidator = menuValidator; this.menuRepository = menuRepository; } @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) public void hideMenuBasedOnMenuAndMenuProductPrice(ProductPriceChangeEvent event) { final List menus = menuRepository.findAllByProductId(event.getProductId()); - menus.stream().filter(this::isMenuPriceGreaterThanSumOfMenuProducts) - .forEach(e -> e.setDisplayed(false)); // TODO 향후 Menu의 도메인 로직으로 이관 - } - private boolean isMenuPriceGreaterThanSumOfMenuProducts(Menu menu) { - BigDecimal sum = menu.getMenuProducts().stream() - .reduce(BigDecimal.ZERO, (acc, e) -> { - BigDecimal sumOfEachMenuProduct = e.getProduct().getPrice().multiply(e.getQuantity()); - return acc.add(sumOfEachMenuProduct); - }, BigDecimal::add); - return greaterThan(menu.getPrice(), sum); + menus.stream() + .filter(e -> menuValidator.isMenuPriceGreaterThanSumOfMenuProducts(e.getPrice(), e.getMenuProducts())) + .forEach(Menu::hide); } + } diff --git a/src/main/java/kitchenpos/menus/domain/Menu.java b/src/main/java/kitchenpos/menus/domain/Menu.java index e923a6e5d..35ba34350 100644 --- a/src/main/java/kitchenpos/menus/domain/Menu.java +++ b/src/main/java/kitchenpos/menus/domain/Menu.java @@ -1,7 +1,9 @@ package kitchenpos.menus.domain; +import kitchenpos.common.values.Name; +import kitchenpos.common.values.Price; + import javax.persistence.*; -import java.math.BigDecimal; import java.util.List; import java.util.UUID; @@ -13,90 +15,73 @@ public class Menu { private UUID id; @Column(name = "name", nullable = false) - private String name; + private Name name; @Column(name = "price", nullable = false) - private BigDecimal price; - - @ManyToOne(optional = false) - @JoinColumn( - name = "menu_group_id", - columnDefinition = "binary(16)", - foreignKey = @ForeignKey(name = "fk_menu_to_menu_group") - ) - private MenuGroup menuGroup; + private Price price; @Column(name = "displayed", nullable = false) private boolean displayed; @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) @JoinColumn( - name = "menu_id", - nullable = false, - columnDefinition = "binary(16)", - foreignKey = @ForeignKey(name = "fk_menu_product_to_menu") + name = "menu_id", + nullable = false, + columnDefinition = "binary(16)", + foreignKey = @ForeignKey(name = "fk_menu_product_to_menu") ) private List menuProducts; - @Transient + @Column(name = "menu_group_id", insertable = false, updatable = false) private UUID menuGroupId; - public Menu() { + protected Menu() { + } + + public Menu(Name name, Price price, UUID menuGroupId, List menuProducts, boolean displayed) { + this.id = UUID.randomUUID(); + this.name = name; + this.price = price; + this.menuGroupId = menuGroupId; + this.menuProducts = menuProducts; + this.displayed = displayed; } public UUID getId() { + return id; } - public void setId(final UUID id) { - this.id = id; - } - public String getName() { + public Name getName() { return name; } - public void setName(final String name) { - this.name = name; - } - - public BigDecimal getPrice() { + public Price getPrice() { return price; } - public void setPrice(final BigDecimal price) { - this.price = price; - } - - public MenuGroup getMenuGroup() { - return menuGroup; - } - - public void setMenuGroup(final MenuGroup menuGroup) { - this.menuGroup = menuGroup; + public UUID getMenuGroupId() { + return this.menuGroupId; } public boolean isDisplayed() { return displayed; } - public void setDisplayed(final boolean displayed) { - this.displayed = displayed; - } - public List getMenuProducts() { return menuProducts; } - public void setMenuProducts(final List menuProducts) { - this.menuProducts = menuProducts; + public void display() { + this.displayed = true; } - public UUID getMenuGroupId() { - return menuGroupId; + public void hide() { + this.displayed = false; } - public void setMenuGroupId(final UUID menuGroupId) { - this.menuGroupId = menuGroupId; + public void changePrice(Price price) { + this.price = price; } } diff --git a/src/main/java/kitchenpos/menus/domain/MenuGroup.java b/src/main/java/kitchenpos/menus/domain/MenuGroup.java index e65017271..4fb1d19b4 100644 --- a/src/main/java/kitchenpos/menus/domain/MenuGroup.java +++ b/src/main/java/kitchenpos/menus/domain/MenuGroup.java @@ -1,9 +1,8 @@ package kitchenpos.menus.domain; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; +import kitchenpos.common.values.Name; + +import javax.persistence.*; import java.util.UUID; @Table(name = "menu_group") @@ -13,25 +12,23 @@ public class MenuGroup { @Id private UUID id; - @Column(name = "name", nullable = false) - private String name; + @Embedded + private Name name; - public MenuGroup() { + protected MenuGroup() { } - public UUID getId() { - return id; + public MenuGroup(final Name name) { + this.id = UUID.randomUUID(); + this.name = name; } - public void setId(final UUID id) { - this.id = id; + public UUID getId() { + return id; } - public String getName() { + public Name getName() { return name; } - public void setName(final String name) { - this.name = name; - } } diff --git a/src/main/java/kitchenpos/menus/domain/MenuProduct.java b/src/main/java/kitchenpos/menus/domain/MenuProduct.java index d4fc1913d..64260a579 100644 --- a/src/main/java/kitchenpos/menus/domain/MenuProduct.java +++ b/src/main/java/kitchenpos/menus/domain/MenuProduct.java @@ -1,7 +1,7 @@ package kitchenpos.menus.domain; -import kitchenpos.products.domain.Product; +import kitchenpos.common.values.Quantity; import javax.persistence.*; import java.util.UUID; @@ -14,53 +14,37 @@ public class MenuProduct { @Id private Long seq; - @ManyToOne(optional = false) - @JoinColumn( - name = "product_id", - columnDefinition = "binary(16)", - foreignKey = @ForeignKey(name = "fk_menu_product_to_product") - ) - private Product product; + @Embedded + private Quantity quantity; - @Column(name = "quantity", nullable = false) - private long quantity; - - @Transient + @Column(name = "product_id", columnDefinition = "binary(16)", nullable = false) private UUID productId; - public MenuProduct() { + protected MenuProduct() { } - public Long getSeq() { - return seq; + public MenuProduct(UUID productId, Quantity quantity) { + this.productId = productId; + this.quantity = quantity; } - public void setSeq(final Long seq) { + public MenuProduct(Long seq, UUID productId, Quantity quantity) { this.seq = seq; + this.productId = productId; + this.quantity = quantity; } - public Product getProduct() { - return product; - } - public void setProduct(final Product product) { - this.product = product; + public Long getSeq() { + return seq; } - public long getQuantity() { - return quantity; - } - public void setQuantity(final long quantity) { - this.quantity = quantity; + public Quantity getQuantity() { + return quantity; } public UUID getProductId() { return productId; } - - public void setProductId(final UUID productId) { - this.productId = productId; - } - } diff --git a/src/main/java/kitchenpos/menus/dto/ChangePriceMenuRequest.java b/src/main/java/kitchenpos/menus/dto/ChangePriceMenuRequest.java new file mode 100644 index 000000000..58dc5ffe8 --- /dev/null +++ b/src/main/java/kitchenpos/menus/dto/ChangePriceMenuRequest.java @@ -0,0 +1,17 @@ +package kitchenpos.menus.dto; + +import java.math.BigDecimal; + +public class ChangePriceMenuRequest { + + private final BigDecimal price; + + public ChangePriceMenuRequest(BigDecimal price) { + this.price = price; + } + + public BigDecimal getPrice() { + return price; + } + +} diff --git a/src/main/java/kitchenpos/menus/dto/CreateMenuGroupRequest.java b/src/main/java/kitchenpos/menus/dto/CreateMenuGroupRequest.java new file mode 100644 index 000000000..5aca61143 --- /dev/null +++ b/src/main/java/kitchenpos/menus/dto/CreateMenuGroupRequest.java @@ -0,0 +1,15 @@ +package kitchenpos.menus.dto; + +public class CreateMenuGroupRequest { + + private final String name; + + public CreateMenuGroupRequest(String name) { + this.name = name; + } + + public String getName() { + return name; + } + +} diff --git a/src/main/java/kitchenpos/menus/dto/CreateMenuProductRequest.java b/src/main/java/kitchenpos/menus/dto/CreateMenuProductRequest.java new file mode 100644 index 000000000..b5bba6761 --- /dev/null +++ b/src/main/java/kitchenpos/menus/dto/CreateMenuProductRequest.java @@ -0,0 +1,28 @@ +package kitchenpos.menus.dto; + +import java.util.UUID; + +public class CreateMenuProductRequest { + + private Long seq; + private long quantity; + private UUID productId; + + public CreateMenuProductRequest(UUID productId, long quantity) { + this.productId = productId; + this.quantity = quantity; + } + + public Long getSeq() { + return seq; + } + + public long getQuantity() { + return quantity; + } + + public UUID getProductId() { + return productId; + } + +} diff --git a/src/main/java/kitchenpos/menus/dto/CreateMenuRequest.java b/src/main/java/kitchenpos/menus/dto/CreateMenuRequest.java new file mode 100644 index 000000000..1f710484e --- /dev/null +++ b/src/main/java/kitchenpos/menus/dto/CreateMenuRequest.java @@ -0,0 +1,41 @@ +package kitchenpos.menus.dto; + +import java.math.BigDecimal; +import java.util.List; +import java.util.UUID; + +public class CreateMenuRequest { + private final String name; + private final BigDecimal price; + private final UUID menuGroupId; + private final boolean displayed; + private final List menuProducts; + + public CreateMenuRequest(String name, BigDecimal price, UUID menuGroupId, boolean displayed, List menuProducts) { + this.name = name; + this.price = price; + this.menuGroupId = menuGroupId; + this.displayed = displayed; + this.menuProducts = menuProducts; + } + + public String getName() { + return name; + } + + public BigDecimal getPrice() { + return price; + } + + public UUID getMenuGroupId() { + return menuGroupId; + } + + public boolean isDisplayed() { + return displayed; + } + + public List getMenuProducts() { + return menuProducts; + } +} diff --git a/src/main/java/kitchenpos/menus/dto/MenuDto.java b/src/main/java/kitchenpos/menus/dto/MenuDto.java new file mode 100644 index 000000000..759106f9d --- /dev/null +++ b/src/main/java/kitchenpos/menus/dto/MenuDto.java @@ -0,0 +1,59 @@ +package kitchenpos.menus.dto; + +import kitchenpos.common.values.Name; +import kitchenpos.common.values.Price; +import kitchenpos.menus.domain.Menu; +import kitchenpos.menus.domain.MenuProduct; + +import java.util.List; +import java.util.UUID; + +public class MenuDto { + + private UUID id; + private Name name; + private Price price; + private boolean displayed; + private List menuProducts; + private UUID menuGroupId; + + public MenuDto() { + } + + public static MenuDto from(Menu menu) { + final MenuDto menuDto = new MenuDto(); + menuDto.id = menu.getId(); + menuDto.name = menu.getName(); + menuDto.price = menu.getPrice(); + menuDto.displayed = menu.isDisplayed(); + menuDto.menuProducts = menu.getMenuProducts(); + menuDto.menuGroupId = menu.getMenuGroupId(); + + return menuDto; + } + + public UUID getId() { + return id; + } + + public Name getName() { + return name; + } + + public Price getPrice() { + return price; + } + + public boolean isDisplayed() { + return displayed; + } + + public List getMenuProducts() { + return menuProducts; + } + + public UUID getMenuGroupId() { + return menuGroupId; + } + +} diff --git a/src/main/java/kitchenpos/menus/dto/MenuGroupDto.java b/src/main/java/kitchenpos/menus/dto/MenuGroupDto.java new file mode 100644 index 000000000..b553148a2 --- /dev/null +++ b/src/main/java/kitchenpos/menus/dto/MenuGroupDto.java @@ -0,0 +1,30 @@ +package kitchenpos.menus.dto; + +import kitchenpos.common.values.Name; +import kitchenpos.menus.domain.MenuGroup; + +import java.util.UUID; + +public class MenuGroupDto { + + private UUID id; + private Name name; + + public MenuGroupDto(UUID id, Name name) { + this.id = id; + this.name = name; + } + + public static MenuGroupDto from(MenuGroup savedResult) { + return new MenuGroupDto(savedResult.getId(), savedResult.getName()); + } + + public UUID getId() { + return id; + } + + public Name getName() { + return name; + } + +} diff --git a/src/main/java/kitchenpos/menus/domain/JpaMenuGroupRepository.java b/src/main/java/kitchenpos/menus/infra/JpaMenuGroupRepository.java similarity index 60% rename from src/main/java/kitchenpos/menus/domain/JpaMenuGroupRepository.java rename to src/main/java/kitchenpos/menus/infra/JpaMenuGroupRepository.java index 233488198..4e9fbf1b9 100644 --- a/src/main/java/kitchenpos/menus/domain/JpaMenuGroupRepository.java +++ b/src/main/java/kitchenpos/menus/infra/JpaMenuGroupRepository.java @@ -1,5 +1,7 @@ -package kitchenpos.menus.domain; +package kitchenpos.menus.infra; +import kitchenpos.menus.domain.MenuGroup; +import kitchenpos.menus.domain.MenuGroupRepository; import org.springframework.data.jpa.repository.JpaRepository; import java.util.UUID; diff --git a/src/main/java/kitchenpos/menus/domain/JpaMenuRepository.java b/src/main/java/kitchenpos/menus/infra/JpaMenuRepository.java similarity index 76% rename from src/main/java/kitchenpos/menus/domain/JpaMenuRepository.java rename to src/main/java/kitchenpos/menus/infra/JpaMenuRepository.java index 796499c30..80c93da76 100644 --- a/src/main/java/kitchenpos/menus/domain/JpaMenuRepository.java +++ b/src/main/java/kitchenpos/menus/infra/JpaMenuRepository.java @@ -1,5 +1,7 @@ -package kitchenpos.menus.domain; +package kitchenpos.menus.infra; +import kitchenpos.menus.domain.Menu; +import kitchenpos.menus.domain.MenuRepository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -8,7 +10,7 @@ import java.util.UUID; public interface JpaMenuRepository extends MenuRepository, JpaRepository { - @Query("select m from Menu m join m.menuProducts mp where mp.product.id = :productId") + @Query("select m from Menu m join m.menuProducts mp where mp.productId = :productId") @Override List findAllByProductId(@Param("productId") UUID productId); } diff --git a/src/main/java/kitchenpos/menus/ui/MenuGroupRestController.java b/src/main/java/kitchenpos/menus/ui/MenuGroupRestController.java index 1a5d0fd06..8e9d1cc5b 100644 --- a/src/main/java/kitchenpos/menus/ui/MenuGroupRestController.java +++ b/src/main/java/kitchenpos/menus/ui/MenuGroupRestController.java @@ -1,7 +1,8 @@ package kitchenpos.menus.ui; import kitchenpos.menus.application.MenuGroupService; -import kitchenpos.menus.domain.MenuGroup; +import kitchenpos.menus.dto.CreateMenuGroupRequest; +import kitchenpos.menus.dto.MenuGroupDto; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -18,14 +19,14 @@ public MenuGroupRestController(final MenuGroupService menuGroupService) { } @PostMapping - public ResponseEntity create(@RequestBody final MenuGroup request) { - final MenuGroup response = menuGroupService.create(request); + public ResponseEntity create(@RequestBody final CreateMenuGroupRequest request) { + final MenuGroupDto response = menuGroupService.create(request); return ResponseEntity.created(URI.create("/api/menu-groups/" + response.getId())) - .body(response); + .body(response); } @GetMapping - public ResponseEntity> findAll() { + public ResponseEntity> findAll() { return ResponseEntity.ok(menuGroupService.findAll()); } } diff --git a/src/main/java/kitchenpos/menus/ui/MenuRestController.java b/src/main/java/kitchenpos/menus/ui/MenuRestController.java index 3e3a0e23a..427071a6c 100644 --- a/src/main/java/kitchenpos/menus/ui/MenuRestController.java +++ b/src/main/java/kitchenpos/menus/ui/MenuRestController.java @@ -1,7 +1,9 @@ package kitchenpos.menus.ui; import kitchenpos.menus.application.MenuService; -import kitchenpos.menus.domain.Menu; +import kitchenpos.menus.dto.ChangePriceMenuRequest; +import kitchenpos.menus.dto.CreateMenuRequest; +import kitchenpos.menus.dto.MenuDto; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -19,29 +21,29 @@ public MenuRestController(final MenuService menuService) { } @PostMapping - public ResponseEntity create(@RequestBody final Menu request) { - final Menu response = menuService.create(request); + public ResponseEntity create(@RequestBody final CreateMenuRequest request) { + final MenuDto response = menuService.create(request); return ResponseEntity.created(URI.create("/api/menus/" + response.getId())) - .body(response); + .body(response); } @PutMapping("/{menuId}/price") - public ResponseEntity changePrice(@PathVariable final UUID menuId, @RequestBody final Menu request) { + public ResponseEntity changePrice(@PathVariable final UUID menuId, @RequestBody final ChangePriceMenuRequest request) { return ResponseEntity.ok(menuService.changePrice(menuId, request)); } @PutMapping("/{menuId}/display") - public ResponseEntity display(@PathVariable final UUID menuId) { + public ResponseEntity display(@PathVariable final UUID menuId) { return ResponseEntity.ok(menuService.display(menuId)); } @PutMapping("/{menuId}/hide") - public ResponseEntity hide(@PathVariable final UUID menuId) { + public ResponseEntity hide(@PathVariable final UUID menuId) { return ResponseEntity.ok(menuService.hide(menuId)); } @GetMapping - public ResponseEntity> findAll() { + public ResponseEntity> findAll() { return ResponseEntity.ok(menuService.findAll()); } } diff --git a/src/main/java/kitchenpos/products/application/ProductService.java b/src/main/java/kitchenpos/products/application/ProductService.java index 702a0ce84..08cf643b7 100644 --- a/src/main/java/kitchenpos/products/application/ProductService.java +++ b/src/main/java/kitchenpos/products/application/ProductService.java @@ -4,12 +4,11 @@ import kitchenpos.common.exception.KitchenPosException; import kitchenpos.common.values.Name; import kitchenpos.common.values.Price; -import kitchenpos.products.dto.ChangePriceRequest; -import kitchenpos.products.dto.CreateReqeust; -import kitchenpos.products.dto.ProductDto; -import kitchenpos.products.event.ProductPriceChangeEvent; import kitchenpos.products.domain.Product; import kitchenpos.products.domain.ProductRepository; +import kitchenpos.products.dto.ChangePriceRequest; +import kitchenpos.products.dto.CreateRequest; +import kitchenpos.products.dto.ProductDto; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -36,7 +35,7 @@ public ProductService( } @Transactional - public ProductDto create(final CreateReqeust request) { + public ProductDto create(final CreateRequest request) { final Name name = new Name(request.getName(), purgomalum); final Price price = new Price(request.getPrice()); final Product product = new Product(name, price); @@ -48,9 +47,9 @@ public ProductDto create(final CreateReqeust request) { public ProductDto changePrice(final UUID productId, final ChangePriceRequest request) { final Price price = new Price(request.getPrice()); final Product product = productRepository.findById(productId) - .orElseThrow(() -> new KitchenPosException("요청하신 ID에 해당하는 상품을", NOT_FOUND)); + .orElseThrow(() -> new KitchenPosException("요청하신 ID에 해당하는 상품을", NOT_FOUND)); product.changePrice(price); - publisher.publishEvent(new ProductPriceChangeEvent(product.getId())); + productRepository.save(product); return ProductDto.from(product); } diff --git a/src/main/java/kitchenpos/products/application/ProductValidator.java b/src/main/java/kitchenpos/products/application/ProductValidator.java new file mode 100644 index 000000000..cd112b9c9 --- /dev/null +++ b/src/main/java/kitchenpos/products/application/ProductValidator.java @@ -0,0 +1,30 @@ +package kitchenpos.products.application; + +import kitchenpos.common.annotation.Validator; +import kitchenpos.common.exception.KitchenPosException; +import kitchenpos.products.domain.Product; +import kitchenpos.products.domain.ProductRepository; + +import java.util.List; +import java.util.UUID; + +import static kitchenpos.common.exception.KitchenPosExceptionType.NOT_FOUND; + +@Validator +public class ProductValidator { + + private final ProductRepository productRepository; + + public ProductValidator(ProductRepository productRepository) { + this.productRepository = productRepository; + } + + public void isExistProducts(List productIds) { + List products = productRepository.findAllByIdIn(productIds); + + if (products.size() != productIds.size()) { + String message = String.format("상품=%s 중 일부를 ", productIds); + throw new KitchenPosException(message, NOT_FOUND); + } + } +} diff --git a/src/main/java/kitchenpos/products/domain/Product.java b/src/main/java/kitchenpos/products/domain/Product.java index b7e284092..bf6b2cefa 100644 --- a/src/main/java/kitchenpos/products/domain/Product.java +++ b/src/main/java/kitchenpos/products/domain/Product.java @@ -1,15 +1,15 @@ package kitchenpos.products.domain; +import kitchenpos.common.domain.AggregateRoot; import kitchenpos.common.values.Name; import kitchenpos.common.values.Price; import javax.persistence.*; -import java.math.BigDecimal; import java.util.UUID; @Table(name = "product") @Entity -public class Product { +public class Product implements AggregateRoot { @Column(name = "id", columnDefinition = "binary(16)") @Id private UUID id; @@ -33,11 +33,9 @@ public UUID getId() { return id; } - public void changePrice(BigDecimal price) { - this.changePrice(new Price(price)); - } public void changePrice(Price price) { this.price = price; + register(new ProductPriceChangeEvent(this.id)); } public Name getName() { diff --git a/src/main/java/kitchenpos/products/event/ProductPriceChangeEvent.java b/src/main/java/kitchenpos/products/domain/ProductPriceChangeEvent.java similarity index 87% rename from src/main/java/kitchenpos/products/event/ProductPriceChangeEvent.java rename to src/main/java/kitchenpos/products/domain/ProductPriceChangeEvent.java index 4f5ad5b85..2382cbbfc 100644 --- a/src/main/java/kitchenpos/products/event/ProductPriceChangeEvent.java +++ b/src/main/java/kitchenpos/products/domain/ProductPriceChangeEvent.java @@ -1,4 +1,4 @@ -package kitchenpos.products.event; +package kitchenpos.products.domain; import java.util.UUID; diff --git a/src/main/java/kitchenpos/products/domain/ProductRepository.java b/src/main/java/kitchenpos/products/domain/ProductRepository.java index 3637e4232..16c2b06cb 100644 --- a/src/main/java/kitchenpos/products/domain/ProductRepository.java +++ b/src/main/java/kitchenpos/products/domain/ProductRepository.java @@ -12,5 +12,6 @@ public interface ProductRepository { List findAll(); List findAllByIdIn(List ids); + } diff --git a/src/main/java/kitchenpos/products/dto/CreateReqeust.java b/src/main/java/kitchenpos/products/dto/CreateRequest.java similarity index 72% rename from src/main/java/kitchenpos/products/dto/CreateReqeust.java rename to src/main/java/kitchenpos/products/dto/CreateRequest.java index 23ae398b3..bd5f850f1 100644 --- a/src/main/java/kitchenpos/products/dto/CreateReqeust.java +++ b/src/main/java/kitchenpos/products/dto/CreateRequest.java @@ -2,15 +2,15 @@ import java.math.BigDecimal; -public class CreateReqeust { +public class CreateRequest { private String name; private BigDecimal price; - public CreateReqeust() { + public CreateRequest() { } - public CreateReqeust(String name, BigDecimal price) { + public CreateRequest(String name, BigDecimal price) { this.name = name; this.price = price; } diff --git a/src/main/java/kitchenpos/products/dto/ProductDto.java b/src/main/java/kitchenpos/products/dto/ProductDto.java index be328c127..9c821ebda 100644 --- a/src/main/java/kitchenpos/products/dto/ProductDto.java +++ b/src/main/java/kitchenpos/products/dto/ProductDto.java @@ -8,42 +8,42 @@ public class ProductDto { - private UUID id; - private Name name; - private Price price; - - public ProductDto() { - } - - public UUID getId() { - return id; - } - - public void setId(UUID id) { - this.id = id; - } - - public Name getName() { - return name; - } - - public void setName(Name name) { - this.name = name; - } - - public Price getPrice() { - return price; - } - - public void setPrice(Price price) { - this.price = price; - } - - public static ProductDto from(Product product) { - ProductDto result = new ProductDto(); - result.id = product.getId(); - result.name = product.getName(); - result.price = product.getPrice(); - return result; - } + private UUID id; + private Name name; + private Price price; + + public ProductDto() { + } + + public static ProductDto from(Product product) { + ProductDto result = new ProductDto(); + result.id = product.getId(); + result.name = product.getName(); + result.price = product.getPrice(); + return result; + } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public Name getName() { + return name; + } + + public void setName(Name name) { + this.name = name; + } + + public Price getPrice() { + return price; + } + + public void setPrice(Price price) { + this.price = price; + } } diff --git a/src/main/java/kitchenpos/products/ui/ProductRestController.java b/src/main/java/kitchenpos/products/ui/ProductRestController.java index 97fddbbaf..2882f0538 100644 --- a/src/main/java/kitchenpos/products/ui/ProductRestController.java +++ b/src/main/java/kitchenpos/products/ui/ProductRestController.java @@ -1,9 +1,9 @@ package kitchenpos.products.ui; import kitchenpos.products.application.ProductService; -import kitchenpos.products.dto.ChangePriceRequest; -import kitchenpos.products.dto.CreateReqeust; import kitchenpos.products.domain.Product; +import kitchenpos.products.dto.ChangePriceRequest; +import kitchenpos.products.dto.CreateRequest; import kitchenpos.products.dto.ProductDto; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -22,10 +22,10 @@ public ProductRestController(final ProductService productService) { } @PostMapping - public ResponseEntity create(@RequestBody final CreateReqeust request) { + public ResponseEntity create(@RequestBody final CreateRequest request) { final ProductDto response = productService.create(request); return ResponseEntity.created(URI.create("/api/products/" + response.getId())) - .body(response); + .body(response); } @PutMapping("/{productId}/price") diff --git a/src/test/java/kitchenpos/Fixtures.java b/src/test/java/kitchenpos/Fixtures.java index 7bdef3ee3..55bcdf903 100644 --- a/src/test/java/kitchenpos/Fixtures.java +++ b/src/test/java/kitchenpos/Fixtures.java @@ -1,15 +1,15 @@ package kitchenpos; +import kitchenpos.common.infra.FakePurgomalum; import kitchenpos.common.values.Name; import kitchenpos.common.values.Price; +import kitchenpos.common.values.Quantity; import kitchenpos.eatinorders.domain.*; -import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuGroup; +import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuProduct; -import kitchenpos.common.infra.FakePurgomalum; import kitchenpos.products.domain.Product; -import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Arrays; import java.util.Random; @@ -27,41 +27,39 @@ public static Menu menu(final long price, final MenuProduct... menuProducts) { } public static Menu menu(final long price, final boolean displayed, final MenuProduct... menuProducts) { - final Menu menu = new Menu(); - menu.setId(UUID.randomUUID()); - menu.setName("후라이드+후라이드"); - menu.setPrice(BigDecimal.valueOf(price)); - menu.setMenuGroup(menuGroup()); - menu.setDisplayed(displayed); - menu.setMenuProducts(Arrays.asList(menuProducts)); - return menu; + Name createdName = new Name("후라이드+후라이드", FakePurgomalum.create()); + Price createdPrice = new Price(price); + return new Menu( + createdName, + createdPrice, + menuGroup().getId(), + Arrays.asList(menuProducts), + displayed + ); } public static MenuGroup menuGroup() { - return menuGroup("두마리메뉴"); + return menuGroup(new Name("후라이드+후라이드", FakePurgomalum.create())); } - public static MenuGroup menuGroup(final String name) { - final MenuGroup menuGroup = new MenuGroup(); - menuGroup.setId(UUID.randomUUID()); - menuGroup.setName(name); - return menuGroup; + public static MenuGroup menuGroup(final Name name) { + return new MenuGroup(name); } public static MenuProduct menuProduct() { - final MenuProduct menuProduct = new MenuProduct(); - menuProduct.setSeq(new Random().nextLong()); - menuProduct.setProduct(product()); - menuProduct.setQuantity(2L); - return menuProduct; + return new MenuProduct( + new Random().nextLong(), + product().getId(), + new Quantity(2L) + ); } public static MenuProduct menuProduct(final Product product, final long quantity) { - final MenuProduct menuProduct = new MenuProduct(); - menuProduct.setSeq(new Random().nextLong()); - menuProduct.setProduct(product); - menuProduct.setQuantity(quantity); - return menuProduct; + return new MenuProduct( + new Random().nextLong(), + product.getId(), + new Quantity(quantity) + ); } public static Order order(final OrderStatus status, final String deliveryAddress) { diff --git a/src/test/java/kitchenpos/IntegrationTest.java b/src/test/java/kitchenpos/IntegrationTest.java new file mode 100644 index 000000000..a1b85f5e7 --- /dev/null +++ b/src/test/java/kitchenpos/IntegrationTest.java @@ -0,0 +1,25 @@ +package kitchenpos; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Lazy; +import org.springframework.test.context.TestConstructor; +import org.springframework.test.context.event.ApplicationEvents; +import org.springframework.test.context.event.RecordApplicationEvents; + +import javax.transaction.Transactional; + +@Transactional +@RecordApplicationEvents +@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public abstract class IntegrationTest { + + /** + * 생성자 주입시 하위 클래스에서 매번 @Lazy 를 달아주어야 하는 불편함이 있습니다. + * 그래서 사용성을 고려해 직접 Autowiring 합니다! + */ + @Autowired + protected ApplicationEvents applicationEvents; + +} diff --git a/src/test/java/kitchenpos/common/ComparisonUtilsTest.java b/src/test/java/kitchenpos/common/ComparisonUtilsTest.java index bb1e89cf4..ff055b085 100644 --- a/src/test/java/kitchenpos/common/ComparisonUtilsTest.java +++ b/src/test/java/kitchenpos/common/ComparisonUtilsTest.java @@ -1,12 +1,14 @@ package kitchenpos.common; +import kitchenpos.common.util.ComparisonUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.math.BigDecimal; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; class ComparisonUtilsTest { diff --git a/src/test/java/kitchenpos/products/application/FakeApplicationEventPublisher.java b/src/test/java/kitchenpos/common/infra/FakeApplicationEventPublisher.java similarity index 91% rename from src/test/java/kitchenpos/products/application/FakeApplicationEventPublisher.java rename to src/test/java/kitchenpos/common/infra/FakeApplicationEventPublisher.java index b7bc0bd1f..d6bcb37ee 100644 --- a/src/test/java/kitchenpos/products/application/FakeApplicationEventPublisher.java +++ b/src/test/java/kitchenpos/common/infra/FakeApplicationEventPublisher.java @@ -1,11 +1,10 @@ -package kitchenpos.products.application; +package kitchenpos.common.infra; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import java.util.ArrayList; import java.util.List; -import java.util.Optional; public class FakeApplicationEventPublisher implements ApplicationEventPublisher { private static final List events = new ArrayList<>(); diff --git a/src/test/java/kitchenpos/common/values/NameTest.java b/src/test/java/kitchenpos/common/values/NameTest.java index d8b6c200a..879fd0381 100644 --- a/src/test/java/kitchenpos/common/values/NameTest.java +++ b/src/test/java/kitchenpos/common/values/NameTest.java @@ -1,17 +1,12 @@ package kitchenpos.common.values; -import kitchenpos.common.exception.KitchenPosException; -import kitchenpos.common.exception.KitchenPosExceptionType; import kitchenpos.common.infra.FakePurgomalum; 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 org.springframework.web.client.HttpClientErrorException; import static kitchenpos.common.exception.KitchenPosExceptionType.BAD_REQUEST; -import static kitchenpos.common.exception.KitchenPosExceptionType.METHOD_NOT_ALLOWED; -import static kitchenpos.util.KitchenPostExceptionAssertionUtils.assertEqualsExceptionType; import static kitchenpos.util.KitchenPostExceptionAssertionUtils.assertThrows; import static org.junit.jupiter.api.Assertions.*; diff --git a/src/test/java/kitchenpos/common/values/PriceTest.java b/src/test/java/kitchenpos/common/values/PriceTest.java index 263270dd4..694f6c3b2 100644 --- a/src/test/java/kitchenpos/common/values/PriceTest.java +++ b/src/test/java/kitchenpos/common/values/PriceTest.java @@ -1,6 +1,5 @@ package kitchenpos.common.values; -import kitchenpos.common.exception.KitchenPosExceptionType; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/kitchenpos/common/values/QuantityTest.java b/src/test/java/kitchenpos/common/values/QuantityTest.java new file mode 100644 index 000000000..486734344 --- /dev/null +++ b/src/test/java/kitchenpos/common/values/QuantityTest.java @@ -0,0 +1,31 @@ +package kitchenpos.common.values; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; + +import static kitchenpos.common.exception.KitchenPosExceptionType.BAD_REQUEST; +import static kitchenpos.util.KitchenPostExceptionAssertionUtils.assertThrows; +import static org.junit.jupiter.api.Assertions.*; + + +class QuantityTest { + + @DisplayName("[정상] 가격을 생성합니다.") + @Test + void create() { + final Quantity quantity = new Quantity(1000L); + assertAll( + () -> assertNotNull(quantity), + () -> assertTrue(quantity.equalValue(1000L)) + ); + } + + @DisplayName("[예외] 음수로 가격을 생성할 수 없습니다.") + @Test + void create_exception1() { + assertThrows(BAD_REQUEST, () -> new Quantity(-1L)); + } + +} diff --git a/src/test/java/kitchenpos/eatinorders/application/OrderServiceTest.java b/src/test/java/kitchenpos/eatinorders/application/OrderServiceTest.java index 96bf0f286..cc7defc0d 100644 --- a/src/test/java/kitchenpos/eatinorders/application/OrderServiceTest.java +++ b/src/test/java/kitchenpos/eatinorders/application/OrderServiceTest.java @@ -1,8 +1,8 @@ package kitchenpos.eatinorders.application; import kitchenpos.eatinorders.domain.*; -import kitchenpos.menus.application.InMemoryMenuRepository; import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.menus.infra.InMemoryMenuRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/kitchenpos/menus/application/MenuGroupServiceTest.java b/src/test/java/kitchenpos/menus/application/MenuGroupServiceTest.java index a5fbc71d1..732d4434a 100644 --- a/src/test/java/kitchenpos/menus/application/MenuGroupServiceTest.java +++ b/src/test/java/kitchenpos/menus/application/MenuGroupServiceTest.java @@ -1,7 +1,12 @@ package kitchenpos.menus.application; -import kitchenpos.menus.domain.MenuGroup; +import kitchenpos.common.domain.Purgomalum; +import kitchenpos.common.infra.FakePurgomalum; +import kitchenpos.common.values.Name; import kitchenpos.menus.domain.MenuGroupRepository; +import kitchenpos.menus.dto.CreateMenuGroupRequest; +import kitchenpos.menus.dto.MenuGroupDto; +import kitchenpos.menus.infra.InMemoryMenuGroupRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -11,29 +16,33 @@ import java.util.List; import static kitchenpos.Fixtures.menuGroup; +import static kitchenpos.common.exception.KitchenPosExceptionType.BAD_REQUEST; +import static kitchenpos.util.KitchenPostExceptionAssertionUtils.assertThrows; 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.assertTrue; class MenuGroupServiceTest { private MenuGroupRepository menuGroupRepository; + private Purgomalum purgomalum; private MenuGroupService menuGroupService; @BeforeEach void setUp() { menuGroupRepository = new InMemoryMenuGroupRepository(); - menuGroupService = new MenuGroupService(menuGroupRepository); + purgomalum = FakePurgomalum.create(); + menuGroupService = new MenuGroupService(menuGroupRepository, purgomalum); } @DisplayName("메뉴 그룹을 등록할 수 있다.") @Test void create() { - final MenuGroup expected = createMenuGroupRequest("두마리메뉴"); - final MenuGroup actual = menuGroupService.create(expected); + final CreateMenuGroupRequest request = createMenuGroupRequest("두마리메뉴"); + final MenuGroupDto actual = menuGroupService.create(request); assertThat(actual).isNotNull(); assertAll( () -> assertThat(actual.getId()).isNotNull(), - () -> assertThat(actual.getName()).isEqualTo(expected.getName()) + () -> assertTrue(actual.getName().equalValue(request.getName())) ); } @@ -41,22 +50,20 @@ void create() { @NullAndEmptySource @ParameterizedTest void create(final String name) { - final MenuGroup expected = createMenuGroupRequest(name); - assertThatThrownBy(() -> menuGroupService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + final CreateMenuGroupRequest request = createMenuGroupRequest(name); + assertThrows(BAD_REQUEST, () -> menuGroupService.create(request)); } @DisplayName("메뉴 그룹의 목록을 조회할 수 있다.") @Test void findAll() { - menuGroupRepository.save(menuGroup("두마리메뉴")); - final List actual = menuGroupService.findAll(); + Name name = new Name("두마리메뉴", purgomalum); + menuGroupRepository.save(menuGroup(name)); + final List actual = menuGroupService.findAll(); assertThat(actual).hasSize(1); } - private MenuGroup createMenuGroupRequest(final String name) { - final MenuGroup menuGroup = new MenuGroup(); - menuGroup.setName(name); - return menuGroup; + private CreateMenuGroupRequest createMenuGroupRequest(final String name) { + return new CreateMenuGroupRequest(name); } } diff --git a/src/test/java/kitchenpos/menus/application/MenuServiceTest.java b/src/test/java/kitchenpos/menus/application/MenuServiceTest.java index 313e3bef2..62a56040e 100644 --- a/src/test/java/kitchenpos/menus/application/MenuServiceTest.java +++ b/src/test/java/kitchenpos/menus/application/MenuServiceTest.java @@ -1,14 +1,19 @@ package kitchenpos.menus.application; import kitchenpos.common.domain.Purgomalum; -import kitchenpos.menus.domain.Menu; -import kitchenpos.menus.domain.MenuGroupRepository; -import kitchenpos.menus.domain.MenuProduct; -import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.common.exception.KitchenPosException; import kitchenpos.common.infra.FakePurgomalum; -import kitchenpos.products.application.InMemoryProductRepository; +import kitchenpos.menus.domain.MenuGroupRepository; +import kitchenpos.menus.dto.ChangePriceMenuRequest; +import kitchenpos.menus.dto.CreateMenuProductRequest; +import kitchenpos.menus.dto.CreateMenuRequest; +import kitchenpos.menus.dto.MenuDto; +import kitchenpos.menus.infra.InMemoryMenuGroupRepository; +import kitchenpos.menus.infra.InMemoryMenuRepository; +import kitchenpos.products.application.ProductValidator; import kitchenpos.products.domain.Product; import kitchenpos.products.domain.ProductRepository; +import kitchenpos.products.infra.InMemoryProductRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -19,15 +24,25 @@ import org.junit.jupiter.params.provider.ValueSource; import java.math.BigDecimal; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.UUID; import static kitchenpos.Fixtures.*; +import static kitchenpos.common.exception.KitchenPosExceptionType.BAD_REQUEST; +import static kitchenpos.common.exception.KitchenPosExceptionType.NOT_FOUND; +import static kitchenpos.util.KitchenPostExceptionAssertionUtils.assertThrows; 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.assertTrue; class MenuServiceTest { - private MenuRepository menuRepository; + private ProductValidator productValidator; + private MenuValidator menuValidator; + private MenuProductService menuProductService; + private InMemoryMenuRepository toBeMenuRepository; private MenuGroupRepository menuGroupRepository; private ProductRepository productRepository; private Purgomalum purgomalum; @@ -37,11 +52,17 @@ class MenuServiceTest { @BeforeEach void setUp() { - menuRepository = new InMemoryMenuRepository(); + toBeMenuRepository = new InMemoryMenuRepository(); menuGroupRepository = new InMemoryMenuGroupRepository(); productRepository = new InMemoryProductRepository(); purgomalum = FakePurgomalum.create(); - menuService = new MenuService(menuRepository, menuGroupRepository, productRepository, purgomalum); + productValidator = new ProductValidator(productRepository); + menuValidator = new MenuValidator(productRepository); + menuProductService = new MenuProductService(productValidator); + menuService = new MenuService( + menuValidator, productValidator, menuProductService, + toBeMenuRepository, menuGroupRepository, purgomalum + ); menuGroupId = menuGroupRepository.save(menuGroup()).getId(); product = productRepository.save(product("후라이드", 16_000L)); } @@ -49,16 +70,16 @@ void setUp() { @DisplayName("1개 이상의 등록된 상품으로 메뉴를 등록할 수 있다.") @Test void create() { - final Menu expected = createMenuRequest( - "후라이드+후라이드", 19_000L, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) + final CreateMenuRequest expected = createMenuRequest( + "후라이드+후라이드", 19_000L, menuGroupId, true, createToBeMenuProductRequest(product.getId(), 2L) ); - final Menu actual = menuService.create(expected); + final MenuDto actual = menuService.create(expected); assertThat(actual).isNotNull(); assertAll( () -> assertThat(actual.getId()).isNotNull(), - () -> assertThat(actual.getName()).isEqualTo(expected.getName()), - () -> assertThat(actual.getPrice()).isEqualTo(expected.getPrice()), - () -> assertThat(actual.getMenuGroup().getId()).isEqualTo(expected.getMenuGroupId()), + () -> assertTrue(actual.getName().equalValue(expected.getName())), + () -> assertTrue(actual.getPrice().equalValue(expected.getPrice())), + () -> assertThat(actual.getMenuGroupId()).isEqualTo(expected.getMenuGroupId()), () -> assertThat(actual.isDisplayed()).isEqualTo(expected.isDisplayed()), () -> assertThat(actual.getMenuProducts()).hasSize(1) ); @@ -67,28 +88,27 @@ void create() { @DisplayName("상품이 없으면 등록할 수 없다.") @MethodSource("menuProducts") @ParameterizedTest - void create(final List menuProducts) { - final Menu expected = createMenuRequest("후라이드+후라이드", 19_000L, menuGroupId, true, menuProducts); + void create(final List menuProducts) { + final CreateMenuRequest expected = createMenuRequest("후라이드+후라이드", 19_000L, menuGroupId, true, menuProducts); assertThatThrownBy(() -> menuService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(KitchenPosException.class); } private static List menuProducts() { return Arrays.asList( null, Arguments.of(Collections.emptyList()), - Arguments.of(Arrays.asList(createMenuProductRequest(INVALID_ID, 2L))) + Arguments.of(Arrays.asList(createToBeMenuProductRequest(INVALID_ID, 2L))) ); } @DisplayName("메뉴에 속한 상품의 수량은 0개 이상이어야 한다.") @Test void createNegativeQuantity() { - final Menu expected = createMenuRequest( - "후라이드+후라이드", 19_000L, menuGroupId, true, createMenuProductRequest(product.getId(), -1L) + final CreateMenuRequest expected = createMenuRequest( + "후라이드+후라이드", 19_000L, menuGroupId, true, createToBeMenuProductRequest(product.getId(), -1L) ); - assertThatThrownBy(() -> menuService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + assertThrows(BAD_REQUEST, () -> menuService.create(expected)); } @DisplayName("메뉴의 가격이 올바르지 않으면 등록할 수 없다.") @@ -96,32 +116,29 @@ void createNegativeQuantity() { @NullSource @ParameterizedTest void create(final BigDecimal price) { - final Menu expected = createMenuRequest( - "후라이드+후라이드", price, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) + final CreateMenuRequest expected = createMenuRequest( + "후라이드+후라이드", price, menuGroupId, true, createToBeMenuProductRequest(product.getId(), 2L) ); - assertThatThrownBy(() -> menuService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + assertThrows(BAD_REQUEST, () -> menuService.create(expected)); } @DisplayName("메뉴에 속한 상품 금액의 합은 메뉴의 가격보다 크거나 같아야 한다.") @Test void createExpensiveMenu() { - final Menu expected = createMenuRequest( - "후라이드+후라이드", 33_000L, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) + final CreateMenuRequest expected = createMenuRequest( + "후라이드+후라이드", 33_000L, menuGroupId, true, createToBeMenuProductRequest(product.getId(), 2L) ); - assertThatThrownBy(() -> menuService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + assertThrows(BAD_REQUEST, () -> menuService.create(expected)); } @DisplayName("메뉴는 특정 메뉴 그룹에 속해야 한다.") @NullSource @ParameterizedTest void create(final UUID menuGroupId) { - final Menu expected = createMenuRequest( - "후라이드+후라이드", 19_000L, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) + final CreateMenuRequest expected = createMenuRequest( + "후라이드+후라이드", 19_000L, menuGroupId, true, createToBeMenuProductRequest(product.getId(), 2L) ); - assertThatThrownBy(() -> menuService.create(expected)) - .isInstanceOf(NoSuchElementException.class); + assertThrows(NOT_FOUND, () -> menuService.create(expected)); } @DisplayName("메뉴의 이름이 올바르지 않으면 등록할 수 없다.") @@ -129,20 +146,20 @@ void create(final UUID menuGroupId) { @NullSource @ParameterizedTest void create(final String name) { - final Menu expected = createMenuRequest( - name, 19_000L, menuGroupId, true, createMenuProductRequest(product.getId(), 2L) + final CreateMenuRequest expected = createMenuRequest( + name, 19_000L, menuGroupId, true, createToBeMenuProductRequest(product.getId(), 2L) ); - assertThatThrownBy(() -> menuService.create(expected)) - .isInstanceOf(IllegalArgumentException.class); + + assertThrows(BAD_REQUEST, () -> menuService.create(expected)); } @DisplayName("메뉴의 가격을 변경할 수 있다.") @Test void changePrice() { - final UUID menuId = menuRepository.save(menu(19_000L, menuProduct(product, 2L))).getId(); - final Menu expected = changePriceRequest(16_000L); - final Menu actual = menuService.changePrice(menuId, expected); - assertThat(actual.getPrice()).isEqualTo(expected.getPrice()); + final UUID menuId = toBeMenuRepository.save(menu(19_000L, menuProduct(product, 2L))).getId(); + final ChangePriceMenuRequest request = changePriceRequest(16_000L); + final MenuDto actual = menuService.changePrice(menuId, request); + assertTrue(actual.getPrice().equalValue(request.getPrice())); } @DisplayName("메뉴의 가격이 올바르지 않으면 변경할 수 없다.") @@ -150,113 +167,101 @@ void changePrice() { @NullSource @ParameterizedTest void changePrice(final BigDecimal price) { - final UUID menuId = menuRepository.save(menu(19_000L, menuProduct(product, 2L))).getId(); - final Menu expected = changePriceRequest(price); - assertThatThrownBy(() -> menuService.changePrice(menuId, expected)) - .isInstanceOf(IllegalArgumentException.class); + final UUID menuId = toBeMenuRepository.save(menu(19_000L, menuProduct(product, 2L))).getId(); + final ChangePriceMenuRequest request = changePriceRequest(price); + assertThrows(BAD_REQUEST, () -> menuService.changePrice(menuId, request)); } @DisplayName("메뉴에 속한 상품 금액의 합은 메뉴의 가격보다 크거나 같아야 한다.") @Test void changePriceToExpensive() { - final UUID menuId = menuRepository.save(menu(19_000L, menuProduct(product, 2L))).getId(); - final Menu expected = changePriceRequest(33_000L); - assertThatThrownBy(() -> menuService.changePrice(menuId, expected)) - .isInstanceOf(IllegalArgumentException.class); + final UUID menuId = toBeMenuRepository.save(menu(19_000L, menuProduct(product, 2L))).getId(); + final ChangePriceMenuRequest request = changePriceRequest(33_000L); + assertThrows(BAD_REQUEST, () -> menuService.changePrice(menuId, request)); } @DisplayName("메뉴를 노출할 수 있다.") @Test void display() { - final UUID menuId = menuRepository.save(menu(19_000L, false, menuProduct(product, 2L))).getId(); - final Menu actual = menuService.display(menuId); + final UUID menuId = toBeMenuRepository.save(menu(19_000L, false, menuProduct(product, 2L))).getId(); + final MenuDto actual = menuService.display(menuId); assertThat(actual.isDisplayed()).isTrue(); } @DisplayName("메뉴의 가격이 메뉴에 속한 상품 금액의 합보다 높을 경우 메뉴를 노출할 수 없다.") @Test void displayExpensiveMenu() { - final UUID menuId = menuRepository.save(menu(33_000L, false, menuProduct(product, 2L))).getId(); - assertThatThrownBy(() -> menuService.display(menuId)) - .isInstanceOf(IllegalStateException.class); + final UUID menuId = toBeMenuRepository.save(menu(33_000L, false, menuProduct(product, 2L))).getId(); + assertThrows(BAD_REQUEST, () -> menuService.display(menuId)); } @DisplayName("메뉴를 숨길 수 있다.") @Test void hide() { - final UUID menuId = menuRepository.save(menu(19_000L, true, menuProduct(product, 2L))).getId(); - final Menu actual = menuService.hide(menuId); + final UUID menuId = toBeMenuRepository.save(menu(19_000L, true, menuProduct(product, 2L))).getId(); + final MenuDto actual = menuService.hide(menuId); assertThat(actual.isDisplayed()).isFalse(); } @DisplayName("메뉴의 목록을 조회할 수 있다.") @Test void findAll() { - menuRepository.save(menu(19_000L, true, menuProduct(product, 2L))); - final List actual = menuService.findAll(); + toBeMenuRepository.save(menu(19_000L, true, menuProduct(product, 2L))); + final List actual = menuService.findAll(); assertThat(actual).hasSize(1); } - private Menu createMenuRequest( + private CreateMenuRequest createMenuRequest( final String name, final long price, final UUID menuGroupId, final boolean displayed, - final MenuProduct... menuProducts + final CreateMenuProductRequest... menuProducts ) { return createMenuRequest(name, BigDecimal.valueOf(price), menuGroupId, displayed, menuProducts); } - private Menu createMenuRequest( + private CreateMenuRequest createMenuRequest( final String name, final BigDecimal price, final UUID menuGroupId, final boolean displayed, - final MenuProduct... menuProducts + final CreateMenuProductRequest... menuProducts ) { return createMenuRequest(name, price, menuGroupId, displayed, Arrays.asList(menuProducts)); } - private Menu createMenuRequest( + private CreateMenuRequest createMenuRequest( final String name, final long price, final UUID menuGroupId, final boolean displayed, - final List menuProducts + final List menuProducts ) { return createMenuRequest(name, BigDecimal.valueOf(price), menuGroupId, displayed, menuProducts); } - private Menu createMenuRequest( + private CreateMenuRequest createMenuRequest( final String name, final BigDecimal price, final UUID menuGroupId, final boolean displayed, - final List menuProducts + final List menuProducts ) { - final Menu menu = new Menu(); - menu.setName(name); - menu.setPrice(price); - menu.setMenuGroupId(menuGroupId); - menu.setDisplayed(displayed); - menu.setMenuProducts(menuProducts); - return menu; + return new CreateMenuRequest( + name, price, menuGroupId, displayed, menuProducts + ); } - private static MenuProduct createMenuProductRequest(final UUID productId, final long quantity) { - final MenuProduct menuProduct = new MenuProduct(); - menuProduct.setProductId(productId); - menuProduct.setQuantity(quantity); - return menuProduct; + private static CreateMenuProductRequest createToBeMenuProductRequest(final UUID productId, final long quantity) { + return new CreateMenuProductRequest(productId, quantity); } - private Menu changePriceRequest(final long price) { + private ChangePriceMenuRequest changePriceRequest(final long price) { return changePriceRequest(BigDecimal.valueOf(price)); } - private Menu changePriceRequest(final BigDecimal price) { - final Menu menu = new Menu(); - menu.setPrice(price); - return menu; + private ChangePriceMenuRequest changePriceRequest(final BigDecimal price) { + return new ChangePriceMenuRequest(price); } } diff --git a/src/test/java/kitchenpos/menus/application/ProductPriceChangeListenerTest.java b/src/test/java/kitchenpos/menus/application/ProductPriceChangeListenerTest.java index 68952909b..d2677155f 100644 --- a/src/test/java/kitchenpos/menus/application/ProductPriceChangeListenerTest.java +++ b/src/test/java/kitchenpos/menus/application/ProductPriceChangeListenerTest.java @@ -2,27 +2,30 @@ import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuRepository; -import kitchenpos.products.application.InMemoryProductRepository; -import kitchenpos.products.event.ProductPriceChangeEvent; +import kitchenpos.menus.infra.InMemoryMenuRepository; import kitchenpos.products.domain.Product; +import kitchenpos.products.domain.ProductPriceChangeEvent; import kitchenpos.products.domain.ProductRepository; +import kitchenpos.products.infra.InMemoryProductRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static kitchenpos.Fixtures.*; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertFalse; class ProductPriceChangeListenerTest { private ProductRepository productRepository; private MenuRepository menuRepository; + private MenuValidator menuValidator; private ProductPriceChangeListener productPriceChangeListener; @BeforeEach void setUp() { productRepository = new InMemoryProductRepository(); menuRepository = new InMemoryMenuRepository(); - productPriceChangeListener = new ProductPriceChangeListener(menuRepository); + menuValidator = new MenuValidator(productRepository); + productPriceChangeListener = new ProductPriceChangeListener(menuValidator, menuRepository); } @Test diff --git a/src/test/java/kitchenpos/menus/application/InMemoryMenuGroupRepository.java b/src/test/java/kitchenpos/menus/infra/InMemoryMenuGroupRepository.java similarity index 94% rename from src/test/java/kitchenpos/menus/application/InMemoryMenuGroupRepository.java rename to src/test/java/kitchenpos/menus/infra/InMemoryMenuGroupRepository.java index 9b50d73bb..d726e79eb 100644 --- a/src/test/java/kitchenpos/menus/application/InMemoryMenuGroupRepository.java +++ b/src/test/java/kitchenpos/menus/infra/InMemoryMenuGroupRepository.java @@ -1,4 +1,4 @@ -package kitchenpos.menus.application; +package kitchenpos.menus.infra; import kitchenpos.menus.domain.MenuGroup; import kitchenpos.menus.domain.MenuGroupRepository; diff --git a/src/test/java/kitchenpos/menus/application/InMemoryMenuRepository.java b/src/test/java/kitchenpos/menus/infra/InMemoryMenuRepository.java similarity index 90% rename from src/test/java/kitchenpos/menus/application/InMemoryMenuRepository.java rename to src/test/java/kitchenpos/menus/infra/InMemoryMenuRepository.java index 971ded7e3..902ae7c35 100644 --- a/src/test/java/kitchenpos/menus/application/InMemoryMenuRepository.java +++ b/src/test/java/kitchenpos/menus/infra/InMemoryMenuRepository.java @@ -1,4 +1,4 @@ -package kitchenpos.menus.application; +package kitchenpos.menus.infra; import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuRepository; @@ -37,7 +37,7 @@ public List findAllByIdIn(final List ids) { public List findAllByProductId(final UUID productId) { return menus.values() .stream() - .filter(menu -> menu.getMenuProducts().stream().anyMatch(menuProduct -> menuProduct.getProduct().getId().equals(productId))) + .filter(menu -> menu.getMenuProducts().stream().anyMatch(menuProduct -> menuProduct.getProductId().equals(productId))) .collect(Collectors.toList()); } } diff --git a/src/test/java/kitchenpos/products/application/ProductServiceIntegrationTest.java b/src/test/java/kitchenpos/products/application/ProductServiceIntegrationTest.java new file mode 100644 index 000000000..09d135861 --- /dev/null +++ b/src/test/java/kitchenpos/products/application/ProductServiceIntegrationTest.java @@ -0,0 +1,58 @@ +package kitchenpos.products.application; + +import kitchenpos.IntegrationTest; +import kitchenpos.common.exception.KitchenPosExceptionType; +import kitchenpos.products.domain.ProductPriceChangeEvent; +import kitchenpos.products.domain.ProductRepository; +import kitchenpos.products.dto.ChangePriceRequest; +import kitchenpos.products.dto.ProductDto; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.test.context.event.ApplicationEvents; + +import java.math.BigDecimal; +import java.util.UUID; + +import static kitchenpos.Fixtures.product; +import static kitchenpos.util.KitchenPostExceptionAssertionUtils.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ProductServiceIntegrationTest extends IntegrationTest { + + private final ProductService productService; + private final ProductRepository productRepository; + + public ProductServiceIntegrationTest(ProductService productService, + ProductRepository productRepository) { + this.productService = productService; + this.productRepository = productRepository; + } + + @DisplayName("가격 변경시 상품의 가격 변경 이벤트가 발행되어야 한다.") + @Test + void changePrice_success() { + final UUID productId = productRepository.save(product("후라이드", 16_000L)).getId(); + final ChangePriceRequest request = new ChangePriceRequest(BigDecimal.valueOf(15_000L)); + final ProductDto actual = productService.changePrice(productId, request); + assertTrue(actual.getPrice().equalValue(request.getPrice())); + + var event = applicationEvents.stream(ProductPriceChangeEvent.class) + .filter(e -> e.getProductId().equals(productId)) + .findFirst(); + assertTrue(event.isPresent()); + } + + @DisplayName("가격 변경 중 실패시 상품의 가격 변경 이벤트가 발행되어선 안된다.") + @Test + void changePrice_fail() { + final UUID productId = productRepository.save(product("후라이드", 16_000L)).getId(); + final ChangePriceRequest expected = new ChangePriceRequest(BigDecimal.valueOf(-1000L)); + assertThrows(KitchenPosExceptionType.BAD_REQUEST, () -> productService.changePrice(productId, expected)); + + var event = applicationEvents.stream(ProductPriceChangeEvent.class) + .filter(e -> e.getProductId().equals(productId)) + .findFirst(); + assertTrue(event.isEmpty()); + } + +} diff --git a/src/test/java/kitchenpos/products/application/ProductServiceTest.java b/src/test/java/kitchenpos/products/application/ProductServiceTest.java index 09b91520e..068415178 100644 --- a/src/test/java/kitchenpos/products/application/ProductServiceTest.java +++ b/src/test/java/kitchenpos/products/application/ProductServiceTest.java @@ -2,21 +2,22 @@ import kitchenpos.common.domain.Purgomalum; import kitchenpos.common.exception.KitchenPosExceptionType; +import kitchenpos.common.infra.FakeApplicationEventPublisher; import kitchenpos.common.infra.FakePurgomalum; -import kitchenpos.menus.application.InMemoryMenuRepository; -import kitchenpos.menus.domain.MenuRepository; -import kitchenpos.products.dto.ChangePriceRequest; -import kitchenpos.products.dto.CreateReqeust; -import kitchenpos.products.dto.ProductDto; -import kitchenpos.products.event.ProductPriceChangeEvent; import kitchenpos.products.domain.Product; +import kitchenpos.products.domain.ProductPriceChangeEvent; import kitchenpos.products.domain.ProductRepository; +import kitchenpos.products.dto.ChangePriceRequest; +import kitchenpos.products.dto.CreateRequest; +import kitchenpos.products.dto.ProductDto; +import kitchenpos.products.infra.InMemoryProductRepository; 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.NullSource; import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.test.context.event.RecordApplicationEvents; import java.math.BigDecimal; import java.util.List; @@ -31,24 +32,22 @@ class ProductServiceTest { private ProductRepository productRepository; - private MenuRepository menuRepository; - private Purgomalum purgomalumClient; + private Purgomalum purgomalum; private ProductService productService; private FakeApplicationEventPublisher publisher; @BeforeEach void setUp() { productRepository = new InMemoryProductRepository(); - menuRepository = new InMemoryMenuRepository(); - purgomalumClient = FakePurgomalum.create(); + purgomalum = FakePurgomalum.create(); publisher = new FakeApplicationEventPublisher(); - productService = new ProductService(productRepository, purgomalumClient, publisher); + productService = new ProductService(productRepository, purgomalum, publisher); } @DisplayName("상품을 등록할 수 있다.") @Test void create() { - final CreateReqeust request = createProductRequest("후라이드", 16_000L); + final CreateRequest request = createProductRequest("후라이드", 16_000L); final ProductDto actual = productService.create(request); assertThat(actual).isNotNull(); assertAll( @@ -63,7 +62,7 @@ void create() { @NullSource @ParameterizedTest void create(final BigDecimal price) { - final CreateReqeust request = createProductRequest("후라이드", price); + final CreateRequest request = createProductRequest("후라이드", price); assertThrows(KitchenPosExceptionType.BAD_REQUEST, () -> productService.create(request)); } @@ -72,7 +71,7 @@ void create(final BigDecimal price) { @NullSource @ParameterizedTest void create(final String name) { - final CreateReqeust request = createProductRequest(name, 16_000L); + final CreateRequest request = createProductRequest(name, 16_000L); assertThrows(KitchenPosExceptionType.BAD_REQUEST, () -> productService.create(request)); } @@ -100,7 +99,7 @@ void changePrice(final BigDecimal price) { void changePriceInMenu() { final Product product = productRepository.save(product("후라이드", 16_000L)); productService.changePrice(product.getId(), changePriceRequest(8_000L)); - ProductPriceChangeEvent event = (ProductPriceChangeEvent) publisher.pop(); + ProductPriceChangeEvent event = (ProductPriceChangeEvent) product.domainEvents().get(0); assertThat(event.getProductId()).isEqualTo(product.getId()); } @@ -113,12 +112,12 @@ void findAll() { assertThat(actual).hasSize(2); } - private CreateReqeust createProductRequest(final String name, final long price) { + private CreateRequest createProductRequest(final String name, final long price) { return createProductRequest(name, BigDecimal.valueOf(price)); } - private CreateReqeust createProductRequest(final String name, final BigDecimal price) { - return new CreateReqeust(name, price); + private CreateRequest createProductRequest(final String name, final BigDecimal price) { + return new CreateRequest(name, price); } private ChangePriceRequest changePriceRequest(final long price) { diff --git a/src/test/java/kitchenpos/products/application/InMemoryProductRepository.java b/src/test/java/kitchenpos/products/infra/InMemoryProductRepository.java similarity index 95% rename from src/test/java/kitchenpos/products/application/InMemoryProductRepository.java rename to src/test/java/kitchenpos/products/infra/InMemoryProductRepository.java index 2fd78e96d..f228793b2 100644 --- a/src/test/java/kitchenpos/products/application/InMemoryProductRepository.java +++ b/src/test/java/kitchenpos/products/infra/InMemoryProductRepository.java @@ -1,4 +1,4 @@ -package kitchenpos.products.application; +package kitchenpos.products.infra; import kitchenpos.products.domain.Product; import kitchenpos.products.domain.ProductRepository; diff --git a/src/test/java/kitchenpos/util/KitchenPostExceptionAssertionUtils.java b/src/test/java/kitchenpos/util/KitchenPostExceptionAssertionUtils.java index 8e7e3171c..e8481606d 100644 --- a/src/test/java/kitchenpos/util/KitchenPostExceptionAssertionUtils.java +++ b/src/test/java/kitchenpos/util/KitchenPostExceptionAssertionUtils.java @@ -3,7 +3,6 @@ import kitchenpos.common.exception.KitchenPosException; import kitchenpos.common.exception.KitchenPosExceptionType; import org.junit.jupiter.api.Assertions; - import org.junit.jupiter.api.function.Executable; import static org.junit.jupiter.api.Assertions.assertTrue;