-
Notifications
You must be signed in to change notification settings - Fork 0
예약하기 기능을 구현했습니다. #12
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
The head ref may contain hidden characters: "feature/\uC608\uC57D\uD558\uAE30"
예약하기 기능을 구현했습니다. #12
Changes from 3 commits
13e73ef
ca48d3f
dc82912
8c19e82
60158c2
5415a6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package com.yscp.catchtable.application.reserve; | ||
|
|
||
| import com.yscp.catchtable.application.queue.StoreQueueService; | ||
| import com.yscp.catchtable.application.queue.dto.StoreQueueDto; | ||
| import com.yscp.catchtable.application.reserve.dto.StoreReserveRegisterDto; | ||
| import com.yscp.catchtable.application.reserve.mapper.UserReserveDataMapper; | ||
| import com.yscp.catchtable.domain.reserve.entity.ReserveData; | ||
| import com.yscp.catchtable.domain.reserve.entity.UserReserveData; | ||
| import com.yscp.catchtable.domain.reserve.repository.UserReserveDataRepository; | ||
| import com.yscp.catchtable.exception.BadRequestError; | ||
| import com.yscp.catchtable.exception.CatchTableException; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
|
|
||
| import java.util.Optional; | ||
|
|
||
| @Transactional | ||
| @RequiredArgsConstructor | ||
| @Service | ||
| public class UserReserveService { | ||
| private final StoreQueueService storeQueueService; | ||
| private final ReserveService reserveService; | ||
| private final UserReserveDataRepository userReserveDataRepository; | ||
|
|
||
| public void reserve(StoreReserveRegisterDto storeReserveRegisterDto) { | ||
|
|
||
| StoreQueueDto storeQueueDto = new StoreQueueDto(storeReserveRegisterDto.storeReserveIdx().toString(), storeReserveRegisterDto.userIdx().toString()); | ||
|
|
||
| if (!isValidWaitingUser(storeQueueDto)) { | ||
| throw new CatchTableException(BadRequestError.EXPIRED_TICKET); | ||
| } | ||
|
|
||
| Optional<ReserveData> reserveDataOptional = reserveService.findWithStoreByIdx(storeReserveRegisterDto.storeReserveIdx()); | ||
|
|
||
| reserveDataOptional.ifPresentOrElse( | ||
| reserveData -> { | ||
| saveUserReserveData( | ||
| storeReserveRegisterDto, | ||
| reserveData, | ||
| storeQueueDto); | ||
| }, | ||
| () -> { | ||
| throw new CatchTableException(BadRequestError.NULL_EXCEPTION); | ||
| } | ||
| ); | ||
| } | ||
|
|
||
| private void saveUserReserveData(StoreReserveRegisterDto dto, | ||
| ReserveData reserveData, | ||
| StoreQueueDto storeQueueDto) { | ||
|
|
||
| reserveData.userReserve(dto.requestDatetime(), dto.userIdx()); | ||
|
|
||
| UserReserveData userReserveData = UserReserveDataMapper.toEntity(reserveData, dto); | ||
|
|
||
| if (userReserveData != null) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이게 null이 될 수 있는걸까요??
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 함수를 통해 호출되는 부분을 사용한다고 생각하여 이부분은 고민이 되는데 응답값이 항상 null을 안 줄 경우 |
||
| userReserveDataRepository.save(userReserveData); | ||
| } | ||
|
|
||
| storeQueueService.delete(storeQueueDto); | ||
| } | ||
|
|
||
| private boolean isValidWaitingUser(StoreQueueDto queueDto) { | ||
| return storeQueueService.isValidWaitingUser(queueDto); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package com.yscp.catchtable.application.reserve.dto; | ||
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| public record StoreReserveRegisterDto( | ||
| Long userIdx, | ||
| Long storeReserveIdx, | ||
| String reservePayType, | ||
| String transactionNo, | ||
| String purpose, | ||
| Integer reservationNumberOfPeople, | ||
| LocalDateTime requestDatetime | ||
| ) { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package com.yscp.catchtable.application.reserve.mapper; | ||
|
|
||
| import com.yscp.catchtable.application.reserve.dto.StoreReserveRegisterDto; | ||
| import com.yscp.catchtable.presentation.reserve.dto.StoreReserveRequestDto; | ||
| import lombok.experimental.UtilityClass; | ||
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| @UtilityClass | ||
| public class StoreReserveMapper { | ||
| public static StoreReserveRegisterDto toDto(StoreReserveRequestDto storeReserveRequestDto, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UtilityClass를 사용하면 static 함수로 만들어 준다고 하는데 static을 붙일 필요가 있을까요? 그리고 궁금한게 UtilityClass를 꼭 사용해야 하는 이유도 궁금합니다.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. RequestDto에서 생성할까 고민하다가. 보통 레이어간의 변환을 어떻게 하시는지 궁금합니다! |
||
| LocalDateTime reserveDatetime) { | ||
| return new StoreReserveRegisterDto( | ||
| storeReserveRequestDto.userIdx(), | ||
| storeReserveRequestDto.storeReserveIdx(), | ||
| storeReserveRequestDto.reserveType(), | ||
| storeReserveRequestDto.transactionNo(), | ||
| storeReserveRequestDto.purpose(), | ||
| storeReserveRequestDto.reservationNumberOfPeople(), | ||
| reserveDatetime | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package com.yscp.catchtable.application.reserve.mapper; | ||
|
|
||
| import com.yscp.catchtable.application.reserve.dto.StoreReserveRegisterDto; | ||
| import com.yscp.catchtable.domain.reserve.entity.ReserveData; | ||
| import com.yscp.catchtable.domain.reserve.entity.UserReserveData; | ||
| import com.yscp.catchtable.domain.reserve.entity.value.ReservePayType; | ||
| import com.yscp.catchtable.domain.reserve.entity.value.ReserveStatus; | ||
| import com.yscp.catchtable.domain.user.entity.User; | ||
|
|
||
| public class UserReserveDataMapper { | ||
| public static UserReserveData toEntity(ReserveData reserveData, StoreReserveRegisterDto dto) { | ||
| User requestUser = User.builder() | ||
| .idx(dto.userIdx()) | ||
| .build(); | ||
|
|
||
| return UserReserveData.builder() | ||
| .user(requestUser) | ||
| .reserveData(reserveData) | ||
| .reserveStatus(ReserveStatus.RESERVE) | ||
| .reservePayType(ReservePayType.from(dto.reservePayType())) | ||
| .regIdx(dto.userIdx()) | ||
| .regDatetime(dto.requestDatetime()) | ||
| .build(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,8 +2,11 @@ | |
|
|
||
| import com.yscp.catchtable.domain.reserve.entity.value.StoreReserveDataStatus; | ||
| import com.yscp.catchtable.domain.store.entity.Store; | ||
| import com.yscp.catchtable.exception.BadRequestError; | ||
| import com.yscp.catchtable.exception.CatchTableException; | ||
| import jakarta.persistence.*; | ||
| import lombok.AccessLevel; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
| import org.hibernate.annotations.Comment; | ||
|
|
@@ -44,4 +47,31 @@ public class ReserveData { | |
| private Long regIdx; | ||
| private LocalDateTime modDatetime; | ||
| private Long modIdx; | ||
|
|
||
| @Builder | ||
| public ReserveData(Long idx, Store store, LocalDate reserveDate, String reserveTime, Integer minUserCount, Integer maxUserCount, Integer canReserveCount, Integer reservedCount, StoreReserveDataStatus reserveStatus, LocalDateTime regDatetime, Long regIdx, LocalDateTime modDatetime, Long modIdx) { | ||
|
||
| this.idx = idx; | ||
| this.store = store; | ||
| this.reserveDate = reserveDate; | ||
| this.reserveTime = reserveTime; | ||
| this.minUserCount = minUserCount; | ||
| this.maxUserCount = maxUserCount; | ||
| this.canReserveCount = canReserveCount; | ||
| this.reservedCount = reservedCount; | ||
| this.reserveStatus = reserveStatus; | ||
| this.regDatetime = regDatetime; | ||
| this.regIdx = regIdx; | ||
| this.modDatetime = modDatetime; | ||
| this.modIdx = modIdx; | ||
| } | ||
|
|
||
| public void userReserve(LocalDateTime userReserveDatetime, Long userIdx) { | ||
| if (reservedCount >= canReserveCount) { | ||
| throw new CatchTableException(BadRequestError.STORE_RESERVATION_MAX); | ||
| } | ||
|
|
||
| reservedCount += 1; | ||
| modDatetime = userReserveDatetime; | ||
| modIdx = userIdx; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,11 @@ | ||
| package com.yscp.catchtable.domain.reserve.entity; | ||
|
|
||
| import com.yscp.catchtable.domain.reserve.entity.value.ReservePayType; | ||
| import com.yscp.catchtable.domain.reserve.entity.value.ReserveStatus; | ||
| import com.yscp.catchtable.domain.user.entity.User; | ||
| import jakarta.persistence.*; | ||
| import lombok.AccessLevel; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
|
|
@@ -28,9 +30,23 @@ public class UserReserveData { | |
|
|
||
| @Enumerated(EnumType.STRING) | ||
| private ReserveStatus reserveStatus; | ||
| @Enumerated(EnumType.STRING) | ||
| private ReservePayType reservePayType; | ||
| private LocalDateTime regDatetime; | ||
| private Long regIdx; | ||
| private LocalDateTime modDatetime; | ||
| private Long modIdx; | ||
|
|
||
| @Builder | ||
| public UserReserveData(Long idx, User user, ReserveData reserveData, ReserveStatus reserveStatus, ReservePayType reservePayType, LocalDateTime regDatetime, Long regIdx, LocalDateTime modDatetime, Long modIdx) { | ||
|
||
| this.idx = idx; | ||
| this.user = user; | ||
| this.reserveData = reserveData; | ||
| this.reserveStatus = reserveStatus; | ||
| this.reservePayType = reservePayType; | ||
| this.regDatetime = regDatetime; | ||
| this.regIdx = regIdx; | ||
| this.modDatetime = modDatetime; | ||
| this.modIdx = modIdx; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.yscp.catchtable.domain.reserve.entity.value; | ||
|
|
||
| import com.yscp.catchtable.exception.BadRequestError; | ||
| import com.yscp.catchtable.exception.CatchTableException; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.Map; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public enum ReservePayType { | ||
| CARD, | ||
| CATCH_PAY; | ||
|
|
||
| private static final Map<String, ReservePayType> MAPPING; | ||
|
|
||
| static { | ||
| MAPPING = Arrays.stream(ReservePayType.values()) | ||
| .collect(Collectors.toMap(Enum::name, e -> e)); | ||
| } | ||
|
|
||
| public static ReservePayType from(String reserveTypeString) { | ||
| if (reserveTypeString == null || reserveTypeString.isEmpty()) { | ||
| throw new CatchTableException(BadRequestError.INVALID_RESERVE_PAY_TYPE); | ||
| } | ||
| return MAPPING.get(reserveTypeString.toUpperCase()); | ||
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,8 @@ | ||
| package com.yscp.catchtable.domain.reserve.entity.value; | ||
|
|
||
| public enum ReserveStatus { | ||
| RESERVE, | ||
| SUCCESS, | ||
| DELETE, | ||
| CANCEL | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |
|
|
||
| import java.time.LocalDate; | ||
| import java.util.List; | ||
| import java.util.Optional; | ||
|
|
||
| public interface ReserveRepository extends JpaRepository<ReserveData, Long> { | ||
|
|
||
|
|
@@ -40,4 +41,12 @@ public interface ReserveRepository extends JpaRepository<ReserveData, Long> { | |
| List<StoreReserveDto> getStoreReserveDtoBeforeMaxDate(@Param("idx") Long idx, @Param("date") LocalDate date); | ||
|
|
||
| List<ReserveData> findByStore_IdxAndReserveDate(Long idx, LocalDate reserveDate); | ||
|
|
||
| @Query(value = """ | ||
| SELECT rd | ||
| FROM ReserveData rd | ||
| JOIN FETCH rd.store s | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 근데 Data는 꼭 붙어야 하는 suffix일까요?ㅎㅎ
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 음.. 다시보니 prefix로 유저와 상점을 구분해놔서 굳이.. 안붙여도 될 것 같습니다! |
||
| WHERE rd.idx = :idx | ||
| """) | ||
| Optional<ReserveData> findWithStoreByIdx(Long idx); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package com.yscp.catchtable.domain.reserve.repository; | ||
|
|
||
| import com.yscp.catchtable.domain.reserve.entity.UserReserveData; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
|
|
||
| public interface UserReserveDataRepository extends JpaRepository<UserReserveData, Long> { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ | |
| import jakarta.persistence.GenerationType; | ||
| import jakarta.persistence.Id; | ||
| import lombok.AccessLevel; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
|
|
@@ -31,6 +32,7 @@ public class User { | |
|
|
||
| private LocalDateTime modDatetime; | ||
|
|
||
| @Builder | ||
| public User(Long idx, String email, String password, String phone, String nickname, LocalDateTime regDatetime, LocalDateTime modDatetime) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이것도 내려쓰기가 있는게 더 좋을 것 같아요 |
||
| this.idx = idx; | ||
| this.email = email; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
예약할 때 더블 클릭하면 어떻게 되어요??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
제 생각에는
Lock이 걸려 있어 동시요청이 처리되지 않아
isValidWaitingUser 메소드에서 Exception을 던질 것 같습니다.
혹시 놓친 부분이 있을까요~?