Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: 예약 도메인 리팩토링 #134

Merged
merged 16 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
e257fe8
refactor: 예약 유효성 검증 조건 및 메세지 상수 클래스 추가
jo0oy Dec 14, 2023
4372274
refactor: 예약 도메인 Request DTO 유효성 검증 조건 상수화한 것 적용
jo0oy Dec 14, 2023
fbe654d
remove: 예약 도메인 불필요한 Exception 삭제
jo0oy Dec 14, 2023
d1e2881
refactor: Reservation 엔티티 @Builder 선언한 생성자 접근권한자 private 변경
jo0oy Dec 14, 2023
2e05a70
move: ReservationMapper 클래스 이동
jo0oy Dec 14, 2023
a2dda91
move: RoomNotFoundException 클래스 Room 도메인 exception 패키지로 이동
jo0oy Dec 14, 2023
d97c251
feat: RoomService에 개별 엔티티 조회 서비스 로직 getRoomById 메서드 추가
jo0oy Dec 14, 2023
9d87029
refactor: 불필요한 debug 로그 제거
jo0oy Dec 14, 2023
2321824
refactor: 전체 예약 내역 조회 API 응답 타입 와일드카드에서 정확한 Response 클래스 타입 명시
jo0oy Dec 14, 2023
6455cde
refactor: 페이징 디폴트 요청값 상수화
jo0oy Dec 14, 2023
de66b63
refactor: ReservationService에서 RoomService.getRoomById(예외 처리 포함)로 Roo…
jo0oy Dec 14, 2023
9dd928b
test: ReservationServiceTest Product, Room Test Data 생성 메서드 추출해서 구현
jo0oy Dec 14, 2023
bb3f67f
test: GetReservationListServiceTest Product, Room, ReservationProduct…
jo0oy Dec 14, 2023
d85dc69
Merge branch 'develop' into feature/reservation-refactoring
jo0oy Dec 14, 2023
017c083
move: util 패키지 하위에 생성했던 constant 패키지 reservation 도메인 패키지 하위로 이동
jo0oy Dec 14, 2023
c9e45b8
fix: 유효성 검증 상수화 했던 것 Wrapper 타입으로 인해 build 에러 -> 원시 타입으로 수정
jo0oy Dec 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.fc.shimpyo_be.domain.reservation.constant;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ReservationValidationConstants {

// regex
public static final String DATE_REGEX = "^\\d{4}-\\d{2}-\\d{2}$";
public static final int RESERVATION_REQ_MIN_SIZE = 1;
public static final int RESERVATION_REQ_MAX_SIZE = 3;
public static final int TOTAL_PRICE_MIN_VALUE = 0;

// validation message
public static final String DATE_PATTERN_MESSAGE = "올바른 날짜 형식이 아닙니다.(yyyy-MM-dd 형식으로 입력하세요.)";
public static final String RESERVATION_REQ_SIZE_MESSAGE = "최소 1개, 최대 3개의 객실 예약이 가능합니다.";
public static final String PAYMETHOD_NOTNULL_MESSAGE = "null 일 수 없습니다. 정해진 결제 수단에서 선택하세요.";
public static final String TOTAL_PRICE_MIN_MESSAGE = "총 결제 금액은 최소 0원 이상이어야 합니다.";
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.fc.shimpyo_be.domain.reservation.dto.request.PreoccupyRoomsRequestDto;
import com.fc.shimpyo_be.domain.reservation.dto.request.ReleaseRoomsRequestDto;
import com.fc.shimpyo_be.domain.reservation.dto.request.SaveReservationRequestDto;
import com.fc.shimpyo_be.domain.reservation.dto.response.ReservationInfoResponseDto;
import com.fc.shimpyo_be.domain.reservation.dto.response.SaveReservationResponseDto;
import com.fc.shimpyo_be.domain.reservation.dto.response.ValidatePreoccupyResultResponseDto;
import com.fc.shimpyo_be.domain.reservation.facade.PreoccupyRoomsLockFacade;
Expand Down Expand Up @@ -31,12 +32,14 @@ public class ReservationRestController {
private final PreoccupyRoomsLockFacade preoccupyRoomsLockFacade;
private final ReservationLockFacade reservationLockFacade;
private final SecurityUtil securityUtil;
private static final int PAGE_SIZE = 10;
private static final int PAGE_NUM = 0;
private static final String PAGE_SORT_BY = "id";

@PostMapping
public ResponseEntity<ResponseDto<SaveReservationResponseDto>> saveReservation(
@Valid @RequestBody SaveReservationRequestDto request
) {
log.debug("[api][POST] /api/reservations");

return ResponseEntity
.status(HttpStatus.CREATED)
Expand All @@ -50,10 +53,9 @@ public ResponseEntity<ResponseDto<SaveReservationResponseDto>> saveReservation(
}

@GetMapping
public ResponseEntity<ResponseDto<Page<?>>> getReservationList(
@PageableDefault(size = 10, page = 0, sort = "id", direction = Sort.Direction.DESC) Pageable pageable
public ResponseEntity<ResponseDto<Page<ReservationInfoResponseDto>>> getReservationList(
@PageableDefault(size = PAGE_SIZE, page = PAGE_NUM, sort = PAGE_SORT_BY, direction = Sort.Direction.DESC) Pageable pageable
) {
log.debug("[api][GET] /api/reservations");

return ResponseEntity
.status(HttpStatus.OK)
Expand All @@ -70,7 +72,6 @@ public ResponseEntity<ResponseDto<Page<?>>> getReservationList(
public ResponseEntity<ResponseDto<ValidatePreoccupyResultResponseDto>> checkAvailableAndPreoccupy(
@Valid @RequestBody PreoccupyRoomsRequestDto request
) {
log.debug("[api][POST] /api/reservations/preoccupy");

return ResponseEntity
.status(HttpStatus.OK)
Expand All @@ -87,7 +88,6 @@ public ResponseEntity<ResponseDto<ValidatePreoccupyResultResponseDto>> checkAvai
public ResponseEntity<ResponseDto<Void>> releaseRooms(
@Valid @RequestBody ReleaseRoomsRequestDto request
) {
log.debug("[api][POST] /api/reservations/release");

reservationService.releaseRooms(securityUtil.getCurrentMemberId(), request);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@
import jakarta.validation.constraints.Pattern;
import lombok.Builder;

import static com.fc.shimpyo_be.domain.reservation.constant.ReservationValidationConstants.*;

@Builder
public record PreoccupyRoomItemRequestDto(
@NotNull
Long cartId,
@NotNull
Long roomCode,
@Pattern(regexp = "^\\d{4}-\\d{2}-\\d{2}$", message = "올바른 날짜 형식이 아닙니다.(yyyy-MM-dd 형식으로 입력하세요.)")
@Pattern(regexp = DATE_REGEX, message = DATE_PATTERN_MESSAGE)
String startDate,
@Pattern(regexp = "^\\d{4}-\\d{2}-\\d{2}$", message = "올바른 날짜 형식이 아닙니다.(yyyy-MM-dd 형식으로 입력하세요.)")
@Pattern(regexp = DATE_REGEX, message = DATE_PATTERN_MESSAGE)
String endDate
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@

import java.util.List;

import static com.fc.shimpyo_be.domain.reservation.constant.ReservationValidationConstants.*;

@Builder
public record PreoccupyRoomsRequestDto(

@Valid
@Size(min = 1, max = 3, message = "최소 1개, 최대 3개의 객실 예약이 가능합니다.")
@Size(min = RESERVATION_REQ_MIN_SIZE, max = RESERVATION_REQ_MAX_SIZE, message = RESERVATION_REQ_SIZE_MESSAGE)
List<PreoccupyRoomItemRequestDto> rooms
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import jakarta.validation.constraints.Pattern;
import lombok.Builder;

import static com.fc.shimpyo_be.domain.reservation.constant.ReservationValidationConstants.*;

@Builder
public record ReleaseRoomItemRequestDto(
@NotNull
Long roomId,
@Pattern(regexp = "^\\d{4}-\\d{2}-\\d{2}$", message = "올바른 날짜 형식이 아닙니다.(yyyy-MM-dd 형식으로 입력하세요.)")
@Pattern(regexp = DATE_REGEX, message = DATE_PATTERN_MESSAGE)
String startDate,
@Pattern(regexp = "^\\d{4}-\\d{2}-\\d{2}$", message = "올바른 날짜 형식이 아닙니다.(yyyy-MM-dd 형식으로 입력하세요.)")
@Pattern(regexp = DATE_REGEX, message = DATE_PATTERN_MESSAGE)
String endDate
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

import java.util.List;

import static com.fc.shimpyo_be.domain.reservation.constant.ReservationValidationConstants.*;

@Builder
public record ReleaseRoomsRequestDto(
@Valid
@Size(min = 1, max = 3, message = "최소 1개, 최대 3개의 객실 요청 정보가 필요합니다.")
@Size(min = RESERVATION_REQ_MIN_SIZE, max = RESERVATION_REQ_MAX_SIZE, message = RESERVATION_REQ_SIZE_MESSAGE)
List<ReleaseRoomItemRequestDto> rooms
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@

import java.util.List;

import static com.fc.shimpyo_be.domain.reservation.constant.ReservationValidationConstants.*;

@Builder
public record SaveReservationRequestDto(
@Valid
@Size(min = 1, max = 3, message = "최소 1개, 최대 3개의 객실 예약이 가능합니다.")
@Size(min = RESERVATION_REQ_MIN_SIZE, max = RESERVATION_REQ_MAX_SIZE, message = RESERVATION_REQ_SIZE_MESSAGE)
List<ReservationProductRequestDto> reservationProducts,
@NotNull(message = "null 일 수 없습니다. 정해진 결제 수단에서 선택하세요.")
@NotNull(message = PAYMETHOD_NOTNULL_MESSAGE)
PayMethod payMethod,
@Min(value = 0, message = "총 결제 금액은 음수일 수 없습니다.")
@Min(value = TOTAL_PRICE_MIN_VALUE, message = TOTAL_PRICE_MIN_MESSAGE)
Integer totalPrice
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class Reservation extends BaseTimeEntity {
private List<ReservationProduct> reservationProducts = new ArrayList<>();

@Builder
public Reservation(
private Reservation(
Long id,
Member member,
PayMethod payMethod,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ public ValidatePreoccupyResultResponseDto checkAvailableAndPreoccupy(Long member
CheckAvailableRoomsResultDto resultDto = preoccupyRoomsService.checkAvailable(memberId, request);

if(!resultDto.isAvailable()) {
log.debug("[{}][check available rooms result] isAvailable = {}, results = {}", currentWorker, false, resultDto.roomResults());
throw new PreoccupyNotAvailableException(
ValidatePreoccupyResultResponseDto.builder()
.isAvailable(false)
Expand All @@ -47,8 +46,6 @@ public ValidatePreoccupyResultResponseDto checkAvailableAndPreoccupy(Long member
);
}

log.debug("[{}][check available rooms result] isAvailable = {}, results = {}", currentWorker, true, resultDto.roomResults());
log.debug("[{}][check available rooms result] preoccupyMap = {}", currentWorker, resultDto.preoccupyMap());
preoccupyRoomsService.preoccupy(resultDto);

return ValidatePreoccupyResultResponseDto.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public SaveReservationResponseDto saveReservation(Long memberId, SaveReservation
String currentWorker = Thread.currentThread().getName();

try {
boolean isLocked = lock.tryLock(2, 4, TimeUnit.SECONDS);
boolean isLocked = lock.tryLock(3, 5, TimeUnit.SECONDS);

if(!isLocked) {
log.error("[{}] 예약 lock 획득 실패", currentWorker);
Expand All @@ -38,8 +38,6 @@ public SaveReservationResponseDto saveReservation(Long memberId, SaveReservation
ValidateReservationResultDto resultDto = reservationService.validate(memberId, request.reservationProducts());

if(!resultDto.isAvailable()) {
log.debug("[{}][validate rooms result] isAvailable = {}, unavailableIds = {}", currentWorker, false, resultDto.unavailableIds());

throw new ReserveNotAvailableException(
ValidateReservationResultResponseDto.builder()
.isAvailable(false)
Expand All @@ -48,8 +46,6 @@ public SaveReservationResponseDto saveReservation(Long memberId, SaveReservation
);
}

log.debug("[{}][validate rooms result] isAvailable = {}, unavailableIds = {}", currentWorker, true, resultDto.unavailableIds());

return reservationService.saveReservation(memberId, request, resultDto.confirmMap());

} catch (InterruptedException exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ public CheckAvailableRoomsResultDto checkAvailable(Long memberId, PreoccupyRooms
String key = String.format(PREOCCUPY_REDIS_KEY_FORMAT, roomId, targetDate);
Object value = opsForValue.get(key);

log.info("roomId: {}, targetDate: {}, value: {}", roomId, targetDate, value);
if(Objects.nonNull(value)) {
dateCheck = false;
preoccupyMap.remove(roomId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.fc.shimpyo_be.domain.cart.service.CartService;
import com.fc.shimpyo_be.domain.member.entity.Member;
import com.fc.shimpyo_be.domain.member.service.MemberService;
import com.fc.shimpyo_be.domain.product.exception.RoomNotFoundException;
import com.fc.shimpyo_be.domain.reservation.dto.ValidateReservationResultDto;
import com.fc.shimpyo_be.domain.reservation.dto.request.ReleaseRoomItemRequestDto;
import com.fc.shimpyo_be.domain.reservation.dto.request.ReleaseRoomsRequestDto;
Expand All @@ -12,12 +11,12 @@
import com.fc.shimpyo_be.domain.reservation.dto.response.SaveReservationResponseDto;
import com.fc.shimpyo_be.domain.reservation.entity.Reservation;
import com.fc.shimpyo_be.domain.reservation.repository.ReservationRepository;
import com.fc.shimpyo_be.domain.reservation.util.ReservationMapper;
import com.fc.shimpyo_be.domain.reservation.util.mapper.ReservationMapper;
import com.fc.shimpyo_be.domain.reservationproduct.dto.request.ReservationProductRequestDto;
import com.fc.shimpyo_be.domain.reservationproduct.entity.ReservationProduct;
import com.fc.shimpyo_be.domain.reservationproduct.repository.ReservationProductRepository;
import com.fc.shimpyo_be.domain.room.entity.Room;
import com.fc.shimpyo_be.domain.room.repository.RoomRepository;
import com.fc.shimpyo_be.domain.room.service.RoomService;
import com.fc.shimpyo_be.global.util.DateTimeUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -41,7 +40,7 @@ public class ReservationService {
private final ReservationRepository reservationRepository;
private final ReservationProductRepository reservationProductRepository;
private final MemberService memberService;
private final RoomRepository roomRepository;
private final RoomService roomService;
private final CartService cartService;
private final RedisTemplate<String, Object> redisTemplate;
private static final String REDIS_ROOM_KEY_FORMAT = "roomId:%d:%s";
Expand All @@ -50,7 +49,6 @@ public class ReservationService {
public SaveReservationResponseDto saveReservation(
Long memberId, SaveReservationRequestDto request, Map<Long, List<String>> reservationMap
) {
log.debug("{} ::: {}", getClass().getSimpleName(), "saveReservation");

// 회원 엔티티 조회
Member member = memberService.getMemberById(memberId);
Expand All @@ -59,8 +57,7 @@ public SaveReservationResponseDto saveReservation(
List<ReservationProduct> reservationProducts = new ArrayList<>();
for (ReservationProductRequestDto reservationProductDto : request.reservationProducts()) {

Room room = roomRepository.findById(reservationProductDto.roomId())
.orElseThrow(RoomNotFoundException::new);
Room room = roomService.getRoomById(reservationProductDto.roomId());

// 장바구니 아이템 삭제
if (reservationProductDto.cartId() > 0) {
Expand Down Expand Up @@ -96,7 +93,6 @@ public SaveReservationResponseDto saveReservation(

@Transactional(readOnly = true)
public Page<ReservationInfoResponseDto> getReservationInfoList(Long memberId, Pageable pageable) {
log.debug("{} ::: {}", getClass().getSimpleName(), "getReservationInfoList");

List<Long> reservationIds = reservationRepository.findIdsByMemberId(memberId);

Expand All @@ -106,7 +102,6 @@ public Page<ReservationInfoResponseDto> getReservationInfoList(Long memberId, Pa
}

public ValidateReservationResultDto validate(Long memberId, List<ReservationProductRequestDto> reservationProducts) {
log.debug("{} ::: {}", getClass().getSimpleName(), "validate");

ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();

Expand Down Expand Up @@ -155,7 +150,6 @@ public ValidateReservationResultDto validate(Long memberId, List<ReservationProd
}

public void releaseRooms(Long memberId, ReleaseRoomsRequestDto request) {
log.debug("{} ::: {}", getClass().getSimpleName(), "releaseRooms");

String memberIdValue = String.valueOf(memberId);
ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
Expand All @@ -180,7 +174,6 @@ public void releaseRooms(Long memberId, ReleaseRoomsRequestDto request) {
}

private void confirmReservationProduct(List<String> reservationKeys, String endDate) {
log.debug("{} ::: {}", getClass().getSimpleName(), "confirmReservationProduct");

Date expireDate = convertLocalDateToDate(DateTimeUtil.toLocalDate(endDate));
for (String key : reservationKeys) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.fc.shimpyo_be.domain.reservation.util;
package com.fc.shimpyo_be.domain.reservation.util.mapper;

import com.fc.shimpyo_be.domain.product.entity.Product;
import com.fc.shimpyo_be.domain.reservation.dto.response.ReservationInfoResponseDto;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.fc.shimpyo_be.domain.reservationproduct.dto.request;

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Builder;
Expand All @@ -15,7 +16,10 @@ public record ReservationProductRequestDto(
String startDate,
@Pattern(regexp = "^\\d{4}-\\d{2}-\\d{2}$", message = "올바른 날짜 형식이 아닙니다.(yyyy-MM-dd 형식으로 입력하세요.)")
String endDate,
@NotBlank
String visitorName,
@NotBlank
@Pattern(regexp = "^0\\d{1,2}-\\d{3,4}-\\d{4}$")
String visitorPhone,
@Min(value = 0, message = "객실 이용 금액은 0원 이상부터 가능합니다.")
Integer price
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.fc.shimpyo_be.domain.product.exception;
package com.fc.shimpyo_be.domain.room.exception;

import com.fc.shimpyo_be.global.exception.ApplicationException;
import com.fc.shimpyo_be.global.exception.ErrorCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.fc.shimpyo_be.domain.room.service;

import com.fc.shimpyo_be.domain.room.exception.RoomNotFoundException;
import com.fc.shimpyo_be.domain.room.dto.response.RoomWithProductResponseDto;
import com.fc.shimpyo_be.domain.room.entity.Room;
import com.fc.shimpyo_be.domain.room.repository.RoomRepository;
import com.fc.shimpyo_be.domain.room.util.RoomMapper;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -33,4 +35,10 @@ public List<Long> getRoomIdsByCode(Long roomCode) {

return roomRepository.findIdsByCode(roomCode);
}

@Transactional(readOnly = true)
public Room getRoomById(Long id) {
return roomRepository.findById(id)
.orElseThrow(RoomNotFoundException::new);
}
}
Loading