Skip to content
This repository has been archived by the owner on Jan 15, 2024. It is now read-only.

Commit

Permalink
Merge pull request #112 from Mini-Team-6/feature/#110-reservation-sto…
Browse files Browse the repository at this point in the history
…k-validation

Feat: 예약 시 이미 품절된 객실 검증 로직 추가
  • Loading branch information
tjdtn0219 authored Nov 29, 2023
2 parents f65de0f + 34da681 commit 1eccf58
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
@AllArgsConstructor
public enum ReservationErrorMessage implements ErrorMessage {

RESERVATION_NOT_FOUND(BAD_REQUEST, "해당 ID의 예약 정보가 없습니다.")
RESERVATION_NOT_FOUND(BAD_REQUEST, "해당 ID의 예약 정보가 없습니다."),
ROOM_STOCK_IS_EMPTY(BAD_REQUEST, "예약하려는 객실 상품이 이미 품절되었습니다.")
;
private final HttpStatus status;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import ybe.mini.travelserver.global.exception.ProblemDetailCreator;

import static ybe.mini.travelserver.domain.reservation.exception.ReservationErrorMessage.RESERVATION_NOT_FOUND;
import static ybe.mini.travelserver.domain.reservation.exception.ReservationErrorMessage.ROOM_STOCK_IS_EMPTY;

@RestControllerAdvice
public class ReservationExceptionHandler extends ProblemDetailCreator<ReservationErrorMessage> {
Expand All @@ -20,5 +21,10 @@ public ProblemDetail handleReservationNotFoundException(HttpServletRequest reque
return createProblemDetail(RESERVATION_NOT_FOUND, request);
}

@ExceptionHandler(RoomStockIsEmptyException.class)
public ProblemDetail handleRoomStockIsEmptyException(HttpServletRequest request) {
return createProblemDetail(ROOM_STOCK_IS_EMPTY, request);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package ybe.mini.travelserver.domain.reservation.exception;

public class RoomStockIsEmptyException extends RuntimeException {
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.core.Local;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ybe.mini.travelserver.domain.accommodation.entity.Accommodation;
Expand All @@ -16,14 +17,16 @@
import ybe.mini.travelserver.domain.reservation.dto.ReservationGetResponse;
import ybe.mini.travelserver.domain.reservation.entity.Reservation;
import ybe.mini.travelserver.domain.reservation.exception.ReservationNotFoundException;
import ybe.mini.travelserver.domain.reservation.exception.RoomStockIsEmptyException;
import ybe.mini.travelserver.domain.reservation.repository.ReservationRepository;
import ybe.mini.travelserver.domain.reservation_room.dto.ReservationRoomCreateRequest;
import ybe.mini.travelserver.domain.reservation_room.entity.ReservationRoom;
import ybe.mini.travelserver.domain.reservation_room.repository.ReservationRoomRepository;
import ybe.mini.travelserver.domain.room.entity.Room;
import ybe.mini.travelserver.domain.room.repository.RoomRepository;
import ybe.mini.travelserver.global.api.TourAPIService;
import ybe.mini.travelserver.global.util.Validation;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -35,6 +38,7 @@
public class ReservationService {

private final ReservationRepository reservationRepository;
private final ReservationRoomRepository reservationRoomRepository;
private final MemberRepository memberRepository;
private final TourAPIService tourAPIService;
private final RoomRepository roomRepository;
Expand All @@ -44,15 +48,35 @@ public class ReservationService {
@Transactional
public ReservationCreateResponse createReservation(String userEmail, ReservationCreateRequest reservationRequest) {


List<ReservationRoom> reservationRooms =
reservationRoomDtosToEntityList(reservationRequest.reservationRooms());

reservationRooms.forEach(this::isEnableReservation);

Member member = getMemberByEmail(userEmail);
Reservation reservation =
Reservation.createReservation(member, reservationRequest.paymentType(), reservationRooms);

return ReservationCreateResponse.fromEntity(reservationRepository.save(reservation));
}

private void isEnableReservation(ReservationRoom resRoom) {
int restStock = getRestStock(
resRoom.getRoom(), resRoom.getCheckIn(), resRoom.getCheckOut()
);
if(restStock==0) throw new RoomStockIsEmptyException();
}

private Integer getRestStock(Room room, LocalDate checkIn, LocalDate checkOut) {
List<ReservationRoom> reservationRooms =
reservationRoomRepository.findAllByRoomAndCheckInBetweenAndCheckOutBetween(
room, checkIn, checkOut, checkIn, checkOut
);
return Math.max(0, room.getStock() - reservationRooms.size());

}

public ReservationCreateResponse createReservationAndDeleteCart(
String userEmail, ReservationCreateFromCartRequest reservationRequest
) {
Expand Down Expand Up @@ -95,7 +119,7 @@ private ReservationRoom reservationRoomDtoToEntity(ReservationRoomCreateRequest
String areaCodeString =
(roomRequest.areaCode() != null) ? String.valueOf(roomRequest.areaCode().getCode()) : null;

Accommodation accommodation = //todo : Bring 제대로 안되면 Exception 날려주는 거 고민
Accommodation accommodation =
tourAPIService.bringAccommodation(roomRequest.accommodationName(), areaCodeString);
Room room = tourAPIService.bringRoom(roomRequest.accommodationId(), roomRequest.roomTypeId());

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package ybe.mini.travelserver.domain.reservation_room.dto;

import jakarta.validation.constraints.*;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Builder;
import org.springframework.format.annotation.DateTimeFormat;
import ybe.mini.travelserver.domain.accommodation.entity.AreaCode;

import java.io.Serializable;
import java.time.LocalDateTime;

@Builder
public record ReservationRoomCreateRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ private Integer getRestStock(Room room, LocalDate checkIn, LocalDate checkOut) {
reservationRoomRepository.findAllByRoomAndCheckInBetweenAndCheckOutBetween(
roomOpt.get(), checkIn, checkOut, checkIn, checkOut
);
return room.getStock() - reservationRooms.size();
return Math.max(0, room.getStock() - reservationRooms.size());
}

}
28 changes: 24 additions & 4 deletions src/test/http/reservation.http
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
### 예약 생성
### 예약 생성1
POST http://localhost:8080/reservations
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiaWF0IjoxNzAxMTU2NTc2LCJleHAiOjE3MDExNTgzNzYsImVtYWlsIjoib2tqYWVvb2s5OEBnbWFpbC5jb20iLCJwYXNzd29yZCI6IntiY3J5cHR9JDJhJDEwJFNCbjZSQ3ZQdFQ2WW1vSVM0ZzU1dE8xTFBwRDJkSjJLbDBKcDRXT3k5RmhuNzNxdnNJQS51IiwibmFtZSI6Im9ramFlb29rIn0.HCiMHNhtW45GEFH2tbkihaeiqADBmehLfg2iGlIDuCE
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiaWF0IjoxNzAxMjQ1MTA0LCJleHAiOjE3MDEyNDY5MDQsImVtYWlsIjoib2tqYWVvb2s5OEBnbWFpbC5jb20iLCJwYXNzd29yZCI6IntiY3J5cHR9JDJhJDEwJFNCbjZSQ3ZQdFQ2WW1vSVM0ZzU1dE8xTFBwRDJkSjJLbDBKcDRXT3k5RmhuNzNxdnNJQS51IiwibmFtZSI6Im9ramFlb29rIn0.cqTN4G92c9KyiwW-0XCFRBM-SUDzIsEyxQFqJnVwzYI

{
"paymentType": "CARD",
Expand All @@ -11,8 +11,28 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiaWF0I
"accommodationName": "가락관광호텔",
"areaCode": "SEOUL",
"roomTypeId": 11430,
"checkIn": "2024-01-01T00:00",
"checkOut": "2024-01-03T00:00",
"checkIn": "20250101",
"checkOut": "20250103",
"guestNumber": 2
}
]
}

### 예약 생성2
POST http://localhost:8080/reservations
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiaWF0IjoxNzAxMjQ1MTA0LCJleHAiOjE3MDEyNDY5MDQsImVtYWlsIjoib2tqYWVvb2s5OEBnbWFpbC5jb20iLCJwYXNzd29yZCI6IntiY3J5cHR9JDJhJDEwJFNCbjZSQ3ZQdFQ2WW1vSVM0ZzU1dE8xTFBwRDJkSjJLbDBKcDRXT3k5RmhuNzNxdnNJQS51IiwibmFtZSI6Im9ramFlb29rIn0.cqTN4G92c9KyiwW-0XCFRBM-SUDzIsEyxQFqJnVwzYI

{
"paymentType": "CARD",
"reservationRooms" : [
{
"accommodationId": 819849,
"accommodationName": "킹모텔(구 호텔킹)",
"areaCode": "GYEONGBUK",
"roomTypeId": 823,
"checkIn": "20250101",
"checkOut": "20250103",
"guestNumber": 2
}
]
Expand Down
2 changes: 1 addition & 1 deletion src/test/http/token.http
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Content-Type: application/json

### 회원 마이페이지 올바른 토큰
GET http://localhost:8080/members/mypage
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1IiwiaWF0IjoxNzAwOTg2ODIwLCJleHAiOjE3MDA5ODg2MjAsImVtYWlsIjoib2tqYWVvb2s5OEBnbWFpbC5jb20ifQ.t6iD-_ymvp5jVKuihpndMDC4Zn6yc8wlTlil-DAci1E
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiaWF0IjoxNzAxMjQ1MTA0LCJleHAiOjE3MDEyNDY5MDQsImVtYWlsIjoib2tqYWVvb2s5OEBnbWFpbC5jb20iLCJwYXNzd29yZCI6IntiY3J5cHR9JDJhJDEwJFNCbjZSQ3ZQdFQ2WW1vSVM0ZzU1dE8xTFBwRDJkSjJLbDBKcDRXT3k5RmhuNzNxdnNJQS51IiwibmFtZSI6Im9ramFlb29rIn0.cqTN4G92c9KyiwW-0XCFRBM-SUDzIsEyxQFqJnVwzYI

#### 만료된 토큰
GET http://localhost:8080/members/mypage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import ybe.mini.travelserver.domain.reservation.dummy.DummyReservationDTO;
import ybe.mini.travelserver.domain.reservation.entity.Reservation;
import ybe.mini.travelserver.domain.reservation.repository.ReservationRepository;
import ybe.mini.travelserver.domain.reservation_room.repository.ReservationRoomRepository;
import ybe.mini.travelserver.domain.room.DummyObjectForRoom;
import ybe.mini.travelserver.domain.room.entity.Room;
import ybe.mini.travelserver.domain.room.repository.RoomRepository;
Expand All @@ -37,6 +38,8 @@ class ReservationServiceTest implements DummyObjectForRoom, DummyReservationDTO,
RoomRepository roomRepository;
@Mock
AccommodationRepository accommodationRepository;
@Mock
ReservationRoomRepository reservationRoomRepository;

@InjectMocks
ReservationService reservationService;
Expand Down

0 comments on commit 1eccf58

Please sign in to comment.