Spring Projcect/[갠플] Online-mall

[9일차] 관리자 API - 상품 등록, 수정, 삭제

계란💕 2022. 10. 4. 01:38

To do list

  • 관리자 - 상품(등록, 수정, 삭제), 관리자 주문 확인 list()
  • 회원 - 상품(조회), 주문 add, 주문 del, (주문 수정은 보류), 장바구니 (조회, 선택 삭제), 쿠폰 조회

 

 

 

 Ex) 상품 등록 / 수정 

  • 등록과 수정은 get, post 매핑을 함께 사용한다.
  • 변수 editMode로 add 페이지에서 등록 모드인지 수정 모드인지 구분한다.

 

  • service
<hide/>
@Override
public boolean add(ProductInput parameter) {

    Product product = Product.builder().productName(parameter.getProductName())
        .productImg(parameter.getProductImg()).stockQuantity(parameter.getStockQuantity())
        .price(parameter.getPrice()).category(parameter.getCategory())
        .stockedDt(parameter.getStockedDt())
        .soldOutYn(false)
        .cumulativeSales(0)
        .build();
    // 재고 수량이 0일 때는 입고 예정일이 필요하다

    productRepository.save(product);
    return true;
}

// 수정
@Override
public boolean update(ProductInput parameter) {  // id로 찾아서 다른 값들을 바꾼다.

    Optional<Product> OptionalProduct = productRepository.findById(parameter.getId());

    if (OptionalProduct.isPresent()) {
        Product product = OptionalProduct.get();
        product.setProductImg(parameter.getProductImg());
        product.setProductName(parameter.getProductName());
        product.setStockQuantity(parameter.getStockQuantity());
        product.setCategory(parameter.getCategory());
        product.setPrice(parameter.getPrice());
        product.setStockedDt(parameter.getStockedDt());
        productRepository.save(product);
        return true;
      }
    return false;
}

// 삭제
@Override
public boolean delete(long id) {
    Optional<Product> OptionalProduct = productRepository.findById(id);
    productRepository.delete(OptionalProduct.get());
    return true;
}

// 모든 상품에 대해 보여준다.
@Override
public List<ProductDto> list() {
    return ProductDto.of(productRepository.findAll());
}

 

  • controller
    • editMode: edit 이라는 단어가 있는 경우 editMode는 true
<hide/>
@GetMapping("/admin/product/list.do")
public String list(HttpServletRequest request,
                   Model model,
                   ProductParam param) {

    param.init();   // 페이지 초기화
    List<ProductDto> list = productService.list();

    // 검색 타입 데이터 추가하기
    //        param.getSearchType();

    long totalCount = 0;
    if (list != null && list.size() > 0) {
        totalCount = list.size();
    }
    String queryString = param.getQueryString();
    String pagerHtml = getPaperHtml(totalCount,
        param.getPageSize(),
        param.getPageIndex(),
        queryString);
    model.addAttribute("list", list);
    model.addAttribute("totalCount", totalCount);
    model.addAttribute("pager", pagerHtml);

    return "admin/product/list";
}

/* searchValue, searchType 상품 검색
@GetMapping("/admin/product/list.do")
public String searchList(HttpServletRequest request,
    Model model,
    ProductParam param) {
}
 */

@GetMapping(value = {"/admin/product/add.do", "/admin/product/edit.do/{id}"})
public String add(HttpServletRequest request,
                   Model model,
                   ProductInput parameter){

    boolean editMode = request.getRequestURI().contains("/edit.do");
    ProductDto detail = new ProductDto();

    // repository에 존재하지 않는 id의 경우 예외 처리를 한다.
    if(editMode){
        long id = parameter.getId();
        Product existProduct = productRepository.findById(id).get();
        ProductDto productDto =  ProductDto.of(existProduct);

        if(existProduct == null){
//                model.addAttribute("message", "수정할 상품 정보가 없습니다.");
            System.out.println("수정할 상품 정보가 없습니다.");
            return "admin/product/list";
        }
        detail = productDto;
    }
    model.addAttribute("editMode", editMode);
    model.addAttribute("detail", detail);
    return "admin/product/add";
}

