Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

게으른 완벽주의자의 개발자 도전기

[shop] 장바구니에서 구매하기 구현 본문

Spring Boot

[shop] 장바구니에서 구매하기 구현

머리방울 2022. 10. 23. 17:46

장바구니에서 선택 구매 후 구매확정을 위한 화면을 구현하고자 한다.

구매확정 시 

장바구니에서 구매했다면 구매 테이블과 구매상세테이블에 데이터가 들어간 후

장바구니에 담겨 있던 상품들은 삭제되도록 mapper를 구성한다

또한, 단일구매의 경우 장바구니에 담겼던 것이 아니기 때문에

장바구니 상품삭제는 필요하지 않기 때문에 if로 두가지 케이스를 구분하여 

구현되도록 하고자 한다.

 

1. mapper

<mapper namespace="buyMapper">

<resultMap type="kh.study.shop.buy.vo.BuyVO" id="buy">
<id column="BUY_CODE" property="buyCode"/>
<result column="MEMBER_ID" property="memberId"/>
<result column="BUY_DATE" property="buyDate"/>
<result column="TOTAL_PRICE" property="totalPrice"/>
<result column="BUY_CNT" property="buyCnt"/>

<collection property="buyDetailList" resultMap="buyDetail"/>

</resultMap>

<resultMap type="kh.study.shop.buy.vo.BuyDetailVO" id="buyDetail">
<id column="BUY_DETAIL_CODE" property="buyDetailCode"/>
<result column="ITEM_CODE" property="itemCode"/>
<result column="BUY_CODE" property="buyCode"/>
<result column="BUY_AMOUNT" property="buyAmount"/>
<result column="BUY_PRICE" property="buyPrice"/>

<association property="itemInfo" resultMap="itemMapper.item"/>

</resultMap>

선택 구매하기 (shop_buy 테이블에 데이터 넣기)
<insert id="cartBuy">
INSERT INTO SHOP_BUY(
        BUY_CODE
      , MEMBER_ID
      , TOTAL_PRICE
        )VALUES(
       #{buyCode}
     , #{memberId}
     , #{totalPrice} 
)
</insert>

buy_detail에 데이터 넣기
<insert id="cartBuyDetail">
INSERT INTO SHOP_BUY_DETAIL (
      BUY_DETAIL_CODE
    , ITEM_CODE
    , BUY_CODE
    , BUY_AMOUNT
)

<foreach collection="buyDetailList" item="BuyDetailVO" separator="UNION ALL" index="status">
    SELECT #{buyCode}||'_'||LPAD(#{status} + 1, 2, 0)
         , #{BuyDetailVO.itemCode}
         , #{buyCode}	
         , #{BuyDetailVO.buyAmount} 
    FROM DUAL
</foreach>

</insert>

선택 구매한 CART_CODE가 cart_001, cart_002인 장바구니 데이터의 조회
<select id="cartBuyInfo" resultMap="cartMapper.cart">
SELECT ITEM_CODE
    , CART_AMOUNT
    , TOTAL_PRICE
FROM SHOP_CART
WHERE CART_CODE IN
<foreach collection="cartCodeList" item="cartCode" open="(" close=")" separator=",">
#{cartCode}
</foreach>

</select>

다음에 들어갈 buyCode
<select id="buyCode" resultType="String">
	SELECT 'BUY_' || LPAD(NVL(MAX(TO_NUMBER(SUBSTR(BUY_CODE, 5))), 0) +1, 3, 0)
	FROM SHOP_BUY
</select>
장바구니 구매확정
@Override
@Transactional(rollbackFor = Exception.class)
public void buyCart(BuyVO buyVO, CartVO cartVO) {

    sqlSession.insert("buyMapper.cartBuy", buyVO);
    sqlSession.insert("buyMapper.cartBuyDetail", buyVO);

    단일구매 확정을 클릭했을 때는 구현되지 않도록 설정
    if(cartVO != null) {
        sqlSession.delete("cartMapper.deleteCart", cartVO);
    }

}

buyCode 가져오기
@Override
public String buyCode() {

    return sqlSession.selectOne("buyMapper.buyCode");
}

장바구니 데이터의 조회
@Override
public List<CartVO> cartBuyInfo(CartVO cartVO) {

    return sqlSession.selectList("buyMapper.cartBuyInfo", cartVO);
}

2. controller

buyInfo에서 구매확정 클릭 
(totalPrice, itemCode, cartAmount 데이터 필요해-> cartCode만 가져오면 해결)
@PostMapping("/buyCart")
public String buyCart(CartVO cartVO, BuyVO buyVO, String[] cartCodes
                    , Authentication authentication
                    , ArrayList<BuyDetailVO> buyDetailList) {

    insert 되어야 하는 buyCode 조회
    String buyCode = buyService.buyCode();

    totalPrice, itemCode들, cartAmount들
    List<String> cartCodeList = Arrays.asList(cartCodes);
    cartVO.setCartCodeList(cartCodeList);
	
    장바구니에 담았던 목록
    List<CartVO> cartList = buyService.cartBuyInfo(cartVO);

    memberId
    User user = (User)authentication.getPrincipal();
    String memberId = user.getUsername();

    totalPrice
    int totalPrice = 0;
    for(CartVO e : cartList) {
         totalPrice = totalPrice +e.getTotalPrice();

         새로운 통 만들어 줘야 함 (buy_001_01,buy_001_02 이런식으로 데이터 들어가니까)
         BuyDetailVO vo = new BuyDetailVO();
         vo.setItemCode(e.getItemCode());
         vo.setBuyAmount(e.getCartAmount());

         buyDetailList.add(vo);

    }

    buyVO (buyVODetail도 같이 사용)
    buyVO.setBuyCode(buyCode);
    buyVO.setMemberId(memberId);
    buyVO.setTotalPrice(totalPrice);
    buyVO.setBuyDetailList(buyDetailList);	//buyDetailVO -> itemCode, cartAmount

    쿼리 실행
    buyService.buyCart(buyVO,cartVO);

    return "redirect:/item/list";

}

