쇼핑몰에서 구매자 기능에 해당하는 장바구니를 구현해보겠습니다!
1. Cart Entity, CartItem Entity를 생성합니다.
< Cart >
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Entity
public class Cart {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name="user_id")
private User user; // 구매자
private int count; // 카트에 담긴 총 상품 개수
@OneToMany(mappedBy = "cart")
private List<CartItem> cartItems = new ArrayList<>();
@DateTimeFormat(pattern = "yyyy-mm-dd")
private LocalDate createDate; // 날짜
@PrePersist
public void createDate(){
this.createDate = LocalDate.now();
}
public static Cart createCart(User user) {
Cart cart = new Cart();
cart.setCount(0);
cart.setUser(user);
return cart;
}
}
< CartItem >
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Entity
public class CartItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="cart_id")
private Cart cart;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="item_id")
private Item item;
private int count; // 상품 개수
public static CartItem createCartItem(Cart cart, Item item, int amount) {
CartItem cartItem = new CartItem();
cartItem.setCart(cart);
cartItem.setItem(item);
cartItem.setCount(amount);
return cartItem;
}
// 이미 담겨있는 물건 또 담을 경우 수량 증가
public void addCount(int count) {
this.count += count;
}
}
2. 상품 상세 페이지 html에서 장바구니 버튼을 만듭니다.
<form class="d-flex" sec:authorize="hasRole('ROLE_USER')" th:action="@{/user/cart/{id}/{itemId}(id=${user.id}, itemId=${item.id})}" method="post">
<div class="d-flex">
<input class="form-control text-center me-3" id="amount" name="amount" type="num" value="1"
style="max-width: 3rem"/>
<button class="btn btn-outline-dark flex-shrink-0" type="submit">
<i class="bi-cart-fill me-1"></i>
장바구니
</button>
</div>
</form>
3. 장바구니 Controller에서 데이터를 받아 처리합니다. (POST)
< Controller >
// 장바구니에 물건 넣기
@PostMapping("/user/cart/{id}/{itemId}")
public String addCartItem(@PathVariable("id") Integer id, @PathVariable("itemId") Integer itemId, int amount) {
User user = userPageService.findUser(id);
Item item = itemService.itemView(itemId);
cartService.addCart(user, item, amount);
return "redirect:/item/view/{itemId}";
}
4. cartService에서 addCart 메소드로 로직을 수행합니다.
< CartService >
// 장바구니 담기
@Transactional
public void addCart(User user, Item newItem, int amount) {
// 유저 id로 해당 유저의 장바구니 찾기
Cart cart = cartRepository.findByUserId(user.getId());
// 장바구니가 존재하지 않는다면
if (cart == null) {
cart = Cart.createCart(user);
cartRepository.save(cart);
}
Item item = itemRepository.findItemById(newItem.getId());
CartItem cartItem = cartItemRepository.findByCartIdAndItemId(cart.getId(), item.getId());
// 상품이 장바구니에 존재하지 않는다면 카트상품 생성 후 추가
if (cartItem == null) {
cartItem = CartItem.createCartItem(cart, item, amount);
cartItemRepository.save(cartItem);
}
// 상품이 장바구니에 이미 존재한다면 수량만 증가
else {
CartItem update = cartItem;
update.setCart(cartItem.getCart());
update.setItem(cartItem.getItem());
update.addCount(amount);
update.setCount(update.getCount());
cartItemRepository.save(update);
}
// 카트 상품 총 개수 증가
cart.setCount(cart.getCount()+amount);
}
이렇게 장바구니에 물건이 담기는 것을 확인할 수 있습니다!!
장바구니 물건 추가 기능 외에도 장바구니 페이지 (GET), 물건 삭제 기능도 있습니다.
상품 CRUD 기능과 유사하기 때문에 이를 응용하여 쉽게 구현할 수 있습니다!!
< 장바구니 페이지 접속 >
// 장바구니 페이지 접속
@GetMapping("/user/cart/{id}")
public String userCartPage(@PathVariable("id") Integer id, Model model, @AuthenticationPrincipal PrincipalDetails principalDetails) {
// 로그인이 되어있는 유저의 id와 장바구니에 접속하는 id가 같아야 함
if (principalDetails.getUser().getId() == id) {
User user = userPageService.findUser(id);
// 로그인 되어 있는 유저에 해당하는 장바구니 가져오기
Cart userCart = user.getCart();
// 장바구니에 들어있는 아이템 모두 가져오기
List<CartItem> cartItemList = cartService.allUserCartView(userCart);
// 장바구니에 들어있는 상품들의 총 가격
int totalPrice = 0;
for (CartItem cartitem : cartItemList) {
totalPrice += cartitem.getCount() * cartitem.getItem().getPrice();
}
model.addAttribute("totalPrice", totalPrice);
model.addAttribute("totalCount", userCart.getCount());
model.addAttribute("cartItems", cartItemList);
model.addAttribute("user", userPageService.findUser(id));
return "/user/userCart";
}
// 로그인 id와 장바구니 접속 id가 같지 않는 경우
else {
return "redirect:/main";
}
}
< 장바구니에서 상품 삭제 >
// 장바구니에서 물건 삭제
// 삭제하고 남은 상품의 총 개수
@GetMapping("/user/cart/{id}/{cartItemId}/delete")
public String deleteCartItem(@PathVariable("id") Integer id, @PathVariable("cartItemId") Integer itemId, Model model, @AuthenticationPrincipal PrincipalDetails principalDetails) {
// 로그인 유저 id와 장바구니 유저의 id가 같아야 함
if (principalDetails.getUser().getId() == id) {
// itemId로 장바구니 상품 찾기
CartItem cartItem = cartService.findCartItemById(itemId);
// 장바구니 물건 삭제
cartService.cartItemDelete(itemId);
// 해당 유저의 카트 찾기
Cart userCart = cartService.findUserCart(id);
// 해당 유저의 장바구니 상품들
List<CartItem> cartItemList = cartService.allUserCartView(userCart);
// 총 가격 += 수량 * 가격
int totalPrice = 0;
for (CartItem cartitem : cartItemList) {
totalPrice += cartitem.getCount() * cartitem.getItem().getPrice();
}
// 총 개수 += 수량
//int totalCount = 0;
//for (CartItem cartitem : cartItemList) {
// totalCount += cartitem.getCount();
//}
userCart.setCount(userCart.getCount()-cartItem.getCount());
model.addAttribute("totalPrice", totalPrice);
model.addAttribute("totalCount", userCart.getCount());
model.addAttribute("cartItems", cartItemList);
model.addAttribute("user", userPageService.findUser(id));
return "/user/userCart";
}
// 로그인 id와 장바구니 삭제하려는 유저의 id가 같지 않는 경우
else {
return "redirect:/main";
}
}
이렇게 하면 구매자의 장바구니 기능 설계 끝입니다~!
다음은 주문을 다뤄보겠습니다!
주문은 장바구니 상품 한 번에 전체 주문 / 상품 개별로 주문 으로 나누어 구현해보겠습니다.
화이띵 !!