개발/Project(Spring-쇼핑몰)

Project (7-3) 장바구니 상품 주문하기

잇(IT) 2023. 8. 18. 14:18
728x90

- 장바구니 목록 중 체크박스가 선택된 상품을 주문하는 로직을 작성한다.

- 장바구니에서 주문을 하면 기존 주문 로직과의 차이점은 여러 개의 상품을 하나의 주문에 담을 수 있다는 점과 주문한 상품은 장바구니에서 삭제해야 한다는 점이다.

 

- 장바구니 페이지에서 주문할 상품 데이터를 전달할 DTO를 생성한다.

- CartOrderDto.java

@Getter @Setter
public class CartOrderDto {

    private Long cartItemId;

    private List<CartOrderDto> cartOrderDtoList;
//    1. 장바구니에서 여러 개의 상품을 주문하므로 CartOrderDto 클래스가 자기 자신을 List로 가지고 있도록 만든다.
}

- 장바구니 주문은 cartItem의 Id와 장바구니에서 여러 개의 상품을 주문하므로 cartOrderDto 클래스가 자기 자신을 List로 가지고 있도록 만들어야 한다.


- OrderService 클래스에 장바구니에서 주문할 상품 데이터를 전달받아서 주문을 생성하는 로직을 만들어야 한다.

- OrderService.java

.....

public Long orders(List<OrderDto> orderDtoList, String email) {

        Member member = memberRepository.findByEmail(email);
        List<OrderItem> orderItemList = new ArrayList<>();

        for (OrderDto orderDto : orderDtoList) {
//            1. 주문할 상품 리스트를 만들어 준다.
            Item item = itemRepository.findById(orderDto.getItemId()).orElseThrow(EntityNotFoundException::new);

            OrderItem orderItem = OrderItem.createOrderItem(item, orderDto.getCount());
            orderItemList.add(orderItem);
        }

        Order order = Order.createOrder(member, orderItemList);
//        2. 현재 로그인한 회원과 주문 상품 목록을 이용하여 주문 엔티티를 만든다.
        orderRepository.save(order);
//        3. 주문 데이터를 저장한다.

        return order.getId();
    }
}

- CartService 클래스에서는 주문 로직으로 전달할 orderDto 리스트 생성 및 주문 로직 호출, 주문한 상품은 장바구니에서 제거하는 로직을 구현한다.

- CartService.java

@Service
@RequiredArgsConstructor
@Transactional
public class CartService {

    private final ItemRepository itemRepository;
    private final MemberRepository memberRepository;
    private final CartRepository cartRepository;
    private final CartItemRepository cartItemRepository;
    private final OrderService orderService;

.....

public Long orderCartItem(List<CartOrderDto> cartOrderDtoList, String email){
        List<OrderDto> orderDtoList = new ArrayList<>();

        for (CartOrderDto cartOrderDto : cartOrderDtoList) {
//            1. 장바구니 페이지에서 전달받은 주문 상품 번호를 이용하여 주문 로직으로 전달할 orderDto 객체를 만든다.
            CartItem cartItem = cartItemRepository
                    .findById(cartOrderDto.getCartItemId())
                    .orElseThrow(EntityNotFoundException::new);

            OrderDto orderDto = new OrderDto();
            orderDto.setItemId(cartItem.getItem().getId());
            orderDto.setCount(cartItem.getCount());
            orderDtoList.add(orderDto);
        }

        Long orderId = orderService.orders(orderDtoList, email);
//        2. 장바구니에 담은 상품을 주문하도록 주문 로직을 호출한다.
        for (CartOrderDto cartOrderDto : cartOrderDtoList) {
//            3. 주문한 상품들을 장바구니에서 제거한다.
            CartItem cartItem = cartItemRepository
                    .findById(cartOrderDto.getCartItemId())
                    .orElseThrow(EntityNotFoundException::new);
            cartItemRepository.delete(cartItem);
        }
        return orderId;
    }
}

- CartController 클래스에 장바구니 상품의 수량을 업데이트하는 요청을 처리할 수 있도록 로직을 추가한다.

- CartController.java

@PostMapping(value = "/cart/orders")
    public @ResponseBody ResponseEntity orderCartItem(@RequestBody CartOrderDto cartOrderDto, Principal principal){

        List<CartOrderDto> cartOrderDtoList = cartOrderDto.getCartOrderDtoList();

        if(cartOrderDtoList == null || cartOrderDtoList.size() == 0){
//            1. 주문할 상품을 선택하지 않았는지 체크한다.
            return new ResponseEntity<String>("주문할 상품을 선택해주세요", HttpStatus.FORBIDDEN);
        }

        for (CartOrderDto cartOrder : cartOrderDtoList) {
//            2. 주문 권한을 체크한다.
            if(!cartService.validateCartItem(cartOrder.getCartItemId(), principal.getName())){
                return new ResponseEntity<String>("주문 권한이 없습니다.", HttpStatus.FORBIDDEN);
            }
        }

        Long orderId = cartService.orderCartItem(cartOrderDtoList, principal.getName());
//        3. 주문 로직 호출 결과 생성된 주문 번호를 반환 받는다.
        return new ResponseEntity<Long>(orderId, HttpStatus.OK);
//        4. 생성된 주문 번호와 요청이 성공했다는 HTTP 응답 상태 코드를 반환한다.
    }
}

- cartList.html 파일에 장바구니에서 선택한 상품 주문을 요청하도록 자바스크립트 함수를 추가한다.

- cartList.html

.....

function orders(){
            var token = $("meta[name='_csrf']").attr("content");
            var header = $("meta[name='_csrf_header']").attr("content");

            var url = "/cart/orders";

            var dataList = new Array();
            var paramData = new Object();

            $("input[name=cartChkBox]:checked").each(function() {
                // 1. 체크된 장바구니 상품 아이디를 전달하기 위해서 dataList 배열에 장바구니 상품 아이디를 객체로 만들어서 저장한다.
                var cartItemId = $(this).val();
                var data = new Object();
                data["cartItemId"] = cartItemId;
                dataList.push(data);
            });

            paramData['cartOrderDtoList'] = dataList;
            // 2. 장바구니 상품 아이디를 저장하고 있는 dataList 배열을 paramData 객체에 추가한다.

            var param = JSON.stringify(paramData);

            $.ajax({
                url      : url,
                type     : "POST",
                contentType : "application/json",
                data     : param,
                beforeSend : function(xhr){
                    /* 데이터를 전송하기 전에 헤더에 csrf값을 설정 */
                    xhr.setRequestHeader(header, token);
                },
                dataType : "json",
                cache   : false,
                success  : function(result, status){
                    alert("주문이 완료 되었습니다.");
                    location.href='/orders';
                //     3. 주문 요청 결과 성공하였다면 구매이력 페이지로 이동한다.
                },
                error : function(jqXHR, status, error){

                    if(jqXHR.status == '401'){
                        alert('로그인 후 이용해주세요');
                        location.href='/members/login';
                    } else{
                        alert(jqXHR.responseJSON.message);
                    }

                }
            });
        }

    </script>

- <주문하기> 버튼을 클락하면 구현한 orders() 함수가 실행될 수 있도록 주문하기 버튼의 onclick 속성에 추가해준다.

.....

<div class="text-center mt-3">
            <button type="button" class="btn btn-primary btn-lg" onclick="orders()">주문하기</button>
        </div>
        
.....

 

728x90