D+79::SHOP_상품구매후 장바구니 삭제(트랜잭션),단일구매

Am.Vinch·2022년 10월 24일
0

20221020_thu

실습내용

  • 1.구매할 상품은 장바구니에서 삭제되어야한다.
  • 2.단일 구매
    : 상품상세정보페이지에서 구매버튼 클릭시 바로 구매되도록 만들기.
    : 구매버튼 클릭시, 바로 구매되는 것이 아니라, buyInfo.html페이지로 바로 이동해야한다.
    : 상품상세페이지에서 구매버튼 클릭시, 'item_code','수량'만 들고오도록 한다.
  • 3.메뉴 나오기
  • 4.주문내역 조회
    : 장바구니 옆에 구매내역 이라는 글자를 넣어라.
    : 장바구니 목록 -> 내정보관리 로 변경하라.
    : side메뉴에는 내정보관리(장바구니 목록,내정보수정,구매내역조회) 만들도록하라.
  • 5.매출관리

BuyController

	@PostMapping("/insertBuy")
	public String buyCart(String[] cartCodes, BuyVO buyVO,CartVO cartVO,Authentication authentication) {
		//totalPrice,itemCode(들),수량(들) -> 데이터를 가져와야한다.
		// 하지만!! cartCode(들)만 들고오면 위에 데이터들도 따라오게할 수 있다!!!
		// cart테이블에가면 아이템코드 수량, 토탈프라이스 모두 있기때문에 cartCode만 알면 연결되 나머지 데이터들을 들고올 수 있다.
		// cartCode(들)을 들고오는 방법은?

		System.out.println("!@!!!!!!!!!!!!!!!!!!!@@@@" + cartCodes);// 콘솔확인시, CART_004,CART_007 -> 자스를 사용하지않아도 이런 식으로 데이터를 들고온다.
		// 매개변수에서부터 배열 자료형으로 받으면(String[] cartCodes), 굳이 위에처럼 ,쉼표로 문자열을 자를 필요가 없다.
		//for문을 돌려 하나씩빼서 콘솔 출력한다.
		for(String e : cartCodes) {
			System.out.println("@@@@@@@@@@@@@@@@@@@ " + e);
		}
		
		// buy_code 데이터 들고오기 : insert되어야하는 buy_code 조회
		String buyCode = buyService.selectNextBuyCode();
		
		//totalPrice,itemCode(들),cartAmount(들) 데이터는 어떻게 들고오냐
			//위에 알고있는 cartCode를 이용해서 위 데이터를 쿼리문을 통해 가져온다. -> buy-mapper에서 만들어주기.
			// 우리가 들고온 cartCode들을 cartVO에 넣어줘야한다.
			// 이미 cartVo에는 리스트형태로 cartCodeList가 있는데, 이를 배열의 형태로 바꾸어 넣어준다.
		
		//List<String> cartCodeList = Arrays.asList(cartCodes);
		cartVO.setCartCodeList(Arrays.asList(cartCodes));
		List<CartVO> cartList = buyService.getCartInfoForBuy(cartVO);
		List<BuyDetailVO> buyDetailList = new ArrayList<>(); //아래 데이터 넣기위해서 미리 통만들기(변수선언)
		//반복해서 itemCode와 amount값,totalPrice값 모두 for문돌려서 하나씩  빼기
		int totalPrice =0;
		for(CartVO cart : cartList) {
			totalPrice = totalPrice + cart.getTotalPrice();
			//아래처럼 만들어준 것을 위에 buydetailList 통에 넣어준다.
			BuyDetailVO vo = new BuyDetailVO();
			vo.setItemCode(cart.getItemCode());
			vo.setBuyAmount(cart.getCartAmount());
			buyDetailList.add(vo);
		}
		
		//memberID 데이터가져오기
		User user = (User)authentication.getPrincipal();
		
		// 위에서 부터 가져온 모든 데이터들을 BuyVO에서 setter를 이용해 데이터 넣어주기
		buyVO.setBuyCode(buyCode);
		buyVO.setMemberId(user.getUsername());
		buyVO.setTotalPrice(totalPrice);
		buyVO.setBuyDetailList(buyDetailList);// buyDetailVO 에서 itemCode,cartAmount값 가져오기.
		
		//실제 구매실행 쿼리문 + (상품 구매 후)장바구니삭제
		buyService.insertBuy(buyVO,cartVO);
		// !! 주의 !! 
		// 구매한 장바구니는 목록에서 삭제-> 한줄만 아래처럼 추가하면 트랜잭션 처리 안됨
		//cartService.deleteCarts(cartVO);
		
		return "content/buy/buy_list";//구매내역페이지
	}

BuyService

package Kh.study.shop.buy.service;
public interface BuyService {
	//구매등록
	void insertBuy(BuyVO buyVO,CartVO cartVO);

BuyServiceImpl

@Transactional(rollbackFor = Exception.class)//어떤 오류든 간에 뭐든지 롤백하겠다.
	@Override
	public void insertBuy(BuyVO buyVO,CartVO cartVO) {
		sqlSession.insert("buyMapper.insertBuy",buyVO);
		sqlSession.insert("buyMapper.insertBuyDetail",buyVO);
		sqlSession.delete("cartMapper.deleteCarts",cartVO);
	}

단일 구매

