이 내용은 스프링 부트 쇼핑몰 프로젝트 with JPA 책을 학습한 내용입니다.
1. CartDetailDto
- 장바구니 조회 페이지에 전달할 Dto 클래스
- CartItem 객체와 비슷함. 따라서 List 에 담겨서 전달됨
@Getter
@Setter
public class CartDetailDto {
private Long cartItemId; // 장바구니 상품 아이디
private String itemNm; // 상품명
private int price; // 상품 금액
private int count; // 수량
private String imgUrl; // 상품 이미지 경로
public CartDetailDto(Long cartItemId, String itemNm, int price, int count, String imgUrl) {
this.cartItemId = cartItemId;
this.itemNm = itemNm;
this.price = price;
this.count = count;
this.imgUrl = imgUrl;
}
}
2. CartItemRepository
- 장바구니 페이지에 전달할 CartDetailDto 리스트를 쿼리 하나로 조회하는 JPQL 문
- 지연 로딩이기 때문에 최적화를 위해서 아래 코드와 같이 DTO의 생성자를 이용하여 조회 결과를 DTO 객체로 변환 후 반환할 수 있음
@Query("select new kr.spring.cart.dto.CartDetailDto(ci.id, i.itemNm, i.price, ci.count, im.imgUrl) " +
"from CartItem ci, ItemImg im " +
"join ci.item i " +
"where ci.cart.id = :cartId " +
"and im.item.id = ci.item.id " +
"and im.repimgYn = 'Y' " +
"order by ci.regTime desc")
List<CartDetailDto> findCartDetailDtoList(@Param("cartId") Long cartId);
3. CartService
- 현재 로그인한 유저의 장바구니안에 존재하는 상품(들) 조회 로직
- 로그인 유저 정보 -> 유저의 cart 조회 -> cart 를 참조하는 CartItem 조회 (cartDetailDto 로 변환)
// 현재 로그인한 회원의 정보를 이용하여 장바구니에 들어있는 상품을 조회
@Transactional(readOnly = true)
public List<CartDetailDto> getCartList(String email) {
List<CartDetailDto> cartDetailDtoList = new ArrayList<>();
Member member = memberRepository.findByEmail(email);
Cart cart = cartRepository.findByMemberId(member.getId());
if(cart == null) {
return cartDetailDtoList;
}
cartDetailDtoList = cartItemRepository.findCartDetailDtoList(cart.getId());
return cartDetailDtoList;
}
4. CartController
- 장바구니 페이지로 이동하는 로직
@GetMapping("/cart")
public String orderHist(Principal principal, Model model) {
List<CartDetailDto> cartDetailList = cartService.getCartList(principal.getName());
model.addAttribute("cartItems", cartDetailList);
return "cart/cartList";
}
장바구니 조회 페이지
1. 장바구니 조회 페이지 View
2. 총 주문 금액
- 주문할 상품을 체크하거나 해제할 경우 총 주문 금액을 구하는 함수 및 호출
<!-- cartList.html -->
$(document).ready(function(){
$("input[name=cartChkBox]").change( function(){
getOrderTotalPrice();
});
});
function getOrderTotalPrice(){
var orderTotalPrice = 0;
$("input[name=cartChkBox]:checked").each(function() {
var cartItemId = $(this).val();
var price = $("#price_" + cartItemId).attr("data-price");
var count = $("#count_" + cartItemId).val();
orderTotalPrice += price*count;
});
$("#orderTotalPrice").html(orderTotalPrice+'원');
}
3. 상품 전체 선택 및 해제
- checkall 태그의 프로퍼티 값이 checked 라면 cartChkBox 태그를 모두 checked 상태로 변경
- checked 가 아니라면 모두 checked 상태를 해제
- 마지막에 총 주문 금액을 수정하는 getOrderTotalPrice() 함수 호출
function checkAll(){
if($("#checkall").prop("checked")){
$("input[name=cartChkBox]").prop("checked",true);
}else{
$("input[name=cartChkBox]").prop("checked",false);
}
getOrderTotalPrice();
}
4. 장바구니 상품 수량 변경
- 수량 부분의 수량을 변경하면 changeCount() 함수 호출
- 변경된 수량을 적용하기 위해 총 주문 금액을 수정하는 getOrderTotalPrice() 함수 호출
<input type="number" name="count" th:id="'count_' + ${cartItem.cartItemId}"
th:value="${cartItem.count}" min="1"
onchange="changeCount(this)" class="form-control mr-2" >
function changeCount(obj){
var count = obj.value;
var cartItemId = obj.id.split('_')[1];
var price = $("#price_" + cartItemId).data("price");
var totalPrice = count*price;
$("#totalPrice_" + cartItemId).html(totalPrice+"원");
getOrderTotalPrice();
updateCartItemCount(cartItemId, count);
}
- data-key-value 형태의 자료구조
<!-- id = price{CartItemId} 엘리먼트에 data 자료구조 생성 후 key = price 에 대한 value 지정 -->
<span th:id="'price_' + ${cartItem.cartItemId}"
th:data-price="${cartItem.price}"
th:text="${cartItem.price} + '원'" class="align-self-center mr-2">
</span>
- 장바구니에 들어있는 상품의 수량을 변경하면 CartItem 의 count 값도 수정되야 하므로 마지막에 updateCartItemCount() 함수 호출
function updateCartItemCount(cartItemId, count){
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
// 상품 Id 값은 PathVariable, 수량(count)은 QueryString
var url = "/cartItem/" + cartItemId+"?count=" + count;
$.ajax({
url : url,
type : "PATCH",
beforeSend : function(xhr){
/* 데이터를 전송하기 전에 헤더에 csrf값을 설정 */
xhr.setRequestHeader(header, token);
},
dataType : "json",
cache : false,
success : function(result, status){
console.log("cartItem count update success");
},
error : function(jqXHR, status, error){
if(jqXHR.status == '401'){
alert('로그인 후 이용해주세요');
location.href='/members/login';
} else{
alert(jqXHR.responseJSON.message);
}
}
});
}
5. CartItem Entity
- 수량 변경을 위한 메소드 추가
// 장바구니에 담겨있는 수량을 변경하는 메소드
public void updateCount(int count) {
this.count = count;
}
6. CartService
- updateCount() 메소드를 호출하는 로직을 추가
- 현재 로그인한 유저와 해당 장바구니 상품의 저장한 유저가 같은지 검증
// 현재 로그인한 회원과 해당 장바구니 상품을 저장한 회원이 같은지 검사
@Transactional(readOnly = true)
public boolean validateCartItem(Long cartItemId, String email) {
Member curMember = memberRepository.findByEmail(email);
CartItem cartItem = cartItemRepository.findById(cartItemId).orElseThrow(EntityNotFoundException::new);
Member savedMmeber = cartItem.getCart().getMember();
if(!StringUtils.equals(curMember.getEmail(), savedMmeber.getEmail())) {
return false;
}
return true;
}
7. CartController
- 위에 존재하는 updateCartItemCount() 함수 호출 시 전송되는 PATCH 요청에 대한 Controller
- cartService.updateCartItemCount() 메소드 호출
- 상품의 개수를 0으로 지정할 시 에러 메시지 반환
// 장바구니 상품의 수량을 업데이트하는 요청 처리
@PatchMapping("/cartItem/{cartItemId}")
public @ResponseBody ResponseEntity updateCartItem(@PathVariable("cartItemId") Long cartItemId, int count, Principal principal) {
if(count <= 0) {
return new ResponseEntity<String>("최소 1개 이상 담아주세요.", HttpStatus.BAD_REQUEST);
} else if(!cartService.validateCartItem(cartItemId, principal.getName())) {
return new ResponseEntity<String>("수정 권한이 없습니다.", HttpStatus.FORBIDDEN);
}
cartService.updateCartItemCount(cartItemId, count);
return new ResponseEntity<Long>(cartItemId, HttpStatus.OK);
}
'Web & Android > 스프링 부트 쇼핑몰 프로젝트 with JPA' 카테고리의 다른 글
[스프링 부트 쇼핑몰 프로젝트 with JPA] 17-1. 게시판 - Entity (1) | 2023.10.16 |
---|---|
[스프링 부트 쇼핑몰 프로젝트 with JPA] 16.장바구니 상품 삭제 & 주문 (0) | 2023.10.16 |
[스프링 부트 쇼핑몰 프로젝트 with JPA] 14. 장바구니 담기 (0) | 2023.10.16 |
[스프링 부트 쇼핑몰 프로젝트 with JPA] 13. 주문 취소 (0) | 2023.10.16 |
[스프링 부트 쇼핑몰 프로젝트 with JPA] 12. 구매 내역 조회 (0) | 2023.10.16 |