coupang Day10

김지원·2022년 7월 12일
0

WebDevelop

목록 보기
21/21

장바구니 상품 삭제

http://localhost:8080/shopping/cart/delete/?index=44
삭제를 누르면 이 주소로 넘어간다.

-> ShoppingController

-> ShoppingService

-> ShoppingController

-> IShoppinMapper

-> ShoppinMapper.xml

-> ShoppingService

-> check

  • 삭제버튼 클릭 시 삭제가 되면 된다.

구매하기

장바구니에서 바로 구매하기

상품 상세페이지에서 바로 구매하기

: 구매버튼누르면 구매가 바로 되도록 하자.

  • Mapping -> /shopping/order : 구매를 위한 페이지
  • detail 페이지에도 바로 구매하기가 있어서 order 로 처리를 할 것이다.
  • confirm 띄우고 확인 누르면 바로 구매가 되도록 구현하자.

/shopping/order?pid=14&count=3
: pidcount 가 붙으면 그 상품만 구매하는 Mapping

/shopping/order
: 사용자의 장바구니에 있는 것 모두 구매하는 Mapping

 <a class="button order" th:href="@{/shopping/order}">구매하기</a>
<a class="button order" href="#" th:if="${productDto.getCount() > 0}">바로 구매하기</a>

-> 수정 전 detail.html

  • 바로 구매하기 버튼을 누르면 이 주소로 매핑이 된다.

-> 수정 후 detail.html

<form class="order-container" method="get" th:action="@{/shopping/order}">
  • form태그에 이것을 추가하고 구매하기 버튼을 클릭 해보자.
  • 수량을 3개 선택하고 바로 구매하기 하면 주소에 구매 갯수와 상품의 남은 갯수가 뜬다.

-> 수정 완료 detail.html

<form class="order-container" method="get" onsubmit="return confirm('정말로 해당 상품을 구매할까요?')" th:action="@{/shopping/order}">
                <label class="quantity-container" th:if="${productDto.getCount() > 0}">
                    <span hidden>개수</span>
                    <input class="quantity-input" id="quantityInput" max="99" min="1" name="count" type="number" value="1">
                </label>
                <input id="productIndexInput" type="hidden" name="pid" th:value="${productDto.getIndex()}">
                <a class="button cart" href="#" id="cartButton" th:if="${productDto.getCount() > 0}">장바구니 넣기</a>
                <input class="button order" type="submit" value="바로 구매하기" th:if="${productDto.getCount() > 0}">
                <a class="button sold-out" href="#" th:if="${productDto.getCount() == 0}">일시 품절</a>
</form>

-> cart.html

-> ShoppingController

  • 이렇게 되면 productIndexcount는 잘넘어온다. 그런데 int타입인데 null이 뜨면 오류이기 때문에 예외를 잡아줘야한다.
    그래서 int를 Optional<Integer>로 변경해주고 orElse(0)사용해주자.

  • 이렇게 수정헤준다.

  • sout productIndex.orElse(0) == 0 찍힘
    count.orElse(0)

-> ShoppingController

-> ShoppingService orderAll

-> ShoppingController getOrder

-> ShoppingService orderAll

-> 배송상태를 담는 order_statues 테이블 생성

-> 구매내역을 담을 수 있는 orders 테이블 생성

-> OrderEntity

-> ShoppingService orderAll

-> IShoppinMapper insertOrder

-> ShoppinMapper.xml insertOrder

-> ShoppingService

  • 장바구니 내역이 삭제가 된다. 녹음 확인

-> ShoppingService orderSpecific

-> -> ShoppingService orderAll

  • @Transactinal 어노테이션 추가
    이유 :
  • stock 재고에 대해서도 추가

-> ShoppingService orderSpecific

  • stock 재고에 대해서도 추가

-> ShoppingController getOrder

  • else추가

-> order.html

-> order.css