  • 단일구매하기
    : 상품상세페이지에서 구매버튼 클릭시, 'item_code','수량'만 들고오도록 한다.
    : 구매를 누르면 상품상세조회하는 쿼리문을 띄운다.
    방법은 두 가지가 있다.
  • 1) 상세페이지의 '구매'버튼에 form태그로 가져갈 데이터 모두 감싸서 보내주도록 한다.
  • 2) 구매버튼누르면 form태그가 실행되도록 버튼form태그 위에 수량이라는 input태그를 감싸지 않은 채로 보내도록한다.눈에 보기좋게 자바스크립트안에 있는 데이터를 넣어줘서 보내기. -> 우리가 할 방법!!

controller

  • BuyController
// 단일구매(상세페이지에서 바로구매 클릭시)
	@PostMapping("/buyInfoDirect")
	public String buyInfoDirect(String itemCode, int buyAmount,Model model,Authentication authentication) {// VO로 매개변수받아도 되지만, 그냥 단순히 필요한 두개의 데이터만 매개변수로 받았다.
		model.addAttribute("item",itemService.selectDetailItem(itemCode));//이전에 만든 itemServiceImpl의 상세정보를 들고온다.
		model.addAttribute("buyAmount",buyAmount);//자스를 통해 매개변수로 들고온데이터 그대로 보낸다
		User user = (User)authentication.getPrincipal();
		model.addAttribute("memberVO",memberService.selectMemberInfo(user.getUsername()));//구매자정보조회
		
		return "content/buy/buy_info";
	}

js

  • detail_item.js
//[함수 ] (단일구매)상세페이지에서 바로 구매 버튼 클릭 시 진행되는 함수
function buy(){
	//실제 입력한 수량값 선택
	const buyAmount = document.querySelector('#cartAmount').value;
	// 우리가 hidden으로 데려갈 input태그에 실제 입력 수량값 넣어주기
	document.querySelector('#buyAmountInput').value = buyAmount;
	// 서브밋 시키기
	document.querySelector('#buyForm').submit();
}

html

👀주의할점👀
: html에서 이미지리스트를 넘길때 그냥 imgList[0]로 넘기면 is_main = 'Y'라는 쿼리문을 상품상세조회 쿼리문 조건절에 없기때문에 이렇게 사용하면, 상세이미지가 나온다.
: 그래서 메인이미지가 출력되도록하려면 저번처럼 th:block태그를 사용해서 반복문을 돌린 후,forecah로 하나씩 빼주어야한다.
: 컨트롤러에서 던져진 item이라는 itemVO의 imgList를 하나씩 빼는데 그 중 img라는 이름의 img정보 하나씩 뺀다. 그 중 is_main이 'Y'값이면, img의 attachedName만을 추출하면된다.

  • buy_info.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
	xmlns:layout="http://www.ultra.net.nz/thymeleaf/layout" 
	layout:decorate="~{layout/base_layout}"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
	