3. html (th:attr 사용하기)

<div class="row justify-content-center mt-3">
<div class="col-10 mb-5">
<h4>구매 상품 정보</h4>

 <table class="table align-middle">
  <colgroup>
     <col width="10%">
     <col width="30%">
     <col width="30%">
     <col width="15%">
     <col width="15%">
  </colgroup>

  <thead>
     <tr>
        <td>No</td>
        <td colspan="2">상품정보</td>
        <td>수량</td>
        <td>가격</td>
     </tr>
  </thead>
  <tbody>
  <!-- 단일상품 구매하기  -->
   <th:block th:if="${#lists.isEmpty(cartInfo)}">
    <tr>
        <td>1</td>
        <td><img th:src="|@{/image/}${item.imgList[0].attachedName}|" 
        	width="100px" height="100px"></td>
        <td th:text="${item.itemName}"></td>
        <td th:text="${buyAmount}"></td>
        <td th:text="${#numbers.formatCurrency(item.itemPrice)}"></td>
    </tr>
   </th:block>
  <!-- 장바구니에서 구매하기 -->
   <th:block th:unless="${#lists.isEmpty(cartInfo)}">
         <tr th:each="cart, status :${cartInfo}">
            <td th:text="${#lists.size(cartInfo) - status.index}"></td>
            <td><img th:src="|@{/image/}${cart.itemList.imgList[0].attachedName}|" 
            	width="100px" height="100px"></td> 
            <td th:text="${cart.itemList.itemName}"></td>
            <td th:text="${cart.cartAmount}"></td>
            <td th:text="${#numbers.formatCurrency(cart.itemList.itemPrice)}"></td>
         </tr>
   </th:block>
  </tbody>
 </table>


 <div class="row mt-4" >
  <div class="col-12 mb-3">
     <div class="row">
        <div class="offset-9 col-1 text-center" style=" height: 2.5rem;
        	font-size: 1.3rem; padding-top: 0.2rem; border-bottom: 1.5px solid; color: block;">
           총 가격
        </div>
        <div class="col-2 text-end" style="border-bottom: 1.5px solid; padding-top: 0.2rem; 
        	height: 2.5rem; font-size: 1.2rem;">
           <span th:text="${#numbers.formatCurrency(totalPrice)}" 
           	th:data-total-price="${totalPrice}"> </span>
        </div>
     </div>
 </div>
 </div>


<div class="row justify-content-center mt-4">
    <h4>주문자 정보</h4>
<div class="col-12 mt-4">
<table class="table" style="text-align: left;">
<colgroup>
    <col width="10%">
    <col width="90%">
</colgroup>

<tbody id="detail">
    <tr>
        <th>회원ID</th>
        <td th:text="${memberInfo.memberId}"></td>
     </tr>
    <tr>
        <th>회원이름</th> 
        <td th:text="${memberInfo.memberName}"></td>
    </tr>
    <tr> 
        <th>주소</th> 
         <td th:text="${memberInfo.memberAddr}"></td> 
    </tr> 
    <tr>
        <th>연락처</th> 
        <td th:text="${memberInfo.memberEmail}"></td>
    </tr>

</tbody>
</table>

 <div class="row mt-4 mb-4" style="text-align: center;">

     <div class="col-12">
    <!--  <form th:action="@{/buy/buyCart}" method="post"> -->
    <form th:attr="action=${#lists.isEmpty(cartInfo) ? '/buy/directBuy' : '/buy/buyCart'}" method="post" >

     <!-- 체크박스가 없기 때문에 아래와 같이 사용 가능 -->
    <th:block th:unless="${#lists.isEmpty(cartInfo)}">
        <th:block th:each="cart : ${cartInfo}">
            <input type="hidden" name="cartCodes" th:value="${cart.cartCode}">
        </th:block>
    </th:block>

     <!-- 상세페이지에서 구매하기 -> 구매확정 -->
    <th:block th:if="${#lists.isEmpty(cartInfo)}">
        <input type="hidden" name="itemCode" th:value="${item.itemCode}">
        <input type="hidden" name="buyAmount" th:value="${buyAmount}">
        <input type="hidden" name="totalPrice" th:value="${totalPrice}">
    </th:block>

        <button type="submit" class="btn btn-outline-dark" id="finalBuyBtn" >
        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box2-heart" viewBox="0 0 16 16">
        <path d="M8 7.982C9.664 6.309 13.825 9.236 8 13 2.175 9.236 6.336 6.31 8 7.982Z"/>
        <path d="M3.75 0a1 1 0 0 0-.8.4L.1 4.2a.5.5 0 0 0-.1.3V15a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1V4.5a.5.5 0 0 0-.1-.3L13.05.4a1 
        	1 0 0 0-.8-.4h-8.5Zm0 1H7.5v3h-6l2.25-3ZM8.5 4V1h3.75l2.25 3h-6ZM15 5v10H1V5h14Z"/>
        </svg> 구매확정 </button>
     </form>
    </div>
 </div>

 </div>
 </div>

</div>
</div>