Skip to content

Commit de9baf3

Browse files
committed
Refactor: 멘티의 기존 예약 시간 중복 확인
1 parent e274b18 commit de9baf3

File tree

4 files changed

+31
-5
lines changed

4 files changed

+31
-5
lines changed

back/src/main/java/com/back/domain/mentoring/reservation/error/ReservationErrorCode.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ public enum ReservationErrorCode implements ErrorCode {
3030
NOT_AVAILABLE_SLOT("409-1", "이미 예약이 완료된 시간대입니다."),
3131
ALREADY_RESERVED_SLOT("409-2", "이미 예약한 시간대입니다. 예약 목록을 확인해 주세요."),
3232
CONCURRENT_RESERVATION_CONFLICT("409-3", "다른 사용자가 먼저 예약했습니다. 새로고침 후 다시 시도해 주세요."),
33-
CONCURRENT_APPROVAL_CONFLICT("409-4", "이미 수락한 예약입니다.");
33+
CONCURRENT_APPROVAL_CONFLICT("409-4", "이미 수락한 예약입니다."),
34+
OVERLAPPING_TIME("409-5", "이미 해당 시간에 다른 예약이 있습니다. 예약 목록을 확인해 주세요.");
3435

3536
private final String code;
3637
private final String message;

back/src/main/java/com/back/domain/mentoring/reservation/repository/ReservationRepository.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.springframework.data.jpa.repository.Query;
1010
import org.springframework.data.repository.query.Param;
1111

12+
import java.time.LocalDateTime;
1213
import java.util.List;
1314
import java.util.Optional;
1415

@@ -58,4 +59,21 @@ Page<Reservation> findAllByMenteeMember(
5859
* - 취소/거절된 예약도 히스토리로 보존
5960
*/
6061
boolean existsByMentorSlotId(Long slotId);
62+
63+
@Query("""
64+
SELECT CASE WHEN COUNT(r) > 0
65+
THEN TRUE
66+
ELSE FALSE
67+
END
68+
FROM Reservation r
69+
WHERE r.mentee.id = :menteeId
70+
AND r.status NOT IN ('REJECTED', 'CANCELED')
71+
AND r.mentorSlot.startDateTime < :end
72+
AND r.mentorSlot.endDateTime > :start
73+
""")
74+
boolean existsOverlappingTimeForMentee(
75+
@Param("menteeId") Long menteeId,
76+
@Param("start") LocalDateTime start,
77+
@Param("end") LocalDateTime end
78+
);
6179
}

back/src/main/java/com/back/domain/mentoring/reservation/service/ReservationService.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@ public ReservationResponse createReservation(Mentee mentee, ReservationRequest r
6262
Mentoring mentoring = mentoringStorage.findMentoring(reqDto.mentoringId());
6363
MentorSlot mentorSlot = mentoringStorage.findMentorSlot(reqDto.mentorSlotId());
6464

65-
validateMentorSlotStatus(mentorSlot, mentee);
6665
DateTimeValidator.validateStartTimeNotInPast(mentorSlot.getStartDateTime());
66+
validateMentorSlotStatus(mentorSlot, mentee);
67+
validateOverlappingTimeForMentee(mentee, mentorSlot);
6768

6869
Reservation reservation = Reservation.builder()
6970
.mentoring(mentoring)
@@ -131,4 +132,13 @@ private void validateMentorSlotStatus(MentorSlot mentorSlot, Mentee mentee) {
131132
throw new ServiceException(ReservationErrorCode.NOT_AVAILABLE_SLOT);
132133
}
133134
}
135+
136+
private void validateOverlappingTimeForMentee(Mentee mentee, MentorSlot mentorSlot) {
137+
boolean isOverlapping = reservationRepository
138+
.existsOverlappingTimeForMentee(mentee.getId(), mentorSlot.getStartDateTime(), mentorSlot.getEndDateTime());
139+
140+
if (isOverlapping) {
141+
throw new ServiceException(ReservationErrorCode.OVERLAPPING_TIME);
142+
}
143+
}
134144
}

back/src/test/java/com/back/domain/mentoring/reservation/service/ReservationServiceTest.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,9 +267,6 @@ void throwExceptionWhenStartTimeInPast() {
267267
.thenReturn(mentoring);
268268
when(mentoringStorage.findMentorSlot(pastRequest.mentorSlotId()))
269269
.thenReturn(pastSlot);
270-
when(reservationRepository.findByMentorSlotIdAndStatusIn(pastSlot.getId(),
271-
List.of(ReservationStatus.PENDING, ReservationStatus.APPROVED, ReservationStatus.COMPLETED)))
272-
.thenReturn(Optional.empty());
273270

274271
// when & then
275272
assertThatThrownBy(() -> reservationService.createReservation(mentee, pastRequest))

0 commit comments

Comments
 (0)