<style>
@charset "UTF-8";
body > .title {
    font-size: 2rem;
    font-weight: 600;
    margin-top: 3rem;
    margin-bottom: 1.5rem;
}
body > .subtitle {
    font-size: 1.125rem;
    margin-bottom: 3rem;
}
body > .buttons {
    align-items: center;
    display: flex;
    flex-direction: row;
    justify-content: center;
    margin: 3rem 0;
}
body > .buttons > .button {
    width: 10rem;
    border-radius: 0.5rem;
    font-size: 1.5rem;
    padding: 1rem 2rem;
    text-align: center;
}
body > .buttons > .button + .button {
    margin-left: 0.75rem;
}
body > .buttons > .button.back {
    border: 0.125rem solid rgb(66, 132, 243);
    color: rgb(66, 132, 243);
}
body > .buttons > .button.order {
    background-color: rgb(66, 132, 243);
    border: 0.125rem solid rgb(66, 132, 243);
    color: rgb(255, 255, 255);
}
</style>  

-> 결과

  • 구매하기 버튼 클릭시 나타나는 페이지

그런데! 이 페이지에서 새로고침을 누르면 구매가 계속되어서 orders 테이블에 데이터가 계속 쌓이게 된다. 한번만 구매가 되도록 하자.

-> detail.html

  • getpost로 변경

-> cart.html

  • divform / ainput

-> ShoppingController getOrder POST로 변경

  • getPost 로 변경
  • setViewNames 경로 변경

-> ShoppingController getOrder 새롭게 추가

-> cheak

  • 구매하기를 누르면 order 페이지로 넘어가며 구매가 되며 orders 테이블에 값이 들어온 것을 확인 할 수 있고 새로고침시 중복 값이 들어오지 않게 되었다.
  • 당연히 carts 테이블의 값은 사라진다.

-> Orders 테이블 수정

`product_index`      INT UNSIGNED     NOT NULL

장바구니에 담을시 / 구매할시 / 미래의 가격이 다 다르기 때문에 수정하자.

  • 원래 있던 테이블 drop 후 price_product, price_shipping 추가
  • ShoppingEntity, ShoppingMapper.xml 도 추가 수정

-> ShoppingService


여기 서비스 추가 해야함 많이..

-> UserController getMy

-> ShoppingService getOrderOf

-> IShoppingMapper selectOrderByEmail

-> ShoppingMapper.xml selectOrderByEmail

-> ShoppingService getOrderOf

-> UserContorller

-> UserController getMy

  • 어떤 상품이 발송 처리가됐는지 는 관리자가 하는 것이다. 모든 사용자의 상품이 다 보여야한다.

-> selectOrders

  • selectOrdersByEmail에서 where만 삭제

-> OrderStatusEntity

-> IShoppingMapper selectOrderStatuses

-> ShoppingMapper.xml selectOrderStatuses

-> ShoppingService getOrderStatuses

-> UserController

-> my.html