@PostMapping(value = {"/admin/product/add.do", "/admin/product/edit.do/{id}"})
public String addSubmit(Model model,
                       ProductInput parameter,
                       Principal principal,
                       HttpServletRequest request) {

    boolean editMode = request.getRequestURI().contains("/edit.do");
    boolean result = false;

    if(!productRepository.existsById(parameter.getId())){
        System.out.println("존재하지 않는 상품 번호입니다.");
        return "admin/product/list";
    }

    // edit 모드
    if(editMode) {
        long id = parameter.getId();
        Product existProduct = productRepository.findById(id).get();
        ProductDto productDto = ProductDto.of(existProduct);
        productService.update(parameter);

        if (existProduct == null) {
            model.addAttribute("message", "수정할 상품 정보가 없습니다.");
            result = false;
            model.addAttribute("result", result);
            model.addAttribute("detail", parameter);
            return "admin/product/list";
        }
    }else{      // 상품 추가
        result = productService.add(parameter);
    }
    model.addAttribute("result", result);
    model.addAttribute("detail", parameter);
    return "redirect:/admin/product/list.do";
}

@PostMapping("/admin/product/delete.do")
public String del(Model model, ProductInput parameter) {
    boolean result = productService.delete(parameter.getId());
    return "redirect:/admin/product/list.do";
}

 

  • list.html
    • 수정 버튼을 누르면 edit.do/{수정할 상품의 id} 페이지로 이동한다.
    • searchType과 searchValue를 가지고 특정 상품을 검색할 수 있도록 구현할 예정이다.
<hide/>
<!doctype html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>관리자</title>

  <style>
    .list table {
      width: 100%;
      border-collapse: collapse;
    }

    .list table th, .list table td {
      border: solid 1px #000;
    }

    .search-form {
      position: relative;
      padding: 5px 0 5px 0;
      text-align: right;
    }

    .search-form .total-count {
      position-position: absolute;
      left: 0;
      top: 0;
      height: 20px;
      float: left;
    }

    .pager {
      margin-top: 10px;
      text-align: center;
    }

    .pager a.on {
      font-weight: bold;
      color: red;
    }
  </style>

</head>
<body>
<h1>관리자 상품 리스트</h1>
<div th:replace="/fragments/layout.html :: fragment-admin-body-menu"></div>


<div class="list">
  <div class="search-form">
    <p class="total-count">전체 <span th:text="${totalCount}"></span>개 </p>

    <a href="/admin/product/add.do">상품 추가</a>

    <form method="get">
      <select name="searchType">
        <option value="all">전체</option>
        <!--        상품을 검색하기 위한 수단  상품 이름 / 카테고리 / -->
        <option th:selected="${#strings.equals(param.searchType, 'productId')}" value="productId">상품
          No
        </option>
        <option th:selected="${#strings.equals(param.searchType, 'category')}" value="category">카테고리
        </option>
        <option th:selected="${#strings.equals(param.searchType, 'id')}" value="id">상품 id
        </option>
        <option th:selected="${#strings.equals(param.searchType, 'productName')}"
                value="productName">상품명
        </option>
        <option th:selected="${#strings.equals(param.searchType, 'price')}" value="price">가격
        </option>
        <option th:selected="${#strings.equals(param.searchType, 'soldOutYn')}" value="soldOutYn">품절
          여부
        </option>
        <option th:selected="${#strings.equals(param.searchType, 'productImg')}" value="productImg">
          상품 사진
        </option>
        <option th:selected="${#strings.equals(param.searchType, 'stockQuantity')}"
                value="stockQuantity">재고 수량
        </option>
        <option th:selected="${#strings.equals(param.searchType, 'stockedDt')}" value="stockedDt">입고
          예정일
        </option>
        <!--        <option th:selected="${#strings.equals(param.searchType, 'cumulativeSales')}" value="cumulativeSales">누적 판매량-->
        <!--        </option>-->

      </select>
      <input th:value="${param.searchValue}" type="search" name="searchValue" placeholder="검색어 입력"/>
      <button type="submit">검색</button>
    </form>
  </div>

  <table>
    <thead>
    <tr>
      <!--      <th>No</th>-->
      <th>카테고리</th>
      <th>상품 Id</th>
      <th>상품명</th>
      <th>가격</th>
      <th>품절 여부</th>
      <th>상품 사진</th>
      <th>재고 수량</th>
      <th>입고 예정일</th>
      <!--      <th>누적 판매량</th>-->
      <th> 수정 바로가기</th>
    </tr>
    </thead>
    <tbody>
    <tr th:each="x : ${list}">
      <!--      <td th:th:text="${x.id}">1</td>-->
      <td th:th:text="${x.category}"></td>
      <td th:text="${x.id}"></td>
      <td th:text="${x.productName}"></td>
      <td th:text="${x.price}"></td>
      <td th:text="${x.soldOutYn}"></td>
      <td th:text="${x.productImg}"></td>
      <td th:text="${x.stockQuantity}"></td>
      <td th:text="${x.stockedDt}"></td>
      <td>
        <a th:href="'edit.do/' + ${x.id}">수정</a>
      </td>
    </tr>
    </tbody>
  </table>
