From cb9a272fb7de7db865b7e05615d83f5e4066069d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Carpena?= Date: Fri, 10 Jun 2022 10:07:52 +0200 Subject: [PATCH] refactoring (step2) --- .../rohlik/application/CartLineAdder.java | 26 ++++++++ .../rohlik/controller/CartController.java | 39 +----------- src/main/java/group/rohlik/entity/Cart.java | 63 ++++++++++++++++++- .../rohlik/acceptance/steps/CartSteps.java | 28 ++------- 4 files changed, 95 insertions(+), 61 deletions(-) create mode 100644 src/main/java/group/rohlik/application/CartLineAdder.java diff --git a/src/main/java/group/rohlik/application/CartLineAdder.java b/src/main/java/group/rohlik/application/CartLineAdder.java new file mode 100644 index 0000000..be0524a --- /dev/null +++ b/src/main/java/group/rohlik/application/CartLineAdder.java @@ -0,0 +1,26 @@ +package group.rohlik.application; + +import group.rohlik.entity.Cart; +import group.rohlik.entity.CartRepository; +import group.rohlik.entity.Product; +import group.rohlik.entity.ProductRepository; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@AllArgsConstructor +@Service +@Transactional +public class CartLineAdder { + + private final CartRepository cartRepository; + private final ProductRepository productRepository; + + public void add(long cartId, String sku, int quantity) { + Cart cart = cartRepository.findById(cartId).orElseThrow(); + Product product = productRepository.findById(sku).orElseThrow(); + cart.addLine(product, quantity); + + cartRepository.save(cart); + } +} diff --git a/src/main/java/group/rohlik/controller/CartController.java b/src/main/java/group/rohlik/controller/CartController.java index 0151ef0..dc91271 100644 --- a/src/main/java/group/rohlik/controller/CartController.java +++ b/src/main/java/group/rohlik/controller/CartController.java @@ -2,11 +2,7 @@ import com.fasterxml.jackson.databind.JsonNode; import group.rohlik.application.CartDiscountAdder; -import group.rohlik.entity.Cart; -import group.rohlik.entity.CartLine; -import group.rohlik.entity.CartRepository; -import group.rohlik.entity.Product; -import group.rohlik.entity.ProductRepository; +import group.rohlik.application.CartLineAdder; import lombok.AllArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -19,8 +15,7 @@ @AllArgsConstructor public class CartController { - private final CartRepository cartRepository; - private final ProductRepository productRepository; + private final CartLineAdder cartLineAdder; private final CartDiscountAdder cartDiscountAdder; @PostMapping(path = "/carts/{id}/lines", consumes = "application/json", produces = "application/json") @@ -28,35 +23,7 @@ public ResponseEntity addLine(@PathVariable long id, @RequestBody JsonNode paylo String sku = payload.get("sku").textValue(); int quantity = payload.get("quantity").intValue(); - if (quantity < 0) { - throw new IllegalArgumentException("Negative quantity not allowed"); - } - - Cart cart = cartRepository.findById(id).orElseThrow(); - Product product = productRepository.findById(sku).orElseThrow(); - CartLine cartLine = cart.getLines() - .stream() - .filter(currentCartLine -> currentCartLine.getProduct().equals(product)) - .findFirst() - .orElse(null); - - if (cartLine == null) { - if (quantity > 0) { - cartLine = new CartLine(); - cartLine.setProduct(product); - cartLine.setQuantity(quantity); - cartLine.setCart(cart); - cart.getLines().add(cartLine); - } - } else { - if (quantity == 0) { - cart.getLines().remove(cartLine); - } else { - cartLine.setQuantity(quantity); - } - } - - cartRepository.save(cart); + cartLineAdder.add(id, sku, quantity); return new ResponseEntity<>(HttpStatus.OK); } diff --git a/src/main/java/group/rohlik/entity/Cart.java b/src/main/java/group/rohlik/entity/Cart.java index eeac636..7695073 100644 --- a/src/main/java/group/rohlik/entity/Cart.java +++ b/src/main/java/group/rohlik/entity/Cart.java @@ -1,8 +1,9 @@ package group.rohlik.entity; -import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import org.springframework.util.Assert; import javax.persistence.CascadeType; import javax.persistence.Entity; @@ -14,11 +15,13 @@ import javax.persistence.ManyToMany; import javax.persistence.OneToMany; import javax.persistence.Table; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.HashSet; import java.util.Set; @Entity -@Data +@Getter @NoArgsConstructor @Table(name = "carts") public class Cart { @@ -37,4 +40,60 @@ public class Cart { ) @EqualsAndHashCode.Exclude private Set discounts = new HashSet<>(); + + public void addLine(Product product, int quantity) { + Assert.isTrue(quantity >= 0, "Line quantity must be positive"); + + CartLine cartLine = lines + .stream() + .filter(currentCartLine -> currentCartLine.getProduct().equals(product)) + .findFirst() + .orElse(null); + + if (cartLine == null) { + if (quantity > 0) { + cartLine = new CartLine(); + cartLine.setProduct(product); + cartLine.setQuantity(quantity); + cartLine.setCart(this); + lines.add(cartLine); + } + } else { + if (quantity == 0) { + lines.remove(cartLine); + } else { + cartLine.setQuantity(quantity); + } + } + } + + private double totalLinesPrice() { + return lines + .stream() + .mapToDouble(currentCartLine -> currentCartLine.getQuantity() * currentCartLine.getProduct().getPrice()) + .sum(); + } + + private double totalDiscountsPrice() { + return discounts + .stream() + .mapToDouble(Discount::getValue) + .sum(); + } + + public double totalPrice() { + return BigDecimal + .valueOf(totalLinesPrice() - totalDiscountsPrice()) + .setScale(2, RoundingMode.CEILING) + .doubleValue(); + } + + public Integer quantityOfProduct(String sku) { + return lines + .stream() + .filter(line -> line.getProduct().getSku().equals(sku)) + .findFirst() + .map(CartLine::getQuantity) + .orElse(0); + } } diff --git a/src/test/java/group/rohlik/acceptance/steps/CartSteps.java b/src/test/java/group/rohlik/acceptance/steps/CartSteps.java index 6bf3aad..7e2f029 100644 --- a/src/test/java/group/rohlik/acceptance/steps/CartSteps.java +++ b/src/test/java/group/rohlik/acceptance/steps/CartSteps.java @@ -64,41 +64,23 @@ public void removeProductOfMyCart(String sku) { @Then("the cart's total cost should be {double} euro(s)") public void cartTotalCost(double amount) { Cart cart = currentCart(); - double totalProducts = cart - .getLines() - .stream() - .mapToDouble(currentCartLine -> currentCartLine.getQuantity() * currentCartLine.getProduct().getPrice()) - .sum(); - double totalDiscounts = cart.getDiscounts().stream().mapToDouble(Discount::getValue).sum(); - double totalPrice = totalProducts - totalDiscounts; - - Assertions.assertEquals(amount, BigDecimal.valueOf(totalPrice).setScale(2, RoundingMode.CEILING).doubleValue()); + double totalPrice = cart.totalPrice(); + Assertions.assertEquals(amount, totalPrice); } @Then("there should be {int} unit(s) of product {string} in my cart") public void thereShouldBeProductUnitsInMyCart(int quantity, String sku) { Cart cart = currentCart(); - CartLine cartLine = cart.getLines() - .stream() - .filter(currentCartLine -> currentCartLine.getProduct().getSku().equals(sku)) - .findFirst() - .orElse(null); - - Assertions.assertNotNull(cartLine, String.format("Product %s not found", sku)); - Assertions.assertEquals(quantity, cartLine.getQuantity()); + + Assertions.assertEquals(quantity, cart.quantityOfProduct(sku)); } @Then("there shouldn't be product {string} in my cart") public void thereShouldNotBeProductInCart(String sku) { Cart cart = currentCart(); - CartLine cartLine = cart.getLines() - .stream() - .filter(currentCartLine -> currentCartLine.getProduct().getSku().equals(sku)) - .findFirst() - .orElse(null); - Assertions.assertNull(cartLine, String.format("Product %s should not be present", sku)); + Assertions.assertTrue(cart.quantityOfProduct(sku) == 0, String.format("Product %s should not be present", sku)); } private Cart currentCart() {