diff --git a/src/main/java/roomescape/reservation/business/ReservationTimeService.kt b/src/main/java/roomescape/reservation/business/ReservationTimeService.kt index 1d72210c..b9559fd2 100644 --- a/src/main/java/roomescape/reservation/business/ReservationTimeService.kt +++ b/src/main/java/roomescape/reservation/business/ReservationTimeService.kt @@ -1,103 +1,87 @@ -package roomescape.reservation.business; +package roomescape.reservation.business -import java.time.LocalDate; -import java.util.List; - -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import roomescape.common.exception.ErrorType; -import roomescape.common.exception.RoomescapeException; -import roomescape.reservation.infrastructure.persistence.ReservationEntity; -import roomescape.reservation.infrastructure.persistence.ReservationRepository; -import roomescape.reservation.infrastructure.persistence.ReservationTimeEntity; -import roomescape.reservation.infrastructure.persistence.ReservationTimeRepository; -import roomescape.reservation.web.ReservationTimeInfoResponse; -import roomescape.reservation.web.ReservationTimeInfosResponse; -import roomescape.reservation.web.ReservationTimeRequest; -import roomescape.reservation.web.ReservationTimeResponse; -import roomescape.reservation.web.ReservationTimesResponse; +import org.springframework.data.repository.findByIdOrNull +import org.springframework.http.HttpStatus +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import roomescape.common.exception.ErrorType +import roomescape.common.exception.RoomescapeException +import roomescape.reservation.infrastructure.persistence.ReservationEntity +import roomescape.reservation.infrastructure.persistence.ReservationRepository +import roomescape.reservation.infrastructure.persistence.ReservationTimeEntity +import roomescape.reservation.infrastructure.persistence.ReservationTimeRepository +import roomescape.reservation.web.* +import java.time.LocalDate @Service -@Transactional -public class ReservationTimeService { +class ReservationTimeService( + private val reservationTimeRepository: ReservationTimeRepository, + private val reservationRepository: ReservationRepository +) { + @Transactional(readOnly = true) + fun findTimeById(id: Long): ReservationTimeEntity = reservationTimeRepository.findByIdOrNull(id) + ?: throw RoomescapeException( + ErrorType.RESERVATION_TIME_NOT_FOUND, + "[reservationTimeId: $id]", + HttpStatus.BAD_REQUEST + ) - private final ReservationTimeRepository reservationTimeRepository; - private final ReservationRepository reservationRepository; - public ReservationTimeService( - ReservationTimeRepository reservationTimeRepository, - ReservationRepository reservationRepository - ) { - this.reservationTimeRepository = reservationTimeRepository; - this.reservationRepository = reservationRepository; - } + @Transactional(readOnly = true) + fun findAllTimes(): ReservationTimesResponse { + val response = reservationTimeRepository.findAll() + .map { it.toResponse() } - @Transactional(readOnly = true) - public ReservationTimeEntity findTimeById(Long id) { - return reservationTimeRepository.findById(id) - .orElseThrow(() -> new RoomescapeException(ErrorType.RESERVATION_TIME_NOT_FOUND, - String.format("[reservationTimeId: %d]", id), HttpStatus.BAD_REQUEST)); - } + return ReservationTimesResponse(response) + } - @Transactional(readOnly = true) - public ReservationTimesResponse findAllTimes() { - List response = reservationTimeRepository.findAll() - .stream() - .map(ReservationTimeResponse::from) - .toList(); + @Transactional + fun addTime(reservationTimeRequest: ReservationTimeRequest): ReservationTimeResponse { + validateIsDuplicatedTimeExists(reservationTimeRequest) - return new ReservationTimesResponse(response); - } + return ReservationTimeEntity(startAt = reservationTimeRequest.startAt) + .also { reservationTimeRepository.save(it) } + .toResponse() + } - public ReservationTimeResponse addTime(ReservationTimeRequest reservationTimeRequest) { - validateTimeDuplication(reservationTimeRequest); - ReservationTimeEntity reservationTime = reservationTimeRepository.save( - new ReservationTimeEntity(null, reservationTimeRequest.startAt) - ); + private fun validateIsDuplicatedTimeExists(reservationTimeRequest: ReservationTimeRequest) { + reservationTimeRepository.findByStartAt(reservationTimeRequest.startAt) + .also { + if (it.isNotEmpty()) { + throw RoomescapeException( + ErrorType.TIME_DUPLICATED, "[startAt: $it]", HttpStatus.CONFLICT + ) + } + } + } - return ReservationTimeResponse.from(reservationTime); - } + @Transactional + fun removeTimeById(id: Long) { + val reservationTime: ReservationTimeEntity = findTimeById(id) + reservationRepository.findByReservationTime(reservationTime) + .also { + if (it.isNotEmpty()) { + throw RoomescapeException( + ErrorType.TIME_IS_USED_CONFLICT, "[timeId: $id]", HttpStatus.CONFLICT + ) + } + reservationTimeRepository.deleteById(id) + } + } - private void validateTimeDuplication(ReservationTimeRequest reservationTimeRequest) { - List duplicateReservationTimes = reservationTimeRepository.findByStartAt( - reservationTimeRequest.startAt); + @Transactional(readOnly = true) + fun findAllAvailableTimesByDateAndTheme(date: LocalDate, themeId: Long): ReservationTimeInfosResponse { + val allTimes = reservationTimeRepository.findAll() + val reservations: List = reservationRepository.findByThemeId(themeId) - if (!duplicateReservationTimes.isEmpty()) { - throw new RoomescapeException(ErrorType.TIME_DUPLICATED, - String.format("[startAt: %s]", reservationTimeRequest.startAt), HttpStatus.CONFLICT); - } - } - - public void removeTimeById(Long id) { - ReservationTimeEntity reservationTime = findTimeById(id); - List usingTimeReservations = reservationRepository.findByReservationTime(reservationTime); - - if (!usingTimeReservations.isEmpty()) { - throw new RoomescapeException(ErrorType.TIME_IS_USED_CONFLICT, String.format("[timeId: %d]", id), - HttpStatus.CONFLICT); - } - - reservationTimeRepository.deleteById(id); - } - - @Transactional(readOnly = true) - public ReservationTimeInfosResponse findAllAvailableTimesByDateAndTheme(LocalDate date, Long themeId) { - List allTimes = reservationTimeRepository.findAll(); - List reservations = reservationRepository.findByThemeId(themeId); - - List response = allTimes.stream() - .map(time -> new ReservationTimeInfoResponse(time.getId(), time.getStartAt(), - isReservationBooked(reservations, date, time))) - .toList(); - - return new ReservationTimeInfosResponse(response); - } - - private boolean isReservationBooked(List reservations, LocalDate date, - ReservationTimeEntity time) { - return reservations.stream() - .anyMatch(reservation -> reservation.isSameDateAndTime(date, time)); - } + return ReservationTimeInfosResponse(allTimes + .map { time -> + ReservationTimeInfoResponse( + time.id!!, + time.startAt, + reservations.any { reservation -> reservation.hasSameDateTime(date, time) } + ) + } + ) + } } diff --git a/src/main/java/roomescape/reservation/infrastructure/persistence/ReservationEntity.kt b/src/main/java/roomescape/reservation/infrastructure/persistence/ReservationEntity.kt index cd8970e3..211c8a77 100644 --- a/src/main/java/roomescape/reservation/infrastructure/persistence/ReservationEntity.kt +++ b/src/main/java/roomescape/reservation/infrastructure/persistence/ReservationEntity.kt @@ -33,7 +33,7 @@ class ReservationEntity( ) { @JsonIgnore - fun isSameDateAndTime(date: LocalDate?, time: ReservationTimeEntity): Boolean { + fun hasSameDateTime(date: LocalDate?, time: ReservationTimeEntity): Boolean { return this.date == date && time.startAt == this.reservationTime.startAt } diff --git a/src/main/java/roomescape/reservation/web/ReservationResponse.kt b/src/main/java/roomescape/reservation/web/ReservationResponse.kt index 548b5d56..e325369e 100644 --- a/src/main/java/roomescape/reservation/web/ReservationResponse.kt +++ b/src/main/java/roomescape/reservation/web/ReservationResponse.kt @@ -111,3 +111,7 @@ data class ReservationTimeResponse( } } } + +fun ReservationTimeEntity.toResponse(): ReservationTimeResponse = ReservationTimeResponse( + this.id!!, this.startAt +) diff --git a/src/test/java/roomescape/reservation/business/ReservationTimeServiceTest.java b/src/test/java/roomescape/reservation/business/ReservationTimeServiceTest.java index 041afa70..2db88ab0 100644 --- a/src/test/java/roomescape/reservation/business/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/reservation/business/ReservationTimeServiceTest.java @@ -61,7 +61,8 @@ class ReservationTimeServiceTest { new ReservationTimeEntity(null, LocalTime.of(12, 30))); // when - Long invalidTimeId = saved.getId() + 1; + assert saved.getId() != null; + long invalidTimeId = saved.getId() + 1; // when & then assertThatThrownBy(() -> reservationTimeService.findTimeById(invalidTimeId)) @@ -85,6 +86,7 @@ class ReservationTimeServiceTest { ReservationStatus.CONFIRMED)); // then + assert reservationTime.getId() != null; assertThatThrownBy(() -> reservationTimeService.removeTimeById(reservationTime.getId())) .isInstanceOf(RoomescapeException.class); }