Skip to content

Commit da2b1d2

Browse files
authored
[feat] 단계별 추천 논알콜 선택시 글라스 타입 선택 #271 (#272)
* feat: selectedCocktailType add * feat: NON_ALCOHOLIC step add
1 parent bd080c3 commit da2b1d2

File tree

2 files changed

+119
-10
lines changed

2 files changed

+119
-10
lines changed

src/main/java/com/back/domain/chatbot/dto/ChatRequestDto.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ public class ChatRequestDto {
2727
// "ALL" 처리를 위해 스텝 2개 String으로 변경
2828
private String selectedAlcoholStrength;
2929
private String selectedAlcoholBaseType;
30-
// selectedCocktailType 삭제
30+
private String selectedCocktailType;
3131

3232
}

src/main/java/com/back/domain/chatbot/service/ChatbotService.java

Lines changed: 118 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
import com.back.domain.cocktail.entity.Cocktail;
1313
import com.back.domain.cocktail.enums.AlcoholBaseType;
1414
import com.back.domain.cocktail.enums.AlcoholStrength;
15+
import com.back.domain.cocktail.enums.CocktailType;
1516
import com.back.domain.cocktail.repository.CocktailRepository;
17+
import com.fasterxml.jackson.core.JsonProcessingException;
1618
import com.fasterxml.jackson.databind.ObjectMapper;
1719
import jakarta.annotation.PostConstruct;
1820
import lombok.RequiredArgsConstructor;
@@ -27,7 +29,6 @@
2729
import org.springframework.stereotype.Service;
2830
import org.springframework.transaction.annotation.Transactional;
2931
import org.springframework.util.StreamUtils;
30-
import com.fasterxml.jackson.core.JsonProcessingException;
3132

