D+80::SHOP_메뉴,상품(구매)주문내역조회,매출관리

Am.Vinch·2022년 10월 24일
0

20221021_fri

실습내용

    1. 메뉴나오기
    1. 주문내역조회
    1. 매출관리

사이드 메뉴

  • 메뉴나오기

    • base_layout.html
    • admin_layout.html
    • (추가) myInfo_layout.html
      : 기존의 레이아웃을 사용할것인가, admin레이아웃처럼 새로운 레이아웃을 만들것인가 두가지방법이있다.

순서

  • 1) 새로운 레이아웃 파일을 생성 버전.
  1. top.html에서 장바구니였던 버튼을 my Info(내정보관리)버튼으로 바꾼다.
    : 로그인인증한 회원만 들어가기때문에 myInfo_layout.html 레이아웃을 새로 만들어 메뉴 사이드바를 만든다.
  2. 새로만든 myInfo_layout파일에서 fragment를 수정해야한다.
  3. 그리고 사이드메뉴 myinfo_side.html 도 다시만든 후, 변경해야한다.

  • 2) 기존의 레이아웃 수정하는 버전
  1. myInfo_layout.html파일을 따로 만들지 않고 기존에 있던 side.html과 cart_list.html파일만 수정해도 가능하다.

주문내역조회

  • 아코디언(accordion) 부트스트랩 사용하기
    <예시>
    No 구매요약
    3 2022-10-10 22:10:10 에 총 3건의 주문으로 30,000원을 구매했습니다.
    No 상품정보(대표이미지,카테,이름) 가격 수량 총가격
    1. 이미지 [카테명]상품명 10,000 2 20,000
    2. 이미지 [카테명]상품명 10,000 2 20,000

2 2022-10-10 22:10:10 에 총 3건의 주문으로 30,000원을 구매했습니다.
1 2022-10-10 22:10:10 에 총 3건의 주문으로 30,000원을 구매했습니다.

  • buy-mapper
    : 아코디언 제목줄 구매내역 조회 쿼리문 _ 서브쿼리 사용
<!-- 아코디언 제목줄 구매내역 조회 + 전체줄 구매내역 조회 같이 -->
	<!-- 뽑아야하는 데이터 : 2022-10-10 22:10:10 에 총 3건의 주문으로 30,000원을 구매했습니다. -->	
		<select id="selecteBuy" resultMap="buyMapper.buy"><!-- 기존에 있던 cart매퍼를 사용한다. -->
			SELECT BUY_CODE 
					, TO_CHAR(BUY_DATE, 'YYYY-MM-DD HH24:MI:SS') BUY_DATE
					, TOTAL_PRICE
					, (SELECT COUNT(BUY_DETAIL_CODE) 
						FROM SHOP_BUY_DETAIL 
						WHERE BUY_CODE  = B.BUY_CODE ) as BUY_CNT <!-- buy테이블이랑 buyDetail테이블 buycode와 같으면! -->
			FROM SHOP_BUY B
			where MEMBER_ID = #{memberId}
			order by BUY_CODE DESC
		</select>	

주문내역 조회시 쿼리 결과 주의사항

  • 구매내역 전체 목록조회 쿼리 결과
    : 구매날짜시간에 따라서 시간이 동일하게 구매가 된 것은 같은 상품코드이며, 시간이 다르게 표시된 것은 다르게 구매가 된 것이다.
    : 이걸로 구매목록을 테이블 데이터 뿌려줄 때, 잘 생각하고 결과를 뿌려줘야한다!!!
    : 그래서 구매날짜시간이 동일한 코드는 buyVO 3개를 가진 하나의 buyList로 가져온다. 구매날짜시간이 다른 것은 buyVO 한개로 상품정보와 상세정보를 가져온것과 같다.

  • 쿼리문 작성 후, 쿼리 실행결과데이터를 자바로 가져오려면
    resultMap 을 사용하면 된다!!!
  • 1번 구매로 상품을 다수 여러개를 할 수 있다.
    shop_buy : shop_buy_detail -> 1:N 관계니까 collection 사용해야한다.

주문(구매) 2번한다고 했을 때, BuyVO로 총 2개(1번,2번)의 데이터를 들고온다.
: 구매목록조회 테이블 작성시,
1번.BuyVO-> a상품 3개 -> 이상품의 상세정보는 buyDetailList안에 있다.
2번.BuyVO-> a상품 1개,b상품 2개 c상품 1개...

buyList의 BuyVO값을 어떻게 잘 들고왔는지 확인해보자

: 이후 null값이 아닌 확인된 값이 있다면 이를 buy_list.html파일에 바로 데이터를 뿌려서 확인한다.

  • 콘솔창
