From c72779d9d46a0ead3a499aefb869d9f2dcb2c549 Mon Sep 17 00:00:00 2001 From: Shin seongsu Date: Mon, 25 Sep 2023 03:04:38 +0900 Subject: [PATCH 1/8] =?UTF-8?q?refactor:=20dto=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20name,=20price=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../menus/application/MenuService.java | 4 +- .../application/ProductMenuServiceImpl.java | 32 ++++++++ .../kitchenpos/menus/domain/MenuProduct.java | 2 +- .../products/application/ProductService.java | 81 ------------------- .../kitchenpos/products/domain/Product.java | 49 ----------- .../tobe/application/ProductMenuService.java | 7 ++ .../tobe/application/ProductService.java | 70 ++++++++++++++++ .../tobe/application/dto/ProductInfo.java | 29 +++++++ .../products/tobe/domain/Product.java | 45 +++++++++++ .../products/tobe/domain/ProductName.java | 37 +++++++++ .../products/tobe/domain/ProductPrice.java | 36 +++++++++ .../{ => tobe}/domain/ProductRepository.java | 4 +- .../infra}/JpaProductRepository.java | 4 +- .../products/ui/ProductRestController.java | 49 ++++++++--- .../ui/request/ProductChangeRequest.java | 26 ++++++ .../ui/request/ProductCreateRequest.java | 27 +++++++ .../ui/response/ProductChangeResponse.java | 28 +++++++ .../ui/response/ProductCreateResponse.java | 29 +++++++ src/test/java/kitchenpos/Fixtures.java | 2 +- .../menus/application/MenuServiceTest.java | 4 +- .../InMemoryProductRepository.java | 4 +- .../application/ProductServiceTest.java | 5 +- 22 files changed, 422 insertions(+), 152 deletions(-) create mode 100644 src/main/java/kitchenpos/menus/application/ProductMenuServiceImpl.java delete mode 100644 src/main/java/kitchenpos/products/application/ProductService.java delete mode 100644 src/main/java/kitchenpos/products/domain/Product.java create mode 100644 src/main/java/kitchenpos/products/tobe/application/ProductMenuService.java create mode 100644 src/main/java/kitchenpos/products/tobe/application/ProductService.java create mode 100644 src/main/java/kitchenpos/products/tobe/application/dto/ProductInfo.java create mode 100644 src/main/java/kitchenpos/products/tobe/domain/Product.java create mode 100644 src/main/java/kitchenpos/products/tobe/domain/ProductName.java create mode 100644 src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java rename src/main/java/kitchenpos/products/{ => tobe}/domain/ProductRepository.java (75%) rename src/main/java/kitchenpos/products/{domain => tobe/infra}/JpaProductRepository.java (56%) create mode 100644 src/main/java/kitchenpos/products/ui/request/ProductChangeRequest.java create mode 100644 src/main/java/kitchenpos/products/ui/request/ProductCreateRequest.java create mode 100644 src/main/java/kitchenpos/products/ui/response/ProductChangeResponse.java create mode 100644 src/main/java/kitchenpos/products/ui/response/ProductCreateResponse.java diff --git a/src/main/java/kitchenpos/menus/application/MenuService.java b/src/main/java/kitchenpos/menus/application/MenuService.java index abf913c11..d010bfc15 100644 --- a/src/main/java/kitchenpos/menus/application/MenuService.java +++ b/src/main/java/kitchenpos/menus/application/MenuService.java @@ -1,8 +1,8 @@ package kitchenpos.menus.application; import kitchenpos.menus.domain.*; -import kitchenpos.products.domain.Product; -import kitchenpos.products.domain.ProductRepository; +import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.tobe.domain.ProductRepository; import kitchenpos.products.infra.PurgomalumClient; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/kitchenpos/menus/application/ProductMenuServiceImpl.java b/src/main/java/kitchenpos/menus/application/ProductMenuServiceImpl.java new file mode 100644 index 000000000..b0c0f0cc6 --- /dev/null +++ b/src/main/java/kitchenpos/menus/application/ProductMenuServiceImpl.java @@ -0,0 +1,32 @@ +package kitchenpos.menus.application; + +import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.products.tobe.application.ProductMenuService; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.UUID; + +@Service +public class ProductMenuServiceImpl implements ProductMenuService { + + private final MenuRepository menuRepository; + + public ProductMenuServiceImpl(MenuRepository menuRepository) { + this.menuRepository = menuRepository; + } + + @Override + public void validMenuDisplay(final UUID productId) { + menuRepository.findAllByProductId(productId) + .forEach(menu -> { + BigDecimal sum = menu.getMenuProducts().stream() + .map(menuProduct -> menuProduct.getProduct().getPrice().getProductPrice().multiply(BigDecimal.valueOf(menuProduct.getQuantity()))) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + if (menu.getPrice().compareTo(sum) > 0) { + menu.setDisplayed(false); + } + }); + } +} diff --git a/src/main/java/kitchenpos/menus/domain/MenuProduct.java b/src/main/java/kitchenpos/menus/domain/MenuProduct.java index 2836096e6..276955c22 100644 --- a/src/main/java/kitchenpos/menus/domain/MenuProduct.java +++ b/src/main/java/kitchenpos/menus/domain/MenuProduct.java @@ -1,6 +1,6 @@ package kitchenpos.menus.domain; -import kitchenpos.products.domain.Product; +import kitchenpos.products.tobe.domain.Product; import javax.persistence.*; import java.util.UUID; diff --git a/src/main/java/kitchenpos/products/application/ProductService.java b/src/main/java/kitchenpos/products/application/ProductService.java deleted file mode 100644 index 20cf63996..000000000 --- a/src/main/java/kitchenpos/products/application/ProductService.java +++ /dev/null @@ -1,81 +0,0 @@ -package kitchenpos.products.application; - -import kitchenpos.menus.domain.Menu; -import kitchenpos.menus.domain.MenuProduct; -import kitchenpos.menus.domain.MenuRepository; -import kitchenpos.products.domain.Product; -import kitchenpos.products.domain.ProductRepository; -import kitchenpos.products.infra.PurgomalumClient; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.math.BigDecimal; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.UUID; - -@Service -public class ProductService { - private final ProductRepository productRepository; - private final MenuRepository menuRepository; - private final PurgomalumClient purgomalumClient; - - public ProductService( - final ProductRepository productRepository, - final MenuRepository menuRepository, - final PurgomalumClient purgomalumClient - ) { - this.productRepository = productRepository; - this.menuRepository = menuRepository; - this.purgomalumClient = purgomalumClient; - } - - @Transactional - public Product create(final Product request) { - final BigDecimal price = request.getPrice(); - if (Objects.isNull(price) || price.compareTo(BigDecimal.ZERO) < 0) { - throw new IllegalArgumentException(); - } - final String name = request.getName(); - if (Objects.isNull(name) || purgomalumClient.containsProfanity(name)) { - throw new IllegalArgumentException(); - } - final Product product = new Product(); - product.setId(UUID.randomUUID()); - product.setName(name); - product.setPrice(price); - return productRepository.save(product); - } - - @Transactional - public Product changePrice(final UUID productId, final Product request) { - final BigDecimal price = request.getPrice(); - if (Objects.isNull(price) || price.compareTo(BigDecimal.ZERO) < 0) { - throw new IllegalArgumentException(); - } - final Product product = productRepository.findById(productId) - .orElseThrow(NoSuchElementException::new); - product.setPrice(price); - final List menus = menuRepository.findAllByProductId(productId); - for (final Menu menu : menus) { - 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) { - menu.setDisplayed(false); - } - } - return product; - } - - @Transactional(readOnly = true) - public List findAll() { - return productRepository.findAll(); - } -} diff --git a/src/main/java/kitchenpos/products/domain/Product.java b/src/main/java/kitchenpos/products/domain/Product.java deleted file mode 100644 index 456864e20..000000000 --- a/src/main/java/kitchenpos/products/domain/Product.java +++ /dev/null @@ -1,49 +0,0 @@ -package kitchenpos.products.domain; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; -import java.math.BigDecimal; -import java.util.UUID; - -@Table(name = "product") -@Entity -public class Product { - @Column(name = "id", columnDefinition = "binary(16)") - @Id - private UUID id; - - @Column(name = "name", nullable = false) - private String name; - - @Column(name = "price", nullable = false) - private BigDecimal price; - - public Product() { - } - - public UUID getId() { - return id; - } - - public void setId(final UUID id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - public BigDecimal getPrice() { - return price; - } - - public void setPrice(final BigDecimal price) { - this.price = price; - } -} diff --git a/src/main/java/kitchenpos/products/tobe/application/ProductMenuService.java b/src/main/java/kitchenpos/products/tobe/application/ProductMenuService.java new file mode 100644 index 000000000..b2aad3029 --- /dev/null +++ b/src/main/java/kitchenpos/products/tobe/application/ProductMenuService.java @@ -0,0 +1,7 @@ +package kitchenpos.products.tobe.application; + +import java.util.UUID; + +public interface ProductMenuService { + void validMenuDisplay(final UUID productId); +} diff --git a/src/main/java/kitchenpos/products/tobe/application/ProductService.java b/src/main/java/kitchenpos/products/tobe/application/ProductService.java new file mode 100644 index 000000000..f45df8a32 --- /dev/null +++ b/src/main/java/kitchenpos/products/tobe/application/ProductService.java @@ -0,0 +1,70 @@ +package kitchenpos.products.tobe.application; + +import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.products.tobe.application.dto.ProductInfo; +import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.tobe.domain.ProductRepository; +import kitchenpos.products.infra.PurgomalumClient; +import kitchenpos.products.tobe.domain.ProductName; +import kitchenpos.products.tobe.domain.ProductPrice; +import kitchenpos.products.ui.request.ProductChangeRequest; +import kitchenpos.products.ui.request.ProductCreateRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; + +@Service +public class ProductService { + private final ProductRepository productRepository; + private final ProductMenuService productMenuService; + private final PurgomalumClient purgomalumClient; + + public ProductService( + final ProductRepository productRepository, + final ProductMenuService productMenuService, + final PurgomalumClient purgomalumClient + ) { + this.productRepository = productRepository; + this.productMenuService = productMenuService; + this.purgomalumClient = purgomalumClient; + } + + @Transactional + public ProductInfo create(final ProductCreateRequest request) { + final Product product = productRepository.save(new Product( + UUID.randomUUID(), + new ProductName(request.getName(), purgomalumClient), + new ProductPrice(request.getPrice()) + )); + + return new ProductInfo( + product.getId(), + product.getName().getProductName(), + product.getPrice().getProductPrice() + ); + } + + @Transactional + public ProductInfo changePrice(final UUID productId, final ProductChangeRequest request) { + final Product product = productRepository.findById(productId) + .orElseThrow(NoSuchElementException::new); + product.changePrice(new ProductPrice(request.getPrice())); + + productMenuService.validMenuDisplay(productId); + + return new ProductInfo( + product.getId(), + product.getName().getProductName(), + product.getPrice().getProductPrice() + ); + } + + @Transactional(readOnly = true) + public List findAll() { + return productRepository.findAll(); + } +} diff --git a/src/main/java/kitchenpos/products/tobe/application/dto/ProductInfo.java b/src/main/java/kitchenpos/products/tobe/application/dto/ProductInfo.java new file mode 100644 index 000000000..e53c4316d --- /dev/null +++ b/src/main/java/kitchenpos/products/tobe/application/dto/ProductInfo.java @@ -0,0 +1,29 @@ +package kitchenpos.products.tobe.application.dto; + +import java.math.BigDecimal; +import java.util.UUID; + +public class ProductInfo { + + private final UUID id; + private final String name; + private final BigDecimal price; + + public ProductInfo(UUID id, String name, BigDecimal price) { + this.id = id; + this.name = name; + this.price = price; + } + + public UUID getId() { + return id; + } + + public String getName() { + return name; + } + + public BigDecimal getPrice() { + return price; + } +} diff --git a/src/main/java/kitchenpos/products/tobe/domain/Product.java b/src/main/java/kitchenpos/products/tobe/domain/Product.java new file mode 100644 index 000000000..44362c45a --- /dev/null +++ b/src/main/java/kitchenpos/products/tobe/domain/Product.java @@ -0,0 +1,45 @@ +package kitchenpos.products.tobe.domain; + +import javax.persistence.*; +import java.math.BigDecimal; +import java.util.UUID; + +@Table(name = "product") +@Entity +public class Product { + + @Column(name = "id", columnDefinition = "binary(16)") + @Id + private UUID id; + + @Embedded + private ProductName name; + + @Embedded + private ProductPrice price; + + protected Product() { + } + + public Product(UUID id, ProductName name, ProductPrice price) { + this.id = id; + this.name = name; + this.price = price; + } + + public UUID getId() { + return id; + } + + public ProductName getName() { + return name; + } + + public ProductPrice getPrice() { + return price; + } + + public void changePrice(final ProductPrice price) { + this.price = price; + } +} diff --git a/src/main/java/kitchenpos/products/tobe/domain/ProductName.java b/src/main/java/kitchenpos/products/tobe/domain/ProductName.java new file mode 100644 index 000000000..d01f14421 --- /dev/null +++ b/src/main/java/kitchenpos/products/tobe/domain/ProductName.java @@ -0,0 +1,37 @@ +package kitchenpos.products.tobe.domain; + +import kitchenpos.products.infra.PurgomalumClient; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.util.Objects; + +@Embeddable +public class ProductName { + + @Column(name = "name", nullable = false) + private String productName; + + public ProductName(String productName, PurgomalumClient purgomalumClient) { + validateProductName(productName, purgomalumClient); + this.productName = productName; + } + + protected ProductName() { + + } + + public String getProductName() { + return productName; + } + + private void validateProductName(String productName, PurgomalumClient purgomalumClient) { + if (Objects.isNull(productName)) { + throw new IllegalArgumentException("상품 이름 값이 존재하지 않습니다."); + } + if (purgomalumClient.containsProfanity(productName)) { + throw new IllegalArgumentException("상품 이름에 비속어가 존재합니다. product Name : " + productName); + } + } + +} diff --git a/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java b/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java new file mode 100644 index 000000000..2420d6c55 --- /dev/null +++ b/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java @@ -0,0 +1,36 @@ +package kitchenpos.products.tobe.domain; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.math.BigDecimal; +import java.util.Objects; + +@Embeddable +public class ProductPrice { + + @Column(name = "price", nullable = false) + private BigDecimal productPrice; + + public ProductPrice(BigDecimal productPrice) { + validateProductPrice(productPrice); + this.productPrice = productPrice; + } + + protected ProductPrice() { + + } + + private void validateProductPrice(BigDecimal productPrice) { + if (Objects.isNull(productPrice)) { + throw new IllegalArgumentException("상풍 가격은 필수로 존재해야 합니다."); + } + if (productPrice.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalArgumentException("상품 가격은 0원 이상이어야 합니다."); + } + } + + public BigDecimal getProductPrice() { + return productPrice; + } + +} diff --git a/src/main/java/kitchenpos/products/domain/ProductRepository.java b/src/main/java/kitchenpos/products/tobe/domain/ProductRepository.java similarity index 75% rename from src/main/java/kitchenpos/products/domain/ProductRepository.java rename to src/main/java/kitchenpos/products/tobe/domain/ProductRepository.java index 3637e4232..7a14e4b36 100644 --- a/src/main/java/kitchenpos/products/domain/ProductRepository.java +++ b/src/main/java/kitchenpos/products/tobe/domain/ProductRepository.java @@ -1,4 +1,6 @@ -package kitchenpos.products.domain; +package kitchenpos.products.tobe.domain; + +import kitchenpos.products.tobe.domain.Product; import java.util.List; import java.util.Optional; diff --git a/src/main/java/kitchenpos/products/domain/JpaProductRepository.java b/src/main/java/kitchenpos/products/tobe/infra/JpaProductRepository.java similarity index 56% rename from src/main/java/kitchenpos/products/domain/JpaProductRepository.java rename to src/main/java/kitchenpos/products/tobe/infra/JpaProductRepository.java index 90b069779..4643ae94a 100644 --- a/src/main/java/kitchenpos/products/domain/JpaProductRepository.java +++ b/src/main/java/kitchenpos/products/tobe/infra/JpaProductRepository.java @@ -1,5 +1,7 @@ -package kitchenpos.products.domain; +package kitchenpos.products.tobe.infra; +import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.tobe.domain.ProductRepository; import org.springframework.data.jpa.repository.JpaRepository; import java.util.UUID; diff --git a/src/main/java/kitchenpos/products/ui/ProductRestController.java b/src/main/java/kitchenpos/products/ui/ProductRestController.java index 7dc532ec2..f400a7556 100644 --- a/src/main/java/kitchenpos/products/ui/ProductRestController.java +++ b/src/main/java/kitchenpos/products/ui/ProductRestController.java @@ -1,13 +1,19 @@ package kitchenpos.products.ui; -import kitchenpos.products.application.ProductService; -import kitchenpos.products.domain.Product; +import kitchenpos.products.tobe.application.ProductService; +import kitchenpos.products.tobe.application.dto.ProductInfo; +import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.ui.request.ProductChangeRequest; +import kitchenpos.products.ui.request.ProductCreateRequest; +import kitchenpos.products.ui.response.ProductChangeResponse; +import kitchenpos.products.ui.response.ProductCreateResponse; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.net.URI; import java.util.List; import java.util.UUID; +import java.util.stream.Collectors; @RequestMapping("/api/products") @RestController @@ -19,19 +25,42 @@ public ProductRestController(final ProductService productService) { } @PostMapping - public ResponseEntity create(@RequestBody final Product request) { - final Product response = productService.create(request); - return ResponseEntity.created(URI.create("/api/products/" + response.getId())) - .body(response); + public ResponseEntity create(@RequestBody final ProductCreateRequest request) { + final ProductInfo product = productService.create(request); + + return ResponseEntity.created(URI.create("/api/products/" + product.getId())) + .body(new ProductCreateResponse( + product.getId(), + product.getName(), + product.getPrice() + ) + ); } @PutMapping("/{productId}/price") - public ResponseEntity changePrice(@PathVariable final UUID productId, @RequestBody final Product request) { - return ResponseEntity.ok(productService.changePrice(productId, request)); + public ResponseEntity changePrice(@PathVariable final UUID productId, @RequestBody final ProductChangeRequest request) { + final ProductInfo productInfo = productService.changePrice(productId, request); + + return ResponseEntity.ok( + new ProductChangeResponse( + productInfo.getId(), + productInfo.getName(), + productInfo.getPrice() + ) + ); } @GetMapping - public ResponseEntity> findAll() { - return ResponseEntity.ok(productService.findAll()); + public ResponseEntity> findAll() { + final List product = productService.findAll(); + + return ResponseEntity.ok( + product.stream() + .map(it -> new ProductInfo( + it.getId(), + it.getName().getProductName(), + it.getPrice().getProductPrice())) + .collect(Collectors.toList()) + ); } } diff --git a/src/main/java/kitchenpos/products/ui/request/ProductChangeRequest.java b/src/main/java/kitchenpos/products/ui/request/ProductChangeRequest.java new file mode 100644 index 000000000..20db35231 --- /dev/null +++ b/src/main/java/kitchenpos/products/ui/request/ProductChangeRequest.java @@ -0,0 +1,26 @@ +package kitchenpos.products.ui.request; + +import java.math.BigDecimal; + +public class ProductChangeRequest { + private String name; + private BigDecimal price; + + private ProductChangeRequest() {} + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } +} diff --git a/src/main/java/kitchenpos/products/ui/request/ProductCreateRequest.java b/src/main/java/kitchenpos/products/ui/request/ProductCreateRequest.java new file mode 100644 index 000000000..3b86a1d57 --- /dev/null +++ b/src/main/java/kitchenpos/products/ui/request/ProductCreateRequest.java @@ -0,0 +1,27 @@ +package kitchenpos.products.ui.request; + +import java.math.BigDecimal; +import java.util.UUID; + +public class ProductCreateRequest { + private String name; + private BigDecimal price; + + private ProductCreateRequest() { } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } +} diff --git a/src/main/java/kitchenpos/products/ui/response/ProductChangeResponse.java b/src/main/java/kitchenpos/products/ui/response/ProductChangeResponse.java new file mode 100644 index 000000000..963a2ac88 --- /dev/null +++ b/src/main/java/kitchenpos/products/ui/response/ProductChangeResponse.java @@ -0,0 +1,28 @@ +package kitchenpos.products.ui.response; + +import java.math.BigDecimal; +import java.util.UUID; + +public class ProductChangeResponse { + private final UUID id; + private final String name; + private final BigDecimal price; + + public ProductChangeResponse(final UUID id, final String name, final BigDecimal price) { + this.id = id; + this.name = name; + this.price = price; + } + + public UUID getId() { + return id; + } + + public String getName() { + return name; + } + + public BigDecimal getPrice() { + return price; + } +} diff --git a/src/main/java/kitchenpos/products/ui/response/ProductCreateResponse.java b/src/main/java/kitchenpos/products/ui/response/ProductCreateResponse.java new file mode 100644 index 000000000..66ab26f55 --- /dev/null +++ b/src/main/java/kitchenpos/products/ui/response/ProductCreateResponse.java @@ -0,0 +1,29 @@ +package kitchenpos.products.ui.response; + +import java.math.BigDecimal; +import java.util.UUID; + +public class ProductCreateResponse { + + private final UUID id; + private final String name; + private final BigDecimal price; + + public ProductCreateResponse(final UUID id, final String name, final BigDecimal price) { + this.id = id; + this.name = name; + this.price = price; + } + + public UUID getId() { + return id; + } + + public String getName() { + return name; + } + + public BigDecimal getPrice() { + return price; + } +} diff --git a/src/test/java/kitchenpos/Fixtures.java b/src/test/java/kitchenpos/Fixtures.java index a17a54ab8..b21527be3 100644 --- a/src/test/java/kitchenpos/Fixtures.java +++ b/src/test/java/kitchenpos/Fixtures.java @@ -4,7 +4,7 @@ import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuGroup; import kitchenpos.menus.domain.MenuProduct; -import kitchenpos.products.domain.Product; +import kitchenpos.products.tobe.domain.Product; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/src/test/java/kitchenpos/menus/application/MenuServiceTest.java b/src/test/java/kitchenpos/menus/application/MenuServiceTest.java index 23f260848..9503ecc3b 100644 --- a/src/test/java/kitchenpos/menus/application/MenuServiceTest.java +++ b/src/test/java/kitchenpos/menus/application/MenuServiceTest.java @@ -6,8 +6,8 @@ import kitchenpos.menus.domain.MenuRepository; import kitchenpos.products.application.FakePurgomalumClient; import kitchenpos.products.application.InMemoryProductRepository; -import kitchenpos.products.domain.Product; -import kitchenpos.products.domain.ProductRepository; +import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.tobe.domain.ProductRepository; import kitchenpos.products.infra.PurgomalumClient; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; diff --git a/src/test/java/kitchenpos/products/application/InMemoryProductRepository.java b/src/test/java/kitchenpos/products/application/InMemoryProductRepository.java index 2fd78e96d..d4c93ca22 100644 --- a/src/test/java/kitchenpos/products/application/InMemoryProductRepository.java +++ b/src/test/java/kitchenpos/products/application/InMemoryProductRepository.java @@ -1,7 +1,7 @@ package kitchenpos.products.application; -import kitchenpos.products.domain.Product; -import kitchenpos.products.domain.ProductRepository; +import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.tobe.domain.ProductRepository; import java.util.*; import java.util.stream.Collectors; diff --git a/src/test/java/kitchenpos/products/application/ProductServiceTest.java b/src/test/java/kitchenpos/products/application/ProductServiceTest.java index 30cc6fb7a..767898b57 100644 --- a/src/test/java/kitchenpos/products/application/ProductServiceTest.java +++ b/src/test/java/kitchenpos/products/application/ProductServiceTest.java @@ -3,8 +3,9 @@ import kitchenpos.menus.application.InMemoryMenuRepository; import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuRepository; -import kitchenpos.products.domain.Product; -import kitchenpos.products.domain.ProductRepository; +import kitchenpos.products.tobe.application.ProductService; +import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.tobe.domain.ProductRepository; import kitchenpos.products.infra.PurgomalumClient; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; From b1b331ef5da568af5bcad07c4483333a65d4e4fe Mon Sep 17 00:00:00 2001 From: Shin seongsu Date: Mon, 25 Sep 2023 03:06:09 +0900 Subject: [PATCH 2/8] =?UTF-8?q?fix:=20=EA=B0=9D=EC=B2=B4=EB=A1=9C=20?= =?UTF-8?q?=EB=AC=B6=EC=97=AC=EC=A0=B8=20=EC=9E=88=EB=8A=94=EA=B1=B0=20?= =?UTF-8?q?=ED=95=9C=EB=B2=88=EB=8D=94=20getter=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/kitchenpos/menus/application/MenuService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/kitchenpos/menus/application/MenuService.java b/src/main/java/kitchenpos/menus/application/MenuService.java index d010bfc15..e21e1fbd4 100644 --- a/src/main/java/kitchenpos/menus/application/MenuService.java +++ b/src/main/java/kitchenpos/menus/application/MenuService.java @@ -61,6 +61,7 @@ public Menu create(final Menu request) { .orElseThrow(NoSuchElementException::new); sum = sum.add( product.getPrice() + .getProductPrice() .multiply(BigDecimal.valueOf(quantity)) ); final MenuProduct menuProduct = new MenuProduct(); @@ -98,6 +99,7 @@ public Menu changePrice(final UUID menuId, final Menu request) { sum = sum.add( menuProduct.getProduct() .getPrice() + .getProductPrice() .multiply(BigDecimal.valueOf(menuProduct.getQuantity())) ); } @@ -117,6 +119,7 @@ public Menu display(final UUID menuId) { sum = sum.add( menuProduct.getProduct() .getPrice() + .getProductPrice() .multiply(BigDecimal.valueOf(menuProduct.getQuantity())) ); } From 93e8cdab3c02c6d6869c29428a31d3c057c95008 Mon Sep 17 00:00:00 2001 From: Shin seongsu Date: Mon, 25 Sep 2023 03:40:49 +0900 Subject: [PATCH 3/8] =?UTF-8?q?test:=20domain=20=EB=B0=8F=20service=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../products/tobe/domain/ProductName.java | 15 +++++- .../products/tobe/domain/ProductPrice.java | 13 ++++- .../ui/request/ProductChangeRequest.java | 5 ++ .../ui/request/ProductCreateRequest.java | 5 ++ src/test/java/kitchenpos/Fixtures.java | 14 +++-- .../application/ProductServiceTest.java | 53 ++++++++++++------- .../products/tobe/domain/ProductNameTest.java | 50 +++++++++++++++++ .../tobe/domain/ProductPriceTest.java | 45 ++++++++++++++++ 8 files changed, 173 insertions(+), 27 deletions(-) create mode 100644 src/test/java/kitchenpos/products/tobe/domain/ProductNameTest.java create mode 100644 src/test/java/kitchenpos/products/tobe/domain/ProductPriceTest.java diff --git a/src/main/java/kitchenpos/products/tobe/domain/ProductName.java b/src/main/java/kitchenpos/products/tobe/domain/ProductName.java index d01f14421..20a1549f1 100644 --- a/src/main/java/kitchenpos/products/tobe/domain/ProductName.java +++ b/src/main/java/kitchenpos/products/tobe/domain/ProductName.java @@ -18,7 +18,6 @@ public ProductName(String productName, PurgomalumClient purgomalumClient) { } protected ProductName() { - } public String getProductName() { @@ -30,8 +29,20 @@ private void validateProductName(String productName, PurgomalumClient purgomalum throw new IllegalArgumentException("상품 이름 값이 존재하지 않습니다."); } if (purgomalumClient.containsProfanity(productName)) { - throw new IllegalArgumentException("상품 이름에 비속어가 존재합니다. product Name : " + productName); + throw new IllegalArgumentException("상품 이름에 비속어가 존재합니다."); } } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ProductName that = (ProductName) o; + return Objects.equals(productName, that.productName); + } + + @Override + public int hashCode() { + return Objects.hash(productName); + } } diff --git a/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java b/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java index 2420d6c55..d4f90e133 100644 --- a/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java +++ b/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java @@ -17,7 +17,6 @@ public ProductPrice(BigDecimal productPrice) { } protected ProductPrice() { - } private void validateProductPrice(BigDecimal productPrice) { @@ -33,4 +32,16 @@ public BigDecimal getProductPrice() { return productPrice; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ProductPrice price = (ProductPrice) o; + return Objects.equals(productPrice, price.productPrice); + } + + @Override + public int hashCode() { + return Objects.hash(productPrice); + } } diff --git a/src/main/java/kitchenpos/products/ui/request/ProductChangeRequest.java b/src/main/java/kitchenpos/products/ui/request/ProductChangeRequest.java index 20db35231..c9dd8d64c 100644 --- a/src/main/java/kitchenpos/products/ui/request/ProductChangeRequest.java +++ b/src/main/java/kitchenpos/products/ui/request/ProductChangeRequest.java @@ -8,6 +8,11 @@ public class ProductChangeRequest { private ProductChangeRequest() {} + public ProductChangeRequest(String name, BigDecimal price) { + this.name = name; + this.price = price; + } + public String getName() { return name; } diff --git a/src/main/java/kitchenpos/products/ui/request/ProductCreateRequest.java b/src/main/java/kitchenpos/products/ui/request/ProductCreateRequest.java index 3b86a1d57..c752c995d 100644 --- a/src/main/java/kitchenpos/products/ui/request/ProductCreateRequest.java +++ b/src/main/java/kitchenpos/products/ui/request/ProductCreateRequest.java @@ -9,6 +9,11 @@ public class ProductCreateRequest { private ProductCreateRequest() { } + public ProductCreateRequest(final String name, final BigDecimal price) { + this.name = name; + this.price = price; + } + public String getName() { return name; } diff --git a/src/test/java/kitchenpos/Fixtures.java b/src/test/java/kitchenpos/Fixtures.java index b21527be3..782818d82 100644 --- a/src/test/java/kitchenpos/Fixtures.java +++ b/src/test/java/kitchenpos/Fixtures.java @@ -4,7 +4,11 @@ import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuGroup; import kitchenpos.menus.domain.MenuProduct; +import kitchenpos.products.application.FakePurgomalumClient; import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.tobe.domain.ProductName; +import kitchenpos.products.tobe.domain.ProductPrice; +import kitchenpos.products.tobe.domain.ProductPriceTest; import java.math.BigDecimal; import java.time.LocalDateTime; @@ -118,10 +122,10 @@ public static Product product() { } public static Product product(final String name, final long price) { - final Product product = new Product(); - product.setId(UUID.randomUUID()); - product.setName(name); - product.setPrice(BigDecimal.valueOf(price)); - return product; + return new Product( + UUID.randomUUID(), + new ProductName(name, new FakePurgomalumClient()), + new ProductPrice(BigDecimal.valueOf(price)) + ); } } diff --git a/src/test/java/kitchenpos/products/application/ProductServiceTest.java b/src/test/java/kitchenpos/products/application/ProductServiceTest.java index 767898b57..7edd4b8cb 100644 --- a/src/test/java/kitchenpos/products/application/ProductServiceTest.java +++ b/src/test/java/kitchenpos/products/application/ProductServiceTest.java @@ -1,12 +1,19 @@ package kitchenpos.products.application; import kitchenpos.menus.application.InMemoryMenuRepository; +import kitchenpos.menus.application.ProductMenuServiceImpl; import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.products.tobe.application.ProductMenuService; import kitchenpos.products.tobe.application.ProductService; +import kitchenpos.products.tobe.application.dto.ProductInfo; import kitchenpos.products.tobe.domain.Product; +import kitchenpos.products.tobe.domain.ProductName; +import kitchenpos.products.tobe.domain.ProductPrice; import kitchenpos.products.tobe.domain.ProductRepository; import kitchenpos.products.infra.PurgomalumClient; +import kitchenpos.products.ui.request.ProductChangeRequest; +import kitchenpos.products.ui.request.ProductCreateRequest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -26,6 +33,7 @@ class ProductServiceTest { private ProductRepository productRepository; private MenuRepository menuRepository; + private ProductMenuService productMenuService; private PurgomalumClient purgomalumClient; private ProductService productService; @@ -33,15 +41,17 @@ class ProductServiceTest { void setUp() { productRepository = new InMemoryProductRepository(); menuRepository = new InMemoryMenuRepository(); + productMenuService = new ProductMenuServiceImpl(menuRepository); purgomalumClient = new FakePurgomalumClient(); - productService = new ProductService(productRepository, menuRepository, purgomalumClient); + + productService = new ProductService(productRepository, productMenuService, purgomalumClient); } @DisplayName("상품을 등록할 수 있다.") @Test void create() { - final Product expected = createProductRequest("후라이드", 16_000L); - final Product actual = productService.create(expected); + final ProductCreateRequest expected = new ProductCreateRequest("후라이드", new BigDecimal(16000)); + final ProductInfo actual = productService.create(expected); assertThat(actual).isNotNull(); assertAll( () -> assertThat(actual.getId()).isNotNull(), @@ -55,7 +65,7 @@ void create() { @NullSource @ParameterizedTest void create(final BigDecimal price) { - final Product expected = createProductRequest("후라이드", price); + final ProductCreateRequest expected = new ProductCreateRequest("후라이드", price); assertThatThrownBy(() -> productService.create(expected)) .isInstanceOf(IllegalArgumentException.class); } @@ -65,7 +75,7 @@ void create(final BigDecimal price) { @NullSource @ParameterizedTest void create(final String name) { - final Product expected = createProductRequest(name, 16_000L); + final ProductCreateRequest expected = new ProductCreateRequest(name, new BigDecimal(16000)); assertThatThrownBy(() -> productService.create(expected)) .isInstanceOf(IllegalArgumentException.class); } @@ -73,9 +83,10 @@ void create(final String name) { @DisplayName("상품의 가격을 변경할 수 있다.") @Test void changePrice() { - final UUID productId = productRepository.save(product("후라이드", 16_000L)).getId(); - final Product expected = changePriceRequest(15_000L); - final Product actual = productService.changePrice(productId, expected); + final Product product = productRepository.save(product("후라이드", 16_000L)); + final ProductChangeRequest expected = new ProductChangeRequest("", new BigDecimal(15000)); + + final ProductInfo actual = productService.changePrice(product.getId(), expected); assertThat(actual.getPrice()).isEqualTo(expected.getPrice()); } @@ -84,9 +95,9 @@ void changePrice() { @NullSource @ParameterizedTest void changePrice(final BigDecimal price) { - final UUID productId = productRepository.save(product("후라이드", 16_000L)).getId(); - final Product expected = changePriceRequest(price); - assertThatThrownBy(() -> productService.changePrice(productId, expected)) + final Product product = productRepository.save(product("후라이드", 16_000L)); + final ProductChangeRequest expected = new ProductChangeRequest("", price); + assertThatThrownBy(() -> productService.changePrice(product.getId(), expected)) .isInstanceOf(IllegalArgumentException.class); } @@ -95,7 +106,8 @@ void changePrice(final BigDecimal price) { void changePriceInMenu() { final Product product = productRepository.save(product("후라이드", 16_000L)); final Menu menu = menuRepository.save(menu(19_000L, true, menuProduct(product, 2L))); - productService.changePrice(product.getId(), changePriceRequest(8_000L)); + final ProductChangeRequest request = new ProductChangeRequest("", new BigDecimal(8000)); + productService.changePrice(product.getId(), request); assertThat(menuRepository.findById(menu.getId()).get().isDisplayed()).isFalse(); } @@ -113,10 +125,11 @@ private Product createProductRequest(final String name, final long price) { } private Product createProductRequest(final String name, final BigDecimal price) { - final Product product = new Product(); - product.setName(name); - product.setPrice(price); - return product; + return new Product( + UUID.randomUUID(), + new ProductName(name, purgomalumClient), + new ProductPrice(price) + ); } private Product changePriceRequest(final long price) { @@ -124,8 +137,10 @@ private Product changePriceRequest(final long price) { } private Product changePriceRequest(final BigDecimal price) { - final Product product = new Product(); - product.setPrice(price); - return product; + return new Product( + UUID.randomUUID(), + new ProductName("", purgomalumClient), + new ProductPrice(price) + ); } } diff --git a/src/test/java/kitchenpos/products/tobe/domain/ProductNameTest.java b/src/test/java/kitchenpos/products/tobe/domain/ProductNameTest.java new file mode 100644 index 000000000..3e76ed28b --- /dev/null +++ b/src/test/java/kitchenpos/products/tobe/domain/ProductNameTest.java @@ -0,0 +1,50 @@ +package kitchenpos.products.tobe.domain; + +import kitchenpos.products.application.FakePurgomalumClient; +import kitchenpos.products.infra.PurgomalumClient; +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 static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class ProductNameTest { + + private PurgomalumClient purgomalumClient; + + @BeforeEach + void setUp() { + this.purgomalumClient = new FakePurgomalumClient(); + } + + @DisplayName("성공적으로 상품이름이 생성된다.") + @Test + void success() { + final ProductName productName = new ProductName("치킨", purgomalumClient); + + assertThat(productName).isEqualTo(new ProductName("치킨", purgomalumClient)); + } + + @DisplayName("상품 이름이 존재하지 않으면 에러를 반환한다.") + @ParameterizedTest + @NullSource + void emptyProductNameException(String name) { + assertThatThrownBy(() -> new ProductName(name, purgomalumClient)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("상품 이름 값이 존재하지 않습니다."); + } + + @DisplayName("상품 이름에 비속어가 존재하면 에러를 반환한다.") + @Test + void containsPurgomalumException() { + final String name = "비속어"; + + assertThatThrownBy(() -> new ProductName(name, purgomalumClient)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("상품 이름에 비속어가 존재합니다."); + } + +} diff --git a/src/test/java/kitchenpos/products/tobe/domain/ProductPriceTest.java b/src/test/java/kitchenpos/products/tobe/domain/ProductPriceTest.java new file mode 100644 index 000000000..b9895b130 --- /dev/null +++ b/src/test/java/kitchenpos/products/tobe/domain/ProductPriceTest.java @@ -0,0 +1,45 @@ +package kitchenpos.products.tobe.domain; + +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 java.math.BigDecimal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class ProductPriceTest { + + @DisplayName("상품 가격이 생성된다.") + @Test + void success() { + final ProductPrice price = new ProductPrice(BigDecimal.ONE); + + assertThat(price).isEqualTo(new ProductPrice(BigDecimal.ONE)); + } + + + @DisplayName("상품 가격이 없으면 에러를 반환한다.") + @NullSource + @ParameterizedTest + void emptyProductPriceException(BigDecimal price) { + assertThatThrownBy(() -> new ProductPrice(price)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("상풍 가격은 필수로 존재해야 합니다."); + } + + @DisplayName("상품가격이 0원 이하이면 에러를 반환한다.") + @ParameterizedTest + @ValueSource(strings = "-1000") + void negativePriceException() { + final BigDecimal price = new BigDecimal(-1000); + + assertThatThrownBy(() -> new ProductPrice(price)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("상품 가격은 0원 이상이어야 합니다."); + } + +} From acf01bda2f2f28d51565abf0efe9deb3eeb82f52 Mon Sep 17 00:00:00 2001 From: Shin seongsu Date: Tue, 26 Sep 2023 23:17:45 +0900 Subject: [PATCH 4/8] =?UTF-8?q?fix:=20Transactional=20class=20=EB=B2=94?= =?UTF-8?q?=EC=9C=84=EB=A1=9C=20=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kitchenpos/products/tobe/application/ProductService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/kitchenpos/products/tobe/application/ProductService.java b/src/main/java/kitchenpos/products/tobe/application/ProductService.java index f45df8a32..7f3a8b013 100644 --- a/src/main/java/kitchenpos/products/tobe/application/ProductService.java +++ b/src/main/java/kitchenpos/products/tobe/application/ProductService.java @@ -18,6 +18,7 @@ import java.util.UUID; @Service +@Transactional public class ProductService { private final ProductRepository productRepository; private final ProductMenuService productMenuService; @@ -33,7 +34,6 @@ public ProductService( this.purgomalumClient = purgomalumClient; } - @Transactional public ProductInfo create(final ProductCreateRequest request) { final Product product = productRepository.save(new Product( UUID.randomUUID(), @@ -48,7 +48,6 @@ public ProductInfo create(final ProductCreateRequest request) { ); } - @Transactional public ProductInfo changePrice(final UUID productId, final ProductChangeRequest request) { final Product product = productRepository.findById(productId) .orElseThrow(NoSuchElementException::new); From c7a97c30813488f34c48c84375edaf7320fc306c Mon Sep 17 00:00:00 2001 From: Shin seongsu Date: Tue, 26 Sep 2023 23:20:07 +0900 Subject: [PATCH 5/8] =?UTF-8?q?fix:=20=EC=A1=B0=EA=B1=B4=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EC=9C=BC=EB=A9=B4=20display=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EB=90=98=EB=8F=84=EB=A1=9D=20=ED=95=98=EB=8A=94=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kitchenpos/menus/application/ProductMenuServiceImpl.java | 2 +- .../products/tobe/application/ProductMenuService.java | 2 +- .../kitchenpos/products/tobe/application/ProductService.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/kitchenpos/menus/application/ProductMenuServiceImpl.java b/src/main/java/kitchenpos/menus/application/ProductMenuServiceImpl.java index b0c0f0cc6..e89525191 100644 --- a/src/main/java/kitchenpos/menus/application/ProductMenuServiceImpl.java +++ b/src/main/java/kitchenpos/menus/application/ProductMenuServiceImpl.java @@ -17,7 +17,7 @@ public ProductMenuServiceImpl(MenuRepository menuRepository) { } @Override - public void validMenuDisplay(final UUID productId) { + public void changeMenuDisplayStatus(final UUID productId) { menuRepository.findAllByProductId(productId) .forEach(menu -> { BigDecimal sum = menu.getMenuProducts().stream() diff --git a/src/main/java/kitchenpos/products/tobe/application/ProductMenuService.java b/src/main/java/kitchenpos/products/tobe/application/ProductMenuService.java index b2aad3029..3ce99bd18 100644 --- a/src/main/java/kitchenpos/products/tobe/application/ProductMenuService.java +++ b/src/main/java/kitchenpos/products/tobe/application/ProductMenuService.java @@ -3,5 +3,5 @@ import java.util.UUID; public interface ProductMenuService { - void validMenuDisplay(final UUID productId); + void changeMenuDisplayStatus(final UUID productId); } diff --git a/src/main/java/kitchenpos/products/tobe/application/ProductService.java b/src/main/java/kitchenpos/products/tobe/application/ProductService.java index 7f3a8b013..b4e3f4d16 100644 --- a/src/main/java/kitchenpos/products/tobe/application/ProductService.java +++ b/src/main/java/kitchenpos/products/tobe/application/ProductService.java @@ -53,7 +53,7 @@ public ProductInfo changePrice(final UUID productId, final ProductChangeRequest .orElseThrow(NoSuchElementException::new); product.changePrice(new ProductPrice(request.getPrice())); - productMenuService.validMenuDisplay(productId); + productMenuService.changeMenuDisplayStatus(productId); return new ProductInfo( product.getId(), From 1d361ee476a99a37a2deeabc6ac959dfaf4dda2a Mon Sep 17 00:00:00 2001 From: Shin seongsu Date: Tue, 26 Sep 2023 23:43:27 +0900 Subject: [PATCH 6/8] =?UTF-8?q?fix:=20Event=20=EC=84=B1=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EB=8B=A4=EB=A5=B8=20=EB=8F=84=EB=A9=94=EC=9D=B8=20Service?= =?UTF-8?q?=EB=A1=9C=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=B3=B4=EB=82=B4?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../menus/application/MenuEventListener.java | 20 ++++++++++++ .../menus/application/MenuService.java | 18 ++++++++--- .../application/ProductMenuServiceImpl.java | 32 ------------------- .../menus/application/dto/MenuEvent.java | 9 ++++++ .../tobe/application/ProductMenuService.java | 7 ---- .../tobe/application/ProductService.java | 13 +++++--- .../tobe/application/dto/ProductEvent.java | 19 +++++++++++ .../FakeApplicationEventPublisher.java | 22 +++++++++++++ .../application/ProductServiceTest.java | 10 +++--- 9 files changed, 97 insertions(+), 53 deletions(-) create mode 100644 src/main/java/kitchenpos/menus/application/MenuEventListener.java delete mode 100644 src/main/java/kitchenpos/menus/application/ProductMenuServiceImpl.java create mode 100644 src/main/java/kitchenpos/menus/application/dto/MenuEvent.java delete mode 100644 src/main/java/kitchenpos/products/tobe/application/ProductMenuService.java create mode 100644 src/main/java/kitchenpos/products/tobe/application/dto/ProductEvent.java create mode 100644 src/test/java/kitchenpos/products/application/FakeApplicationEventPublisher.java diff --git a/src/main/java/kitchenpos/menus/application/MenuEventListener.java b/src/main/java/kitchenpos/menus/application/MenuEventListener.java new file mode 100644 index 000000000..0cd6df794 --- /dev/null +++ b/src/main/java/kitchenpos/menus/application/MenuEventListener.java @@ -0,0 +1,20 @@ +package kitchenpos.menus.application; + +import kitchenpos.menus.application.dto.MenuEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +@Component +public class MenuEventListener { + + private final MenuService menuService; + + public MenuEventListener(MenuService menuService) { + this.menuService = menuService; + } + + @EventListener + public void changeMenuDisplayStatus(final MenuEvent menuEvent) { + menuService.changeMenuDisplayStatus(menuEvent.getProductId()); + } +} diff --git a/src/main/java/kitchenpos/menus/application/MenuService.java b/src/main/java/kitchenpos/menus/application/MenuService.java index e21e1fbd4..8ba9df8b4 100644 --- a/src/main/java/kitchenpos/menus/application/MenuService.java +++ b/src/main/java/kitchenpos/menus/application/MenuService.java @@ -12,6 +12,7 @@ import java.util.stream.Collectors; @Service +@Transactional public class MenuService { private final MenuRepository menuRepository; private final MenuGroupRepository menuGroupRepository; @@ -30,7 +31,6 @@ public MenuService( this.purgomalumClient = purgomalumClient; } - @Transactional public Menu create(final Menu request) { final BigDecimal price = request.getPrice(); if (Objects.isNull(price) || price.compareTo(BigDecimal.ZERO) < 0) { @@ -86,7 +86,6 @@ public Menu create(final Menu request) { return menuRepository.save(menu); } - @Transactional public Menu changePrice(final UUID menuId, final Menu request) { final BigDecimal price = request.getPrice(); if (Objects.isNull(price) || price.compareTo(BigDecimal.ZERO) < 0) { @@ -110,7 +109,6 @@ public Menu changePrice(final UUID menuId, final Menu request) { return menu; } - @Transactional public Menu display(final UUID menuId) { final Menu menu = menuRepository.findById(menuId) .orElseThrow(NoSuchElementException::new); @@ -130,7 +128,6 @@ public Menu display(final UUID menuId) { return menu; } - @Transactional public Menu hide(final UUID menuId) { final Menu menu = menuRepository.findById(menuId) .orElseThrow(NoSuchElementException::new); @@ -138,6 +135,19 @@ public Menu hide(final UUID menuId) { return menu; } + public void changeMenuDisplayStatus(final UUID productId) { + menuRepository.findAllByProductId(productId) + .forEach(menu -> { + BigDecimal sum = menu.getMenuProducts().stream() + .map(menuProduct -> menuProduct.getProduct().getPrice().getProductPrice().multiply(BigDecimal.valueOf(menuProduct.getQuantity()))) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + if (menu.getPrice().compareTo(sum) > 0) { + menu.setDisplayed(false); + } + }); + } + @Transactional(readOnly = true) public List findAll() { return menuRepository.findAll(); diff --git a/src/main/java/kitchenpos/menus/application/ProductMenuServiceImpl.java b/src/main/java/kitchenpos/menus/application/ProductMenuServiceImpl.java deleted file mode 100644 index e89525191..000000000 --- a/src/main/java/kitchenpos/menus/application/ProductMenuServiceImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -package kitchenpos.menus.application; - -import kitchenpos.menus.domain.MenuRepository; -import kitchenpos.products.tobe.application.ProductMenuService; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.util.UUID; - -@Service -public class ProductMenuServiceImpl implements ProductMenuService { - - private final MenuRepository menuRepository; - - public ProductMenuServiceImpl(MenuRepository menuRepository) { - this.menuRepository = menuRepository; - } - - @Override - public void changeMenuDisplayStatus(final UUID productId) { - menuRepository.findAllByProductId(productId) - .forEach(menu -> { - BigDecimal sum = menu.getMenuProducts().stream() - .map(menuProduct -> menuProduct.getProduct().getPrice().getProductPrice().multiply(BigDecimal.valueOf(menuProduct.getQuantity()))) - .reduce(BigDecimal.ZERO, BigDecimal::add); - - if (menu.getPrice().compareTo(sum) > 0) { - menu.setDisplayed(false); - } - }); - } -} diff --git a/src/main/java/kitchenpos/menus/application/dto/MenuEvent.java b/src/main/java/kitchenpos/menus/application/dto/MenuEvent.java new file mode 100644 index 000000000..307415b92 --- /dev/null +++ b/src/main/java/kitchenpos/menus/application/dto/MenuEvent.java @@ -0,0 +1,9 @@ +package kitchenpos.menus.application.dto; + +import java.util.UUID; + +public abstract class MenuEvent { + + public abstract UUID getProductId(); + +} diff --git a/src/main/java/kitchenpos/products/tobe/application/ProductMenuService.java b/src/main/java/kitchenpos/products/tobe/application/ProductMenuService.java deleted file mode 100644 index 3ce99bd18..000000000 --- a/src/main/java/kitchenpos/products/tobe/application/ProductMenuService.java +++ /dev/null @@ -1,7 +0,0 @@ -package kitchenpos.products.tobe.application; - -import java.util.UUID; - -public interface ProductMenuService { - void changeMenuDisplayStatus(final UUID productId); -} diff --git a/src/main/java/kitchenpos/products/tobe/application/ProductService.java b/src/main/java/kitchenpos/products/tobe/application/ProductService.java index b4e3f4d16..e4a0e1fc2 100644 --- a/src/main/java/kitchenpos/products/tobe/application/ProductService.java +++ b/src/main/java/kitchenpos/products/tobe/application/ProductService.java @@ -1,6 +1,7 @@ package kitchenpos.products.tobe.application; import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.products.tobe.application.dto.ProductEvent; import kitchenpos.products.tobe.application.dto.ProductInfo; import kitchenpos.products.tobe.domain.Product; import kitchenpos.products.tobe.domain.ProductRepository; @@ -9,6 +10,7 @@ import kitchenpos.products.tobe.domain.ProductPrice; import kitchenpos.products.ui.request.ProductChangeRequest; import kitchenpos.products.ui.request.ProductCreateRequest; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,17 +23,18 @@ @Transactional public class ProductService { private final ProductRepository productRepository; - private final ProductMenuService productMenuService; private final PurgomalumClient purgomalumClient; + private final ApplicationEventPublisher applicationEventPublisher; + public ProductService( final ProductRepository productRepository, - final ProductMenuService productMenuService, - final PurgomalumClient purgomalumClient + final PurgomalumClient purgomalumClient, + final ApplicationEventPublisher applicationEventPublisher ) { this.productRepository = productRepository; - this.productMenuService = productMenuService; this.purgomalumClient = purgomalumClient; + this.applicationEventPublisher = applicationEventPublisher; } public ProductInfo create(final ProductCreateRequest request) { @@ -53,7 +56,7 @@ public ProductInfo changePrice(final UUID productId, final ProductChangeRequest .orElseThrow(NoSuchElementException::new); product.changePrice(new ProductPrice(request.getPrice())); - productMenuService.changeMenuDisplayStatus(productId); + applicationEventPublisher.publishEvent(new ProductEvent(productId)); return new ProductInfo( product.getId(), diff --git a/src/main/java/kitchenpos/products/tobe/application/dto/ProductEvent.java b/src/main/java/kitchenpos/products/tobe/application/dto/ProductEvent.java new file mode 100644 index 000000000..8756701b8 --- /dev/null +++ b/src/main/java/kitchenpos/products/tobe/application/dto/ProductEvent.java @@ -0,0 +1,19 @@ +package kitchenpos.products.tobe.application.dto; + +import kitchenpos.menus.application.dto.MenuEvent; + +import java.util.UUID; + +public class ProductEvent extends MenuEvent { + + private final UUID productId; + + public ProductEvent(final UUID productId) { + this.productId = productId; + } + + @Override + public UUID getProductId() { + return productId; + } +} diff --git a/src/test/java/kitchenpos/products/application/FakeApplicationEventPublisher.java b/src/test/java/kitchenpos/products/application/FakeApplicationEventPublisher.java new file mode 100644 index 000000000..e2aef0e77 --- /dev/null +++ b/src/test/java/kitchenpos/products/application/FakeApplicationEventPublisher.java @@ -0,0 +1,22 @@ +package kitchenpos.products.application; + +import kitchenpos.menus.application.MenuService; +import kitchenpos.menus.application.dto.MenuEvent; +import kitchenpos.menus.domain.MenuRepository; +import kitchenpos.products.tobe.domain.ProductRepository; +import org.springframework.context.ApplicationEventPublisher; + +public class FakeApplicationEventPublisher implements ApplicationEventPublisher { + private final MenuService menuService; + + public FakeApplicationEventPublisher(ProductRepository productRepository, MenuRepository menuRepository) { + this.menuService = new MenuService(menuRepository, null, productRepository, null); + } + + @Override + public void publishEvent(Object event) { + if (event instanceof MenuEvent) { + menuService.changeMenuDisplayStatus(((MenuEvent) event).getProductId()); + } + } +} diff --git a/src/test/java/kitchenpos/products/application/ProductServiceTest.java b/src/test/java/kitchenpos/products/application/ProductServiceTest.java index 7edd4b8cb..ec47ab845 100644 --- a/src/test/java/kitchenpos/products/application/ProductServiceTest.java +++ b/src/test/java/kitchenpos/products/application/ProductServiceTest.java @@ -1,10 +1,9 @@ package kitchenpos.products.application; import kitchenpos.menus.application.InMemoryMenuRepository; -import kitchenpos.menus.application.ProductMenuServiceImpl; +import kitchenpos.menus.application.MenuEventListener; import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuRepository; -import kitchenpos.products.tobe.application.ProductMenuService; import kitchenpos.products.tobe.application.ProductService; import kitchenpos.products.tobe.application.dto.ProductInfo; import kitchenpos.products.tobe.domain.Product; @@ -20,6 +19,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.context.ApplicationEventPublisher; import java.math.BigDecimal; import java.util.List; @@ -33,18 +33,18 @@ class ProductServiceTest { private ProductRepository productRepository; private MenuRepository menuRepository; - private ProductMenuService productMenuService; private PurgomalumClient purgomalumClient; private ProductService productService; + private ApplicationEventPublisher applicationEventPublisher; @BeforeEach void setUp() { productRepository = new InMemoryProductRepository(); menuRepository = new InMemoryMenuRepository(); - productMenuService = new ProductMenuServiceImpl(menuRepository); purgomalumClient = new FakePurgomalumClient(); + applicationEventPublisher = new FakeApplicationEventPublisher(productRepository, menuRepository); - productService = new ProductService(productRepository, productMenuService, purgomalumClient); + productService = new ProductService(productRepository, purgomalumClient, applicationEventPublisher); } @DisplayName("상품을 등록할 수 있다.") From 3618040a198595232e28b454a720d6da94988c87 Mon Sep 17 00:00:00 2001 From: Shin seongsu Date: Wed, 27 Sep 2023 00:02:39 +0900 Subject: [PATCH 7/8] =?UTF-8?q?feat:=20Global=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/GlobalRestControllerAdvice.java | 23 +++++++++++++++++++ .../custom/NotFoundProductException.java | 8 +++++++ .../global/exception/dto/ErrorCode.java | 22 ++++++++++++++++++ .../exception/dto/ExceptionResponse.java | 20 ++++++++++++++++ .../tobe/application/ProductService.java | 3 ++- 5 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 src/main/java/kitchenpos/global/exception/GlobalRestControllerAdvice.java create mode 100644 src/main/java/kitchenpos/global/exception/custom/NotFoundProductException.java create mode 100644 src/main/java/kitchenpos/global/exception/dto/ErrorCode.java create mode 100644 src/main/java/kitchenpos/global/exception/dto/ExceptionResponse.java diff --git a/src/main/java/kitchenpos/global/exception/GlobalRestControllerAdvice.java b/src/main/java/kitchenpos/global/exception/GlobalRestControllerAdvice.java new file mode 100644 index 000000000..d2915e4c7 --- /dev/null +++ b/src/main/java/kitchenpos/global/exception/GlobalRestControllerAdvice.java @@ -0,0 +1,23 @@ +package kitchenpos.global.exception; + +import kitchenpos.global.exception.dto.ErrorCode; +import kitchenpos.global.exception.dto.ExceptionResponse; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.NoSuchElementException; + +@RestControllerAdvice +public class GlobalRestControllerAdvice { + + @ResponseBody + @ExceptionHandler(NoSuchElementException.class) + public ExceptionResponse noSuchElementExceptionHandler(NoSuchElementException exception) { + return new ExceptionResponse( + ErrorCode.NO_SUCH_ELEMENT.getCode(), + ErrorCode.NO_SUCH_ELEMENT.getMessage() + ); + } + +} diff --git a/src/main/java/kitchenpos/global/exception/custom/NotFoundProductException.java b/src/main/java/kitchenpos/global/exception/custom/NotFoundProductException.java new file mode 100644 index 000000000..58f28229e --- /dev/null +++ b/src/main/java/kitchenpos/global/exception/custom/NotFoundProductException.java @@ -0,0 +1,8 @@ +package kitchenpos.global.exception.custom; + +import java.util.NoSuchElementException; + +public class NotFoundProductException extends NoSuchElementException { + public NotFoundProductException() { + } +} diff --git a/src/main/java/kitchenpos/global/exception/dto/ErrorCode.java b/src/main/java/kitchenpos/global/exception/dto/ErrorCode.java new file mode 100644 index 000000000..5106554e8 --- /dev/null +++ b/src/main/java/kitchenpos/global/exception/dto/ErrorCode.java @@ -0,0 +1,22 @@ +package kitchenpos.global.exception.dto; + +public enum ErrorCode { + + NO_SUCH_ELEMENT("E001", "데이터를 찾지 못했습니다."); + + private final String code; + private final String message; + + ErrorCode(String code, String message) { + this.code = code; + this.message = message; + } + + public String getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/kitchenpos/global/exception/dto/ExceptionResponse.java b/src/main/java/kitchenpos/global/exception/dto/ExceptionResponse.java new file mode 100644 index 000000000..f046e1a7c --- /dev/null +++ b/src/main/java/kitchenpos/global/exception/dto/ExceptionResponse.java @@ -0,0 +1,20 @@ +package kitchenpos.global.exception.dto; + +public class ExceptionResponse { + + private final String code; + private final String message; + + public ExceptionResponse(String code, String message) { + this.code = code; + this.message = message; + } + + public String getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/kitchenpos/products/tobe/application/ProductService.java b/src/main/java/kitchenpos/products/tobe/application/ProductService.java index e4a0e1fc2..9a99e90a5 100644 --- a/src/main/java/kitchenpos/products/tobe/application/ProductService.java +++ b/src/main/java/kitchenpos/products/tobe/application/ProductService.java @@ -1,5 +1,6 @@ package kitchenpos.products.tobe.application; +import kitchenpos.global.exception.custom.NotFoundProductException; import kitchenpos.menus.domain.MenuRepository; import kitchenpos.products.tobe.application.dto.ProductEvent; import kitchenpos.products.tobe.application.dto.ProductInfo; @@ -53,7 +54,7 @@ public ProductInfo create(final ProductCreateRequest request) { public ProductInfo changePrice(final UUID productId, final ProductChangeRequest request) { final Product product = productRepository.findById(productId) - .orElseThrow(NoSuchElementException::new); + .orElseThrow(NotFoundProductException::new); product.changePrice(new ProductPrice(request.getPrice())); applicationEventPublisher.publishEvent(new ProductEvent(productId)); From 953cbd458fdafd2328601eb3c5da6a5619bd4d27 Mon Sep 17 00:00:00 2001 From: Shin seongsu Date: Wed, 27 Sep 2023 00:44:27 +0900 Subject: [PATCH 8/8] =?UTF-8?q?fix:=20vo=20=EC=97=90=EC=84=9C=20validator?= =?UTF-8?q?=20=EC=B2=B4=ED=81=AC=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tobe/application/ProductService.java | 14 ++++----- .../products/tobe/domain/NameValidator.java | 29 +++++++++++++++++++ .../products/tobe/domain/PriceValidator.java | 29 +++++++++++++++++++ .../products/tobe/domain/ProductName.java | 12 +------- .../products/tobe/domain/ProductPrice.java | 10 ------- .../tobe/domain/ProductValidator.java | 24 +++++++++++++++ src/test/java/kitchenpos/Fixtures.java | 4 +-- .../application/ProductServiceTest.java | 4 +-- ...ctNameTest.java => NameValidatorTest.java} | 14 ++------- ...PriceTest.java => PriceValidatorTest.java} | 17 ++--------- 10 files changed, 99 insertions(+), 58 deletions(-) create mode 100644 src/main/java/kitchenpos/products/tobe/domain/NameValidator.java create mode 100644 src/main/java/kitchenpos/products/tobe/domain/PriceValidator.java create mode 100644 src/main/java/kitchenpos/products/tobe/domain/ProductValidator.java rename src/test/java/kitchenpos/products/tobe/domain/{ProductNameTest.java => NameValidatorTest.java} (71%) rename src/test/java/kitchenpos/products/tobe/domain/{ProductPriceTest.java => PriceValidatorTest.java} (69%) diff --git a/src/main/java/kitchenpos/products/tobe/application/ProductService.java b/src/main/java/kitchenpos/products/tobe/application/ProductService.java index 9a99e90a5..c62286e9b 100644 --- a/src/main/java/kitchenpos/products/tobe/application/ProductService.java +++ b/src/main/java/kitchenpos/products/tobe/application/ProductService.java @@ -4,11 +4,8 @@ import kitchenpos.menus.domain.MenuRepository; import kitchenpos.products.tobe.application.dto.ProductEvent; import kitchenpos.products.tobe.application.dto.ProductInfo; -import kitchenpos.products.tobe.domain.Product; -import kitchenpos.products.tobe.domain.ProductRepository; +import kitchenpos.products.tobe.domain.*; import kitchenpos.products.infra.PurgomalumClient; -import kitchenpos.products.tobe.domain.ProductName; -import kitchenpos.products.tobe.domain.ProductPrice; import kitchenpos.products.ui.request.ProductChangeRequest; import kitchenpos.products.ui.request.ProductCreateRequest; import org.springframework.context.ApplicationEventPublisher; @@ -39,10 +36,12 @@ public ProductService( } public ProductInfo create(final ProductCreateRequest request) { + ProductValidator productValidator = new ProductValidator(request.getName(), request.getPrice(), purgomalumClient); + final Product product = productRepository.save(new Product( UUID.randomUUID(), - new ProductName(request.getName(), purgomalumClient), - new ProductPrice(request.getPrice()) + new ProductName(productValidator.getNameValidator().getName()), + new ProductPrice(productValidator.getPriceValidator().getPrice()) )); return new ProductInfo( @@ -55,7 +54,8 @@ public ProductInfo create(final ProductCreateRequest request) { public ProductInfo changePrice(final UUID productId, final ProductChangeRequest request) { final Product product = productRepository.findById(productId) .orElseThrow(NotFoundProductException::new); - product.changePrice(new ProductPrice(request.getPrice())); + PriceValidator priceValidator = new PriceValidator(request.getPrice()); + product.changePrice(new ProductPrice(priceValidator.getPrice())); applicationEventPublisher.publishEvent(new ProductEvent(productId)); diff --git a/src/main/java/kitchenpos/products/tobe/domain/NameValidator.java b/src/main/java/kitchenpos/products/tobe/domain/NameValidator.java new file mode 100644 index 000000000..24b84fb95 --- /dev/null +++ b/src/main/java/kitchenpos/products/tobe/domain/NameValidator.java @@ -0,0 +1,29 @@ +package kitchenpos.products.tobe.domain; + +import kitchenpos.products.infra.PurgomalumClient; + +import java.util.Objects; + +public class NameValidator { + + private final String name; + + public NameValidator(String name, PurgomalumClient purgomalumClient) { + validateProductName(name, purgomalumClient); + this.name = name; + } + + public String getName() { + return name; + } + + private void validateProductName(final String productName, final PurgomalumClient purgomalumClient) { + if (Objects.isNull(productName)) { + throw new IllegalArgumentException("상품 이름 값이 존재하지 않습니다."); + } + if (purgomalumClient.containsProfanity(productName)) { + throw new IllegalArgumentException("상품 이름에 비속어가 존재합니다."); + } + } + +} diff --git a/src/main/java/kitchenpos/products/tobe/domain/PriceValidator.java b/src/main/java/kitchenpos/products/tobe/domain/PriceValidator.java new file mode 100644 index 000000000..fbe6f6e39 --- /dev/null +++ b/src/main/java/kitchenpos/products/tobe/domain/PriceValidator.java @@ -0,0 +1,29 @@ +package kitchenpos.products.tobe.domain; + +import kitchenpos.products.infra.PurgomalumClient; + +import java.math.BigDecimal; +import java.util.Objects; + +public class PriceValidator { + + private final BigDecimal price; + + public PriceValidator(BigDecimal price) { + this.validatePrice(price); + this.price = price; + } + + public BigDecimal getPrice() { + return price; + } + + private void validatePrice(final BigDecimal productPrice) { + if (Objects.isNull(productPrice)) { + throw new IllegalArgumentException("상풍 가격은 필수로 존재해야 합니다."); + } + if (productPrice.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalArgumentException("상품 가격은 0원 이상이어야 합니다."); + } + } +} diff --git a/src/main/java/kitchenpos/products/tobe/domain/ProductName.java b/src/main/java/kitchenpos/products/tobe/domain/ProductName.java index 20a1549f1..a1aaec23a 100644 --- a/src/main/java/kitchenpos/products/tobe/domain/ProductName.java +++ b/src/main/java/kitchenpos/products/tobe/domain/ProductName.java @@ -12,8 +12,7 @@ public class ProductName { @Column(name = "name", nullable = false) private String productName; - public ProductName(String productName, PurgomalumClient purgomalumClient) { - validateProductName(productName, purgomalumClient); + public ProductName(String productName) { this.productName = productName; } @@ -24,15 +23,6 @@ public String getProductName() { return productName; } - private void validateProductName(String productName, PurgomalumClient purgomalumClient) { - if (Objects.isNull(productName)) { - throw new IllegalArgumentException("상품 이름 값이 존재하지 않습니다."); - } - if (purgomalumClient.containsProfanity(productName)) { - throw new IllegalArgumentException("상품 이름에 비속어가 존재합니다."); - } - } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java b/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java index d4f90e133..63219f4a4 100644 --- a/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java +++ b/src/main/java/kitchenpos/products/tobe/domain/ProductPrice.java @@ -12,22 +12,12 @@ public class ProductPrice { private BigDecimal productPrice; public ProductPrice(BigDecimal productPrice) { - validateProductPrice(productPrice); this.productPrice = productPrice; } protected ProductPrice() { } - private void validateProductPrice(BigDecimal productPrice) { - if (Objects.isNull(productPrice)) { - throw new IllegalArgumentException("상풍 가격은 필수로 존재해야 합니다."); - } - if (productPrice.compareTo(BigDecimal.ZERO) < 0) { - throw new IllegalArgumentException("상품 가격은 0원 이상이어야 합니다."); - } - } - public BigDecimal getProductPrice() { return productPrice; } diff --git a/src/main/java/kitchenpos/products/tobe/domain/ProductValidator.java b/src/main/java/kitchenpos/products/tobe/domain/ProductValidator.java new file mode 100644 index 000000000..5f6bf7f20 --- /dev/null +++ b/src/main/java/kitchenpos/products/tobe/domain/ProductValidator.java @@ -0,0 +1,24 @@ +package kitchenpos.products.tobe.domain; + +import kitchenpos.products.infra.PurgomalumClient; + +import java.math.BigDecimal; +import java.util.Objects; + +public class ProductValidator { + private final NameValidator nameValidator; + private final PriceValidator priceValidator; + + public ProductValidator(String name, BigDecimal price, PurgomalumClient purgomalumClient) { + this.nameValidator = new NameValidator(name, purgomalumClient); + this.priceValidator = new PriceValidator(price); + } + + public NameValidator getNameValidator() { + return nameValidator; + } + + public PriceValidator getPriceValidator() { + return priceValidator; + } +} diff --git a/src/test/java/kitchenpos/Fixtures.java b/src/test/java/kitchenpos/Fixtures.java index 782818d82..cfa26366c 100644 --- a/src/test/java/kitchenpos/Fixtures.java +++ b/src/test/java/kitchenpos/Fixtures.java @@ -4,11 +4,9 @@ import kitchenpos.menus.domain.Menu; import kitchenpos.menus.domain.MenuGroup; import kitchenpos.menus.domain.MenuProduct; -import kitchenpos.products.application.FakePurgomalumClient; import kitchenpos.products.tobe.domain.Product; import kitchenpos.products.tobe.domain.ProductName; import kitchenpos.products.tobe.domain.ProductPrice; -import kitchenpos.products.tobe.domain.ProductPriceTest; import java.math.BigDecimal; import java.time.LocalDateTime; @@ -124,7 +122,7 @@ public static Product product() { public static Product product(final String name, final long price) { return new Product( UUID.randomUUID(), - new ProductName(name, new FakePurgomalumClient()), + new ProductName(name), new ProductPrice(BigDecimal.valueOf(price)) ); } diff --git a/src/test/java/kitchenpos/products/application/ProductServiceTest.java b/src/test/java/kitchenpos/products/application/ProductServiceTest.java index ec47ab845..5f35ba8b8 100644 --- a/src/test/java/kitchenpos/products/application/ProductServiceTest.java +++ b/src/test/java/kitchenpos/products/application/ProductServiceTest.java @@ -127,7 +127,7 @@ private Product createProductRequest(final String name, final long price) { private Product createProductRequest(final String name, final BigDecimal price) { return new Product( UUID.randomUUID(), - new ProductName(name, purgomalumClient), + new ProductName(name), new ProductPrice(price) ); } @@ -139,7 +139,7 @@ private Product changePriceRequest(final long price) { private Product changePriceRequest(final BigDecimal price) { return new Product( UUID.randomUUID(), - new ProductName("", purgomalumClient), + new ProductName(""), new ProductPrice(price) ); } diff --git a/src/test/java/kitchenpos/products/tobe/domain/ProductNameTest.java b/src/test/java/kitchenpos/products/tobe/domain/NameValidatorTest.java similarity index 71% rename from src/test/java/kitchenpos/products/tobe/domain/ProductNameTest.java rename to src/test/java/kitchenpos/products/tobe/domain/NameValidatorTest.java index 3e76ed28b..fd34a834c 100644 --- a/src/test/java/kitchenpos/products/tobe/domain/ProductNameTest.java +++ b/src/test/java/kitchenpos/products/tobe/domain/NameValidatorTest.java @@ -8,10 +8,9 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.NullSource; -import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -class ProductNameTest { +public class NameValidatorTest { private PurgomalumClient purgomalumClient; @@ -20,19 +19,12 @@ void setUp() { this.purgomalumClient = new FakePurgomalumClient(); } - @DisplayName("성공적으로 상품이름이 생성된다.") - @Test - void success() { - final ProductName productName = new ProductName("치킨", purgomalumClient); - - assertThat(productName).isEqualTo(new ProductName("치킨", purgomalumClient)); - } @DisplayName("상품 이름이 존재하지 않으면 에러를 반환한다.") @ParameterizedTest @NullSource void emptyProductNameException(String name) { - assertThatThrownBy(() -> new ProductName(name, purgomalumClient)) + assertThatThrownBy(() -> new NameValidator(name, purgomalumClient)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("상품 이름 값이 존재하지 않습니다."); } @@ -42,7 +34,7 @@ void emptyProductNameException(String name) { void containsPurgomalumException() { final String name = "비속어"; - assertThatThrownBy(() -> new ProductName(name, purgomalumClient)) + assertThatThrownBy(() -> new NameValidator(name, purgomalumClient)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("상품 이름에 비속어가 존재합니다."); } diff --git a/src/test/java/kitchenpos/products/tobe/domain/ProductPriceTest.java b/src/test/java/kitchenpos/products/tobe/domain/PriceValidatorTest.java similarity index 69% rename from src/test/java/kitchenpos/products/tobe/domain/ProductPriceTest.java rename to src/test/java/kitchenpos/products/tobe/domain/PriceValidatorTest.java index b9895b130..87b42563a 100644 --- a/src/test/java/kitchenpos/products/tobe/domain/ProductPriceTest.java +++ b/src/test/java/kitchenpos/products/tobe/domain/PriceValidatorTest.java @@ -1,32 +1,21 @@ package kitchenpos.products.tobe.domain; 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 java.math.BigDecimal; -import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -public class ProductPriceTest { - - @DisplayName("상품 가격이 생성된다.") - @Test - void success() { - final ProductPrice price = new ProductPrice(BigDecimal.ONE); - - assertThat(price).isEqualTo(new ProductPrice(BigDecimal.ONE)); - } - +public class PriceValidatorTest { @DisplayName("상품 가격이 없으면 에러를 반환한다.") @NullSource @ParameterizedTest void emptyProductPriceException(BigDecimal price) { - assertThatThrownBy(() -> new ProductPrice(price)) + assertThatThrownBy(() -> new PriceValidator(price)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("상풍 가격은 필수로 존재해야 합니다."); } @@ -37,7 +26,7 @@ void emptyProductPriceException(BigDecimal price) { void negativePriceException() { final BigDecimal price = new BigDecimal(-1000); - assertThatThrownBy(() -> new ProductPrice(price)) + assertThatThrownBy(() -> new PriceValidator(price)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("상품 가격은 0원 이상이어야 합니다."); }