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
7 changes: 7 additions & 0 deletions src/main/java/ssu/eatssu/domain/menu/entity/Menu.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ public void update(String name, Integer price) {
this.price = price;
}

public void updateNameEn(String nameEn) {
if (nameEn == null || nameEn.isBlank()) {
return;
}
this.nameEn = nameEn;
}

public void changeDiscontinuedStatus() {
this.isDiscontinued = !this.isDiscontinued;
}
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/ssu/eatssu/domain/menu/service/MealService.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ private List<String> upsertMainMenus(Long mealId, List<String> menuNames, List<M
}

Meal meal = mealRepository.getReferenceById(mealId);
Map<String, Menu> menusByName = getMenusByName(meal);
List<String> unmatchedMainMenus = new ArrayList<>();
int seq = 0;
for (MainMenuRequest mainMenu : mainMenus) {
Expand All @@ -231,11 +232,25 @@ private List<String> upsertMainMenus(Long mealId, List<String> menuNames, List<M
continue;
}
mealMainMenuRepository.save(MealMainMenu.of(meal, seq++, mainMenu.nameKo(), mainMenu.nameEn()));
syncMenuNameEn(menusByName.get(mainMenu.nameKo()), mainMenu.nameEn());
}

return unmatchedMainMenus;
}

private Map<String, Menu> getMenusByName(Meal meal) {
return meal.getMealMenus().stream()
.map(MealMenu::getMenu)
.collect(Collectors.toMap(Menu::getName, menu -> menu, (existing, duplicate) -> existing));
}

private void syncMenuNameEn(Menu menu, String nameEn) {
if (menu == null) {
return;
}
menu.updateNameEn(nameEn);
}