</div>
</body>
</html>

 

  • add.html
    • 컨트롤러에서  detail 변수를 통해 add.html페이지에 정보를 보낸다.
<hide/>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>관리자</title>
</head>
<body>
<h1 th:if="${editMode}">상품 관리 - 수정</h1>
<h1 th:if="${editMode eq false}">상품 관리 -등록</h1>
<div th:replace="/fragments/layout.html :: fragment-admin-body-menu"></div>
<div class="detail">
  <form id="addForm" method="post">
    <table>
      <tbody>
      <tr>
        <th>상품명</th>
        <td><input th:value="${detail.productName}" type="text" name="productName"
                   placeholder="상품명 입력" required/></td>
      </tr>
      <tr>
        <th>상품 가격</th>
        <td><input th:value="${detail.price}" type="number" name="price"
                   placeholder="상품 가격 입력" required/></td>
      </tr>
      <tr>
        <th>상품 사진</th>
        <td><input th:value="${detail.productImg}" type="text" name="productImg"
                   placeholder="상품 사진 등록" required/></td>
      </tr>
      <tr>
        <th>카테고리 선택</th>
        <td>
          <select name="category" required>
            <option value="">카테고리 선택</option>

            <option value="CATEGORY_OUTER">OUTER</option>
            <option value="CATEGORY_TOP">TOP</option>
            <option value="CATEGORY_PANTS">PANTS</option>
            <option value="CATEGORY_SKIRT">SKIRT</option>
            <option value="CATEGORY_SHOES">SHOES</option>
            <option value="CATEGORY_BAG">BAG</option>
            <option value="CATEGORY_HEADWEAR">HEADWEAR</option>
            <option value="CATEGORY_UNDERWEAR">UNDERWEAR</option>
            <option value="CATEGORY_ACCESSORY">ACCESSORY</option>
          </select>
        </td>
      </tr>
      <tr>
        <th>재고 수량</th>
        <td><input th:value="${detail.stockQuantity}" type="text" name="stockQuantity"
                   placeholder="재고 수량" required/></td>
      </tr>
      </tbody>
    </table>
    <button th:if="${editMode}">상품 수정</button>
    <button th:if="${!editMode}">상품 추가</button>
  </form>
</div>
</body>
</html>

 

  Note) 실행 결과

상품 리스트 화면

 

상품 add

 

상품 update

 

 

 

chech list

  • searchValue, searchType을 이용해서 상품 검색하기
  • 등록 / 수정에 대한 예외처리도 필요하다.
  • 회원이 보는 상품 페이지 구현
    • 관리자 상품 리스트에서 조금 수정해서 만들기
    • 장바구니, 주문하기 버튼이 필요하다.