Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] 추천 전략 적용 #154

Merged
merged 20 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from 16 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 @@ -2,14 +2,14 @@


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.transaction.annotation.Transactional;
import tify.server.api.common.slice.SliceResponse;
import tify.server.api.config.security.SecurityUtils;
import tify.server.api.product.model.dto.ProductFilterCondition;
import tify.server.api.product.model.vo.ProductRetrieveVo;
import tify.server.core.annotation.UseCase;
Expand All @@ -20,18 +20,22 @@
import tify.server.domain.domains.product.dto.model.ProductRetrieveDto;
import tify.server.domain.domains.question.adaptor.FavorQuestionAdaptor;
import tify.server.domain.domains.question.domain.FavorQuestionCategory;
import tify.server.domain.domains.question.strategy.ProductRecommendationStrategy;
import tify.server.domain.domains.question.strategy.ProductRecommendationStrategyFactory;

@UseCase
@RequiredArgsConstructor
public class RetrieveProductListUseCase {

private final ProductAdaptor productAdaptor;
private final FavorQuestionAdaptor favorQuestionAdaptor;
private final ProductRecommendationStrategyFactory strategyFactory;

@Transactional(readOnly = true)
public SliceResponse<ProductRetrieveVo> executeToSmallCategory(
ProductFilterCondition productFilterCondition, Pageable pageable) {
List<Long> categoryIdList = new ArrayList<>();
List<ProductRecommendationStrategy> strategies = new ArrayList<>();
productFilterCondition
.getSmallCategoryList()
.forEach(
Expand All @@ -40,19 +44,30 @@ public SliceResponse<ProductRetrieveVo> executeToSmallCategory(
favorQuestionAdaptor.queryBySmallCategory(category).stream()
.map(FavorQuestionCategory::getId)
.toList());
strategies.addAll(strategyFactory.findStrategy(category));
});

if (productFilterCondition.getPriceOrder().equals(PriceOrder.DEFAULT)
&& productFilterCondition.getPriceFilter().equals(PriceFilter.DEFAULT)) {
// TODO : 추천 전략을 적용하는 부분일듯
List<ProductRetrieveDto> list =
productAdaptor.findAllBySmallCategoryId(
new ProductCategoryCondition(
categoryIdList,
productFilterCondition.getPriceOrder(),
productFilterCondition.getPriceFilter(),
pageable));
Collections.shuffle(list);
List<ProductRetrieveDto> list = new ArrayList<>();
strategies.forEach(
strategy -> {
list.addAll(
strategy
.recommendation(
SecurityUtils.getCurrentUserId(),
strategy.getStrategyName().getValue())
.stream()
.map(
product -> {
return ProductRetrieveDto.of(
product,
favorQuestionAdaptor.queryCategory(
product
.getFavorQuestionCategoryId()));
})
.toList());
});
return SliceResponse.of(
new SliceImpl<>(
list.stream().map(ProductRetrieveVo::from).toList(), pageable, true));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,12 @@ public class ProductRetrieveDto {
private Product product;

private FavorQuestionCategory favorQuestionCategory;

public static ProductRetrieveDto of(
Product product, FavorQuestionCategory favorQuestionCategory) {
return ProductRetrieveDto.builder()
.product(product)
.favorQuestionCategory(favorQuestionCategory)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,10 @@ public List<FavorQuestionCategory> queryBySmallCategory(SmallCategory smallCateg
public List<FavorQuestion> queryAll() {
return favorQuestionRepository.findAll();
}

public FavorQuestionCategory queryCategory(Long favorQuestionCategory) {
return favorQuestionCategoryRepository
.findById(favorQuestionCategory)
.orElseThrow(() -> FavorQuestionCategoryNotFoundException.EXCEPTION);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import tify.server.domain.domains.product.adaptor.ProductAdaptor;
import tify.server.domain.domains.product.domain.Product;
import tify.server.domain.domains.question.adaptor.FavorAnswerAdaptor;
import tify.server.domain.domains.question.domain.FavorAnswer;
import tify.server.domain.domains.question.dto.condition.FavorRecommendationDTO;

@Component
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class BFMOIRecommendationStrategy implements ProductRecommendationStrategy {
Expand All @@ -20,8 +22,7 @@ public class BFMOIRecommendationStrategy implements ProductRecommendationStrateg
private static final String CATEGORY_NAME = "BFMOI";

@Override
public List<Product> recommendation(
Long userId, String categoryName, List<FavorRecommendationDTO> dto) {
public List<Product> recommendation(Long userId, String categoryName) {

List<FavorRecommendationDTO> recommendationDTO = getRecommendationDTO(userId);
List<Product> productList = new ArrayList<>();
Expand Down Expand Up @@ -74,6 +75,11 @@ public List<Product> recommendation(
}
}

@Override
public StrategyName getStrategyName() {
return StrategyName.BFMOI;
}

private List<Product> filterStep(String categoryName, String answer) {
return productAdaptor.queryAllByCategoryNameAndCharacter(categoryName, answer);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,23 @@
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import tify.server.domain.domains.product.adaptor.ProductAdaptor;
import tify.server.domain.domains.product.domain.Product;
import tify.server.domain.domains.question.adaptor.FavorAnswerAdaptor;
import tify.server.domain.domains.question.dto.condition.FavorRecommendationDTO;

@Component
@RequiredArgsConstructor
public class BMPERRecommendationStrategy implements ProductRecommendationStrategy {
public class BFPERRecommendationStrategy implements ProductRecommendationStrategy {

private final ProductAdaptor productAdaptor;
private final FavorAnswerAdaptor favorAnswerAdaptor;

private static final String CATEGORY_NAME = "BMPER";
private static final String CATEGORY_NAME = "BFPER";

@Override
public List<Product> recommendation(
Long userId, String categoryName, List<FavorRecommendationDTO> dto) {
public List<Product> recommendation(Long userId, String categoryName) {

List<FavorRecommendationDTO> recommendationDTO = getRecommendationDTO(userId);
List<Product> productList = new ArrayList<>();
Expand All @@ -32,6 +33,7 @@ public List<Product> recommendation(

/** 2번 스텝(내가 원하는 나의 이미지?) 객관식 2개까지 가능이기 때문에 답변 개수별로 경우를 나눔 */
String[] splitAnswer = recommendationDTO.get(1).getAnswer().split(", ");

if (splitAnswer.length > 1) {
return productList.stream()
.filter(product -> product.getCharacteristic().contains(splitAnswer[0]))
Expand All @@ -47,6 +49,11 @@ public List<Product> recommendation(
}
}

@Override
public StrategyName getStrategyName() {
return StrategyName.valueOf(CATEGORY_NAME);
}

private List<Product> filterStep(String categoryName, String answer) {
return productAdaptor.queryAllByCategoryNameAndCharacter(categoryName, answer);
}
Expand All @@ -57,10 +64,14 @@ private List<FavorRecommendationDTO> getRecommendationDTO(Long userId) {
favorAnswerAdaptor
.searchByCategoryNameAndNumber(userId, CATEGORY_NAME, 1L)
.getAnswerContent();
if (firstAnswer.equals("진한") || firstAnswer.equals("깊은")) {
favorRecommendationDTOs.add(new FavorRecommendationDTO(1L, "퍼퓸, 오드퍼퓸"));
} else if (firstAnswer.equals("은은한") || firstAnswer.equals("가벼운")) {
favorRecommendationDTOs.add(new FavorRecommendationDTO(1L, "오드뚜왈렛, 오드코롱, 샤워코롱"));
if (firstAnswer.equals("진한")) {
favorRecommendationDTOs.add(new FavorRecommendationDTO(1L, " 퍼퓸"));
} else if (firstAnswer.equals("깊은")) {
favorRecommendationDTOs.add(new FavorRecommendationDTO(1L, "오드퍼퓸"));
} else if (firstAnswer.equals("은은한")) {
favorRecommendationDTOs.add(new FavorRecommendationDTO(1L, "오드뚜왈렛"));
} else if (firstAnswer.equals("가벼운")) {
favorRecommendationDTOs.add(new FavorRecommendationDTO(1L, "오드코롱•샤워코롱"));
}

favorRecommendationDTOs.add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import tify.server.domain.domains.product.adaptor.ProductAdaptor;
import tify.server.domain.domains.product.domain.Product;
import tify.server.domain.domains.question.adaptor.FavorAnswerAdaptor;
import tify.server.domain.domains.question.domain.FavorAnswer;
import tify.server.domain.domains.question.dto.condition.FavorRecommendationDTO;

@Component
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class BFPLARecommendationStrategy implements ProductRecommendationStrategy {
Expand All @@ -21,8 +23,7 @@ public class BFPLARecommendationStrategy implements ProductRecommendationStrateg
private final FavorAnswerAdaptor favorAnswerAdaptor;

@Override
public List<Product> recommendation(
Long userId, String categoryName, List<FavorRecommendationDTO> dto) {
public List<Product> recommendation(Long userId, String categoryName) {

List<FavorRecommendationDTO> recommendationDTO = getRecommendationDTO(userId);
List<Product> productList = new ArrayList<>();
Expand All @@ -43,35 +44,47 @@ public List<Product> recommendation(
productList.addAll(filterStep(CATEGORY_NAME, firstFavorRecommendationDTO.getAnswer()));
}

return productList;

/**
* 2번 스텝(원하는 우리집의 이미지?) 1번 스텝과 거의 동일함 answer가 최대 2개 선택이므로 경우를 나눈다 1개인 경우 productList를 답변으로
* 필터한다 2개인 경우 필터를 두번 거친다
*
* <p>// TODO : 질문에 대한 답변을 포함하는 상품이 아직 없음.. 나중에 상품 업데이트 후 다시 활성화
*/
FavorRecommendationDTO secondFavorRecommendationDTO = recommendationDTO.get(1);
List<Product> resultProductList = new ArrayList<>();
if (secondFavorRecommendationDTO.getAnswer().split(", ").length > 1) {
return productList.stream()
.filter(
product ->
product.getCharacteristic()
.contains(
secondFavorRecommendationDTO.getAnswer()
.split(", ")[0]))
.filter(
product ->
product.getCharacteristic()
.contains(
secondFavorRecommendationDTO.getAnswer()
.split(", ")[1]))
.toList();
} else {
return productList.stream()
.filter(
product ->
product.getCharacteristic()
.contains(secondFavorRecommendationDTO.getAnswer()))
.toList();
}
// FavorRecommendationDTO secondFavorRecommendationDTO = recommendationDTO.get(1);
// List<Product> resultProductList = new ArrayList<>();
// if (secondFavorRecommendationDTO.getAnswer().split(", ").length > 1) {
// return productList.stream()
// .filter(
// product ->
// product.getCharacteristic()
// .contains(
//
// secondFavorRecommendationDTO.getAnswer()
// .split(", ")[0]))
// .filter(
// product ->
// product.getCharacteristic()
// .contains(
//
// secondFavorRecommendationDTO.getAnswer()
// .split(", ")[1]))
// .toList();
// } else {
// return productList.stream()
// .filter(
// product ->
// product.getCharacteristic()
//
// .contains(secondFavorRecommendationDTO.getAnswer()))
// .toList();
// }
}

@Override
public StrategyName getStrategyName() {
return StrategyName.valueOf(CATEGORY_NAME);
}

private List<Product> filterStep(String categoryName, String answer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import tify.server.core.exception.BaseException;
import tify.server.domain.domains.product.adaptor.ProductAdaptor;
Expand All @@ -13,6 +14,7 @@
import tify.server.domain.domains.question.dto.condition.FavorRecommendationDTO;
import tify.server.domain.domains.question.exception.QuestionException;

@Component
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class BMEYERecommendationStrategy implements ProductRecommendationStrategy {
Expand All @@ -26,8 +28,7 @@ public class BMEYERecommendationStrategy implements ProductRecommendationStrateg
private static final String SECOND_CATEGORY_NAME = "BMEYE";

@Override
public List<Product> recommendation(
Long userId, String categoryName, List<FavorRecommendationDTO> dto) {
public List<Product> recommendation(Long userId, String categoryName) {

List<FavorRecommendationDTO> recommendationDTO = getRecommendationDTO(userId);

Expand All @@ -41,6 +42,11 @@ public List<Product> recommendation(
return secondStep(firstProducts, recommendationDTO.get(1).getAnswer());
}

@Override
public StrategyName getStrategyName() {
return StrategyName.valueOf(SECOND_CATEGORY_NAME);
}

private List<FavorRecommendationDTO> getRecommendationDTO(Long userId) {
List<FavorAnswer> favorAnswers = new ArrayList<>();
favorAnswers.add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.Arrays;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import tify.server.core.exception.BaseException;
import tify.server.domain.domains.product.adaptor.ProductAdaptor;
Expand All @@ -14,6 +15,7 @@
import tify.server.domain.domains.question.dto.condition.FavorRecommendationDTO;
import tify.server.domain.domains.question.exception.QuestionException;

@Component
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class BMLIPRecommendationStrategy implements ProductRecommendationStrategy {
Expand All @@ -26,8 +28,7 @@ public class BMLIPRecommendationStrategy implements ProductRecommendationStrateg
private static final String CATEGORY_NAME = "BMLIP";

@Override
public List<Product> recommendation(
Long userId, String categoryName, List<FavorRecommendationDTO> dto) {
public List<Product> recommendation(Long userId, String categoryName) {

List<FavorRecommendationDTO> recommendationDTO = getRecommendationDTO(userId);

Expand All @@ -52,6 +53,11 @@ public List<Product> recommendation(
return otherStep(secondStepProducts, recommendationDTO.get(2).getAnswer());
}

@Override
public StrategyName getStrategyName() {
return StrategyName.valueOf(CATEGORY_NAME);
}

private List<FavorRecommendationDTO> getRecommendationDTO(Long userId) {
List<FavorAnswer> favorAnswers = new ArrayList<>();
favorAnswers.add(
Expand All @@ -76,7 +82,7 @@ private List<Product> otherStep(List<Product> findProducts, String answer) {
return product.getCharacteristic().contains(answerSplits.get(0));
} else if (answerSplits.size() == 2) {
return product.getCharacteristic().contains(answerSplits.get(0))
&& product.getCharacteristic()
|| product.getCharacteristic()
.contains(answerSplits.get(1));
} else {
return true;
Expand Down
Loading
Loading