현재 장바구니 , 찜목록 추가 , 제거 기능을 완료했다.
완료하고 테스트를 거쳐 지난 회의때 완료되었다고 전달한것 같은데
커뮤니케이션 미스인지 기능이 완성된걸 모르고 계셨나보다 ...
쨌든 프론트에서도 잘 사용할수 있음을 확인해서 마음놓고 있었는데 ...
로그인한 유저가 장바구니를 조회했을때 디폴트 수량을 1 로 두고 수량증가 , 감소 를 만들어라.
장바구니를 조회하면 HttpServletRequest 에서 "Authorization" 헤더를 찾아 유저를 찾고
헤더의 토큰으로 로그인한 유저의 정보를 찾는다.
User 안에는 Cart 가 있고 Cart 에는 List<Product> 가 있다.
User 와 Cart 는
@OneToOne 관계를 맺고
Cart 와 Product 는
@OneToMany 관계를 맺는다.
Product 에는 id, name, description, categories, numberOfsold, productImage, brandName, Cart, Wish 가 존재했었다.
아마 장바구니에서 바로 주문으로 넘어갈때 해당 정보를 넘기는데 사용하지 않을까 추측해보았다.
또 장바구니에 수량을 포함해서 보여주는 기능을 추가하여도 나쁠건 없었다.
Product Entity 는 상품의 정보만을 담고 있어서 수량을 추가하려면 무언가 추가되어야 하고
Cart 와 Product 의 관계를 끊고 수량을 추가하며 Product 의 정보를 담는 무언가와 관계를 맺어줘야한다.
package com.hello.foreverpet.domain.entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.ManyToOne;
import com.hello.foreverpet.auditing.BaseTimeEntity;
import com.hello.foreverpet.domain.dto.Categories;
import com.hello.foreverpet.domain.dto.request.UpdateProductRequest;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Product extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long productId;
@NotNull
private String productName;
@NotNull
@Column(length = 500)
private String productDescription;
@NotNull
@Enumerated(EnumType.STRING)
private Categories categories;
@NotNull
private Long productPrice;
private Long numberOfSold;
private String productImage;
private String brandName;
@ManyToOne(fetch = FetchType.LAZY)
private Wish wish;
@Builder
public Product(String productName, String productDescription, Categories categories, Long productPrice,
String productImage, String brandName) {
this.productName = productName;
this.productDescription = productDescription;
this.categories = categories;
this.productPrice = productPrice;
this.numberOfSold = 0L;
this.productImage = productImage;
this.brandName = brandName;
}
public Product updateProductByUpdateRequest(UpdateProductRequest updateProductRequest) {
this.productName = updateProductRequest.getProductName();
this.productDescription = updateProductRequest.getProductDescription();
this.categories = Categories.valueOf(updateProductRequest.getCategories());
this.productPrice = updateProductRequest.getProductPrice();
this.productImage = updateProductRequest.getProductImage();
this.brandName = updateProductRequest.getBrandName();
return this;
}
public void setWish(Wish wish) {
this.wish = wish;
if (wish != null && !wish.getProducts().contains(this)) {
wish.getProducts().add(this);
}
}
// 주문시 판매수량 증가
public void soldProducts(OrderProduct orderProduct) {
this.numberOfSold += orderProduct.getOrderProductAmount();
}
// 주문 취소시 판매수량 감소
public void cancelOrder(OrderProduct orderProduct) {
this.numberOfSold -= orderProduct.getOrderProductAmount();
}
}
package com.hello.foreverpet.domain.entity;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Entity
@Getter
@NoArgsConstructor
@Slf4j
public class Cart {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(fetch = FetchType.LAZY)
private UserInfo userInfo;
@OneToMany(mappedBy = "cart", fetch = FetchType.LAZY,cascade = CascadeType.ALL)
private List<CartProduct> cartProducts = new ArrayList<>();
public Cart(UserInfo userInfo) {
this.userInfo = userInfo;
}
public void addProductToCart(Product product) {
CartProduct cartProduct = new CartProduct(product);
cartProducts.add(cartProduct);
cartProduct.setCart(this);
}
public void deleteProductInCart(CartProduct cartProduct) {
log.info("deleteProductInCart()");
for (CartProduct product : cartProducts) {
log.info("CartProductName = {}",product.getProduct().getProductName());
}
this.cartProducts.remove(cartProduct);
log.info("After Remove");
for (CartProduct product : cartProducts) {
log.info("CartProductName = {}",product.getProduct().getProductName());
}
}
public void setUserInfo(UserInfo userInfo) {
this.userInfo = userInfo;
}
}
package com.hello.foreverpet.domain.entity;
import com.hello.foreverpet.auditing.BaseTimeEntity;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Getter
@NoArgsConstructor
public class CartProduct extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Cart cart;
@ManyToOne(fetch = FetchType.LAZY)
private Product product;
private Long quantity;
public CartProduct(Product product) {
this.product = product;
this.quantity = 1L;
}
public void setCart(Cart cart) {
this.cart = cart;
}
public void increaseQuantity() {
this.quantity++;
}
public void decreaseQuantity() {
if (quantity > 1) {
quantity--;
}
}
}
Cart 에서 List 로 Product 를 담고있던것을
CartProduct 라는 새로운 엔티티를 생성하여 Cart 와 Product 사이의 연결 엔티티로 사용했다.
Before : Cart - @OneToMany - Product
After : Cart - @OneToMany - CartProduct - @OneToOne - Product
Product 에 수량에 대한 변수를 추가해서 쉽게 해결할수도 있지 않을까 했지만
상품에 대한 엔티티의 명확성을 가지면 좋을거 같아서 따로 Product 엔티티를 포함하고 장바구니에서 사용될 수량을 포함한 CartProduct 엔티티를 새로 생성하였다.
이곳저곳 코드 수정을 해야해서 번거로웠고 애초에 저렇게 설계해서 작업했으면 시간단축도 많이 되었을거같다.