From 0806f71b89393fe63bb1631e61278ade5afdf1b5 Mon Sep 17 00:00:00 2001 From: jeonghyemin Date: Tue, 8 Jul 2025 18:20:44 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat(Reservation):=20=EC=98=88=EC=95=BD=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EB=93=B1=EB=A1=9D=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/GlobalExceptionHandler.java | 8 ++++++++ .../oauth/oauth2/CustomOAuth2UserService.java | 1 + .../reservation/service/ReservationService.java | 14 +++++++++++++- .../com/nowait/common/exception/ErrorMessage.java | 1 + .../exception/DuplicateReservationException.java | 10 ++++++++++ .../repository/ReservationRepository.java | 5 +++++ 6 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/reservation/exception/DuplicateReservationException.java diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/exception/GlobalExceptionHandler.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/exception/GlobalExceptionHandler.java index 116ade92..57f9d0b6 100644 --- a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/exception/GlobalExceptionHandler.java +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/exception/GlobalExceptionHandler.java @@ -26,6 +26,7 @@ import com.nowait.domaincorerdb.order.exception.DuplicateOrderException; import com.nowait.domaincorerdb.order.exception.OrderItemsEmptyException; import com.nowait.domaincorerdb.order.exception.OrderParameterEmptyException; +import com.nowait.domaincorerdb.reservation.exception.DuplicateReservationException; import com.nowait.domaincorerdb.reservation.exception.ReservationNotFoundException; import com.nowait.domaincorerdb.token.exception.BusinessException; import com.nowait.domaincorerdb.user.exception.UserNotFoundException; @@ -162,6 +163,13 @@ public ErrorResponse reservationNotFoundException(ReservationNotFoundException e return new ErrorResponse(e.getMessage(), NOTFOUND_RESERVATION.getCode()); } + @ResponseStatus(value = BAD_REQUEST) + @ExceptionHandler(DuplicateReservationException.class) + public ErrorResponse duplicateReservationException(DuplicateReservationException e) { + log.error("duplicateReservationException", e); + return new ErrorResponse(e.getMessage(), DUPLICATE_RESERVATION.getCode()); + } + private static Map getErrors(MethodArgumentNotValidException e) { return e.getBindingResult() diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/oauth/oauth2/CustomOAuth2UserService.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/oauth/oauth2/CustomOAuth2UserService.java index dd5e7855..a7e12685 100644 --- a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/oauth/oauth2/CustomOAuth2UserService.java +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/oauth/oauth2/CustomOAuth2UserService.java @@ -54,6 +54,7 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic .profileImage(oAuth2Response.getProfileImage()) .socialType(SocialType.KAKAO) .role(Role.USER) // 일반 유저 설정 + .storeId(0L) .build(); userRepository.save(user); diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/reservation/service/ReservationService.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/reservation/service/ReservationService.java index 2e79bbda..86e69ad8 100644 --- a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/reservation/service/ReservationService.java +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/reservation/service/ReservationService.java @@ -1,6 +1,7 @@ package com.nowait.applicationuser.reservation.service; import java.time.LocalDateTime; +import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -11,11 +12,13 @@ import com.nowait.domaincorerdb.reservation.entity.Reservation; import com.nowait.domaincorerdb.reservation.repository.ReservationRepository; import com.nowait.domaincorerdb.store.entity.Store; +import com.nowait.domaincorerdb.store.exception.StoreNotFoundException; import com.nowait.domaincorerdb.store.repository.StoreRepository; import com.nowait.domaincorerdb.user.entity.User; import com.nowait.domaincorerdb.user.exception.UserNotFoundException; import com.nowait.domaincorerdb.user.repository.UserRepository; import com.nowait.domainuserrdb.oauth.dto.CustomOAuth2User; +import com.sun.jdi.request.DuplicateRequestException; import lombok.RequiredArgsConstructor; @@ -31,10 +34,19 @@ public class ReservationService { public ReservationCreateResponseDto create(Long storeId, CustomOAuth2User customOAuth2User, ReservationCreateRequestDto requestDto) { Store store = storeRepository.findById(storeId) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 store")); + .orElseThrow(StoreNotFoundException::new); User user = userRepository.findById(customOAuth2User.getUserId()) .orElseThrow(UserNotFoundException::new); + // 중복 예약 존재 여부 확인 + boolean hasOngoingReservation = reservationRepository.existsByUserAndStoreAndStatusIn( + user, + store, + List.of(ReservationStatus.WAITING, ReservationStatus.CALLING) + ); + if (hasOngoingReservation) { + throw new DuplicateRequestException(); + } Reservation reservation = Reservation.builder() .store(store) .user(user) diff --git a/nowait-common/src/main/java/com/nowait/common/exception/ErrorMessage.java b/nowait-common/src/main/java/com/nowait/common/exception/ErrorMessage.java index 5a651f45..e521cfdc 100644 --- a/nowait-common/src/main/java/com/nowait/common/exception/ErrorMessage.java +++ b/nowait-common/src/main/java/com/nowait/common/exception/ErrorMessage.java @@ -27,6 +27,7 @@ public enum ErrorMessage { NOTFOUND_RESERVATION("저장된 예약 정보가 없습니다.", "reservation001"), RESERVATION_VIEW_UNAUTHORIZED("예약 보기 권한이 없습니다.(슈퍼계정 or 주점 관리자만 가능)", "reservation002"), RESERVATION_UPDATE_UNAUTHORIZED("예약 수정 권한이 없습니다.(슈퍼계정 or 주점 관리자만 가능)", "reservation003"), + DUPLICATE_RESERVATION("이미 대기 중인 예약이 존재합니다.", "reservation004"), // bookmark DUPLICATE_BOOKMARK("이미 북마크한 주점입니다.", "bookmark001"), diff --git a/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/reservation/exception/DuplicateReservationException.java b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/reservation/exception/DuplicateReservationException.java new file mode 100644 index 00000000..588a0a49 --- /dev/null +++ b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/reservation/exception/DuplicateReservationException.java @@ -0,0 +1,10 @@ +package com.nowait.domaincorerdb.reservation.exception; + +import com.nowait.common.exception.ErrorMessage; + +public class DuplicateReservationException extends RuntimeException { + public DuplicateReservationException() { + super(ErrorMessage.DUPLICATE_RESERVATION.getMessage()); + } +} + diff --git a/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/reservation/repository/ReservationRepository.java b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/reservation/repository/ReservationRepository.java index 874469c8..235242b9 100644 --- a/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/reservation/repository/ReservationRepository.java +++ b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/reservation/repository/ReservationRepository.java @@ -5,9 +5,14 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import com.nowait.common.enums.ReservationStatus; import com.nowait.domaincorerdb.reservation.entity.Reservation; +import com.nowait.domaincorerdb.store.entity.Store; +import com.nowait.domaincorerdb.user.entity.User; @Repository public interface ReservationRepository extends JpaRepository { List findAllByStore_StoreIdOrderByRequestedAtAsc(Long storeId); + boolean existsByUserAndStoreAndStatusIn(User user, Store store, List statuses); + } From ee8fd1cc243b76e12834ccdd50a8e3dc5d5c609c Mon Sep 17 00:00:00 2001 From: jeonghyemin Date: Tue, 8 Jul 2025 18:26:21 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat(Reservation):=20=EC=98=88=EC=95=BD=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EB=93=B1=EB=A1=9D=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reservation/service/ReservationService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/reservation/service/ReservationService.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/reservation/service/ReservationService.java index 86e69ad8..4bb0169a 100644 --- a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/reservation/service/ReservationService.java +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/reservation/service/ReservationService.java @@ -10,6 +10,7 @@ import com.nowait.applicationuser.reservation.dto.ReservationCreateResponseDto; import com.nowait.common.enums.ReservationStatus; import com.nowait.domaincorerdb.reservation.entity.Reservation; +import com.nowait.domaincorerdb.reservation.exception.DuplicateReservationException; import com.nowait.domaincorerdb.reservation.repository.ReservationRepository; import com.nowait.domaincorerdb.store.entity.Store; import com.nowait.domaincorerdb.store.exception.StoreNotFoundException; @@ -18,7 +19,6 @@ import com.nowait.domaincorerdb.user.exception.UserNotFoundException; import com.nowait.domaincorerdb.user.repository.UserRepository; import com.nowait.domainuserrdb.oauth.dto.CustomOAuth2User; -import com.sun.jdi.request.DuplicateRequestException; import lombok.RequiredArgsConstructor; @@ -45,7 +45,7 @@ public ReservationCreateResponseDto create(Long storeId, CustomOAuth2User custom List.of(ReservationStatus.WAITING, ReservationStatus.CALLING) ); if (hasOngoingReservation) { - throw new DuplicateRequestException(); + throw new DuplicateReservationException(); } Reservation reservation = Reservation.builder() .store(store) From f7b311f5746ae98954efeb3978a2e0f1e9cc8753 Mon Sep 17 00:00:00 2001 From: jeonghyemin Date: Tue, 8 Jul 2025 18:42:05 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat(Store):=20store=20=EC=9B=A8=EC=9D=B4?= =?UTF-8?q?=ED=8C=85=20=EB=B9=84=ED=99=9C=EC=84=B1=ED=99=94=20=EC=8B=9C=20?= =?UTF-8?q?=EC=98=88=EC=95=BD=20=EB=B6=88=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 예약 create 시 방어로직 추가 --- .../exception/GlobalExceptionHandler.java | 8 ++++++++ .../reservation/service/ReservationService.java | 5 ++++- .../java/com/nowait/common/exception/ErrorMessage.java | 1 + .../store/exception/StoreWaitingDisabledException.java | 9 +++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreWaitingDisabledException.java diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/exception/GlobalExceptionHandler.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/exception/GlobalExceptionHandler.java index 57f9d0b6..78a405c0 100644 --- a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/exception/GlobalExceptionHandler.java +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/exception/GlobalExceptionHandler.java @@ -28,6 +28,7 @@ import com.nowait.domaincorerdb.order.exception.OrderParameterEmptyException; import com.nowait.domaincorerdb.reservation.exception.DuplicateReservationException; import com.nowait.domaincorerdb.reservation.exception.ReservationNotFoundException; +import com.nowait.domaincorerdb.store.exception.StoreWaitingDisabledException; import com.nowait.domaincorerdb.token.exception.BusinessException; import com.nowait.domaincorerdb.user.exception.UserNotFoundException; import com.nowait.domainuserrdb.bookmark.exception.BookmarkOwnerMismatchException; @@ -170,6 +171,13 @@ public ErrorResponse duplicateReservationException(DuplicateReservationException return new ErrorResponse(e.getMessage(), DUPLICATE_RESERVATION.getCode()); } + @ResponseStatus(value = BAD_REQUEST) + @ExceptionHandler(StoreWaitingDisabledException.class) + public ErrorResponse storeWaitingDisabledException(StoreWaitingDisabledException e) { + log.error("storeWaitingDisabledException", e); + return new ErrorResponse(e.getMessage(), STORE_WAITING_DISABLED.getCode()); + } + private static Map getErrors(MethodArgumentNotValidException e) { return e.getBindingResult() diff --git a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/reservation/service/ReservationService.java b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/reservation/service/ReservationService.java index 4bb0169a..d5dde8ab 100644 --- a/nowait-app-user-api/src/main/java/com/nowait/applicationuser/reservation/service/ReservationService.java +++ b/nowait-app-user-api/src/main/java/com/nowait/applicationuser/reservation/service/ReservationService.java @@ -14,6 +14,7 @@ import com.nowait.domaincorerdb.reservation.repository.ReservationRepository; import com.nowait.domaincorerdb.store.entity.Store; import com.nowait.domaincorerdb.store.exception.StoreNotFoundException; +import com.nowait.domaincorerdb.store.exception.StoreWaitingDisabledException; import com.nowait.domaincorerdb.store.repository.StoreRepository; import com.nowait.domaincorerdb.user.entity.User; import com.nowait.domaincorerdb.user.exception.UserNotFoundException; @@ -37,7 +38,9 @@ public ReservationCreateResponseDto create(Long storeId, CustomOAuth2User custom .orElseThrow(StoreNotFoundException::new); User user = userRepository.findById(customOAuth2User.getUserId()) .orElseThrow(UserNotFoundException::new); - + // store 웨이팅 비활성화 여부 + if (Boolean.FALSE.equals(store.getIsActive())) + throw new StoreWaitingDisabledException(); // 중복 예약 존재 여부 확인 boolean hasOngoingReservation = reservationRepository.existsByUserAndStoreAndStatusIn( user, diff --git a/nowait-common/src/main/java/com/nowait/common/exception/ErrorMessage.java b/nowait-common/src/main/java/com/nowait/common/exception/ErrorMessage.java index e521cfdc..02a107a1 100644 --- a/nowait-common/src/main/java/com/nowait/common/exception/ErrorMessage.java +++ b/nowait-common/src/main/java/com/nowait/common/exception/ErrorMessage.java @@ -47,6 +47,7 @@ public enum ErrorMessage { STORE_VIEW_UNAUTHORIZED("주점 보기 권한이 없습니다.(슈퍼계정 or 주점 관리자만 가능)", "store003"), STORE_UPDATE_UNAUTHORIZED("주점 수정 권한이 없습니다.(슈퍼계정 or 주점 관리자만 가능)", "store004"), STORE_DELETE_UNAUTHORIZED("주점 삭제 권한이 없습니다.(슈퍼계정 or 주점 관리자만 가능)", "store005"), + STORE_WAITING_DISABLED("해당 주점은 대기 비활성화된 주점입니다.", "store006"), // image IMAGE_FILE_EMPTY("이미지 파일을 업로드 해주세요", "image001"), diff --git a/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreWaitingDisabledException.java b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreWaitingDisabledException.java new file mode 100644 index 00000000..cf1d2c49 --- /dev/null +++ b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreWaitingDisabledException.java @@ -0,0 +1,9 @@ +package com.nowait.domaincorerdb.store.exception; + +import com.nowait.common.exception.ErrorMessage; + +public class StoreWaitingDisabledException extends RuntimeException { + public StoreWaitingDisabledException() { + super(ErrorMessage.STORE_WAITING_DISABLED.getMessage()); + } +}