** 미리 방지 **
Order와 OrderItem Entity를 구현하고 실행하는데 에러가 났습니다.
[SQL Error] you have an error in your SQL Syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' order
간단한 에러였지만 실수할 수 있으니 주의해야겠습니다!!
오늘은 상품 주문 기능에 대해 다뤄보겠습니다. 상품 주문은 장바구니에서 할 수 있고 상품 상세 페이지에서 바로 구매할 수도 있습니다!
먼저 장바구니 상품 주문을 보겠습니다.
1. Order Entity와 OrderItem Entity를 생성합니다.
< Order >
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
private User user; // 구매자
@OneToMany(mappedBy = "order")
private List<OrderItem> orderItems = new ArrayList<>();
@DateTimeFormat(pattern = "yyyy-mm-dd")
private LocalDate createDate; // 구매 날짜
@PrePersist
public void createDate() {
this.createDate = LocalDate.now();
}
public void addOrderItem(OrderItem orderItem) {
orderItems.add(orderItem);
orderItem.setOrder(this);
}
public static Order createOrder(User user, List<OrderItem> orderItemList) {
Order order = new Order();
order.setUser(user);
for (OrderItem orderItem : orderItemList) {
order.addOrderItem(orderItem);
}
order.setCreateDate(order.createDate);
return order;
}
public static Order createOrder(User user) {
Order order = new Order();
order.setUser(user);
order.setCreateDate(order.createDate);
return order;
}
}
< OrderItem >
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Entity
public class OrderItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="order_id")
private Order order;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
private User user; // 구매자
private int itemId; // 주문 상품 번호
private String itemName; // 주문 상품 이름
private int itemPrice; // 주문 상품 가격
private int itemCount; // 주문 상품 수량
private int itemTotalPrice; // 가격*수량
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name="saleItem_id")
private SaleItem saleItem; // 주문상품에 매핑되는 판매상품
private int isCancel; // 주문 취소 여부 (0:주문완료 / 1:주문취소)
// 장바구니 전체 주문
public static OrderItem createOrderItem(int itemId, User user, CartItem cartItem, SaleItem saleItem) {
OrderItem orderItem = new OrderItem();
orderItem.setItemId(itemId);
orderItem.setUser(user);
orderItem.setItemName(cartItem.getItem().getName());
orderItem.setItemPrice(cartItem.getItem().getPrice());
orderItem.setItemCount(cartItem.getCount());
orderItem.setItemTotalPrice(cartItem.getItem().getPrice()*cartItem.getCount());
orderItem.setSaleItem(saleItem);
return orderItem;
}
// 상품 개별 주문
public static OrderItem createOrderItem(int itemId, User user, Item item, int count, Order order, SaleItem saleItem) {
OrderItem orderItem = new OrderItem();
orderItem.setItemId(itemId);
orderItem.setUser(user);
orderItem.setOrder(order);
orderItem.setItemName(item.getName());
orderItem.setItemPrice(item.getPrice());
orderItem.setItemCount(count);
orderItem.setItemTotalPrice(item.getPrice()*count);
orderItem.setSaleItem(saleItem);
return orderItem;
}
}
2. Sale Entity와 SaleItem Entity를 생성합니다.
< Sale >
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Entity
public class Sale {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="seller_id")
private User seller; // 판매자
@OneToMany(mappedBy = "sale")
private List<SaleItem> saleItems = new ArrayList<>();
private int totalCount; // 총 판매 개수
public static Sale createSale(User seller) {
Sale sale = new Sale();
sale.setSeller(seller);
sale.setTotalCount(0);
return sale;
}
}
< SaleItem >
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Entity
public class SaleItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="sale_id")
private Sale sale;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "seller_id")
private User seller; // 판매자
private int itemId; // 주문 상품 번호
private String itemName; // 주문 상품 이름
private int itemPrice; // 주문 상품 가격
private int itemCount; // 주문 상품 수량
private int itemTotalPrice; // 가격*수량
@OneToOne(mappedBy = "saleItem")
private OrderItem orderItem; // 판매 상품에 매핑되는 주문 상품
private int isCancel; // 판매 취소 여부 (0:판매완료 / 1:판매취소)
@DateTimeFormat(pattern = "yyyy-mm-dd")
private LocalDate createDate; // 날짜
@PrePersist
public void createDate(){
this.createDate = LocalDate.now();
}
// 장바구니 전체 주문
public static SaleItem createSaleItem(int itemId, Sale sale, User seller, CartItem cartItem) {
SaleItem saleItem = new SaleItem();
saleItem.setItemId(itemId);
saleItem.setSale(sale);
saleItem.setSeller(seller);
saleItem.setItemName(cartItem.getItem().getName());
saleItem.setItemPrice(cartItem.getItem().getPrice());
saleItem.setItemCount(cartItem.getCount());
saleItem.setItemTotalPrice(cartItem.getItem().getPrice()*cartItem.getCount());
return saleItem;
}
// 상품 개별 주문
public static SaleItem createSaleItem(int itemId, Sale sale, User seller, Item item, int count) {
SaleItem saleItem = new SaleItem();
saleItem.setItemId(itemId);
saleItem.setSale(sale);
saleItem.setSeller(seller);
saleItem.setItemName(item.getName());
saleItem.setItemPrice(item.getPrice());
saleItem.setItemCount(count);
saleItem.setItemTotalPrice(item.getPrice()*count);
return saleItem;
}
}
3. userCart.html 에서 구매 버튼을 생성합니다.
4. Controller에서 POST 처리를 합니다.
// 장바구니 상품 전체 주문
@Transactional
@PostMapping("/user/cart/checkout/{id}")
public String cartCheckout(@PathVariable("id") Integer id, @AuthenticationPrincipal PrincipalDetails principalDetails, Model model) {
// 로그인이 되어있는 유저의 id와 주문하는 id가 같아야 함
if(principalDetails.getUser().getId() == id) {
User user = userPageService.findUser(id);
// 유저 카트 찾기
Cart userCart = cartService.findUserCart(user.getId());
// 유저 카트 안에 있는 상품들
List<CartItem> userCartItems = cartService.allUserCartView(userCart);
// 최종 결제 금액
int totalPrice = 0;
for (CartItem cartItem : userCartItems) {
// 장바구니 안에 있는 상품의 재고가 없거나 재고보다 많이 주문할 경우
if (cartItem.getItem().getStock() == 0 || cartItem.getItem().getStock() < cartItem.getCount()) {
return "redirect:/main";
}
totalPrice += cartItem.getCount() * cartItem.getItem().getPrice();
}
int userCoin = user.getCoin();
// 유저의 현재 잔액이 부족하다면
if (userCoin < totalPrice) {
return "redirect:/main";
} else {
// 유저 돈에서 최종 결제금액 빼야함
user.setCoin(user.getCoin() - totalPrice);
List<OrderItem> orderItemList = new ArrayList<>();
for (CartItem cartItem : userCartItems) {
// 각 상품에 대한 판매자
User seller = cartItem.getItem().getSeller();
// 판매자 수익 증가
seller.setCoin(seller.getCoin() + (cartItem.getCount() * cartItem.getItem().getPrice()));
// 재고 감소
cartItem.getItem().setStock(cartItem.getItem().getStock() - cartItem.getCount());
// 상품 개별로 판매 개수 증가
cartItem.getItem().setCount(cartItem.getItem().getCount() + cartItem.getCount());
// sale, saleItem 에 담기
SaleItem saleItem = saleService.addSale(cartItem.getItem().getId(), seller.getId(), cartItem);
// order, orderItem 에 담기
OrderItem orderItem = orderService.addCartOrder(cartItem.getItem().getId(), user.getId(), cartItem, saleItem);
orderItemList.add(orderItem);
}
orderService.addOrder(user, orderItemList);
// 장바구니 상품 모두 삭제
cartService.allCartItemDelete(id);
}
model.addAttribute("totalPrice", totalPrice);
model.addAttribute("cartItems", userCartItems);
model.addAttribute("user", userPageService.findUser(id));
return "redirect:/user/cart/{id}";
} else {
return "redirect:/main";
}
}
5. cartService, orderService, saleService에서 로직을 각각 구현합니다.
< cartService >
// 장바구니 아이템 전체 삭제 -> 매개변수는 유저 id
public void allCartItemDelete(int id) {
// 전체 cartItem 찾기
List<CartItem> cartItems = cartItemRepository.findAll();
// 반복문을 이용하여 해당하는 User 의 CartItem 만 찾아서 삭제
for(CartItem cartItem : cartItems){
if(cartItem.getCart().getUser().getId() == id) {
cartItem.getCart().setCount(0);
cartItemRepository.deleteById(cartItem.getId());
}
}
}
< orderService >
// 장바구니상품주문
@Transactional
public OrderItem addCartOrder(int itemId, int userId, CartItem cartItem, SaleItem saleItem) {
User user = userPageService.findUser(userId);
OrderItem orderItem = OrderItem.createOrderItem(itemId, user, cartItem, saleItem);
orderItemRepository.save(orderItem);
return orderItem;
}
< saleService >
// 판매내역에 저장 (장바구니 전체 주문)
@Transactional
public SaleItem addSale (int itemId, int sellerId, CartItem cartItem) {
User seller = userPageService.findUser(sellerId);
Sale sale = saleRepository.findBySellerId(sellerId);
sale.setTotalCount(sale.getTotalCount()+cartItem.getCount());
saleRepository.save(sale);
SaleItem saleItem = SaleItem.createSaleItem(itemId, sale, seller, cartItem);
saleItemRepository.save(saleItem);
return saleItem;
}
이렇게 하면 장바구니의 상품 주문이 성공적으로 끝납니다!!
구매자는 이제 다양한 상품을 장바구니에 담아놓고, 한 번에 주문 할 수 있습니다!