Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
import site.kikihi.custom.global.response.ApiResponse;
import site.kikihi.custom.global.response.page.PageRequest;
import site.kikihi.custom.global.response.page.SliceResponse;
import site.kikihi.custom.platform.adapter.in.web.dto.request.custom.CustomCategoryType;
import site.kikihi.custom.platform.adapter.in.web.dto.request.custom.CustomKeyboardRequest;
import site.kikihi.custom.platform.adapter.in.web.dto.response.custom.CustomKeyboardLayoutResponse;
import site.kikihi.custom.platform.adapter.in.web.dto.response.custom.CustomKeyboardDetailResponse;
import site.kikihi.custom.platform.adapter.in.web.dto.response.custom.CustomKeyboardListResponse;
import site.kikihi.custom.platform.adapter.in.web.dto.response.product.ProductListResponse;
import site.kikihi.custom.platform.adapter.in.web.swagger.CustomKeyboardControllerSpec;
import site.kikihi.custom.platform.application.in.custom.CustomKeyboardUseCase;
import site.kikihi.custom.platform.application.in.product.ProductUseCase;
import site.kikihi.custom.platform.domain.custom.CustomKeyboardLayout;
import site.kikihi.custom.platform.domain.custom.CustomKeyboardWithName;
import site.kikihi.custom.security.oauth2.domain.PrincipalDetails;
Expand All @@ -23,6 +23,7 @@
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping("/api/v1/custom")
Expand All @@ -31,9 +32,6 @@ public class CustomKeyboardController implements CustomKeyboardControllerSpec {

private final CustomKeyboardUseCase service;

/// 상품 조회를 위한 의존성
private final ProductUseCase productService;

/**
* 커스텀 키보드 저장
*
Expand Down Expand Up @@ -119,11 +117,14 @@ public ApiResponse<List<CustomKeyboardLayoutResponse>> getCustomKeyboardLayout()
@GetMapping("/products")
public ApiResponse<SliceResponse<ProductListResponse>> getCustomKeyboardProductsByLayout(
@AuthenticationPrincipal PrincipalDetails principalDetails,
@RequestParam String categoryId,
@RequestParam CustomCategoryType category,
@RequestParam CustomKeyboardLayout layout,
PageRequest pageRequest
) {

/// 유저가 없다면 null 저장
UUID userId = principalDetails != null ? principalDetails.getId() : null;

/// Pageable
Pageable pageable = org.springframework.data.domain.PageRequest.of(
pageRequest.getPage() - 1,
Expand All @@ -132,7 +133,7 @@ public ApiResponse<SliceResponse<ProductListResponse>> getCustomKeyboardProducts
);

/// 서비스
Slice<ProductListResponse> content = productService.getProductsByLayout(principalDetails.getId(), categoryId, layout, pageable);
Slice<ProductListResponse> content = service.getCustomProducts(userId, category.getValue(), layout, pageable);

/// DTO 변경
Slice<ProductListResponse> dtoSlice = new SliceImpl<>(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package site.kikihi.custom.platform.adapter.in.web.converter;

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import site.kikihi.custom.global.response.ErrorCode;
import site.kikihi.custom.platform.adapter.in.web.dto.request.custom.CustomCategoryType;

/**
* 파라미터 변환을 위한 컨버터입니다.
*/
@Component
public class CustomCategoryTypeConverter implements Converter<String, CustomCategoryType> {

/**
* 문자열을 CategoryType enum으로 변환합니다. 대소문자 구분 없이 비교합니다.
* @param source the source object to convert, which must be an instance of {@code S} (never {@code null})
*/
@Override
public CustomCategoryType convert(String source) {
for (CustomCategoryType type : CustomCategoryType.values()) {
if (type.getValue().equalsIgnoreCase(source)) {
return type;
}
}
throw new IllegalArgumentException(ErrorCode.INVALID_INPUT.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package site.kikihi.custom.platform.adapter.in.web.dto.request.custom;


import com.fasterxml.jackson.annotation.JsonValue;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
@Schema(
name = "[요청][커스텀] 커스텀 카테고리 타입 Enum",
description = "커스텀에서 사용하는 카테고리 구분 타입 Enum입니다."
)
public enum CustomCategoryType {

@Schema(description = "하우징(프레임)", example = "housing")
HOUSING("housing"),

@Schema(description = "스위치", example = "switch")
SWITCH("switch"),

@Schema(description = "키캡", example = "keycap")
KEYCAP("keycap"),

@Schema(description = "액세서리(기타)", example = "accessory")
ACCESSORY("accessory"),
;

private final String value;

@JsonValue
public String getValue() {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import site.kikihi.custom.global.response.ApiResponse;
import site.kikihi.custom.global.response.page.PageRequest;
import site.kikihi.custom.global.response.page.SliceResponse;
import site.kikihi.custom.platform.adapter.in.web.dto.request.custom.CustomCategoryType;
import site.kikihi.custom.platform.adapter.in.web.dto.request.custom.CustomKeyboardRequest;
import site.kikihi.custom.platform.adapter.in.web.dto.response.custom.CustomKeyboardLayoutResponse;
import site.kikihi.custom.platform.adapter.in.web.dto.response.custom.CustomKeyboardDetailResponse;
Expand Down Expand Up @@ -93,7 +94,7 @@ ApiResponse<SliceResponse<CustomKeyboardListResponse>> getMyCustoms(
)
ApiResponse<SliceResponse<ProductListResponse>> getCustomKeyboardProductsByLayout(
@AuthenticationPrincipal PrincipalDetails principalDetails,
@RequestParam String categoryId,
@RequestParam CustomCategoryType category,
@RequestParam CustomKeyboardLayout layout,
PageRequest pageRequest
);
Expand All @@ -110,10 +111,10 @@ ApiResponse<Void> deleteCustomKeyboard(

String REQUEST = """
{
"layout" : "PERCENT_75",
"housingId" : "686bd26d34c3c12ea9b8e7e2",
"layout" : "PERCENT_60",
"housingId" : "68b3f4fedc26d32d8881fdff",
"switchId" : "686bd26d34c3c12ea9b8e7e3",
"keyCapId" : "686bd26d89b5df14c6125f58",
"keyCapId" : "68b3f653dc26d32d8881fe3d",
"name" : "테스트 커스텀"
}
""";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,26 @@ public Map<String, Product> getProductsByIds(List<String> productIds) {
.collect(Collectors.toMap(Product::getId, Function.identity()));
}

/**
* 커스텀에서 사용할 함수
*
* @param type 조회할 타입
* @param pageable 페이징
*/
@Override
public Slice<Product> getProductsAndCategoryByType(String type, String categoryId, Pageable pageable) {

return documentRepository.findByTypeAndCategoryAndIsCustomTrue(type, categoryId, pageable)
.map(ProductDocument::toDomain);
}

@Override
public Slice<Product> getProductsByCategoryAndCustom(String categoryId, Pageable pageable) {
return documentRepository.findByCategoryAndIsCustomTrue(categoryId, pageable)
.map(ProductDocument::toDomain);
}


/**
* 상품 개수 조회
* @param category 카테고리
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ public class ProductDocument {
@Builder.Default
private Map<String, Object> specTable = new java.util.HashMap<>();

@Field("type")
private String type;

@Field("is_custom")
private boolean isCustom;

/// 도메인 변경
public Product toDomain(){
return Product.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,31 @@ Slice<ProductDocument> findByCategoryAndManufacturerAndPriceRange(
Pageable pageable
);


@Query("""
{
'type': ?0,
'category': ?1,
'is_custom': true
}
""")
Slice<ProductDocument> findByTypeAndCategoryAndIsCustomTrue(
String type,
String category,
Pageable pageable
);

@Query("""
{
'category': ?0,
'is_custom': true
}
""")
Slice<ProductDocument> findByCategoryAndIsCustomTrue(
String category,
Pageable pageable
);

/// 아이디 기반 조회
Slice<ProductDocument> findByIdIn(List<String> ids, Pageable pageable);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package site.kikihi.custom.platform.application.in.custom;

import org.springframework.data.domain.Pageable;
import site.kikihi.custom.platform.adapter.in.web.dto.request.custom.CustomKeyboardRequest;
import site.kikihi.custom.platform.adapter.in.web.dto.response.product.ProductListResponse;
import site.kikihi.custom.platform.domain.custom.CustomKeyboard;
import site.kikihi.custom.platform.domain.custom.CustomKeyboardLayout;
import site.kikihi.custom.platform.domain.custom.CustomKeyboardWithName;
Expand Down Expand Up @@ -35,7 +37,8 @@ public interface CustomKeyboardUseCase {
// 나의 커스텀 키보드 목록 조회
CustomKeyboardWithName getCustomKeyboard(Long customKeyboardId);

// 부품 추가하기
// 배열에 맞는 상품 조회하기
Slice<ProductListResponse> getCustomProducts(UUID userId, String categoryId, CustomKeyboardLayout type, Pageable pageable);


/// 삭제
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ public interface ProductPort {
/// 상품 ID들 바탕으로 조회
Map<String, Product> getProductsByIds(List<String> productIds);

Slice<Product> getProductsAndCategoryByType(String type, String categoryId, Pageable pageable);

Slice<Product> getProductsByCategoryAndCustom(String categoryId, Pageable pageable);

/// 상품 개수 조회
Long getProductsCount(String category);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package site.kikihi.custom.platform.application.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import site.kikihi.custom.global.response.ErrorCode;
import site.kikihi.custom.platform.adapter.in.web.dto.request.custom.CustomKeyboardRequest;
import site.kikihi.custom.platform.adapter.in.web.dto.request.product.CategoryType;
import site.kikihi.custom.platform.adapter.in.web.dto.response.product.ProductListResponse;
import site.kikihi.custom.platform.application.in.custom.CustomKeyboardUseCase;
import site.kikihi.custom.platform.application.out.bookmark.BookmarkPort;
import site.kikihi.custom.platform.application.out.custom.CustomKeyboardPort;
import site.kikihi.custom.platform.application.out.product.ProductPort;
import site.kikihi.custom.platform.application.out.user.UserPort;
import site.kikihi.custom.platform.domain.bookmark.Bookmark;
import site.kikihi.custom.platform.domain.custom.CustomKeyboard;
import site.kikihi.custom.platform.domain.custom.CustomKeyboardLayout;
import site.kikihi.custom.platform.domain.custom.CustomKeyboardWithName;
Expand All @@ -18,22 +24,25 @@
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
* 키보드 커스텀 서비스
*/

@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class CustomKeyboardService implements CustomKeyboardUseCase {

/// DB 포트
private final CustomKeyboardPort port;
private final ProductPort productPort;

/// 외부 의존성 처리
private final UserPort userPort;
private final ProductPort productPort;
private final BookmarkPort bookmarkPort;

// =================
// 저장 함수
Expand Down Expand Up @@ -73,6 +82,11 @@ public List<CustomKeyboardLayout> getKeyboardLayouts() {
return CustomKeyboardLayout.getKeyboardLayouts();
}


/**
* 내가 만든 키보드 목록 조회
* @param userId 유저 ID
*/
@Override
public Slice<CustomKeyboardWithName> getCustomKeyboards(UUID userId) {

Expand Down Expand Up @@ -135,6 +149,38 @@ public CustomKeyboardWithName getCustomKeyboard(Long customKeyboardId) {

}

/**
* 키보드 배열을 바탕으로 가능한 상품 목록 조회
*
* @param userId 유저ID
* @param type 조회할 배열 타입
* @param pageable 페이징
*/
@Override
public Slice<ProductListResponse> getCustomProducts(UUID userId, String categoryId, CustomKeyboardLayout type, Pageable pageable) {

Slice<Product> products;
log.info("userId : {}", userId);
log.info("categoryId : {}", categoryId);
log.info("type : {}", type);
log.info("pageable : {}", pageable);

/// 타입을 바탕으로 조회하기
/// 하우징인 경우
if (categoryId.equals(CategoryType.HOUSING.getValue())){
products = productPort.getProductsAndCategoryByType(type.getDb(), categoryId, pageable);
}
/// 키캡인 경우
else if (categoryId.equals(CategoryType.KEYCAP.getValue())) {
products = productPort.getProductsByCategoryAndCustom(categoryId, pageable);
} else {
products = productPort.getProducts(categoryId, pageable);
}

/// 북마크 여부도 파악하기
return toProductListResponse(userId, categoryId, products);
}

// =================
// 삭제 함수
// =================
Expand Down Expand Up @@ -201,4 +247,44 @@ private CustomKeyboard getKeyboard(Long customKeyboardId) {
.orElseThrow(() -> new NoSuchElementException(ErrorCode.CUSTOM_NOT_FOUND.getMessage()));
}

// =================
// 공통 함수
// =================
/**
* 상품 목록 조회를 진행할때, 북마크 여부를 파악하는 함수입니다.
* @param userId 유저 ID
* @param categoryId 카테고리 ID
* @param products 상품 목록
*/
private Slice<ProductListResponse> toProductListResponse(UUID userId, String categoryId, Slice<Product> products) {
/// 응답 값
List<ProductListResponse> dtoList;

/// 상품 목록 꺼내서 DTO 변환
List<Product> content = products.getContent();

/// 로그인 하지 않은 유저가 확인한다면
if (userId == null) {

/// 하트가 전부 false 되는 로직
dtoList = ProductListResponse.from(content);

/// 새로운 Slice 객체로 생성
return new SliceImpl<>(dtoList, products.getPageable(), products.hasNext());
}

/// 유저가 북마크를 했는지 체크
List<Bookmark> bookmarks = bookmarkPort.getBookmarksByUserIdAndCategoryId(userId, categoryId);

/// 북마크된 상품 ID만 추출
Set<String> bookmarkedProductIds = bookmarks.stream()
.map(Bookmark::getProductId)
.collect(Collectors.toSet());

// 북마크 여부 반영하여 DTO 변환
dtoList = ProductListResponse.from(content, bookmarkedProductIds);

return new SliceImpl<>(dtoList, products.getPageable(), products.hasNext());
}

}
Loading
Loading