BuyVO
(buyCode=BUY_007, 
memberId=null, 
buyDate=2022-10-20 16:54:09, 
totalPrice=32000, 
buyCnt=2, 
cateName=소설, 
itemName=이국에서, 
itemPrice=16000, 
attachedName=1bb400e3-67d1-4d9d-b6ee-0c714ac9fa61.jpg, buyPrice=16000, 
cartCodeList=null, 
itemVO=ItemVO
(itemCode=null, 
itemName=아주 오랜만에 행복하다는 느낌, 
itemPrice=16000, 
itemComment=null, 
regDate=null, itemStock=0, cateCode=null, itemStatus=null, cateName=null, cateStatus=null, memberId=null, 

imgList=[ImgVO(imgCode=null, originName=null, attachedName=a783e530-31dd-4e66-a438-3f7dced6fbfd.jpg, isMain=null, itemCode=null)],

categoryVO=CategoryVO(cateCode=null, cateName=기타, cateStatus=null)), 
imgVO=null, memberVO=null, 
cartVO=CartVO(cartCode=null, itemCode=null, memberId=null, cartAmount=0, regDate=null, totalPrice=32000, cateName=기타, itemName=아주 오랜만에 행복하다는 느낌, itemPrice=16000, attachedName=a783e530-31dd-4e66-a438-3f7dced6fbfd.jpg,

itemVO=ItemVO(itemCode=null, itemName=아주 오랜만에 행복하다는 느낌, itemPrice=16000, itemComment=null, regDate=null, itemStock=0, cateCode=null, itemStatus=null, cateName=null, cateStatus=null, memberId=null, 

imgList=[ImgVO(imgCode=null, originName=null, attachedName=a783e530-31dd-4e66-a438-3f7dced6fbfd.jpg, isMain=null, itemCode=null)], 

categoryVO=CategoryVO(cateCode=null, cateName=기타, cateStatus=null)), 
imgVO=null, 
memberVO=null, 
cartCodeList=null), 

buyDetailList=[BuyDetailVO(buyDetailCode=null, itemCode=null, buyCode=BUY_007, buyAmount=1, buyCnt=2, cateName=소설, itemName=이국에서, itemPrice=16000, buyPrice=16000, attachedName=1bb400e3-67d1-4d9d-b6ee-0c714ac9fa61.jpg), BuyDetailVO(buyDetailCode=null, itemCode=null, buyCode=BUY_007, buyAmount=1, buyCnt=2, cateName=기타, itemName=아주 오랜만에 행복하다는 느낌, itemPrice=16000, buyPrice=16000, attachedName=a783e530-31dd-4e66-a438-3f7dced6fbfd.jpg)],

itemCode=null, buyDetailVO=null)

mapper

VO

package Kh.study.shop.buy.vo;

import java.util.List;

import Kh.study.shop.cart.vo.CartVO;
import Kh.study.shop.item.vo.ImgVO;
import Kh.study.shop.item.vo.ItemVO;
import Kh.study.shop.member.vo.MemberVO;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class BuyVO {
	private String buyCode;
	private String memberId;
	private String buyDate;
	private int totalPrice;
	
	// mapper 같이 추가
	// 구매내역조회하기위해 추가함.
	private int buyCnt;
	private String cateName;
	private String itemName;
	private int itemPrice;
	private String attachedName;
	//임의 별칭부여한 구매한 총가격
	private int buyPrice;
	
	private List<String> cartCodeList;
	private ItemVO itemVO;
	private ImgVO imgVO;
	private MemberVO memberVO;
	private CartVO cartVO;
	
	// 한 번 구매하면 여러개의 상품디테일정보가 여러개 들어가있으므로
	// 리스트로 변수선언하고 리절트맵에 컬렉션으로 추가하기 1:N 관계
	private List<BuyDetailVO> buyDetailList; // 주의!! 리절트맵의 프로퍼티와 이름이 같아야한다.
	private String itemCode;//??없어도 될듯
	private BuyDetailVO buyDetailVO;
	
	
}
package Kh.study.shop.buy.vo;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class BuyDetailVO {
	private String buyDetailCode;
	private String itemCode;
	private String buyCode;
	private int buyAmount;
	
	// mapper에서 구매목록조회시 
	//리절트맵 추가한것 변수선언하기
	private int buyCnt;
	private String cateName;
	private String itemName;
	private int itemPrice;
	private int buyPrice;
	private String attachedName;
}

service

package Kh.study.shop.buy.service;

import java.util.List;

import Kh.study.shop.buy.vo.BuyVO;
import Kh.study.shop.cart.vo.CartVO;
import Kh.study.shop.item.vo.ItemVO;

