diff --git a/.github/workflows/cd-with-discord.yml b/.github/workflows/cd-with-discord.yml index 525066bc..414565fe 100644 --- a/.github/workflows/cd-with-discord.yml +++ b/.github/workflows/cd-with-discord.yml @@ -1,4 +1,4 @@ -name: CI and request Discord Message to review +name: CD and request Discord Message to deploy on: push: diff --git a/.github/workflows/ci-with-discord.yml b/.github/workflows/ci-with-discord.yml index 5d043ac7..10637343 100644 --- a/.github/workflows/ci-with-discord.yml +++ b/.github/workflows/ci-with-discord.yml @@ -25,7 +25,7 @@ jobs: mysql: image: mysql:8.0 ports: - - 3306:3306 + - 3307:3306 env: MYSQL_DATABASE: testdb MYSQL_ROOT_PASSWORD: testdb @@ -35,6 +35,16 @@ jobs: --health-timeout=5s --health-retries=3 + redis: + image: redis + ports: + - 6380:6379 + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v4 - name: JDK 17 를 준비한다. @@ -49,13 +59,33 @@ jobs: - name: Gradle 를 준비한다. uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + - name: ACT 환경에 대해서 패키지를 업데이터 & 설치한다 + if: ${{ env.ACT }} + run: | + apt-get update && apt-get install sudo -y + + - name: sudo 설치 테스트한다 + if: ${{ env.ACT }} + run: | + sudo id + + - name: DDL 경로 확인 + run: | + ls -al infra/sql/ + cat infra/sql/ddl.sql + + - name: DDL 파일을 실행하여 테이블을 생성한다. + run: | + sudo apt-get install -y default-mysql-client + mysql -h 127.0.0.1 -P 3307 -uroot -ptestdb testdb --verbose < infra/sql/ddl.sql + - name: 빌드한다. env: - SPRING_DATASOURCE_URL: jdbc:mysql://127.0.0.1:3306/testdb + SPRING_DATASOURCE_URL: jdbc:mysql://127.0.0.1:3307/testdb SPRING_DATASOURCE_USERNAME: root SPRING_DATASOURCE_PASSWORD: testdb - SPRING_JPA_HIBERNATE_DDL_AUTO: update - SPRING_DATA_REDIS_HOST: localhost + SPRING_DATA_REDIS_HOST: 127.0.0.1 + SPRING_DATA_REDIS_PORT: 6380 SPRING_DATA_REDIS_PASSWORD: MONGO_URL: ${{ secrets.MONGO_URL }} S3_BUCKET: ${{ secrets.S3_BUCKET }} diff --git a/.gitignore b/.gitignore index a00fec87..e1175e49 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ build/ !gradle/wrapper/gradle-wrapper.jar !**/src/main/**/build/ !**/src/test/**/build/ +.DS_Store ### STS ### .apt_generated @@ -37,3 +38,4 @@ out/ .vscode/ .env +.act_secrets diff --git a/infra/docker/docker-compose.yml b/infra/docker/docker-compose.yml index 74a9307f..319012a9 100644 --- a/infra/docker/docker-compose.yml +++ b/infra/docker/docker-compose.yml @@ -21,3 +21,5 @@ services: S3_SECRET_KEY: ${S3_SECRET_KEY} SPRING_SWAGGER_SERVER_URL: ${URL} DEFAULT_BUCKET_URL: ${DEFAULT_BUCKET_URL} + volumes: + - /var/log/springboot/:/var/log/springboot/ \ No newline at end of file diff --git a/infra/sql/ddl.sql b/infra/sql/ddl.sql new file mode 100644 index 00000000..997b8a4a --- /dev/null +++ b/infra/sql/ddl.sql @@ -0,0 +1,136 @@ +SET FOREIGN_KEY_CHECKS = 0; + +create table home_question_answer ( + id bigint not null auto_increment, + user_id bigint, + answer enum ('DISLIKE','LIKE','MOUNTAIN','RAINY','SEA','SPICY','SUMMER','SUNNY','SWEET','WINTER'), + question enum ('FEEL','SEASON','STRESS','TRIP','WEATHER'), + primary key (id) +) engine=InnoDB; + +create table map ( + created_at datetime(6), + id bigint not null auto_increment, + modified_at datetime(6), + location POINT SRID 4326 not null, + primary key (id) +) engine=InnoDB; + +create table meal_time ( + meal_time time(6), + created_at datetime(6), + id bigint not null auto_increment, + modified_at datetime(6), + user_id bigint, + primary key (id) +) engine=InnoDB; + +create table menu ( + is_crawled bit, + pin tinyint check (pin between 0 and 22), + price integer not null, + created_at datetime(6), + id bigint not null auto_increment, + modified_at datetime(6), + store_id bigint, + user_id bigint not null, + memo_content varchar(255), + memo_title varchar(255), + title varchar(255) not null, + primary key (id) +) engine=InnoDB; + +create table menu_folder ( + custom_index integer not null, + icon tinyint check (icon between 0 and 31), + created_at datetime(6), + id bigint not null auto_increment, + modified_at datetime(6), + user_id bigint not null, + img_url varchar(255), + title varchar(255) not null, + primary key (id) +) engine=InnoDB; + +create table menu_menu_folder ( + created_at datetime(6), + folder_id bigint, + id bigint not null auto_increment, + menu_id bigint, + modified_at datetime(6), + primary key (id) +) engine=InnoDB; + +create table menu_img ( + created_at datetime(6), + id bigint not null auto_increment, + menu_id bigint, + modified_at datetime(6), + img_url varchar(255), + primary key (id) +) engine=InnoDB; + +create table menu_tag ( + created_at datetime(6), + id bigint not null auto_increment, + menu_id bigint not null, + modified_at datetime(6), + tag enum ('ASIA','BREAD','BUSINESS','BUY_FOOD','CAFE','CHINA','COOL','DATE','DESSERT','FAST_FOOD','FISH','HOT','HOT_SPICY','JAPAN','KOREA','MEAT','NOODLE','ORGANIZATION','PROMISE','RICE','SOLO','SPICY','SWEET','WESTERN'), + primary key (id) +) engine=InnoDB; + +create table not_owned_search_history ( + created_at datetime(6), + id bigint not null auto_increment, + modified_at datetime(6), + user_id bigint not null, + address varchar(255) not null, + title varchar(255) not null, + primary key (id) +) engine=InnoDB; + +create table not_found_store ( + mapx float(53) not null, + mapy float(53) not null, + created_at datetime(6), + id bigint not null auto_increment, + modified_at datetime(6), + address varchar(255) not null, + store_id varchar(255), + title varchar(255) not null, + primary key (id) +) engine=InnoDB; + +create table owned_menu_search ( + created_at datetime(6), + id bigint not null auto_increment, + menu_id bigint not null, + modified_at datetime(6), + user_id bigint not null, + menu_title varchar(255) not null, + store_address varchar(255) not null, + store_title varchar(255) not null, + primary key (id) +) engine=InnoDB; + +create table store ( + created_at datetime(6), + id bigint not null auto_increment, + map_id bigint, + modified_at datetime(6), + address varchar(255), + title varchar(255) not null, + primary key (id) +) engine=InnoDB; + +create table user ( + created_at datetime(6), + id bigint not null auto_increment, + modified_at datetime(6), + email varchar(255), + password varchar(255), + sign_in_type enum ('EMAIL','KAKAO'), + primary key (id) +) engine=InnoDB; + +SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/src/main/java/com/ourmenu/backend/domain/cache/application/CacheService.java b/src/main/java/com/ourmenu/backend/domain/cache/application/CacheService.java index d7f155e5..efae0f3d 100644 --- a/src/main/java/com/ourmenu/backend/domain/cache/application/CacheService.java +++ b/src/main/java/com/ourmenu/backend/domain/cache/application/CacheService.java @@ -33,7 +33,7 @@ public GetCacheInfoResponse getCacheInfo() { private List getMenuFolderIconInfo() { return Arrays.stream(MenuFolderIcon.values()) .map(menuFolderIcon -> { - String menuFolderIconUrl = urlConvertor.getMenuFolderUrl(menuFolderIcon); + String menuFolderIconUrl = urlConvertor.getMenuFolderImgUrl(menuFolderIcon); return SimpleMenuFolderIconResponse.of(menuFolderIcon, menuFolderIconUrl); }) .toList(); @@ -44,7 +44,7 @@ private List getMenuPinInfo() { .map(menuPin -> { String menuPinMapUrl = urlConvertor.getMenuPinMapUrl(menuPin); String menuPinAddUrl = urlConvertor.getMenuPinAddUrl(menuPin); - String menuPinMapAddDiable = urlConvertor.getMenuPinMapAddDiable(menuPin); + String menuPinMapAddDiable = urlConvertor.getMenuPinMapAddDisable(menuPin); return SimpleMenuPinResponse.of(menuPin, menuPinMapUrl, menuPinAddUrl, menuPinMapAddDiable); }) diff --git a/src/main/java/com/ourmenu/backend/domain/cache/util/MenuPinConverter.java b/src/main/java/com/ourmenu/backend/domain/cache/util/MenuPinConverter.java new file mode 100644 index 00000000..60395ef5 --- /dev/null +++ b/src/main/java/com/ourmenu/backend/domain/cache/util/MenuPinConverter.java @@ -0,0 +1,27 @@ +package com.ourmenu.backend.domain.cache.util; + +import com.ourmenu.backend.domain.cache.domain.MenuPin; +import java.util.List; + +public class MenuPinConverter { + + private MenuPinConverter() { + + } + + public static MenuPin of(List menuPins) { + if (menuPins.size() == 1) { + return menuPins.get(0); + } + if (menuPins.size() == 2) { + return MenuPin.TWO; + } + if (menuPins.size() == 3) { + return MenuPin.THREE; + } + if (menuPins.size() == 4) { + return MenuPin.FOUR; + } + return MenuPin.FIVE; + } +} diff --git a/src/main/java/com/ourmenu/backend/domain/cache/util/UrlConverter.java b/src/main/java/com/ourmenu/backend/domain/cache/util/UrlConverter.java index 352f0643..d4420ff5 100644 --- a/src/main/java/com/ourmenu/backend/domain/cache/util/UrlConverter.java +++ b/src/main/java/com/ourmenu/backend/domain/cache/util/UrlConverter.java @@ -3,6 +3,7 @@ import com.ourmenu.backend.domain.cache.domain.HomeImg; import com.ourmenu.backend.domain.cache.domain.MenuFolderIcon; import com.ourmenu.backend.domain.cache.domain.MenuPin; +import com.ourmenu.backend.domain.home.domain.Answer; import com.ourmenu.backend.domain.tag.domain.Tag; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -14,24 +15,21 @@ public class UrlConverter { private String url; public String getMenuPinMapUrl(MenuPin pin) { - return url + "/menu-pins/" + pin.getImgUrl() + "_map.svg"; + return url + "/menu-pins/" + pin.getImgUrl() + "_map.png"; } public String getMenuPinAddUrl(MenuPin pin) { if (isETCMenuPin(pin)) { return null; } - return url + "/menu-pins/" + pin.getImgUrl() + "_add.svg"; + return url + "/menu-pins/" + pin.getImgUrl() + "_add.png"; } - public String getMenuPinMapAddDiable(MenuPin pin) { - if (isETCMenuPin(pin)) { - return null; - } - return url + "/menu-pins/" + pin.getImgUrl() + "_add_disable.svg"; + public String getMenuPinMapAddDisable(MenuPin pin) { + return url + "/menu-pins/" + pin.getImgUrl() + "_add_disable.png"; } - public String getMenuFolderUrl(MenuFolderIcon icon) { + public String getMenuFolderImgUrl(MenuFolderIcon icon) { return url + "/menu-folder-icons/" + icon.getImgUrl() + ".svg"; } @@ -47,6 +45,14 @@ public String getWhiteTagImgUrl(Tag tag) { return url + "/tags/" + tag.getImgUrl() + "_white.svg"; } + public String getAnswerImgUrl(Answer answer) { + return url + "/answers/" + answer.toString() + ".svg"; + } + + public String getHomeRecommendTagImgUrl(Tag tag) { + return url + "/home_tags/" + tag.getTagEnum() + ".svg"; + } + private boolean isETCMenuPin(MenuPin pin) { return pin.equals(MenuPin.TWO) || pin.equals(MenuPin.THREE) || pin.equals(MenuPin.FOUR) || pin.equals( MenuPin.FIVE); diff --git a/src/main/java/com/ourmenu/backend/domain/home/application/HomeService.java b/src/main/java/com/ourmenu/backend/domain/home/application/HomeService.java index 705c1421..46cb01ff 100644 --- a/src/main/java/com/ourmenu/backend/domain/home/application/HomeService.java +++ b/src/main/java/com/ourmenu/backend/domain/home/application/HomeService.java @@ -1,5 +1,6 @@ package com.ourmenu.backend.domain.home.application; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.home.dao.HomeQuestionAnswerRepository; import com.ourmenu.backend.domain.home.domain.Answer; import com.ourmenu.backend.domain.home.domain.HomeQuestionAnswer; @@ -29,6 +30,7 @@ public class HomeService { private final RecommendMenuCacheService recommendMenuCacheService; private final MenuService menuService; private final MealTimeService mealTimeService; + private final UrlConverter urlConverter; /** * 홈 질문 응답 값을 저장 및 추천 메뉴를 캐싱한다. 질문에 관련 없는 응답이면 에러를 반환한다. @@ -68,12 +70,12 @@ public SaveAndGetQuestionRequest updateQuestion(Long userId) { .userId(userId) .build(); HomeQuestionAnswer saveHomeQuestionAnswer = homeQuestionAnswerRepository.save(homeQuestionAnswer); - return SaveAndGetQuestionRequest.from(saveHomeQuestionAnswer); + return SaveAndGetQuestionRequest.from(saveHomeQuestionAnswer, urlConverter); } HomeQuestionAnswer homeQuestionAnswer = optionalHomeQuestionAnswer.get(); homeQuestionAnswer.update(randomQuestion); - return SaveAndGetQuestionRequest.from(homeQuestionAnswer); + return SaveAndGetQuestionRequest.from(homeQuestionAnswer, urlConverter); } /** @@ -91,7 +93,7 @@ public GetHomeRecommendResponse getRecommendMenus(Long userId) { List randomRecommendMenus = getRandomRecommendMenu(); return GetHomeRecommendResponse.of(answer, questionRecommendMenus, tagRandomRecommendDto.getTag(), - tagRandomRecommendDto.getGetRecommendMenuResponses(), randomRecommendMenus); + tagRandomRecommendDto.getGetRecommendMenuResponses(), randomRecommendMenus, urlConverter); } /** diff --git a/src/main/java/com/ourmenu/backend/domain/home/domain/Answer.java b/src/main/java/com/ourmenu/backend/domain/home/domain/Answer.java index b4310516..13ad996b 100644 --- a/src/main/java/com/ourmenu/backend/domain/home/domain/Answer.java +++ b/src/main/java/com/ourmenu/backend/domain/home/domain/Answer.java @@ -22,6 +22,7 @@ import com.ourmenu.backend.domain.tag.domain.Tag; import java.util.Arrays; import java.util.List; +import java.util.Random; import lombok.Getter; @Getter @@ -38,6 +39,7 @@ public enum Answer { SUMMER("여름", Tag.COOL, SUMMER1, SUMMER2, SUMMER3), WINTER("겨울", Tag.HOT, WINTER1, WINTER2); + private static final Random RANDOM = new Random(); private String answer; private Tag tag; private List homeImgs; @@ -47,4 +49,9 @@ public enum Answer { this.tag = tag; this.homeImgs = Arrays.asList(homeImgs); } + + public HomeImg getRandomHomeImg() { + return homeImgs.get(RANDOM.nextInt(homeImgs.size())); + } + } diff --git a/src/main/java/com/ourmenu/backend/domain/home/domain/Question.java b/src/main/java/com/ourmenu/backend/domain/home/domain/Question.java index 0b50623c..231b0520 100644 --- a/src/main/java/com/ourmenu/backend/domain/home/domain/Question.java +++ b/src/main/java/com/ourmenu/backend/domain/home/domain/Question.java @@ -5,6 +5,7 @@ import static com.ourmenu.backend.domain.home.domain.Answer.MOUNTAIN; import static com.ourmenu.backend.domain.home.domain.Answer.RAINY; import static com.ourmenu.backend.domain.home.domain.Answer.SEA; +import static com.ourmenu.backend.domain.home.domain.Answer.SPICY; import static com.ourmenu.backend.domain.home.domain.Answer.SUMMER; import static com.ourmenu.backend.domain.home.domain.Answer.SUNNY; import static com.ourmenu.backend.domain.home.domain.Answer.SWEET; @@ -19,7 +20,7 @@ public enum Question { FEEL("오늘 기분은 어떠신가요?", LIKE, DISLIKE), WEATHER("오늘 날씨는 어떤가요?", SUNNY, RAINY), - STRESS("스트레스 받을 때는 어떤 음식을 드시나요?", SWEET, RAINY), + STRESS("스트레스 받을 때는 어떤 음식을 드시나요?", SWEET, SPICY), TRIP("어디로 떠나고 싶은가요?", SEA, MOUNTAIN), SEASON("어느 계절을 더 좋아하세요?", SUMMER, WINTER); diff --git a/src/main/java/com/ourmenu/backend/domain/home/dto/GetHomeRecommendResponse.java b/src/main/java/com/ourmenu/backend/domain/home/dto/GetHomeRecommendResponse.java index c31edcb7..12eb5612 100644 --- a/src/main/java/com/ourmenu/backend/domain/home/dto/GetHomeRecommendResponse.java +++ b/src/main/java/com/ourmenu/backend/domain/home/dto/GetHomeRecommendResponse.java @@ -1,5 +1,7 @@ package com.ourmenu.backend.domain.home.dto; +import com.ourmenu.backend.domain.cache.domain.HomeImg; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.home.domain.Answer; import com.ourmenu.backend.domain.tag.domain.Tag; import java.util.List; @@ -13,22 +15,30 @@ @Builder(access = AccessLevel.PRIVATE) public class GetHomeRecommendResponse { - private Answer answer; + private String answerImgUrl; private List answerRecommendMenus; - private Tag tag; + private String tagRecommendImgUrl; private List tagRecommendMenus; + private String otherRecommendImgUrl; private List otherRecommendMenus; public static GetHomeRecommendResponse of(Answer answer, List answerRecommendMenus, Tag tag, List tagRecommendMenus, - List otherRecommendMenus) { + List otherRecommendMenus, + UrlConverter urlConverter) { + HomeImg homeImg = answer.getRandomHomeImg(); + String HomeImgUrl = urlConverter.getHomeImgUrl(homeImg); + String tagRecommendImgUrl = urlConverter.getHomeRecommendTagImgUrl(tag); + String otherRecommendImgUrl = tagRecommendImgUrl; + return GetHomeRecommendResponse.builder() - .answer(answer) + .answerImgUrl(HomeImgUrl) .answerRecommendMenus(answerRecommendMenus) - .tag(tag) + .tagRecommendImgUrl(tagRecommendImgUrl) .tagRecommendMenus(tagRecommendMenus) + .otherRecommendImgUrl(otherRecommendImgUrl) .otherRecommendMenus(otherRecommendMenus) .build(); } diff --git a/src/main/java/com/ourmenu/backend/domain/home/dto/GetRecommendMenuResponse.java b/src/main/java/com/ourmenu/backend/domain/home/dto/GetRecommendMenuResponse.java index b9cb0c8b..e0f7c6c9 100644 --- a/src/main/java/com/ourmenu/backend/domain/home/dto/GetRecommendMenuResponse.java +++ b/src/main/java/com/ourmenu/backend/domain/home/dto/GetRecommendMenuResponse.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.ourmenu.backend.domain.menu.domain.Menu; import com.ourmenu.backend.domain.menu.dto.MenuSimpleDto; +import com.ourmenu.backend.domain.store.domain.Store; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; @@ -18,14 +19,15 @@ public class GetRecommendMenuResponse { private Long menuId; private String menuTitle; - private int menuPrice; + private String storeName; private String menuImgUrl; public static GetRecommendMenuResponse of(Menu menu, String imgUrl) { + Store store = menu.getStore(); return GetRecommendMenuResponse.builder() .menuId(menu.getId()) .menuTitle(menu.getTitle()) - .menuPrice(menu.getPrice()) + .storeName(store.getTitle()) .menuImgUrl(imgUrl) .build(); } @@ -34,7 +36,7 @@ public static GetRecommendMenuResponse of(MenuSimpleDto menuSimpleDto, String im return GetRecommendMenuResponse.builder() .menuId(menuSimpleDto.getMenuId()) .menuTitle(menuSimpleDto.getMenuTitle()) - .menuPrice(menuSimpleDto.getMenuPrice()) + .storeName(menuSimpleDto.getStoreTitle()) .menuImgUrl(imgUrl) .build(); } diff --git a/src/main/java/com/ourmenu/backend/domain/home/dto/SaveAndGetQuestionRequest.java b/src/main/java/com/ourmenu/backend/domain/home/dto/SaveAndGetQuestionRequest.java index 0299534e..f7731381 100644 --- a/src/main/java/com/ourmenu/backend/domain/home/dto/SaveAndGetQuestionRequest.java +++ b/src/main/java/com/ourmenu/backend/domain/home/dto/SaveAndGetQuestionRequest.java @@ -1,7 +1,10 @@ package com.ourmenu.backend.domain.home.dto; +import com.ourmenu.backend.domain.cache.util.UrlConverter; +import com.ourmenu.backend.domain.home.domain.Answer; import com.ourmenu.backend.domain.home.domain.HomeQuestionAnswer; import com.ourmenu.backend.domain.home.domain.Question; +import java.util.List; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; @@ -12,11 +15,36 @@ @Builder(access = AccessLevel.PRIVATE) public class SaveAndGetQuestionRequest { - private Question question; + private String question; + private List answers; + + public static SaveAndGetQuestionRequest from(HomeQuestionAnswer homeQuestionAnswer, UrlConverter urlConverter) { + Question question = homeQuestionAnswer.getQuestion(); + + Answer answer1 = question.getAnswer1(); + AnswerDto answerDto1 = AnswerDto.builder() + .answer(answer1) + .answerImgUrl(urlConverter.getAnswerImgUrl(answer1)) + .build(); + + Answer answer2 = question.getAnswer2(); + AnswerDto answerDto2 = AnswerDto.builder() + .answer(answer2) + .answerImgUrl(urlConverter.getAnswerImgUrl(answer2)) + .build(); - public static SaveAndGetQuestionRequest from(HomeQuestionAnswer homeQuestionAnswer) { return SaveAndGetQuestionRequest.builder() - .question(homeQuestionAnswer.getQuestion()) + .question(question.getQuestion()) + .answers(List.of(answerDto1, answerDto2)) .build(); } + + @AllArgsConstructor(access = AccessLevel.PRIVATE) + @Getter + @Builder(access = AccessLevel.PRIVATE) + private static class AnswerDto { + private Answer answer; + private String answerImgUrl; + + } } diff --git a/src/main/java/com/ourmenu/backend/domain/home/dto/SaveAnswerRequest.java b/src/main/java/com/ourmenu/backend/domain/home/dto/SaveAnswerRequest.java index a12eb159..01055308 100644 --- a/src/main/java/com/ourmenu/backend/domain/home/dto/SaveAnswerRequest.java +++ b/src/main/java/com/ourmenu/backend/domain/home/dto/SaveAnswerRequest.java @@ -1,10 +1,12 @@ package com.ourmenu.backend.domain.home.dto; import com.ourmenu.backend.domain.home.domain.Answer; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @NoArgsConstructor +@AllArgsConstructor @Getter public class SaveAnswerRequest { diff --git a/src/main/java/com/ourmenu/backend/domain/menu/api/MenuController.java b/src/main/java/com/ourmenu/backend/domain/menu/api/MenuController.java index e67bbed3..d890255d 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/api/MenuController.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/api/MenuController.java @@ -60,12 +60,12 @@ public ApiResponse deleteMenu(@PathVariable("menuId") Long menuId, @Operation(summary = "메뉴판 메뉴 리스트 조회", description = "메뉴판의 메뉴 리스트를 조회한다. 필터를 사용할 수 있다") @GetMapping("/menu-folders/{menuFolderId}/menus") - public ApiResponse> getMenuFolderMenus( + public ApiResponse getMenuFolderMenus( @PathVariable("menuFolderId") Long menuFolderId, @RequestParam(value = "sortOrder") SortOrder sortOrder, @AuthenticationPrincipal CustomUserDetails userDetails) { MenuFilterDto menuFilterDto = MenuFilterDto.from(sortOrder); - List response = menuService.findMenusByMenuFolder(userDetails.getId(), + GetMenuFolderMenuResponse response = menuService.findMenusByMenuFolder(userDetails.getId(), menuFolderId, menuFilterDto); return ApiUtil.success(response); } diff --git a/src/main/java/com/ourmenu/backend/domain/menu/application/MapService.java b/src/main/java/com/ourmenu/backend/domain/menu/application/MapService.java index 0794ec64..fd5555da 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/application/MapService.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/application/MapService.java @@ -1,11 +1,12 @@ package com.ourmenu.backend.domain.menu.application; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.menu.dao.MenuFolderRepository; import com.ourmenu.backend.domain.menu.dao.MenuImgRepository; -import com.ourmenu.backend.domain.menu.domain.MenuFolder; -import com.ourmenu.backend.domain.menu.domain.MenuImg; import com.ourmenu.backend.domain.menu.dao.MenuRepository; import com.ourmenu.backend.domain.menu.domain.Menu; +import com.ourmenu.backend.domain.menu.domain.MenuFolder; +import com.ourmenu.backend.domain.menu.domain.MenuImg; import com.ourmenu.backend.domain.menu.dto.MapSearchDto; import com.ourmenu.backend.domain.menu.dto.MapSearchHistoryDto; import com.ourmenu.backend.domain.menu.dto.MenuFolderInfoOnMapDto; @@ -22,6 +23,9 @@ import com.ourmenu.backend.domain.user.dao.UserRepository; import com.ourmenu.backend.domain.user.domain.User; import com.ourmenu.backend.domain.user.exception.NotFoundUserException; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.locationtech.jts.geom.Coordinate; @@ -35,10 +39,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - @Service @RequiredArgsConstructor @Slf4j @@ -51,6 +51,7 @@ public class MapService { private final MenuImgRepository menuImgRepository; private final MenuFolderRepository menuFolderRepository; private final OwnedMenuSearchRepository ownedMenuSearchRepository; + private final UrlConverter urlConverter; /** * 유저가 보유한 메뉴들을 가져와 위치가 같은 메뉴들은 그룹핑하여 조회 @@ -62,18 +63,19 @@ public List findMenusOnMap(Long userId) { User user = userRepository.findById(userId) .orElseThrow(NotFoundUserException::new); List menus = menuRepository.findMenusByUserId(userId); - + java.util.Map> menuMaps = menus.stream() .filter(menu -> menu.getStore().getMap() != null) .collect(Collectors.groupingBy(menu -> menu.getStore().getMap())); return menuMaps.entrySet().stream() - .map(entry -> MenuOnMapDto.from(entry.getKey(), entry.getValue())) + .map(entry -> MenuOnMapDto.from( + entry.getKey(), entry.getValue(), urlConverter)) .collect(Collectors.toList()); } /** - * 지도 화면에서의 같은 위치에 존재하는 메뉴들 조회 + * 지도 화면에서의 같은 위치에 존재하는 메뉴들 조회 * * @param mapId * @param userId @@ -172,10 +174,10 @@ private MenuInfoOnMapDto getMenuInfo(Menu menu) { if (!menuFolders.isEmpty()) { MenuFolder latestMenuFolder = menuFolders.stream() .max(Comparator.comparing(MenuFolder::getCreatedAt)).get(); - menuFolderInfo = MenuFolderInfoOnMapDto.of(latestMenuFolder, menuFolders.size()); + menuFolderInfo = MenuFolderInfoOnMapDto.of(latestMenuFolder, menuFolders.size(), urlConverter); } - return MenuInfoOnMapDto.of(menu, menuTags, menuImgs, menuFolderInfo); + return MenuInfoOnMapDto.of(menu, menuTags, menuImgs, menuFolderInfo, urlConverter); } /** diff --git a/src/main/java/com/ourmenu/backend/domain/menu/application/MenuFolderService.java b/src/main/java/com/ourmenu/backend/domain/menu/application/MenuFolderService.java index ea89b722..ddc698ed 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/application/MenuFolderService.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/application/MenuFolderService.java @@ -1,5 +1,6 @@ package com.ourmenu.backend.domain.menu.application; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.menu.dao.MenuFolderRepository; import com.ourmenu.backend.domain.menu.dao.MenuRepository; import com.ourmenu.backend.domain.menu.domain.MenuFolder; @@ -28,6 +29,7 @@ public class MenuFolderService { private final MenuMenuFolderService menuMenuFolderService; private final DefaultImgConverter defaultImgConvertor; private final MenuRepository menuRepository; + private final UrlConverter urlConverter; /** * 메뉴 폴더 저장 @@ -43,7 +45,7 @@ public SaveMenuFolderResponse saveMenuFolder(MenuFolderDto menuFolderDto) { MenuFolder menuFolder = saveMenuFolder(menuFolderDto, menuFolderImgUrl); return SaveMenuFolderResponse.of(menuFolder, menuFolderDto.getMenuIds(), - defaultImgConvertor.getDefaultMenuFolderImgUrl()); + defaultImgConvertor.getDefaultMenuFolderImgUrl(), urlConverter); } /** @@ -93,7 +95,7 @@ public UpdateMenuFolderResponse updateMenuFolder(Long userId, Long menuFolderId, menuFolder.update(menuFolderDto); List menuMenuFolders = menuMenuFolderService.findAllByMenuFolderId(menuFolderId); return UpdateMenuFolderResponse.of(menuFolder, menuMenuFolders, - defaultImgConvertor.getDefaultMenuFolderImgUrl()); + defaultImgConvertor.getDefaultMenuFolderImgUrl(), urlConverter); } /** @@ -124,7 +126,7 @@ public UpdateMenuFolderResponse updateMenuFolderIndex(Long userId, Long menuFold findMenuFolder.updateIndex(index); List menuMenuFolders = menuMenuFolderService.findAllByMenuFolderId(menuFolderId); return UpdateMenuFolderResponse.of(findMenuFolder, menuMenuFolders, - defaultImgConvertor.getDefaultMenuFolderImgUrl()); + defaultImgConvertor.getDefaultMenuFolderImgUrl(), urlConverter); } @@ -134,7 +136,6 @@ public UpdateMenuFolderResponse updateMenuFolderIndex(Long userId, Long menuFold * @param userId * @return index 기준 내림 차순 메뉴판 리스트 */ - @Transactional public GetMenuFolderResponse findAllMenuFolder(Long userId) { List menuFolders = menuFolderRepository.findAllByUserIdOrderByIndexDesc(userId); @@ -143,17 +144,26 @@ public GetMenuFolderResponse findAllMenuFolder(Long userId) { List menuMenuFolders = menuMenuFolderService.findAllByMenuFolderId( menuFolder.getId()); return MenuFolderResponse.of(menuFolder, menuMenuFolders, - defaultImgConvertor.getDefaultMenuFolderImgUrl()); + defaultImgConvertor.getDefaultMenuFolderImgUrl(), urlConverter); }).toList(); int menuCount = menuRepository.countByUserId(userId); return GetMenuFolderResponse.of(menuCount, menuFolderResponses); } - @Transactional public List findAllByMenuId(Long menuId) { return menuFolderRepository.findMenuFoldersByMenuId(menuId); } + public MenuFolder findOne(Long userId, Long menuFolderId) { + MenuFolder menuFolder = menuFolderRepository.findById(menuFolderId) + .orElseThrow(NotFoundMenuFolderException::new); + Long findUserId = menuFolder.getUserId(); + if (!userId.equals(findUserId)) { + throw new ForbiddenMenuFolderException(); + } + return menuFolder; + } + /** * 메뉴폴더 저장 * @@ -173,14 +183,4 @@ private MenuFolder saveMenuFolder(MenuFolderDto menuFolderDto, String imgUrl) { menuMenuFolderService.saveMenuMenuFolders(menuFolderDto.getMenuIds(), menuFolder.getUserId(), saveMenuFolder); return saveMenuFolder; } - - private MenuFolder findOne(Long userId, Long menuFolderId) { - MenuFolder menuFolder = menuFolderRepository.findById(menuFolderId) - .orElseThrow(NotFoundMenuFolderException::new); - Long findUserId = menuFolder.getUserId(); - if (!userId.equals(findUserId)) { - throw new ForbiddenMenuFolderException(); - } - return menuFolder; - } } diff --git a/src/main/java/com/ourmenu/backend/domain/menu/application/MenuService.java b/src/main/java/com/ourmenu/backend/domain/menu/application/MenuService.java index 1d065e0e..c0701ef9 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/application/MenuService.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/application/MenuService.java @@ -1,5 +1,6 @@ package com.ourmenu.backend.domain.menu.application; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.home.dto.GetRecommendMenuResponse; import com.ourmenu.backend.domain.menu.dao.MenuRepository; import com.ourmenu.backend.domain.menu.domain.Menu; @@ -12,10 +13,12 @@ import com.ourmenu.backend.domain.menu.dto.GetSimpleMenuResponse; import com.ourmenu.backend.domain.menu.dto.MenuDto; import com.ourmenu.backend.domain.menu.dto.MenuFilterDto; +import com.ourmenu.backend.domain.menu.dto.MenuFolderMenuResponse; import com.ourmenu.backend.domain.menu.dto.MenuSimpleDto; import com.ourmenu.backend.domain.menu.dto.SaveMenuResponse; import com.ourmenu.backend.domain.menu.exception.ForbiddenMenuException; import com.ourmenu.backend.domain.menu.exception.NotFoundMenuException; +import com.ourmenu.backend.domain.menu.util.DefaultImgConverter; import com.ourmenu.backend.domain.store.application.StoreService; import com.ourmenu.backend.domain.store.domain.Store; import com.ourmenu.backend.domain.tag.application.MenuTagService; @@ -37,6 +40,8 @@ public class MenuService { private final StoreService storeService; private final MenuImgService menuImgService; private final MenuFolderService menuFolderService; + private final DefaultImgConverter defaultImgConverter; + private final UrlConverter urlConverter; /** * 메뉴 저장(메뉴 사진, 메뉴판, 태그 의존 엔티티 생성 @@ -50,7 +55,7 @@ public SaveMenuResponse saveMenu(MenuDto menuDto) { Store store = storeService.saveStoreAndMap(menuDto.getStoreTitle(), menuDto.getStoreAddress(), menuDto.getMapX(), menuDto.getMapY()); - + Menu menu = Menu.builder() .title(menuDto.getMenuTitle()) .price(menuDto.getMenuPrice()) @@ -73,7 +78,8 @@ public SaveMenuResponse saveMenu(MenuDto menuDto) { //s3 업로드및 이미지 연관관계 생성 List menuImgs = menuImgService.saveMenuImgs(saveMenu.getId(), menuDto.getMenuImgs()); - return SaveMenuResponse.of(saveMenu, store, store.getMap(), menuImgs, saveMenuMenuFolders, saveTag); + return SaveMenuResponse.of(saveMenu, store, store.getMap(), menuImgs, saveMenuMenuFolders, saveTag, + urlConverter); } /** @@ -100,8 +106,8 @@ public void deleteMenu(Long userId, Long menuId) { * @return */ @Transactional - public List findMenusByMenuFolder(Long userId, Long menuFolderId, - MenuFilterDto menuFilterDto) { + public GetMenuFolderMenuResponse findMenusByMenuFolder(Long userId, Long menuFolderId, + MenuFilterDto menuFilterDto) { List findMenuSimpleDto = new ArrayList<>(); SortOrder sortOrder = menuFilterDto.getSortOrder(); if (sortOrder.equals(SortOrder.TITLE_ASC)) { @@ -113,12 +119,16 @@ public List findMenusByMenuFolder(Long userId, Long m if (sortOrder.equals(SortOrder.PRICE_ASC)) { findMenuSimpleDto.addAll(menuRepository.findByMenuFolderIdOrderByPriceAsc(userId, menuFolderId)); } - return findMenuSimpleDto.stream() + List menuResponses = findMenuSimpleDto.stream() .map(menuSimpleDto -> { String imgUrl = menuImgService.findUniqueImg(menuSimpleDto.getMenuId()); - return GetMenuFolderMenuResponse.of(menuSimpleDto, imgUrl); + return MenuFolderMenuResponse.of(menuSimpleDto, imgUrl); }) .toList(); + MenuFolder menuFolder = menuFolderService.findOne(userId, menuFolderId); + + return GetMenuFolderMenuResponse.of(menuFolder, defaultImgConverter.getDefaultMenuFolderImgUrl(), + menuResponses, urlConverter); } /** @@ -208,7 +218,7 @@ public GetMenuResponse findMenu(Long userId, Long menuId) { List imgUrls = menuImgService.findImgUrls(menuId); List tags = menuTagService.findTagNames(menuId); List menuFolders = menuFolderService.findAllByMenuId(menuId); - return GetMenuResponse.of(menu, imgUrls, tags, menuFolders); + return GetMenuResponse.of(menu, imgUrls, tags, menuFolders, urlConverter); } diff --git a/src/main/java/com/ourmenu/backend/domain/menu/dto/GetMenuFolderMenuResponse.java b/src/main/java/com/ourmenu/backend/domain/menu/dto/GetMenuFolderMenuResponse.java index 6b41af40..b13fa41a 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/dto/GetMenuFolderMenuResponse.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/dto/GetMenuFolderMenuResponse.java @@ -1,33 +1,40 @@ package com.ourmenu.backend.domain.menu.dto; -import java.time.LocalDateTime; +import com.ourmenu.backend.domain.cache.util.UrlConverter; +import com.ourmenu.backend.domain.menu.domain.MenuFolder; +import java.util.List; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @AllArgsConstructor(access = AccessLevel.PRIVATE) +@Builder @Getter -@Builder(access = AccessLevel.PRIVATE) public class GetMenuFolderMenuResponse { - private Long menuId; - private String menuTitle; - private String storeTitle; - private String storeAddress; - private int menuPrice; - private String menuImgUrl; - private LocalDateTime createdAt; + private Long menuFolderId; + private String menuFolderTitle; + private String menuFolderImgUrl; + private String menuFolderIconImgUrl; + private List menus; + + public static GetMenuFolderMenuResponse of(MenuFolder menuFolder, String defaultMenuFolderImgUrl, + List menus, UrlConverter urlConverter) { + String menuFolderImgUrl = menuFolder.getImgUrl(); + if (menuFolderImgUrl == null) { + menuFolderImgUrl = defaultMenuFolderImgUrl; + } + + String menuFolderIconImgUrl = urlConverter.getMenuFolderImgUrl(menuFolder.getIcon()); - public static GetMenuFolderMenuResponse of(MenuSimpleDto menuSimpleDto, String menuImgUrl) { return GetMenuFolderMenuResponse.builder() - .menuId(menuSimpleDto.getMenuId()) - .menuTitle(menuSimpleDto.getMenuTitle()) - .storeTitle(menuSimpleDto.getStoreTitle()) - .storeAddress(menuSimpleDto.getStoreAddress()) - .menuPrice(menuSimpleDto.getMenuPrice()) - .menuImgUrl(menuImgUrl) - .createdAt(menuSimpleDto.getCreatedAt()) + .menuFolderId(menuFolder.getId()) + .menuFolderTitle(menuFolder.getTitle()) + .menuFolderImgUrl(menuFolderImgUrl) + .menuFolderIconImgUrl(menuFolderIconImgUrl) + .menus(menus) .build(); } + } diff --git a/src/main/java/com/ourmenu/backend/domain/menu/dto/GetMenuResponse.java b/src/main/java/com/ourmenu/backend/domain/menu/dto/GetMenuResponse.java index 9e739150..055669eb 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/dto/GetMenuResponse.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/dto/GetMenuResponse.java @@ -1,7 +1,6 @@ package com.ourmenu.backend.domain.menu.dto; -import com.ourmenu.backend.domain.cache.domain.MenuFolderIcon; -import com.ourmenu.backend.domain.cache.domain.MenuPin; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.menu.domain.Menu; import com.ourmenu.backend.domain.menu.domain.MenuFolder; import com.ourmenu.backend.domain.tag.domain.Tag; @@ -19,10 +18,10 @@ public class GetMenuResponse { private Long menuId; private String menuTitle; private int menuPrice; - private MenuPin menuPin; + private String menuPinImgUrl; private String storeTitle; private String storeAddress; - private List tags; + private List tagImgUrls; private List menuImgUrls; private List menuFolders; @@ -33,26 +32,35 @@ public class GetMenuResponse { private static class SimpleMenuFolder { private Long menuFolderId; private String menuFolderTitle; - private MenuFolderIcon menuFolderIcon; + private String menuFolderIconImgUrl; } public static GetMenuResponse of(Menu menu, List imgUrls, List tags, - List menuFolders) { + List menuFolders, UrlConverter urlConverter) { + String menuPinImgUrl = urlConverter.getMenuPinMapUrl(menu.getPin()); + List simpleMenuFolders = menuFolders.stream() - .map(menuFolder -> SimpleMenuFolder.builder() - .menuFolderId(menuFolder.getId()) - .menuFolderTitle(menuFolder.getTitle()) - .menuFolderIcon(menuFolder.getIcon()) - .build()) + .map(menuFolder -> { + String menuFolderIconImgUrl = urlConverter.getMenuFolderImgUrl(menuFolder.getIcon()); + return SimpleMenuFolder.builder() + .menuFolderId(menuFolder.getId()) + .menuFolderTitle(menuFolder.getTitle()) + .menuFolderIconImgUrl(menuFolderIconImgUrl) + .build(); + }) + .toList(); + List tagImgUrls = tags.stream() + .map(urlConverter::getOrangeTagImgUrl) .toList(); + return GetMenuResponse.builder(). menuId(menu.getId()) .menuTitle(menu.getTitle()) .menuPrice(menu.getPrice()) - .menuPin(menu.getPin()) + .menuPinImgUrl(menuPinImgUrl) .storeAddress(menu.getStore().getAddress()) .storeTitle(menu.getStore().getTitle()) - .tags(tags) + .tagImgUrls(tagImgUrls) .menuImgUrls(imgUrls) .menuFolders(simpleMenuFolders) .build(); diff --git a/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuFolderInfoOnMapDto.java b/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuFolderInfoOnMapDto.java index 82dfd1ab..1ddd40c9 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuFolderInfoOnMapDto.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuFolderInfoOnMapDto.java @@ -1,6 +1,6 @@ package com.ourmenu.backend.domain.menu.dto; -import com.ourmenu.backend.domain.cache.domain.MenuFolderIcon; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.menu.domain.MenuFolder; import lombok.Builder; import lombok.Getter; @@ -10,13 +10,15 @@ public class MenuFolderInfoOnMapDto { private String menuFolderTitle; - private MenuFolderIcon menuFolderIcon; + private String menuFolderIconImgUrl; private int menuFolderCount; - public static MenuFolderInfoOnMapDto of(MenuFolder menuFolder, int count) { + public static MenuFolderInfoOnMapDto of(MenuFolder menuFolder, int count, UrlConverter urlConverter) { + String menuFolderIconImgUrl = urlConverter.getMenuFolderImgUrl(menuFolder.getIcon()); + return MenuFolderInfoOnMapDto.builder() .menuFolderTitle(menuFolder.getTitle()) - .menuFolderIcon(menuFolder.getIcon()) + .menuFolderIconImgUrl(menuFolderIconImgUrl) .menuFolderCount(count) .build(); } @@ -24,7 +26,7 @@ public static MenuFolderInfoOnMapDto of(MenuFolder menuFolder, int count) { public static MenuFolderInfoOnMapDto empty() { return MenuFolderInfoOnMapDto.builder() .menuFolderTitle("") - .menuFolderIcon(null) + .menuFolderIconImgUrl(null) .menuFolderCount(0) .build(); } diff --git a/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuFolderMenuResponse.java b/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuFolderMenuResponse.java new file mode 100644 index 00000000..4683d340 --- /dev/null +++ b/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuFolderMenuResponse.java @@ -0,0 +1,33 @@ +package com.ourmenu.backend.domain.menu.dto; + +import java.time.LocalDateTime; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Builder(access = AccessLevel.PRIVATE) +public class MenuFolderMenuResponse { + + private Long menuId; + private String menuTitle; + private String storeTitle; + private String storeAddress; + private int menuPrice; + private String menuImgUrl; + private LocalDateTime createdAt; + + public static MenuFolderMenuResponse of(MenuSimpleDto menuSimpleDto, String menuImgUrl) { + return MenuFolderMenuResponse.builder() + .menuId(menuSimpleDto.getMenuId()) + .menuTitle(menuSimpleDto.getMenuTitle()) + .storeTitle(menuSimpleDto.getStoreTitle()) + .storeAddress(menuSimpleDto.getStoreAddress()) + .menuPrice(menuSimpleDto.getMenuPrice()) + .menuImgUrl(menuImgUrl) + .createdAt(menuSimpleDto.getCreatedAt()) + .build(); + } +} diff --git a/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuFolderResponse.java b/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuFolderResponse.java index 8080d2f1..67b177cc 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuFolderResponse.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuFolderResponse.java @@ -1,6 +1,6 @@ package com.ourmenu.backend.domain.menu.dto; -import com.ourmenu.backend.domain.cache.domain.MenuFolderIcon; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.menu.domain.MenuFolder; import com.ourmenu.backend.domain.menu.domain.MenuMenuFolder; import java.util.List; @@ -16,26 +16,28 @@ public class MenuFolderResponse { private Long menuFolderId; private String menuFolderTitle; - private String menuFolderUrl; - private MenuFolderIcon menuFolderIcon; + private String menuFolderImgUrl; + private String menuFolderIconImgUrl; private List menuIds; private int index; public static MenuFolderResponse of(MenuFolder menuFolder, List menuFolders, - String defaultMenuFolderImgUrl) { + String defaultMenuFolderImgUrl, UrlConverter urlConverter) { String menuFolderImgUrl = menuFolder.getImgUrl(); if (menuFolderImgUrl == null) { menuFolderImgUrl = defaultMenuFolderImgUrl; } + String menuFolderIconImgUrl = urlConverter.getMenuFolderImgUrl(menuFolder.getIcon()); + List menuIds = menuFolders.stream() .map(menuMenuFolder -> menuMenuFolder.getMenu().getId()) .toList(); return MenuFolderResponse.builder() .menuFolderId(menuFolder.getId()) .menuFolderTitle(menuFolder.getTitle()) - .menuFolderUrl(menuFolderImgUrl) - .menuFolderIcon(menuFolder.getIcon()) + .menuFolderImgUrl(menuFolderImgUrl) + .menuFolderIconImgUrl(menuFolderIconImgUrl) .menuIds(menuIds) .index(menuFolder.getIndex()) .build(); diff --git a/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuInfoOnMapDto.java b/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuInfoOnMapDto.java index 4f6fecf8..9d4bbc26 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuInfoOnMapDto.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuInfoOnMapDto.java @@ -1,10 +1,9 @@ package com.ourmenu.backend.domain.menu.dto; -import com.ourmenu.backend.domain.cache.domain.MenuPin; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.menu.domain.Menu; import com.ourmenu.backend.domain.menu.domain.MenuImg; import com.ourmenu.backend.domain.tag.domain.MenuTag; -import com.ourmenu.backend.domain.tag.domain.Tag; import java.util.List; import java.util.stream.Collectors; import lombok.Builder; @@ -17,8 +16,8 @@ public class MenuInfoOnMapDto { private Long menuId; private String menuTitle; private Integer menuPrice; - private MenuPin menuPin; - private List menuTags; + private String menuPinImgUrl; + private List menuTagImgUrls; private List menuImgUrls; private MenuFolderInfoOnMapDto menuFolderInfo; private Long mapId; @@ -26,15 +25,19 @@ public class MenuInfoOnMapDto { private Double mapY; public static MenuInfoOnMapDto of(Menu menu, List menuTags, List menuImgs, - MenuFolderInfoOnMapDto menuFolderInfo) { + MenuFolderInfoOnMapDto menuFolderInfo, UrlConverter urlConverter) { + String menuPinImgUrl = urlConverter.getMenuPinMapUrl(menu.getPin()); + List menuTagImgUrls = menuTags.stream() + .map(MenuTag::getTag) + .map(urlConverter::getOrangeTagImgUrl) + .toList(); + return MenuInfoOnMapDto.builder() .menuId(menu.getId()) .menuTitle(menu.getTitle()) .menuPrice(menu.getPrice()) - .menuPin(menu.getPin()) - .menuTags(menuTags.stream().map( - MenuTag::getTag - ).collect(Collectors.toList())) + .menuPinImgUrl(menuPinImgUrl) + .menuTagImgUrls(menuTagImgUrls) .menuImgUrls(menuImgs.stream().map( menuImg -> menuImg.getImgUrl() ).collect(Collectors.toList())) diff --git a/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuOnMapDto.java b/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuOnMapDto.java index 7d13253a..61c21080 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuOnMapDto.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/dto/MenuOnMapDto.java @@ -1,10 +1,11 @@ package com.ourmenu.backend.domain.menu.dto; import com.ourmenu.backend.domain.cache.domain.MenuPin; +import com.ourmenu.backend.domain.cache.util.MenuPinConverter; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.menu.domain.Menu; import com.ourmenu.backend.domain.store.domain.Map; import java.util.List; -import java.util.stream.Collectors; import lombok.Builder; import lombok.Getter; @@ -13,16 +14,24 @@ public class MenuOnMapDto { private Long mapId; - private List menuPins; + private String menuPinImgUrl; + private String menuPinDisableImgUrl; private Double mapX; private Double mapY; - public static MenuOnMapDto from(Map map, List menus) { + public static MenuOnMapDto from(Map map, List menus, UrlConverter urlConverter) { + + List menuPins = menus.stream() + .map(Menu::getPin) + .toList(); + MenuPin menuPin = MenuPinConverter.of(menuPins); + String menuPinImgUrl = urlConverter.getMenuPinMapUrl(menuPin); + String menuPinDisableImgUrl = urlConverter.getMenuPinMapAddDisable(menuPin); + return MenuOnMapDto.builder() .mapId(map.getId()) - .menuPins(menus.stream() - .map(Menu::getPin) - .collect(Collectors.toList())) + .menuPinImgUrl(menuPinImgUrl) + .menuPinDisableImgUrl(menuPinDisableImgUrl) .mapX(map.getLocation().getX()) .mapY(map.getLocation().getY()) .build(); diff --git a/src/main/java/com/ourmenu/backend/domain/menu/dto/SaveMenuFolderResponse.java b/src/main/java/com/ourmenu/backend/domain/menu/dto/SaveMenuFolderResponse.java index 7e50e420..a9a59b37 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/dto/SaveMenuFolderResponse.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/dto/SaveMenuFolderResponse.java @@ -1,6 +1,6 @@ package com.ourmenu.backend.domain.menu.dto; -import com.ourmenu.backend.domain.cache.domain.MenuFolderIcon; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.menu.domain.MenuFolder; import java.util.List; import lombok.AccessLevel; @@ -16,13 +16,14 @@ public class SaveMenuFolderResponse { private Long menuFolderId; private String menuFolderTitle; private String menuFolderUrl; - private MenuFolderIcon menuFolderIcon; + private String menuFolderIconImgUrl; private List menuIds; private int index; public static SaveMenuFolderResponse of(MenuFolder menuFolder, List menuIds, - String defaultMenuFolderImgUrl) { + String defaultMenuFolderImgUrl, UrlConverter urlConverter) { String menuFolderImgUrl = menuFolder.getImgUrl(); + String menuFolderIconImgUrl = urlConverter.getMenuFolderImgUrl(menuFolder.getIcon()); if (menuFolderImgUrl == null) { menuFolderImgUrl = defaultMenuFolderImgUrl; } @@ -31,7 +32,7 @@ public static SaveMenuFolderResponse of(MenuFolder menuFolder, List menuId .menuFolderId(menuFolder.getId()) .menuFolderTitle(menuFolder.getTitle()) .menuFolderUrl(menuFolderImgUrl) - .menuFolderIcon(menuFolder.getIcon()) + .menuFolderIconImgUrl(menuFolderIconImgUrl) .menuIds(menuIds) .index(menuFolder.getIndex()) .build(); diff --git a/src/main/java/com/ourmenu/backend/domain/menu/dto/SaveMenuResponse.java b/src/main/java/com/ourmenu/backend/domain/menu/dto/SaveMenuResponse.java index 4b60b184..85b88613 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/dto/SaveMenuResponse.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/dto/SaveMenuResponse.java @@ -1,6 +1,6 @@ package com.ourmenu.backend.domain.menu.dto; -import com.ourmenu.backend.domain.cache.domain.MenuPin; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.menu.domain.Menu; import com.ourmenu.backend.domain.menu.domain.MenuImg; import com.ourmenu.backend.domain.menu.domain.MenuMenuFolder; @@ -23,10 +23,10 @@ public class SaveMenuResponse { private int menuPrice; private String menuMemoTitle; private String menuMemoContent; - private MenuPin menuPin; + private String menuPinImgUrl; private List menuFolderIds; private boolean isCrawled; - private List tags; + private List tagImgUrls; private String storeTitle; private String storeAddress; private Double storeMapX; @@ -34,19 +34,27 @@ public class SaveMenuResponse { private List menuImgUrls; public static SaveMenuResponse of(Menu menu, Store store, Map map, List menuImgs, - List menuMenuFolders, List tags) { - List menuImgUrls = menuImgs.stream().map(MenuImg::getImgUrl).toList(); - List menuFolderIds = menuMenuFolders.stream().map(MenuMenuFolder::getFolderId).toList(); + List menuMenuFolders, List tags, UrlConverter urlConverter) { + String menuPinImgUrl = urlConverter.getMenuPinAddUrl(menu.getPin()); + List menuFolderIds = menuMenuFolders.stream() + .map(MenuMenuFolder::getFolderId) + .toList(); + List tagImgUrls = tags.stream() + .map(urlConverter::getOrangeTagImgUrl) + .toList(); + List menuImgUrls = menuImgs.stream() + .map(MenuImg::getImgUrl) + .toList(); return SaveMenuResponse.builder() .menuId(menu.getId()) .menuTitle(menu.getTitle()) .menuPrice(menu.getPrice()) .menuMemoTitle(menu.getMemoTitle()) .menuMemoContent(menu.getMemoContent()) - .menuPin(menu.getPin()) + .menuPinImgUrl(menuPinImgUrl) .menuFolderIds(menuFolderIds) .isCrawled(menu.getIsCrawled()) - .tags(tags) + .tagImgUrls(tagImgUrls) .storeTitle(store.getTitle()) .storeAddress(store.getAddress()) .storeMapX(map.getLocation().getX()) diff --git a/src/main/java/com/ourmenu/backend/domain/menu/dto/UpdateMenuFolderIndexRequest.java b/src/main/java/com/ourmenu/backend/domain/menu/dto/UpdateMenuFolderIndexRequest.java index f6eba902..5df5ad58 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/dto/UpdateMenuFolderIndexRequest.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/dto/UpdateMenuFolderIndexRequest.java @@ -1,9 +1,11 @@ package com.ourmenu.backend.domain.menu.dto; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @NoArgsConstructor +@AllArgsConstructor @Getter public class UpdateMenuFolderIndexRequest { diff --git a/src/main/java/com/ourmenu/backend/domain/menu/dto/UpdateMenuFolderResponse.java b/src/main/java/com/ourmenu/backend/domain/menu/dto/UpdateMenuFolderResponse.java index 1ea3793c..afbffaf0 100644 --- a/src/main/java/com/ourmenu/backend/domain/menu/dto/UpdateMenuFolderResponse.java +++ b/src/main/java/com/ourmenu/backend/domain/menu/dto/UpdateMenuFolderResponse.java @@ -1,6 +1,6 @@ package com.ourmenu.backend.domain.menu.dto; -import com.ourmenu.backend.domain.cache.domain.MenuFolderIcon; +import com.ourmenu.backend.domain.cache.util.UrlConverter; import com.ourmenu.backend.domain.menu.domain.MenuFolder; import com.ourmenu.backend.domain.menu.domain.MenuMenuFolder; import java.util.List; @@ -16,26 +16,28 @@ public class UpdateMenuFolderResponse { private Long menuFolderId; private String menuFolderTitle; - private String menuFolderUrl; - private MenuFolderIcon menuFolderIcon; + private String menuFolderImgUrl; + private String menuFolderIconImgUrl; private List menuIds; private int index; public static UpdateMenuFolderResponse of(MenuFolder menuFolder, List menuMenuFolders, - String defaultMenuFolderImgUrl) { + String defaultMenuFolderImgUrl, UrlConverter urlConverter) { String menuFolderImgUrl = menuFolder.getImgUrl(); if (menuFolderImgUrl == null) { menuFolderImgUrl = defaultMenuFolderImgUrl; } + String menuFolderIconImgUrl = urlConverter.getMenuFolderImgUrl(menuFolder.getIcon()); + List menuId = menuMenuFolders.stream() .map(menuMenuFolder -> menuMenuFolder.getMenu().getId()) .toList(); return UpdateMenuFolderResponse.builder() .menuFolderId(menuFolder.getId()) .menuFolderTitle(menuFolder.getTitle()) - .menuFolderUrl(menuFolderImgUrl) - .menuFolderIcon(menuFolder.getIcon()) + .menuFolderImgUrl(menuFolderImgUrl) + .menuFolderIconImgUrl(menuFolderIconImgUrl) .menuIds(menuId) .index(menuFolder.getIndex()) .build(); diff --git a/src/main/java/com/ourmenu/backend/domain/user/api/EmailController.java b/src/main/java/com/ourmenu/backend/domain/user/api/EmailController.java index 17e0605e..fe326fd5 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/api/EmailController.java +++ b/src/main/java/com/ourmenu/backend/domain/user/api/EmailController.java @@ -26,21 +26,21 @@ public class EmailController { @Operation(summary = "이메일 인증 요청", description = "메일에 인증 메세지를 요청한다.") @PostMapping("") - private ApiResponse sendConfirmCode(@Valid @RequestBody PostEmailRequest request) { + public ApiResponse sendConfirmCode(@Valid @RequestBody PostEmailRequest request) { EmailResponse response = emailService.sendCodeToEmail(request); return ApiUtil.success(response); } @Operation(summary = "이메일 인증", description = "메일에 전송된 이메일을 인증한다.") @PostMapping("/confirm-code") - private ApiResponse verifyEmail(@Valid @RequestBody VerifyEmailRequest request) { + public ApiResponse verifyEmail(@Valid @RequestBody VerifyEmailRequest request) { emailService.verifyConfirmCode(request); return ApiUtil.successOnly(); } @Operation(summary = "임시 비밀번호 발급", description = "임시 비밀번호를 발급한다.") @PostMapping("/temporary-password") - private ApiResponse sendTemporaryPassword(@RequestBody PostEmailRequest request) { + public ApiResponse sendTemporaryPassword(@RequestBody PostEmailRequest request) { TemporaryPasswordResponse response = emailService.sendTemporaryPassword(request); return ApiUtil.success(response); } diff --git a/src/main/java/com/ourmenu/backend/domain/user/api/UserController.java b/src/main/java/com/ourmenu/backend/domain/user/api/UserController.java index 985319c2..41676589 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/api/UserController.java +++ b/src/main/java/com/ourmenu/backend/domain/user/api/UserController.java @@ -40,28 +40,28 @@ public class UserController { @Operation(summary = "회원가입", description = "회원가입한다") @PostMapping("/sign-up") - private ApiResponse signUp(@Valid @RequestBody SignUpRequest request) { + public ApiResponse signUp(@Valid @RequestBody SignUpRequest request) { TokenDto response = userService.signUp(request); return ApiUtil.success(response); } @Operation(summary = "로그인", description = "로그인한다.") @PostMapping("/sign-in") - private ApiResponse signIn(@Valid @RequestBody SignInRequest request, HttpServletResponse response) { - TokenDto tokenDto = userService.signIn(request, response); + public ApiResponse signIn(@Valid @RequestBody SignInRequest request) { + TokenDto tokenDto = userService.signIn(request); return ApiUtil.success(tokenDto); } @Operation(summary = "카카오 계정 검증", description = "카카오 계정 존재 여부를 확인한다.") @PostMapping("/auth/kakao") - private ApiResponse checkKakaoUserExists(@RequestBody PostEmailRequest request) { + public ApiResponse checkKakaoUserExists(@RequestBody PostEmailRequest request) { KakaoExistenceResponse response = userService.validateKakaoUserExists(request); return ApiUtil.success(response); } @Operation(summary = "패스워드 변경", description = "패스워드를 변경한다.") @PatchMapping("/password") - private ApiResponse changePassword(@Valid @RequestBody UpdatePasswordRequest request, + public ApiResponse changePassword(@Valid @RequestBody UpdatePasswordRequest request, @AuthenticationPrincipal CustomUserDetails userDetails) { userService.changePassword(request, userDetails); return ApiUtil.successOnly(); @@ -69,7 +69,7 @@ private ApiResponse changePassword(@Valid @RequestBody UpdatePasswordReque @Operation(summary = "식사 시간 변경", description = "식사 시간을 변경한다.") @PatchMapping("/meal-time") - private ApiResponse changeMealTime(@Valid @RequestBody UpdateMealTimeRequest request, + public ApiResponse changeMealTime(@Valid @RequestBody UpdateMealTimeRequest request, @AuthenticationPrincipal CustomUserDetails userDetails) { mealTimeService.changeMealTime(request, userDetails.getId()); return ApiUtil.successOnly(); @@ -77,14 +77,14 @@ private ApiResponse changeMealTime(@Valid @RequestBody UpdateMealTimeReque @Operation(summary = "유저 정보 조회", description = "유저 정보를 조회한다") @GetMapping("") - private ApiResponse getUserInfo(@AuthenticationPrincipal CustomUserDetails userDetails) { + public ApiResponse getUserInfo(@AuthenticationPrincipal CustomUserDetails userDetails) { UserDto response = userService.getUserInfo(userDetails); return ApiUtil.success(response); } @Operation(summary = "로그아웃", description = "로그아웃한다.") @PostMapping("/sign-out") - private ApiResponse signOut(HttpServletRequest request, + public ApiResponse signOut(HttpServletRequest request, @AuthenticationPrincipal CustomUserDetails userDetails) { userService.signOut(request); return ApiUtil.successOnly(); @@ -92,14 +92,14 @@ private ApiResponse signOut(HttpServletRequest request, @Operation(summary = "토큰 갱신", description = "Access 토큰을 갱신한다.") @PostMapping("/reissue-token") - private ApiResponse reissueToken(@Valid @RequestBody ReissueRequest reissueRequest) { + public ApiResponse reissueToken(@Valid @RequestBody ReissueRequest reissueRequest) { TokenDto response = userService.reissueToken(reissueRequest); return ApiUtil.success(response); } @Operation(summary = "유저 삭제", description = "유저를 DB에서 삭제한다.") @DeleteMapping("") - private ApiResponse deleteUser(@AuthenticationPrincipal CustomUserDetails userDetails) { + public ApiResponse deleteUser(@AuthenticationPrincipal CustomUserDetails userDetails) { userService.removeUser(userDetails.getId()); return ApiUtil.successOnly(); } diff --git a/src/main/java/com/ourmenu/backend/domain/user/application/EmailService.java b/src/main/java/com/ourmenu/backend/domain/user/application/EmailService.java index 8d1b64b7..c07a95bb 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/application/EmailService.java +++ b/src/main/java/com/ourmenu/backend/domain/user/application/EmailService.java @@ -15,6 +15,7 @@ import jakarta.mail.MessagingException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import java.util.concurrent.ThreadLocalRandom; @@ -28,6 +29,7 @@ public class EmailService { private final int CONFIRM_CODE_LENGTH = 6; private final ConfirmCodeRepository confirmCodeRepository; private final UserRepository userRepository; + private final PasswordEncoder passwordEncoder; public EmailResponse sendCodeToEmail(PostEmailRequest request){ String email = request.getEmail(); @@ -55,7 +57,7 @@ public EmailResponse sendCodeToEmail(PostEmailRequest request){ } public String generateRandomCode(int length) { - String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + String characters = "0123456789"; StringBuilder confirmCode = new StringBuilder(); ThreadLocalRandom random = ThreadLocalRandom.current(); @@ -85,7 +87,7 @@ public TemporaryPasswordResponse sendTemporaryPassword(PostEmailRequest request) User user = userRepository.findByEmail(email) .orElseThrow(NotFoundUserException::new); - user.changePassword(temporaryPassword); + user.changePassword(passwordEncoder.encode(temporaryPassword)); userRepository.save(user); return TemporaryPasswordResponse.from(temporaryPassword); } diff --git a/src/main/java/com/ourmenu/backend/domain/user/application/MealTimeService.java b/src/main/java/com/ourmenu/backend/domain/user/application/MealTimeService.java index c1839b8e..a17a536c 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/application/MealTimeService.java +++ b/src/main/java/com/ourmenu/backend/domain/user/application/MealTimeService.java @@ -48,7 +48,7 @@ public long getNextUpdateMinute(Long userId) { * @return */ @Transactional - public List saveMealTimes(List mealTimes, Long userId) { + public List saveMealTimes(List mealTimes, Long userId) { return mealTimes.stream() .map(mealTime -> saveMealTime(mealTime, userId)) .toList(); @@ -90,12 +90,11 @@ private LocalTime getFirstMealTime(Long userId) { /** * 식시시간을 시간 타입을 변환하여 저장한다. * - * @param timeInteger + * @param time * @param userId * @return */ - private MealTime saveMealTime(int timeInteger, Long userId) { - LocalTime time = TimeUtil.of(timeInteger); + private MealTime saveMealTime(LocalTime time, Long userId) { MealTime mealTime = MealTime.builder() .userId(userId) .mealTime(time) diff --git a/src/main/java/com/ourmenu/backend/domain/user/application/UserService.java b/src/main/java/com/ourmenu/backend/domain/user/application/UserService.java index 73bd05a7..e22a7069 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/application/UserService.java +++ b/src/main/java/com/ourmenu/backend/domain/user/application/UserService.java @@ -12,6 +12,7 @@ import com.ourmenu.backend.domain.user.dto.request.SignUpRequest; import com.ourmenu.backend.domain.user.dto.request.UpdatePasswordRequest; import com.ourmenu.backend.domain.user.dto.response.KakaoExistenceResponse; +import com.ourmenu.backend.domain.user.dto.response.MealTimeDto; import com.ourmenu.backend.domain.user.dto.response.ReissueRequest; import com.ourmenu.backend.domain.user.dto.response.TokenDto; import com.ourmenu.backend.domain.user.dto.response.UserDto; @@ -25,14 +26,16 @@ import com.ourmenu.backend.domain.user.exception.UnsupportedSignInTypeException; import com.ourmenu.backend.global.util.JwtTokenProvider; import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.transaction.Transactional; + +import java.time.LocalTime; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Slf4j @Service @@ -72,10 +75,10 @@ public TokenDto signUp(SignUpRequest request) { * 로그인 로직 및 로그인 성공시 RefreshToken 갱신 후 JWT 정보 반환한다 * * @param request User의 Email, Password, SignInType Request - * @param response HTTP Response * @return Token 정보 */ - public TokenDto signIn(SignInRequest request, HttpServletResponse response) { + @Transactional + public TokenDto signIn(SignInRequest request) { Optional optionalUser = userRepository.findByEmail(request.getEmail()); if (optionalUser.isEmpty() || !optionalUser.get().getSignInType().name().equals(request.getSignInType())) { throw new NotFoundUserException(); @@ -106,6 +109,7 @@ public TokenDto signIn(SignInRequest request, HttpServletResponse response) { * @param request * @param userDetails */ + @Transactional public void changePassword(UpdatePasswordRequest request, CustomUserDetails userDetails) { String rawPassword = request.getPassword(); String encodedPassword = userDetails.getPassword(); @@ -133,8 +137,15 @@ public UserDto getUserInfo(CustomUserDetails userDetails) { .orElseThrow(NotFoundUserException::new); List mealTimes = mealTimeService.findAllByUserId(userDetails.getId()); + List mealTimeDtos = new ArrayList<>(); + + for (MealTime mealTime : mealTimes) { + boolean isAfter = LocalTime.now().isAfter(mealTime.getMealTime()); + MealTimeDto mealTimeDto = MealTimeDto.of(mealTime, isAfter); + mealTimeDtos.add(mealTimeDto); + } - return UserDto.of(user, mealTimes); + return UserDto.of(user, mealTimeDtos); } /** @@ -143,6 +154,7 @@ public UserDto getUserInfo(CustomUserDetails userDetails) { * @param reissueRequest * @return */ + @Transactional public TokenDto reissueToken(ReissueRequest reissueRequest) { String refreshToken = reissueRequest.getRefreshToken(); String email = jwtTokenProvider.getEmailFromToken(refreshToken); @@ -178,6 +190,7 @@ public TokenDto reissueToken(ReissueRequest reissueRequest) { * * @param request */ + @Transactional public void signOut(HttpServletRequest request) { String token = request.getHeader("Authorization"); if (token.startsWith("Bearer ")) { @@ -213,6 +226,7 @@ public KakaoExistenceResponse validateKakaoUserExists(PostEmailRequest request) * * @param userId */ + @Transactional public void removeUser(Long userId) { User user = userRepository.findById(userId) .orElseThrow(NotFoundUserException::new); diff --git a/src/main/java/com/ourmenu/backend/domain/user/dto/request/PostEmailRequest.java b/src/main/java/com/ourmenu/backend/domain/user/dto/request/PostEmailRequest.java index 99eb87be..cb5bb397 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/dto/request/PostEmailRequest.java +++ b/src/main/java/com/ourmenu/backend/domain/user/dto/request/PostEmailRequest.java @@ -3,7 +3,8 @@ import lombok.*; @Getter -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor public class PostEmailRequest { private String email; } diff --git a/src/main/java/com/ourmenu/backend/domain/user/dto/request/SignInRequest.java b/src/main/java/com/ourmenu/backend/domain/user/dto/request/SignInRequest.java index 5c2e9788..0d53e451 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/dto/request/SignInRequest.java +++ b/src/main/java/com/ourmenu/backend/domain/user/dto/request/SignInRequest.java @@ -1,10 +1,13 @@ package com.ourmenu.backend.domain.user.dto.request; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @Getter -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor public class SignInRequest { private String email; private String password; diff --git a/src/main/java/com/ourmenu/backend/domain/user/dto/request/SignUpRequest.java b/src/main/java/com/ourmenu/backend/domain/user/dto/request/SignUpRequest.java index 0d7f7e62..770ee187 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/dto/request/SignUpRequest.java +++ b/src/main/java/com/ourmenu/backend/domain/user/dto/request/SignUpRequest.java @@ -1,15 +1,26 @@ package com.ourmenu.backend.domain.user.dto.request; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import java.util.ArrayList; +import java.time.LocalTime; +import java.util.List; @Getter -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor public class SignUpRequest { private String email; private String password; - private ArrayList mealTime; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm:ss") + @ArraySchema(arraySchema = @Schema(example = "[\"12:00:00\"]"), + schema = @Schema(type = "string", format = "time", example = "12:00:00")) + private List mealTime; private String signInType; } diff --git a/src/main/java/com/ourmenu/backend/domain/user/dto/request/UpdateMealTimeRequest.java b/src/main/java/com/ourmenu/backend/domain/user/dto/request/UpdateMealTimeRequest.java index 48611e52..786db7a3 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/dto/request/UpdateMealTimeRequest.java +++ b/src/main/java/com/ourmenu/backend/domain/user/dto/request/UpdateMealTimeRequest.java @@ -1,13 +1,23 @@ package com.ourmenu.backend.domain.user.dto.request; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import java.util.ArrayList; +import java.time.LocalTime; +import java.util.List; @Getter -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor public class UpdateMealTimeRequest { - ArrayList mealTime; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm:ss") + @ArraySchema(arraySchema = @Schema(example = "[\"12:00:00\"]"), + schema = @Schema(type = "string", format = "time", example = "12:00:00")) + List mealTime; } diff --git a/src/main/java/com/ourmenu/backend/domain/user/dto/request/UpdatePasswordRequest.java b/src/main/java/com/ourmenu/backend/domain/user/dto/request/UpdatePasswordRequest.java index 9673daf7..8b69b944 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/dto/request/UpdatePasswordRequest.java +++ b/src/main/java/com/ourmenu/backend/domain/user/dto/request/UpdatePasswordRequest.java @@ -1,10 +1,13 @@ package com.ourmenu.backend.domain.user.dto.request; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @Getter -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor public class UpdatePasswordRequest { String password; String newPassword; diff --git a/src/main/java/com/ourmenu/backend/domain/user/dto/request/VerifyEmailRequest.java b/src/main/java/com/ourmenu/backend/domain/user/dto/request/VerifyEmailRequest.java index 4dd9f1b8..b20fc092 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/dto/request/VerifyEmailRequest.java +++ b/src/main/java/com/ourmenu/backend/domain/user/dto/request/VerifyEmailRequest.java @@ -1,10 +1,13 @@ package com.ourmenu.backend.domain.user.dto.request; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @Getter -@NoArgsConstructor +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor public class VerifyEmailRequest { private String email; private String confirmCode; diff --git a/src/main/java/com/ourmenu/backend/domain/user/dto/response/MealTimeDto.java b/src/main/java/com/ourmenu/backend/domain/user/dto/response/MealTimeDto.java new file mode 100644 index 00000000..b86d33ae --- /dev/null +++ b/src/main/java/com/ourmenu/backend/domain/user/dto/response/MealTimeDto.java @@ -0,0 +1,33 @@ +package com.ourmenu.backend.domain.user.dto.response; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.ourmenu.backend.domain.user.domain.MealTime; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalTime; + +@Getter +@Builder +@JsonIgnoreProperties({"after"}) +public class MealTimeDto { + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm:ss") + @ArraySchema(arraySchema = @Schema(example = "[\"12:00:00\"]"), + schema = @Schema(type = "string", format = "time", example = "12:00:00")) + private LocalTime mealTime; + + @JsonProperty("isAfter") + private boolean isAfter; + + public static MealTimeDto of(MealTime mealTime, boolean isAfter) { + return MealTimeDto.builder() + .mealTime(mealTime.getMealTime()) + .isAfter(isAfter) + .build(); + } +} diff --git a/src/main/java/com/ourmenu/backend/domain/user/dto/response/ReissueRequest.java b/src/main/java/com/ourmenu/backend/domain/user/dto/response/ReissueRequest.java index c06abdbd..3c6b16b4 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/dto/response/ReissueRequest.java +++ b/src/main/java/com/ourmenu/backend/domain/user/dto/response/ReissueRequest.java @@ -1,9 +1,11 @@ package com.ourmenu.backend.domain.user.dto.response; import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; import lombok.Getter; @Getter +@AllArgsConstructor public class ReissueRequest { @NotBlank diff --git a/src/main/java/com/ourmenu/backend/domain/user/dto/response/UserDto.java b/src/main/java/com/ourmenu/backend/domain/user/dto/response/UserDto.java index 8942c534..9beb45aa 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/dto/response/UserDto.java +++ b/src/main/java/com/ourmenu/backend/domain/user/dto/response/UserDto.java @@ -1,10 +1,8 @@ package com.ourmenu.backend.domain.user.dto.response; -import com.ourmenu.backend.domain.user.domain.MealTime; import com.ourmenu.backend.domain.user.domain.User; -import java.time.LocalTime; import java.util.List; -import java.util.stream.Collectors; + import lombok.Builder; import lombok.Getter; @@ -14,15 +12,19 @@ public class UserDto { private String email; private String signInType; - private List mealTime; + private List mealTimeList; + private String announcementUrl; + private String customerServiceUrl; + private String appReviewUrl; - public static UserDto of(User user, List mealTimes) { + public static UserDto of(User user, List mealTimes) { return UserDto.builder() .email(user.getEmail()) .signInType(user.getSignInType().name()) - .mealTime(mealTimes.stream() - .map(MealTime::getMealTime) - .collect(Collectors.toList())) + .mealTimeList(mealTimes) + .announcementUrl("") + .customerServiceUrl("") + .appReviewUrl("") .build(); } } diff --git a/src/main/java/com/ourmenu/backend/domain/user/util/TimeUtil.java b/src/main/java/com/ourmenu/backend/domain/user/util/TimeUtil.java index a5c940b2..2253d610 100644 --- a/src/main/java/com/ourmenu/backend/domain/user/util/TimeUtil.java +++ b/src/main/java/com/ourmenu/backend/domain/user/util/TimeUtil.java @@ -10,21 +10,6 @@ public class TimeUtil { private TimeUtil() { } - /** - * 시간을 LocalTime으로 변환한다. - * - * @param time - * @return - */ - public static LocalTime of(int time) { - String timeStr = String.format("%04d", time); - - int hour = Integer.parseInt(timeStr.substring(0, 2)); - int minute = Integer.parseInt(timeStr.substring(2, 4)); - - return LocalTime.of(hour, minute); - } - /** * 파라미터 값이 현재 시간을 경과 했는지 검증한다 * @@ -75,4 +60,5 @@ public static long getTimeDifferenceDayAfter(LocalTime time) { return todayDuration.toMinutes() + tomorrowDuration.toMinutes(); } + } diff --git a/src/main/java/com/ourmenu/backend/global/response/ApiResponse.java b/src/main/java/com/ourmenu/backend/global/response/ApiResponse.java index 44832ee2..8cd4c835 100644 --- a/src/main/java/com/ourmenu/backend/global/response/ApiResponse.java +++ b/src/main/java/com/ourmenu/backend/global/response/ApiResponse.java @@ -1,13 +1,17 @@ package com.ourmenu.backend.global.response; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.ourmenu.backend.global.exception.ErrorResponse; import lombok.AllArgsConstructor; +import lombok.Getter; @AllArgsConstructor @JsonInclude(Include.NON_NULL) +@JsonIgnoreProperties({"success"}) +@Getter public class ApiResponse { @JsonProperty(value = "isSuccess") diff --git a/src/main/java/com/ourmenu/backend/global/util/JwtTokenProvider.java b/src/main/java/com/ourmenu/backend/global/util/JwtTokenProvider.java index 25f668a9..d918aa25 100644 --- a/src/main/java/com/ourmenu/backend/global/util/JwtTokenProvider.java +++ b/src/main/java/com/ourmenu/backend/global/util/JwtTokenProvider.java @@ -22,6 +22,7 @@ import java.util.Base64; import java.util.Date; import java.util.Optional; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index be6e2df8..d09bb2b2 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -13,7 +13,6 @@ spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #MongoDb spring.data.mongodb.uri=${MONGO_URL} # JPA Configuration -spring.jpa.hibernate.ddl-auto=create spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect @@ -48,4 +47,6 @@ springdoc.swagger-ui.syntax-highlight.theme=arta springdoc.swagger-ui.display-request-duration=true # actuator management.endpoint.prometheus.enabled=true -management.endpoints.web.exposure.include=prometheus \ No newline at end of file +management.endpoints.web.exposure.include=prometheus +# logging +logging.file.name=/var/log/springboot/app.log diff --git a/src/test/java/com/ourmenu/backend/domain/cache/api/CacheApiTest.java b/src/test/java/com/ourmenu/backend/domain/cache/api/CacheApiTest.java new file mode 100644 index 00000000..4e3ee722 --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/cache/api/CacheApiTest.java @@ -0,0 +1,157 @@ +package com.ourmenu.backend.domain.cache.api; + +import com.ourmenu.backend.domain.cache.domain.MenuPin; +import com.ourmenu.backend.domain.cache.dto.GetCacheInfoResponse; +import com.ourmenu.backend.domain.cache.dto.SimpleHomeImgResponse; +import com.ourmenu.backend.domain.cache.dto.SimpleMenuFolderIconResponse; +import com.ourmenu.backend.domain.cache.dto.SimpleMenuPinResponse; +import com.ourmenu.backend.domain.cache.dto.SimpleTagImgResponse; +import com.ourmenu.backend.domain.cache.util.UrlConverter; +import com.ourmenu.backend.global.TestConfig; +import com.ourmenu.backend.global.config.GlobalDataConfig; +import com.ourmenu.backend.global.data.GlobalUserTestData; +import com.ourmenu.backend.global.response.ApiResponse; +import java.util.List; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; + +@SpringBootTest +@Import({GlobalDataConfig.class, TestConfig.class}) +@DisplayName("캐시 통합 테스트") +public class CacheApiTest { + + @Autowired + CacheController cacheController; + + @Autowired + GlobalUserTestData userTestData; + + @Autowired + UrlConverter urlConvertor; + + RestTemplate restTemplate = new RestTemplate(); + + @Test + void 확인할_수_없는_이미지는_조회할_수_없다() { + //given + + //when + String menuPinMapUrl = urlConvertor.getMenuPinMapUrl(MenuPin.BBQ); + + //then + Assertions.assertThatThrownBy( + () -> restTemplate.getForEntity( + menuPinMapUrl + "trash", String.class)) + .isInstanceOf(HttpClientErrorException.class); + } + + @Test + void 메뉴판_캐시_이미지를_모두_조회할_수_있다() { + //given + ApiResponse response = cacheController.getCacheInfo(); + GetCacheInfoResponse getCacheInfoResponse = response.getResponse(); + + //when + List menuFolderIcons = getCacheInfoResponse.getMenuFolderIcons(); + + //then + menuFolderIcons.stream().forEach(simpleMenuFolderIconResponse -> { + String menuFolderIconUrl = simpleMenuFolderIconResponse.getMenuFolderIconUrl(); + ResponseEntity responseEntity = restTemplate.getForEntity(menuFolderIconUrl, String.class); + Assertions.assertThat(responseEntity.getStatusCode().is2xxSuccessful()).isTrue(); + Assertions.assertThat(responseEntity.getBody()).isNotEmpty(); + }); + } + + @Test + void 메뉴핀_캐시_이미지를_모두_조회할_수_있다() { + //given + ApiResponse response = cacheController.getCacheInfo(); + GetCacheInfoResponse getCacheInfoResponse = response.getResponse(); + + List menuPins = getCacheInfoResponse.getMenuPins(); + + //then + menuPins.stream().forEach(simpleMenuFolderIconResponse -> { + String menuPinAddImgUrl = simpleMenuFolderIconResponse.getMenuPinAddImgUrl(); + if (menuPinAddImgUrl == null) { + return; + } + ResponseEntity responseEntity = restTemplate.getForEntity(menuPinAddImgUrl, String.class); + Assertions.assertThat(responseEntity.getStatusCode().is2xxSuccessful()).isTrue(); + Assertions.assertThat(responseEntity.getBody()).isNotEmpty(); + }); + + menuPins.stream().forEach(simpleMenuFolderIconResponse -> { + String menuPinAddDisableImgUrl = simpleMenuFolderIconResponse.getMenuPinAddDisableImgUrl(); + if (menuPinAddDisableImgUrl == null) { + return; + } + ResponseEntity responseEntity = restTemplate.getForEntity(menuPinAddDisableImgUrl, String.class); + Assertions.assertThat(responseEntity.getStatusCode().is2xxSuccessful()).isTrue(); + Assertions.assertThat(responseEntity.getBody()).isNotEmpty(); + }); + + menuPins.stream().forEach(simpleMenuFolderIconResponse -> { + String menuPinMapImgUrl = simpleMenuFolderIconResponse.getMenuPinMapImgUrl(); + if (menuPinMapImgUrl == null) { + return; + } + + ResponseEntity responseEntity = restTemplate.getForEntity(menuPinMapImgUrl, String.class); + Assertions.assertThat(responseEntity.getStatusCode().is2xxSuccessful()).isTrue(); + Assertions.assertThat(responseEntity.getBody()).isNotEmpty(); + }); + + } + + @Test + void 홈이미지_캐시_이미지를_모두_조회할_수_있다() { + //given + ApiResponse response = cacheController.getCacheInfo(); + GetCacheInfoResponse getCacheInfoResponse = response.getResponse(); + + //when + List homeImgs = getCacheInfoResponse.getHomeImgs(); + + //then + homeImgs.stream().forEach(simpleMenuFolderIconResponse -> { + String homeImgUrl = simpleMenuFolderIconResponse.getHomeImgUrl(); + ResponseEntity responseEntity = restTemplate.getForEntity(homeImgUrl, String.class); + Assertions.assertThat(responseEntity.getStatusCode().is2xxSuccessful()).isTrue(); + Assertions.assertThat(responseEntity.getBody()).isNotEmpty(); + }); + } + + @Test + void 태그_캐시_이미지를_모두_조회할_수_있다() { + //given + ApiResponse response = cacheController.getCacheInfo(); + GetCacheInfoResponse getCacheInfoResponse = response.getResponse(); + + //when + List tags = getCacheInfoResponse.getTags(); + + //then + tags.stream().forEach(simpleMenuFolderIconResponse -> { + String orangeTagImgUrl = simpleMenuFolderIconResponse.getOrangeTagImgUrl(); + ResponseEntity responseEntity = restTemplate.getForEntity(orangeTagImgUrl, String.class); + Assertions.assertThat(responseEntity.getStatusCode().is2xxSuccessful()).isTrue(); + Assertions.assertThat(responseEntity.getBody()).isNotEmpty(); + }); + + tags.stream().forEach(simpleMenuFolderIconResponse -> { + String whiteTagImgUrl = simpleMenuFolderIconResponse.getWhiteTagImgUrl(); + ResponseEntity responseEntity = restTemplate.getForEntity(whiteTagImgUrl, String.class); + Assertions.assertThat(responseEntity.getStatusCode().is2xxSuccessful()).isTrue(); + Assertions.assertThat(responseEntity.getBody()).isNotEmpty(); + }); + } +} diff --git a/src/test/java/com/ourmenu/backend/domain/home/api/HomeApiTest.java b/src/test/java/com/ourmenu/backend/domain/home/api/HomeApiTest.java new file mode 100644 index 00000000..69ffbaa1 --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/home/api/HomeApiTest.java @@ -0,0 +1,112 @@ +package com.ourmenu.backend.domain.home.api; + +import com.ourmenu.backend.domain.cache.domain.HomeImg; +import com.ourmenu.backend.domain.cache.util.UrlConverter; +import com.ourmenu.backend.domain.home.config.HomeTestConfig; +import com.ourmenu.backend.domain.home.data.HomeTestData; +import com.ourmenu.backend.domain.home.domain.Answer; +import com.ourmenu.backend.domain.home.dto.GetHomeRecommendResponse; +import com.ourmenu.backend.domain.home.dto.SaveAndGetQuestionRequest; +import com.ourmenu.backend.domain.home.dto.SaveAnswerRequest; +import com.ourmenu.backend.domain.user.domain.CustomUserDetails; +import com.ourmenu.backend.global.DatabaseCleaner; +import com.ourmenu.backend.global.TestConfig; +import com.ourmenu.backend.global.config.GlobalDataConfig; +import com.ourmenu.backend.global.data.GlobalUserTestData; +import com.ourmenu.backend.global.response.ApiResponse; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; + +@SpringBootTest +@Import({GlobalDataConfig.class, TestConfig.class, HomeTestConfig.class}) +@DisplayName("홈 통합 테스트") +public class HomeApiTest { + + @Autowired + HomeController homeController; + + @Autowired + UrlConverter urlConverter; + + @Autowired + HomeTestData homeTestData; + + @Autowired + GlobalUserTestData userTestData; + + @Autowired + DatabaseCleaner databaseCleaner; + + CustomUserDetails testCustomUserDetails; + + @BeforeEach + void setUp() { + databaseCleaner.clear(); + testCustomUserDetails = userTestData.createTestEmailUserWithMealTime(); + } + + @Test + void 온보딩_질문을_갱신_또는_생성_할_수_있다() { + //given + + //when + ApiResponse response = homeController.saveAndGetQuestion( + testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isTrue(); + } + + @Test + void 온보딩_질문_답을_저장_할_수_있다() { + //given + homeTestData.createTestQuestion(testCustomUserDetails.getId()); + + //when + SaveAnswerRequest request = new SaveAnswerRequest(Answer.LIKE); + ApiResponse response = homeController.saveQuestionAnswer(request, testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isTrue(); + } + + @Test + void 올바르지_않는_온보딩_질문_답에_대해서_예외를_발생시킨다() { + //given + homeTestData.createTestQuestion(testCustomUserDetails.getId()); + + //when + SaveAnswerRequest request = new SaveAnswerRequest(Answer.SEA); + + //then + Assertions.assertThatThrownBy(() -> homeController.saveQuestionAnswer(request, testCustomUserDetails)) + .isInstanceOf(RuntimeException.class); + } + + @Test + void 온보딩_질문_응답에_대한_추천_메뉴를_구성한다() { + //given + homeTestData.createTestHomeMenu(testCustomUserDetails); + + //when + SaveAnswerRequest request = new SaveAnswerRequest(Answer.LIKE); + homeController.saveQuestionAnswer(request, testCustomUserDetails); + ApiResponse response = homeController.getHomeMenus(testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + Assertions.assertThat(response.getResponse().getAnswerRecommendMenus().size()).isEqualTo(2); + + Assertions.assertThat(response.getResponse().getAnswerImgUrl()).satisfiesAnyOf( + answerImgUrl -> Assertions.assertThat(answerImgUrl) + .isEqualTo(urlConverter.getHomeImgUrl(HomeImg.LIKE1)), + answerImgUrl -> Assertions.assertThat(answerImgUrl).isEqualTo(urlConverter.getHomeImgUrl(HomeImg.LIKE2)) + ); + } + +} diff --git a/src/test/java/com/ourmenu/backend/domain/home/application/HomeImgUrlTest.java b/src/test/java/com/ourmenu/backend/domain/home/application/HomeImgUrlTest.java new file mode 100644 index 00000000..15366402 --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/home/application/HomeImgUrlTest.java @@ -0,0 +1,57 @@ +package com.ourmenu.backend.domain.home.application; + +import com.ourmenu.backend.domain.cache.domain.HomeImg; +import com.ourmenu.backend.domain.cache.util.UrlConverter; +import com.ourmenu.backend.domain.tag.domain.Tag; +import java.util.Arrays; +import java.util.List; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +@SpringBootTest +@DisplayName("홈 이미지 URL 통합 테스트") +public class HomeImgUrlTest { + + @Autowired + UrlConverter urlConverter; + + RestTemplate restTemplate = new RestTemplate(); + + @Test + void 홈_이미지를_모두_조회_할_수_있다() { + //given + List homeImgs = Arrays.stream(HomeImg.values()).toList(); + + //when + + //then + homeImgs.stream().forEach(homeImg -> { + String homeImgUrl = urlConverter.getHomeImgUrl(homeImg); + ResponseEntity responseEntity = restTemplate.getForEntity(homeImgUrl, String.class); + Assertions.assertThat(responseEntity.getStatusCode().is2xxSuccessful()).isTrue(); + Assertions.assertThat(responseEntity.getBody()).isNotEmpty(); + }); + } + + @Test + void 홈_추천문구_이미지를_모두_조회_할_수_있다() { + //given + List tags = Arrays.stream(Tag.values()).toList(); + + //when + + //then + tags.stream().forEach(tag -> { + String homeRecommendTagImgUrl = urlConverter.getHomeRecommendTagImgUrl(tag); + ResponseEntity responseEntity = restTemplate.getForEntity(homeRecommendTagImgUrl, String.class); + Assertions.assertThat(responseEntity.getStatusCode().is2xxSuccessful()).isTrue(); + Assertions.assertThat(responseEntity.getBody()).isNotEmpty(); + }); + + } +} diff --git a/src/test/java/com/ourmenu/backend/domain/home/config/HomeTestConfig.java b/src/test/java/com/ourmenu/backend/domain/home/config/HomeTestConfig.java new file mode 100644 index 00000000..afe233b4 --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/home/config/HomeTestConfig.java @@ -0,0 +1,19 @@ +package com.ourmenu.backend.domain.home.config; + +import com.ourmenu.backend.domain.home.data.HomeTestData; +import jakarta.persistence.EntityManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; + +@TestConfiguration +public class HomeTestConfig { + + @Autowired + EntityManager entityManager; + + @Bean + public HomeTestData homeTestData() { + return new HomeTestData(entityManager); + } +} diff --git a/src/test/java/com/ourmenu/backend/domain/home/data/HomeTestData.java b/src/test/java/com/ourmenu/backend/domain/home/data/HomeTestData.java new file mode 100644 index 00000000..d3c13b06 --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/home/data/HomeTestData.java @@ -0,0 +1,103 @@ +package com.ourmenu.backend.domain.home.data; + +import com.ourmenu.backend.domain.cache.domain.MenuPin; +import com.ourmenu.backend.domain.home.domain.HomeQuestionAnswer; +import com.ourmenu.backend.domain.home.domain.Question; +import com.ourmenu.backend.domain.menu.domain.Menu; +import com.ourmenu.backend.domain.store.domain.Map; +import com.ourmenu.backend.domain.store.domain.Store; +import com.ourmenu.backend.domain.tag.domain.MenuTag; +import com.ourmenu.backend.domain.tag.domain.Tag; +import com.ourmenu.backend.domain.user.domain.CustomUserDetails; +import jakarta.persistence.EntityManager; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Point; +import org.locationtech.jts.geom.PrecisionModel; +import org.springframework.transaction.annotation.Transactional; + +public class HomeTestData { + + EntityManager entityManager; + + public HomeTestData(EntityManager entityManager) { + this.entityManager = entityManager; + } + + @Transactional + public HomeQuestionAnswer createTestQuestion(Long userId) { + HomeQuestionAnswer homeQuestionAnswer = HomeQuestionAnswer.builder() + .question(Question.FEEL) + .userId(userId) + .build(); + entityManager.persist(homeQuestionAnswer); + return homeQuestionAnswer; + } + + /** + * 홈 화면에 필요한 테스트 데이터를 저장한다 + * + * @param customUserDetails + */ + @Transactional + public void createTestHomeMenu(CustomUserDetails customUserDetails) { + int srid = 4326; + GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), srid); + + Coordinate coordinate = new Coordinate(127.085, 37.538); + Point location = geometryFactory.createPoint(coordinate); + + Map map = Map.builder() + .location(location) + .build(); + entityManager.persist(map); + + Store store = Store.builder() + .title("테스트 식당1") + .address("광진구 어딘가") + .map(map) + .build(); + entityManager.persist(store); + + createTestMenu("테스트 메뉴1 비비큐", MenuPin.BBQ, Tag.PROMISE, store, customUserDetails); + createTestMenu("테스트 메뉴2 빵", MenuPin.BREAD, Tag.PROMISE, store, customUserDetails); + + HomeQuestionAnswer homeQuestionAnswer = HomeQuestionAnswer.builder() + .question(Question.FEEL) + .userId(customUserDetails.getId()) + .build(); + entityManager.persist(homeQuestionAnswer); + } + + /** + * 메뉴와 관련된 엔티티를 모두 저장 + * + * @param title + * @param menuPin + * @param tag + * @param store + * @param customUserDetails + */ + private void createTestMenu(String title, MenuPin menuPin, Tag tag, Store store, + CustomUserDetails customUserDetails) { + Menu menu = Menu.builder() + .title(title) + .price(1000) + .pin(MenuPin.BBQ) + .memoTitle("테스트 메뉴1 메모 제목") + .memoContent("테스트 메뉴1 메모 내용") + .store(store) + .isCrawled(Boolean.FALSE) + .userId(customUserDetails.getId()) + .build(); + + entityManager.persist(menu); + + MenuTag menuTag = MenuTag.builder() + .menuId(menu.getId()) + .tag(tag) + .build(); + + entityManager.persist(menuTag); + } +} diff --git a/src/test/java/com/ourmenu/backend/domain/menu/api/MenuApiTest.java b/src/test/java/com/ourmenu/backend/domain/menu/api/MenuApiTest.java new file mode 100644 index 00000000..e893d6aa --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/menu/api/MenuApiTest.java @@ -0,0 +1,122 @@ +package com.ourmenu.backend.domain.menu.api; + +import com.ourmenu.backend.domain.cache.domain.MenuPin; +import com.ourmenu.backend.domain.cache.util.UrlConverter; +import com.ourmenu.backend.domain.menu.config.MenuTestConfig; +import com.ourmenu.backend.domain.menu.data.MenuTestData; +import com.ourmenu.backend.domain.menu.domain.Menu; +import com.ourmenu.backend.domain.menu.domain.MenuFolder; +import com.ourmenu.backend.domain.menu.domain.SortOrder; +import com.ourmenu.backend.domain.menu.dto.GetMenuFolderMenuResponse; +import com.ourmenu.backend.domain.menu.dto.GetSimpleMenuResponse; +import com.ourmenu.backend.domain.menu.dto.SaveMenuRequest; +import com.ourmenu.backend.domain.menu.dto.SaveMenuResponse; +import com.ourmenu.backend.domain.menu.exception.NotFoundMenuException; +import com.ourmenu.backend.domain.user.domain.CustomUserDetails; +import com.ourmenu.backend.global.DatabaseCleaner; +import com.ourmenu.backend.global.TestConfig; +import com.ourmenu.backend.global.config.GlobalDataConfig; +import com.ourmenu.backend.global.data.GlobalUserTestData; +import com.ourmenu.backend.global.response.ApiResponse; +import java.util.List; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; + +@SpringBootTest +@Import({GlobalDataConfig.class, TestConfig.class, MenuTestConfig.class}) +@DisplayName("메뉴 통합 테스트") +public class MenuApiTest { + + @Autowired + MenuController menuController; + + @Autowired + UrlConverter urlConverter; + + @Autowired + GlobalUserTestData userTestData; + + @Autowired + MenuTestData menuTestData; + + @Autowired + DatabaseCleaner databaseCleaner; + + CustomUserDetails testCustomUserDetails; + + @BeforeEach + void setUp() { + databaseCleaner.clear(); + testCustomUserDetails = userTestData.createTestEmailUser(); + } + + @Test + void 메뉴판_정보_및_메뉴판에_속한_메뉴들을_조회_할_수_있다() { + //given + MenuFolder testMenuFolder = menuTestData.createMenuFolderWithMenu(testCustomUserDetails); + + //when + ApiResponse response = menuController.getMenuFolderMenus( + testMenuFolder.getId(), SortOrder.TITLE_ASC, testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isTrue(); + Assertions.assertThat(response.getResponse().getMenuFolderTitle()).isEqualTo(testMenuFolder.getTitle()); + Assertions.assertThat(response.getResponse().getMenus().size()).isEqualTo(3); + + Assertions.assertThat(response.getResponse().getMenuFolderIconImgUrl()) + .isEqualTo(urlConverter.getMenuFolderImgUrl(testMenuFolder.getIcon())); + } + + @Test + void 메뉴를_등록_할_수_있다() { + //given + String menuMemoTitle = "비비큐"; + SaveMenuRequest request = new SaveMenuRequest(null, "테스트 메뉴", 1000, MenuPin.BBQ, menuMemoTitle, + "맛있다", null, "31060661", true, null); + + //when + ApiResponse response = menuController.saveMenu(request, + testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isTrue(); + Assertions.assertThat(response.getResponse().getMenuMemoTitle()).isEqualTo(menuMemoTitle); + + Assertions.assertThat(response.getResponse().getMenuPinImgUrl()) + .isEqualTo(urlConverter.getMenuPinAddUrl(MenuPin.BBQ)); + } + + @Test + void 메뉴를_전체_조회_할_수_있다() { + //given + List preStoredMenus = menuTestData.createTestMenusWithStore(testCustomUserDetails); + + //when + ApiResponse> response = menuController.getMenus(null, null, null, 0, 10, + SortOrder.CREATED_AT_DESC, testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isTrue(); + Assertions.assertThat(response.getResponse().size()).isEqualTo(preStoredMenus.size()); + } + + @Test + void 메뉴를_삭제할_수_있다() { + //given + Menu testMenu = menuTestData.createTestMenu(testCustomUserDetails); + + //when + ApiResponse response = menuController.deleteMenu(testMenu.getId(), testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isTrue(); + Assertions.assertThatThrownBy(() -> menuController.getMenu(testMenu.getId(), testCustomUserDetails)) + .isInstanceOf(NotFoundMenuException.class); + } +} diff --git a/src/test/java/com/ourmenu/backend/domain/menu/api/MenuFolderApiTest.java b/src/test/java/com/ourmenu/backend/domain/menu/api/MenuFolderApiTest.java new file mode 100644 index 00000000..db16f95c --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/menu/api/MenuFolderApiTest.java @@ -0,0 +1,201 @@ +package com.ourmenu.backend.domain.menu.api; + +import com.ourmenu.backend.domain.cache.domain.MenuFolderIcon; +import com.ourmenu.backend.domain.cache.util.UrlConverter; +import com.ourmenu.backend.domain.menu.config.MenuTestConfig; +import com.ourmenu.backend.domain.menu.data.MenuTestData; +import com.ourmenu.backend.domain.menu.domain.MenuFolder; +import com.ourmenu.backend.domain.menu.dto.GetMenuFolderResponse; +import com.ourmenu.backend.domain.menu.dto.SaveMenuFolderRequest; +import com.ourmenu.backend.domain.menu.dto.SaveMenuFolderResponse; +import com.ourmenu.backend.domain.menu.dto.UpdateMenuFolderIndexRequest; +import com.ourmenu.backend.domain.menu.dto.UpdateMenuFolderRequest; +import com.ourmenu.backend.domain.menu.dto.UpdateMenuFolderResponse; +import com.ourmenu.backend.domain.user.domain.CustomUserDetails; +import com.ourmenu.backend.global.DatabaseCleaner; +import com.ourmenu.backend.global.TestConfig; +import com.ourmenu.backend.global.data.GlobalUserTestData; +import com.ourmenu.backend.global.response.ApiResponse; +import java.util.Collections; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; + +@SpringBootTest +@Import({GlobalUserTestData.class, TestConfig.class, MenuTestConfig.class}) +@DisplayName("메뉴 폴더 통합 테스트") +public class MenuFolderApiTest { + + @Autowired + MenuFolderController menuFolderController; + + @Autowired + UrlConverter urlConverter; + + @Autowired + GlobalUserTestData userTestData; + + @Autowired + MenuTestData menuTestData; + + @Autowired + DatabaseCleaner databaseCleaner; + + @BeforeEach + void setUp() { + databaseCleaner.clear(); + } + + @Test + void 테스트_유저를_생성_할_수_있다() { + //given + + //when + CustomUserDetails testCustomUserDetails = userTestData.createTestEmailUser(); + + //then + Assertions.assertThat(testCustomUserDetails.getId()).isEqualTo(1L); + } + + @Test + void 메뉴판을_저장_할_수_있다() { + //given + String menuFolderTitle = "메뉴판 제목"; + SaveMenuFolderRequest saveMenuFolderRequest = new SaveMenuFolderRequest(null, menuFolderTitle, + MenuFolderIcon.ANGRY, + Collections.emptyList()); + CustomUserDetails testCustomUserDetails = userTestData.createTestEmailUser(); + + //when + ApiResponse response = menuFolderController.saveMenuFolder( + saveMenuFolderRequest, testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + Assertions.assertThat(response.getResponse().getMenuFolderTitle()).isEqualTo(menuFolderTitle); + } + + @Test + void 메뉴판_저장시_시간순으로_순서가_정해진다() { + //given + CustomUserDetails testCustomUserDetails = userTestData.createTestEmailUser(); + MenuFolder testMenuFolder = menuTestData.createTestMenuFolder(testCustomUserDetails); + + String menuFolderTitle = "새로운 메뉴판 제목"; + SaveMenuFolderRequest saveMenuFolderRequest = new SaveMenuFolderRequest(null, menuFolderTitle, + MenuFolderIcon.ANGRY, + Collections.emptyList()); + ApiResponse saveMenuFolderResponseApiResponse = menuFolderController.saveMenuFolder( + saveMenuFolderRequest, testCustomUserDetails); + + //when + ApiResponse response = menuFolderController.getMenuFolder(testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + Assertions.assertThat(response.getResponse().getMenuFolders().get(0).getIndex()) + .isEqualTo(saveMenuFolderResponseApiResponse.getResponse().getIndex()); + Assertions.assertThat(response.getResponse().getMenuFolders().get(1).getIndex()) + .isEqualTo(testMenuFolder.getIndex()); + } + + @Test + void 메뉴판들을_조회_할_수_있다() { + //given + CustomUserDetails testCustomUserDetails = userTestData.createTestEmailUser(); + MenuFolder testMenuFolder = menuTestData.createTestMenuFolder(testCustomUserDetails); + + //when + ApiResponse response = menuFolderController.getMenuFolder(testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + Assertions.assertThat(response.getResponse().getMenuFolders().size()).isEqualTo(1); + Assertions.assertThat(response.getResponse().getMenuFolders().get(0).getMenuFolderTitle()) + .isEqualTo(testMenuFolder.getTitle()); + } + + @Test + void 메뉴판들을_조회시_유저_메뉴_전체_개수_를_확인_할_수_있다() { + //given + CustomUserDetails testCustomUserDetails = userTestData.createTestEmailUser(); + MenuFolder testMenuFolder = menuTestData.createTestMenuFolder(testCustomUserDetails); + menuTestData.createTestMenu(testCustomUserDetails); + + //when + ApiResponse response = menuFolderController.getMenuFolder(testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + Assertions.assertThat(response.getResponse().getMenuFolders().size()).isEqualTo(1); + Assertions.assertThat(response.getResponse().getMenuCount()).isEqualTo(1); + Assertions.assertThat(response.getResponse().getMenuFolders().get(0).getMenuFolderTitle()) + .isEqualTo(testMenuFolder.getTitle()); + } + + @Test + void 메뉴_폴더를_변경_할_수_있다() { + //given + CustomUserDetails testCustomUserDetails = userTestData.createTestEmailUser(); + MenuFolder testMenuFolder = menuTestData.createTestMenuFolder(testCustomUserDetails); + + String modifiedMenuFolderName = "수정된 메뉴폴더 이름"; + UpdateMenuFolderRequest updateMenuFolderRequest = new UpdateMenuFolderRequest(null, false, + modifiedMenuFolderName, null, null); + + //when + ApiResponse updateMenuFolderResponseApiResponse = menuFolderController.updateMenuFolder( + testMenuFolder.getId(), updateMenuFolderRequest, testCustomUserDetails); + + //then + Assertions.assertThat(updateMenuFolderResponseApiResponse.isSuccess()).isEqualTo(true); + Assertions.assertThat(updateMenuFolderResponseApiResponse.getResponse().getMenuFolderTitle()) + .isEqualTo(modifiedMenuFolderName); + + Assertions.assertThat(updateMenuFolderResponseApiResponse.getResponse().getMenuFolderIconImgUrl()) + .isEqualTo(urlConverter.getMenuFolderImgUrl(testMenuFolder.getIcon())); + } + + @Test + void 메뉴_폴더_순서를_변경_할_수_있다() { + //given + CustomUserDetails testCustomUserDetails = userTestData.createTestEmailUser(); + menuTestData.createTestMenuFolders(testCustomUserDetails); + + //when + ApiResponse preResponse = menuFolderController.getMenuFolder( + testCustomUserDetails); + UpdateMenuFolderIndexRequest updateMenuFolderIndexRequest = new UpdateMenuFolderIndexRequest(3); + ApiResponse updateMenuFolderResponseApiResponse = menuFolderController.updateMenuFolderIndex( + 1L, updateMenuFolderIndexRequest, testCustomUserDetails); + ApiResponse response = menuFolderController.getMenuFolder(testCustomUserDetails); + + //then + Assertions.assertThat(updateMenuFolderResponseApiResponse.isSuccess()).isEqualTo(true); + Assertions.assertThat(preResponse.getResponse().getMenuFolders().get(0).getMenuFolderTitle()) + .isEqualTo(response.getResponse().getMenuFolders().get(1).getMenuFolderTitle()); + Assertions.assertThat(preResponse.getResponse().getMenuFolders().get(1).getMenuFolderTitle()) + .isEqualTo(response.getResponse().getMenuFolders().get(2).getMenuFolderTitle()); + Assertions.assertThat(preResponse.getResponse().getMenuFolders().get(2).getMenuFolderTitle()) + .isEqualTo(response.getResponse().getMenuFolders().get(0).getMenuFolderTitle()); + } + + @Test + void 메뉴_폴더를_삭제_할_수_있다() { + //given + CustomUserDetails testCustomUserDetails = userTestData.createTestEmailUser(); + MenuFolder testMenuFolder = menuTestData.createTestMenuFolder(testCustomUserDetails); + + //when + menuFolderController.deleteMenuFolder(testMenuFolder.getId(), testCustomUserDetails); + ApiResponse response = menuFolderController.getMenuFolder(testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + Assertions.assertThat(response.getResponse().getMenuFolders().size()).isEqualTo(0); + } +} diff --git a/src/test/java/com/ourmenu/backend/domain/menu/config/MenuTestConfig.java b/src/test/java/com/ourmenu/backend/domain/menu/config/MenuTestConfig.java new file mode 100644 index 00000000..64647fc3 --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/menu/config/MenuTestConfig.java @@ -0,0 +1,25 @@ +package com.ourmenu.backend.domain.menu.config; + +import com.ourmenu.backend.domain.menu.data.MenuTestData; +import com.ourmenu.backend.domain.menu.data.StoreTestData; +import jakarta.persistence.EntityManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; + +@TestConfiguration +public class MenuTestConfig { + + @Autowired + EntityManager entityManager; + + @Bean + public MenuTestData menuTestData() { + return new MenuTestData(entityManager, storeTestData()); + } + + @Bean + public StoreTestData storeTestData() { + return new StoreTestData(entityManager); + } +} diff --git a/src/test/java/com/ourmenu/backend/domain/menu/data/MenuTestData.java b/src/test/java/com/ourmenu/backend/domain/menu/data/MenuTestData.java new file mode 100644 index 00000000..2492818c --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/menu/data/MenuTestData.java @@ -0,0 +1,146 @@ +package com.ourmenu.backend.domain.menu.data; + +import com.ourmenu.backend.domain.cache.domain.MenuFolderIcon; +import com.ourmenu.backend.domain.cache.domain.MenuPin; +import com.ourmenu.backend.domain.menu.domain.Menu; +import com.ourmenu.backend.domain.menu.domain.MenuFolder; +import com.ourmenu.backend.domain.menu.domain.MenuMenuFolder; +import com.ourmenu.backend.domain.store.domain.Store; +import com.ourmenu.backend.domain.user.domain.CustomUserDetails; +import jakarta.persistence.EntityManager; +import java.util.List; +import org.springframework.transaction.annotation.Transactional; + +public class MenuTestData { + + private EntityManager entityManager; + private StoreTestData storeTestData; + + public MenuTestData(EntityManager entityManager, StoreTestData storeTestData) { + this.entityManager = entityManager; + this.storeTestData = storeTestData; + } + + @Transactional + public MenuFolder createTestMenuFolder(CustomUserDetails customUserDetails) { + MenuFolder menuFolder = MenuFolder.builder() + .title("테스트 메뉴 폴더") + .imgUrl(null) + .icon(MenuFolderIcon.ANGRY) + .index(1) + .userId(customUserDetails.getId()) + .build(); + entityManager.persist(menuFolder); + return menuFolder; + } + + @Transactional + public List createTestMenuFolders(CustomUserDetails customUserDetails) { + MenuFolder menuFolder1 = MenuFolder.builder() + .title("테스트 메뉴 폴더1") + .imgUrl(null) + .icon(MenuFolderIcon.ANGRY) + .index(1) + .userId(customUserDetails.getId()) + .build(); + MenuFolder menuFolder2 = MenuFolder.builder() + .title("테스트 메뉴 폴더2") + .imgUrl(null) + .icon(MenuFolderIcon.BAEKSUK) + .index(2) + .userId(customUserDetails.getId()) + .build(); + MenuFolder menuFolder3 = MenuFolder.builder() + .title("테스트 메뉴 폴더3") + .imgUrl(null) + .icon(MenuFolderIcon.BASKET) + .index(3) + .userId(customUserDetails.getId()) + .build(); + entityManager.persist(menuFolder1); + entityManager.persist(menuFolder2); + entityManager.persist(menuFolder3); + return List.of(menuFolder1, menuFolder2, menuFolder3); + } + + @Transactional + public Menu createTestMenu(CustomUserDetails customUserDetails) { + Store store = storeTestData.createTestStore(); + + Menu menu = Menu.builder() + .title("테스트 메뉴 비비큐") + .price(1000) + .pin(MenuPin.BBQ) + .memoTitle("테스트 메뉴 메모 제목") + .memoContent("테스트 메뉴 메모 내용") + .store(store) + .isCrawled(Boolean.FALSE) + .userId(customUserDetails.getId()) + .build(); + + entityManager.persist(menu); + return menu; + } + + @Transactional + public List createTestMenusWithStore(CustomUserDetails customUserDetails) { + Store store = storeTestData.createTestStore(); + + Menu menu1 = Menu.builder() + .title("테스트 메뉴1 비비큐") + .price(1000) + .pin(MenuPin.BBQ) + .memoTitle("테스트 메뉴1 메모 제목") + .memoContent("테스트 메뉴1 메모 내용") + .store(store) + .isCrawled(Boolean.FALSE) + .userId(customUserDetails.getId()) + .build(); + + Menu menu2 = Menu.builder() + .title("테스트 메뉴2 빵") + .price(2000) + .pin(MenuPin.BREAD) + .memoTitle("테스트 메뉴2 메모 제목") + .memoContent("테스트 메뉴2 메모 내용") + .store(store) + .isCrawled(Boolean.FALSE) + .userId(customUserDetails.getId()) + .build(); + + Menu menu3 = Menu.builder() + .title("테스트 메뉴3 케익") + .price(3000) + .pin(MenuPin.CAKE) + .memoTitle("테스트 메뉴3 메모 제목") + .memoContent("테스트 메뉴3 메모 내용") + .store(store) + .isCrawled(Boolean.FALSE) + .userId(customUserDetails.getId()) + .build(); + + entityManager.persist(menu1); + entityManager.persist(menu2); + entityManager.persist(menu3); + return List.of(menu1, menu2, menu3); + } + + /** + * 메뉴판 생성 및 메뉴들과 연결합니다. + * + * @param customUserDetails + * @return + */ + @Transactional + public MenuFolder createMenuFolderWithMenu(CustomUserDetails customUserDetails) { + MenuFolder menuFolder = createTestMenuFolder(customUserDetails); + List menus = createTestMenusWithStore(customUserDetails); + menus.stream() + .map(menu -> MenuMenuFolder.builder() + .menu(menu) + .folderId(menuFolder.getId()) + .build()) + .forEach(entityManager::persist); + return menuFolder; + } +} diff --git a/src/test/java/com/ourmenu/backend/domain/menu/data/StoreTestData.java b/src/test/java/com/ourmenu/backend/domain/menu/data/StoreTestData.java new file mode 100644 index 00000000..0824ee7b --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/menu/data/StoreTestData.java @@ -0,0 +1,39 @@ +package com.ourmenu.backend.domain.menu.data; + +import com.ourmenu.backend.domain.store.domain.Map; +import com.ourmenu.backend.domain.store.domain.Store; +import jakarta.persistence.EntityManager; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Point; +import org.locationtech.jts.geom.PrecisionModel; + +public class StoreTestData { + + private EntityManager entityManager; + + public StoreTestData(EntityManager entityManager) { + this.entityManager = entityManager; + } + + public Store createTestStore() { + int srid = 4326; + GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), srid); + + Coordinate coordinate = new Coordinate(127.085, 37.538); + Point location = geometryFactory.createPoint(coordinate); + + Map map = Map.builder() + .location(location) + .build(); + entityManager.persist(map); + + Store store = Store.builder() + .title("테스트 식당1") + .address("광진구 어딘가") + .map(map) + .build(); + entityManager.persist(store); + return store; + } +} diff --git a/src/test/java/com/ourmenu/backend/domain/search/api/SearchApiTest.java b/src/test/java/com/ourmenu/backend/domain/search/api/SearchApiTest.java new file mode 100644 index 00000000..ab984e7c --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/search/api/SearchApiTest.java @@ -0,0 +1,94 @@ +package com.ourmenu.backend.domain.search.api; + +import com.ourmenu.backend.domain.menu.config.MenuTestConfig; +import com.ourmenu.backend.domain.search.dto.GetSearchHistoryResponse; +import com.ourmenu.backend.domain.search.dto.GetStoreResponse; +import com.ourmenu.backend.domain.search.dto.SearchStoreResponse; +import com.ourmenu.backend.domain.user.domain.CustomUserDetails; +import com.ourmenu.backend.global.DatabaseCleaner; +import com.ourmenu.backend.global.TestConfig; +import com.ourmenu.backend.global.config.GlobalDataConfig; +import com.ourmenu.backend.global.data.GlobalUserTestData; +import com.ourmenu.backend.global.response.ApiResponse; +import java.util.List; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; + +@SpringBootTest +@Import({GlobalDataConfig.class, TestConfig.class, MenuTestConfig.class}) +@DisplayName("검색 통합 테스트") +public class SearchApiTest { + + @Autowired + SearchController searchController; + + @Autowired + GlobalUserTestData userTestData; + + @Autowired + DatabaseCleaner databaseCleaner; + + CustomUserDetails testCustomUserDetails; + + @BeforeEach + void setUp() { + databaseCleaner.clear(); + testCustomUserDetails = userTestData.createTestEmailUser(); + } + + @Test + void 식당을_최대_5개_검색_할_수_있디() { + //given + String searchWord = "고기"; + + //when + ApiResponse> response = searchController.searchStore(searchWord, 127.0759204, + 37.5423265); + + //then + Assertions.assertThat(response.isSuccess()).isTrue(); + Assertions.assertThat(response.getResponse().size()).isBetween(1, 5); + } + + @Test + void 검색한_식당을_상세조회_할_수_있다() { + //given + String searchWord = "고기"; + String storeId = getStoreIds(searchWord).stream().findFirst().orElseThrow(() -> new RuntimeException("테스트 실패")); + + //when + ApiResponse response = searchController.getStore(true, storeId, testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isTrue(); + } + + @Test + void 검색_기록을_조회_할_수_있다() { + //given + String searchWord = "고기"; + String storeId = getStoreIds(searchWord).stream().findFirst().orElseThrow(() -> new RuntimeException("테스트 실패")); + searchController.getStore(true, storeId, testCustomUserDetails); + + //when + ApiResponse> response = searchController.getSearchHistory( + testCustomUserDetails); + + //then + Assertions.assertThat(response.isSuccess()).isTrue(); + Assertions.assertThat(response.getResponse().size()).isEqualTo(1); + } + + private List getStoreIds(String query) { + ApiResponse> response = searchController.searchStore(query, 127.0759204, + 37.5423265); + return response.getResponse().stream() + .map(SearchStoreResponse::getStoreId) + .toList(); + } +} diff --git a/src/test/java/com/ourmenu/backend/domain/user/api/EmailApiTest.java b/src/test/java/com/ourmenu/backend/domain/user/api/EmailApiTest.java new file mode 100644 index 00000000..37ef154f --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/user/api/EmailApiTest.java @@ -0,0 +1,90 @@ +package com.ourmenu.backend.domain.user.api; + +import com.ourmenu.backend.domain.user.domain.CustomUserDetails; +import com.ourmenu.backend.domain.user.dto.request.PostEmailRequest; +import com.ourmenu.backend.domain.user.dto.request.SignInRequest; +import com.ourmenu.backend.domain.user.dto.request.VerifyEmailRequest; +import com.ourmenu.backend.domain.user.dto.response.EmailResponse; +import com.ourmenu.backend.domain.user.dto.response.TemporaryPasswordResponse; +import com.ourmenu.backend.global.DatabaseCleaner; +import com.ourmenu.backend.global.TestConfig; +import com.ourmenu.backend.global.config.GlobalDataConfig; +import com.ourmenu.backend.global.data.GlobalUserTestData; +import com.ourmenu.backend.global.response.ApiResponse; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.security.crypto.password.PasswordEncoder; + +@SpringBootTest +@Import({GlobalDataConfig.class, TestConfig.class}) +@DisplayName("이메일 통합 테스트") +public class EmailApiTest { + + @Autowired + EmailController emailController; + + @Autowired + DatabaseCleaner databaseCleaner; + + @Autowired + UserController userController; + + @Autowired + GlobalUserTestData userTestData; + + @Autowired + PasswordEncoder passwordEncoder; + + @BeforeEach + void setUp() { + databaseCleaner.clear(); + } + + @Test + public void 이메일_인증을_요청할_수_있다() { + //given + PostEmailRequest request = new PostEmailRequest("test123@naver.com"); + + //when + ApiResponse response = emailController.sendConfirmCode(request); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + } + + @Test + public void 이메일_인증_코드를_검증한다() { + //given + PostEmailRequest emailRequest = new PostEmailRequest("test123@naver.com"); + ApiResponse emailResponse = emailController.sendConfirmCode(emailRequest); + VerifyEmailRequest request = new VerifyEmailRequest("test123@naver.com", + emailResponse.getResponse().getCode()); + + //when + ApiResponse response = emailController.verifyEmail(request); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + } + + @Test + public void 임시_비밀번호를_발급받을_수_있다() { + //given + CustomUserDetails testEmailUser = userTestData.createTestEmailUser(); + PostEmailRequest request = new PostEmailRequest("testEmailUser@naver.com"); + + //when + ApiResponse response = emailController.sendTemporaryPassword(request); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + Assertions.assertThatCode(() -> userController.signIn + (new SignInRequest(testEmailUser.getEmail(), response.getResponse().getTemporaryPassword(), "EMAIL"))) + .doesNotThrowAnyException(); + } +} diff --git a/src/test/java/com/ourmenu/backend/domain/user/api/UserApiTest.java b/src/test/java/com/ourmenu/backend/domain/user/api/UserApiTest.java new file mode 100644 index 00000000..fe3eaed4 --- /dev/null +++ b/src/test/java/com/ourmenu/backend/domain/user/api/UserApiTest.java @@ -0,0 +1,212 @@ +package com.ourmenu.backend.domain.user.api; + +import com.ourmenu.backend.domain.user.domain.CustomUserDetails; +import com.ourmenu.backend.domain.user.domain.MealTime; +import com.ourmenu.backend.domain.user.dto.request.PostEmailRequest; +import com.ourmenu.backend.domain.user.dto.request.SignInRequest; +import com.ourmenu.backend.domain.user.dto.request.SignUpRequest; +import com.ourmenu.backend.domain.user.dto.request.UpdateMealTimeRequest; +import com.ourmenu.backend.domain.user.dto.request.UpdatePasswordRequest; +import com.ourmenu.backend.domain.user.dto.response.KakaoExistenceResponse; +import com.ourmenu.backend.domain.user.dto.response.ReissueRequest; +import com.ourmenu.backend.domain.user.dto.response.TokenDto; +import com.ourmenu.backend.domain.user.dto.response.UserDto; +import com.ourmenu.backend.domain.user.exception.NotFoundUserException; +import com.ourmenu.backend.domain.user.exception.NotMatchTokenException; +import com.ourmenu.backend.global.DatabaseCleaner; +import com.ourmenu.backend.global.TestConfig; +import com.ourmenu.backend.global.config.GlobalDataConfig; +import com.ourmenu.backend.global.data.GlobalUserTestData; +import com.ourmenu.backend.global.response.ApiResponse; +import com.ourmenu.backend.global.util.JwtTokenProvider; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.mock.web.MockHttpServletRequest; + +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; + +@SpringBootTest +@Import({GlobalDataConfig.class, TestConfig.class}) +@DisplayName("유저 통합 테스트") +public class UserApiTest { + + @Autowired + UserController userController; + + @Autowired + GlobalUserTestData userTestData; + + @Autowired + DatabaseCleaner databaseCleaner; + + @Autowired + JwtTokenProvider jwtTokenProvider; + + @BeforeEach + void setUp() { + databaseCleaner.clear(); + } + + @Test + public void 회원_가입을_통해_유저를_생성할_수_있다() { + //given + List mealTime = new ArrayList<>(); + mealTime.add(LocalTime.of(12, 0)); + mealTime.add(LocalTime.of(16, 0)); + SignUpRequest signUpRequest = new SignUpRequest("test123@gmail.com", + "password123", + mealTime, + "EMAIL"); + + //when + ApiResponse response = userController.signUp(signUpRequest); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + } + + @Test + public void 로그인을_할_수_있다() { + //given + CustomUserDetails testEmailUser = userTestData.createTestEmailUser(); + SignInRequest request = new SignInRequest( + "testEmailUser@naver.com", + "password1!", + "EMAIL" + ); + + //when + ApiResponse signInResponse = userController.signIn(request); + + //then + Assertions.assertThat(signInResponse.isSuccess()).isEqualTo(true); + } + + @Test + public void 카카오_계정을_검증할_수_있다() { + //given + CustomUserDetails testKakaoUser = userTestData.createTestKakaoUser(); + PostEmailRequest request = new PostEmailRequest("testKakaoUser@naver.com"); + + //when + ApiResponse response = userController.checkKakaoUserExists(request); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + } + + @Test + public void 식사시간_정보를_변경할_수_있다() { + //given + CustomUserDetails testEmailUserWithMealTime = userTestData.createTestEmailUserWithMealTime(); + List changeMealTime = new ArrayList<>(); + changeMealTime.add(LocalTime.of(12,0)); + changeMealTime.add(LocalTime.of(16,0)); + UpdateMealTimeRequest request = new UpdateMealTimeRequest(changeMealTime); + + //when + ApiResponse response = userController.changeMealTime(request, testEmailUserWithMealTime); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + } + + @Test + public void 비밀번호를_변경할_수_있다() { + //given + CustomUserDetails testEmailUser = userTestData.createTestEmailUser(); + UpdatePasswordRequest request = new UpdatePasswordRequest( + "password1!", + "password2@" + ); + + //when + ApiResponse response = userController.changePassword(request, testEmailUser); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + } + + @Test + public void 로그아웃_할_수_있다() { + //given + CustomUserDetails testEmailUser = userTestData.createTestEmailUser(); + SignInRequest request = new SignInRequest( + "testEmailUser@naver.com", + "password1!", + "EMAIL" + ); + MockHttpServletRequest httpServletRequest = new MockHttpServletRequest(); + ApiResponse signInResponse = userController.signIn(request); + httpServletRequest.addHeader("Authorization", + "Bearer " + signInResponse.getResponse().getRefreshToken()); + + //when + ApiResponse response = userController.signOut(httpServletRequest, testEmailUser); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + Assertions.assertThatThrownBy(() -> userController.reissueToken + (new ReissueRequest(signInResponse.getResponse().getRefreshToken()))) + .isInstanceOf(NotMatchTokenException.class); + } + + @Test + public void 본인의_유저_정보를_조회할_수_있다() { + //given + CustomUserDetails testEmailUser = userTestData.createTestEmailUserWithMealTime(); + MealTime mealTime = MealTime.builder() + .userId(testEmailUser.getId()) + .mealTime(LocalTime.NOON) + .build(); + + //when + ApiResponse response = userController.getUserInfo(testEmailUser); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + Assertions.assertThat(response.getResponse().getEmail()).isEqualTo("testEmailUser@naver.com"); + Assertions.assertThat(response.getResponse().getSignInType()).isEqualTo("EMAIL"); + Assertions.assertThat(response.getResponse().getMealTimeList().get(0).getMealTime()).isEqualTo(LocalTime.NOON); + } + + @Test + public void 본인의_유저_정보를_삭제할_수_있다() { + //given + CustomUserDetails testEmailUser = userTestData.createTestEmailUser(); + + //when + ApiResponse response = userController.deleteUser(testEmailUser); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + Assertions.assertThatThrownBy(() -> userController.getUserInfo(testEmailUser)) + .isInstanceOf(NotFoundUserException.class); + } + + + @Test + public void 토큰을_재발급_받을_수_있다() { + //given + List mealTime = List.of(LocalTime.of(12, 0), LocalTime.of(16, 0)); + SignUpRequest signUpRequest = new SignUpRequest("test123@gmail.com", + "password123", + mealTime, + "EMAIL"); + ApiResponse signUpResponse = userController.signUp(signUpRequest); + ReissueRequest request = new ReissueRequest(signUpResponse.getResponse().getRefreshToken()); + + //when + ApiResponse response = userController.reissueToken(request); + + //then + Assertions.assertThat(response.isSuccess()).isEqualTo(true); + } +} diff --git a/src/test/java/com/ourmenu/backend/global/DatabaseCleaner.java b/src/test/java/com/ourmenu/backend/global/DatabaseCleaner.java new file mode 100644 index 00000000..1a6f44a8 --- /dev/null +++ b/src/test/java/com/ourmenu/backend/global/DatabaseCleaner.java @@ -0,0 +1,42 @@ +package com.ourmenu.backend.global; + +import jakarta.annotation.PostConstruct; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.transaction.annotation.Transactional; + +public class DatabaseCleaner implements InitializingBean { + + private final List tables = new ArrayList<>(); + + @PersistenceContext + private EntityManager entityManager; + + @PostConstruct + public void findDatabaseTableNames() { + List tableInfos = entityManager.createNativeQuery("SHOW TABLES").getResultList(); + tables.addAll(tableInfos); + } + + private void truncate() { + entityManager.createNativeQuery(String.format("SET FOREIGN_KEY_CHECKS = %d", 0)).executeUpdate(); + for (String tableName : tables) { + entityManager.createNativeQuery(String.format("TRUNCATE TABLE %s", tableName)).executeUpdate(); + } + entityManager.createNativeQuery(String.format("SET FOREIGN_KEY_CHECKS = %d", 1)).executeUpdate(); + } + + @Override + public void afterPropertiesSet() { + findDatabaseTableNames(); + } + + @Transactional + public void clear() { + entityManager.clear(); + truncate(); + } +} \ No newline at end of file diff --git a/src/test/java/com/ourmenu/backend/global/TestConfig.java b/src/test/java/com/ourmenu/backend/global/TestConfig.java new file mode 100644 index 00000000..8b5b09ba --- /dev/null +++ b/src/test/java/com/ourmenu/backend/global/TestConfig.java @@ -0,0 +1,13 @@ +package com.ourmenu.backend.global; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; + +@TestConfiguration +public class TestConfig { + + @Bean + public DatabaseCleaner databaseCleaner() { + return new DatabaseCleaner(); + } +} diff --git a/src/test/java/com/ourmenu/backend/global/config/GlobalDataConfig.java b/src/test/java/com/ourmenu/backend/global/config/GlobalDataConfig.java new file mode 100644 index 00000000..a44fb8f6 --- /dev/null +++ b/src/test/java/com/ourmenu/backend/global/config/GlobalDataConfig.java @@ -0,0 +1,19 @@ +package com.ourmenu.backend.global.config; + +import com.ourmenu.backend.global.data.GlobalUserTestData; +import jakarta.persistence.EntityManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; + +@TestConfiguration +public class GlobalDataConfig { + + @Autowired + EntityManager entityManager; + + @Bean + public GlobalUserTestData globalUserTestData() { + return new GlobalUserTestData(entityManager); + } +} diff --git a/src/test/java/com/ourmenu/backend/global/data/GlobalUserTestData.java b/src/test/java/com/ourmenu/backend/global/data/GlobalUserTestData.java new file mode 100644 index 00000000..6e102e79 --- /dev/null +++ b/src/test/java/com/ourmenu/backend/global/data/GlobalUserTestData.java @@ -0,0 +1,67 @@ +package com.ourmenu.backend.global.data; + +import com.ourmenu.backend.domain.user.domain.CustomUserDetails; +import com.ourmenu.backend.domain.user.domain.MealTime; +import com.ourmenu.backend.domain.user.domain.SignInType; +import com.ourmenu.backend.domain.user.domain.User; +import jakarta.persistence.EntityManager; +import java.time.LocalTime; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.transaction.annotation.Transactional; + +public class GlobalUserTestData { + + @Autowired + PasswordEncoder passwordEncoder; + + private EntityManager entityManager; + + + public GlobalUserTestData(EntityManager entityManager) { + this.entityManager = entityManager; + } + + + @Transactional + public CustomUserDetails createTestEmailUser() { + String email = "testEmailUser@naver.com"; + String password = passwordEncoder.encode("password1!"); + User user = User.builder() + .email(email) + .password(password) + .signInType(SignInType.EMAIL) + .build(); + entityManager.persist(user); + entityManager.flush(); + return new CustomUserDetails(user.getId(), email, password); + } + + @Transactional + public CustomUserDetails createTestKakaoUser() { + String email = "testKakaoUser@naver.com"; + String password = "password1!"; + User user = User.builder() + .email(email) + .password(password) + .signInType(SignInType.KAKAO) + .build(); + entityManager.persist(user); + entityManager.flush(); + return new CustomUserDetails(user.getId(), email, password); + } + + @Transactional + public CustomUserDetails createTestEmailUserWithMealTime() { + CustomUserDetails testEmailUser = createTestEmailUser(); + + MealTime mealTime = MealTime.builder() + .userId(testEmailUser.getId()) + .mealTime(LocalTime.NOON) + .build(); + entityManager.persist(mealTime); + + return testEmailUser; + } +}