Skip to content

Commit

Permalink
feat: 메뉴 카테고리 목록 조회 (#153)
Browse files Browse the repository at this point in the history
* feat: 메뉴 카테고리 조회 기능 구현

* refactor: 응답 DTO 생성 로직 수정

* refactor: cascade 처리 방식 변경

refactor: cascade 처리 방식 변경

* test: 테스트 문맥 변경

(cherry picked from commit 1130bfb)
  • Loading branch information
Invidam authored and Choi-JJunho committed May 9, 2024
1 parent 5e7a842 commit 8d6272d
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import in.koreatech.koin.domain.shop.dto.MenuCategoriesResponse;
import in.koreatech.koin.domain.shop.dto.ShopMenuResponse;
import in.koreatech.koin.domain.shop.service.ShopService;
import lombok.RequiredArgsConstructor;
Expand All @@ -20,4 +21,10 @@ public ResponseEntity<ShopMenuResponse> findMenu(@PathVariable Long shopId, @Pat
ShopMenuResponse shopMenu = shopService.findMenu(menuId);
return ResponseEntity.ok(shopMenu);
}

@GetMapping("/shops/{shopId}/menus/categories")
public ResponseEntity<MenuCategoriesResponse> findMenuCategories(@PathVariable Long shopId) {
MenuCategoriesResponse menuCategories = shopService.getMenuCategories(shopId);
return ResponseEntity.ok(menuCategories);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package in.koreatech.koin.domain.shop.dto;

import java.util.List;

import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

import in.koreatech.koin.domain.shop.model.MenuCategory;

@JsonNaming(value = SnakeCaseStrategy.class)
public record MenuCategoriesResponse(Long count, List<MenuCategoryResponse> menuCategories) {
public static MenuCategoriesResponse from(List<MenuCategory> menuCategories) {
List<MenuCategoryResponse> categories = menuCategories.stream()
.map(menuCategory -> MenuCategoryResponse.of(menuCategory.getId(), menuCategory.getName()))
.toList();

return new MenuCategoriesResponse((long)categories.size(), categories);
}

private record MenuCategoryResponse(Long id, String name) {
public static MenuCategoryResponse of(Long id, String name) {
return new MenuCategoryResponse(id, name);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package in.koreatech.koin.domain.shop.model;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
Expand Down Expand Up @@ -29,7 +28,7 @@ public class MenuCategoryMap {
@JoinColumn(name = "shop_menu_id")
private Menu menu;

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "shop_menu_category_id")
private MenuCategory menuCategory;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package in.koreatech.koin.domain.shop.repository;

import java.util.List;

import org.springframework.data.repository.Repository;

import in.koreatech.koin.domain.shop.model.MenuCategory;

public interface MenuCategoryRepository extends Repository<MenuCategory, Long> {
List<MenuCategory> findAllByShopId(Long shopId);

MenuCategory save(MenuCategory menuCategory);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import in.koreatech.koin.domain.shop.dto.MenuCategoriesResponse;
import in.koreatech.koin.domain.shop.dto.ShopMenuResponse;
import in.koreatech.koin.domain.shop.model.Menu;
import in.koreatech.koin.domain.shop.model.MenuCategory;
import in.koreatech.koin.domain.shop.model.MenuCategoryMap;
import in.koreatech.koin.domain.shop.dto.ShopMenuResponse;
import in.koreatech.koin.domain.shop.repository.MenuCategoryRepository;
import in.koreatech.koin.domain.shop.repository.MenuRepository;
import lombok.RequiredArgsConstructor;

Expand All @@ -18,6 +20,7 @@
public class ShopService {

private final MenuRepository menuRepository;
private final MenuCategoryRepository menuCategoryRepository;

public ShopMenuResponse findMenu(Long menuId) {
Menu menu = menuRepository.findById(menuId)
Expand All @@ -37,4 +40,10 @@ private ShopMenuResponse createShopMenuResponse(Menu menu, List<MenuCategory> me
}
return ShopMenuResponse.createForSingleOption(menu, menuCategories);
}

public MenuCategoriesResponse getMenuCategories(Long shopId) {
//TODO 존재하는 상점인지 검증하고, 없다면 401를 반환하여야 한다. 작업시점: 상점 도메인 조회 기능 추가시
List<MenuCategory> menuCategories = menuCategoryRepository.findAllByShopId(shopId);
return MenuCategoriesResponse.from(menuCategories);
}
}
74 changes: 72 additions & 2 deletions src/test/java/in/koreatech/koin/acceptance/ShopApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import in.koreatech.koin.domain.shop.model.MenuCategoryMap;
import in.koreatech.koin.domain.shop.model.MenuImage;
import in.koreatech.koin.domain.shop.model.MenuOption;
import in.koreatech.koin.domain.shop.repository.MenuCategoryRepository;
import in.koreatech.koin.domain.shop.repository.MenuRepository;
import io.restassured.RestAssured;
import io.restassured.response.ExtractableResponse;
Expand All @@ -22,6 +23,9 @@ class ShopApiTest extends AcceptanceTest {
@Autowired
private MenuRepository menuRepository;

@Autowired
private MenuCategoryRepository menuCategoryRepository;

@Test
@DisplayName("옵션이 하나 있는 상점의 메뉴를 조회한다.")
void findMenuSingleOption() {
Expand All @@ -45,15 +49,15 @@ void findMenuSingleOption() {
.shopId(1L)
.name("중식")
.build();
menuCategoryRepository.save(menuCategory);

MenuCategoryMap menuCategoryMap = MenuCategoryMap.create();

// when then
menuOption.setMenu(menu);
menuImage.setMenu(menu);

// when then
menuCategoryMap.map(menu, menuCategory);

menuRepository.save(menu);

ExtractableResponse<Response> response = RestAssured
Expand Down Expand Up @@ -124,6 +128,7 @@ void findMenuMultipleOption() {
.build();

MenuCategoryMap menuCategoryMap = MenuCategoryMap.create();
menuCategoryRepository.save(menuCategory);

// when then
menuOption1.setMenu(menu);
Expand Down Expand Up @@ -177,4 +182,69 @@ void findMenuMultipleOption() {
}
);
}

@Test
@DisplayName("상점의 메뉴 카테고리들을 조회한다.")
void findShopMenuCategories() {
// given
final long SHOP_ID = 1L;

Menu menu = Menu.builder()
.shopId(SHOP_ID)
.name("짜장면")
.description("맛있는 짜장면")
.build();

MenuCategory menuCategory1 = MenuCategory.builder()
.shopId(SHOP_ID)
.name("이벤트 메뉴")
.build();

MenuCategory menuCategory2 = MenuCategory.builder()
.shopId(SHOP_ID)
.name("메인 메뉴")
.build();

menuCategoryRepository.save(menuCategory1);
menuCategoryRepository.save(menuCategory2);

MenuCategoryMap menuCategoryMap1 = MenuCategoryMap.create();
MenuCategoryMap menuCategoryMap2 = MenuCategoryMap.create();

// when then
menuCategoryMap1.map(menu, menuCategory1);
menuCategoryMap2.map(menu, menuCategory2);

menuRepository.save(menu);

ExtractableResponse<Response> response = RestAssured
.given()
.log().all()
.when()
.log().all()
.get("/shops/{shopId}/menus/categories", menu.getShopId())
.then()
.log().all()
.statusCode(HttpStatus.OK.value())
.extract();

SoftAssertions.assertSoftly(
softly -> {
softly.assertThat(response.body().jsonPath().getLong("count")).isEqualTo(2);

softly.assertThat(response.body().jsonPath().getList("menu_categories"))
.hasSize(2);

softly.assertThat(response.body().jsonPath().getLong("menu_categories[0].id"))
.isEqualTo(menuCategory1.getId());
softly.assertThat(response.body().jsonPath().getString("menu_categories[0].name"))
.isEqualTo(menuCategory1.getName());

softly.assertThat(response.body().jsonPath().getLong("menu_categories[1].id"))
.isEqualTo(menuCategory2.getId());
softly.assertThat(response.body().jsonPath().getString("menu_categories[1].name"))
.isEqualTo(menuCategory2.getName());
}
);
}
}

0 comments on commit 8d6272d

Please sign in to comment.