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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package kitchenpos.menus.tobe.application;

import kitchenpos.menus.tobe.domain.MenuGroup;
import kitchenpos.menus.tobe.domain.MenuGroupName;
import kitchenpos.menus.tobe.domain.MenuGroupRepository;
import kitchenpos.menus.tobe.ui.MenuGroupCreateRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.UUID;

@Service("tobeMenuGroupService")
public class MenuGroupService {
private final MenuGroupRepository menuGroupRepository;

public MenuGroupService(final MenuGroupRepository menuGroupRepository) {
this.menuGroupRepository = menuGroupRepository;
}

@Transactional
public MenuGroup create(final MenuGroupCreateRequest request) {
final MenuGroupName name = new MenuGroupName(request.name());
final MenuGroup menuGroup = new MenuGroup(UUID.randomUUID(), name);
return menuGroupRepository.save(menuGroup);
}

@Transactional(readOnly = true)
public List<MenuGroup> findAll() {
return menuGroupRepository.findAll();
}

@Transactional(readOnly = true)
public MenuGroup findById(UUID menuGroupId) {
return menuGroupRepository.findById(menuGroupId)
.orElseThrow(NoSuchElementException::new);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package kitchenpos.menus.tobe.application;

import kitchenpos.menus.tobe.domain.MenuProduct;
import kitchenpos.menus.tobe.domain.MenuProductQuantity;
import kitchenpos.menus.tobe.infra.ProductResponse;
import kitchenpos.menus.tobe.infra.ProductResponses;
import kitchenpos.menus.tobe.ui.MenuProductRequest;

import java.util.ArrayList;
import java.util.List;

public class MenuProductCreator {

private MenuProductCreator() {
throw new AssertionError();
}

public static List<MenuProduct> create(List<MenuProductRequest> menuProductRequests, ProductResponses productResponses) {
final List<MenuProduct> menuProducts = new ArrayList<>();
for (MenuProductRequest menuProductRequest : menuProductRequests) {
final MenuProductQuantity quantity = new MenuProductQuantity(menuProductRequest.quantity());
final ProductResponse productResponse = productResponses.findById(menuProductRequest.productId());
menuProducts.add(new MenuProduct(productResponse.id(), quantity));
}
return menuProducts;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package kitchenpos.menus.tobe.application;

import kitchenpos.menus.tobe.domain.MenuPrice;
import kitchenpos.menus.tobe.domain.MenuProduct;
import kitchenpos.menus.tobe.domain.MenuProducts;
import kitchenpos.menus.tobe.infra.ProductClient;
import kitchenpos.menus.tobe.infra.ProductResponses;
import kitchenpos.menus.tobe.ui.MenuProductRequest;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;

@Service
public class MenuProductService {

private final ProductClient productClient;

public MenuProductService(ProductClient productClient) {
this.productClient = productClient;
}

public List<MenuProduct> getMenuProducts(MenuPrice price, List<MenuProductRequest> menuProductRequests, List<UUID> productIds) {
MenuValidator.validateMenuProductRequests(menuProductRequests);
final ProductResponses productResponses = productClient.listByIds(productIds);
MenuValidator.validateProductResponses(productResponses, productIds);
MenuValidator.validateMenuPriceWithRequests(price, productResponses, menuProductRequests);
return MenuProductCreator.create(menuProductRequests, productResponses);
}

public void checkMenuProductPrice(final MenuProducts menuProducts, final MenuPrice price) {
List<UUID> productIds = menuProducts.getProductIds();
final ProductResponses productResponses = productClient.listByIds(productIds);
MenuValidator.validateMenuPrice(price, productResponses, menuProducts);
}
}
75 changes: 75 additions & 0 deletions src/main/java/kitchenpos/menus/tobe/application/MenuService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package kitchenpos.menus.tobe.application;

import kitchenpos.menus.tobe.domain.*;
import kitchenpos.menus.tobe.ui.MenuCreateRequest;
import kitchenpos.menus.tobe.ui.MenuPriceChangeRequest;
import kitchenpos.products.infra.PurgomalumClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.UUID;

@Service("tobeMenuService")
public class MenuService {

private final MenuRepository menuRepository;
private final MenuGroupService menuGroupService;
private final PurgomalumClient purgomalumClient;
private final MenuProductService menuProductService;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Application Service ๊ฐ„์˜ ๊ฒฐํ•ฉ์ด ๋ฐœ์ƒํ•˜๋ฉด ์–ด๋–ค ๋ฌธ์ œ์ ์ด ์žˆ์„๊นŒ์š” ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ œ๊ฐ€ ์ƒ๊ฐํ•˜๋Š” Application Service ๊ฐ„์˜ ๊ฒฐํ•ฉ์ด ๋ฐœ์ƒํ•  ๋•Œ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์ˆœํ™˜ ์ฐธ์กฐ์™€ ๋ณต์žก์„ฑ ์ฆ๊ฐ€๊ฐ€ ์ฃผ์š” ์ด์Šˆ์ž…๋‹ˆ๋‹ค.
  2. ํ•˜์ง€๋งŒ ์ €๋Š” MenuGroup์ด Menu์˜ ์ˆœํ•˜์œ„ ๋„๋ฉ”์ธ์ด๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ ํฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.
  3. ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์„œ๋น„์Šค ๊ฐ„ ์ฑ…์ž„์„ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด Facade ํŒจํ„ด์„ ์ ์šฉํ•˜์—ฌ ์„œ๋น„์Šค์˜ ์—ญํ• ์„ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.


public MenuService(
final MenuRepository menuRepository,
final MenuGroupService menuGroupService,
final PurgomalumClient purgomalumClient,
final MenuProductService menuProductService
) {
this.menuRepository = menuRepository;
this.menuGroupService = menuGroupService;
this.purgomalumClient = purgomalumClient;
this.menuProductService = menuProductService;
}

@Transactional
public Menu create(final MenuCreateRequest request) {
final MenuPrice price = new MenuPrice(request.price());
final MenuGroup menuGroup = menuGroupService.findById(request.menuGroupId());
final List<MenuProduct> menuProducts = menuProductService.getMenuProducts(price, request.menuProducts(), request.productIds());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

menuProductService ๋ฅผ ํ†ตํ•˜์—ฌ menuproduct ๋ฅผ ๊ฐ€์ง€๊ณ  ์˜จ ์ด์œ ๊ฐ€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค !

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Menu Context ์ž์ฒด์—์„œ๋Š” Product๋ฅผ ์ง์ ‘ ์ฐธ์กฐํ•˜์ง€ ์•Š์ง€๋งŒ Product ์ •๋ณด๋ฅผ ํ™•์ธํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ํ•˜์œ„ ๋„๋ฉ”์ธ์ธ MenuProduct์—์„œ Product๋ฅผ ์กฐํšŒํ•˜๋„๋ก ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

final MenuName name = new MenuName(request.name(), purgomalumClient::containsProfanity);
final Menu menu = new Menu(UUID.randomUUID(), name, price, menuGroup, request.displayed(), menuProducts);
return menuRepository.save(menu);
}

@Transactional
public Menu changePrice(final UUID menuId, final MenuPriceChangeRequest request) {
final MenuPrice price = new MenuPrice(request.price());
final Menu menu = menuRepository.findById(menuId)
.orElseThrow(NoSuchElementException::new);
menuProductService.checkMenuProductPrice(menu.getMenuProducts(), price);
menu.changePrice(price);
return menu;
}

@Transactional
public Menu display(final UUID menuId) {
final Menu menu = menuRepository.findById(menuId)
.orElseThrow(NoSuchElementException::new);
menuProductService.checkMenuProductPrice(menu.getMenuProducts(), menu.getPrice());
menu.display();
return menu;
}

@Transactional
public Menu hide(final UUID menuId) {
final Menu menu = menuRepository.findById(menuId)
.orElseThrow(NoSuchElementException::new);
menu.hide();
return menu;
}

@Transactional(readOnly = true)
public List<Menu> findAll() {
return menuRepository.findAll();
}
}
43 changes: 43 additions & 0 deletions src/main/java/kitchenpos/menus/tobe/application/MenuValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package kitchenpos.menus.tobe.application;

import kitchenpos.menus.tobe.domain.MenuPrice;
import kitchenpos.menus.tobe.domain.MenuProducts;
import kitchenpos.menus.tobe.infra.ProductResponses;
import kitchenpos.menus.tobe.ui.MenuProductRequest;

import java.util.List;
import java.util.Objects;
import java.util.UUID;

public class MenuValidator {

private MenuValidator() {
throw new AssertionError();
}

public static void validateMenuPriceWithRequests(MenuPrice price, ProductResponses productResponses, List<MenuProductRequest> menuProductRequests) {
var sum = productResponses.getSumsWithRequests(menuProductRequests);
if (price.isGreaterThan(sum)) {
throw new IllegalArgumentException();
}
}

public static void validateMenuPrice(MenuPrice price, ProductResponses productResponses, MenuProducts menuProducts) {
var sum = productResponses.getSums(menuProducts);
if (price.isGreaterThan(sum)) {
throw new IllegalArgumentException();
}
}

public static void validateProductResponses(ProductResponses productResponses, List<UUID> productIds) {
if (productResponses.size() != productIds.size()) {
throw new IllegalArgumentException();
}
}

public static void validateMenuProductRequests(List<MenuProductRequest> menuProductRequests) {
if (Objects.isNull(menuProductRequests) || menuProductRequests.isEmpty()) {
throw new IllegalArgumentException();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package kitchenpos.menus.tobe.domain;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.UUID;

@Repository("menuGroupToBeRepository")
public interface JpaMenuGroupRepository extends MenuGroupRepository, JpaRepository<MenuGroup, UUID> {
}
16 changes: 16 additions & 0 deletions src/main/java/kitchenpos/menus/tobe/domain/JpaMenuRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package kitchenpos.menus.tobe.domain;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.UUID;

@Repository("menuToBeRepository")
public interface JpaMenuRepository extends MenuRepository, JpaRepository<Menu, UUID> {
@Query("select m from Menu m join m.menuProducts mp where mp.product.id = :productId")
@Override
List<Menu> findAllByProductId(@Param("productId") UUID productId);
}
73 changes: 73 additions & 0 deletions src/main/java/kitchenpos/menus/tobe/domain/Menu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package kitchenpos.menus.tobe.domain;

import jakarta.persistence.*;

import java.util.List;
import java.util.UUID;

@Table(name = "menu")
@Entity(name = "tobeMenu")
public class Menu {
@Column(name = "id", columnDefinition = "binary(16)")
@Id
private UUID id;

@Embedded
private MenuName name;

@Embedded
private MenuPrice price;

@ManyToOne(optional = false)
@JoinColumn(
name = "menu_group_id",
columnDefinition = "binary(16)",
foreignKey = @ForeignKey(name = "fk_menu_to_menu_group")
)
private MenuGroup menuGroup;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MenuGroup์„ ์ง์ ‘ ์ฐธ์กฐ๋กœ ๊ตฌํ˜„ํ•ด์ฃผ์‹  ์ด์œ ๊ฐ€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜„

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ํ•œ Context์•ˆ์— ์กด์žฌํ•˜์—ฌ ๋งŒ์•ฝ์— Id๋กœ ์ฐธ์กฐํ•˜๋ฉด ์˜คํžˆ๋ ค ๋” ๋ณต์žกํ•œ ๊ตฌ์กฐ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์–ด์š”,


@Column(name = "displayed", nullable = false)
private boolean displayed;

@Embedded
private MenuProducts menuProducts;

@Transient
private UUID menuGroupId;

protected Menu() {
}

public Menu(UUID id, MenuName name, MenuPrice price, MenuGroup menuGroup, boolean displayed, List<MenuProduct> menuProducts) {
this.id = id;
this.name = name;
this.price = price;
this.menuGroup = menuGroup;
this.displayed = displayed;
this.menuProducts = new MenuProducts(menuProducts);
}

public UUID getId() {
return id;
}

public void changePrice(MenuPrice price) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ํ˜„์žฌ domain ๊ฐ์ฒด๊ฐ€ ๋ฉ”๋‰ด ๊ฐ€๊ฒฉ ๋ณ€๊ฒฝ์— ๋Œ€ํ•œ ์š”๊ตฌ์‚ฌํ•ญ์„ ํ•ญ์ƒ ๋งŒ์กฑํ• ์ˆ˜์žˆ์„๊นŒ์š” ?
domain ๊ฐ์ฒด๋งŒ์œผ๋กœ ๋ชจ๋“  ์š”๊ตฌ์‚ฌํ•ญ์„ ๋งŒ์กฑํ• ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•ด๋ณด์„ธ์š” ๐Ÿ˜„
๋‹ค๋ฅธ ํ–‰์œ„๋„ ํ™•์ธ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค !

this.price = price;
}

public MenuProducts getMenuProducts() {
return this.menuProducts;
}

public void display() {
this.displayed = true;
}

public void hide() {
this.displayed = false;
}

public MenuPrice getPrice() {
return price;
}
}
28 changes: 28 additions & 0 deletions src/main/java/kitchenpos/menus/tobe/domain/MenuGroup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package kitchenpos.menus.tobe.domain;

import jakarta.persistence.*;

import java.util.UUID;

@Table(name = "menu_group")
@Entity(name = "tobeMenuGroup")
public class MenuGroup {
@Column(name = "id", columnDefinition = "binary(16)")
@Id
private UUID id;

@Embedded
private MenuGroupName name;

protected MenuGroup() {
}

public MenuGroup(final UUID id, final MenuGroupName name) {
this.id = id;
this.name = name;
}

public UUID getId() {
return id;
}
}
25 changes: 25 additions & 0 deletions src/main/java/kitchenpos/menus/tobe/domain/MenuGroupName.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package kitchenpos.menus.tobe.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;

@Embeddable
public class MenuGroupName {

@Column(name = "name", nullable = false)
private String name;

protected MenuGroupName() {
}

public MenuGroupName(final String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("๋ฉ”๋‰ด ๊ทธ๋ฃน ์ด๋ฆ„์€ ํ•„์ˆ˜๋กœ ์ž…๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.");
}
this.name = name;
}

public String value() {
return name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package kitchenpos.menus.tobe.domain;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

public interface MenuGroupRepository {
MenuGroup save(MenuGroup menuGroup);

Optional<MenuGroup> findById(UUID id);

List<MenuGroup> findAll();
}
Loading