Skip to content

Commit

Permalink
Merge pull request #28 from KUIT-Couphone/feature/brand
Browse files Browse the repository at this point in the history
feat: 브랜드 조회 필터링 추가
  • Loading branch information
versatile0010 authored Aug 8, 2023
2 parents aa1fe30 + d34b7c5 commit 96b4099
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 70 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.example.couphoneserver.controller;

import com.example.couphoneserver.common.annotation.NoAuth;
import com.example.couphoneserver.common.exception.BadRequestException;
import com.example.couphoneserver.common.exception.InternalServerErrorException;
import com.example.couphoneserver.common.response.BaseResponse;
Expand All @@ -9,6 +8,7 @@
import com.example.couphoneserver.dto.brand.PostBrandRequest;
import com.example.couphoneserver.dto.brand.PostBrandResponse;
import com.example.couphoneserver.service.BrandService;
import com.example.couphoneserver.service.MemberService;
import com.example.couphoneserver.utils.S3Uploader;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
Expand All @@ -33,6 +33,7 @@
@RequestMapping("/brands")
public class BrandController {
private final BrandService brandService;
private final MemberService memberService;
private final S3Uploader s3Uploader;

@PreAuthorize("hasRole('ADMIN')")
Expand All @@ -57,25 +58,30 @@ public BaseResponse<PostBrandResponse> postBrand(@RequestPart PostBrandRequest r

@PreAuthorize("hasRole('MEMBER') or hasRole('ADMIN')")
@GetMapping("")
@Operation(summary = "브랜드 조회",
@Operation(summary = "브랜드 조회 (검색어 or 카테고리별)",
description =
"""
브랜드를 검색어 또는 카테고리별로 조회합니다.
Query String으로 카테고리 ID를 담아서 보내주시면 카테고리별로 브랜드를 조회하고, 검색어 담아서 보내주시면 검색한 이름에 따라 브랜드를 조회합니다.
Header에 Access Token, Query String으로 정렬 옵션 담아주세요.
- [ROLE_MEMBER OR ROLE_ADMIN]
- Header에 Access Token 담아주세요!
- Query String으로 카테고리 ID를 담아서 보내주시면 카테고리별로 브랜드를 조회하고, 검색어 담아서 보내주시면 검색한 이름에 따라 브랜드를 조회합니다.
- 1(default): 쿠폰 많은 순, 생성 시간 빠른 순
- 2: 생성 시간 빠른 순, 쿠폰 많은 순
- 3: 브랜드 이름 순
""",
security = @SecurityRequirement(name = "bearerAuth"))
public BaseResponse<List<GetBrandResponse>> getBrand(@RequestParam(required = false, value = "category-id") Long categoryId,
@RequestParam(required = false, value = "name") String name,
@RequestParam(required = false, defaultValue = "1", value = "sorted-by") int sortedBy,
Principal principal) {

Long memberId = memberService.findMemberIdByPrincipal(principal);

if ((categoryId != null) && (name == null)) {
return new BaseResponse<>(brandService.findByCategoryId(principal, categoryId));
return new BaseResponse<>(brandService.findByCategoryId(memberId, categoryId, sortedBy));
}

if ((categoryId == null) && (name != null)) {
return new BaseResponse<>(brandService.findByNameContaining(principal, name));
return new BaseResponse<>(brandService.findByNameContaining(memberId, name, sortedBy));
}

throw new BadRequestException(BAD_REQUEST);
Expand All @@ -92,7 +98,7 @@ public BaseResponse<List<GetBrandResponse>> getBrand(@RequestParam(required = fa
security = @SecurityRequirement(name = "bearerAuth"))
public BaseResponse<GetBrandDetailResponse> getBrandDetail(@PathVariable(value = "brand-id") Long brandId,
Principal principal) {

return new BaseResponse<>(brandService.getBrandDetail(brandId, principal));
Long memberId = memberService.findMemberIdByPrincipal(principal);
return new BaseResponse<>(brandService.getBrandDetail(brandId, memberId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ public class GetBrandResponse {
@Schema(description = "스탬프 적립 개수", example = "3")
int stampCount;

@Schema(description = "생성 시간", example = "2023-07-29 18:35:46.434060")
@Schema(description = "쿠폰 생성 시간", example = "2023-07-29 18:35:46.434060")
LocalDateTime createdDate;

public GetBrandResponse(Brand brand, int stampCount) {
public GetBrandResponse(Brand brand, int stampCount, LocalDateTime createdDate) {
this.id = brand.getId();
this.name = brand.getName();
this.rewardDescription = brand.getRewardDescription();
this.brandImageUrl = brand.getBrandImageUrl();
this.stampCount = stampCount;
this.createdDate = brand.getCreatedDate();
this.createdDate = createdDate;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public interface BrandRepository extends JpaRepository<Brand, Long> {
Optional<Brand> findById(Long id);
Optional<List<Brand>> findAllByNameContaining(String name);
Optional<List<Brand>> findAllByCategoryId(Long categoryId);
Optional<List<Brand>> findAllByCategoryIdOrderByName(Long categoryId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ public interface CouponItemRepository extends JpaRepository<CouponItem, Long> {
CouponItem findByMemberIdAndBrandIdAndStatus(Long mid, Long bid, CouponItemStatus status);

@Query("select c from CouponItem c " +
"where c.brand.id = :bid and c.member.id = :mid " +
"and c.status <> 'EXPIRED' " +
"ORDER BY c.stampCount DESC, c.createdDate ASC")
"where c.brand.id = :bid and c.member.id = :mid " +
"and c.status <> 'EXPIRED'")
CouponItem findByMemberIdAndBrandIdAndStatusNotExpired(@Param("mid") Long mid, @Param("bid") Long bid);


List<CouponItem> findAllByMemberIdAndBrandId(Long mid, Long bid);

Optional<CouponItem> findById(Long couponId);
Expand Down
149 changes: 97 additions & 52 deletions src/main/java/com/example/couphoneserver/service/BrandService.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.example.couphoneserver.service;

import com.example.couphoneserver.common.exception.*;
import com.example.couphoneserver.domain.CouponItemStatus;
import com.example.couphoneserver.domain.entity.Brand;
import com.example.couphoneserver.domain.entity.Category;
import com.example.couphoneserver.domain.entity.CouponItem;
import com.example.couphoneserver.domain.entity.Member;
import com.example.couphoneserver.dto.brand.GetBrandDetailResponse;
import com.example.couphoneserver.dto.brand.GetBrandResponse;
import com.example.couphoneserver.dto.brand.PostBrandRequest;
Expand All @@ -14,13 +12,9 @@
import com.example.couphoneserver.repository.BrandRepository;
import com.example.couphoneserver.repository.CategoryRepository;
import com.example.couphoneserver.repository.CouponItemRepository;
import com.example.couphoneserver.repository.MemberRepository;
import com.example.couphoneserver.utils.S3Uploader;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.security.Principal;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -32,10 +26,6 @@ public class BrandService {
private final BrandRepository brandRepository;
private final CategoryRepository categoryRepository;
private final CouponItemRepository couponItemRepository;
private final MemberRepository memberRepository;

private final MemberService memberService;


public PostBrandResponse saveBrand(PostBrandRequest request, String brandImageUrl) {
// 카테고리 존재하는지 검사
Expand All @@ -44,7 +34,6 @@ public PostBrandResponse saveBrand(PostBrandRequest request, String brandImageUr
// 브랜드 이름 중복 검사
existsBrandByName(request.getName());


// 브랜드 저장
Brand brand = brandRepository.save(request.toEntity(category, brandImageUrl));

Expand All @@ -55,45 +44,34 @@ public PostBrandResponse saveBrand(PostBrandRequest request, String brandImageUr
return new PostBrandResponse(brand);
}

public List<GetBrandResponse> findByCategoryId(Principal principal, Long categoryId) {

// 멤버 ID
Long memberId = findMemberIdByPrincipal(principal);

// 멤버 존재하는지 검사
findMemberById(memberId);
public List<GetBrandResponse> findByCategoryId(Long memberId, Long categoryId, int sortedBy) {
List<Brand> brands;

// 카테고리 존재하는지 검사
findCategoryById(categoryId);

// 카테고리로 브랜드 찾기
List<Brand> brands = brandRepository.findAllByCategoryId(categoryId)
.orElseThrow(() -> new BrandException(BRAND_NOT_FOUND));
if (sortedBy == 3) {
brands = brandRepository.findAllByCategoryIdOrderByName(categoryId)
.orElseThrow(() -> new BrandException(BRAND_NOT_FOUND));
} else {
brands = brandRepository.findAllByCategoryId(categoryId)
.orElseThrow(() -> new BrandException(BRAND_NOT_FOUND));
}

return getNotExpiredBrandList(memberId, brands);
return getNotExpiredBrandListByCategoryId(memberId, categoryId, brands, sortedBy);
}

public List<GetBrandResponse> findByNameContaining(Principal principal, String name) {

// 멤버 ID
Long memberId = findMemberIdByPrincipal(principal);

// 멤버 존재하는지 검사
findMemberById(memberId);
public List<GetBrandResponse> findByNameContaining(Long memberId, String name, int sortedBy) {

// 검색어로 브랜드 찾기
List<Brand> brands = brandRepository.findAllByNameContaining(name)
.orElseThrow(() -> new BrandException(BRAND_NOT_FOUND));

return getNotExpiredBrandList(memberId, brands);
return getNotExpiredBrandListByName(memberId, name, brands, sortedBy);
}

public GetBrandDetailResponse getBrandDetail(Long brandId, Principal principal) {
// 멤버 ID
Long memberId = findMemberIdByPrincipal(principal);

// 멤버 존재하는지 검사
findMemberById(memberId);
public GetBrandDetailResponse getBrandDetail(Long brandId, Long memberId) {

// 브랜드 존재하는지 검사
Brand brand = findById(brandId);
Expand All @@ -118,36 +96,103 @@ private Category findCategoryById(Long categoryId) {
.orElseThrow(() -> new CategoryException(CATEGORY_NOT_FOUND));
}

private Member findMemberById(Long memberId) {
return memberRepository.findById(memberId)
.orElseThrow(() -> new MemberException(MEMBER_NOT_FOUND));
}

private void existsBrandByName(String name) {
if (brandRepository.existsByName(name)) {
throw new BrandException(DUPLICATE_BRAND_NAME);
}
}

private Long findMemberIdByPrincipal(Principal principal) {
String email = principal.getName();
return memberService.findOneByEmail(email).getId();
}

private List<GetBrandResponse> getNotExpiredBrandList(Long memberId, List<Brand> brands) {
private List<GetBrandResponse> getNotExpiredBrandListByCategoryId(Long memberId, Long categoryId, List<Brand> brands, int sortedBy) {
List<GetBrandResponse> brandList = new ArrayList<>();

for (Brand brand : brands) {
List<CouponItem> couponItems;
List<Long> brandIdx = new ArrayList<>();

if (sortedBy == 3) {
for (Brand brand : brands) {
// 쿠폰 찾기
CouponItem couponItem = couponItemRepository.findByMemberIdAndBrandIdAndStatusNotExpired(memberId, brand.getId());

if (couponItem == null) {
brandList.add(new GetBrandResponse(brand, 0, null));
} else {
brandList.add(new GetBrandResponse(brand, couponItem.getStampCount(), couponItem.getCreatedDate()));
}
}
} else {
// 쿠폰 찾기
CouponItem couponItem = couponItemRepository.findByMemberIdAndBrandIdAndStatusNotExpired(memberId, brand.getId());
couponItems = (sortedBy == 1)? couponItemRepository.findByMemberIdOrderByStampCountAndCreatedDate(memberId)
: couponItemRepository.findByMemberIdOrderByCreatedDateAndStampCount(memberId);

// 사용자가 쿠폰을 가지고 있는 브랜드 먼저 추가
for (CouponItem couponItem: couponItems) {
if (getCategoryIdByCouponItem(couponItem) != categoryId) {
continue;
}
brandIdx.add(couponItem.getBrand().getId());
brandList.add(new GetBrandResponse(couponItem.getBrand(), couponItem.getStampCount(), couponItem.getCreatedDate()));
}

if (couponItem == null) { // 해당 브랜드에 쿠폰이 없을 경우
brandList.add(new GetBrandResponse(brand, 0));
} else { // 해당 브랜드에 쿠폰이 있을 경우
brandList.add(new GetBrandResponse(brand, couponItem.getStampCount()));
// 나머지 브랜드 추가
for (Brand brand : brands) {
if (brandIdx.contains(brand.getId())) {
continue;
}

brandList.add(new GetBrandResponse(brand, 0, null));
}
}

return brandList;
}

private List<GetBrandResponse> getNotExpiredBrandListByName(Long memberId, String name, List<Brand> brands, int sortedBy) {
List<GetBrandResponse> brandList = new ArrayList<>();
List<CouponItem> couponItems;
List<Long> brandIdx = new ArrayList<>();

if (sortedBy == 3) {
for (Brand brand : brands) {
// 쿠폰 찾기
CouponItem couponItem = couponItemRepository.findByMemberIdAndBrandIdAndStatusNotExpired(memberId, brand.getId());

if (couponItem == null) {
brandList.add(new GetBrandResponse(brand, 0, null));
} else {
brandList.add(new GetBrandResponse(brand, couponItem.getStampCount(), couponItem.getCreatedDate()));
}
}
} else {
// 쿠폰 찾기
couponItems = (sortedBy == 1) ? couponItemRepository.findByMemberIdOrderByStampCountAndCreatedDate(memberId)
: couponItemRepository.findByMemberIdOrderByCreatedDateAndStampCount(memberId);

// 사용자가 쿠폰을 가지고 있는 브랜드 먼저 추가
for (CouponItem couponItem : couponItems) {
if (!getBrandNameByCouponItem(couponItem).contains(name)) {
continue;
}
brandIdx.add(couponItem.getBrand().getId());
brandList.add(new GetBrandResponse(couponItem.getBrand(), couponItem.getStampCount(), couponItem.getCreatedDate()));
}

// 나머지 브랜드 추가
for (Brand brand : brands) {
if (brandIdx.contains(brand.getId())) {
continue;
}

brandList.add(new GetBrandResponse(brand, 0, null));
}
}
return brandList;
}

private Long getCategoryIdByCouponItem(CouponItem couponItem) {
return couponItem.getBrand().getCategory().getId();
}

private String getBrandNameByCouponItem(CouponItem couponItem) {
return couponItem.getBrand().getName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ public GetMemberCouponBrandsResponse getBrands(Long memberId, int option) {
}
}
List<BrandDto> brands = coupons.stream().map(coupon -> {
GetBrandResponse brandInfo = new GetBrandResponse(coupon.getBrand(), coupon.getStampCount());
GetBrandResponse brandInfo = new GetBrandResponse(coupon.getBrand(), coupon.getStampCount(), coupon.getCreatedDate());
return new BrandDto(brandInfo, coupon.getStatus());
}).toList();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ public GetBrandResponse getGetBrandResponse(Principal principal, Long id) {
CouponItem couponItem = couponItemRepository.findByMemberIdAndBrandIdAndStatus(memberId, id, CouponItemStatus.ACTIVE);

if (couponItem == null) // 해당 브랜드에 쿠폰이 없을 경우
return new GetBrandResponse(brand, 0);
return new GetBrandResponse(brand, couponItem.getStampCount());
return new GetBrandResponse(brand, 0, null);
return new GetBrandResponse(brand, couponItem.getStampCount(), couponItem.getCreatedDate());
}

private Long findMemberIdByPrincipal(Principal principal) {
Expand Down

0 comments on commit 96b4099

Please sign in to comment.