<body>
<th:block th:replace="~{fragments/header.html :: content}"></th:block>
<table class="table order-table">
    <caption>구매내역</caption>
    <thead>
    <tr>
        <th>주문번호</th>
        <th th:if="${userEntity.isAdmin()}">주문자</th>
        <th class="info" colspan="2">상품정보</th>
        <th>주문금액</th>
        <th>배송비</th>
        <th>배송현황</th>
        <th></th>
    </tr>
    </thead>
    <tbody>
    <tr th:each="pair : ${pairList}"
        th:with="orderEntity=${pair.getLeft()}, productEntity=${pair.getRight()}">
        <td class="index" th:text="${orderEntity.getIndex()}"></td>
        <td th:if="${userEntity.isAdmin()}" th:text="${userEntity.getEmail()}"></td>
        <td class="thumbnail-container">
            <img alt="상품이미지" class="thumbnail" th:src="@{/product/detail/thumbnail (id=${productEntity.getThumbnailId()})}">
        </td>
        <td>
            <div class="datetime" th:text="${#dates.format(orderEntity.getCreatedAt(), 'yyyy-MM-dd mm:HH:ss') + '구매'}"></div>
            <div class="title" th:text="${productEntity.getTitle()}"></div>
        </td>
        <td class="nowrap centered" th:text="${#numbers.formatInteger(orderEntity.getPriceProduct(), 0, 'COMMA') + '원'}"></td>
        <td class="nowrap centered" th:text="${orderEntity.getPriceShipping() == 0 ? '무료' : #numbers.formatInteger(orderEntity.getPriceShipping(), 0, 'COMMA') + '원'}"></td>
        <td class="centered " th:text="${orderStatuses.get(orderEntity.getOrderStatusIndex())}"></td>
        <td>
            <div class="delivery-container" th:if="${userEntity.isAdmin()}">
                <select class="delivery-select" rel="deliverySelect" th:data-oid="${orderEntity.getIndex()}">
                    <option th:each="key : ${orderStatuses.keySet()}"
                            th:value="${key}"
                            th:text="${orderStatuses.get(key)}"
                            th:selected="${orderEntity.getOrderStatusIndex() == key}"></option>
                </select>
            </div>
            <div class="button-container">
                <a class="button" th:if="${orderEntity.getOrderStatusIndex() == 4 && userEntity.getEmail().equals(orderEntity.getUserEmail())}">리뷰쓰기</a>
                <a class="button" th:if="${orderEntity.getOrderStatusIndex() == 1 || orderEntity.getOrderStatusIndex() ==2 || orderEntity.getOrderStatusIndex() == 3}">구매취소</a>
                <a class="button" th:if="${orderEntity.getOrderStatusIndex() == 4}">반품신청</a>
            </div>
        </td>
    </tr>
    </tbody>
</table>
</body>

-> my.css

<style>
body > .table  {
    width: var(--content-max-width);
    border-collapse: collapse;
    margin-top: 1.5rem;
}
body > .table > caption {
    background-color: rgb(250, 250, 250);
    border-top: 0.125rem solid rgb(221,221,221);
    border-bottom: 0.125rem solid rgb(221,221,221);
    font-size: 1.125rem;
    font-weight: 600;
    margin-bottom: 1rem;
    padding: 0.625rem 1rem;
    text-align: left;
}
body > .table > thead th {
    background-color: rgb(250, 250, 250);
    border-top: 0.125rem solid rgb(221,221,221);
    border-bottom: 0.125rem solid rgb(221,221,221);
    font-weight: 500;
    padding: 0.425rem 0.75rem;
    white-space: nowrap;
}
body > .table > thead th.info {
    width: 100%;
}
body > .table > tbody td {
    border-bottom:  0.0625rem solid rgb(221,221,221);
    padding: 0.5rem 1rem;
}
body > .table > tbody td:not(:last-child) {
    border-right: 0.0625rem solid rgb(221,221,221);
}
body > .table > tbody td.index {
    text-align: center;
}
body > .table > tbody td.nowrap {
    white-space: nowrap;
}
body > .table > tbody td.centered {
    text-align: center;
}
body > .table > tbody td.thumbnail-container {
    border-right: none;
    padding-right: 0;
}
body > .table > tbody .thumbnail {
    height: 5rem;
}
body > .table > tbody .datetime {
    color: rgb(160,160,160);
    font-size: 0.8rem;
    margin-bottom: 0.375rem;
}
body > .table > tbody .title {
    font-weight: 500;
}
body > .table > tbody .delivery-select {
    width: auto;
    border: 0.0625rem solid rgb(221,221,221);
    border-radius: 0.25rem;
    margin-bottom: 0.5rem;
    padding: 0.25rem 0.5rem;
}
body > .table > tbody .button-container {
    align-items: stretch;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
}
body > .table > tbody .button-container > .button {
    border: 0.0625rem solid rgb(221,221,221);
    border-radius: 0.25rem;
    cursor: pointer;
    padding: 0.25rem 0.5rem;
    text-align: center;
}
body > .table > tbody .button-container > .button + .button {
    margin-top: 0.395rem;
}
</style>

-> 결과

0개의 댓글