Skip to content

Commit

Permalink
feat : 판매량순 정렬기능 추가
Browse files Browse the repository at this point in the history
이미지기능을 할때 dto에 collection 파싱 에러
java.lang.UnsupportedOperationException: null
  • Loading branch information
krkarma777 committed Feb 29, 2024
1 parent 5a757b8 commit 35ea59c
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.bulkpurchase.domain.dto.product;

import com.bulkpurchase.domain.entity.user.User;
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter
@Setter
public class ProductForSalesVolumeSortDTO {
private Long productID;
private String productName;
private Double price;
private Integer stock;
private String username; // 판매자 이름
private List<String> imageUrls;
private Long totalQuantity;
private User user;

public ProductForSalesVolumeSortDTO(Long productID, String productName, Double price, Integer stock, String username, List<String> imageUrls, Long totalQuantity, User user) {
this.productID = productID;
this.productName = productName;
this.price = price;
this.stock = stock;
this.username = username;
this.imageUrls = imageUrls;
this.totalQuantity = totalQuantity;
this.user = user;
}

public ProductForSalesVolumeSortDTO(Long productID, String productName, Double price, Integer stock, String username, Long totalQuantity, User user) {
this.productID = productID;
this.productName = productName;
this.price = price;
this.stock = stock;
this.username = username;
this.totalQuantity = totalQuantity;
this.user = user;
}



public ProductForSalesVolumeSortDTO() {
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bulkpurchase.domain.repository.product;

import com.bulkpurchase.domain.dto.product.ProductForSalesVolumeSortDTO;
import com.bulkpurchase.domain.entity.user.User;
import com.bulkpurchase.domain.entity.product.Product;
import com.bulkpurchase.domain.enums.ProductStatus;
Expand Down Expand Up @@ -45,4 +46,18 @@ public interface ProductRepository extends JpaRepository<Product, Long> {

@Query("SELECT p FROM Product p ORDER BY p.productID desc ")
List<Product> findAllProducts();

@Query(value = "SELECT new com.bulkpurchase.domain.dto.product.ProductForSalesVolumeSortDTO" +
"(p.productID, p.productName, p.price, p.stock, p.user.username, p.imageUrls,SUM(od.quantity) , p.user)" +
"FROM OrderDetail od JOIN od.product p " +
"WHERE p.productName LIKE %:productName% " +
"GROUP BY p.productID, p.productName, p.price, p.stock, p.user.username, p.imageUrls,od.order, p.user " +
"ORDER BY SUM(od.quantity) DESC",
countQuery = "SELECT COUNT(DISTINCT p.productID) " +
"FROM OrderDetail od JOIN od.product p " +
"WHERE p.productName LIKE %:productName%",
nativeQuery = false)
Page<ProductForSalesVolumeSortDTO> findByProductNameContainingAndOrderBySalesVolume(@Param("productName") String productName, Pageable pageable);


}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.bulkpurchase.domain.service.product;

import com.bulkpurchase.domain.dto.product.ProductForCouponDTO;
import com.bulkpurchase.domain.dto.product.ProductForSalesVolumeSortDTO;
import com.bulkpurchase.domain.entity.user.User;
import com.bulkpurchase.domain.enums.ProductStatus;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -80,4 +81,8 @@ public String findProductNameById(Long productId) {
public Page<Product> findPageByProductNameContaining(Pageable pageable, String productName) {
return productRepository.findByProductNameContaining(pageable, productName);
}

public Page<ProductForSalesVolumeSortDTO> findProductsBySearchTermAndSortBySalesVolume(String productName, Pageable pageable) {
return productRepository.findByProductNameContainingAndOrderBySalesVolume(productName, pageable);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.bulkpurchase.web.controller.product;

import com.bulkpurchase.domain.dto.product.ProductForSalesVolumeSortDTO;
import com.bulkpurchase.domain.entity.product.Product;
import com.bulkpurchase.domain.service.product.ProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -18,20 +20,48 @@ public class ProductSearchController {
private final ProductService productService;

@GetMapping("/product/search")
public String productSearchView(@RequestParam(value = "q", required = false) String productName, @RequestParam(value = "p", required = false) Integer page, Model model) {
int size = 12;
public String productSearchView(@RequestParam(value = "q", required = false) String productName,
@RequestParam(value = "p", required = false) Integer page,
@RequestParam(value = "sortField", required = false) String sortField,
@RequestParam(value = "sortDir", required = false) String sortDir ,
@RequestParam(value = "size", required = false) Integer size,
Model model) {
if (size == null) {
size = 12;
}
if (page==null) {
page = 1;
}

if (sortDir == null) {
sortDir = "desc";
}
if (productName == null) {
return "redirect:/";
}
Pageable pageable = PageRequest.of(page-1, size);
Page<Product> productPage = productService.findPageByProductNameContaining(pageable, productName);
model.addAttribute("productPage", productPage);
model.addAttribute("totalPages", productPage.getTotalPages());


if (sortField == null) {
sortField = "productID";
}

if (sortField.equals("salesVolume")) {
Page<ProductForSalesVolumeSortDTO> productPage = productService.findProductsBySearchTermAndSortBySalesVolume(productName, PageRequest.of(page - 1, size));
model.addAttribute("productPage", productPage);
model.addAttribute("totalPages", productPage.getTotalPages());
System.out.println("productPage = " + productPage);
} else {
Sort sort = Sort.by(Sort.Direction.fromString(sortDir), sortField);
Pageable pageable = PageRequest.of(page-1, size, sort);
Page<Product> productPage = productService.findPageByProductNameContaining(pageable, productName);
model.addAttribute("productPage", productPage);
model.addAttribute("totalPages", productPage.getTotalPages());
}

model.addAttribute("page", page);
model.addAttribute("q", productName);
model.addAttribute("sortField", sortField);
model.addAttribute("sortDir", sortDir);
return "product/productSearchView";
}
}
22 changes: 10 additions & 12 deletions src/main/resources/templates/product/productSearchView.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,9 @@

.floating-buttons {
position: fixed;
right: 550px; /* 조정값 */
right: 50px; /* 조정값 */
top: 50%;
transform: translateY(-50%);
display: flex;
flex-direction: column;
transform: translateY(-80%); /* 세로 중앙 정렬 */
}

.floating-buttons button {
Expand Down Expand Up @@ -105,11 +103,11 @@
<div class="container custom-container">
<div class="action-bar">
<div class="sorting-buttons">
<button class="btn btn-modern">랭킹순</button>
<button class="btn btn-modern">낮은 가격순</button>
<button class="btn btn-modern">높은 가격순</button>
<button class="btn btn-modern">판매량순</button>
<button class="btn btn-modern">최신순</button>
<button class="btn btn-modern">랭킹순(구현중)</button>
<a href="#" class="btn btn-modern" th:href="@{/product/search(q=${q}, p=${page}, sortField='price', sortDir='asc')}">낮은 가격순</a>
<a href="#" class="btn btn-modern" th:href="@{/product/search(q=${q}, p=${page}, sortField='price', sortDir='desc')}">높은 가격순</a>
<a href="#" class="btn btn-modern" th:href="@{/product/search(q=${q}, p=${page}, sortField='salesVolume', sortDir='desc')}">판매량순</a>
<a href="#" class="btn btn-modern" th:href="@{/product/search(q=${q}, p=${page}, sortField='productID', sortDir='desc')}">최신순</a>
</div>
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-expanded="false">
Expand Down Expand Up @@ -151,15 +149,15 @@ <h5 th:text="${product.productName}">상품명</h5>
<nav aria-label="Page navigation example" class="d-flex justify-content-center">
<ul class="pagination">
<li class="page-item" th:classappend="${page == 1} ? 'disabled' : ''">
<a class="page-link" th:href="@{/product/search(q=${q}, p=${page - 1})}" aria-label="Previous">
<a class="page-link" th:href="@{/product/search(q=${q}, p=${page - 1}, sortField=${sortField}, sortDir=${sortDir})}" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
<li th:each="pageNum : ${#numbers.sequence(1, totalPages)}" class="page-item" th:classappend="${pageNum == page} ? 'active' : ''">
<a class="page-link" th:href="@{/product/search(q=${q}, p=${pageNum})}" th:text="${pageNum}">1</a>
<a class="page-link" th:href="@{/product/search(q=${q}, p=${pageNum}, sortField=${sortField}, sortDir=${sortDir})}" th:text="${pageNum}">1</a>
</li>
<li class="page-item" th:classappend="${page == totalPages} ? 'disabled' : ''">
<a class="page-link" th:href="@{/product/search(q=${q}, p=${page + 1})}" aria-label="Next">
<a class="page-link" th:href="@{/product/search(q=${q}, p=${page + 1}, sortField=${sortField}, sortDir=${sortDir})}" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
Expand Down

0 comments on commit 35ea59c

Please sign in to comment.