public interface BuyService {
	//구매할 목록조회
	List<CartVO> selecteBuyingList(CartVO cartVO);
	
	// 다음 buycode조회
	String selectNextBuyCode();
	//구매등록
	void insertBuy(BuyVO buyVO,CartVO cartVO);
	//구매를 위한 장바구니 정보 조회
	List<CartVO> getCartInfoForBuy(CartVO cartVO);
	//단일 구매 조회
	ItemVO DirectSelectBuyingInfo(String itemCode);
	
	
	// 구매내역 조회_요약줄
	List<BuyVO> selecteBuy(String memberId);
	// 구매내역 목록조회_ 내용줄
	List<BuyVO> selecteBuyList(String memberId);
	
}

serviceImpl

package Kh.study.shop.buy.service;

import java.util.List;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import Kh.study.shop.buy.vo.BuyVO;
import Kh.study.shop.cart.vo.CartVO;
import Kh.study.shop.item.vo.ItemVO;

@Service("buyService")
public class BuyServiceImpl implements BuyService{
	@Autowired
	private SqlSessionTemplate sqlSession;
	
	//구매등록(+ 구매상세정보,장바구니삭제 같이 트랜잭션 처리해야한다)
	@Transactional(rollbackFor = Exception.class)//어떤 오류든 간에 뭐든지 롤백하겠다.
	@Override
	public void insertBuy(BuyVO buyVO,CartVO cartVO) {
		sqlSession.insert("buyMapper.insertBuy",buyVO);
		sqlSession.insert("buyMapper.insertBuyDetail",buyVO);
		// 단일구매시 장바구니상품에 담지않기때문에 장바구니 삭제할 필요가 없다. 그래서 단일구매시 컨트롤러에서 cartVO 매개변수대신 null을 던진다. 
		//아래는 단일구매가 아닌 장바구니 상세페이지에서 선택구매를 할 때를 말한다. 
		//왜? 장바구니에 등록이 된 후, 선택구매를 하기때문에 구매 후에는 장바구니에 등록되었던 것을 삭제해야하기때문이다.
		if(cartVO != null) {
		sqlSession.delete("cartMapper.deleteCarts",cartVO);
	
		}
	}
	
	@Override
	public String selectNextBuyCode() {
		return sqlSession.selectOne("buyMapper.selectNextBuyCode");
	}
	//구매할 장바구니목록조회
	@Override
	public List<CartVO> selecteBuyingList(CartVO cartVO) {
		return sqlSession.selectList("buyMapper.selecteBuyingList",cartVO);
	}
	//구매위한 장바구니정보조회
	@Override
	public List<CartVO> getCartInfoForBuy(CartVO cartVO) {
		return sqlSession.selectList("buyMapper.getCartInfoForBuy",cartVO);
	}
	//단일 구매 조회
	@Override
	public ItemVO DirectSelectBuyingInfo(String itemCode) {
		return sqlSession.selectOne("buyMapper.DirectSelectBuyingInfo",itemCode);
	}
	// 구매내역조회_전체줄
	@Override
	public List<BuyVO> selecteBuyList(String memberId) {
		return sqlSession.selectList("buyMapper.selecteBuyList",memberId);
	}
	// 구매내역조회 요약줄
	@Override
	public List<BuyVO> selecteBuy(String memberId) {
		return sqlSession.selectList("buyMapper.selecteBuy",memberId);
	}
}

controller

// 구매내역조회(전체 + 요약 모두 한꺼번에) 
	@GetMapping("/buyList")
	public String buyList(Model model,Authentication authentication,CartVO cartVO, ItemVO itemVO,BuyVO buyVO) {
		User user = (User)authentication.getPrincipal();
		// 구매내역조회_요약 쿼리문
		model.addAttribute("buys",buyService.selecteBuy(user.getUsername()));
		
		//리스트를 만들면 반복문으로 하나씩 빼서 
		// buyVO하나씩의 값들을 잘 들고왔는지 확인해보자!!!! 
		for(BuyVO e : buyService.selecteBuy(user.getUsername()) ) {
			System.out.println("XOXOXOXOOXOXOXOXOXOXOXOOXOXOXOXO"+e);
		}
		
		// 요약과 전체 따로 쿼리문 만들었다면 아래 코드 작성
		//(전체)구매내역조회 쿼리문
		//model.addAttribute("buyList", buyService.selecteBuyList(user.getUsername()));
		return "content/buy/buy_list";
	}

html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
	xmlns:layout="http://www.ultra.net.nz/thymeleaf/layout" 
	layout:decorate="layout/myInfo_layout"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
	
