저번 시간에 장바구니 등록기능을 만들어보았고 이번에는 장바구니에 들어있는 내용을 확인할 수 있는 html을 만들어주고 장바구니에 들어있는 상품을 제거하는 API를 만들어보자
제일 먼저 장바구니에 들어있는 상품들을 보여주는 html을 설계해보자!
package com.qkrtprjs.happyexercise.dto;
import com.qkrtprjs.happyexercise.entitiy.member.Member;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@NoArgsConstructor
@Getter
public class CartResponseDto {
private Long id;
private int price;
private MemberResponseDto memberResponseDto;
@Builder
public CartResponseDto(Long id, int price, MemberResponseDto memberResponseDto) {
this.id = id;
this.price = price;
this.memberResponseDto = memberResponseDto;
}
}
package com.qkrtprjs.happyexercise.dto;
import com.qkrtprjs.happyexercise.entitiy.BaseTimeEntity;
import com.qkrtprjs.happyexercise.entitiy.cart.Cart;
import com.qkrtprjs.happyexercise.entitiy.cart.CartItem;
import com.qkrtprjs.happyexercise.entitiy.item.Item;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Getter
@NoArgsConstructor
public class CartItemResponseDto {
private Long id;
private int count;
private CartResponseDto cartResponseDto;
private ItemResponseDto itemResponseDto;
@Builder
public CartItemResponseDto(Long id, int count, CartResponseDto cartResponseDto, ItemResponseDto itemResponseDto) {
this.id = id;
this.count = count;
this.cartResponseDto = cartResponseDto;
this.itemResponseDto = itemResponseDto;
}
}
public List<CartItemResponseDto> findByMember(SessionMember sessionMember) {
Member member = memberRepository.findByEmail(sessionMember.getEmail()).orElseThrow(() -> new IllegalArgumentException("해당 이메일은 존재하지 않습니다!"));
Cart cart = cartRepository.findByMember(member).orElseThrow(() -> new IllegalArgumentException("해당 member 값은 존재하지않습니다!"));
return cartItemRepository.findByCart(cart).stream().map(cartItem -> CartItem.toDto(cartItem)).collect(Collectors.toList());
}
public CartResponseDto findByMember(SessionMember sessionMember) {
Member member = memberRepository.findByEmail(sessionMember.getEmail()).orElseThrow(() -> new IllegalArgumentException("해당 이메일은 존재하지않습니다!"));
Cart cart = cartRepository.findByMember(member).orElseThrow(() -> new IllegalArgumentException("해당 member는 존재하지않습니다!"));
return Cart.toDto(cart);
}
@GetMapping("/cartDetail")
private String cartDetail(Model model, @LoginMember SessionMember sessionMember) {
List<CartItemResponseDto> cartItemResponseDtoList = cartItemService.findByMember(sessionMember);
CartResponseDto cartResponseDto = cartService.findByMember(sessionMember);
model.addAttribute("cartItemList", cartItemResponseDtoList);
model.addAttribute("cart", cartResponseDto);
return "cart/cartDetail";
}
장바구니에 들어있는 총 금액을 알 수 있는 기능도 추가하기위해서 Entity 수정
package com.qkrtprjs.happyexercise.entitiy.cart;
import com.qkrtprjs.happyexercise.dto.CartResponseDto;
import com.qkrtprjs.happyexercise.entitiy.BaseTimeEntity;
import com.qkrtprjs.happyexercise.entitiy.member.Member;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Getter
@NoArgsConstructor
@Entity
public class Cart extends BaseTimeEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Long id;
private int price; //수정된 부분
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "memberId")
private Member member;
@Builder
public Cart(int price,Member member) {
this.price = price;
this.member = member;
}
public static CartResponseDto toDto(Cart cart) {
return CartResponseDto.builder()
.id(cart.getId())
.price(cart.getPrice())
.memberResponseDto(Member.toDto(cart.getMember()))
.build();
}
public void sumPrice(int price) {
this.price += price;
}
}
public void sumPrice(int price) {
this.price += price;
}
@Transactional
public Long save(Item item, int count, Member member) {
//장바구니가 존재하는지 확인
if (!cartRepository.findByMember(member).isPresent()) {
cartRepository.save(
Cart.builder()
.price(0)
.member(member)
.build()
);
}
Cart cart = cartRepository.findByMember(member).orElseThrow(() -> new IllegalArgumentException("해당 member 값은 존재하지않습니다!"));
cart.sumPrice(count * item.getPrice()); //추가된 부분!
return cartItemRepository.save(CartItem.builder()
.count(count)
.item(item)
.cart(cart)
.build()).getId();
}
<!DOCTYPE html>
<html xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/default_layout}">
<div layout:fragment="content">
<div class="container mt-3">
<h2>내 장바구니 보기</h2>
<br>
<table class="table">
<thead>
<tr>
<th>상품명</th>
<th>개당 가격</th>
<th>개수</th>
<th>가격</th>
</tr>
</thead>
<tbody>
<th:block th:each="cartItem:${cartItemList}">
<tr>
<td th:text="${cartItem.itemResponseDto.name}"></td>
<td th:text="${cartItem.itemResponseDto.price}"></td>
<td th:text="${cartItem.count}"></td>
<td th:text="${cartItem.itemResponseDto.price*cartItem.count}"></td>
</tr>
</th:block>
</tbody>
</table>
<br>
<div class="mb-3">
<label for="orderPrice">총 주문 금액:</label>
<input type="text" class="form-control" id="orderPrice" th:value="${cart.price}" name="orderPrice" readonly>
</div>
</div>
</div>
</html>
정상적으로 데이터를 불러오는 것을 확인했기때문에 장바구니에서 상품을 삭제하는 기능을 추가해보자!
과정
- 버튼 추가
- 버튼에 id 값을 전달할 수 있는 속성 추가
- id값을 js파일로 들고와서 ajax통신에 전달
- 해당 컨트롤러로 id 값을 받아주고 서비스로 전달
- 서비스에서 id값을 통한 CartItem 삭제 및 Cart의 총 가격 수정
<table class="table">
<thead>
<tr>
<th>상품명</th>
<th>개당 가격</th>
<th>개수</th>
<th>가격</th>
<th></th>
</tr>
</thead>
<tbody>
<th:block th:each="cartItem:${cartItemList}">
<tr>
<td th:text="${cartItem.itemResponseDto.name}"></td>
<td th:text="${cartItem.itemResponseDto.price}"></td>
<td th:text="${cartItem.count}"></td>
<td th:text="${cartItem.itemResponseDto.price*cartItem.count}"></td>
<td><button th:cartItemId="${cartItem.id}" type="button" class="btn btn-danger" name="cartItemDelete-btn">삭제</button></td>
</tr>
</th:block>
</tbody>
</table>
$("[name=cartItemDelete-btn]").on('click',function (){
let id = this.getAttribute("cartItemId");
if (confirm("해당 상품을 장바구니에서 삭제하시겠습니까?")) {
_this.deleteCartItem(id);
}else{
alert("취소되었습니다!");
}
});
deleteCartItem: function (id) {
$.ajax({
url: '/api/cartItem/'+id ,
method: 'DELETE',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
}).done(function () {
alert("상품이 장바구니에서 삭제되었습니다!");
location.href = '/cartDetail';
}).fail(function (error) {
alert(JSON.stringify(error));
});
},
@DeleteMapping("/api/cartItem/{id}")
private Long delete(@PathVariable Long id) {
cartItemService.delete(id);
return id;
}
@Transactional
public void delete(Long id) {
CartItem cartItem = cartItemRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("해당 id는 존재하지않습니다!"));
//장바구니 가격 수정
Cart cart = cartItem.getCart();
cart.deleteItem(cartItem);
cartItemRepository.delete(cartItem);
}
public void deleteItem(CartItem cartItem) {
this.price -= cartItem.getItem().getPrice()*cartItem.getCount();
}
장바구니에 가격을 추가하고 수정하는 부분에 있어서 가격이라는 민감한 부분에 대해서 해당 함수들은 더해주거나 빼주는 너무 1차원적인 단순한 로직으로 구현되어있다는게 불안하지만 더 공부하면서 이런 금액적인 부분에서는 다른 플랫폼들이나 다른 개발자분들은 어떻게 처리하는지 공부하자.
그럼 다음에 이어서 장바구니에 들어있는 상품들을 한번에 주문하는 기능을 추가해보자