Skip to content

Commit

Permalink
Merge pull request #64 from lotteon2/feat/methods-for-ux
Browse files Browse the repository at this point in the history
Feat/methods for ux
  • Loading branch information
CokeLee777 authored Jan 18, 2024
2 parents 3503920 + f70a46a commit cddcfb8
Show file tree
Hide file tree
Showing 20 changed files with 314 additions and 159 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
import com.dailyon.productservice.brand.service.BrandService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/brands")
Expand All @@ -19,4 +17,12 @@ public class BrandController {
public ResponseEntity<ReadBrandListResponse> readBrands() {
return ResponseEntity.ok(brandService.readAllBrands());
}

/*
브랜드 이름으로 검색. 관리자 페이지 및 회원 페이지에서 모두 사용할 듯
*/
@GetMapping("/name/{name}")
public ResponseEntity<ReadBrandListResponse> findBrandsByName(@PathVariable String name) {
return ResponseEntity.ok(brandService.findBrandsByName(name));
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package com.dailyon.productservice.brand.repository;

import com.dailyon.productservice.brand.entity.Brand;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface BrandRepository extends JpaRepository<Brand, Long> {
boolean existsByName(String name);
List<Brand> findBrandsByNameContainsOrderByName(String name);
Page<Brand> findAllByOrderByNameAsc(Pageable pageable);
List<Brand> findAllByOrderByNameAsc();
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ public CreateBrandResponse createBrand(CreateBrandRequest createBrandRequest) {
}

public ReadBrandListResponse readAllBrands() {
return ReadBrandListResponse.fromEntity(brandRepository.findAll());
return ReadBrandListResponse.fromEntity(brandRepository.findAllByOrderByNameAsc());
}

public ReadBrandListResponse findBrandsByName(String name) {
return ReadBrandListResponse.fromEntity(brandRepository.findBrandsByNameContainsOrderByName(name));
}

@Transactional
Expand All @@ -52,7 +56,7 @@ public void updateBrand(Long id, UpdateBrandRequest updateBrandRequest) {
}

public ReadBrandPageResponse readBrandPage(Pageable pageable) {
return ReadBrandPageResponse.fromEntity(brandRepository.findAll(pageable));
return ReadBrandPageResponse.fromEntity(brandRepository.findAllByOrderByNameAsc(pageable));
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import com.dailyon.productservice.category.service.CategoryService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
Expand Down Expand Up @@ -38,6 +36,14 @@ public ResponseEntity<ReadCategoryPageResponse> readCategoryPages(Pageable pagea
return ResponseEntity.status(HttpStatus.OK).body(categoryService.readCategoryPages(pageable));
}

/*
카테고리 이름으로 검색. 관리자 페이지에서 사용할 듯
*/
@GetMapping("/categories/name/{name}")
public ResponseEntity<ReadAllCategoryListResponse> findCategoriesByName(@PathVariable String name) {
return ResponseEntity.status(HttpStatus.OK).body(categoryService.findCategoriesByName(name));
}

@GetMapping("/categories/leaf")
public ResponseEntity<ReadChildrenCategoryListResponse> readLeafCategories() {
return ResponseEntity.status(HttpStatus.OK).body(categoryService.readLeafCategories());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.dailyon.productservice.category.repository;

import com.dailyon.productservice.category.entity.Category;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
Expand All @@ -13,7 +12,11 @@
public interface CategoryRepository extends JpaRepository<Category, Long> {
boolean existsByName(String name);

List<Category> findByMasterCategory_Id(Long masterCategoryId);
List<Category> findByMasterCategory_IdOrderByNameAsc(Long masterCategoryId);

List<Category> findAllByOrderByNameAsc();

List<Category> findCategoriesByNameContainsOrderByNameAsc(String name);

@Query(nativeQuery = true, value =
"WITH RECURSIVE LeafCategory(id) AS (" +
Expand All @@ -30,7 +33,7 @@ public interface CategoryRepository extends JpaRepository<Category, Long> {
"WHERE c.is_deleted = false) " +
"SELECT c.* FROM category AS c " +
"INNER JOIN LeafCategory AS ct ON c.id = ct.id AND " +
"c.is_deleted = false")
"c.is_deleted = false ORDER BY c.name ASC")
List<Category> findLeafCategories();

@Query(nativeQuery = true, value =
Expand All @@ -46,6 +49,6 @@ public interface CategoryRepository extends JpaRepository<Category, Long> {
"WHERE c.is_deleted = false)" +
"SELECT c.* FROM category AS c " +
"INNER JOIN CategoryTree AS ct ON c.id = ct.id AND " +
"c.is_deleted = false")
"c.is_deleted = false ORDER BY c.name ASC")
List<Category> findAllChildCategories(@Param("categoryId") Long categoryId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,17 @@ public CreateCategoryResponse createCategory(CreateCategoryRequest createCategor
}

public ReadChildrenCategoryListResponse readChildrenCategoriesByMaster(Long masterCategoryId) {
return ReadChildrenCategoryListResponse.fromEntity(categoryRepository.findByMasterCategory_Id(masterCategoryId));
return ReadChildrenCategoryListResponse.fromEntity(
categoryRepository.findByMasterCategory_IdOrderByNameAsc(masterCategoryId)
);
}

public ReadAllCategoryListResponse readAllCategories() {
return ReadAllCategoryListResponse.fromEntity(categoryRepository.findAll());
return ReadAllCategoryListResponse.fromEntity(categoryRepository.findAllByOrderByNameAsc());
}

public ReadAllCategoryListResponse findCategoriesByName(String name) {
return ReadAllCategoryListResponse.fromEntity(categoryRepository.findCategoriesByNameContainsOrderByNameAsc(name));
}

public ReadBreadCrumbListResponse readBreadCrumbs(Long id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,43 @@
import java.util.List;

@RestController
@RequestMapping("/admin")
@RequestMapping("/admin/products")
@RequiredArgsConstructor
public class ProductAdminController {
private final ProductFacade productFacade;
@PostMapping("/products")
public ResponseEntity<CreateProductResponse> createProduct(@Valid @RequestBody CreateProductRequest createProductRequest) {
@PostMapping
public ResponseEntity<CreateProductResponse> createProduct(
@Valid @RequestBody CreateProductRequest createProductRequest
) {
return ResponseEntity.status(HttpStatus.CREATED).body(productFacade.createProduct(createProductRequest));
}

@PutMapping("/products/{productId}")
public ResponseEntity<UpdateProductResponse> updateProduct(@PathVariable Long productId,
@RequestBody UpdateProductRequest updateProductRequest) {
@PutMapping("/{productId}")
public ResponseEntity<UpdateProductResponse> updateProduct(
@PathVariable Long productId,
@RequestBody UpdateProductRequest updateProductRequest
) {
return ResponseEntity.status(HttpStatus.OK).body(productFacade.updateProduct(productId, updateProductRequest));
}

@GetMapping("/products")
ResponseEntity<ReadProductPageResponse> readProductPage(@RequestParam(required = false) Long brandId,
@RequestParam(required = false) Long categoryId,
@RequestParam ProductType type,
Pageable pageable) {
return ResponseEntity.status(HttpStatus.OK).body(productFacade.readProductPage(brandId, categoryId, type, pageable));
@GetMapping
ResponseEntity<ReadProductPageResponse> readProductPage(
@RequestParam(required = false) Long brandId,
@RequestParam(required = false) Long categoryId,
@RequestParam ProductType type,
@RequestParam(required = false) String query,
@PageableDefault(
size = 5,
sort = {"updatedAt"},
direction = Sort.Direction.DESC
) Pageable pageable
) {
return ResponseEntity.status(HttpStatus.OK).body(
productFacade.readProductPage(brandId, categoryId, type, query, pageable)
);
}

@DeleteMapping("/products")
@DeleteMapping
ResponseEntity<Void> deleteProducts(@RequestParam List<Long> ids) {
productFacade.deleteProducts(ids);
return ResponseEntity.status(HttpStatus.OK).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,39 @@ ResponseEntity<ReadProductDetailResponse> readProductDetail(@PathVariable Long p
return ResponseEntity.status(HttpStatus.OK).body(productFacade.readProductDetail(productId));
}

/**
* 쇼핑몰 화면에서 무한 스크롤 위한 조회 api
* @param lastVal 최초 호출 시 direction이 asc면 0, desc면 큰 값
* @param type 상품 타입(NORMAL, AUCTION)
* @param brandId 브랜드 id
* @param categoryId 카테고리 id(카테고리 지정하면 하위 카테고리들 포함)
* @param gender 성별(MALE, FEMALE, COMMON)
* @param lowPrice 가격 필터 하한
* @param highPrice 가격 필터 상한
* @param sort 정렬 기준(price, review, rating)
* @param direction 오름/내림차순(asc, desc)
* @param query 상품명 또는 코드
* @return hasNext, List -> List의 마지막값을 lastVal에 저장하고 다음 요청에 포함시켜야 함.
*/
@GetMapping
ResponseEntity<ReadProductSliceResponse> readProductSlice(@RequestParam Long lastId,
@RequestParam(required = false) Long brandId,
@RequestParam(required = false) Long categoryId,
@RequestParam(required = false) Gender gender,
@RequestParam ProductType type) {
return ResponseEntity.status(HttpStatus.OK).body(productFacade.readProductSlice(lastId, brandId, categoryId, gender, type));
}

@GetMapping("/search")
ResponseEntity<ReadProductSliceResponse> searchProducts(@RequestParam Long lastId,
@RequestParam(required = false) String query) {
return ResponseEntity.status(HttpStatus.OK).body(productFacade.searchProductSlice(lastId, query));
ResponseEntity<ReadProductSliceResponse> readProductSlice(
@RequestParam(required = false) String lastVal,
@RequestParam(required = false, defaultValue = "NORMAL") ProductType type,
@RequestParam(required = false) Long brandId,
@RequestParam(required = false) Long categoryId,
@RequestParam(required = false) Gender gender,
@RequestParam(required = false) Integer lowPrice,
@RequestParam(required = false) Integer highPrice,
@RequestParam(required = false) String query,
@RequestParam(required = false) String sort,
@RequestParam(required = false) String direction
) {
return ResponseEntity.status(HttpStatus.OK).body(
productFacade.readProductSlice(
lastVal, brandId, categoryId, gender, type,
lowPrice, highPrice, query, sort, direction
)
);
}

@GetMapping("/search/ootd")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public static ReadOOTDSearchSliceResponse fromEntity(Slice<Product> products) {
return ReadOOTDSearchSliceResponse.builder()
.hasNext(products.hasNext())
.products(products.stream()
.filter(product -> !product.getProductStocks().isEmpty())
.map(ReadOOTDSearchResponse::fromEntity)
.collect(Collectors.toList()))
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class ReadProductAdminResponse {
private Integer price;
private String code;
private String imgUrl;
private Double avgRating;
private Long reviewCount;
private List<ReadProductStockAdminResponse> productStocks;
private List<String> describeImgUrls;

Expand All @@ -37,6 +39,8 @@ public static ReadProductAdminResponse fromEntity(Product product) {
.price(product.getPrice())
.code(product.getCode())
.imgUrl(product.getImgUrl())
.avgRating(product.getReviewAggregate().getAvgRating())
.reviewCount(product.getReviewAggregate().getReviewCount())
.productStocks(product.getProductStocks().stream()
.map(ReadProductStockAdminResponse::fromEntity)
.collect(Collectors.toList()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import lombok.NoArgsConstructor;
import org.springframework.data.domain.Slice;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -43,6 +44,7 @@ public static class ReadProductResponse {
private String imgUrl;
private Double avgRating;
private Long reviewCount;
private LocalDateTime createdAt;
private List<CouponInfoItemResponse> coupons;

public static ReadProductResponse create(Product product, List<CouponInfoItemResponse> coupons) {
Expand All @@ -56,6 +58,7 @@ public static ReadProductResponse create(Product product, List<CouponInfoItemRes
.imgUrl(product.getImgUrl())
.avgRating(product.getReviewAggregate().getAvgRating())
.reviewCount(product.getReviewAggregate().getReviewCount())
.createdAt(product.getCreatedAt())
.coupons(coupons)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,13 @@ public ReadProductDetailResponse readProductDetail(Long productId) {
return productService.readProductDetail(productId);
}

public ReadProductSliceResponse readProductSlice(Long lastId, Long brandId, Long categoryId,
Gender gender, ProductType productType) {
Slice<Product> products = productService.readProductSlice(lastId, brandId, categoryId, gender, productType);

MultipleProductCouponsResponse response = promotionFeignClient.getCouponsForProducts(
MultipleProductCouponsRequest.fromEntity(products.getContent())
).getBody();

return ReadProductSliceResponse.create(products, response.getCoupons());
}

public ReadProductSliceResponse searchProductSlice(Long lastId, String query) {
Slice<Product> products = productService.searchProductSlice(lastId, query);
public ReadProductSliceResponse readProductSlice(
String lastVal, Long brandId, Long categoryId, Gender gender, ProductType productType,
Integer lowPrice, Integer highPrice, String query, String sort, String direction
) {
Slice<Product> products = productService.readProductSlice(
lastVal, brandId, categoryId, gender, productType,
lowPrice, highPrice, query, sort, direction);

MultipleProductCouponsResponse response = promotionFeignClient.getCouponsForProducts(
MultipleProductCouponsRequest.fromEntity(products.getContent())
Expand All @@ -97,8 +91,8 @@ public ReadOOTDSearchSliceResponse searchFromOOTD(Long lastId, String query) {
return productService.searchFromOOTD(lastId, query);
}

public ReadProductPageResponse readProductPage(Long brandId, Long categoryId, ProductType type, Pageable pageable) {
return productService.readProductPage(brandId, categoryId, type, pageable);
public ReadProductPageResponse readProductPage(Long brandId, Long categoryId, ProductType type, String query, Pageable pageable) {
return productService.readProductPage(brandId, categoryId, type, query, pageable);
}

@Cacheable(value = "newProducts", unless = "#result == null")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@
import java.util.List;

public interface ProductCustomRepository {
Slice<Product> findProductSlice(Long lastId, Long brandId, List<Category> childCategories,
Gender gender, ProductType productType);
Slice<Product> findProductSlice(
String lastVal, Long brandId, List<Category> childCategories, Gender gender, ProductType productType,
Integer lowPrice, Integer highPrice, String query, String sort, String direction
);

Page<Product> findProductPage(Long brandId, List<Category> childCategories, ProductType type, Pageable pageable);

Slice<Product> searchProducts(Long lastId, String query);
Page<Product> findProductPage(
Long brandId, List<Category> childCategories,
ProductType type, String query, Pageable pageable
);

Slice<Product> searchProductsFromOOTD(Long lastId, String query);
}
Loading

0 comments on commit cddcfb8

Please sign in to comment.