diff --git a/mysql/init/init.sql b/mysql/init/init.sql index d2554790..e14951c0 100644 --- a/mysql/init/init.sql +++ b/mysql/init/init.sql @@ -75,6 +75,14 @@ create table menu_tag ( primary key (menu_tag_id) ) engine=InnoDB; +create table on_boarding_state ( + answer_type tinyint check (answer_type between 0 and 1), + question_id integer not null, + id bigint not null auto_increment, + user_id bigint, + primary key (id) +) engine=InnoDB; + create table place ( latitude float(53), longitude float(53), diff --git a/src/main/java/com/ourMenu/backend/domain/onboarding/api/OnBoardingController.java b/src/main/java/com/ourMenu/backend/domain/onboarding/api/OnBoardingController.java index 110ac3d1..ec6779e5 100644 --- a/src/main/java/com/ourMenu/backend/domain/onboarding/api/OnBoardingController.java +++ b/src/main/java/com/ourMenu/backend/domain/onboarding/api/OnBoardingController.java @@ -1,13 +1,14 @@ package com.ourMenu.backend.domain.onboarding.api; import com.ourMenu.backend.domain.menu.domain.Menu; -import com.ourMenu.backend.domain.menu.dto.response.MenuDto; import com.ourMenu.backend.domain.onboarding.api.response.GetOnboardingResponse; +import com.ourMenu.backend.domain.onboarding.api.response.GetOnboardingState; import com.ourMenu.backend.domain.onboarding.api.response.GetQuestionRecommands; import com.ourMenu.backend.domain.onboarding.api.response.GetTagRecommends; import com.ourMenu.backend.domain.onboarding.application.OnBoardingService; import com.ourMenu.backend.domain.onboarding.domain.AnswerType; import com.ourMenu.backend.domain.onboarding.domain.DefaultTag; +import com.ourMenu.backend.domain.onboarding.domain.OnBoardingState; import com.ourMenu.backend.domain.onboarding.domain.Question; import com.ourMenu.backend.global.argument_resolver.UserId; import com.ourMenu.backend.global.common.ApiResponse; @@ -39,7 +40,7 @@ public ApiResponse> getOnboarding() { public ApiResponse getQuestionRecommend(@RequestParam("questionId") int questionId, @RequestParam("answer") AnswerType answerType, @UserId Long userId) { - List menus = onBoardService.findStoreByQuestionAnswer(userId, questionId, answerType); + List menus = onBoardService.saveAndFindStoreByQuestionAnswer(userId, questionId, answerType); return ApiUtils.success(GetQuestionRecommands.toDto(menus, questionId, answerType)); } @@ -51,10 +52,15 @@ public ApiResponse> getQuestionRecommend(@UserId Long use List getTagRecommendsList = new ArrayList<>(); for (DefaultTag defaultTag : defaultTagList) { List menuList = onBoardService.findStoreByRandomTag(userId, defaultTag); - getTagRecommendsList.add(GetTagRecommends.toDto(menuList,defaultTag)); + getTagRecommendsList.add(GetTagRecommends.toDto(menuList, defaultTag)); } return ApiUtils.success(getTagRecommendsList); + } + @GetMapping("/state") + public ApiResponse getOnboardingState(@UserId Long userId) { + OnBoardingState onBoardingState = onBoardService.findOneById(userId); + return ApiUtils.success(GetOnboardingState.toDto(onBoardingState)); } } diff --git a/src/main/java/com/ourMenu/backend/domain/onboarding/api/response/GetOnboardingState.java b/src/main/java/com/ourMenu/backend/domain/onboarding/api/response/GetOnboardingState.java new file mode 100644 index 00000000..a4f5511a --- /dev/null +++ b/src/main/java/com/ourMenu/backend/domain/onboarding/api/response/GetOnboardingState.java @@ -0,0 +1,24 @@ +package com.ourMenu.backend.domain.onboarding.api.response; + +import com.ourMenu.backend.domain.onboarding.domain.AnswerType; +import com.ourMenu.backend.domain.onboarding.domain.OnBoardingState; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@AllArgsConstructor +@Builder +@Getter +public class GetOnboardingState { + + private int questionId; + + private AnswerType answerType; + + public static GetOnboardingState toDto(OnBoardingState onBoardingState) { + return GetOnboardingState.builder() + .questionId(onBoardingState.getQuestionId()) + .answerType(onBoardingState.getAnswerType()) + .build(); + } +} diff --git a/src/main/java/com/ourMenu/backend/domain/onboarding/application/OnBoardingService.java b/src/main/java/com/ourMenu/backend/domain/onboarding/application/OnBoardingService.java index 2937d557..1c173bbe 100644 --- a/src/main/java/com/ourMenu/backend/domain/onboarding/application/OnBoardingService.java +++ b/src/main/java/com/ourMenu/backend/domain/onboarding/application/OnBoardingService.java @@ -3,12 +3,12 @@ import com.ourMenu.backend.domain.menu.application.MenuService; import com.ourMenu.backend.domain.menu.dao.MenuRepository; import com.ourMenu.backend.domain.menu.domain.Menu; -import com.ourMenu.backend.domain.menu.dto.response.MenuDto; +import com.ourMenu.backend.domain.onboarding.dao.OnBoardingStateRepository; import com.ourMenu.backend.domain.onboarding.domain.AnswerType; import com.ourMenu.backend.domain.onboarding.domain.DefaultTag; +import com.ourMenu.backend.domain.onboarding.domain.OnBoardingState; import com.ourMenu.backend.domain.onboarding.domain.Question; -import com.ourMenu.backend.domain.onboarding.util.S3Util; -import com.ourMenu.backend.domain.store.domain.Store; +import com.ourMenu.backend.domain.onboarding.exception.SearchResultNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,11 +21,30 @@ public class OnBoardingService { private final MenuRepository menuRepository; private final MenuService menuService; + private final OnBoardingStateRepository onBoardingStateRepository; public List getAllQuestion() { return Question.getAllQuestions(); } + @Transactional + public List saveAndFindStoreByQuestionAnswer(Long userId, int questionId, AnswerType answerType) { + OnBoardingState onBoardingState = saveAndUpdateOnBoardingState(userId, questionId, answerType); + return findStoreByQuestionAnswer(userId, questionId, answerType); + } + + @Transactional + public OnBoardingState saveAndUpdateOnBoardingState(Long userId, int questionId, AnswerType answerType){ + Optional onBoardingStateOptional = onBoardingStateRepository.findByUserId(userId); + if(onBoardingStateOptional.isEmpty()){ + OnBoardingState onBoardingState = OnBoardingState.toEntity(userId, questionId, answerType); + return save(onBoardingState); + } + OnBoardingState onBoardingState = onBoardingStateOptional.get(); + onBoardingState.update(questionId,answerType); + return onBoardingState; + } + @Transactional public List findStoreByQuestionAnswer(Long userId, int questionId, AnswerType answerType) { List foodStringList = Question.getAnswerFoodByIdAndAnswerType(questionId, answerType); @@ -33,7 +52,7 @@ public List findStoreByQuestionAnswer(Long userId, int questionId, AnswerT for (String s : foodStringList) { List menus = menuRepository.findMenusByTitleContainingAndUserId(s, userId); for (Menu menu : menus) { - map.put(menu.getId(),menu); + map.put(menu.getId(), menu); } } @@ -44,4 +63,24 @@ public List findStoreByQuestionAnswer(Long userId, int questionId, AnswerT public List findStoreByRandomTag(Long userId, DefaultTag randomTag) { return menuService.getAllMenusByTagName(randomTag.getTagName(), userId); } + + @Transactional(readOnly = true) + public String findOnboardingStateByUserId(Long userId) { + OnBoardingState onBoardingState = findOneById(userId); + + return "success"; + } + + @Transactional + public OnBoardingState findOneById(Long userId) { + Optional onBoardingStateOptional = onBoardingStateRepository.findByUserId(userId); + if (onBoardingStateOptional.isEmpty()) + throw new SearchResultNotFoundException(); + return onBoardingStateOptional.get(); + } + + @Transactional + public OnBoardingState save(OnBoardingState onBoardingState) { + return onBoardingStateRepository.save(onBoardingState); + } } diff --git a/src/main/java/com/ourMenu/backend/domain/onboarding/dao/OnBoardingStateRepository.java b/src/main/java/com/ourMenu/backend/domain/onboarding/dao/OnBoardingStateRepository.java new file mode 100644 index 00000000..af93616c --- /dev/null +++ b/src/main/java/com/ourMenu/backend/domain/onboarding/dao/OnBoardingStateRepository.java @@ -0,0 +1,14 @@ +package com.ourMenu.backend.domain.onboarding.dao; + +import com.ourMenu.backend.domain.menu.domain.Tag; +import com.ourMenu.backend.domain.onboarding.domain.OnBoardingState; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface OnBoardingStateRepository extends JpaRepository { + + Optional findByUserId(Long userId); +} diff --git a/src/main/java/com/ourMenu/backend/domain/onboarding/domain/OnBoardingState.java b/src/main/java/com/ourMenu/backend/domain/onboarding/domain/OnBoardingState.java new file mode 100644 index 00000000..daf83854 --- /dev/null +++ b/src/main/java/com/ourMenu/backend/domain/onboarding/domain/OnBoardingState.java @@ -0,0 +1,36 @@ +package com.ourMenu.backend.domain.onboarding.domain; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.*; + +@Entity +@Builder +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class OnBoardingState { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private Long userId; + private int questionId; + private AnswerType answerType; + + public static OnBoardingState toEntity(Long userId, int questionId, AnswerType answerType) { + return OnBoardingState.builder() + .userId(userId) + .questionId(questionId) + .answerType(answerType) + .build(); + } + + public void update(int questionId, AnswerType answerType) { + this.questionId = questionId; + this.answerType = answerType; + } +} diff --git a/src/main/java/com/ourMenu/backend/domain/onboarding/exception/SearchResultNotFoundException.java b/src/main/java/com/ourMenu/backend/domain/onboarding/exception/SearchResultNotFoundException.java new file mode 100644 index 00000000..049b61ae --- /dev/null +++ b/src/main/java/com/ourMenu/backend/domain/onboarding/exception/SearchResultNotFoundException.java @@ -0,0 +1,12 @@ +package com.ourMenu.backend.domain.onboarding.exception; + +import com.ourMenu.backend.global.exception.CustomException; +import com.ourMenu.backend.global.exception.ErrorCode; + +public class SearchResultNotFoundException extends CustomException { + + public SearchResultNotFoundException(){ + super(ErrorCode.ON_BOARDING_STATE_NOT_FOUND); + } + +} \ No newline at end of file diff --git a/src/main/java/com/ourMenu/backend/global/exception/ErrorCode.java b/src/main/java/com/ourMenu/backend/global/exception/ErrorCode.java index bfd19667..6cdb9d24 100644 --- a/src/main/java/com/ourMenu/backend/global/exception/ErrorCode.java +++ b/src/main/java/com/ourMenu/backend/global/exception/ErrorCode.java @@ -39,8 +39,10 @@ public enum ErrorCode { IMAGE_NOT_LOADED_ERROR(HttpStatus.BAD_REQUEST, "I400", "이미지 업로드에 실패하였습니다."), //place - PLACE_NOT_FOUND(HttpStatus.NOT_FOUND, "P401", "식당을 찾을 수 없습니다."); + PLACE_NOT_FOUND(HttpStatus.NOT_FOUND, "P401", "식당을 찾을 수 없습니다."), + //onboarding + ON_BOARDING_STATE_NOT_FOUND(HttpStatus.NOT_FOUND,"O401","저장된 온보딩 상태가 없습니다.") ; private final HttpStatus status;