Skip to content
This repository was archived by the owner on Apr 26, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/main/java/group/rohlik/application/CartLineAdder.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
39 changes: 3 additions & 36 deletions src/main/java/group/rohlik/controller/CartController.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -19,44 +15,15 @@
@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")
public ResponseEntity addLine(@PathVariable long id, @RequestBody JsonNode payload) {
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);
}
Expand Down
63 changes: 61 additions & 2 deletions src/main/java/group/rohlik/entity/Cart.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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 {
Expand All @@ -37,4 +40,60 @@ public class Cart {
)
@EqualsAndHashCode.Exclude
private Set<Discount> 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);
}
}
28 changes: 5 additions & 23 deletions src/test/java/group/rohlik/acceptance/steps/CartSteps.java
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down