Skip to content

This file was deleted.

This file was deleted.

22 changes: 0 additions & 22 deletions src/main/java/com/sparta/tdd/domain/ai/dto/AiResponseDto.java

This file was deleted.

30 changes: 15 additions & 15 deletions src/main/java/com/sparta/tdd/domain/ai/service/AiService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@

import com.google.genai.Client;
import com.google.genai.types.GenerateContentConfig;
import com.google.genai.types.GenerateContentResponse;
import com.sparta.tdd.domain.ai.dto.AiRequestDto;
import com.sparta.tdd.domain.ai.dto.AiResponseDto;
import com.sparta.tdd.domain.ai.entity.Ai;
import com.sparta.tdd.domain.ai.repository.AiRepository;
import com.sparta.tdd.domain.auth.UserDetailsImpl;
import com.sparta.tdd.domain.user.entity.User;
import com.sparta.tdd.domain.user.repository.UserRepository;
import com.sparta.tdd.global.exception.BusinessException;
import com.sparta.tdd.global.exception.ErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Slf4j(topic = "AI 코멘트 생성")
Expand All @@ -25,28 +22,31 @@ public class AiService {
private final Client client;
private final GenerateContentConfig config;

public AiResponseDto createComment(AiRequestDto requestDto, Long userId) {
public String createComment(String menuName, Long userId) {
User user = userRepository.findById(userId).orElseThrow(() ->
new IllegalArgumentException("존재하지 않는 회원입니다.")
new BusinessException(ErrorCode.USER_NOT_FOUND)
);

String response = generateText(requestDto.comment());
Ai ai = Ai.of(requestDto.comment(), response, user);
String response = generateText(menuName);
Ai ai = Ai.of(menuName, response, user);

aiRepository.save(ai);
log.info(getLog(ai));
return AiResponseDto.from(ai);
return response;
}


private String generateText(String comment) {
return client.models.generateContent("gemini-2.5-flash", comment, config).text();
}

private String getLog(Ai ai) {
return String.format(
"AI Comment Log => User: %d | Input: \"%s\" | Output: \"%s\" | CreatedAt: %s",
ai.getUser().getId(),
ai.getInputText(),
ai.getOutputText(),
ai.getCreatedAt()
"AI Comment Log => User: %d | Input: \"%s\" | Output: \"%s\" | CreatedAt: %s",
ai.getUser().getId(),
ai.getInputText(),
ai.getOutputText(),
ai.getCreatedAt()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,27 @@ public record MenuRequestDto(
String name,
String description,
Integer price,
String imageUrl
String imageUrl,
boolean useAiDescription
) {

public Menu toEntity(Store store, String description) {
return Menu.builder()
.name(name)
.description(description)
.price(price)
.imageUrl(imageUrl)
.store(store)
.build();
}

public Menu toEntity(Store store) {
return Menu.builder()
.dto(this)
.store(store).build();
.name(name)
.description(description)
.price(price)
.imageUrl(imageUrl)
.store(store)
.build();
}
}
10 changes: 5 additions & 5 deletions src/main/java/com/sparta/tdd/domain/menu/entity/Menu.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ public class Menu extends BaseEntity {
private Store store;

@Builder
public Menu(MenuRequestDto dto, Store store) {
this.name = dto.name();
this.description = dto.description();
this.price = dto.price();
this.imageUrl = dto.imageUrl();
public Menu(String name, String description, Integer price, String imageUrl, Store store) {
this.name = name;
this.description = description;
this.price = price;
this.imageUrl = imageUrl;
this.store = store;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sparta.tdd.domain.menu.service;

import com.sparta.tdd.domain.ai.service.AiService;
import com.sparta.tdd.domain.menu.dto.MenuRequestDto;
import com.sparta.tdd.domain.menu.dto.MenuResponseDto;
import com.sparta.tdd.domain.menu.entity.Menu;
Expand All @@ -9,6 +10,8 @@
import com.sparta.tdd.domain.user.entity.User;
import com.sparta.tdd.domain.user.enums.UserAuthority;
import com.sparta.tdd.domain.user.repository.UserRepository;
import com.sparta.tdd.global.exception.BusinessException;
import com.sparta.tdd.global.exception.ErrorCode;
import java.util.List;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
Expand All @@ -23,6 +26,7 @@ public class MenuService {
private final MenuRepository menuRepository;
private final StoreRepository storeRepository;
private final UserRepository userRepository;
private final AiService aiService;

public List<MenuResponseDto> getMenus(UUID storeId, UserAuthority authority) {
List<Menu> menus;
Expand All @@ -40,7 +44,7 @@ public List<MenuResponseDto> getMenus(UUID storeId, UserAuthority authority) {
public MenuResponseDto getMenu(UUID storeId, UUID menuId, UserAuthority authority) {
Menu menu = findMenu(storeId, menuId);
if (authority.isCustomerOrManager() && menu.isHidden()) {
throw new IllegalArgumentException("숨겨진 메뉴입니다.");
throw new BusinessException(ErrorCode.IS_HIDDEN_MENU);
}
return MenuResponseDto.from(menu);
}
Expand All @@ -50,8 +54,15 @@ public MenuResponseDto createMenu(UUID storeId, MenuRequestDto menuRequestDto, L
User user = findUser(userId);
Store store = findStore(storeId);
validateUserOnMenu(user, store);
Menu menu;

if (menuRequestDto.useAiDescription()) {
String aiDescription = aiService.createComment(menuRequestDto.name(), userId);
menu = menuRequestDto.toEntity(store, aiDescription);
} else {
menu = menuRequestDto.toEntity(store);
}

Menu menu = menuRequestDto.toEntity(store);
menuRepository.save(menu);

return MenuResponseDto.from(menu);
Expand Down Expand Up @@ -89,22 +100,22 @@ public void deleteMenu(UUID storeId, UUID menuId, Long userId) {

private Menu findMenu(UUID storeId, UUID menuId) {
return menuRepository.findByIdAndStoreIdAndIsDeletedFalse(menuId, storeId)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 메뉴입니다."));
.orElseThrow(() -> new BusinessException(ErrorCode.MENU_NOT_FOUND));
}

private Store findStore(UUID storeId) {
return storeRepository.findById(storeId)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 가게입니다."));
.orElseThrow(() -> new BusinessException(ErrorCode.STORE_NOT_FOUND));
}

private User findUser(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 사용자입니다."));
.orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND));
}

private void validateUserOnMenu(User user, Store store) {
if (!store.isOwner(user)) {
throw new IllegalArgumentException("권한이 없는 사용자입니다.");
throw new BusinessException(ErrorCode.STORE_OWNERSHIP_DENIED);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,14 @@ public enum ErrorCode {

// ORDER 도메인 관련
ORDER_PERMISSION_DENIED(HttpStatus.FORBIDDEN, "권한이 없습니다."),
MENU_NOT_IN_STORE(HttpStatus.BAD_REQUEST, "해당 가게의 메뉴가 아닙니다."),
MENU_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 메뉴가 포함되어 있습니다."),
MENU_INVALID_INFO(HttpStatus.BAD_REQUEST, "메뉴 정보가 올바르지 않습니다."),
ORDER_CANCELLATION_NOT_ALLOWED(HttpStatus.BAD_REQUEST, "주문 생성 후 5분이 지나 취소할 수 없습니다."),
ORDER_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 주문입니다."),
ORDER_CANCELLATION_NOT_ALLOWED(HttpStatus.BAD_REQUEST, "주문 생성 후 5분이 지나 취소할 수 없습니다."),

// MENU 도메인 관련
IS_HIDDEN_MENU(HttpStatus.BAD_REQUEST, "숨겨진 메뉴입니다."),
MENU_NOT_IN_STORE(HttpStatus.BAD_REQUEST, "해당 가게의 메뉴가 아닙니다."),
MENU_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 메뉴가 포함되어 있습니다."),
MENU_INVALID_INFO(HttpStatus.BAD_REQUEST, "메뉴 정보가 올바르지 않습니다."),

// REVIEW 도메인 관련
REVIEW_NOT_OWNED(HttpStatus.FORBIDDEN, "본인의 리뷰만 수정/삭제할 수 있습니다."),
Expand Down
3 changes: 1 addition & 2 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,4 @@ ai:
naver:
client:
id: testClientId
secret: testClientSecret

secret: testClientSecret
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,19 @@ void setUp() {

// 테스트 메뉴 생성
menu1 = Menu.builder()
.dto(new com.sparta.tdd.domain.menu.dto.MenuRequestDto(
"김치찌개", "맛있는 김치찌개", 8000, null
))
.name("김치찌개")
.description("맛있는 김치찌개")
.price(8000)
.imageUrl(null)
.store(store)
.build();
em.persist(menu1);

menu2 = Menu.builder()
.dto(new com.sparta.tdd.domain.menu.dto.MenuRequestDto(
"된장찌개", "구수한 된장찌개", 7000, null
))
.name("된장찌개")
.description("구수한 된장찌개")
.price(7000)
.imageUrl(null)
.store(store)
.build();
em.persist(menu2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ void setUp() {

// 테스트 메뉴 생성
menu = Menu.builder()
.dto(new com.sparta.tdd.domain.menu.dto.MenuRequestDto(
"김치찌개", "맛있는 김치찌개", 8000, null
))
.name("김치찌개")
.description("맛있는 김치찌개")
.price(8000)
.imageUrl(null)
.store(store)
.build();
em.persist(menu);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,10 @@ void setUp() {

// 메뉴
menu = Menu.builder()
.dto(new com.sparta.tdd.domain.menu.dto.MenuRequestDto(
"김치찌개", "맛있는 김치찌개", 8000, null
))
.name("김치찌개")
.description("맛있는 김치찌개")
.price(8000)
.imageUrl(null)
.store(store)
.build();
setId(menu, UUID.randomUUID());
Expand Down Expand Up @@ -266,9 +267,10 @@ void addItemToCart_DifferentStore_Fail() {
setId(differentStore, UUID.randomUUID());

Menu differentMenu = Menu.builder()
.dto(new com.sparta.tdd.domain.menu.dto.MenuRequestDto(
"짜장면", "맛있는 짜장면", 6000, null
))
.name("짜장면")
.description("맛있는 짜장면")
.price(6000)
.imageUrl(null)
.store(differentStore)
.build();
setId(differentMenu, menuId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,11 @@ void setUp() {
.build();
storeRepository.save(store);

MenuRequestDto dto = MenuRequestDto.builder()
menu = Menu.builder()
.name("menu")
.description("this is menu")
.price(30000)
.imageUrl("this is image url")
.build();

menu = Menu.builder()
.dto(dto)
.store(store)
.build();
menuRepository.save(menu);
Expand Down Expand Up @@ -264,7 +260,7 @@ void ownerDeletesMenu() throws Exception {
mockMvc.perform(
get("/v1/store/{storeId}/menu/{menuId}", storeId, menuId)
.with(csrf()))
.andExpectAll(status().isBadRequest());
.andExpectAll(status().isNotFound());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.sparta.tdd.domain.user.entity.User;
import com.sparta.tdd.domain.user.enums.UserAuthority;
import com.sparta.tdd.domain.user.repository.UserRepository;
import com.sparta.tdd.global.exception.BusinessException;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -170,7 +171,7 @@ void getMenusCustomerTest() {
.thenReturn(Optional.of(menu2));

// when & then
assertThrows(IllegalArgumentException.class,
assertThrows(BusinessException.class,
() -> menuService.getMenu(store.getId(), menu2.getId(),
customer.getAuthority()));
verify(menuRepository, times(1)).findByIdAndStoreIdAndIsDeletedFalse(menu2.getId(), store.getId());
Expand Down
Loading