CartService.java
package com.ctrlbuy.webshop.service;
import com.ctrlbuy.webshop.entity.Cart;
import com.ctrlbuy.webshop.entity.CartItem;
import com.ctrlbuy.webshop.entity.Product;
import com.ctrlbuy.webshop.repository.CartRepository;
import com.ctrlbuy.webshop.repository.ProductRepository;
import com.ctrlbuy.webshop.security.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@Service
@Transactional
public class CartService {
private final CartRepository cartRepository;
private final ProductRepository productRepository;
@Autowired
public CartService(CartRepository cartRepository,
ProductRepository productRepository) {
this.cartRepository = cartRepository;
this.productRepository = productRepository;
}
public Cart getOrCreateCart(User user) {
if (user == null) {
return new Cart();
}
return cartRepository.findByUser(user)
.orElseGet(() -> {
Cart newCart = new Cart(user);
return cartRepository.save(newCart);
});
}
public Cart getOrCreateSessionCart(String sessionId) {
if (sessionId == null || sessionId.isEmpty()) {
return new Cart();
}
return cartRepository.findBySessionId(sessionId)
.orElseGet(() -> {
Cart newCart = new Cart(sessionId);
return cartRepository.save(newCart);
});
}
public Cart addProductToCart(Cart cart, Long productId, Integer quantity) {
if (cart == null || productId == null || quantity == null || quantity <= 0) {
return cart;
}
Product product = productRepository.findById(productId)
.orElseThrow(() -> new RuntimeException("Product not found: " + productId));
// Check if item already exists in cart
CartItem existingItem = cart.findItemByProduct(product);
if (existingItem != null) {
// Update quantity of existing item
existingItem.setQuantity(existingItem.getQuantity() + quantity);
existingItem.calculateSubtotal();
} else {
// Create new cart item
CartItem newItem = new CartItem(cart, product, quantity);
cart.addItem(newItem);
}
cart.updateTotalPrice();
return cartRepository.save(cart);
}
public Cart updateCartItemQuantity(Cart cart, Long productId, Integer newQuantity) {
if (cart == null || productId == null || newQuantity == null) {
return cart;
}
Product product = productRepository.findById(productId)
.orElseThrow(() -> new RuntimeException("Product not found: " + productId));
CartItem item = cart.findItemByProduct(product);
if (item != null) {
if (newQuantity <= 0) {
// Remove item if quantity is 0 or negative
cart.removeItem(item);
} else {
// Update quantity
item.setQuantity(newQuantity);
item.calculateSubtotal();
}
cart.updateTotalPrice();
return cartRepository.save(cart);
}
return cart;
}
public Cart removeProductFromCart(Cart cart, Long productId) {
if (cart == null || productId == null) {
return cart;
}
Product product = productRepository.findById(productId)
.orElseThrow(() -> new RuntimeException("Product not found: " + productId));
CartItem item = cart.findItemByProduct(product);
if (item != null) {
cart.removeItem(item);
cart.updateTotalPrice();
return cartRepository.save(cart);
}
return cart;
}
public void clearCart(Cart cart) {
if (cart != null && !cart.isEmpty()) {
// Clear the cart - JPA will handle cascade delete
cart.clear();
cart.updateTotalPrice();
cartRepository.save(cart);
}
}
public BigDecimal getCartTotal(User user, String sessionId) {
Cart cart;
if (user != null) {
cart = cartRepository.findByUser(user).orElse(null);
} else {
cart = cartRepository.findBySessionId(sessionId).orElse(null);
}
return cart != null ? cart.getTotalPrice() : BigDecimal.ZERO;
}
public int getCartItemCount(User user, String sessionId) {
Cart cart;
if (user != null) {
cart = cartRepository.findByUser(user).orElse(null);
} else {
cart = cartRepository.findBySessionId(sessionId).orElse(null);
}
return cart != null ? cart.getTotalItems() : 0;
}
public Cart mergeSessionCartWithUserCart(String sessionId, User user) {
if (sessionId == null || user == null) {
return getOrCreateCart(user);
}
Optional<Cart> sessionCartOpt = cartRepository.findBySessionId(sessionId);
if (sessionCartOpt.isEmpty()) {
return getOrCreateCart(user);
}
Cart sessionCart = sessionCartOpt.get();
Cart userCart = getOrCreateCart(user);
// Merge items from session cart to user cart
for (CartItem sessionItem : sessionCart.getItems()) {
CartItem existingUserItem = userCart.findItemByProduct(sessionItem.getProduct());
if (existingUserItem != null) {
// Merge quantities
existingUserItem.setQuantity(existingUserItem.getQuantity() + sessionItem.getQuantity());
existingUserItem.calculateSubtotal();
} else {
// Move item to user cart
sessionItem.setCart(userCart);
userCart.addItem(sessionItem);
}
}
// Delete session cart
cartRepository.delete(sessionCart);
// Update and save user cart
userCart.updateTotalPrice();
return cartRepository.save(userCart);
}
@Transactional
public void cleanupOldCarts() {
LocalDateTime cutoffDate = LocalDateTime.now().minusDays(30);
cartRepository.deleteBySessionIdAndCreatedAtBefore(null, cutoffDate);
}
public List<Cart> findCartsByUser(User user) {
return cartRepository.findAllByUser(user);
}
public void deleteCart(Cart cart) {
if (cart != null) {
cartRepository.delete(cart);
}
}
}