주문 기능을 완료했다면 주문이 정상적으로 진행되었는지 사용자가 확인할 수 있는 구매 내역 조회 기능을 추가해보자
구매 내역 조회 기능 순서
구매내역 보여주는 html 설계
html에 들어갈 정보와 맞는 dto설정
해당 정보를 저장시켜주는 service 설계
가져온 데이터를 html로 보내주는 controller 설계
구매내역 보여주는 html 설계
<!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>
<table class="table">
<thead>
<tr>
<th>주문 번호</th>
<th>구매 날짜</th>
<th>구매 상품</th>
<th>구매 개수</th>
<th>가격</th>
<th>주문 상태</th>
</tr>
</thead>
<tbody>
<th:block th:each="order:${orderList}">
<th:block th:each="orderItem:${order.orderItemResponseDtoList}">
<tr>
<td th:text="${order.id}"></td>
<td th:text="${order.date}"></td>
<td th:text="${orderItem.itemResponseDto.name}"></td>
<td th:text="${orderItem.count}"></td>
<td th:text="${order.price}"></td>
<td th:text="${order.status}"></td>
</tr>
</th:block>
</th:block>
</tbody>
</table>
</div>
</div>
</html>
package com.qkrtprjs.happyexercise.dto;
import com.qkrtprjs.happyexercise.entitiy.order.Order;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
@Getter
@NoArgsConstructor
public class OrderListResponseDto {
private Long id;
private LocalDateTime date;
private String status;
private int price;
private List<OrderItemResponseDto> orderItemResponseDtoList;
@Builder
public OrderListResponseDto(Long id, LocalDateTime date, String status, int price, List<OrderItemResponseDto> orderItemResponseDtoList) {
this.id = id;
this.date = date;
this.status = status;
this.price = price;
this.orderItemResponseDtoList = orderItemResponseDtoList;
}
}
//Entity이름의 ResponseDto는 해당 Entity와 알맞는 정보의 필드들을 갖고있음을 의미한다.
public List<OrderListResponseDto> orderList(SessionMember loginMember) {
List<OrderListResponseDto> dtoList = new ArrayList<>();
Member member = memberRepository.findByEmail(loginMember.getEmail()).orElseThrow(() -> new IllegalArgumentException("해당 이메일은 존재하지 않습니다!"));
List<Order> orderList = orderRepository.findByMember(member);
for (Order order : orderList) {
List<OrderItemResponseDto> orderItemResponseDtoList =
orderItemRepository.findByOrder(order).stream().map(orderItem -> OrderItem.toDto(orderItem)).collect(Collectors.toList());
dtoList.add(
OrderListResponseDto.builder()
.id(order.getId())
.date(order.getDate())
.status(order.getStatus())
.price(order.getPrice())
.orderItemResponseDtoList(orderItemResponseDtoList)
.build()
);
}
return dtoList;
}
@GetMapping("/orderList")
private String orderList(Model model, @LoginMember SessionMember loginMember) {
List<OrderListResponseDto> orderListResponseDtoList = orderService.orderList(loginMember);
model.addAttribute("loginMember", loginMember);
model.addAttribute("orderList", orderListResponseDtoList);
return "order/orderList";
}
정상적으로 보여지는 것을 확인할 수 있다. 추가로 현재는 하나의 주문에 하나의 상품이 들어가있지만 장바구니 기능을 추가하면서 여러가지를 한번에 주문할 수 있는 기능을 추가할 때에는 하나의 주문에 여러가지 상품이 들어갈 수 있기때문에 dto의 필드를
private Long id; private LocalDateTime date; private String status; private int price; private List<OrderItemResponseDto> orderItemResponseDtoList;
로 지정해주었다.
이어서 주문 취소기능을 추가하려고 구상하던 중에 문득 주문 상세보기 페이지가 있다면 더 효율적으로 진행할 수 있다고 생각했다 무작정 구매 내역에서 주문 취소를 하는 것은 깔끔하지가 않다고 생각했고 다른 플랫폼들을 확인해본결과 하나의 주문을 상세보기를 이용해서 들어간다음 거기서 주문 취소를 하는 방식을 이용하고 있어서 비슷하게 접근해보려고한다.
그렇다면 먼저 주문 상세보기 페이지부터 수정해보자!
우선 상세보기 버튼을 만들어주고 클릭시에 id 값을 전달해준다
이 과정은
<button th:id="${order.id}" type="button" class="btn btn-primary" name="orderDetail-btn">상세보기</button>
버튼에 id 라는 속성값을 만들어주고 거기에 id값을 저장시켜준다음에
$("[name=orderDetail-btn]").on('click',function (){
console.log(this.getAttribute("id"));
});
버튼을 클릭했을때에 클릭한 버튼(this)의 id 라는 속성값을 가져오게하면 id 값을 가져올 수 있다!!
$("[name=orderDetail-btn]").on('click',function (){
location.href="/order/" + this.getAttribute("id");
});
가져온 id값을 이용해서 페이지를 이동시켜준다.
@GetMapping("/order/{id}")
private String orderDetail(Model model, @PathVariable Long id) {
OrderDetailResponseDto orderDetailResponseDto = orderService.orderDetail(id);
model.addAttribute("order", orderDetailResponseDto);
return "order/orderDetail";
}
public OrderDetailResponseDto orderDetail(Long id) {
Order order = orderRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("해당 id값은 존재하지 않습니다!"));
List<OrderItemResponseDto> orderItemResponseDtoList =
orderItemRepository.findByOrder(order).stream().map(orderItem -> OrderItem.toDto(orderItem)).collect(Collectors.toList());
return OrderDetailResponseDto.builder()
.id(order.getId())
.date(order.getDate())
.status(order.getStatus())
.price(order.getPrice())
.orderItemResponseDtoList(orderItemResponseDtoList)
.build();
}
<!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>
<button type="button" class="btn btn-danger" id="delete-item-btn">삭제</button>
<div class="mb-3 mt-3">
<label for="id">주문번호:</label>
<input type="text" class="form-control" id="id" th:value="${order.id}" name="id" readonly>
</div>
<table class="table">
<thead>
<tr>
<th>상품명</th>
<th>개당 가격</th>
<th>구매 개수</th>
<th>구매 가격</th>
</tr>
</thead>
<tbody>
<th:block th:each="orderItem:${order.orderItemResponseDtoList}">
<tr>
<td th:text="${orderItem.itemResponseDto.name}"></td>
<td th:text="${orderItem.itemResponseDto.price}"></td>
<td th:text="${orderItem.count}"></td>
<td th:text="${orderItem.price}"></td>
</tr>
</th:block>
</tbody>
</table>
<div class="mb-3">
<label for="orderPrice">주문 금액:</label>
<input type="text" class="form-control" id="orderPrice" th:value="${order.price}" name="orderPrice" readonly>
</div>
<div class="mb-3">
<label for="date">주문 날짜:</label>
<input type="text" class="form-control" id="date" th:value="${order.date}" name="date" readonly>
</div>
<div class="mb-3">
<label for="status">주문 상황:</label>
<input type="text" class="form-control" id="status" th:value="${order.status}" name="status" readonly>
</div>
</div>
</div>
</html>
주문을 삭제하는 기능을 추가해보자!