3233
import java.io.IOException;
3334
import java.nio.charset.StandardCharsets;
@@ -722,8 +723,18 @@ private ChatResponseDto handleStepRecommendation(ChatRequestDto requestDto) {
722723
break;
723724

724725
case 2:
725-
stepData = getAlcoholBaseTypeOptions(parseAlcoholStrength(requestDto.getSelectedAlcoholStrength()));
726-
message = "좋은 선택이네요! \n이제 베이스가 될 술을 선택해주세요 🍸";
726+
// 논알콜 선택 여부에 따라 다른 옵션 제공
727+
boolean isNonAlcoholic = "NON_ALCOHOLIC".equals(requestDto.getSelectedAlcoholStrength());
728+
729+
if (isNonAlcoholic) {
730+
// 논알콜인 경우: 글라스 타입 선택
731+
stepData = getCocktailTypeOptions();
732+
message = "논알콜 칵테일이네요! 🥤\n어떤 스타일의 칵테일을 원하시나요?";
733+
} else {
734+
// 알콜인 경우: 베이스 타입 선택
735+
stepData = getAlcoholBaseTypeOptions(parseAlcoholStrength(requestDto.getSelectedAlcoholStrength()));
736+
message = "좋은 선택이네요! \n이제 베이스가 될 술을 선택해주세요 🍸";
737+
}
727738
type = MessageType.RADIO_OPTIONS;
728739
break;
729740

@@ -740,11 +751,23 @@ private ChatResponseDto handleStepRecommendation(ChatRequestDto requestDto) {
740751
break;
741752

742753
case 4:
743-
stepData = getFinalRecommendationsWithMessage(
744-
parseAlcoholStrength(requestDto.getSelectedAlcoholStrength()),
745-
parseAlcoholBaseType(requestDto.getSelectedAlcoholBaseType()),
746-
requestDto.getMessage()
747-
);
754+
// 논알콜 여부 다시 확인
755+
boolean isNonAlcoholicFinal = "NON_ALCOHOLIC".equals(requestDto.getSelectedAlcoholStrength());
756+
757+
if (isNonAlcoholicFinal) {
758+
// 논알콜: 도수와 칵테일 타입으로 검색
759+
stepData = getFinalRecommendationsForNonAlcoholic(
760+
parseCocktailType(requestDto.getSelectedCocktailType()),
761+
requestDto.getMessage()
762+
);
763+
} else {
764+
// 알콜: 도수와 베이스 타입으로 검색
765+
stepData = getFinalRecommendationsWithMessage(
766+
parseAlcoholStrength(requestDto.getSelectedAlcoholStrength()),
767+
parseAlcoholBaseType(requestDto.getSelectedAlcoholBaseType()),
768+
requestDto.getMessage()
769+
);
770+
}
748771
message = stepData.getStepTitle();
749772
type = MessageType.CARD_LIST;
750773
break;
@@ -776,6 +799,44 @@ private ChatResponseDto handleStepRecommendation(ChatRequestDto requestDto) {
776799
.build();
777800
}
778801

802+
private StepRecommendationResponseDto getCocktailTypeOptions() {
803+
List<StepRecommendationResponseDto.StepOption> options = new ArrayList<>();
804+
805+
options.add(new StepRecommendationResponseDto.StepOption(
806+
"ALL",
807+
"전체",
808+
null
809+
));
810+
811+
for (CocktailType type : CocktailType.values()) {
812+
options.add(new StepRecommendationResponseDto.StepOption(
813+
type.name(),
814+
type.getDescription(),
815+
null
816+
));
817+
}
818+
819+
return new StepRecommendationResponseDto(
820+
2,
821+
"어떤 스타일의 칵테일을 원하시나요?",
822+
options,
823+
null,
824+
false
825+
);
826+
}
827+
828+
private CocktailType parseCocktailType(String value) {
829+
if (value == null || value.trim().isEmpty() || "ALL".equalsIgnoreCase(value)) {
830+
return null;
831+
}
832+
try {
833+
return CocktailType.valueOf(value);
834+
} catch (IllegalArgumentException e) {
835+
log.warn("Invalid CocktailType value: {}", value);
836+
return null;
837+
}
838+
}
839+
779840
private AlcoholStrength parseAlcoholStrength(String value) {
780841
if (value == null || value.trim().isEmpty() || "ALL".equalsIgnoreCase(value)) {
781842
return null;
@@ -900,4 +961,52 @@ private StepRecommendationResponseDto getFinalRecommendationsWithMessage(
900961
true
901962
);
902963
}
903-
}
964+
private StepRecommendationResponseDto getFinalRecommendationsForNonAlcoholic(
965+
CocktailType cocktailType,
966+
String userMessage) {
967+
968+
// 논알콜 도수만 필터링
969+
List<AlcoholStrength> strengths = List.of(AlcoholStrength.NON_ALCOHOLIC);
970+
List<CocktailType> types = (cocktailType == null) ? null : List.of(cocktailType);
971+
972+
String keyword = null;
973+
if (userMessage != null && !userMessage.trim().isEmpty()) {
974+
String trimmed = userMessage.trim().toLowerCase();
975+
if (!trimmed.equals("x") && !trimmed.equals("없음")) {
976+
keyword = userMessage;
977+
}
978+
}
979+
980+
Page<Cocktail> cocktailPage = cocktailRepository.searchWithFilters(
981+
keyword,
982+
strengths,
983+
types, // 칵테일 타입 필터 적용
984+
null, // 베이스 타입은 null
985+
PageRequest.of(0, 3)
986+
);
987+
988+
List<CocktailSummaryResponseDto> recommendations = cocktailPage.getContent().stream()
989+
.map(cocktail -> new CocktailSummaryResponseDto(
990+
cocktail.getId(),
991+
cocktail.getCocktailName(),
992+
cocktail.getCocktailNameKo(),
993+
cocktail.getCocktailImgUrl(),
994+
cocktail.getAlcoholStrength().getDescription()
995+
))
996+
.collect(Collectors.toList());
997+
998+
String stepTitle = recommendations.isEmpty()
999+
? "조건에 맞는 논알콜 칵테일을 찾을 수 없습니다 😢"
1000+
: "짠🎉🎉 논알콜 칵테일 추천!\n" +
1001+
"칵테일의 자세한 정보는 '상세보기'를 클릭해서 확인할 수 있어요.\n" +
1002+
"마음에 드는 칵테일은 '킵' 버튼을 눌러 나만의 Bar에 저장해보세요!";
1003+
1004+
return new StepRecommendationResponseDto(
1005+
4,
1006+
stepTitle,
1007+
null,
1008+
recommendations,
1009+
true
1010+
);
1011+
}
1012+
}

0 commit comments

Comments
 (0)