private Optional<Long> getExistingMealId(Date date, TimePart timePart, Restaurant restaurant,
List<String> menuNames) {
List<Meal> meals = mealRepository.findAllByDateAndTimePartAndRestaurant(date, timePart, restaurant);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
ALTER TABLE menu
MODIFY COLUMN name_en VARCHAR(500) NULL;

UPDATE menu m
JOIN (SELECT ranked.name_ko, ranked.restaurant, ranked.name_en
FROM (SELECT mmm.name_ko,
ml.restaurant,
mmm.name_en,
ROW_NUMBER() OVER (
PARTITION BY mmm.name_ko, ml.restaurant
ORDER BY ml.date DESC, mmm.meal_main_menu_id DESC
) AS rn
FROM meal_main_menu mmm
JOIN meal ml ON ml.meal_id = mmm.meal_id
WHERE TRIM(mmm.name_en) <> '') ranked
WHERE ranked.rn = 1) latest
ON CONVERT(latest.name_ko USING utf8mb4) COLLATE utf8mb4_bin = CONVERT(m.name USING utf8mb4) COLLATE utf8mb4_bin
AND CAST(latest.restaurant AS CHAR) = CAST(m.restaurant AS CHAR)
SET m.name_en = latest.name_en
WHERE m.name_en IS NULL
OR TRIM(m.name_en) = '';
99 changes: 99 additions & 0 deletions src/test/java/ssu/eatssu/domain/menu/service/MealServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
import ssu.eatssu.domain.favorite.persistence.MenuFavoriteQueryRepository;
import ssu.eatssu.domain.menu.entity.Meal;
import ssu.eatssu.domain.menu.entity.Menu;
import ssu.eatssu.domain.menu.entity.constants.TimePart;
import ssu.eatssu.domain.menu.persistence.MealMainMenuRepository;
import ssu.eatssu.domain.menu.persistence.MealMenuRepository;
Expand Down Expand Up @@ -48,6 +50,9 @@ class MealServiceTest {
@Autowired
private MenuRepository menuRepository;

@Autowired
private MenuFavoriteQueryRepository menuFavoriteQueryRepository;

@BeforeEach
void setUp() {
cleanUp();
Expand Down Expand Up @@ -177,6 +182,100 @@ void createMealWithEmptyMainMenusReturnsEmptyUnmatchedList() {
assertThat(result.unmatchedMainMenus()).isEmpty();
}

@Test
void createMealSyncsMainMenuTranslationToMenuNameEn() {
// given
CreateMealRequest request = new CreateMealRequest(List.of("김치찌개", "깍두기"),
List.of(new MainMenuRequest("김치찌개", "Kimchi Stew")));

// when
mealService.createMeal(Date.valueOf("2024-01-03"), Restaurant.HAKSIK, LUNCH, request);

// then
assertThat(menuNameEn("김치찌개")).isEqualTo("Kimchi Stew");
assertThat(menuNameEn("깍두기")).isNull();
}

@Test
void laterMealTranslationOverwritesMenuNameEn() {
// given
mealService.createMeal(Date.valueOf("2024-01-03"), Restaurant.HAKSIK, LUNCH,
new CreateMealRequest(List.of("김치찌개"), List.of(new MainMenuRequest("김치찌개", "Kimchi Stew"))));

// when
mealService.createMeal(Date.valueOf("2024-01-04"), Restaurant.HAKSIK, LUNCH,
new CreateMealRequest(List.of("김치찌개"), List.of(new MainMenuRequest("김치찌개", "Kimchi Jjigae"))));

// then
assertThat(menuNameEn("김치찌개")).isEqualTo("Kimchi Jjigae");
}

@Test
void menuNameEnIsKeptWhenOmittedFromMainMenusOrBlank() {
// given
mealService.createMeal(Date.valueOf("2024-01-03"), Restaurant.HAKSIK, LUNCH,
new CreateMealRequest(List.of("김치찌개", "돈까스"),
List.of(new MainMenuRequest("김치찌개", "Kimchi Stew"),
new MainMenuRequest("돈까스", "Pork Cutlet"))));

// when
mealService.createMeal(Date.valueOf("2024-01-04"), Restaurant.HAKSIK, LUNCH,
new CreateMealRequest(List.of("김치찌개", "돈까스"),
List.of(new MainMenuRequest("돈까스", " "))));

// then
assertThat(menuNameEn("김치찌개")).isEqualTo("Kimchi Stew");
assertThat(menuNameEn("돈까스")).isEqualTo("Pork Cutlet");
}

@Test
void unmatchedMainMenuDoesNotTouchMenuNameEn() {
// given
CreateMealRequest request = new CreateMealRequest(List.of("돈까스"),
List.of(new MainMenuRequest("김치", "Kimchi")));

// when
mealService.createMeal(Date.valueOf("2024-01-03"), Restaurant.HAKSIK, LUNCH, request);

// then
assertThat(menuRepository.findByNameAndRestaurant("김치", Restaurant.HAKSIK)).isEmpty();
assertThat(menuNameEn("돈까스")).isNull();
}

@Test
void reconcileMealSlotSyncsMainMenuTranslationToMenuNameEn() {
// given
List<MealCreateWithPriceRequest> requests = List.of(new MealCreateWithPriceRequest(
List.of("김치볶음밥"), 5000, List.of(new MainMenuRequest("김치볶음밥", "Kimchi Fried Rice"))));

// when
mealService.reconcileMealSlot(Date.valueOf("2024-01-03"), Restaurant.HAKSIK, LUNCH, requests);

// then
assertThat(menuNameEn("김치볶음밥")).isEqualTo("Kimchi Fried Rice");
}

@Test
void favoriteSearchMatchesSyncedEnglishName() {
// given
mealService.createMeal(Date.valueOf("2024-01-03"), Restaurant.HAKSIK, LUNCH,
new CreateMealRequest(List.of("김치찌개"), List.of(new MainMenuRequest("김치찌개", "Kimchi Stew"))));

// when
List<Menu> englishResults = menuFavoriteQueryRepository.searchMenus("kimchi", Language.EN);
List<Menu> koreanResults = menuFavoriteQueryRepository.searchMenus("kimchi", Language.KO);

// then
assertThat(englishResults).extracting(Menu::getName).containsExactly("김치찌개");
assertThat(koreanResults).isEmpty();
}

private String menuNameEn(String name) {
return menuRepository.findByNameAndRestaurant(name, Restaurant.HAKSIK)
.orElseThrow()
.getNameEn();
}

@Test
void 메뉴가_없는_식단을_조회하면_빈_목록을_반환한다() {
// given
Expand Down
Loading