<div layout:fragment="content">
<div class="row mt-4">
<!-- 좌측 -->
<div class="col-7">
	<!-- 제목줄 -->
	<div class="row mb-5">
		<div class="col">
			 <h2>✔ ORDER </h2>
		 </div>
	</div>
	<!-- 구매할  장바구니 목록 영역 -->
	<div class="row mb-3">
		<div class="col">
			<table class="table table-hover">
			<colgroup>
				<col width="10%" >
				<col width="25%" >
				<col width="25%" >
				<col width="20%" >
				<col width="20%" >
			</colgroup>	
				<thead style="font-size: 20px; font-weight: bold; color: #425F57;">
					<tr >
						<!-- <td >
							(1)리스트 값 null인지 아는 방법 
							장바구니에서 선택구매했을 때
							<th:block th:if="${buyingList != null}">No.</th:block>
							단일구매로 상세페이지에서 바로 구매했을 때
							<th:block th:if="${buyingList == null}">✔</th:block>
							(2)리스트 값 null인지 아는 방법 
							리스트의 값이 비어있는지 -> true/false값으로 출력
							[[${#lists.isEmpty(buyingList)}]]
						</td> -->
						<td>No.</td>
						<td style="text-align: center;">상품명</td>
						<td>상품이미지</td>
						<td>가격</td>
						<td>수량</td>
					</tr>
				</thead>

				
				<tbody>
					<!-- 장바구니에서 선택구매 했을 때 -->
					<th:block th:if="${#lists.isEmpty(buyingList)}"><!-- if는 true값이라면 아래 데이터 보여주는 것! -->
					<tr>
						<td>#</td>
						<!-- 단, 쿼리문에서 is_main값 y인것만 뽑으라고 안했기때문에 반복문돌려야한다. -->
						<td>
						<th:block th:each="img : ${item.imgList}"><!-- item하나에는 여러개의 이미지리스트가 있다. 그 중 하나의 이미지정보를 img 뺐을 때 -->
							<th:block th:if="${img.isMain eq 'Y'}">
								<img  width="100px;" height="140px;" th:src="|@{/images/}${img.attachedName}|">
							</th:block>
						</th:block>
						</td>
						<td>[[${item.itemName}]]</td>
						<td>[[${item.itemPrice}]]</td>
						<td>[[${buyAmount}]]</td>
					</tr>
					</th:block >
					<!-- 상세페이지에서 바로 구매했을 때(단일구매) -->
					<th:block th:unless="${#lists.isEmpty(buyingList)}"><!-- th:uless는 false값이면 데이터 보여주겠다. -->
						<tr th:each="buy : ${buyingList}"><!-- buy 자료형은 cartVO -->
							<td><span th:text="${#lists.size(buyingList) - buyStat.index}"></span> </td>
							<!-- 다른방법 상품명불러오기 : ${buy.itemVO.itemName} -->
							<td><span th:text=" ${buy.itemName}" ></span> </td>
							<!-- 다른방법 이미지 불러오기 : th:src="|@{/images/}${buy.itmeVO.imgList[0].attachedName}|" -->
							<td><img  width="100px;" height="140px;" th:src="|@{/images/}${buy.attachedName}|"></td>
							<!-- 다른방법 가격불러오기 : [[${buy.itemVO.itemPrice}]]  -->
							<td><span th:text=" ${#numbers.formatCurrency(buy.itemPrice)}" ></span> </td>
							<td><span th:text=" ${buy.cartAmount}" ></span> </td>
						</tr>
					</th:block>
				</tbody>
			</table>
		</div>
	</div> 
</div>


<!-- 우측 -->
<div class="col-5">
	<!-- 제목줄 영역 -->
	<div class="row mb-5">
		<div class="col">
			 <h2>✔ MEMBER INFO</h2>
		 </div>
	</div>	
		
	<!-- 주문자 정보 영역 -->
	<div class="row  mb-3">
		<div class="col">
		 <table class="table">
		  <thead>
		    <tr>
		      <th scope="col">
			     <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check2-circle" viewBox="0 0 16 16">
				  <path d="M2.5 8a5.5 5.5 0 0 1 8.25-4.764.5.5 0 0 0 .5-.866A6.5 6.5 0 1 0 14.5 8a.5.5 0 0 0-1 0 5.5 5.5 0 1 1-11 0z"/>
				  <path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l7-7z"/>
			   </svg> Detail
		      </th>
		       <th scope="row">
		        </th>
		   </tr>
		   <tr> 
		   <th scope="col">ID</th>
		    <td th:text="${#authentication.name}"></td>
		   </tr>
		   <tr>
		    <th scope="col">이름</th>
		     <td th:text="${memberVO.memberName}"></td></tr>
		   <tr>
		     <th scope="col">E-Mail</th>
		      <td th:text="${memberVO.memberEmail}"></td></tr>
		   <tr>
		     <th scope="col">주소</th>
		     <td th:text="${memberVO.memberAddr}"></td>
		     </tr>
		  </thead>
		  <tbody class="table-group-divider">
		  </tbody>
		</table>
		</div>
	</div>
	<div class="row">
		<div align="center" class="col-7">
			<div  class="input-group mb-3  " >
				  <span class="input-group-text" id="inputGroup-sizing-default"> 총가격 </span>
				  <span id="finalPriceTag" style="text-align: right;" th:data-total-price="${finalPrice}"   th:text=" ${#numbers.formatCurrency(finalPrice)}"  class="form-control" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-default"></span>
			</div>
		</div>
		<div align="center" class="col-5">
			<form th:action="@{/buy/insertBuy}" method="post" >
				<!-- 여기 목록조회에서 cartCode를 사용하려면 목록조회 쿼리문에 조회컬럼 추가하기! CART_CODE -->
				<!-- 체크박스때문에 체크된 상품만 가져와야해서 for문으로 문자열잘라야하는 cart_list와 달리 자바스크립트 사용하지 않고 한번에 보낼수있기때문에 사용! -->
				<th:block th:each="buy : ${buyingList}" >
					<input type="hidden" name="cartCodes" th:value="${buy.cartCode}"><!-- 구매하기 버튼클릭시 cartCodes라는 이름으로 데이터 가져간다. -> 컨트롤러가서 받기. -->
				</th:block>
				<button type="submit" class="btn btn-outline-success">구매하기</button>
			</form>
		</div>
	</div>
</div>
</div>
</div>
</html>

레이아웃 수정

  • 장바구니 목록 -> 내정보관리 로 변경하라.
  • side메뉴에는 내정보관리(장바구니 목록,내정보수정,구매내역조회) 만들도록하라.

단일구매 실제 DB SHOP_BUY테이블 insert 시키기

  • itemCode, itemPrice,buyAmount 총 세가지 데이터를 가져가야한다!
  1. buy_info.html에서 주문하기 버튼 form태그 경로 설정 수정하기.
    : th:attr="" 새로운 타임리프 속성값 사용하기
  2. 컨트롤러에서 새롭게 단일구매 메소드 생성
  3. 쿼리문에서 insertBuy 미리만든것 알아보기
profile
Dev.Vinch

0개의 댓글