diff --git a/src/main/java/ybe/mini/travelserver/domain/reservation/controller/ReservationController.java b/src/main/java/ybe/mini/travelserver/domain/reservation/controller/ReservationController.java index 17004ec..227cfd7 100644 --- a/src/main/java/ybe/mini/travelserver/domain/reservation/controller/ReservationController.java +++ b/src/main/java/ybe/mini/travelserver/domain/reservation/controller/ReservationController.java @@ -17,6 +17,7 @@ import java.util.List; +import static ybe.mini.travelserver.global.security.Role.HAS_ROLE_USER; import static ybe.mini.travelserver.global.security.Role.ROLE_USER; @Slf4j @@ -27,10 +28,10 @@ public class ReservationController { private final ReservationService reservationService; - @PreAuthorize("hasRole('ROLE_USER')") + @PreAuthorize(HAS_ROLE_USER) @PostMapping public ResponseDto tryReservation ( - @RequestBody @Valid ReservationCreateRequest createRequest, + @RequestBody ReservationCreateRequest createRequest, @AuthenticationPrincipal PrincipalDetails principalDetails ) { return new ResponseDto<>( @@ -39,7 +40,7 @@ public ResponseDto tryReservation ( ); } - @PreAuthorize("hasRole('ROLE_USER')") + @PreAuthorize(HAS_ROLE_USER) @PostMapping("/from-cart") public ResponseDto tryReservationFromCart ( @RequestBody @Valid ReservationCreateFromCartRequest createRequest, @@ -51,7 +52,7 @@ public ResponseDto tryReservationFromCart ( ); } - @PreAuthorize("hasRole('ROLE_USER')") + @PreAuthorize(HAS_ROLE_USER) @GetMapping public ResponseDto> getMyReservations ( @AuthenticationPrincipal PrincipalDetails principalDetails diff --git a/src/main/java/ybe/mini/travelserver/domain/reservation/exception/ReservationErrorMessage.java b/src/main/java/ybe/mini/travelserver/domain/reservation/exception/ReservationErrorMessage.java index c6aa6b3..5fb25a2 100644 --- a/src/main/java/ybe/mini/travelserver/domain/reservation/exception/ReservationErrorMessage.java +++ b/src/main/java/ybe/mini/travelserver/domain/reservation/exception/ReservationErrorMessage.java @@ -11,7 +11,6 @@ @AllArgsConstructor public enum ReservationErrorMessage implements ErrorMessage { - HTTP_MESSAGE_NOT_READABLE(BAD_REQUEST, "DTO 양식이 맞지 않습니다."), RESERVATION_NOT_FOUND(BAD_REQUEST, "해당 ID의 예약 정보가 없습니다.") ; private final HttpStatus status; diff --git a/src/main/java/ybe/mini/travelserver/domain/reservation/exception/ReservationExceptionHandler.java b/src/main/java/ybe/mini/travelserver/domain/reservation/exception/ReservationExceptionHandler.java index 7aaf454..c95ad9f 100644 --- a/src/main/java/ybe/mini/travelserver/domain/reservation/exception/ReservationExceptionHandler.java +++ b/src/main/java/ybe/mini/travelserver/domain/reservation/exception/ReservationExceptionHandler.java @@ -2,12 +2,10 @@ import jakarta.servlet.http.HttpServletRequest; import org.springframework.http.ProblemDetail; -import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import ybe.mini.travelserver.global.exception.ProblemDetailCreator; -import static ybe.mini.travelserver.domain.reservation.exception.ReservationErrorMessage.HTTP_MESSAGE_NOT_READABLE; import static ybe.mini.travelserver.domain.reservation.exception.ReservationErrorMessage.RESERVATION_NOT_FOUND; @RestControllerAdvice @@ -17,11 +15,6 @@ protected ReservationExceptionHandler() { super("예약 처리 실패"); } - @ExceptionHandler(HttpMessageNotReadableException.class) - public ProblemDetail handleHttpMessageNotReadableException(HttpServletRequest request) { - return createProblemDetail(HTTP_MESSAGE_NOT_READABLE, request); //todo : Global로 분리할지 논의 - } - @ExceptionHandler(ReservationNotFoundException.class) public ProblemDetail handleReservationNotFoundException(HttpServletRequest request) { return createProblemDetail(RESERVATION_NOT_FOUND, request); diff --git a/src/main/java/ybe/mini/travelserver/domain/reservation_room/controller/ReservationRoomController.java b/src/main/java/ybe/mini/travelserver/domain/reservation_room/controller/ReservationRoomController.java index 8433b4a..d90bec6 100644 --- a/src/main/java/ybe/mini/travelserver/domain/reservation_room/controller/ReservationRoomController.java +++ b/src/main/java/ybe/mini/travelserver/domain/reservation_room/controller/ReservationRoomController.java @@ -11,6 +11,8 @@ import java.util.List; +import static ybe.mini.travelserver.global.security.Role.HAS_ROLE_USER; + @Slf4j @RequestMapping("/reservation-rooms") @RestController @@ -19,7 +21,7 @@ public class ReservationRoomController { private final ReservationRoomService reservationRoomService; - @PreAuthorize("hasRole('ROLE_USER')") + @PreAuthorize(HAS_ROLE_USER) @GetMapping("/{reservationId}") public ResponseDto> getReservationRoomsByReserveId( @PathVariable Long reservationId @@ -30,8 +32,8 @@ public ResponseDto> getReservationRoomsByReserv reservationRoomService.getReservationRoomsFromReservation(reservationId) ); } - - @PreAuthorize("hasRole('ROLE_USER')") + + @PreAuthorize(HAS_ROLE_USER) @DeleteMapping public ResponseDto deleteReservationRoom( @RequestParam Long reservationId, diff --git a/src/main/java/ybe/mini/travelserver/domain/reservation_room/dto/ReservationRoomCreateRequest.java b/src/main/java/ybe/mini/travelserver/domain/reservation_room/dto/ReservationRoomCreateRequest.java index 36a96b3..84b39c2 100644 --- a/src/main/java/ybe/mini/travelserver/domain/reservation_room/dto/ReservationRoomCreateRequest.java +++ b/src/main/java/ybe/mini/travelserver/domain/reservation_room/dto/ReservationRoomCreateRequest.java @@ -1,8 +1,11 @@ package ybe.mini.travelserver.domain.reservation_room.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import jakarta.validation.constraints.*; +import jakarta.validation.constraints.FutureOrPresent; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.Builder; +import org.springframework.format.annotation.DateTimeFormat; import ybe.mini.travelserver.domain.accommodation.entity.AreaCode; import java.io.Serializable; @@ -20,14 +23,13 @@ public record ReservationRoomCreateRequest( @NotNull(message = "roomTypeId 양식이 잘못 입력되었습니다.") Long roomTypeId, - @NotNull + @FutureOrPresent - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm") + @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDateTime checkIn, - @NotNull @FutureOrPresent - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm") + @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDateTime checkOut, @NotNull @Min(value = 1, message = "숙박 인원은 최소 1명 이어야 합니다.") diff --git a/src/main/java/ybe/mini/travelserver/global/exception/dto/DTOErrorMessage.java b/src/main/java/ybe/mini/travelserver/global/exception/dto/DTOErrorMessage.java index 1252edd..fd0ae40 100644 --- a/src/main/java/ybe/mini/travelserver/global/exception/dto/DTOErrorMessage.java +++ b/src/main/java/ybe/mini/travelserver/global/exception/dto/DTOErrorMessage.java @@ -11,6 +11,7 @@ @AllArgsConstructor public enum DTOErrorMessage implements ErrorMessage { METHOD_ARGUMENT_NOT_VALID(BAD_REQUEST, "DTO 값이 유효하지 않습니다"), + DATETIME_PARSE(BAD_REQUEST, "날짜 형식이 유효하지 않습니다"), ; private final HttpStatus status; diff --git a/src/main/java/ybe/mini/travelserver/global/exception/dto/DTOExceptionHandler.java b/src/main/java/ybe/mini/travelserver/global/exception/dto/DTOExceptionHandler.java index a695e5a..4091267 100644 --- a/src/main/java/ybe/mini/travelserver/global/exception/dto/DTOExceptionHandler.java +++ b/src/main/java/ybe/mini/travelserver/global/exception/dto/DTOExceptionHandler.java @@ -7,8 +7,10 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import ybe.mini.travelserver.global.exception.ProblemDetailCreator; +import java.time.format.DateTimeParseException; import java.util.Objects; +import static ybe.mini.travelserver.global.exception.dto.DTOErrorMessage.DATETIME_PARSE; import static ybe.mini.travelserver.global.exception.dto.DTOErrorMessage.METHOD_ARGUMENT_NOT_VALID; @RestControllerAdvice @@ -26,4 +28,10 @@ public ProblemDetail handleMethodArgumentNotValidException( return createProblemDetail(errorMessage, METHOD_ARGUMENT_NOT_VALID.getStatus().value(), request); } + @ExceptionHandler(DateTimeParseException.class) + public ProblemDetail handleDateTimeParseException( + HttpServletRequest request + ) { + return createProblemDetail(DATETIME_PARSE, request); + } } \ No newline at end of file diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 8d6e62e..f18a0b4 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -21,7 +21,7 @@ spring: jpa: show-sql: true hibernate: - ddl-auto: create + ddl-auto: update properties: hibernate: format_sql: true diff --git a/src/test/http/reservation.http b/src/test/http/reservation.http index 94e3eb7..987051c 100644 --- a/src/test/http/reservation.http +++ b/src/test/http/reservation.http @@ -1,7 +1,7 @@ ### 예약 생성 POST http://localhost:8080/reservations Content-Type: application/json -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiaWF0IjoxNzAxMTE2MTk4LCJleHAiOjE3MDExMTc5OTgsImVtYWlsIjoib2tqYWVvb2s5OEBnbWFpbC5jb20iLCJwYXNzd29yZCI6IntiY3J5cHR9JDJhJDEwJGRWc3JDenZCWVdWdU5XWm5WN3d3QWVra3E5RUJWZ0t1anpxT28ucmZBU05FZEswZkd5QzVlIiwibmFtZSI6Im9ramFlb29rIn0.PUhHIiJF_XQ1vCcZW1LVXQLLJGkx_HAYKTYinAtH84c +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiaWF0IjoxNzAxMTU2NTc2LCJleHAiOjE3MDExNTgzNzYsImVtYWlsIjoib2tqYWVvb2s5OEBnbWFpbC5jb20iLCJwYXNzd29yZCI6IntiY3J5cHR9JDJhJDEwJFNCbjZSQ3ZQdFQ2WW1vSVM0ZzU1dE8xTFBwRDJkSjJLbDBKcDRXT3k5RmhuNzNxdnNJQS51IiwibmFtZSI6Im9ramFlb29rIn0.HCiMHNhtW45GEFH2tbkihaeiqADBmehLfg2iGlIDuCE { "paymentType": "CARD", @@ -11,8 +11,8 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiaWF0I "accommodationName": "가락관광호텔", "areaCode": "SEOUL", "roomTypeId": 11430, - "checkIn": "2024-01-01 14:00", - "checkOut": "2024-01-02 11:00", + "checkIn": "2024-01-01T00:00", + "checkOut": "2024-01-03T00:00", "guestNumber": 2 } ] diff --git a/src/test/java/ybe/mini/travelserver/domain/reservation/service/ReservationServiceTest.java b/src/test/java/ybe/mini/travelserver/domain/reservation/service/ReservationServiceTest.java index dd094d2..daee7a3 100644 --- a/src/test/java/ybe/mini/travelserver/domain/reservation/service/ReservationServiceTest.java +++ b/src/test/java/ybe/mini/travelserver/domain/reservation/service/ReservationServiceTest.java @@ -1,6 +1,5 @@ package ybe.mini.travelserver.domain.reservation.service; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -42,25 +41,25 @@ class ReservationServiceTest implements DummyObjectForRoom, DummyReservationDTO, @InjectMocks ReservationService reservationService; -// @Test -// void createReservation_success() { -// //given -// given(tourAPIService.bringAccommodation(anyLong(), any())).willReturn(dummyAccommodation()); -// given(tourAPIService.bringRoom(anyLong(), anyLong())).willReturn(dummyRoom(dummyAccommodation())); -// given(roomRepository.findByRoomTypeId(any())).willReturn(Optional.empty()); -// given(roomRepository.save(any(Room.class))).willReturn(dummyRoom(dummyAccommodation())); -// given(accommodationRepository.findById(any())).willReturn(Optional.ofNullable(dummyAccommodation())); -// given(memberRepository.findByEmail(any())).willReturn(Optional.ofNullable(dummyMember())); -// given(reservationRepository.save(any(Reservation.class))).willReturn(dummyReservation()); -// -// //when -// var actual = reservationService.createReservation(dummyMember().getEmail(), dummyReservationCreateReq()); -// -// //then -// var expected = dummyReservationCreateRes(); -// assertEquals(actual, expected); -// -// } + @Test + void createReservation_success() { + //given + given(tourAPIService.bringAccommodation(any(), any())).willReturn(dummyAccommodation()); + given(tourAPIService.bringRoom(anyLong(), anyLong())).willReturn(dummyRoom(dummyAccommodation())); + given(roomRepository.findByRoomTypeId(any())).willReturn(Optional.empty()); + given(roomRepository.save(any(Room.class))).willReturn(dummyRoom(dummyAccommodation())); + given(accommodationRepository.findById(any())).willReturn(Optional.ofNullable(dummyAccommodation())); + given(memberRepository.findByEmail(any())).willReturn(Optional.ofNullable(dummyMember())); + given(reservationRepository.save(any(Reservation.class))).willReturn(dummyReservation()); + + //when + var actual = reservationService.createReservation(dummyMember().getEmail(), dummyReservationCreateReq()); + + //then + var expected = dummyReservationCreateRes(); + assertEquals(actual, expected); + + } @Test void deleteReservation_success() {