<div layout:fragment="content">
<div class="row  mb-3">
	<div class="col">
		<!--  제목줄 -->
		<div class="row">
			<div class="col">
				 <h2>✔ 상품 구매 내역 </h2>
			</div>
		</div>
		<!-- 중간줄 -->
		<div class="row mt-3 " style="font-size: 15px;  color: #3C4048;">
			<span style="font-style: italic;">[ <span sec:authentication="name"></span>	] 님이 결제하신 상품구매내역입니다.</span>
			
		</div>
	 
	 <!-- 내용줄- 아코디언사용-->
	<div class="row mt-1 mb-5">
		<div class="col-12">
	
					<!-- 아코디언 펼쳐지기 전 구매요약 내용 -->
			<div class="accordion" id="accordionPanelsStayOpenExample">
				 <div class="accordion-item">
					<th:block th:each="buyInfo : ${buys}">
				    <h2 class="accordion-header" id="panelsStayOpen-headingOne">
						
				      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"  th:data-bs-target="|#panelsStayOpen-collapseOne${buyInfoStat.count}|" aria-expanded="true" aria-controls="panelsStayOpen-collapseOne">
						 	<!-- 스판태그는 너비가 먹지않는다!!! div(블록태그)는 조절가능하지만 스판태그(인라인)태그는 조절이 불가능하다. 
						 	그래서 display속성값으로 인라인블록으로 변경해야 너비 조정이 가능해진다. -->
							 <span  style="font-weight: bold; width: 20%; padding-left: 10px;">No.[[${#lists.size(buys) - buyInfoStat.index}]] </span>
								 <span> <span style="font-size: 1.1rem;">[[${buyInfo.buyDate}]] </span> <!-- rem : 원ㄹ 글자크기의 배수를 의미함 -->
									 에 총 
									 <span style="font-size: 1.1rem;">[[${buyInfo.buyCnt}]]</span>
									 건의 주문으로 
									 <span style="font-size: 1.1rem;">[[${#numbers.formatCurrency(buyInfo.totalPrice)}]]</span>
									 원을 결제했습니다.
								 </span>
						  
				      </button>
				    </h2>
				    <div  th:id="|panelsStayOpen-collapseOne${buyInfoStat.count}|" class="accordion-collapse collapse " aria-labelledby="panelsStayOpen-headingOne">
				      <div class="accordion-body">
				      <!--   <strong>강조하는 줄 영역</strong>  -->
								<!-- 아코디언 클릭시 펼쳐지는 구매 상세 내용줄 -->
								<table class="table table-sm">
									<thead>
										<tr>
											<td>No.</td>
											<td colspan="2" style="text-align: center;">상품정보</td>
											<td>단가 가격</td>
											<td>수량</td>
											<td>총가격</td>
										</tr>
									</thead>
									<!-- 구매목록에서 buy_001의 buy_001_01,02...를 조회하는 것 -->
									<tbody >
										<tr th:each="buyList,status : ${buyInfo.buyDetailList}">
											<td>[[${status.index}+1]] </td>
											<td ><img width="100px;" height="140px;" th:src="|@{/images/}${buyList.attachedName}|">   </td>
											<td>
												[<span style="color: #749F82;" th:text=" ${buyList.cateName}"></span>]
												<span th:text=" ${buyList.itemName}" ></span> </td>
											<td>[[${buyList.itemPrice}]]</td>
											<td>[[${buyList.buyAmount}]]</td>
											<td>[[${buyList.buyPrice}]]</td>
										</tr>
									</tbody>
								</table>
							</div>
						</div>     
						</th:block> 
					</div>
	   			 </div>
	   			 
	
	 	 </div>
	  </div>
		
	
	<!-- 뒤로가기 버튼 줄 -->
	<div class="row mt-3">
		<div class="col">
		    <div align="center">
		    	<button class="btn btn-light" type="button" th:onclick="@{/item/list}">뒤로가기</button>
		    </div>
		</div>
	</div> 
	
	
		</div>
	</div>
</div>
</html>

결과

  • 구매내역조회 페이지 첫화면
    : 부트스트랩의 아코디언(accordion) 디자인을 가져와서 수정하여 사용
    : 첫화면부터 모두 열리지않게 show삭제, 반복문마다의 버튼의 id값과 내용줄 div의 id값을 각각 다르게 설정(i,인덱스값부여하기)하면 하나를 클릭시 모두가 열리지않고 1:1로 열리도록 만들고, 첫 화면에서부터 파란색이 뜨지않고 하얀배경으로 시작하도록 collapse라는 속서을 버튼의 class값에 넣어준다.
  • 상품코드별로 조회된 목록을 한 줄씩 클릭하면, 목록List안에 있는 buyDetailList 데이터를 하나씩 뽑아서 확인 할 수 있다.
profile
Dev.Vinch

0개의 댓글